diff options
Diffstat (limited to 'drivers/md/dm-pcache/cache.h')
| -rw-r--r-- | drivers/md/dm-pcache/cache.h | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/drivers/md/dm-pcache/cache.h b/drivers/md/dm-pcache/cache.h index 27613b56be54..021292c43677 100644 --- a/drivers/md/dm-pcache/cache.h +++ b/drivers/md/dm-pcache/cache.h @@ -180,6 +180,7 @@ struct pcache_cache { u32 advance; int ret; } writeback_ctx; + atomic_t writeback_errors; char gc_kset_onmedia_buf[PCACHE_KSET_ONMEDIA_SIZE_MAX]; struct delayed_work gc_work; @@ -273,7 +274,7 @@ struct pcache_cache_subtree_walk_ctx { struct list_head *submit_req_list; /* - * |--------| key_tmp + * |--------| key_tmp * |====| key */ int (*before)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp, @@ -281,7 +282,7 @@ struct pcache_cache_subtree_walk_ctx { /* * |----------| key_tmp - * |=====| key + * |=====| key */ int (*after)(struct pcache_cache_key *key, struct pcache_cache_key *key_tmp, struct pcache_cache_subtree_walk_ctx *ctx); @@ -421,6 +422,20 @@ static inline bool cache_seg_is_ctrl_seg(u32 cache_seg_id) } /** + * cache_seg_id_valid - Validate a cache segment id read from the cache device. + * @cache: Pointer to the pcache_cache structure. + * @cache_seg_id: Segment id decoded from on-media metadata. + * + * On-media segment ids are only protected by a CRC, which an attacker who can + * format the cache device computes over their chosen value. Reject any id that + * would index cache->segments[] out of bounds before it is dereferenced. + */ +static inline bool cache_seg_id_valid(struct pcache_cache *cache, u32 cache_seg_id) +{ + return cache_seg_id < cache->cache_info.n_segs; +} + +/** * cache_key_cutfront - Cuts a specified length from the front of a cache key. * @key: Pointer to pcache_cache_key structure. * @cut_len: Length to cut from the front. @@ -491,6 +506,27 @@ static inline u32 cache_key_data_crc(struct pcache_cache_key *key) return crc32c(PCACHE_CRC_SEED, data, key->len); } +/** + * kset_onmedia_valid - Validate a kset header read from the cache device. + * @kset_onmedia: Pointer to the kset copied from on-media metadata. + * + * The magic and CRC are attacker-computable (fixed public seed). A non-last + * kset stores key_num keys inline, and cache_kset_crc() and the replay loop + * read struct_size(.., data, key_num) bytes from a buffer sized for + * PCACHE_KSET_KEYS_MAX keys, so key_num must be bounded before any such use. + */ +static inline bool kset_onmedia_valid(struct pcache_cache_kset_onmedia *kset_onmedia) +{ + if (kset_onmedia->magic != PCACHE_KSET_MAGIC) + return false; + + if (!(kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST) && + kset_onmedia->key_num > PCACHE_KSET_KEYS_MAX) + return false; + + return true; +} + static inline u32 cache_kset_crc(struct pcache_cache_kset_onmedia *kset_onmedia) { u32 crc_size; @@ -630,6 +666,8 @@ static inline int cache_decode_dirty_tail(struct pcache_cache *cache) &cache->dirty_tail_index); } +int cache_verify_dirty_tail(struct pcache_cache *cache); + int pcache_cache_init(void); void pcache_cache_exit(void); #endif /* _PCACHE_CACHE_H */ |
