summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--udev/udev-event.c4
-rw-r--r--udev/udev-node.c5
-rw-r--r--udev/udev-rules.c14
-rw-r--r--udev/udev.h1
-rw-r--r--udev/udevd.c5
5 files changed, 23 insertions, 6 deletions
diff --git a/udev/udev-event.c b/udev/udev-event.c
index 823768a3e2..391fce81c3 100644
--- a/udev/udev-event.c
+++ b/udev/udev-event.c
@@ -1030,6 +1030,10 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules,
}
}
+ /* set sticky bit, so we do not remove the node on module unload */
+ if (event->static_node)
+ event->mode |= 01000;
+
err = udev_node_add(dev, event->mode, event->uid, event->gid);
}
diff --git a/udev/udev-node.c b/udev/udev-node.c
index dc7d9c365a..6fbe250b85 100644
--- a/udev/udev-node.c
+++ b/udev/udev-node.c
@@ -425,6 +425,11 @@ int udev_node_remove(struct udev_device *dev)
goto out;
}
+ if (stats.st_mode & 01000) {
+ info(udev, "device node '%s' has sticky bit set, skip removal\n", devnode);
+ goto out;
+ }
+
dev_check = udev_device_new_from_syspath(udev, udev_device_get_syspath(dev));
if (dev_check != NULL) {
/* do not remove device node if the same sys-device is re-created in the meantime */
diff --git a/udev/udev-rules.c b/udev/udev-rules.c
index 742d88b3d5..6bf2726e1e 100644
--- a/udev/udev-rules.c
+++ b/udev/udev-rules.c
@@ -2572,6 +2572,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
rule->rule.filename_line);
break;
case TK_A_STATIC_NODE:
+ event->static_node = true;
break;
case TK_A_ENV: {
const char *name = &rules->buf[cur->key.attr_off];
@@ -2793,10 +2794,15 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
goto next;
if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode))
goto next;
-
- if (mode == 0 && gid > 0)
- mode = 0660;
- if (mode != (stats.st_mode & 0777)) {
+ if (mode == 0) {
+ if (gid > 0)
+ mode = 0660;
+ else
+ mode = 0600;
+ }
+ /* set sticky bit, so we do not remove the node on module unload */
+ mode |= 01000;
+ if (mode != (stats.st_mode & 01777)) {
chmod(filename, mode);
info(rules->udev, "chmod '%s' %#o\n", filename, mode);
}
diff --git a/udev/udev.h b/udev/udev.h
index 1f9650fc42..5aaf117a9c 100644
--- a/udev/udev.h
+++ b/udev/udev.h
@@ -53,6 +53,7 @@ struct udev_event {
bool owner_final;
bool mode_set;
bool mode_final;
+ bool static_node;
bool name_final;
bool devlink_final;
bool run_final;
diff --git a/udev/udevd.c b/udev/udevd.c
index 1220deaaa6..f1a31e7afb 100644
--- a/udev/udevd.c
+++ b/udev/udevd.c
@@ -889,10 +889,11 @@ static void static_dev_create_from_modules(struct udev *udev)
if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3)
continue;
+ /* set sticky bit, so we do not remove the node on module unload */
if (type == 'c')
- mode = 0600 | S_IFCHR;
+ mode = 01600|S_IFCHR;
else if (type == 'b')
- mode = 0600 | S_IFBLK;
+ mode = 01600|S_IFBLK;
else
continue;