about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2022-08-03 19:53:11 +0000
committerLaurent Bercot <ska@appnovation.com>2022-08-03 19:53:11 +0000
commit6e21f54b5519af90847d87158ecc75adb5892e1c (patch)
tree69c7d5ba2a75f5a2ef2578406fa3f9a1a4550c35
parent8ad0f7f39526ee0d8f52f44f5434dfd518f8897a (diff)
downloadmdevd-6e21f54b5519af90847d87158ecc75adb5892e1c.tar.gz
mdevd-6e21f54b5519af90847d87158ecc75adb5892e1c.tar.xz
mdevd-6e21f54b5519af90847d87158ecc75adb5892e1c.zip
Fix mdevd-coldlplug -O loop bug
mdevd-coldplug -O reads its data from mdevd, a user process,
so the check that we only read kernel data is invalid. Add an
option to mdevd_uevent_read() to activate the check or not.

Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--package/targets.mak2
-rw-r--r--src/mdevd/mdevd-coldplug.c6
-rw-r--r--src/mdevd/mdevd-internal.h3
-rw-r--r--src/mdevd/mdevd.c2
-rw-r--r--src/mdevd/mdevd_uevent_read.c8
5 files changed, 13 insertions, 8 deletions
diff --git a/package/targets.mak b/package/targets.mak
index 79e56ea..1a21f42 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -2,5 +2,7 @@ BIN_TARGETS := \
 mdevd \
 mdevd-coldplug
 
+INTERNAL_LIBS := libmdevd.a.xyzzy
+
 LIBEXEC_TARGETS :=
 
diff --git a/src/mdevd/mdevd-coldplug.c b/src/mdevd/mdevd-coldplug.c
index 2be7be0..e692fd4 100644
--- a/src/mdevd/mdevd-coldplug.c
+++ b/src/mdevd/mdevd-coldplug.c
@@ -145,9 +145,11 @@ int main (int argc, char const *const *argv, char const *const *envp)
   if (nlgroup && subsystem[0] && mdev[0])
   {
     struct uevent_s event ;
-    for (;;) if (mdevd_uevent_read(nlfd, &event, verbosity))
+    for (;;) if (mdevd_uevent_read(nlfd, &event, 0, verbosity))
     {
-      char *x = mdevd_uevent_getvar(&event, "SUBSYSTEM") ;
+      char *x = mdevd_uevent_getvar(&event, "ACTION") ;
+      if (strcmp(x, "add")) continue ;
+      x = mdevd_uevent_getvar(&event, "SUBSYSTEM") ;
       if (strcmp(x, subsystem)) continue ;
       x = mdevd_uevent_getvar(&event, "MDEV") ;
       if (!strcmp(x, mdev)) break ;
diff --git a/src/mdevd/mdevd-internal.h b/src/mdevd/mdevd-internal.h
index cc98a6d..cff7cdf 100644
--- a/src/mdevd/mdevd-internal.h
+++ b/src/mdevd/mdevd-internal.h
@@ -6,6 +6,7 @@
 #define UEVENT_MAX_VARS 63
 #define UEVENT_MAX_SIZE 8192
 
+#include <stdint.h>
 #include <limits.h>
 
 struct uevent_s
@@ -18,7 +19,7 @@ struct uevent_s
 #define UEVENT_ZERO { .len = 0, .varn = 0 }
 
 extern int mdevd_netlink_init (unsigned int, unsigned int) ;
-extern int mdevd_uevent_read (int, struct uevent_s *, unsigned int) ;
+extern int mdevd_uevent_read (int, struct uevent_s *, uint32_t, unsigned int) ;
 extern char *mdevd_uevent_getvar (struct uevent_s *, char const *) ;
 
 #endif
diff --git a/src/mdevd/mdevd.c b/src/mdevd/mdevd.c
index 2bc6e08..1ac2bc6 100644
--- a/src/mdevd/mdevd.c
+++ b/src/mdevd/mdevd.c
@@ -862,7 +862,7 @@ static inline int handle_signals (struct uevent_s *event, scriptelem const *scri
 
 static inline int handle_event (int fd, struct uevent_s *event, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, udata *ud)
 {
-  if (!mdevd_uevent_read(fd, event, verbosity) || event->varn <= 1) return 0 ;
+  if (!mdevd_uevent_read(fd, event, 1, verbosity) || event->varn <= 1) return 0 ;
   return on_event(event, script, scriptlen, storage, envmatch, ud) ;
 }
 
diff --git a/src/mdevd/mdevd_uevent_read.c b/src/mdevd/mdevd_uevent_read.c
index 2cb4245..ed33843 100644
--- a/src/mdevd/mdevd_uevent_read.c
+++ b/src/mdevd/mdevd_uevent_read.c
@@ -24,7 +24,7 @@ static inline ssize_t fd_recvmsg (int fd, struct msghdr *hdr)
   return r ;
 }
 
-static inline size_t netlink_read (int fd, char *s, unsigned int verbosity)
+static inline size_t netlink_read (int fd, char *s, uint32_t options, unsigned int verbosity)
 {
   struct sockaddr_nl nl;
   struct iovec v = { .iov_base = s, .iov_len = UEVENT_MAX_SIZE } ;
@@ -44,7 +44,7 @@ static inline size_t netlink_read (int fd, char *s, unsigned int verbosity)
   if (!r) return 0 ;
   if (msg.msg_flags & MSG_TRUNC)
     strerr_diefu1x(111, "buffer too small for netlink message") ;
-  if (nl.nl_pid)
+  if (options & 1 && nl.nl_pid)
   {
     if (verbosity >= 3)
     {
@@ -67,10 +67,10 @@ static inline size_t netlink_read (int fd, char *s, unsigned int verbosity)
   return r ;
 }
 
-int mdevd_uevent_read (int fd, struct uevent_s *event, unsigned int verbosity)
+int mdevd_uevent_read (int fd, struct uevent_s *event, uint32_t options, unsigned int verbosity)
 {
   unsigned short len = 0 ;
-  event->len = netlink_read(fd, event->buf, verbosity) ;
+  event->len = netlink_read(fd, event->buf, options, verbosity) ;
   if (!event->len) return 0 ;
   event->varn = 0 ;
   while (len < event->len)