lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 28 Jun 2022 21:47:41 +0200
From:   Alexander Lobakin <alexandr.lobakin@...el.com>
To:     Alexei Starovoitov <ast@...nel.org>,
        Daniel Borkmann <daniel@...earbox.net>,
        Andrii Nakryiko <andrii@...nel.org>
Cc:     Alexander Lobakin <alexandr.lobakin@...el.com>,
        Larysa Zaremba <larysa.zaremba@...el.com>,
        Michal Swiatkowski <michal.swiatkowski@...ux.intel.com>,
        Jesper Dangaard Brouer <hawk@...nel.org>,
        Björn Töpel <bjorn@...nel.org>,
        Magnus Karlsson <magnus.karlsson@...el.com>,
        Maciej Fijalkowski <maciej.fijalkowski@...el.com>,
        Jonathan Lemon <jonathan.lemon@...il.com>,
        Toke Hoiland-Jorgensen <toke@...hat.com>,
        Lorenzo Bianconi <lorenzo@...nel.org>,
        "David S. Miller" <davem@...emloft.net>,
        Eric Dumazet <edumazet@...gle.com>,
        Jakub Kicinski <kuba@...nel.org>,
        Paolo Abeni <pabeni@...hat.com>,
        Jesse Brandeburg <jesse.brandeburg@...el.com>,
        John Fastabend <john.fastabend@...il.com>,
        Yajun Deng <yajun.deng@...ux.dev>,
        Willem de Bruijn <willemb@...gle.com>, bpf@...r.kernel.org,
        netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
        xdp-hints@...-project.net
Subject: [PATCH RFC bpf-next 21/52] net, xdp: allow metadata > 32

Hardware/driver-prepended XDP metadata might be much bigger than 32
bytes, especially if it includes a piece of a descriptor.
Relax the restriction and allow metadata larger than 32 bytes and
make __skb_metadata_differs() work with bigger lengths. The new
restriction is pretty much mechanical -- skb_shared_info::meta_len
is a u8 and XDP_PACKET_HEADROOM is 256 (minus
`sizeof(struct xdp_frame)`).
The requirement of having its length aligned to 4 bytes is still
valid.

Signed-off-by: Alexander Lobakin <alexandr.lobakin@...el.com>
---
 include/linux/skbuff.h | 13 ++++++++-----
 include/net/xdp_meta.h | 21 ++++++++++++++++++++-
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 82edf0359ab3..a825ea7f375d 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -4096,10 +4096,13 @@ static inline bool __skb_metadata_differs(const struct sk_buff *skb_a,
 {
 	const void *a = skb_metadata_end(skb_a);
 	const void *b = skb_metadata_end(skb_b);
-	/* Using more efficient varaiant than plain call to memcmp(). */
-#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
 	u64 diffs = 0;
 
+	if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
+	    BITS_PER_LONG != 64)
+		goto slow;
+
+	/* Using more efficient variant than plain call to memcmp(). */
 	switch (meta_len) {
 #define __it(x, op) (x -= sizeof(u##op))
 #define __it_diff(a, b, op) (*(u##op *)__it(a, op)) ^ (*(u##op *)__it(b, op))
@@ -4119,11 +4122,11 @@ static inline bool __skb_metadata_differs(const struct sk_buff *skb_a,
 		fallthrough;
 	case  4: diffs |= __it_diff(a, b, 32);
 		break;
+	default:
+slow:
+		return memcmp(a - meta_len, b - meta_len, meta_len);
 	}
 	return diffs;
-#else
-	return memcmp(a - meta_len, b - meta_len, meta_len);
-#endif
 }
 
 static inline bool skb_metadata_differs(const struct sk_buff *skb_a,
diff --git a/include/net/xdp_meta.h b/include/net/xdp_meta.h
index e1f3df9ceb93..3a40189d71c6 100644
--- a/include/net/xdp_meta.h
+++ b/include/net/xdp_meta.h
@@ -5,6 +5,7 @@
 #define __LINUX_NET_XDP_META_H__
 
 #include <net/xdp.h>
+#include <uapi/linux/bpf.h>
 
 /* Drivers not supporting XDP metadata can use this helper, which
  * rejects any room expansion for metadata as a result.
@@ -21,9 +22,27 @@ xdp_data_meta_unsupported(const struct xdp_buff *xdp)
 	return unlikely(xdp->data_meta > xdp->data);
 }
 
+/**
+ * xdp_metalen_invalid -- check if the length of a frame's metadata is valid
+ * @metalen: the length of the frame's metadata
+ *
+ * skb_shared_info::meta_len is of 1 byte long, thus it can't be longer than
+ * 255, but this always can change. XDP_PACKET_HEADROOM is 256, and this is a
+ * UAPI. sizeof(struct xdp_frame) is reserved since xdp_frame is being placed
+ * at xdp_buff::data_hard_start whilst being constructed on XDP_REDIRECT.
+ * The 32-bit alignment requirement is arbitrary, kept for simplicity and,
+ * sometimes, speed.
+ */
 static inline bool xdp_metalen_invalid(unsigned long metalen)
 {
-	return (metalen & (sizeof(__u32) - 1)) || (metalen > 32);
+	typeof(metalen) max;
+
+	max = min_t(typeof(max),
+		    (typeof_member(struct skb_shared_info, meta_len))~0UL,
+		    XDP_PACKET_HEADROOM - sizeof(struct xdp_frame));
+	BUILD_BUG_ON(!__builtin_constant_p(max));
+
+	return (metalen & (sizeof(u32) - 1)) || metalen > max;
 }
 
 #endif /* __LINUX_NET_XDP_META_H__ */
-- 
2.36.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