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:
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) {