chiark / gitweb /
[PATCH] provide temporary device node for callouts to access the device
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Wed, 9 Feb 2005 03:37:32 +0000 (04:37 +0100)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 06:27:32 +0000 (23:27 -0700)
%N will create a temporary node for a callout a be sustituted with the
name of the node.

namedev.c
test/udev-test.pl
udev.8.in
udev.h
udev_add.c
udev_remove.c
udev_utils.c
udev_utils.h

index 0c5d050..332e2d5 100644 (file)
--- 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;
 }
index 67c0672..fa1e4af 100644 (file)
@@ -1068,6 +1068,24 @@ BUS="scsi", KERNEL="sda", NAME="should_not_match", DRIVER="sd-wrong"
 BUS="scsi", KERNEL="sda", NAME="node", DRIVER="sd"
 EOF
        },
+       {
+               desc            => "temporary node creation test",
+               subsys          => "block",
+               devpath         => "/block/sda",
+               exp_name        => "sda",
+               conf            => <<EOF
+BUS="scsi", KERNEL="sda", PROGRAM="/usr/bin/test -b %N" NAME="%N"
+EOF
+       },
+       {
+               desc            => "devpath substitution test",
+               subsys          => "block",
+               devpath         => "/block/sda",
+               exp_name        => "sda",
+               conf            => <<EOF
+BUS="scsi", KERNEL="sda", PROGRAM="/bin/echo %p", RESULT="/block/sda" NAME="%k"
+EOF
+       },
 );
 
 # set env
index aaaf231..51c55bc 100644 (file)
--- a/udev.8.in
+++ b/udev.8.in
@@ -188,6 +188,9 @@ For example, 'sda3' has a "kernel number" of '3'.
 .B %k
 The "kernel name" for the device.
 .TP
+.B %p
+The devpath for the device.
+.TP
 .B %M
 The kernel major number for the device.
 .TP
@@ -211,6 +214,10 @@ If the number is followed by the + char this part plus
 all remaining parts of the result string are substituted:
 .BI %c{ N+ }
 .TP
+.B %N
+The name of a created temporary device node to provide access to the
+device from a external program.
+.TP
 .BI %s{ filename }
 The content of a sysfs attribute.
 .TP
diff --git a/udev.h b/udev.h
index 07385cc..5beec64 100644 (file)
--- a/udev.h
+++ b/udev.h
@@ -23,6 +23,7 @@
 #ifndef _UDEV_H_
 #define _UDEV_H_
 
+#include <sys/types.h>
 #include <sys/param.h>
 #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];
index 24a20bb..a495902 100644 (file)
@@ -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);
                        }
                }
        }
index 1425035..e1af3db 100644 (file)
@@ -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);
                }
        }
 
index 5b0355d..ca46258 100644 (file)
@@ -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;
index 5d2c9c5..19061f1 100644 (file)
@@ -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);