mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-31 08:28:13 +00:00
5ce7ab4961
In BSD and abstract address cases, we store sockets in the hash table with keys between 0 and UNIX_HASH_SIZE - 1. However, the hash saved in a socket varies depending on its address type; sockets with BSD addresses always have UNIX_HASH_SIZE in their unix_sk(sk)->addr->hash. This is just for the UNIX_ABSTRACT() macro used to check the address type. The difference of the saved hashes comes from the first byte of the address in the first place. So, we can test it directly. Then we can keep a real hash in each socket and replace unix_table_lock with per-hash locks in the later patch. Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
80 lines
2 KiB
C
80 lines
2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright Amazon.com Inc. or its affiliates. */
|
|
#include "bpf_iter.h"
|
|
#include "bpf_tracing_net.h"
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_endian.h>
|
|
|
|
char _license[] SEC("license") = "GPL";
|
|
|
|
static long sock_i_ino(const struct sock *sk)
|
|
{
|
|
const struct socket *sk_socket = sk->sk_socket;
|
|
const struct inode *inode;
|
|
unsigned long ino;
|
|
|
|
if (!sk_socket)
|
|
return 0;
|
|
|
|
inode = &container_of(sk_socket, struct socket_alloc, socket)->vfs_inode;
|
|
bpf_probe_read_kernel(&ino, sizeof(ino), &inode->i_ino);
|
|
return ino;
|
|
}
|
|
|
|
SEC("iter/unix")
|
|
int dump_unix(struct bpf_iter__unix *ctx)
|
|
{
|
|
struct unix_sock *unix_sk = ctx->unix_sk;
|
|
struct sock *sk = (struct sock *)unix_sk;
|
|
struct seq_file *seq;
|
|
__u32 seq_num;
|
|
|
|
if (!unix_sk)
|
|
return 0;
|
|
|
|
seq = ctx->meta->seq;
|
|
seq_num = ctx->meta->seq_num;
|
|
if (seq_num == 0)
|
|
BPF_SEQ_PRINTF(seq, "Num RefCount Protocol Flags Type St Inode Path\n");
|
|
|
|
BPF_SEQ_PRINTF(seq, "%pK: %08X %08X %08X %04X %02X %8lu",
|
|
unix_sk,
|
|
sk->sk_refcnt.refs.counter,
|
|
0,
|
|
sk->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
|
|
sk->sk_type,
|
|
sk->sk_socket ?
|
|
(sk->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
|
|
(sk->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
|
|
sock_i_ino(sk));
|
|
|
|
if (unix_sk->addr) {
|
|
if (unix_sk->addr->name->sun_path[0]) {
|
|
BPF_SEQ_PRINTF(seq, " %s", unix_sk->addr->name->sun_path);
|
|
} else {
|
|
/* The name of the abstract UNIX domain socket starts
|
|
* with '\0' and can contain '\0'. The null bytes
|
|
* should be escaped as done in unix_seq_show().
|
|
*/
|
|
__u64 i, len;
|
|
|
|
len = unix_sk->addr->len - sizeof(short);
|
|
|
|
BPF_SEQ_PRINTF(seq, " @");
|
|
|
|
for (i = 1; i < len; i++) {
|
|
/* unix_mkname() tests this upper bound. */
|
|
if (i >= sizeof(struct sockaddr_un))
|
|
break;
|
|
|
|
BPF_SEQ_PRINTF(seq, "%c",
|
|
unix_sk->addr->name->sun_path[i] ?:
|
|
'@');
|
|
}
|
|
}
|
|
}
|
|
|
|
BPF_SEQ_PRINTF(seq, "\n");
|
|
|
|
return 0;
|
|
}
|