From: kay.sievers@vrfy.org Date: Wed, 9 Feb 2005 03:37:32 +0000 (+0100) Subject: [PATCH] provide temporary device node for callouts to access the device X-Git-Tag: 052~7 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=c1ab046124ebef3c82950b91ccfd1678d9f7fe5b [PATCH] provide temporary device node for callouts to access the device %N will create a temporary node for a callout a be sustituted with the name of the node. --- diff --git a/namedev.c b/namedev.c index 0c5d0509f..332e2d57d 100644 --- a/namedev.c +++ b/namedev.c @@ -201,6 +201,12 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize, switch (c) { + case 'p': + if (strlen(udev->devpath) == 0) + break; + strfieldcatmax(string, udev->devpath, maxsize); + dbg("substitute kernel name '%s'", udev->kernel_name); + break; case 'b': if (strlen(udev->bus_id) == 0) break; @@ -290,6 +296,15 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize, strfieldcatmax(string, temp2, maxsize); } break; + case 'N': + if (udev->tmp_node[0] == '\0') { + dbg("create temporary device node for callout"); + snprintf(udev->tmp_node, NAME_SIZE-1, "%s/.tmp-%u-%u", udev_root, udev->major, udev->minor); + udev_make_node(udev, udev->tmp_node, udev->major, udev->minor, 0600, 0, 0); + } + strfieldcatmax(string, udev->tmp_node, maxsize); + dbg("substitute temporary device node name '%s'", udev->tmp_node); + break; default: dbg("unknown substitution type '%%%c'", c); break; @@ -787,5 +802,11 @@ int namedev_name_device(struct udevice *udev, struct sysfs_class_device *class_d dbg("no rule found, use kernel name '%s'", udev->name); exit: + if (udev->tmp_node[0] != '\0') { + dbg("removing temporary device node"); + unlink_secure(udev->tmp_node); + udev->tmp_node[0] = '\0'; + } + return 0; } diff --git a/test/udev-test.pl b/test/udev-test.pl index 67c067275..fa1e4affc 100644 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -1066,6 +1066,24 @@ EOF conf => < "temporary node creation test", + subsys => "block", + devpath => "/block/sda", + exp_name => "sda", + conf => < "devpath substitution test", + subsys => "block", + devpath => "/block/sda", + exp_name => "sda", + conf => < #include #include "libsysfs/sysfs/libsysfs.h" @@ -59,6 +60,7 @@ struct udevice { int minor; char devname[NAME_SIZE]; + char tmp_node[NAME_SIZE]; int partitions; int ignore_remove; int config_line; @@ -75,6 +77,7 @@ extern int udev_remove_device(struct udevice *udev); extern void udev_init_config(void); extern int udev_start(void); extern void udev_multiplex_directory(struct udevice *udev, const char *basedir, const char *suffix); +extern int udev_make_node(struct udevice *udev, const char *file, int major, int minor, mode_t mode, uid_t uid, gid_t gid); extern char sysfs_path[SYSFS_PATH_MAX]; extern char udev_root[PATH_MAX]; diff --git a/udev_add.c b/udev_add.c index 24a20bba9..a495902ab 100644 --- a/udev_add.c +++ b/udev_add.c @@ -67,7 +67,7 @@ error: return -1; } -static int make_node(struct udevice *udev, char *file, int major, int minor, unsigned int mode, uid_t uid, gid_t gid) +int udev_make_node(struct udevice *udev, const char *file, int major, int minor, mode_t mode, uid_t uid, gid_t gid) { struct stat stats; int retval = 0; @@ -183,7 +183,7 @@ static int create_node(struct udevice *udev) if (!udev->test_run) { info("creating device node '%s'", filename); - if (make_node(udev, filename, udev->major, udev->minor, udev->mode, uid, gid) != 0) + if (udev_make_node(udev, filename, udev->major, udev->minor, udev->mode, uid, gid) != 0) goto error; } else { info("creating device node '%s', major = '%d', minor = '%d', " @@ -198,7 +198,7 @@ static int create_node(struct udevice *udev) for (i = 1; i <= udev->partitions; i++) { strfieldcpy(partitionname, filename); strintcat(partitionname, i); - make_node(udev, partitionname, udev->major, udev->minor + i, udev->mode, uid, gid); + udev_make_node(udev, partitionname, udev->major, udev->minor + i, udev->mode, uid, gid); } } } diff --git a/udev_remove.c b/udev_remove.c index 142503589..e1af3dbef 100644 --- a/udev_remove.c +++ b/udev_remove.c @@ -67,41 +67,6 @@ static int delete_path(const char *path) return 0; } -/** Remove all permissions on the device node, before - * unlinking it. This fixes a security issue. - * If the user created a hard-link to the device node, - * he can't use it any longer, because he lost permission - * to do so. - */ -static int secure_unlink(const char *filename) -{ - int retval; - - retval = chown(filename, 0, 0); - if (retval) { - dbg("chown(%s, 0, 0) failed with error '%s'", - filename, strerror(errno)); - /* We continue nevertheless. - * I think it's very unlikely for chown - * to fail here, if the file exists. - */ - } - retval = chmod(filename, 0000); - if (retval) { - dbg("chmod(%s, 0000) failed with error '%s'", - filename, strerror(errno)); - /* We continue nevertheless. */ - } - retval = unlink(filename); - if (errno == ENOENT) - retval = 0; - if (retval) { - dbg("unlink(%s) failed with error '%s'", - filename, strerror(errno)); - } - return retval; -} - static int delete_node(struct udevice *udev) { char filename[NAME_SIZE]; @@ -116,7 +81,7 @@ static int delete_node(struct udevice *udev) filename[NAME_SIZE-1] = '\0'; info("removing device node '%s'", filename); - retval = secure_unlink(filename); + retval = unlink_secure(filename); if (retval) return retval; @@ -131,7 +96,7 @@ static int delete_node(struct udevice *udev) for (i = 1; i <= num; i++) { strfieldcpy(partitionname, filename); strintcat(partitionname, i); - secure_unlink(partitionname); + unlink_secure(partitionname); } } diff --git a/udev_utils.c b/udev_utils.c index 5b0355d0e..ca46258de 100644 --- a/udev_utils.c +++ b/udev_utils.c @@ -112,6 +112,31 @@ int create_path(const char *path) return mkdir(p, 0755); } +/* Reset permissions on the device node, before unlinking it to make sure, + * that permisions of possible hard links will be removed to. + */ +int unlink_secure(const char *filename) +{ + int retval; + + retval = chown(filename, 0, 0); + if (retval) + dbg("chown(%s, 0, 0) failed with error '%s'", filename, strerror(errno)); + + retval = chmod(filename, 0000); + if (retval) + dbg("chmod(%s, 0000) failed with error '%s'", filename, strerror(errno)); + + retval = unlink(filename); + if (errno == ENOENT) + retval = 0; + + if (retval) + dbg("unlink(%s) failed with error '%s'", filename, strerror(errno)); + + return retval; +} + int parse_get_pair(char **orig_string, char **left, char **right) { char *temp; diff --git a/udev_utils.h b/udev_utils.h index 5d2c9c580..19061f16f 100644 --- a/udev_utils.h +++ b/udev_utils.h @@ -80,6 +80,7 @@ extern void udev_init_device(struct udevice *udev, const char* devpath, const ch extern int kernel_release_satisfactory(unsigned int version, unsigned int patchlevel, unsigned int sublevel); extern int create_path(const char *path); extern int parse_get_pair(char **orig_string, char **left, char **right); +extern int unlink_secure(const char *filename); extern int file_map(const char *filename, char **buf, size_t *bufsize); extern void file_unmap(char *buf, size_t bufsize); extern size_t buf_get_line(const char *buf, size_t buflen, size_t cur);