#include "list.h"
#include "udev.h"
+#include "udev_lib.h"
#include "udev_version.h"
#include "udevd.h"
#include "logging.h"
-unsigned char logname[42];
static int expected_seqnum = 0;
volatile static int children_waiting;
volatile static int msg_q_timeout;
-LIST_HEAD(msg_list);
-LIST_HEAD(exec_list);
-LIST_HEAD(running_list);
+static LIST_HEAD(msg_list);
+static LIST_HEAD(exec_list);
+static LIST_HEAD(running_list);
static void exec_queue_manager(void);
static void msg_queue_manager(void);
+#ifdef LOG
+unsigned char logname[LOGNAME_SIZE];
+void log_message (int level, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vsyslog(level, format, args);
+ va_end(args);
+}
+#endif
+
static void msg_dump_queue(void)
{
struct hotplug_msg *msg;
static void udev_run(struct hotplug_msg *msg)
{
pid_t pid;
- setenv("ACTION", msg->action, 1);
- setenv("DEVPATH", msg->devpath, 1);
+ char action[ACTION_SIZE];
+ char devpath[DEVPATH_SIZE];
+ char *env[] = { action, devpath, NULL };
+
+ snprintf(action, sizeof(action), "ACTION=%s", msg->action);
+ snprintf(devpath, sizeof(devpath), "DEVPATH=%s", msg->devpath);
pid = fork();
switch (pid) {
case 0:
/* child */
- execl(UDEV_BIN, "udev", msg->subsystem, NULL);
+ execle(UDEV_BIN, "udev", msg->subsystem, NULL, env);
dbg("exec of child failed");
exit(1);
break;
{
struct hotplug_msg *msg;
int retval;
+ struct msghdr smsg;
+ struct cmsghdr *cmsg;
+ struct iovec iov;
+ struct ucred *cred;
+ char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
msg = msg_create();
if (msg == NULL) {
return;
}
- retval = recv(sock, msg, sizeof(struct hotplug_msg), 0);
+ iov.iov_base = msg;
+ iov.iov_len = sizeof(struct hotplug_msg);
+
+ memset(&smsg, 0x00, sizeof(struct msghdr));
+ smsg.msg_iov = &iov;
+ smsg.msg_iovlen = 1;
+ smsg.msg_control = cred_msg;
+ smsg.msg_controllen = sizeof(cred_msg);
+
+ retval = recvmsg(sock, &smsg, 0);
if (retval < 0) {
if (errno != EINTR)
dbg("unable to receive message");
return;
}
-
+ cmsg = CMSG_FIRSTHDR(&smsg);
+ cred = (struct ucred *) CMSG_DATA(cmsg);
+
+ if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
+ dbg("no sender credentials received, message ignored");
+ goto skip;
+ }
+
+ if (cred->uid != 0) {
+ dbg("sender uid=%i, message ignored", cred->uid);
+ goto skip;
+ }
+
if (strncmp(msg->magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
dbg("message magic '%s' doesn't match, ignore it", msg->magic);
- free(msg);
- return;
+ goto skip;
}
/* if no seqnum is given, we move straight to exec queue */
} else {
msg_queue_insert(msg);
}
+ return;
+
+skip:
+ free(msg);
+ return;
}
static void sig_handler(int signum)
struct sockaddr_un saddr;
socklen_t addrlen;
int retval;
+ const int on = 1;
+ struct sigaction act;
init_logging("udevd");
+ dbg("version %s", UDEV_VERSION);
- signal(SIGINT, sig_handler);
- signal(SIGTERM, sig_handler);
- signal(SIGALRM, sig_handler);
- signal(SIGCHLD, sig_handler);
+ if (getuid() != 0) {
+ dbg("need to be root, exit");
+ exit(1);
+ }
+
+ /* set signal handler */
+ act.sa_handler = sig_handler;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
/* we want these two to interrupt system calls */
- siginterrupt(SIGALRM, 1);
- siginterrupt(SIGCHLD, 1);
+ act.sa_flags = 0;
+ sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGCHLD, &act, NULL);
memset(&saddr, 0x00, sizeof(saddr));
saddr.sun_family = AF_LOCAL;
ssock = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (ssock == -1) {
- dbg("error getting socket");
+ dbg("error getting socket, exit");
exit(1);
}
/* the bind takes care of ensuring only one copy running */
- retval = bind(ssock, &saddr, addrlen);
+ retval = bind(ssock, (struct sockaddr *) &saddr, addrlen);
if (retval < 0) {
- dbg("bind failed\n");
+ dbg("bind failed, exit");
goto exit;
}
+ /* enable receiving of the sender credentials */
+ setsockopt(ssock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+
while (1) {
handle_msg(ssock);