remove mknod() logic and rely on 'devtmpfs'

This commit is contained in:
Kay Sievers 2012-01-01 04:21:15 +01:00
parent eed0832780
commit 220893b3cb
28 changed files with 169 additions and 613 deletions

6
NEWS
View file

@ -1,5 +1,9 @@
udev 175
========
The 'devtmpfs' filesystem is required now, udev will not create or delete
device nodes anymore, it only adjusts permissions and ownership of device
nodes and maintains additional symlinks.
A writable /run directory (tmpfs) is required now for a fully functional
udev.
@ -26,7 +30,7 @@ All built-in tools can be listed and tested with 'udevadm test-builtin'.
The 'udevadm control --reload-rules' option has been renamed to '--reload'.
It reloads the kernel module configuration.
The systemd socket files use PassCred=yes, which requires systemd
The systemd socket files use PassCredentials=yes, which requires systemd
version 38.
The udev build system only creates a .xz tarball now.

View file

@ -9,10 +9,10 @@ ENV{DEVTYPE}!="disk", GOTO="cdrom_end"
KERNEL=="sr[0-9]*", ENV{ID_CDROM}="1"
# media eject button pressed
ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $tempnode", GOTO="cdrom_end"
ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $devnode", GOTO="cdrom_end"
# import device and media properties and lock tray to
# enable the receiving of media eject button events
IMPORT{program}="cdrom_id --lock-media $tempnode"
IMPORT{program}="cdrom_id --lock-media $devnode"
LABEL="cdrom_end"

View file

@ -5,7 +5,7 @@ SUBSYSTEM!="block", GOTO="persistent_storage_edd_end"
KERNEL!="sd*|hd*|cciss*", GOTO="persistent_storage_edd_end"
# BIOS Enhanced Disk Device
ENV{DEVTYPE}=="disk", IMPORT{program}="edd_id --export $tempnode"
ENV{DEVTYPE}=="disk", IMPORT{program}="edd_id --export $devnode"
ENV{DEVTYPE}=="disk", ENV{ID_EDD}=="?*", SYMLINK+="disk/by-id/edd-$env{ID_EDD}"
ENV{DEVTYPE}=="partition", ENV{ID_EDD}=="?*", SYMLINK+="disk/by-id/edd-$env{ID_EDD}-part%n"

View file

@ -2,7 +2,7 @@
ACTION!="add", GOTO="mtd_probe_end"
KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $tempnode"
KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $devnode"
KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", IMPORT{builtin}="kmod load sm_ftl"
LABEL="mtd_probe_end"

View file

@ -4,7 +4,7 @@ ACTION=="remove", GOTO="persistent_v4l_end"
SUBSYSTEM!="video4linux", GOTO="persistent_v4l_end"
ENV{MAJOR}=="", GOTO="persistent_v4l_end"
IMPORT{program}="v4l_id $tempnode"
IMPORT{program}="v4l_id $devnode"
SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
KERNEL=="video*", ENV{ID_SERIAL}=="?*", SYMLINK+="v4l/by-id/$env{ID_BUS}-$env{ID_SERIAL}-video-index$attr{index}"

View file

