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]
Message-Id: <20250422-afabre-traits-010-rfc2-v2-17-92bcc6b146c9@arthurfabre.com>
Date: Tue, 22 Apr 2025 15:23:46 +0200
From: Arthur Fabre <arthur@...hurfabre.com>
To: netdev@...r.kernel.org, bpf@...r.kernel.org
Cc: jakub@...udflare.com, hawk@...nel.org, yan@...udflare.com, 
 jbrandeburg@...udflare.com, thoiland@...hat.com, lbiancon@...hat.com, 
 ast@...nel.org, kuba@...nel.org, edumazet@...gle.com, 
 Arthur Fabre <arthur@...hurfabre.com>
Subject: [PATCH RFC bpf-next v2 17/17] trait: Allow socket filters to
 access traits

Add kfuncs to allow socket filter programs access to traits in an skb.

To ensure every skb can modify traits independently, copy on write if
multiple skbs are using the same traits.

To allow new traits to be set (which requires more memory), try to use
up more of the headroom of the skb if we run out of space setting.

Signed-off-by: Arthur Fabre <arthur@...hurfabre.com>
---
 include/linux/skbuff.h |   9 ++++
 net/core/skbuff.c      | 112 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ae569b1b1af83b586e1be6c69439ef74bac38cf3..e573889cf1256e7aff84b488af875a13f558cb01 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -4874,9 +4874,11 @@ void *__skb_ext_set(struct sk_buff *skb, enum skb_ext_id id,
 		    struct skb_ext *ext);
 void *skb_ext_add(struct sk_buff *skb, enum skb_ext_id id);
 void *skb_ext_from_headroom(struct sk_buff *skb, enum skb_ext_id id, int head_offset, int size);
+bool skb_ext_grow_headroom(const struct sk_buff *skb, int add);
 void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id);
 void __skb_ext_put(struct skb_ext *ext);
 int __skb_ext_total_size(const struct skb_ext *ext);
+int skb_ext_size(const struct sk_buff *skb, enum skb_ext_id id);
 
 static inline void skb_ext_put(struct sk_buff *skb)
 {
@@ -4960,6 +4962,13 @@ static inline void *skb_traits(const struct sk_buff *skb)
 #endif
 }
 
+int skb_trait_set(struct sk_buff *skb, u64 key,
+			const void *val, u64 val__sz, u64 flags);
+int skb_trait_is_set(const struct sk_buff *skb, u64 key);
+int skb_trait_get(const struct sk_buff *skb, u64 key,
+			void *val, u64 val__sz);
+int skb_trait_del(const struct sk_buff *skb, u64 key);
+
 static inline void nf_reset_ct(struct sk_buff *skb)
 {
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 9f27caba82af0be7897b68b5fad087f3e9c62955..27e163b83b12ffac973e1e098f035b807e1f4232 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -7148,6 +7148,19 @@ void *skb_ext_from_headroom(struct sk_buff *skb, enum skb_ext_id id, int head_of
 	return __skb_ext_set_active(skb, new, id);
 }
 
+bool skb_ext_grow_headroom(const struct sk_buff *skb, int add)
+{
+	if (!skb->active_extensions)
+		return false;
+	if (skb->extensions->mode != SKB_EXT_HEADROOM)
+		return false;
+	if (skb_headroom(skb) < add)
+		return false;
+
+	skb->extensions->chunks += SKB_EXT_CHUNKS(add);
+	return true;
+}
+
 #ifdef CONFIG_XFRM
 static void skb_ext_put_sp(struct sec_path *sp)
 {
@@ -7215,8 +7228,107 @@ int __skb_ext_total_size(const struct skb_ext *ext)
 {
 	return SKB_EXT_CHUNKS_BYTES(ext->chunks);
 }
+
+int skb_ext_size(const struct sk_buff *skb, enum skb_ext_id id)
+{
+	if (!skb_ext_exist(skb, id))
+		return 0;
+
+	switch (skb->extensions->mode) {
+	case SKB_EXT_ALLOC:
+		return skb_ext_type_len[id];
+	case SKB_EXT_HEADROOM:
+		return SKB_EXT_CHUNKS_BYTES(skb->extensions->chunks - skb->extensions->offset[id]);
+	}
+}
 #endif /* CONFIG_SKB_EXTENSIONS */
 
+__bpf_kfunc_start_defs();
+
+__bpf_kfunc int skb_trait_set(struct sk_buff *skb, u64 key,
+			      const void *val, u64 val__sz, u64 flags)
+{
+#ifndef CONFIG_SKB_EXTENSIONS
+	return -EOPNOTSUPP;
+#else
+	int err;
+	void *traits = skb_traits(skb);
+
+	if (!traits)
+		return -EOPNOTSUPP;
+
+	/* Traits are shared, get our own copy before modifying */
+	if (refcount_read(&skb->extensions->refcnt) > 1) {
+		traits = skb_ext_add(skb, SKB_EXT_TRAITS);
+		if (!traits)
+			return -ENOMEM;
+	}
+
+	err = trait_set(traits, traits + skb_ext_size(skb, SKB_EXT_TRAITS),
+			key, val, val__sz, flags);
+	if (err == -ENOSPC && skb->extensions->mode == SKB_EXT_HEADROOM) {
+		/* Take more headroom if available */
+		if (!skb_ext_grow_headroom(skb, val__sz))
+			return err;
+
+		err = trait_set(traits, traits + skb_ext_size(skb, SKB_EXT_TRAITS),
+				key, val, val__sz, flags);
+	}
+	return err;
+#endif /* CONFIG_SKB_EXTENSIONS */
+}
+
+__bpf_kfunc int skb_trait_is_set(const struct sk_buff *skb, u64 key)
+{
+	void *traits = skb_traits(skb);
+
+	if (!traits)
+		return -EOPNOTSUPP;
+
+	return trait_is_set(traits, key);
+}
+
+__bpf_kfunc int skb_trait_get(const struct sk_buff *skb, u64 key,
+			      void *val, u64 val__sz)
+{
+	void *traits = skb_traits(skb);
+
+	if (!traits)
+		return -EOPNOTSUPP;
+
+	return trait_get(traits, key, val, val__sz);
+}
+
+__bpf_kfunc int skb_trait_del(const struct sk_buff *skb, u64 key)
+{
+	void *traits = skb_traits(skb);
+
+	if (!traits)
+		return -EOPNOTSUPP;
+
+	return trait_del(traits, key);
+}
+
+__bpf_kfunc_end_defs();
+
+BTF_KFUNCS_START(bpf_skb_traits)
+BTF_ID_FLAGS(func, skb_trait_set)
+BTF_ID_FLAGS(func, skb_trait_is_set)
+BTF_ID_FLAGS(func, skb_trait_get)
+BTF_ID_FLAGS(func, skb_trait_del)
+BTF_KFUNCS_END(bpf_skb_traits)
+
+static const struct btf_kfunc_id_set bpf_traits_kfunc_set = {
+	.owner = THIS_MODULE,
+	.set   = &bpf_skb_traits,
+};
+
+static int init_subsystem(void)
+{
+	return register_btf_kfunc_id_set(BPF_PROG_TYPE_SOCKET_FILTER, &bpf_traits_kfunc_set);
+}
+late_initcall(init_subsystem);
+
 static void kfree_skb_napi_cache(struct sk_buff *skb)
 {
 	/* if SKB is a clone, don't handle this case */

-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