inaccessible: move inaccessible file nodes to /systemd/ subdir in runtime dir always
Let's make sure $XDG_RUNTIME_DIR for the user instance and /run for the system instance is always organized the same way: the "inaccessible" device nodes should be placed in a subdir of either called "systemd" and a subdir of that called "inaccessible". This way we can emphasize the common behaviour, and only differ where really necessary. Follow-up for #13823
This commit is contained in:
parent
b8c9074534
commit
48b747fa03
|
@ -535,9 +535,9 @@ int mount_setup(bool loaded_policy, bool leave_propagation) {
|
|||
(void) mkdir_label("/run/systemd", 0755);
|
||||
(void) mkdir_label("/run/systemd/system", 0755);
|
||||
|
||||
/* Also create /run/systemd/inaccessible nodes, so that we always have something to mount inaccessible nodes
|
||||
* from. */
|
||||
(void) make_inaccessible_nodes("/run/systemd", UID_INVALID, GID_INVALID);
|
||||
/* Also create /run/systemd/inaccessible nodes, so that we always have something to mount
|
||||
* inaccessible nodes from. */
|
||||
(void) make_inaccessible_nodes(NULL, UID_INVALID, GID_INVALID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -939,10 +939,10 @@ static int apply_mount(
|
|||
}
|
||||
|
||||
if (geteuid() == 0)
|
||||
runtime_dir = "/run/systemd";
|
||||
runtime_dir = "/run";
|
||||
else {
|
||||
if (asprintf(&tmp, "/run/user/"UID_FMT, geteuid()) < 0)
|
||||
log_oom();
|
||||
if (asprintf(&tmp, "/run/user/" UID_FMT, geteuid()) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
runtime_dir = tmp;
|
||||
}
|
||||
|
|
|
@ -898,7 +898,7 @@ static int mount_inaccessible(const char *dest, CustomMount *m) {
|
|||
return m->graceful ? 0 : r;
|
||||
}
|
||||
|
||||
r = mode_to_inaccessible_node("/run/systemd", st.st_mode, &source);
|
||||
r = mode_to_inaccessible_node(NULL, st.st_mode, &source);
|
||||
if (r < 0)
|
||||
return m->graceful ? 0 : r;
|
||||
|
||||
|
|
|
@ -3471,7 +3471,7 @@ static int outer_child(
|
|||
|
||||
(void) dev_setup(directory, arg_uid_shift, arg_uid_shift);
|
||||
|
||||
p = prefix_roota(directory, "/run/systemd");
|
||||
p = prefix_roota(directory, "/run");
|
||||
(void) make_inaccessible_nodes(p, arg_uid_shift, arg_uid_shift);
|
||||
|
||||
r = setup_pts(directory);
|
||||
|
|
|
@ -56,31 +56,38 @@ int dev_setup(const char *prefix, uid_t uid, gid_t gid) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int make_inaccessible_nodes(const char *root, uid_t uid, gid_t gid) {
|
||||
int make_inaccessible_nodes(
|
||||
const char *runtime_dir,
|
||||
uid_t uid,
|
||||
gid_t gid) {
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
mode_t mode;
|
||||
} table[] = {
|
||||
{ "", S_IFDIR | 0755 },
|
||||
{ "/inaccessible", S_IFDIR | 0000 },
|
||||
{ "/inaccessible/reg", S_IFREG | 0000 },
|
||||
{ "/inaccessible/dir", S_IFDIR | 0000 },
|
||||
{ "/inaccessible/fifo", S_IFIFO | 0000 },
|
||||
{ "/inaccessible/sock", S_IFSOCK | 0000 },
|
||||
{ "/systemd", S_IFDIR | 0755 },
|
||||
{ "/systemd/inaccessible", S_IFDIR | 0000 },
|
||||
{ "/systemd/inaccessible/reg", S_IFREG | 0000 },
|
||||
{ "/systemd/inaccessible/dir", S_IFDIR | 0000 },
|
||||
{ "/systemd/inaccessible/fifo", S_IFIFO | 0000 },
|
||||
{ "/systemd/inaccessible/sock", S_IFSOCK | 0000 },
|
||||
|
||||
/* The following two are likely to fail if we lack the privs for it (for example in an userns
|
||||
* environment, if CAP_SYS_MKNOD is missing, or if a device node policy prohibit major/minor of 0
|
||||
* device nodes to be created). But that's entirely fine. Consumers of these files should carry
|
||||
* fallback to use a different node then, for example <root>/inaccessible/sock, which is close
|
||||
* enough in behaviour and semantics for most uses. */
|
||||
{ "/inaccessible/chr", S_IFCHR | 0000 },
|
||||
{ "/inaccessible/blk", S_IFBLK | 0000 },
|
||||
{ "/systemd/inaccessible/chr", S_IFCHR | 0000 },
|
||||
{ "/systemd/inaccessible/blk", S_IFBLK | 0000 },
|
||||
};
|
||||
|
||||
_cleanup_umask_ mode_t u;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
if (!runtime_dir)
|
||||
runtime_dir = "/run";
|
||||
|
||||
u = umask(0000);
|
||||
|
||||
/* Set up inaccessible (and empty) file nodes of all types. This are used to as mount sources for over-mounting
|
||||
|
@ -91,7 +98,7 @@ int make_inaccessible_nodes(const char *root, uid_t uid, gid_t gid) {
|
|||
for (i = 0; i < ELEMENTSOF(table); i++) {
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
path = path_join(root, table[i].name);
|
||||
path = path_join(runtime_dir, table[i].name);
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
|
|
|
@ -397,71 +397,73 @@ int repeat_unmount(const char *path, int flags) {
|
|||
}
|
||||
}
|
||||
|
||||
int mode_to_inaccessible_node(const char *runtime_dir, mode_t mode, char **dest) {
|
||||
/* This function maps a node type to a corresponding inaccessible file node. These nodes are created during
|
||||
* early boot by PID 1. In some cases we lacked the privs to create the character and block devices (maybe
|
||||
* because we run in an userns environment, or miss CAP_SYS_MKNOD, or run with a devices policy that excludes
|
||||
* device nodes with major and minor of 0), but that's fine, in that case we use an AF_UNIX file node instead,
|
||||
* which is not the same, but close enough for most uses. And most importantly, the kernel allows bind mounts
|
||||
* from socket nodes to any non-directory file nodes, and that's the most important thing that matters. */
|
||||
int mode_to_inaccessible_node(
|
||||
const char *runtime_dir,
|
||||
mode_t mode,
|
||||
char **ret) {
|
||||
|
||||
/* This function maps a node type to a corresponding inaccessible file node. These nodes are created
|
||||
* during early boot by PID 1. In some cases we lacked the privs to create the character and block
|
||||
* devices (maybe because we run in an userns environment, or miss CAP_SYS_MKNOD, or run with a
|
||||
* devices policy that excludes device nodes with major and minor of 0), but that's fine, in that
|
||||
* case we use an AF_UNIX file node instead, which is not the same, but close enough for most
|
||||
* uses. And most importantly, the kernel allows bind mounts from socket nodes to any non-directory
|
||||
* file nodes, and that's the most important thing that matters.
|
||||
*
|
||||
* Note that the runtime directory argument shall be the top-level runtime directory, i.e. /run/ if
|
||||
* we operate in system context and $XDG_RUNTIME_DIR if we operate in user context. */
|
||||
|
||||
_cleanup_free_ char *d = NULL;
|
||||
const char *node = NULL;
|
||||
char *tmp;
|
||||
bool fallback = false;
|
||||
|
||||
assert(dest);
|
||||
assert(ret);
|
||||
|
||||
if (!runtime_dir)
|
||||
runtime_dir = "/run";
|
||||
|
||||
switch(mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
node = "/inaccessible/reg";
|
||||
node = "/systemd/inaccessible/reg";
|
||||
break;
|
||||
|
||||
case S_IFDIR:
|
||||
node = "/inaccessible/dir";
|
||||
node = "/systemd/inaccessible/dir";
|
||||
break;
|
||||
|
||||
case S_IFCHR:
|
||||
d = path_join(runtime_dir, "/inaccessible/chr");
|
||||
if (!d)
|
||||
return log_oom();
|
||||
|
||||
if (access(d, F_OK) == 0) {
|
||||
*dest = TAKE_PTR(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = "/inaccessible/sock";
|
||||
node = "/systemd/inaccessible/chr";
|
||||
fallback = true;
|
||||
break;
|
||||
|
||||
case S_IFBLK:
|
||||
d = path_join(runtime_dir, "/inaccessible/blk");
|
||||
if (!d)
|
||||
return log_oom();
|
||||
|
||||
if (access(d, F_OK) == 0) {
|
||||
*dest = TAKE_PTR(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = "/inaccessible/sock";
|
||||
node = "/systemd/inaccessible/blk";
|
||||
fallback = true;
|
||||
break;
|
||||
|
||||
case S_IFIFO:
|
||||
node = "/inaccessible/fifo";
|
||||
node = "/systemd/inaccessible/fifo";
|
||||
break;
|
||||
|
||||
case S_IFSOCK:
|
||||
node = "/inaccessible/sock";
|
||||
node = "/systemd/inaccessible/sock";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = path_join(runtime_dir, node);
|
||||
if (!tmp)
|
||||
return log_oom();
|
||||
d = path_join(runtime_dir, node);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
*dest = tmp;
|
||||
if (fallback && access(d, F_OK) < 0) {
|
||||
free(d);
|
||||
d = path_join(runtime_dir, "/systemd/inaccessible/sock");
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ int main(int argc, char *argv[]) {
|
|||
f = prefix_roota(p, "/run");
|
||||
assert_se(mkdir(f, 0755) >= 0);
|
||||
|
||||
f = prefix_roota(p, "/run/systemd");
|
||||
assert_se(make_inaccessible_nodes(f, 1, 1) >= 0);
|
||||
|
||||
f = prefix_roota(p, "/run/systemd/inaccessible/reg");
|
||||
|
|
Loading…
Reference in New Issue