Patch "bpf: Reject struct_ops registration that uses module ptr and the module btf_id is missing" has been added to the 6.12-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    bpf: Reject struct_ops registration that uses module ptr and the module btf_id is missing

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     bpf-reject-struct_ops-registration-that-uses-module-.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 5d362f7310c0bf545cebcdc083599379ed58d908
Author: Martin KaFai Lau <martin.lau@xxxxxxxxxx>
Date:   Fri Dec 20 12:18:18 2024 -0800

    bpf: Reject struct_ops registration that uses module ptr and the module btf_id is missing
    
    [ Upstream commit 96ea081ed52bf077cad6d00153b6fba68e510767 ]
    
    There is a UAF report in the bpf_struct_ops when CONFIG_MODULES=n.
    In particular, the report is on tcp_congestion_ops that has
    a "struct module *owner" member.
    
    For struct_ops that has a "struct module *owner" member,
    it can be extended either by the regular kernel module or
    by the bpf_struct_ops. bpf_try_module_get() will be used
    to do the refcounting and different refcount is done
    based on the owner pointer. When CONFIG_MODULES=n,
    the btf_id of the "struct module" is missing:
    
    WARN: resolve_btfids: unresolved symbol module
    
    Thus, the bpf_try_module_get() cannot do the correct refcounting.
    
    Not all subsystem's struct_ops requires the "struct module *owner" member.
    e.g. the recent sched_ext_ops.
    
    This patch is to disable bpf_struct_ops registration if
    the struct_ops has the "struct module *" member and the
    "struct module" btf_id is missing. The btf_type_is_fwd() helper
    is moved to the btf.h header file for this test.
    
    This has happened since the beginning of bpf_struct_ops which has gone
    through many changes. The Fixes tag is set to a recent commit that this
    patch can apply cleanly. Considering CONFIG_MODULES=n is not
    common and the age of the issue, targeting for bpf-next also.
    
    Fixes: 1611603537a4 ("bpf: Create argument information for nullable arguments.")
    Reported-by: Robert Morris <rtm@xxxxxxxxxxxxx>
    Closes: https://lore.kernel.org/bpf/74665.1733669976@localhost/
    Signed-off-by: Martin KaFai Lau <martin.lau@xxxxxxxxxx>
    Tested-by: Eduard Zingerman <eddyz87@xxxxxxxxx>
    Acked-by: Eduard Zingerman <eddyz87@xxxxxxxxx>
    Link: https://lore.kernel.org/r/20241220201818.127152-1-martin.lau@xxxxxxxxx
    Signed-off-by: Alexei Starovoitov <ast@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/include/linux/btf.h b/include/linux/btf.h
index b8a583194c4a9..d99178ce01d21 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -352,6 +352,11 @@ static inline bool btf_type_is_scalar(const struct btf_type *t)
 	return btf_type_is_int(t) || btf_type_is_enum(t);
 }
 
+static inline bool btf_type_is_fwd(const struct btf_type *t)
+{
+	return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
+}
+
 static inline bool btf_type_is_typedef(const struct btf_type *t)
 {
 	return BTF_INFO_KIND(t->info) == BTF_KIND_TYPEDEF;
diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
index b3a2ce1e5e22e..b70d0eef8a284 100644
--- a/kernel/bpf/bpf_struct_ops.c
+++ b/kernel/bpf/bpf_struct_ops.c
@@ -311,6 +311,20 @@ void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_ops_desc)
 	kfree(arg_info);
 }
 
+static bool is_module_member(const struct btf *btf, u32 id)
+{
+	const struct btf_type *t;
+
+	t = btf_type_resolve_ptr(btf, id, NULL);
+	if (!t)
+		return false;
+
+	if (!__btf_type_is_struct(t) && !btf_type_is_fwd(t))
+		return false;
+
+	return !strcmp(btf_name_by_offset(btf, t->name_off), "module");
+}
+
 int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
 			     struct btf *btf,
 			     struct bpf_verifier_log *log)
@@ -390,6 +404,13 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc,
 			goto errout;
 		}
 
+		if (!st_ops_ids[IDX_MODULE_ID] && is_module_member(btf, member->type)) {
+			pr_warn("'struct module' btf id not found. Is CONFIG_MODULES enabled? bpf_struct_ops '%s' needs module support.\n",
+				st_ops->name);
+			err = -EOPNOTSUPP;
+			goto errout;
+		}
+
 		func_proto = btf_type_resolve_func_ptr(btf,
 						       member->type,
 						       NULL);
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 41d20b7199c4a..a44f4be592be7 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -498,11 +498,6 @@ bool btf_type_is_void(const struct btf_type *t)
 	return t == &btf_void;
 }
 
-static bool btf_type_is_fwd(const struct btf_type *t)
-{
-	return BTF_INFO_KIND(t->info) == BTF_KIND_FWD;
-}
-
 static bool btf_type_is_datasec(const struct btf_type *t)
 {
 	return BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC;




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux