bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Yafang Shao <laoar.shao@gmail.com>
To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
	kafai@fb.com, songliubraving@fb.com, yhs@fb.com,
	john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com,
	haoluo@google.com, jolsa@kernel.org
Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org,
	Yafang Shao <laoar.shao@gmail.com>
Subject: [RFC PATCH bpf-next 09/13] bpf: Alloc and free bpf_prog id in bpf namespace
Date: Sun, 26 Mar 2023 09:22:04 +0000	[thread overview]
Message-ID: <20230326092208.13613-10-laoar.shao@gmail.com> (raw)
In-Reply-To: <20230326092208.13613-1-laoar.shao@gmail.com>

Similar to bpf map, We only expose the bpf map id under current bpf
namespace to user. The prog->aux->id is still the id in the init bpf
namespace.
The id of used_maps is also the id in current bpf namespace.

The result as follows,

Run bpftool in current namespace,
$ bpftool map show
4: array  name kprobe_b.rodata  flags 0x80
        key 4B  value 37B  max_entries 1  memlock 360B
        btf_id 96  frozen
        pids kprobe(8790)
5: array  name kprobe_b.data  flags 0x400
        key 4B  value 4B  max_entries 1  memlock 8192B
        btf_id 96
        pids kprobe(8790)

$ bpftool prog show
7: kprobe  name kretprobe_run  tag 0de47cc241a2b1b3  gpl
        loaded_at 2023-03-21T10:20:58+0800  uid 0
        xlated 56B  jited 39B  memlock 4096B  map_ids 4
        btf_id 96
9: kprobe  name kprobe_run  tag bf163b23cd3b174d  gpl
        loaded_at 2023-03-21T10:20:58+0800  uid 0
        xlated 48B  jited 35B  memlock 4096B  map_ids 4
        btf_id 96

At the same time, run bpftool in init bpf namespace.
$ bpftool map show
18: array  name kprobe_b.rodata  flags 0x80
        key 4B  value 37B  max_entries 1  memlock 360B
        btf_id 96  frozen
        pids kprobe(8790)
19: array  name kprobe_b.data  flags 0x400
        key 4B  value 4B  max_entries 1  memlock 8192B
        btf_id 96
        pids kprobe(8790)

$ bpftool prog show
29: kprobe  name kretprobe_run  tag 0de47cc241a2b1b3  gpl
        loaded_at 2023-03-21T10:20:58+0800  uid 0
        xlated 56B  jited 39B  memlock 4096B  map_ids 18
        btf_id 96
        pids kprobe(8790)
31: kprobe  name kprobe_run  tag bf163b23cd3b174d  gpl
        loaded_at 2023-03-21T10:20:58+0800  uid 0
        xlated 48B  jited 35B  memlock 4096B  map_ids 18
        btf_id 96
        pids kprobe(8790)

In init bpf namespace, bpftool can also show other bpf progs, but the
bpftool running in the new bpf namespace can't.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
---
 include/linux/bpf.h                       |  3 +-
 kernel/bpf/bpf_namespace.c                |  1 +
 kernel/bpf/syscall.c                      | 56 ++++++++++---------------------
 tools/bpf/bpftool/skeleton/pid_iter.bpf.c |  3 +-
 4 files changed, 22 insertions(+), 41 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 2a1f19c..16f2a01 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1416,6 +1416,7 @@ struct bpf_prog_aux {
 		struct work_struct work;
 		struct rcu_head	rcu;
 	};
