git: 8a1576dc26b9 - main - truss: track Netlink socket protocols
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 05 Jul 2026 14:15:53 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=8a1576dc26b90706948061e5ed33f07a03a5899c
commit 8a1576dc26b90706948061e5ed33f07a03a5899c
Author: Ishan Agrawal <iagrawal9990@gmail.com>
AuthorDate: 2026-07-04 03:40:31 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2026-07-05 14:03:20 +0000
truss: track Netlink socket protocols
Record the Netlink protocol associated with AF_NETLINK sockets when
they are created and pass it to libsysdecode during message decoding.
Use the protocol to distinguish between Generic Netlink and Route
Netlink sockets, ensuring that Generic Netlink decoding is only
performed for NETLINK_GENERIC sockets.
Signed-off-by: Ishan Agrawal <iagrawal9990@gmail.com>
Reviewed by: kp
Sponsored-by : Google LLC (GSoC 2026)
---
lib/libsysdecode/netlink.c | 2 +-
lib/libsysdecode/sysdecode.h | 3 ++-
usr.bin/truss/setup.c | 1 +
usr.bin/truss/syscalls.c | 32 ++++++++++++++++++++------------
usr.bin/truss/truss.h | 1 +
5 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/lib/libsysdecode/netlink.c b/lib/libsysdecode/netlink.c
index 2143a0d391a5..723272d3b8da 100644
--- a/lib/libsysdecode/netlink.c
+++ b/lib/libsysdecode/netlink.c
@@ -21,7 +21,7 @@
* to fallback to a standard hex/string dump.
*/
bool
-sysdecode_netlink(FILE *fp, const void *buf, size_t len)
+sysdecode_netlink(FILE *fp, const void *buf, size_t len, int protocol)
{
const struct nlmsghdr *nl = buf;
size_t remaining = len;
diff --git a/lib/libsysdecode/sysdecode.h b/lib/libsysdecode/sysdecode.h
index 3675a582a9b8..bd38bb5bdc42 100644
--- a/lib/libsysdecode/sysdecode.h
+++ b/lib/libsysdecode/sysdecode.h
@@ -136,7 +136,8 @@ bool sysdecode_wait4_options(FILE *_fp, int _options, int *_rem);
bool sysdecode_wait6_options(FILE *_fp, int _options, int *_rem);
const char *sysdecode_whence(int _whence);
bool sysdecode_shmflags(FILE *_fp, int _flags, int *_rem);
-bool sysdecode_netlink(FILE *_fp, const void *_buf, size_t _len);
+bool sysdecode_netlink(FILE *_fp, const void *_buf, size_t _len,
+ int _protocol);
#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__)
diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c
index ecc4a1792144..d35b392aba1e 100644
--- a/usr.bin/truss/setup.c
+++ b/usr.bin/truss/setup.c
@@ -587,6 +587,7 @@ exit_syscall(struct trussinfo *info, struct ptrace_lwpinfo *pl)
f->fd = (int)psr.sr_retval[0];
f->domain = (int)t->cs.args[0];
+ f->protocol = (int)t->cs.args[2];
LIST_INSERT_HEAD(&p->fdlist, f, entries);
}
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
index dbc621124071..a92c903dc691 100644
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -1573,17 +1573,17 @@ user_ptr32_to_psaddr(int32_t user_pointer)
* Check whether a file descriptor belongs to an AF_NETLINK socket
* for the current traced process.
*/
-static bool
-is_netlink(struct trussinfo *trussinfo, int num_fd)
+static int
+get_netlink_protocol(struct trussinfo *trussinfo, int num_fd)
{
struct procinfo *p = trussinfo->curthread->proc;
struct fd_domain *f;
LIST_FOREACH(f, &p->fdlist, entries) {
if (f->fd == num_fd && f->domain == AF_NETLINK)
- return (true);
+ return (f->protocol);
}
- return (false);
+ return (-1);
}
#define NETLINK_MAX_DECODE 4096
@@ -1593,7 +1593,8 @@ is_netlink(struct trussinfo *trussinfo, int num_fd)
* and attempt to decode and print it.
*/
static bool
-print_netlink(FILE *fp, struct trussinfo *trussinfo, void *msg, size_t len)
+print_netlink(FILE *fp, struct trussinfo *trussinfo, void *msg, size_t len,
+ int protocol)
{
char *buf;
pid_t pid = trussinfo->curthread->proc->pid;
@@ -1615,7 +1616,7 @@ print_netlink(FILE *fp, struct trussinfo *trussinfo, void *msg, size_t len)
return (false);
}
- if (sysdecode_netlink(fp, buf, read_len)) {
+ if (sysdecode_netlink(fp, buf, read_len, protocol)) {
success = true;
}
free(buf);
@@ -1690,12 +1691,18 @@ print_arg(struct syscall_arg *sc, syscallarg_t *args, syscallarg_t *retval,
}
case BinString: {
if ((strcmp(decode->name, "sendto") == 0 ||
- strcmp(decode->name, "recvfrom") == 0) &&
- is_netlink(trussinfo, (int)args[0]))
- if (print_netlink(fp, trussinfo,
+ strcmp(decode->name, "recvfrom") == 0)) {
+
+ int protocol =
+ get_netlink_protocol(trussinfo, (int)args[0]);
+
+ if ((protocol != -1) &&
+ print_netlink(fp, trussinfo,
(void *)args[sc->offset],
- (size_t)args[sc->offset + 1]))
+ (size_t)args[sc->offset + 1],
+ protocol))
break;
+ }
/*
* Binary block of data that might have printable characters.
* XXX If type|OUT, assume that the length is the syscall's
@@ -2770,11 +2777,12 @@ print_arg(struct syscall_arg *sc, syscallarg_t *args, syscallarg_t *retval,
print_sockaddr(fp, trussinfo, (uintptr_t)msghdr.msg_name, msghdr.msg_namelen);
fprintf(fp, ",%d,", msghdr.msg_namelen);
/* Attempt Netlink decode; fallback to standard iovec if it fails. */
- if ((!is_netlink(trussinfo, (int)args[0])) ||
+ int protocol = get_netlink_protocol(trussinfo, (int)args[0]);
+ if ((protocol == -1) ||
(get_struct(pid, (uintptr_t)msghdr.msg_iov,
&iov, sizeof(iov)) == -1) ||
(!print_netlink(fp, trussinfo, (void *)iov.iov_base,
- (size_t)iov.iov_len))) {
+ (size_t)iov.iov_len, protocol))) {
print_iovec(fp, trussinfo, (uintptr_t)msghdr.msg_iov,
msghdr.msg_iovlen);
}
diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h
index 737ebc184806..077460fe4090 100644
--- a/usr.bin/truss/truss.h
+++ b/usr.bin/truss/truss.h
@@ -100,6 +100,7 @@ struct fd_domain
int fd;
int domain;
+ int protocol;
};
struct procinfo {