@ -78,7 +78,6 @@ int udev_device_tag_index(struct udev_device *dev, struct udev_device *dev_old,
static bool device_has_info(struct udev_device *udev_device)
{
struct udev *udev = udev_device_get_udev(udev_device);
struct udev_list_entry *list_entry;
if (udev_device_get_devlinks_list_entry(udev_device) != NULL)
@ -90,12 +89,6 @@ static bool device_has_info(struct udev_device *udev_device)
return true;
if (udev_device_get_tags_list_entry(udev_device) != NULL)
return true;
if (udev_device_get_devnode(udev_device) != NULL && udev_device_get_knodename(udev_device) != NULL) {
size_t devlen = strlen(udev_get_dev_path(udev))+1;
if (strcmp(&udev_device_get_devnode(udev_device)[devlen], udev_device_get_knodename(udev_device)) != 0)
return true;
}
if (udev_device_get_watch_handle(udev_device) >= 0)
return true;
return false;
@ -142,20 +135,22 @@ int udev_device_update_db(struct udev_device *udev_device)
fchmod(fileno(f), 01644);
if (has_info) {
size_t devlen = strlen(udev_get_dev_path(udev))+1;
struct udev_list_entry *list_entry;
if (udev_device_get_devnode(udev_device) != NULL) {
fprintf(f, "N:%s\n", &udev_device_get_devnode(udev_device)[devlen]);
if (major(udev_device_get_devnum(udev_device)) > 0) {
size_t devlen = strlen(udev_get_dev_path(udev))+1;
udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(udev_device))
fprintf(f, "S:%s\n", &udev_list_entry_get_name(list_entry)[devlen]);
if (udev_device_get_devlink_priority(udev_device) != 0)
fprintf(f, "L:%i\n", udev_device_get_devlink_priority(udev_device));
if (udev_device_get_watch_handle(udev_device) >= 0)
fprintf(f, "W:%i\n", udev_device_get_watch_handle(udev_device));
}
if (udev_device_get_devlink_priority(udev_device) != 0)
fprintf(f, "L:%i\n", udev_device_get_devlink_priority(udev_device));
if (udev_device_get_watch_handle(udev_device) >= 0)
fprintf(f, "W:%i\n", udev_device_get_watch_handle(udev_device));
if (udev_device_get_usec_initialized(udev_device) > 0)
fprintf(f, "I:%llu\n", udev_device_get_usec_initialized(udev_device));
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) {
if (!udev_list_entry_get_num(list_entry))
continue;
@ -163,6 +158,7 @@ int udev_device_update_db(struct udev_device *udev_device)
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
}
udev_list_entry_foreach(list_entry, udev_device_get_tags_list_entry(udev_device))
fprintf(f, "G:%s\n", udev_list_entry_get_name(list_entry));
}

View file

@ -57,7 +57,6 @@ struct udev_device {
char *driver;
char *action;
char *devpath_old;
char *knodename;
char *id_filename;
char **envp;
char *monitor_buf;
@ -161,23 +160,6 @@ static int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
return 0;
}
const char *udev_device_get_knodename(struct udev_device *udev_device)
{
return udev_device->knodename;
}
static int udev_device_set_knodename(struct udev_device *udev_device, const char *knodename)
{
free(udev_device->knodename);
udev_device->knodename = strdup(knodename);
if (udev_device->knodename == NULL)
return -ENOMEM;
/* do not overwrite the udev property with the kernel property */
if (udev_device->devnode == NULL)
udev_device_add_property(udev_device, "DEVNAME", udev_device->knodename);
return 0;
}
const char *udev_device_get_devpath_old(struct udev_device *udev_device)
{
return udev_device->devpath_old;
@ -381,10 +363,7 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device,
} else if (strncmp(property, "DEVTYPE=", 8) == 0) {
udev_device_set_devtype(udev_device, &property[8]);
} else if (strncmp(property, "DEVNAME=", 8) == 0) {
if (property[8] == '/')
udev_device_set_devnode(udev_device, &property[8]);
else
udev_device_set_knodename(udev_device, &property[8]);
udev_device_set_devnode(udev_device, &property[8]);
} else if (strncmp(property, "DEVLINKS=", 9) == 0) {
char devlinks[UTIL_PATH_SIZE];
char *slink;
@ -516,10 +495,6 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
line[len-1] = '\0';
val = &line[2];
switch(line[0]) {
case 'N':
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL);
udev_device_set_devnode(udev_device, filename);
break;
case 'S':
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL);
udev_device_add_devlink(udev_device, filename, 0);
@ -582,7 +557,7 @@ int udev_device_read_uevent_file(struct udev_device *udev_device)
else if (strncmp(line, "IFINDEX=", 8) == 0)
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]);
udev_device_set_devnode(udev_device, &line[8]);
else if (strncmp(line, "DEVMODE=", 8) == 0)
udev_device->devnode_mode = strtoul(&line[8], NULL, 8);
@ -1073,7 +1048,6 @@ UDEV_EXPORT void udev_device_unref(struct udev_device *udev_device)
free(udev_device->action);
free(udev_device->driver);
free(udev_device->devpath_old);
free(udev_device->knodename);
free(udev_device->id_filename);
free(udev_device->envp);
free(udev_device->monitor_buf);
@ -1152,21 +1126,10 @@ UDEV_EXPORT const char *udev_device_get_devnode(struct udev_device *udev_device)
{
if (udev_device == NULL)
return NULL;
if (!udev_device->info_loaded) {
udev_device_read_uevent_file(udev_device);
udev_device_read_db(udev_device, NULL);
}
/* we might get called before we handled an event and have a db, use the kernel-provided name */
if (udev_device->devnode == NULL && udev_device_get_knodename(udev_device) != NULL) {
char filename[UTIL_NAME_SIZE];
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/",
udev_device_get_knodename(udev_device), NULL);
udev_device_set_devnode(udev_device, filename);
if (udev_device->devnode != NULL)
return udev_device->devnode;
}
if (!udev_device->info_loaded)
udev_device_read_uevent_file(udev_device);
return udev_device->devnode;
}
@ -1522,7 +1485,12 @@ int udev_device_set_syspath(struct udev_device *udev_device, const char *syspath
int udev_device_set_devnode(struct udev_device *udev_device, const char *devnode)
{
free(udev_device->devnode);
udev_device->devnode = strdup(devnode);
if (devnode[0] != '/') {
if (asprintf(&udev_device->devnode, "%s/%s", udev_get_dev_path(udev_device->udev), devnode) < 0)
udev_device->devnode = NULL;
} else {
udev_device->devnode = strdup(devnode);
}
if (udev_device->devnode == NULL)
return -ENOMEM;
udev_device_add_property(udev_device, "DEVNAME", udev_device->devnode);

View file

@ -83,7 +83,6 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile);
int udev_device_read_uevent_file(struct udev_device *udev_device);
int udev_device_set_action(struct udev_device *udev_device, const char *action);
const char *udev_device_get_devpath_old(struct udev_device *udev_device);
const char *udev_device_get_knodename(struct udev_device *udev_device);
const char *udev_device_get_id_filename(struct udev_device *udev_device);
void udev_device_set_is_initialized(struct udev_device *udev_device);
int udev_device_add_tag(struct udev_device *udev_device, const char *tag);
@ -187,7 +186,6 @@ uint64_t util_string_bloom64(const char *str);
int util_create_path(struct udev *udev, const char *path);
int util_create_path_selinux(struct udev *udev, const char *path);
int util_delete_path(struct udev *udev, const char *path);
int util_unlink_secure(struct udev *udev, const char *filename);
uid_t util_lookup_user(struct udev *udev, const char *user);
gid_t util_lookup_group(struct udev *udev, const char *group);
int util_resolve_subsys_kernel(struct udev *udev, const char *string,

View file

@ -113,23 +113,6 @@ int util_delete_path(struct udev *udev, const char *path)
return err;
}
/* Reset permissions on the device node, before unlinking it to make sure,
* that permissions of possible hard links will be removed too.
*/
int util_unlink_secure(struct udev *udev, const char *filename)
{
int err;
chown(filename, 0, 0);
chmod(filename, 0000);
err = unlink(filename);
if (errno == ENOENT)
err = 0;
if (err)
err(udev, "unlink(%s) failed: %m\n", filename);
return err;
}
uid_t util_lookup_user(struct udev *udev, const char *user)
{
char *endptr;

View file

@ -223,6 +223,10 @@ UDEV_EXPORT struct udev *udev_new(void)
set_value(&udev->run_path, val);
continue;
}
if (strcmp(key, "udev_sys") == 0) {
set_value(&udev->sys_path, val);
continue;
}
if (strcmp(key, "udev_rules") == 0) {
set_value(&udev->rules_path[0], val);
udev->rules_path_count = 1;
@ -237,18 +241,6 @@ UDEV_EXPORT struct udev *udev_new(void)
if (env != NULL)
udev_set_log_priority(udev, util_log_priority(env));
env = getenv("UDEV_ROOT");
if (env != NULL) {
set_value(&udev->dev_path, env);
udev_add_property(udev, "UDEV_ROOT", udev->dev_path);
}
env = getenv("SYSFS_PATH");
if (env != NULL) {
set_value(&udev->sys_path, env);
udev_add_property(udev, "SYSFS_PATH", udev->sys_path);
}
/* set defaults */
if (udev->dev_path == NULL)
if (set_value(&udev->dev_path, "/dev") == NULL)
@ -401,8 +393,8 @@ int udev_get_rules_path(struct udev *udev, char **path[], unsigned long long *st
* @udev: udev library context
*
* Retrieve the sysfs mount point. The default is "/sys". For
* testing purposes, it can be overridden with the environment
* variable SYSFS_PATH.
* testing purposes, it can be overridden with udev_sys=
* in the udev configuration file.
*
* Returns: the sys mount point
**/

View file

@ -5,7 +5,7 @@
ACTION=="remove", GOTO="persistent_storage_tape_end"
# type 8 devices are "Medium Changers"
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $tempnode", \
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \
SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL}"
SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end"

View file

@ -27,20 +27,20 @@ KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLIN
KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n"
# ATA devices with their own "ata" kernel subsystem
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="ata", IMPORT{program}="ata_id --export $tempnode"
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="ata", IMPORT{program}="ata_id --export $devnode"
# ATA devices using the "scsi" subsystem
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $tempnode"
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $devnode"
# ATA/ATAPI devices (SPC-3 or later) using the "scsi" subsystem
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", ATTRS{scsi_level}=="[6-9]*", IMPORT{program}="ata_id --export $tempnode"
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", ATTRS{scsi_level}=="[6-9]*", IMPORT{program}="ata_id --export $devnode"
# Run ata_id on non-removable USB Mass Storage (SATA/PATA disks in enclosures)
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", ATTR{removable}=="0", SUBSYSTEMS=="usb", IMPORT{program}="ata_id --export $tempnode"
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", ATTR{removable}=="0", SUBSYSTEMS=="usb", IMPORT{program}="ata_id --export $devnode"
# Otherwise fall back to using usb_id for USB devices
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
# scsi devices
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $tempnode", ENV{ID_BUS}="scsi"
KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $tempnode", ENV{ID_BUS}="cciss"
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="scsi"
KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="cciss"
KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n"
@ -49,7 +49,7 @@ KERNEL=="sd*[!0-9]|sr*", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394
KERNEL=="sd*[0-9]", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}-part%n"
# scsi compat links for ATA devices
KERNEL=="sd*[!0-9]", ENV{ID_BUS}=="ata", PROGRAM="scsi_id --whitelisted --replace-whitespace -p0x80 -d$tempnode", RESULT=="?*", ENV{ID_SCSI_COMPAT}="$result", SYMLINK+="disk/by-id/scsi-$env{ID_SCSI_COMPAT}"
KERNEL=="sd*[!0-9]", ENV{ID_BUS}=="ata", PROGRAM="scsi_id --whitelisted --replace-whitespace -p0x80 -d $devnode", RESULT=="?*", ENV{ID_SCSI_COMPAT}="$result", SYMLINK+="disk/by-id/scsi-$env{ID_SCSI_COMPAT}"
KERNEL=="sd*[0-9]", ENV{ID_SCSI_COMPAT}=="?*", SYMLINK+="disk/by-id/scsi-$env{ID_SCSI_COMPAT}-part%n"
KERNEL=="mmcblk[0-9]", SUBSYSTEMS=="mmc", ATTRS{name}=="?*", ATTRS{serial}=="?*", ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}"

View file

@ -1,3 +1,3 @@
DEVNAME=ttyACM0
MAJOR=166
MINOR=0
DEVNAME=ttyACM0

View file

@ -1,3 +1,4 @@
MAJOR=8
MINOR=5
DEVTYPE=partition
DEVNAME=sda5

View file

@ -1,3 +1,4 @@
MAJOR=7
MINOR=0
DEVTYPE=disk
DEVNAME=fake/blockdev0

View file

@ -1,2 +1,4 @@
MAJOR=4095
MINOR=1
DEVNAME=misc-fake1

View file

@ -1,2 +1,3 @@
MAJOR=4095
MINOR=89999
DEVNAME=misc-fake89999

View file

@ -1,2 +1,3 @@
MAJOR=5
MINOR=1
DEVNAME=console

View file

@ -1,2 +1,3 @@
MAJOR=4
MINOR=0
DEVNAME=tty0

View file

@ -1,2 +1,3 @@
MAJOR=4
MINOR=33
DEVNAME=tty33

File diff suppressed because it is too large Load diff

View file

@ -43,7 +43,6 @@ int main(int argc, char *argv[])
char syspath[UTIL_PATH_SIZE];
const char *devpath;
const char *action;
const char *subsystem;
sigset_t mask, sigmask_orig;
int err = -EINVAL;
@ -55,12 +54,15 @@ int main(int argc, char *argv[])
sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
action = getenv("ACTION");
devpath = getenv("DEVPATH");
subsystem = getenv("SUBSYSTEM");
action = argv[1];
if (action == NULL) {
err(udev, "action missing\n");
goto out;
}
if (action == NULL || subsystem == NULL || devpath == NULL) {
err(udev, "action, subsystem or devpath missing\n");
devpath = argv[2];
if (devpath == NULL) {
err(udev, "devpath missing\n");
goto out;
}
@ -73,10 +75,6 @@ int main(int argc, char *argv[])
goto out;
}
/* skip reading of db, but read kernel parameters */
udev_device_set_info_loaded(dev);
udev_device_read_uevent_file(dev);
udev_device_set_action(dev, action);
event = udev_event_new(dev);
@ -88,6 +86,24 @@ int main(int argc, char *argv[])
goto out;
}
/* do what devtmpfs usually provides us */
if (udev_device_get_devnode(dev) != NULL) {
mode_t mode;
if (strcmp(udev_device_get_subsystem(dev), "block") == 0)
mode |= S_IFBLK;
else
mode |= S_IFCHR;
if (strcmp(action, "remove") != 0) {
util_create_path(udev, udev_device_get_devnode(dev));
mknod(udev_device_get_devnode(dev), mode, udev_device_get_devnum(dev));
} else {
unlink(udev_device_get_devnode(dev));
util_delete_path(udev, udev_device_get_devnode(dev));
}
}
err = udev_event_execute_rules(event, rules, &sigmask_orig);
if (err == 0)
udev_event_execute_run(event, NULL);

