nlmon

NetLink MONitor; a lightweight udevadm monitor replacement.
git clone git://r-36.net/nlmon
Log | Files | Refs | LICENSE

commit b7a5e96412c29606d5a18919b62789b29a894892
parent f1f75870440190dbc194e15467091c96f7e83346
Author: Christoph Lohmann <20h@r-36.net>
Date:   Sat, 28 Apr 2012 11:14:59 +0200

More safe standard-compliant msg handling.

Diffstat:
config.mk | 2+-
nlmon.c | 44+++++++++++++++++++++++++++++++++++++++-----
2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/config.mk b/config.mk @@ -15,7 +15,7 @@ LIBS = -L/usr/lib -lc # flags CPPFLAGS = -DVERSION=\"${VERSION}\" CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -LDFLAGS = -g ${LIBS} +LDFLAGS = -g -static ${LIBS} #LDFLAGS = -s ${LIBS} # compiler and linker diff --git a/nlmon.c b/nlmon.c @@ -56,8 +56,10 @@ usage(void) int main(int argc, char *argv[]) { - struct sockaddr_nl nls; + struct sockaddr_nl nls, cnls; struct pollfd fds; + struct msghdr hdr; + struct iovec iov; char buf[4097], obuf[4098], *subsystem; int i, len, olen, slen, showudev, showkernel; @@ -84,26 +86,58 @@ main(int argc, char *argv[]) nls.nl_pid = getpid(); nls.nl_groups = -1; + /* + * The whole process of decoding the kernel messages is + * kept simple to avoid clashes with root rights. One + * goal of nlmon is to be able to decode the kernel + * messages in userspace. + */ + fds.events = POLLIN; fds.fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (fds.fd < 0) edie("socket"); + /* + * Setting the sockopts here will require root rights. + * Just keep it that way and pretend to have a big + * enough buffer. + */ + if (bind(fds.fd, (void *)&nls, sizeof(nls))) edie("bind"); buf[sizeof(buf)-1] = '\0'; while (poll(&fds, 1, -1) > -1) { - len = recv(fds.fd, buf, sizeof(buf)-1, MSG_DONTWAIT); - if (len < 0) - edie("recv"); + iov.iov_base = &buf; + iov.iov_len = sizeof(buf); + memset(&hdr, 0, sizeof(hdr)); + hdr.msg_iov = &iov; + hdr.msg_iovlen = 1; + hdr.msg_name = &cnls; + hdr.msg_namelen = sizeof(cnls); + + len = recvmsg(fds.fd, &hdr, 0); + if (len < 0) { + if (errno == EINTR) + continue; + edie("recvmsg"); + } + if (len < 32 || len >= sizeof(buf)) + continue; - if (strstr(buf, "libudev")) { + if (!memcmp(buf, "libudev", 8)) { if (!showudev) continue; } else { if (!showkernel) continue; + + /* + * Kernel messages should be from root. + */ + if (cnls.nl_pid > 0) + continue; } for (i = 0, olen = 0; i < len; i += slen + 1) {