1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2020 Facebook */ 3 /* "undefine" structs in vmlinux.h, because we "override" them below */ 4 #define bpf_iter_meta bpf_iter_meta___not_used 5 #define bpf_iter__netlink bpf_iter__netlink___not_used 6 #include "vmlinux.h" 7 #undef bpf_iter_meta 8 #undef bpf_iter__netlink 9 #include <bpf/bpf_helpers.h> 10 #include <bpf/bpf_tracing.h> 11 12 char _license[] SEC("license") = "GPL"; 13 14 #define sk_rmem_alloc sk_backlog.rmem_alloc 15 #define sk_refcnt __sk_common.skc_refcnt 16 17 struct bpf_iter_meta { 18 struct seq_file *seq; 19 __u64 session_id; 20 __u64 seq_num; 21 } __attribute__((preserve_access_index)); 22 23 struct bpf_iter__netlink { 24 struct bpf_iter_meta *meta; 25 struct netlink_sock *sk; 26 } __attribute__((preserve_access_index)); 27 28 static inline struct inode *SOCK_INODE(struct socket *socket) 29 { 30 return &container_of(socket, struct socket_alloc, socket)->vfs_inode; 31 } 32 33 SEC("iter/netlink") 34 int dump_netlink(struct bpf_iter__netlink *ctx) 35 { 36 struct seq_file *seq = ctx->meta->seq; 37 struct netlink_sock *nlk = ctx->sk; 38 unsigned long group, ino; 39 struct inode *inode; 40 struct socket *sk; 41 struct sock *s; 42 43 if (nlk == (void *)0) 44 return 0; 45 46 if (ctx->meta->seq_num == 0) 47 BPF_SEQ_PRINTF(seq, "sk Eth Pid Groups " 48 "Rmem Wmem Dump Locks Drops " 49 "Inode\n"); 50 51 s = &nlk->sk; 52 BPF_SEQ_PRINTF(seq, "%pK %-3d ", s, s->sk_protocol); 53 54 if (!nlk->groups) { 55 group = 0; 56 } else { 57 /* FIXME: temporary use bpf_probe_read here, needs 58 * verifier support to do direct access. 59 */ 60 bpf_probe_read(&group, sizeof(group), &nlk->groups[0]); 61 } 62 BPF_SEQ_PRINTF(seq, "%-10u %08x %-8d %-8d %-5d %-8d ", 63 nlk->portid, (u32)group, 64 s->sk_rmem_alloc.counter, 65 s->sk_wmem_alloc.refs.counter - 1, 66 nlk->cb_running, s->sk_refcnt.refs.counter); 67 68 sk = s->sk_socket; 69 if (!sk) { 70 ino = 0; 71 } else { 72 /* FIXME: container_of inside SOCK_INODE has a forced 73 * type conversion, and direct access cannot be used 74 * with current verifier. 75 */ 76 inode = SOCK_INODE(sk); 77 bpf_probe_read(&ino, sizeof(ino), &inode->i_ino); 78 } 79 BPF_SEQ_PRINTF(seq, "%-8u %-8lu\n", s->sk_drops.counter, ino); 80 81 return 0; 82 } 83