View file

@ -59,7 +59,6 @@ void udev_event_unref(struct udev_event *event)
if (event == NULL)
return;
udev_list_cleanup(&event->run_list);
free(event->tmp_node);
free(event->program_result);
free(event->name);
dbg(event->udev, "free event %p\n", event);
@ -71,7 +70,7 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
struct udev_device *dev = event->dev;
enum subst_type {
SUBST_UNKNOWN,
SUBST_TEMP_NODE,
SUBST_DEVNODE,
SUBST_ATTR,
SUBST_ENV,
SUBST_KERNEL,
@ -93,7 +92,8 @@ size_t udev_event_apply_format(struct udev_event *event, const char *src, char *
char fmt;
enum subst_type type;
} map[] = {
{ .name = "tempnode", .fmt = 'N', .type = SUBST_TEMP_NODE },
{ .name = "devnode", .fmt = 'N', .type = SUBST_DEVNODE },
{ .name = "tempnode", .fmt = 'N', .type = SUBST_DEVNODE },
{ .name = "attr", .fmt = 's', .type = SUBST_ATTR },
{ .name = "sysfs", .fmt = 's', .type = SUBST_ATTR },
{ .name = "env", .fmt = 'E', .type = SUBST_ENV },
@ -332,7 +332,7 @@ subst:
dev_parent = udev_device_get_parent(event->dev);
if (dev_parent == NULL)
break;
devnode = udev_device_get_devnode(dev_parent);
devnode = udev_device_get_devnode(dev_parent);
if (devnode != NULL) {
size_t devlen = strlen(udev_get_dev_path(event->udev))+1;
@ -342,56 +342,10 @@ subst:
}
break;
}
case SUBST_TEMP_NODE: {
dev_t devnum;
struct stat statbuf;
char filename[UTIL_PATH_SIZE];
const char *devtype;
if (event->tmp_node != NULL) {
l = util_strpcpy(&s, l, event->tmp_node);
dbg(event->udev, "tempnode: return earlier created one\n");
break;
}
devnum = udev_device_get_devnum(dev);
if (major(devnum) == 0)
break;
/* lookup kernel provided node */
if (udev_device_get_knodename(dev) != NULL) {
util_strscpyl(filename, sizeof(filename),
udev_get_dev_path(event->udev), "/", udev_device_get_knodename(dev), NULL);
if (stat(filename, &statbuf) == 0 && statbuf.st_rdev == devnum) {
l = util_strpcpy(&s, l, filename);
dbg(event->udev, "tempnode: return kernel node\n");
break;
}
}
/* lookup /dev/{char,block}/<maj>:<min> */
if (strcmp(udev_device_get_subsystem(dev), "block") == 0)
devtype = "block";
else
devtype = "char";
snprintf(filename, sizeof(filename), "%s/%s/%u:%u",
udev_get_dev_path(event->udev), devtype,
major(udev_device_get_devnum(dev)),
minor(udev_device_get_devnum(dev)));
if (stat(filename, &statbuf) == 0 && statbuf.st_rdev == devnum) {
l = util_strpcpy(&s, l, filename);
dbg(event->udev, "tempnode: return maj:min node\n");
break;
}
/* create temporary node */
dbg(event->udev, "tempnode: create temp node\n");
asprintf(&event->tmp_node, "%s/.tmp-%s-%u:%u",
udev_get_dev_path(event->udev), devtype,
major(udev_device_get_devnum(dev)),
minor(udev_device_get_devnum(dev)));
if (event->tmp_node == NULL)
break;
udev_node_mknod(dev, event->tmp_node, 0600, 0, 0);
l = util_strpcpy(&s, l, event->tmp_node);
case SUBST_DEVNODE:
if (udev_device_get_devnode(dev) != NULL)
l = util_strpcpy(&s, l, udev_device_get_devnode(dev));
break;
}
case SUBST_NAME:
if (event->name != NULL) {
l = util_strpcpy(&s, l, event->name);
@ -975,44 +929,6 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules,
}
if (major(udev_device_get_devnum(dev)) != 0) {
char filename[UTIL_PATH_SIZE];
if (event->tmp_node != NULL) {
info(event->udev, "cleanup temporary device node\n");
util_unlink_secure(event->udev, event->tmp_node);
free(event->tmp_node);
event->tmp_node = NULL;
}
/* no rule, use kernel provided name */
if (event->name == NULL) {
if (udev_device_get_knodename(dev) != NULL) {
event->name = strdup(udev_device_get_knodename(dev));
info(event->udev, "no node name set, will use kernel supplied name '%s'\n", event->name);
} else {
event->name = strdup(udev_device_get_sysname(event->dev));
info(event->udev, "no node name set, will use device name '%s'\n", event->name);
}
}
if (event->name == NULL || event->name[0] == '\0') {
udev_device_delete_db(dev);
udev_device_tag_index(dev, NULL, false);
udev_device_unref(event->dev_db);
err = -ENOMEM;
err(event->udev, "no node name, something went wrong, ignoring\n");
goto out;
}
if (udev_device_get_knodename(dev) != NULL && strcmp(udev_device_get_knodename(dev), event->name) != 0)
err(event->udev, "kernel-provided name '%s' and NAME= '%s' disagree, "
"please use SYMLINK+= or change the kernel to provide the proper name\n",
udev_device_get_knodename(dev), event->name);
/* set device node name */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", event->name, NULL);
udev_device_set_devnode(dev, filename);
/* remove/update possible left-over symlinks from old database entry */
if (event->dev_db != NULL)
udev_node_update_old_links(dev, event->dev_db);
@ -1030,10 +946,6 @@ 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);
}

