X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev-add.c;h=e1e145de8a532b3c42caa3275df166ba316f5f62;hp=09c2ac6d3efd2634ceb1eacac37791e1409c658d;hb=da767d0739c86a04a0c0326cebff6c08ffe1228c;hpb=9b28a52a0ac9b7993c932bbfe9d86dfc814be218 diff --git a/udev-add.c b/udev-add.c index 09c2ac6d3..e1e145de8 100644 --- a/udev-add.c +++ b/udev-add.c @@ -50,6 +50,8 @@ #define LOCAL_USER "$local" +#include "selinux.h" + /* * Right now the major/minor of a device is stored in a file called * "dev" in sysfs. @@ -92,6 +94,7 @@ static int create_path(char *file) break; *pos = 0x00; if (stat(p, &stats)) { + selinux_setfscreatecon(p, S_IFDIR); retval = mkdir(p, 0755); if (retval != 0) { dbg("mkdir(%s) failed with error '%s'", @@ -99,35 +102,56 @@ static int create_path(char *file) return retval; } dbg("created '%s'", p); + } else { + selinux_setfilecon(p, S_IFDIR); } *pos = '/'; } return 0; } -static int make_node(char *filename, int major, int minor, unsigned int mode, uid_t uid, gid_t gid) +static int make_node(char *file, int major, int minor, unsigned int mode, uid_t uid, gid_t gid) { - int retval; + struct stat stats; + int retval = 0; + + if (stat(file, &stats) != 0) + goto create; - retval = mknod(filename, mode, makedev(major, minor)); + /* preserve node with already correct numbers, to not change the inode number */ + if (((stats.st_mode & S_IFMT) == S_IFBLK || (stats.st_mode & S_IFMT) == S_IFCHR) && + (stats.st_rdev == makedev(major, minor))) { + dbg("preserve file '%s', cause it has correct dev_t", file); + selinux_setfilecon(file,stats.st_mode); + goto perms; + } + + if (unlink(file) != 0) + dbg("unlink(%s) failed with error '%s'", file, strerror(errno)); + else + dbg("already present file '%s' unlinked", file); + +create: + selinux_setfscreatecon(file, mode); + retval = mknod(file, mode, makedev(major, minor)); if (retval != 0) { dbg("mknod(%s, %#o, %u, %u) failed with error '%s'", - filename, mode, major, minor, strerror(errno)); + file, mode, major, minor, strerror(errno)); goto exit; } - dbg("chmod(%s, %#o)", filename, mode); - if (chmod(filename, mode) != 0) { - dbg("chmod(%s, %#o) failed with error '%s'", - filename, mode, strerror(errno)); +perms: + dbg("chmod(%s, %#o)", file, mode); + if (chmod(file, mode) != 0) { + dbg("chmod(%s, %#o) failed with error '%s'", file, mode, strerror(errno)); goto exit; } if (uid != 0 || gid != 0) { - dbg("chown(%s, %u, %u)", filename, uid, gid); - if (chown(filename, uid, gid) != 0) { + dbg("chown(%s, %u, %u)", file, uid, gid); + if (chown(file, uid, gid) != 0) { dbg("chown(%s, %u, %u) failed with error '%s'", - filename, uid, gid, strerror(errno)); + file, uid, gid, strerror(errno)); goto exit; } } @@ -167,23 +191,6 @@ static void set_to_local_user(char *user) endutent(); } -static int unlink_entry(char *filename) -{ - struct stat stats; - int retval = 0; - - if (lstat(filename, &stats) == 0) { - if ((stats.st_mode & S_IFMT) != S_IFDIR) { - retval = unlink(filename); - if (retval) { - dbg("unlink(%s) failed with error '%s'", - filename, strerror(errno)); - } - } - } - return retval; -} - static int create_node(struct udevice *dev, int fake) { char filename[NAME_SIZE]; @@ -253,7 +260,6 @@ static int create_node(struct udevice *dev, int fake) } if (!fake) { - unlink_entry(filename); info("creating device node '%s'", filename); if (make_node(filename, dev->major, dev->minor, dev->mode, uid, gid) != 0) goto error; @@ -270,7 +276,6 @@ static int create_node(struct udevice *dev, int fake) for (i = 1; i <= dev->partitions; i++) { strfieldcpy(partitionname, filename); strintcat(partitionname, i); - unlink_entry(partitionname); make_node(partitionname, dev->major, dev->minor + i, dev->mode, uid, gid); } @@ -304,11 +309,10 @@ static int create_node(struct udevice *dev, int fake) strfieldcat(linktarget, &dev->name[tail]); - if (!fake) - unlink_entry(filename); - dbg("symlink(%s, %s)", linktarget, filename); if (!fake) { + selinux_setfscreatecon(filename, S_IFLNK); + unlink(filename); if (symlink(linktarget, filename) != 0) dbg("symlink(%s, %s) failed with error '%s'", linktarget, filename, strerror(errno)); @@ -320,7 +324,7 @@ error: return -1; } -static struct sysfs_class_device *get_class_dev(char *device_name) +static struct sysfs_class_device *get_class_dev(const char *device_name) { char dev_path[SYSFS_PATH_MAX]; struct sysfs_class_device *class_dev = NULL; @@ -345,7 +349,7 @@ exit: * If it doesn't happen in about 10 seconds, give up. */ #define SECONDS_TO_WAIT_FOR_FILE 10 -static int sleep_for_file(char *path, char* file) +static int sleep_for_file(const char *path, char* file) { char filename[SYSFS_PATH_MAX + 6]; int loop = SECONDS_TO_WAIT_FOR_FILE; @@ -399,7 +403,7 @@ static int rename_net_if(struct udevice *dev, int fake) return retval; } -int udev_add_device(char *path, char *subsystem, int fake) +int udev_add_device(const char *path, const char *subsystem, int fake) { struct sysfs_class_device *class_dev; struct udevice dev; @@ -442,13 +446,14 @@ int udev_add_device(char *path, char *subsystem, int fake) dbg("name='%s'", dev.name); + selinux_init(); switch (dev.type) { case 'b': case 'c': retval = create_node(&dev, fake); - if (fake || retval != 0) + if (retval != 0) goto exit; - if (udevdb_add_dev(path, &dev) != 0) + if ((!fake) && (udevdb_add_dev(path, &dev) != 0)) dbg("udevdb_add_dev failed, but we are going to try " "to create the node anyway. But remove might not " "work properly for this device."); @@ -457,21 +462,21 @@ int udev_add_device(char *path, char *subsystem, int fake) break; case 'n': + strfieldcpy(devpath, path); if (strcmp(dev.name, dev.kernel_name) != 0) { retval = rename_net_if(&dev, fake); - if (fake || retval != 0) + if (retval != 0) goto exit; /* netif's are keyed with the configured name, cause * the original kernel name sleeps with the fishes */ - strfieldcpy(devpath, path); pos = strrchr(devpath, '/'); if (pos != NULL) { pos[1] = '\0'; strfieldcat(devpath, dev.name); } } - if (udevdb_add_dev(devpath, &dev) != 0) + if ((!fake) && (udevdb_add_dev(devpath, &dev) != 0)) dbg("udevdb_add_dev failed"); dev_d_send(&dev, subsystem, devpath); @@ -479,6 +484,7 @@ int udev_add_device(char *path, char *subsystem, int fake) } exit: + selinux_restore(); sysfs_close_class_device(class_dev); return retval;