+	struct bpf_obj_id *obj_id;
 };
 
 struct bpf_prog {
@@ -1940,8 +1941,6 @@ struct bpf_prog *bpf_prog_get_type_dev(u32 ufd, enum bpf_prog_type type,
 struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog);
 void bpf_prog_put(struct bpf_prog *prog);
 
-void bpf_prog_free_id(struct bpf_prog *prog);
-
 struct btf_field *btf_record_find(const struct btf_record *rec,
 				  u32 offset, u32 field_mask);
 void btf_record_free(struct btf_record *rec);
diff --git a/kernel/bpf/bpf_namespace.c b/kernel/bpf/bpf_namespace.c
index 6a6ef70..8c70945 100644
--- a/kernel/bpf/bpf_namespace.c
+++ b/kernel/bpf/bpf_namespace.c
@@ -12,6 +12,7 @@
 
 #define MAX_BPF_NS_LEVEL 32
 DEFINE_SPINLOCK(map_idr_lock);
+DEFINE_SPINLOCK(prog_idr_lock);
 static struct kmem_cache *bpfns_cachep;
 static struct kmem_cache *obj_id_cache[MAX_PID_NS_LEVEL];
 static struct ns_common *bpfns_get(struct task_struct *task);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 1335200..4725924 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -48,8 +48,6 @@
 #define BPF_OBJ_FLAG_MASK   (BPF_F_RDONLY | BPF_F_WRONLY)
 
 DEFINE_PER_CPU(int, bpf_prog_active);
-static DEFINE_IDR(prog_idr);
-DEFINE_SPINLOCK(prog_idr_lock);
 static DEFINE_IDR(link_idr);
 DEFINE_SPINLOCK(link_idr_lock);
 
@@ -1983,32 +1981,10 @@ static void bpf_audit_prog(const struct bpf_prog *prog, unsigned int op)
 	if (unlikely(!ab))
 		return;
 	audit_log_format(ab, "prog-id=%u op=%s",
-			 prog->aux->id, bpf_audit_str[op]);
+			 bpf_obj_id_vnr(prog->aux->obj_id), bpf_audit_str[op]);
 	audit_log_end(ab);
 }
 
-static int bpf_prog_alloc_id(struct bpf_prog *prog)
-{
-	int id;
-
-	idr_preload(GFP_KERNEL);
-	spin_lock_bh(&prog_idr_lock);
-	id = idr_alloc_cyclic(&prog_idr, prog, 1, INT_MAX, GFP_ATOMIC);
-	spin_unlock_bh(&prog_idr_lock);
-	idr_preload_end();
-
-	return id;
-}
-
-void bpf_prog_free_id(struct bpf_prog *prog)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&prog_idr_lock, flags);
-	idr_remove(&prog_idr, prog->aux->id);
-	spin_unlock_irqrestore(&prog_idr_lock, flags);
-}
-
 static void __bpf_prog_put_rcu(struct rcu_head *rcu)
 {
 	struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
@@ -2056,7 +2032,7 @@ static void bpf_prog_put_deferred(struct work_struct *work)
 	 * simply waiting for refcnt to drop to be freed.
 	 */
 	if (prog->aux->id) {
-		bpf_prog_free_id(prog);
+		bpf_free_obj_id(prog->aux->obj_id, PROG_OBJ_ID);
 		prog->aux->id = 0;
 	}
 	__bpf_prog_put_noref(prog, true);
@@ -2157,7 +2133,7 @@ static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
 		   prog->jited,
 		   prog_tag,
 		   prog->pages * 1ULL << PAGE_SHIFT,
-		   prog->aux->id,
+		   bpf_obj_id_vnr(prog->aux->obj_id),
 		   stats.nsecs,
 		   stats.cnt,
 		   stats.misses,
@@ -2468,6 +2444,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
 	enum bpf_prog_type type = attr->prog_type;
 	struct bpf_prog *prog, *dst_prog = NULL;
 	struct btf *attach_btf = NULL;
+	struct bpf_obj_id *obj_id;
 	int err;
 	char license[128];
 	bool is_gpl;
@@ -2621,12 +2598,13 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr)
 	if (err < 0)
 		goto free_used_maps;
 
-	err = bpf_prog_alloc_id(prog);
-	if (err < 0)
+	obj_id = bpf_alloc_obj_id(current->nsproxy->bpf_ns, prog, PROG_OBJ_ID);
+	if (IS_ERR(obj_id))
 		goto free_used_maps;
-	prog->aux->id = err;
+	prog->aux->obj_id = obj_id;
+	prog->aux->id = bpf_obj_id_nr(obj_id);
 
