aboutsummaryrefslogtreecommitdiff
path: root/util-linux/uevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/uevent.c')
-rw-r--r--util-linux/uevent.c41
1 files changed, 12 insertions, 29 deletions
diff --git a/util-linux/uevent.c b/util-linux/uevent.c
index 761743f45..7a1d7d4a7 100644
--- a/util-linux/uevent.c
+++ b/util-linux/uevent.c
@@ -46,37 +46,19 @@ enum { RCVBUF = 2 * 1024 * 1024 };
46int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 46int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
47int uevent_main(int argc UNUSED_PARAM, char **argv) 47int uevent_main(int argc UNUSED_PARAM, char **argv)
48{ 48{
49 struct sockaddr_nl sa;
50 int fd; 49 int fd;
51 50
52 INIT_G(); 51 INIT_G();
53 52
54 argv++; 53 argv++;
55 54
56 // Subscribe for UEVENT kernel messages 55 // Subscribe for UEVENT kernel messages.
57 sa.nl_family = AF_NETLINK;
58 sa.nl_pad = 0;
59 sa.nl_pid = getpid();
60 sa.nl_groups = 1 << 0;
61 fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
62 xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
63 close_on_exec_on(fd);
64
65 // Without a sufficiently big RCVBUF, a ton of simultaneous events 56 // Without a sufficiently big RCVBUF, a ton of simultaneous events
66 // can trigger ENOBUFS on read, which is unrecoverable. 57 // can trigger ENOBUFS on read, which is unrecoverable.
67 // Reproducer: 58 // Reproducer:
68 // uevent mdev & 59 // uevent mdev &
69 // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' 60 // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
70 // 61 fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, RCVBUF);
71 // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
72 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, RCVBUF);
73 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, RCVBUF);
74 if (0) {
75 int z;
76 socklen_t zl = sizeof(z);
77 getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &z, &zl);
78 bb_error_msg("SO_RCVBUF:%d", z);
79 }
80 62
81 for (;;) { 63 for (;;) {
82 char *netbuf; 64 char *netbuf;
@@ -93,12 +75,12 @@ int uevent_main(int argc UNUSED_PARAM, char **argv)
93 MAP_PRIVATE | MAP_ANON, 75 MAP_PRIVATE | MAP_ANON,
94 /* ignored: */ -1, 0); 76 /* ignored: */ -1, 0);
95 if (netbuf == MAP_FAILED) 77 if (netbuf == MAP_FAILED)
96 bb_perror_msg_and_die("mmap"); 78 bb_simple_perror_msg_and_die("mmap");
97 79
98 // Here we block, possibly for a very long time 80 // Here we block, possibly for a very long time
99 len = safe_read(fd, netbuf, BUFFER_SIZE - 1); 81 len = safe_read(fd, netbuf, BUFFER_SIZE - 1);
100 if (len < 0) 82 if (len < 0)
101 bb_perror_msg_and_die("read"); 83 bb_simple_perror_msg_and_die("read");
102 end = netbuf + len; 84 end = netbuf + len;
103 *end = '\0'; 85 *end = '\0';
104 86
@@ -118,14 +100,15 @@ int uevent_main(int argc UNUSED_PARAM, char **argv)
118 } 100 }
119 env[idx] = NULL; 101 env[idx] = NULL;
120 102
121 idx = 0; 103 if (argv[0]) {
122 while (env[idx]) 104 idx = 0;
123 putenv(env[idx++]); 105 while (env[idx])
124 if (argv[0]) 106 putenv(env[idx++]);
125 spawn_and_wait(argv); 107 spawn_and_wait(argv);
126 idx = 0; 108 idx = 0;
127 while (env[idx]) 109 while (env[idx])
128 bb_unsetenv(env[idx++]); 110 bb_unsetenv(env[idx++]);
111 }
129 munmap(netbuf, BUFFER_SIZE); 112 munmap(netbuf, BUFFER_SIZE);
130 } 113 }
131 114