diff options
Diffstat (limited to 'nldev.c')
-rw-r--r-- | nldev.c | 133 |
1 files changed, 14 insertions, 119 deletions
@@ -24,44 +24,22 @@ #include "arg.h" #include "log.h" -int listfd = -1; int dofork = 0; -struct handler { - int fd; - int argc; - char **argv; -}; - -void -spawn_handler(struct handler *child) +pid_t +spawn_handler(int fd, char **argv) { - int pipefd[2]; - - if (pipe(pipefd) == -1) - edie("pipe"); - pid_t pid = fork(); if (pid < 0) edie("fork"); if (pid == 0) { - close(pipefd[1]); - dup2(pipefd[0], 0); - execv(child->argv[0], child->argv); + dup2(fd, 0); + execv(argv[0], argv); edie("execl"); } - close(pipefd[0]); - child->fd = pipefd[1]; -} - -int -write_to_handler(struct handler *child, const char *buf, size_t count) -{ - if (child->fd == -1) - spawn_handler(child); - return write(child->fd, buf, count); + return pid; } void @@ -129,25 +107,13 @@ init_netlink_socket(void) void usage(void) { - die("usage: %s [-hdb] [-ku] [-- run [...]]\n", argv0); + die("usage: %s [-bd] -- runpath [...]\n", argv0); } int main(int argc, char *argv[]) { - struct sockaddr_nl cnls; - struct pollfd fds[2]; - struct msghdr hdr; - struct iovec iov; - char buf[4097], cbuf[CMSG_SPACE(sizeof(struct ucred))]; - struct cmsghdr *chdr; - struct ucred *cred; - int len, showudev, showkernel; - - struct handler child; - - showkernel = 1; - showudev = 1; + struct pollfd fds; ARGBEGIN { case 'b': @@ -156,27 +122,12 @@ main(int argc, char *argv[]) case 'd': dodebug = 1; break; - case 'k': - showudev = 0; - break; - case 'u': - showkernel = 0; - break; default: usage(); } ARGEND; - child.fd = -1; - child.argc = argc; - child.argv = argv; - - fds[0].events = POLLIN; - fds[0].fd = init_netlink_socket(); - - fds[1].fd = child.fd; - fds[1].events = POLLERR; - - listfd = fds[0].fd; + fds.events = POLLIN; + fds.fd = init_netlink_socket(); if (dofork) { if (daemon(0, 0) < 0) @@ -186,68 +137,12 @@ main(int argc, char *argv[]) initsignals(); - while (poll(fds, 2, -1) > -1) { - if (fds[1].revents & POLLERR) { - dbg("handler exited"); - close(child.fd); - fds[1].fd = child.fd = -1; - } - - if (!(fds[0].revents & POLLIN)) - continue; - - iov.iov_base = &buf; - iov.iov_len = sizeof(buf); - memset(&hdr, 0, sizeof(hdr)); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - hdr.msg_control = cbuf; - hdr.msg_controllen = sizeof(cbuf); - hdr.msg_name = &cnls; - hdr.msg_namelen = sizeof(cnls); - - len = recvmsg(fds[0].fd, &hdr, 0); - if (len < 0) { - if (errno == EINTR) - continue; - edie("recvmsg"); - } - if (len < 32 || len >= sizeof(buf)) - continue; - - chdr = CMSG_FIRSTHDR(&hdr); - if (chdr == NULL || chdr->cmsg_type != SCM_CREDENTIALS) - continue; - - /* - * Don't allow anyone but root to send us messages. - * - * We will allow users to send us messages, when - * udev is enabled. Udev is just a toy you should - * only use for testing. - */ - cred = (struct ucred *)CMSG_DATA(chdr); - if (cred->uid != 0 && !showudev) - continue; - - if (!memcmp(buf, "libudev", 8)) { - /* - * Receiving messages from udev is insecure. - */ - if (!showudev) - continue; - } else { - if (!showkernel) - continue; - /* - * Kernel messages shouldn't come from the - * userspace. - */ - if (cnls.nl_pid > 0) - continue; + while (poll(&fds, 1, -1) > -1) { + if (fds.revents & POLLIN) { + int status; + pid_t childpid = spawn_handler(fds.fd, argv); + waitpid(childpid, &status, 0); } - write_to_handler(&child, buf, len); - fds[1].fd = child.fd; } return 0; |