diff options
author | Andrii Nakryiko <andrii@kernel.org> | 2021-08-15 00:13:33 -0700 |
---|---|---|
committer | Andrii Nakryiko <andrii@kernel.org> | 2021-08-15 00:19:10 -0700 |
commit | fa183a86eefd47188054974e67dff2b8e9012aba (patch) | |
tree | 79e57fa8095f7d37d9a0e41cf230c8727f548df5 /net/unix/af_unix.c | |
parent | d1bf7c4d5deae6685a42463f4d29418fd2515d05 (diff) | |
parent | ce547335d4a42e645320402b24aeadb39531f73c (diff) |
Merge branch 'BPF iterator for UNIX domain socket.'
Kuniyuki Iwashima says:
====================
This patch set adds BPF iterator support for UNIX domain socket. The first
patch implements it, and the second adds "%c" support for BPF_SEQ_PRINTF().
Thanks to Yonghong Song for the fix [0] for the LLVM code gen. The fix
prevents the LLVM compiler from transforming the loop exit condition '<' to
'!=', where the upper bound is not a constant. The transformation leads
the verifier to interpret it as an infinite loop.
And thanks to Andrii Nakryiko for its workaround [1].
[0] https://reviews.llvm.org/D107483
[1] https://lore.kernel.org/netdev/CAEf4BzZ3sVx1m1mOCcPcuVPiY6cWEAO=6VGHDiXEs9ZVD-RoLg@mail.gmail.com/
Changelog:
v6:
- Align the header "Inde" column
- Change int vars to __u64 not to break test_progs-no_alu32
- Move the if statement into the for loop not to depend on the fix [0]
- Drop the README change
- Modify "%c" positive test patterns
v5:
https://lore.kernel.org/netdev/20210812164557.79046-1-kuniyu@amazon.co.jp/
- Align header line of bpf_iter_unix.c
- Add test for "%c"
v4:
https://lore.kernel.org/netdev/20210810092807.13190-1-kuniyu@amazon.co.jp/
- Check IS_BUILTIN(CONFIG_UNIX)
- Support "%c" in BPF_SEQ_PRINTF()
- Uncomment the code to print the name of the abstract socket
- Mention the LLVM fix in README.rst
- Remove the 'aligned' attribute in bpf_iter.h
- Keep the format string on a single line
v3:
https://lore.kernel.org/netdev/20210804070851.97834-1-kuniyu@amazon.co.jp/
- Export some functions for CONFIG_UNIX=m
v2:
https://lore.kernel.org/netdev/20210803011110.21205-1-kuniyu@amazon.co.jp/
- Implement bpf_iter specific seq_ops->stop()
- Add bpf_iter__unix in bpf_iter.h
- Move common definitions in selftest to bpf_tracing_net.h
- Include the code for abstract UNIX domain socket as comment in selftest
- Use ASSERT_OK_PTR() instead of CHECK()
- Make ternary operators on single line
v1:
https://lore.kernel.org/netdev/20210729233645.4869-1-kuniyu@amazon.co.jp/
====================
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1c2224f05b51..bad8f19174e3 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -113,6 +113,7 @@ #include <linux/security.h> #include <linux/freezer.h> #include <linux/file.h> +#include <linux/btf_ids.h> #include "scm.h" @@ -3143,6 +3144,64 @@ static const struct seq_operations unix_seq_ops = { .stop = unix_seq_stop, .show = unix_seq_show, }; + +#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) +struct bpf_iter__unix { + __bpf_md_ptr(struct bpf_iter_meta *, meta); + __bpf_md_ptr(struct unix_sock *, unix_sk); + uid_t uid __aligned(8); +}; + +static int unix_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta, + struct unix_sock *unix_sk, uid_t uid) +{ + struct bpf_iter__unix ctx; + + meta->seq_num--; /* skip SEQ_START_TOKEN */ + ctx.meta = meta; + ctx.unix_sk = unix_sk; + ctx.uid = uid; + return bpf_iter_run_prog(prog, &ctx); +} + +static int bpf_iter_unix_seq_show(struct seq_file *seq, void *v) +{ + struct bpf_iter_meta meta; + struct bpf_prog *prog; + struct sock *sk = v; + uid_t uid; + + if (v == SEQ_START_TOKEN) + return 0; + + uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)); + meta.seq = seq; + prog = bpf_iter_get_info(&meta, false); + return unix_prog_seq_show(prog, &meta, v, uid); +} + +static void bpf_iter_unix_seq_stop(struct seq_file *seq, void *v) +{ + struct bpf_iter_meta meta; + struct bpf_prog *prog; + + if (!v) { + meta.seq = seq; + prog = bpf_iter_get_info(&meta, true); + if (prog) + (void)unix_prog_seq_show(prog, &meta, v, 0); + } + + unix_seq_stop(seq, v); +} + +static const struct seq_operations bpf_iter_unix_seq_ops = { + .start = unix_seq_start, + .next = unix_seq_next, + .stop = bpf_iter_unix_seq_stop, + .show = bpf_iter_unix_seq_show, +}; +#endif #endif static const struct net_proto_family unix_family_ops = { @@ -3183,6 +3242,35 @@ static struct pernet_operations unix_net_ops = { .exit = unix_net_exit, }; +#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) +DEFINE_BPF_ITER_FUNC(unix, struct bpf_iter_meta *meta, + struct unix_sock *unix_sk, uid_t uid) + +static const struct bpf_iter_seq_info unix_seq_info = { + .seq_ops = &bpf_iter_unix_seq_ops, + .init_seq_private = bpf_iter_init_seq_net, + .fini_seq_private = bpf_iter_fini_seq_net, + .seq_priv_size = sizeof(struct seq_net_private), +}; + +static struct bpf_iter_reg unix_reg_info = { + .target = "unix", + .ctx_arg_info_size = 1, + .ctx_arg_info = { + { offsetof(struct bpf_iter__unix, unix_sk), + PTR_TO_BTF_ID_OR_NULL }, + }, + .seq_info = &unix_seq_info, +}; + +static void __init bpf_iter_register(void) +{ + unix_reg_info.ctx_arg_info[0].btf_id = btf_sock_ids[BTF_SOCK_TYPE_UNIX]; + if (bpf_iter_reg_target(&unix_reg_info)) + pr_warn("Warning: could not register bpf iterator unix\n"); +} +#endif + static int __init af_unix_init(void) { int rc = -1; @@ -3198,6 +3286,11 @@ static int __init af_unix_init(void) sock_register(&unix_family_ops); register_pernet_subsys(&unix_net_ops); unix_bpf_build_proto(); + +#if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) + bpf_iter_register(); +#endif + out: return rc; } |