-	/* Upon success of bpf_prog_alloc_id(), the BPF prog is
+	/* Upon success of bpf_alloc_obj_id(), the BPF prog is
 	 * effectively publicly exposed. However, retrieving via
 	 * bpf_prog_get_fd_by_id() will take another reference,
 	 * therefore it cannot be gone underneath us.
@@ -2803,7 +2781,7 @@ static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
 			   "prog_tag:\t%s\n"
 			   "prog_id:\t%u\n",
 			   prog_tag,
-			   prog->aux->id);
+			   bpf_obj_id_vnr(prog->aux->obj_id));
 	}
 	if (link->ops->show_fdinfo)
 		link->ops->show_fdinfo(link, m);
@@ -3706,11 +3684,12 @@ struct bpf_map *bpf_map_get_curr_or_next(u32 *id)
 
 struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id)
 {
+	struct bpf_namespace *ns = current->nsproxy->bpf_ns;
 	struct bpf_prog *prog;
 
 	spin_lock_bh(&prog_idr_lock);
 again:
-	prog = idr_get_next(&prog_idr, id);
+	prog = idr_get_next(&ns->idr[PROG_OBJ_ID], id);
 	if (prog) {
 		prog = bpf_prog_inc_not_zero(prog);
 		if (IS_ERR(prog)) {
@@ -3727,13 +3706,14 @@ struct bpf_prog *bpf_prog_get_curr_or_next(u32 *id)
 
 struct bpf_prog *bpf_prog_by_id(u32 id)
 {
+	struct bpf_namespace *ns = current->nsproxy->bpf_ns;
 	struct bpf_prog *prog;
 
 	if (!id)
 		return ERR_PTR(-ENOENT);
 
 	spin_lock_bh(&prog_idr_lock);
-	prog = idr_find(&prog_idr, id);
+	prog = idr_find(&ns->idr[PROG_OBJ_ID], id);
 	if (prog)
 		prog = bpf_prog_inc_not_zero(prog);
 	else
@@ -3939,7 +3919,7 @@ static int bpf_prog_get_info_by_fd(struct file *file,
 		return -EFAULT;
 
 	info.type = prog->type;
-	info.id = prog->aux->id;
+	info.id = bpf_obj_id_vnr(prog->aux->obj_id);
 	info.load_time = prog->aux->load_time;
 	info.created_by_uid = from_kuid_munged(current_user_ns(),
 					       prog->aux->user->uid);
@@ -4287,7 +4267,7 @@ static int bpf_link_get_info_by_fd(struct file *file,
 	info.type = link->type;
 	info.id = link->id;
 	if (link->prog)
-		info.prog_id = link->prog->aux->id;
+		info.prog_id = bpf_obj_id_vnr(link->prog->aux->obj_id);
 
 	if (link->ops->fill_link_info) {
 		err = link->ops->fill_link_info(link, &info);
@@ -4452,7 +4432,7 @@ static int bpf_task_fd_query(const union bpf_attr *attr,
 			struct bpf_raw_event_map *btp = raw_tp->btp;
 
 			err = bpf_task_fd_query_copy(attr, uattr,
-						     raw_tp->link.prog->aux->id,
+						     bpf_obj_id_vnr(raw_tp->link.prog->aux->obj_id),
 						     BPF_FD_TYPE_RAW_TRACEPOINT,
 						     btp->tp->name, 0, 0);
 			goto put_file;
@@ -5048,7 +5028,7 @@ static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size)
 		break;
 	case BPF_PROG_GET_NEXT_ID:
 		err = bpf_obj_get_next_id(&attr, uattr.user,
-					  &prog_idr, &prog_idr_lock);
+					  &ns->idr[PROG_OBJ_ID], &prog_idr_lock);
 		break;
 	case BPF_MAP_GET_NEXT_ID:
 		err = bpf_obj_get_next_id(&attr, uattr.user,
diff --git a/tools/bpf/bpftool/skeleton/pid_iter.bpf.c b/tools/bpf/bpftool/skeleton/pid_iter.bpf.c
index a71aef7..1fd8ceb 100644
--- a/tools/bpf/bpftool/skeleton/pid_iter.bpf.c
+++ b/tools/bpf/bpftool/skeleton/pid_iter.bpf.c
@@ -28,7 +28,8 @@ static __always_inline __u32 get_obj_id(void *ent, enum bpf_obj_type type)
 
 	switch (type) {
 	case BPF_OBJ_PROG:
-		return BPF_CORE_READ((struct bpf_prog *)ent, aux, id);
+		obj_id = BPF_CORE_READ((struct bpf_prog *)ent, aux, obj_id);
+		break;
 	case BPF_OBJ_MAP:
 		obj_id = BPF_CORE_READ((struct bpf_map *)ent, obj_id);
 		break;
-- 
1.8.3.1


  parent reply	other threads:[~2023-03-26  9:22 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-26  9:21 [RFC PATCH bpf-next 00/13] bpf: Introduce BPF namespace Yafang Shao
2023-03-26  9:21 ` [RFC PATCH bpf-next 01/13] fork: New clone3 flag for " Yafang Shao
2023-03-26  9:21 ` [RFC PATCH bpf-next 02/13] proc_ns: Extend the field type in struct proc_ns_operations to long Yafang Shao
2023-03-26  9:21 ` [RFC PATCH bpf-next 03/13] bpf: Implement bpf namespace Yafang Shao
2023-03-26  9:21 ` [RFC PATCH bpf-next 04/13] bpf: No need to check if id is 0 Yafang Shao
2023-03-26  9:22 ` [RFC PATCH bpf-next 05/13] bpf: Make bpf objects id have the same alloc and free pattern Yafang Shao
2023-03-26  9:22 ` [RFC PATCH bpf-next 06/13] bpf: Helpers to alloc and free object id in bpf namespace Yafang Shao
2023-03-26  9:22 ` [RFC PATCH bpf-next 07/13] bpf: Add bpf helper to get bpf object id Yafang Shao
2023-03-26  9:22 ` [RFC PATCH bpf-next 08/13] bpf: Alloc and free bpf_map id in bpf namespace Yafang Shao
2023-03-26 10:50   ` Toke Høiland-Jørgensen
2023-03-27  2:44     ` Yafang Shao
2023-03-26  9:22 ` Yafang Shao [this message]
2023-03-26  9:22 ` [RFC PATCH bpf-next 10/13] bpf: Alloc and free bpf_link " Yafang Shao
2023-03-26  9:22 ` [RFC PATCH bpf-next 11/13] bpf: Allow iterating bpf objects with CAP_BPF " Yafang Shao
2023-03-26  9:22 ` [RFC PATCH bpf-next 12/13] bpf: Use bpf_idr_lock array instead Yafang Shao
2023-03-26  9:22 ` [RFC PATCH bpf-next 13/13] selftests/bpf: Add selftest for bpf namespace Yafang Shao
2023-03-26 10:49 ` [RFC PATCH bpf-next 00/13] bpf: Introduce BPF namespace Toke Høiland-Jørgensen
2023-03-27  3:07   ` Yafang Shao
2023-03-27 20:51     ` Toke Høiland-Jørgensen
2023-03-28  3:48       ` Yafang Shao
2023-03-27 17:28 ` Stanislav Fomichev
2023-03-28  3:42   ` Yafang Shao
2023-03-28 17:15     ` Stanislav Fomichev
2023-03-29  3:02       ` Yafang Shao
2023-03-29 20:50         ` Stanislav Fomichev
2023-03-30  2:40           ` Yafang Shao
2023-03-27 19:03 ` Song Liu
2023-03-28  3:47   ` Yafang Shao
2023-04-02 23:37     ` Alexei Starovoitov
2023-04-03  3:05       ` Yafang Shao
2023-04-03 22:50         ` Alexei Starovoitov
2023-04-04  2:59           ` Yafang Shao
2023-04-06  2:06             ` Alexei Starovoitov
2023-04-06  2:54               ` Yafang Shao
2023-04-06  3:05                 ` Alexei Starovoitov
2023-04-06  3:22                   ` Yafang Shao
2023-04-06  4:24                     ` Alexei Starovoitov
2023-04-06  5:43                       ` Yafang Shao
2023-04-06 20:22                         ` Andrii Nakryiko
2023-04-07  1:43                           ` Alexei Starovoitov
2023-04-07  4:33                             ` Yafang Shao
2023-04-07 15:32                               ` Alexei Starovoitov
2023-04-07 15:59                             ` Andrii Nakryiko
2023-04-07 16:05                               ` Alexei Starovoitov
2023-04-07 16:21                                 ` Yafang Shao
2023-04-07 16:31                                   ` Alexei Starovoitov
2023-04-07 16:35                                     ` Yafang Shao
2023-03-31  5:52 ` Hao Luo
2023-04-01 16:32   ` Yafang Shao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230326092208.13613-10-laoar.shao@gmail.com \
    --to=laoar.shao@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kafai@fb.com \
    --cc=kpsingh@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sdf@google.com \
    --cc=songliubraving@fb.com \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).