View file

@ -33,90 +33,6 @@
#define TMP_FILE_EXT ".udev-tmp"
int udev_node_mknod(struct udev_device *dev, const char *file, mode_t mode, uid_t uid, gid_t gid)
{
struct udev *udev = udev_device_get_udev(dev);
dev_t devnum = udev_device_get_devnum(dev);
struct stat stats;
int err = 0;
if (strcmp(udev_device_get_subsystem(dev), "block") == 0)
mode |= S_IFBLK;
else
mode |= S_IFCHR;
if (file == NULL)
file = udev_device_get_devnode(dev);
if (lstat(file, &stats) == 0) {
if (((stats.st_mode & S_IFMT) == (mode & S_IFMT)) && (stats.st_rdev == devnum)) {
info(udev, "preserve file '%s', because it has correct dev_t\n", file);
if ((stats.st_mode & 0777) != (mode & 0777) || stats.st_uid != uid || stats.st_gid != gid) {
/* preserve 'sticky' bit, if already set */
mode |= stats.st_mode & 01000;
info(udev, "set permissions %s, %#o, uid=%u, gid=%u\n", file, mode, uid, gid);
chmod(file, mode);
chown(file, uid, gid);
} else {
info(udev, "preserve permissions %s, %#o, uid=%u, gid=%u\n", file, mode, uid, gid);
}
/*
* Set initial selinux file context only on add events.
* We set the proper context on bootup (triger) or for newly
* added devices, but we don't change it later, in case
* something else has set a custom context in the meantime.
*/
if (strcmp(udev_device_get_action(dev), "add") == 0)
udev_selinux_lsetfilecon(udev, file, mode);
/* always update timestamp when we re-use the node, like on media change events */
utimensat(AT_FDCWD, file, NULL, 0);
} else {
char file_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)];
info(udev, "atomically replace existing file '%s'\n", file);
util_strscpyl(file_tmp, sizeof(file_tmp), file, TMP_FILE_EXT, NULL);
unlink(file_tmp);
udev_selinux_setfscreatecon(udev, file_tmp, mode);
err = mknod(file_tmp, mode, devnum);
udev_selinux_resetfscreatecon(udev);
if (err != 0) {
err(udev, "mknod '%s' %u:%u %#o failed: %m\n",
file_tmp, major(devnum), minor(devnum), mode);
goto exit;
}
err = rename(file_tmp, file);
if (err != 0) {
err(udev, "rename '%s' '%s' failed: %m\n", file_tmp, file);
unlink(file_tmp);
goto exit;
}
info(udev, "set permissions '%s' %#o uid=%u gid=%u\n", file, mode, uid, gid);
chmod(file, mode);
chown(file, uid, gid);
}
} else {
info(udev, "mknod '%s' %u:%u %#o\n", file, major(devnum), minor(devnum), mode);
do {
err = util_create_path_selinux(udev, file);
if (err != 0 && err != -ENOENT)
break;
udev_selinux_setfscreatecon(udev, file, mode);
err = mknod(file, mode, devnum);
if (err != 0)
err = -errno;
udev_selinux_resetfscreatecon(udev);
} while (err == -ENOENT);
if (err != 0 && err != -EEXIST)
err(udev, "mknod '%s' %u:%u %#o' failed: %m\n", file, major(devnum), minor(devnum), mode);
info(udev, "set permissions '%s' %#o uid=%u gid=%u\n", file, mode, uid, gid);
chmod(file, mode);
chown(file, uid, gid);
}
exit:
return err;
}
static int node_symlink(struct udev *udev, const char *node, const char *slink)
{
struct stat stats;
@ -362,6 +278,55 @@ void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev
}
}
static int node_fixup(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid)
{
struct udev *udev = udev_device_get_udev(dev);
const char *devnode = udev_device_get_devnode(dev);
dev_t devnum = udev_device_get_devnum(dev);
struct stat stats;
int err = 0;
if (strcmp(udev_device_get_subsystem(dev), "block") == 0)
mode |= S_IFBLK;
else
mode |= S_IFCHR;
if (lstat(devnode, &stats) != 0) {
err = -errno;
info(udev, "can not stat() node '%s' (%m)\n", devnode);
goto out;
}
if (((stats.st_mode & S_IFMT) != (mode & S_IFMT)) || (stats.st_rdev != devnum)) {
err = -EEXIST;
info(udev, "found node '%s' with non-matching devnum %s, skip handling\n",
udev_device_get_devnode(dev), udev_device_get_id_filename(dev));
goto out;
}
if ((stats.st_mode & 0777) != (mode & 0777) || stats.st_uid != uid || stats.st_gid != gid) {
info(udev, "set permissions %s, %#o, uid=%u, gid=%u\n", devnode, mode, uid, gid);
chmod(devnode, mode);
chown(devnode, uid, gid);
} else {
info(udev, "preserve permissions %s, %#o, uid=%u, gid=%u\n", devnode, mode, uid, gid);
}
/*
* Set initial selinux file context only on add events.
* We set the proper context on bootup (triger) or for newly
* added devices, but we don't change it later, in case
* something else has set a custom context in the meantime.
*/
if (strcmp(udev_device_get_action(dev), "add") == 0)
udev_selinux_lsetfilecon(udev, devnode, mode);
/* always update timestamp when we re-use the node, like on media change events */
utimensat(AT_FDCWD, devnode, NULL, 0);
out:
return err;
}
int udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid)
{
struct udev *udev = udev_device_get_udev(dev);
@ -369,15 +334,12 @@ int udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid)
struct udev_list_entry *list_entry;
int err = 0;
info(udev, "creating device node '%s', devnum=%d:%d, mode=%#o, uid=%d, gid=%d\n",
udev_device_get_devnode(dev),
major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)),
mode, uid, gid);
info(udev, "handling device node '%s', devnum=%s, mode=%#o, uid=%d, gid=%d\n",
udev_device_get_devnode(dev), udev_device_get_id_filename(dev), mode, uid, gid);
if (udev_node_mknod(dev, NULL, mode, uid, gid) != 0) {
err = -1;
err = node_fixup(dev, mode, uid, gid);
if (err < 0)
goto exit;
}
/* always add /dev/{block,char}/$major:$minor */
snprintf(filename, sizeof(filename), "%s/%s/%u:%u",
@ -412,38 +374,6 @@ int udev_node_remove(struct udev_device *dev)
udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev))
link_update(dev, udev_list_entry_get_name(list_entry), 0);
devnode = udev_device_get_devnode(dev);
if (devnode == NULL)
goto out;
if (stat(devnode, &stats) == 0) {
if (stats.st_rdev != udev_device_get_devnum(dev)) {
info(udev, "device node '%s' points to a different device, skip removal\n", devnode);
err = -1;
goto out;
}
if (stats.st_mode & 01000) {
info(udev, "device node '%s' has sticky bit set, skip removal\n", devnode);
goto out;
}
} else {
info(udev, "device node '%s' not found\n", devnode);
}
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 */
info(udev, "keeping device node of existing device'%s'\n", devnode);
udev_device_unref(dev_check);
goto out;
}
info(udev, "removing device node '%s'\n", devnode);
err = util_unlink_secure(udev, devnode);
if (err == 0)
util_delete_path(udev, devnode);
/* remove /dev/{block,char}/$major:$minor */
snprintf(filename, sizeof(filename), "%s/%s/%u:%u",
udev_get_dev_path(udev),

View file

@ -2504,9 +2504,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
&rules->buf[rule->rule.filename_off],
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];
char *value = &rules->buf[cur->key.value_off];
@ -2729,8 +2726,6 @@ void udev_rules_apply_static_dev_perms(struct udev_rules *rules)
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);

