From: Yang Yingliang yangyingliang@huawei.com
hulk inclusion category: bugfix bugzilla: 47452 CVE: NA
-------------------------------------------------
Use bit-23 for connector debug will change __GFP_BITS_SHIFT that will break some driver to use this flag. So we use bit-31 instead and keep __GFP_BITS_SHIFT unchanged.
For using GFP_CONNECTOR, it need be ignored when checking slab bug mask in new_slab().
If driver uses wrong gfp flag (bit-31) and also use __GFP_ZERO to allocate zeroed memory, the last 8-bytes memory will not be set to 0, so set magic number before clear memory to avoid this.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- drivers/connector/connector.c | 6 +++++- include/linux/gfp.h | 8 ++++---- mm/slub.c | 10 +++++++--- 3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index b5cdd0b99736..a4c5e04fcaaa 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -107,7 +107,11 @@ int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 __group,
size = sizeof(*msg) + len;
- skb = nlmsg_new(size, gfp_mask | GFP_CONNECTOR); + if (sysctl_connector_debug) + skb = nlmsg_new(size, gfp_mask | GFP_CONNECTOR); + else + skb = nlmsg_new(size, gfp_mask); + if (!skb) return -ENOMEM;
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index e3274fdc2736..d7b5f2333fc3 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -39,13 +39,13 @@ struct vm_area_struct; #define ___GFP_ACCOUNT 0x100000u #define ___GFP_DIRECT_RECLAIM 0x200000u #define ___GFP_KSWAPD_RECLAIM 0x400000u -#define ___GFP_CONNECTOR 0x800000u #ifdef CONFIG_LOCKDEP -#define ___GFP_NOLOCKDEP 0x1000000u +#define ___GFP_NOLOCKDEP 0x800000u #else #define ___GFP_NOLOCKDEP 0 #endif -/* used bit-23 for dfx in connector */ +/* used bit-31 for dfx in connector */ +#define ___GFP_CONNECTOR 0x80000000u #define __GFP_CONNECTOR ((__force gfp_t)___GFP_CONNECTOR) #define GFP_CONNECTOR __GFP_CONNECTOR /* If the above are modified, __GFP_BITS_SHIFT may need updating */ @@ -221,7 +221,7 @@ struct vm_area_struct; #define __GFP_NOLOCKDEP ((__force gfp_t)___GFP_NOLOCKDEP)
/* Room for N __GFP_FOO bits */ -#define __GFP_BITS_SHIFT (24 + IS_ENABLED(CONFIG_LOCKDEP)) +#define __GFP_BITS_SHIFT (23 + IS_ENABLED(CONFIG_LOCKDEP)) #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
/** diff --git a/mm/slub.c b/mm/slub.c index 2301c04353d0..3cfec27018ac 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1689,12 +1689,16 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) { if (unlikely(flags & GFP_SLAB_BUG_MASK)) { gfp_t invalid_mask = flags & GFP_SLAB_BUG_MASK; + if (sysctl_connector_debug && + (invalid_mask & GFP_CONNECTOR)) + goto out; flags &= ~GFP_SLAB_BUG_MASK; pr_warn("Unexpected gfp: %#x (%pGg). Fixing up to gfp: %#x (%pGg). Fix your code!\n", invalid_mask, &invalid_mask, flags, &flags); dump_stack(); }
+out: return allocate_slab(s, flags & (GFP_RECLAIM_MASK | GFP_CONSTRAINT_MASK), node); } @@ -2782,15 +2786,15 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, stat(s, ALLOC_FASTPATH); }
- if (unlikely(gfpflags & __GFP_ZERO) && object) - memset(object, 0, s->object_size); - if (sysctl_connector_debug && unlikely(gfpflags & __GFP_CONNECTOR) && object) { if (s->object_size == 512) memset(object + 504, 0xad, 8); }
+ if (unlikely(gfpflags & __GFP_ZERO) && object) + memset(object, 0, s->object_size); + slab_post_alloc_hook(s, gfpflags, 1, &object);
return object;