mirror of
https://github.com/systemd/systemd.git
synced 2025-01-26 14:04:03 +03:00
[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.
This commit is contained in:
parent
bce52be81e
commit
c1ab046124
21
namedev.c
21
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;
|
||||
}
|
||||
|
@ -1066,6 +1066,24 @@ EOF
|
||||
conf => <<EOF
|
||||
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
|
||||
},
|
||||
);
|
||||
|
@ -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
|
||||
|
3
udev.h
3
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];
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
25
udev_utils.c
25
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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user