View file

@ -32,7 +32,6 @@ struct udev_event {
struct udev_device *dev_parent;
struct udev_device *dev_db;
char *name;
char *tmp_node;
char *program_result;
mode_t mode;
uid_t uid;
@ -51,7 +50,6 @@ struct udev_event {
bool owner_final;
bool mode_set;
bool mode_final;
bool static_node;
bool name_final;
bool devlink_final;
bool run_final;
@ -91,7 +89,6 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev);
struct udev_device *udev_watch_lookup(struct udev *udev, int wd);
/* udev-node.c */
int udev_node_mknod(struct udev_device *dev, const char *file, mode_t mode, uid_t uid, gid_t gid);
int udev_node_add(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid);
int udev_node_remove(struct udev_device *dev);
void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old);

View file

@ -167,9 +167,8 @@
<varlistentry>
<term><option>NAME</option></term>
<listitem>
<para>Match the name of the node or network interface. It can
be used once the NAME key has been set in one of the preceding
rules.</para>
<para>Match the name of a network interface. It can be used once the
NAME key has been set in one of the preceding rules.</para>
</listitem>
</varlistentry>
@ -319,17 +318,8 @@
<varlistentry>
<term><option>NAME</option></term>
<listitem>
<para>What a network interface should be named.</para>
<para>Also, as a temporary workaround, this is what a device node
should be named; usually the kernel provides the defined node name or creates
and removes the node before udev even receives any event. Changing
the node name from the kernel's default creates inconsistencies
and is not supported. If the kernel and NAME specify different names,
an error is logged. udev is only expected to handle device node
permissions and to create additional symlinks, not to change
kernel-provided device node names. Instead of renaming a device node,
SYMLINK should be used. However, symlink names must never conflict with
device node names, as that would result in unpredictable behavior.</para>
<para>The name to use for a network interface. The name of a device node
can not be changed by udev, only additional symlinks can be created.</para>
</listitem>
</varlistentry>
@ -637,7 +627,7 @@
<varlistentry>
<term><option>$name</option></term>
<listitem>
<para>The current name of the device node. If not changed by a rule, it is the
<para>The current name of the device. If not changed by a rule, it is the
name of the kernel device.</para>
</listitem>
</varlistentry>
@ -665,10 +655,9 @@
</varlistentry>
<varlistentry>
<term><option>$tempnode</option>, <option>%N</option></term>
<term><option>$devnode</option>, <option>%N</option></term>
<listitem>
<para>The name of a temporary device node created to provide access to
the device from a external program before the real node is created.</para>
<para>The name of the device node.</para>
</listitem>
</varlistentry>

View file

@ -863,11 +863,10 @@ 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 = 01600|S_IFCHR;
mode = S_IFCHR;
else if (type == 'b')
mode = 01600|S_IFBLK;
mode = S_IFBLK;
else
continue;