diff --git a/TODO b/TODO index 7416c6f670a..2d43162095d 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,3 @@ - - support kernel-supplied DEVMODE= - - /run/udev/control socket - read settle_timout from udev.conf diff --git a/libudev/libudev-device.c b/libudev/libudev-device.c index ffde21ad57d..d57a9eb5971 100644 --- a/libudev/libudev-device.c +++ b/libudev/libudev-device.c @@ -51,6 +51,7 @@ struct udev_device { char *sysname; const char *sysnum; char *devnode; + mode_t devnode_mode; char *subsystem; char *devtype; char *driver; @@ -199,6 +200,8 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device, udev_device_set_timeout(udev_device, strtoull(&property[8], NULL, 10)); } else if (strncmp(property, "IFINDEX=", 8) == 0) { udev_device_set_ifindex(udev_device, strtoull(&property[8], NULL, 10)); + } else if (strncmp(property, "DEVMODE=", 8) == 0) { + udev_device_set_devnode_mode(udev_device, strtoul(&property[8], NULL, 8)); } else { udev_device_add_property_from_string(udev_device, property); } @@ -343,6 +346,8 @@ int udev_device_read_uevent_file(struct udev_device *udev_device) udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10)); else if (strncmp(line, "DEVNAME=", 8) == 0) udev_device_set_knodename(udev_device, &line[8]); + else if (strncmp(line, "DEVMODE=", 8) == 0) + udev_device->devnode_mode = strtoul(&line[8], NULL, 8); udev_device_add_property_from_string(udev_device, line); } @@ -930,6 +935,13 @@ const char *udev_device_get_devnode(struct udev_device *udev_device) return udev_device->devnode; } +mode_t udev_device_get_devnode_mode(struct udev_device *udev_device) +{ + if (!udev_device->info_loaded) + udev_device_read_uevent_file(udev_device); + return udev_device->devnode_mode; +} + /** * udev_device_get_subsystem: * @udev_device: udev device @@ -1414,6 +1426,16 @@ int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode return 0; } +int udev_device_set_devnode_mode(struct udev_device *udev_device, mode_t mode) +{ + char num[32]; + + udev_device->devnode_mode = mode; + snprintf(num, sizeof(num), "%#o", mode); + udev_device_add_property(udev_device, "DEVMODE", num); + return 0; +} + int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink, int unique) { struct udev_list_entry *list_entry; diff --git a/libudev/libudev-private.h b/libudev/libudev-private.h index 2fcfe4131c0..39b46dde315 100644 --- a/libudev/libudev-private.h +++ b/libudev/libudev-private.h @@ -69,6 +69,8 @@ struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev); /* libudev-device.c */ struct udev_device *udev_device_new(struct udev *udev); struct udev_device *udev_device_new_from_id_filename(struct udev *udev, char *id); +mode_t udev_device_get_devnode_mode(struct udev_device *udev_device); +int udev_device_set_devnode_mode(struct udev_device *udev_device, mode_t mode); int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath); int udev_device_set_subsystem(struct udev_device *udev_device, const char *subsystem); int udev_device_set_devtype(struct udev_device *udev_device, const char *devtype); diff --git a/libudev/test-libudev.c b/libudev/test-libudev.c index 4192ba14b24..966a4065078 100644 --- a/libudev/test-libudev.c +++ b/libudev/test-libudev.c @@ -221,7 +221,7 @@ static int test_enumerate_print_list(struct udev_enumerate *enumerate) static int test_monitor(struct udev *udev) { - struct udev_monitor *udev_monitor; + struct udev_monitor *udev_monitor = NULL; int fd_ep; int fd_udev = -1; struct epoll_event ep_udev, ep_stdin; diff --git a/test/udev-test.pl b/test/udev-test.pl index 4103cf0bff6..4322da5ecd2 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -1487,7 +1487,7 @@ EOF subsys => "block", devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", exp_name => "sda", - exp_perms => "0:0:0600", + exp_perms => "0:0:0440", exp_rem_error => "yes", rules => <mode = 0600; event->dev = dev; event->udev = udev_device_get_udev(dev); udev_list_init(&event->run_list); @@ -1021,9 +1020,18 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, if (event->dev_db != NULL) udev_node_update_old_links(dev, event->dev_db); - /* change default 0600 to 0660 if a group is assigned */ - if (event->mode == 0600 && event->gid > 0) - event->mode = 0660; + if (!event->mode_set) { + if (udev_device_get_devnode_mode(dev) > 0) { + /* kernel supplied value */ + event->mode = udev_device_get_devnode_mode(dev); + } else if (event->gid > 0) { + /* default 0660 if a group is assigned */ + event->mode = 0660; + } else { + /* default 0600 */ + event->mode = 0600; + } + } err = udev_node_add(dev, event->mode, event->uid, event->gid); } diff --git a/udev/udev-rules.c b/udev/udev-rules.c index 892d8f27a76..63123e083a9 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -2443,19 +2443,22 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event } case TK_A_MODE: { - char mode[UTIL_NAME_SIZE]; + char mode_str[UTIL_NAME_SIZE]; + mode_t mode; char *endptr; if (event->mode_final) break; + udev_event_apply_format(event, &rules->buf[cur->key.value_off], mode_str, sizeof(mode_str)); + mode = strtol(mode_str, &endptr, 8); + if (endptr[0] != '\0') { + err(event->udev, "ignoring invalid mode '%s'\n", mode_str); + break; + } if (cur->key.op == OP_ASSIGN_FINAL) event->mode_final = true; - udev_event_apply_format(event, &rules->buf[cur->key.value_off], mode, sizeof(mode)); - event->mode = strtol(mode, &endptr, 8); - if (endptr[0] != '\0') { - err(event->udev, "invalide mode '%s' set default mode 0600\n", mode); - event->mode = 0600; - } + event->mode_set = true; + event->mode = mode; info(event->udev, "MODE %#o %s:%u\n", event->mode, &rules->buf[rule->rule.filename_off], @@ -2489,6 +2492,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->mode_final = true; + event->mode_set = true; event->mode = cur->key.mode; info(event->udev, "MODE %#o %s:%u\n", event->mode, diff --git a/udev/udev.h b/udev/udev.h index 16a029e4860..88c32ec2032 100644 --- a/udev/udev.h +++ b/udev/udev.h @@ -49,6 +49,7 @@ struct udev_event { bool inotify_watch_final; bool group_final; bool owner_final; + bool mode_set; bool mode_final; bool name_final; bool devlink_final;