From: eillon yezhenyu2@huawei.com
euleros inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4YW86
--------------------------------
When building with defconfig on arm32, we got a compile error: ./include/linux/page-flags-layout.h:95:2: error: #error "Not enough bits in page flags" 95 | #error "Not enough bits in page flags" | ^~~~~
Limit PG_reserve_pgflag_0 and PG_reserve_pgflag_1 to compile only on X86_64 and ARM64 to resolve this issue.
Fixes: afdf2a6cdee7 ("kabi: Add reserved page and gfp flags for future extension") Signed-off-by: eillon yezhenyu2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/linux/page-flags.h | 2 ++ include/trace/events/mmflags.h | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index e1af0a6c8165..65e1cbe1d1ce 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -150,8 +150,10 @@ enum pageflags { * flags which backported from kernel upstream, please place them * behind the reserved page flags. */ +#if defined(CONFIG_X86_64) || defined(CONFIG_ARM64) PG_reserve_pgflag_0, PG_reserve_pgflag_1, +#endif
__NR_PAGEFLAGS,
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h index b50012bea1ef..366d972ce735 100644 --- a/include/trace/events/mmflags.h +++ b/include/trace/events/mmflags.h @@ -89,8 +89,12 @@
#if defined(CONFIG_X86_64) || defined(CONFIG_ARM64) #define IF_HAVE_PG_POOL(flag,string) ,{1UL << flag, string} +#define IF_HAVE_PG_RESERVE0(flag,string) ,{1UL << flag, string} +#define IF_HAVE_PG_RESERVE1(flag,string) ,{1UL << flag, string} #else #define IF_HAVE_PG_POOL(flag,string) +#define IF_HAVE_PG_RESERVE0(flag,string) +#define IF_HAVE_PG_RESERVE1(flag,string) #endif
#ifdef CONFIG_PIN_MEMORY @@ -128,9 +132,9 @@ IF_HAVE_PG_IDLE(PG_young, "young" ) \ IF_HAVE_PG_IDLE(PG_idle, "idle" ) \ IF_HAVE_PG_ARCH_2(PG_arch_2, "arch_2" ) \ IF_HAVE_PG_POOL(PG_pool, "pool" ) \ -IF_HAVE_PG_HOTREPLACE(PG_hotreplace, "hotreplace" ), \ - {1UL << PG_reserve_pgflag_0, "reserve_pgflag_0"}, \ - {1UL << PG_reserve_pgflag_1, "reserve_pgflag_1"} +IF_HAVE_PG_HOTREPLACE(PG_hotreplace, "hotreplace" ) \ +IF_HAVE_PG_RESERVE0(PG_reserve_pgflag_0,"reserve_pgflag_0") \ +IF_HAVE_PG_RESERVE1(PG_reserve_pgflag_1,"reserve_pgflag_1")
#define show_page_flags(flags) \ (flags) ? __print_flags(flags, "|", \
From: Yunsheng Lin linyunsheng@huawei.com
mainline inclusion from mainline-v5.15-rc1 commit 723783d077e39c256a1fafebbd97cbb14207c28f category: bugfix bugzilla: 186409, https://gitee.com/openeuler/kernel/issues/I4YXSX CVE: CVE-2022-0886
--------------------------------
Both SKB_FRAG_PAGE_ORDER are defined to the same value in net/core/sock.c and drivers/vhost/net.c.
Move the SKB_FRAG_PAGE_ORDER definition to net/core/sock.h, as both net/core/sock.c and drivers/vhost/net.c include it, and it seems a reasonable file to put the macro.
Signed-off-by: Yunsheng Lin linyunsheng@huawei.com Acked-by: Jason Wang jasowang@redhat.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Xu Jia xujia39@huawei.com Reviewed-by: Wei Yongjun weiyongjun1@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/vhost/net.c | 2 -- include/net/sock.h | 1 + net/core/sock.c | 1 - 3 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 666c2d5b6673..379bae56040a 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -651,8 +651,6 @@ static bool tx_can_batch(struct vhost_virtqueue *vq, size_t total_len) !vhost_vq_avail_empty(vq->dev, vq); }
-#define SKB_FRAG_PAGE_ORDER get_order(32768) - static bool vhost_net_page_frag_refill(struct vhost_net *net, unsigned int sz, struct page_frag *pfrag, gfp_t gfp) { diff --git a/include/net/sock.h b/include/net/sock.h index e2150b3ecd41..c958be11d172 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2693,6 +2693,7 @@ extern int sysctl_optmem_max; extern __u32 sysctl_wmem_default; extern __u32 sysctl_rmem_default;
+#define SKB_FRAG_PAGE_ORDER get_order(32768) DECLARE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
static inline int sk_get_wmem0(const struct sock *sk, const struct proto *proto) diff --git a/net/core/sock.c b/net/core/sock.c index 6d9af4ef93d7..bee3c320dbfe 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2445,7 +2445,6 @@ static void sk_leave_memory_pressure(struct sock *sk) } }
-#define SKB_FRAG_PAGE_ORDER get_order(32768) DEFINE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key);
/**
From: Steffen Klassert steffen.klassert@secunet.com
mainline inclusion from mainline commit ebe48d368e97d007bfeb76fcb065d6cfc4c96645 category: bugfix bugzilla: 186409, https://gitee.com/openeuler/kernel/issues/I4YXSX CVE: CVE-2022-0886
--------------------------------
The maximum message size that can be send is bigger than the maximum site that skb_page_frag_refill can allocate. So it is possible to write beyond the allocated buffer.
Fix this by doing a fallback to COW in that case.
v2:
Avoid get get_order() costs as suggested by Linus Torvalds.
Fixes: cac2661c53f3 ("esp4: Avoid skb_cow_data whenever possible") Fixes: 03e2a30f6a27 ("esp6: Avoid skb_cow_data whenever possible") Reported-by: valis sec@valis.email Signed-off-by: Steffen Klassert steffen.klassert@secunet.com Signed-off-by: Xu Jia xujia39@huawei.com Reviewed-by: Wei Yongjun weiyongjun1@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- include/net/esp.h | 2 ++ net/ipv4/esp4.c | 5 +++++ net/ipv6/esp6.c | 5 +++++ 3 files changed, 12 insertions(+)
diff --git a/include/net/esp.h b/include/net/esp.h index 9c5637d41d95..90cd02ff77ef 100644 --- a/include/net/esp.h +++ b/include/net/esp.h @@ -4,6 +4,8 @@
#include <linux/skbuff.h>
+#define ESP_SKB_FRAG_MAXSIZE (PAGE_SIZE << SKB_FRAG_PAGE_ORDER) + struct ip_esp_hdr;
static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index ed9857b2875d..e2b91fca93ba 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -448,6 +448,7 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * struct page *page; struct sk_buff *trailer; int tailen = esp->tailen; + unsigned int allocsz;
/* this is non-NULL only with TCP/UDP Encapsulation */ if (x->encap) { @@ -457,6 +458,10 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * return err; }
+ allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); + if (allocsz > ESP_SKB_FRAG_MAXSIZE) + goto cow; + if (!skb_cloned(skb)) { if (tailen <= skb_tailroom(skb)) { nfrags = 1; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 7f2ffc7b1f75..e106dc3ec039 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -483,6 +483,7 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info struct page *page; struct sk_buff *trailer; int tailen = esp->tailen; + unsigned int allocsz;
if (x->encap) { int err = esp6_output_encap(x, skb, esp); @@ -491,6 +492,10 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info return err; }
+ allocsz = ALIGN(skb->data_len + tailen, L1_CACHE_BYTES); + if (allocsz > ESP_SKB_FRAG_MAXSIZE) + goto cow; + if (!skb_cloned(skb)) { if (tailen <= skb_tailroom(skb)) { nfrags = 1;