Compare commits

..

No commits in common. "5961d35a5bc0d9bb095acc1307d7023b5b83be67" and "62320feb9f3baefcad3ff69f21d9a6e5a767dcd2" have entirely different histories.

25 changed files with 98 additions and 276 deletions

8
NEWS
View File

@ -516,14 +516,6 @@ CHANGES WITH 246:
https://systemd.io/JOURNAL_FILE_FORMAT https://systemd.io/JOURNAL_FILE_FORMAT
* The interface for containers (https://systemd.io/CONTAINER_INTERFACE)
has been extended by a set of environment variables that expose
select fields from the host's os-release file to the container
payload. Similarly, host's os-release files can be mounted into the
container underneath /run/hosts. Together, those mechanisms provide a
standardized way to expose information about the host to the
container payload. Both interfaces are implemented in systemd-nspawn.
* All D-Bus services shipped in systemd now implement the generic * All D-Bus services shipped in systemd now implement the generic
LogControl1 D-Bus API which allows clients to change log level + LogControl1 D-Bus API which allows clients to change log level +
target of the service during runtime. target of the service during runtime.

View File

@ -121,16 +121,6 @@ manager, please consider supporting the following interfaces.
`container_ttys=pts/7 pts/8 pts/14` it will spawn three additional login `container_ttys=pts/7 pts/8 pts/14` it will spawn three additional login
gettys on ptys 7, 8, and 14. gettys on ptys 7, 8, and 14.
4. To allow applications to detect the OS version and other metadata of the host
running the container manager, if this is considered desirable, please parse
the host's `/etc/os-release` and set a `$container_host_<key>=<VALUE>`
environment variable for the ID fields described by the [os-release
interface](https://www.freedesktop.org/software/systemd/man/os-release.html), eg:
`$container_host_id=debian`
`$container_host_build_id=2020-06-15`
`$container_host_variant_id=server`
`$container_host_version_id=10`
## Advanced Integration ## Advanced Integration
1. Consider syncing `/etc/localtime` from the host file system into the 1. Consider syncing `/etc/localtime` from the host file system into the

View File

@ -339,13 +339,6 @@
name in order to avoid name clashes. Applications name in order to avoid name clashes. Applications
reading this file must ignore unknown fields. Example: reading this file must ignore unknown fields. Example:
<literal>DEBIAN_BTS="debbugs://bugs.debian.org/"</literal></para> <literal>DEBIAN_BTS="debbugs://bugs.debian.org/"</literal></para>
<para>Container and sandbox runtime managers may make the host's
identification data available to applications by providing the host's
<filename>/etc/os-release</filename> and
<filename>/usr/lib/os-release</filename> as respectively
<filename>/run/host/etc/os-release</filename> and
<filename>/run/host/usr/lib/os-release</filename>.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -499,22 +499,11 @@
<para>The MACVLAN mode to use. The supported options are <para>The MACVLAN mode to use. The supported options are
<literal>private</literal>, <literal>private</literal>,
<literal>vepa</literal>, <literal>vepa</literal>,
<literal>bridge</literal>, <literal>bridge</literal>, and
<literal>passthru</literal>, and <literal>passthru</literal>.
<literal>source</literal>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>SourceMACAddress=</varname></term>
<listitem>
<para>A whitespace-separated list of remote hardware addresses allowed on the MACVLAN. This
option only has an effect in source mode. Use full colon-, hyphen- or dot-delimited
hexadecimal. This option may appear more than once, in which case the lists are merged. If
the empty string is assigned to this option, the list of hardware addresses defined prior
to this is reset. Defaults to unset.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -10,7 +10,6 @@
#include "mkdir.h" #include "mkdir.h"
#include "selinux-util.h" #include "selinux-util.h"
#include "smack-util.h" #include "smack-util.h"
#include "user-util.h"
int mkdir_label(const char *path, mode_t mode) { int mkdir_label(const char *path, mode_t mode) {
int r; int r;
@ -51,9 +50,9 @@ int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirF
} }
int mkdir_parents_label(const char *path, mode_t mode) { int mkdir_parents_label(const char *path, mode_t mode) {
return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_label); return mkdir_parents_internal(NULL, path, mode, mkdir_label);
} }
int mkdir_p_label(const char *path, mode_t mode) { int mkdir_p_label(const char *path, mode_t mode) {
return mkdir_p_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_label); return mkdir_p_internal(NULL, path, mode, mkdir_label);
} }

View File

@ -93,7 +93,7 @@ int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags f
return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_errno_wrapper); return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_errno_wrapper);
} }
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) { int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
const char *p, *e; const char *p, *e;
int r; int r;
@ -136,54 +136,34 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, ui
if (prefix && path_startswith(prefix, t)) if (prefix && path_startswith(prefix, t))
continue; continue;
if (uid == UID_INVALID && gid == UID_INVALID && flags == 0) { r = _mkdir(t, mode);
r = _mkdir(t, mode); if (r < 0 && r != -EEXIST)
if (r < 0 && r != -EEXIST) return r;
return r;
} else {
r = mkdir_safe_internal(t, mode, uid, gid, flags, _mkdir);
if (r < 0 && r != -EEXIST)
return r;
}
} }
} }
int mkdir_parents(const char *path, mode_t mode) { int mkdir_parents(const char *path, mode_t mode) {
return mkdir_parents_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_errno_wrapper); return mkdir_parents_internal(NULL, path, mode, mkdir_errno_wrapper);
} }
int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) {
return mkdir_parents_internal(prefix, path, mode, uid, gid, flags, mkdir_errno_wrapper);
}
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) {
int r; int r;
/* Like mkdir -p */ /* Like mkdir -p */
assert(_mkdir != mkdir); assert(_mkdir != mkdir);
r = mkdir_parents_internal(prefix, path, mode, uid, gid, flags, _mkdir); r = mkdir_parents_internal(prefix, path, mode, _mkdir);
if (r < 0) if (r < 0)
return r; return r;
if (uid == UID_INVALID && gid == UID_INVALID && flags == 0) { r = _mkdir(path, mode);
r = _mkdir(path, mode); if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0))
if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0)) return r;
return r;
} else {
r = mkdir_safe_internal(path, mode, uid, gid, flags, _mkdir);
if (r < 0 && r != -EEXIST)
return r;
}
return 0; return 0;
} }
int mkdir_p(const char *path, mode_t mode) { int mkdir_p(const char *path, mode_t mode) {
return mkdir_p_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdir_errno_wrapper); return mkdir_p_internal(NULL, path, mode, mkdir_errno_wrapper);
}
int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdir_errno_wrapper);
} }

View File

@ -12,17 +12,15 @@ int mkdir_errno_wrapper(const char *pathname, mode_t mode);
int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode); int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode);
int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_parents(const char *path, mode_t mode); int mkdir_parents(const char *path, mode_t mode);
int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_p(const char *path, mode_t mode); int mkdir_p(const char *path, mode_t mode);
int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
/* mandatory access control(MAC) versions */ /* mandatory access control(MAC) versions */
int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags);
int mkdir_parents_label(const char *path, mode_t mod); int mkdir_parents_label(const char *path, mode_t mode);
int mkdir_p_label(const char *path, mode_t mode); int mkdir_p_label(const char *path, mode_t mode);
/* internally used */ /* internally used */
typedef int (*mkdir_func_t)(const char *pathname, mode_t mode); typedef int (*mkdir_func_t)(const char *pathname, mode_t mode);
int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir);
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir);

View File

@ -5955,7 +5955,7 @@ const char *unit_label_path(const Unit *u) {
return NULL; return NULL;
/* If a unit is masked, then don't read the SELinux label of /dev/null, as that really makes no sense */ /* If a unit is masked, then don't read the SELinux label of /dev/null, as that really makes no sense */
if (null_or_empty_path(p) > 0) if (path_equal(p, "/dev/null"))
return NULL; return NULL;
return p; return p;

View File

@ -93,20 +93,9 @@ static const NLType rtnl_link_info_data_ipvlan_types[] = {
[IFLA_IPVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 }, [IFLA_IPVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
}; };
static const NLType rtnl_macvlan_macaddr_types[] = {
[IFLA_MACVLAN_MACADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
};
static const NLTypeSystem rtnl_macvlan_macaddr_type_system = {
.count = ELEMENTSOF(rtnl_macvlan_macaddr_types),
.types = rtnl_macvlan_macaddr_types,
};
static const NLType rtnl_link_info_data_macvlan_types[] = { static const NLType rtnl_link_info_data_macvlan_types[] = {
[IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 }, [IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 },
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 }, [IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
[IFLA_MACVLAN_MACADDR_MODE] = { .type = NETLINK_TYPE_U32 },
[IFLA_MACVLAN_MACADDR_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_macvlan_macaddr_type_system },
}; };
static const NLType rtnl_link_info_data_bridge_types[] = { static const NLType rtnl_link_info_data_bridge_types[] = {

View File

@ -23,29 +23,6 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net
assert(m); assert(m);
if (m->mode == NETDEV_MACVLAN_MODE_SOURCE && !set_isempty(m->match_source_mac)) {
Iterator i;
const struct ether_addr *mac_addr;
r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MACADDR_MODE, MACVLAN_MACADDR_SET);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MACADDR_MODE attribute: %m");
r = sd_netlink_message_open_container(req, IFLA_MACVLAN_MACADDR_DATA);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not open IFLA_MACVLAN_MACADDR_DATA container: %m");
SET_FOREACH(mac_addr, m->match_source_mac, i) {
r = sd_netlink_message_append_ether_addr(req, IFLA_MACVLAN_MACADDR, mac_addr);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MACADDR attribute: %m");
}
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not close IFLA_MACVLAN_MACADDR_DATA container: %m");
}
if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) { if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) {
r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode); r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode);
if (r < 0) if (r < 0)
@ -55,21 +32,6 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net
return 0; return 0;
} }
static void macvlan_done(NetDev *n) {
MacVlan *m;
assert(n);
if (n->kind == NETDEV_KIND_MACVLAN)
m = MACVLAN(n);
else
m = MACVTAP(n);
assert(m);
set_free_free(m->match_source_mac);
}
static void macvlan_init(NetDev *n) { static void macvlan_init(NetDev *n) {
MacVlan *m; MacVlan *m;
@ -88,7 +50,6 @@ static void macvlan_init(NetDev *n) {
const NetDevVTable macvtap_vtable = { const NetDevVTable macvtap_vtable = {
.object_size = sizeof(MacVlan), .object_size = sizeof(MacVlan),
.init = macvlan_init, .init = macvlan_init,
.done = macvlan_done,
.sections = NETDEV_COMMON_SECTIONS "MACVTAP\0", .sections = NETDEV_COMMON_SECTIONS "MACVTAP\0",
.fill_message_create = netdev_macvlan_fill_message_create, .fill_message_create = netdev_macvlan_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,
@ -98,7 +59,6 @@ const NetDevVTable macvtap_vtable = {
const NetDevVTable macvlan_vtable = { const NetDevVTable macvlan_vtable = {
.object_size = sizeof(MacVlan), .object_size = sizeof(MacVlan),
.init = macvlan_init, .init = macvlan_init,
.done = macvlan_done,
.sections = NETDEV_COMMON_SECTIONS "MACVLAN\0", .sections = NETDEV_COMMON_SECTIONS "MACVLAN\0",
.fill_message_create = netdev_macvlan_fill_message_create, .fill_message_create = netdev_macvlan_fill_message_create,
.create_type = NETDEV_CREATE_STACKED, .create_type = NETDEV_CREATE_STACKED,

View File

@ -5,13 +5,11 @@ typedef struct MacVlan MacVlan;
#include "macvlan-util.h" #include "macvlan-util.h"
#include "netdev.h" #include "netdev.h"
#include "set.h"
struct MacVlan { struct MacVlan {
NetDev meta; NetDev meta;
MacVlanMode mode; MacVlanMode mode;
Set *match_source_mac;
}; };
DEFINE_NETDEV_CAST(MACVLAN, MacVlan); DEFINE_NETDEV_CAST(MACVLAN, MacVlan);

View File

@ -52,9 +52,7 @@ VLAN.MVRP, config_parse_tristate,
VLAN.LooseBinding, config_parse_tristate, 0, offsetof(VLan, loose_binding) VLAN.LooseBinding, config_parse_tristate, 0, offsetof(VLan, loose_binding)
VLAN.ReorderHeader, config_parse_tristate, 0, offsetof(VLan, reorder_hdr) VLAN.ReorderHeader, config_parse_tristate, 0, offsetof(VLan, reorder_hdr)
MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
MACVLAN.SourceMACAddress, config_parse_hwaddrs, 0, offsetof(MacVlan, match_source_mac)
MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
MACVTAP.SourceMACAddress, config_parse_hwaddrs, 0, offsetof(MacVlan, match_source_mac)
IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags) IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
IPVTAP.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) IPVTAP.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)

View File

@ -487,6 +487,59 @@ int mount_sysfs(const char *dest, MountSettingsMask mount_settings) {
MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL); MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL);
} }
static int mkdir_userns(const char *path, mode_t mode, uid_t uid_shift) {
int r;
assert(path);
r = mkdir_errno_wrapper(path, mode);
if (r < 0 && r != -EEXIST)
return r;
if (uid_shift == UID_INVALID)
return 0;
if (lchown(path, uid_shift, uid_shift) < 0)
return -errno;
return 0;
}
static int mkdir_userns_p(const char *prefix, const char *path, mode_t mode, uid_t uid_shift) {
const char *p, *e;
int r;
assert(path);
if (prefix && !path_startswith(path, prefix))
return -ENOTDIR;
/* create every parent directory in the path, except the last component */
p = path + strspn(path, "/");
for (;;) {
char t[strlen(path) + 1];
e = p + strcspn(p, "/");
p = e + strspn(e, "/");
/* Is this the last component? If so, then we're done */
if (*p == 0)
break;
memcpy(t, path, e - path);
t[e-path] = 0;
if (prefix && path_startswith(prefix, t))
continue;
r = mkdir_userns(t, mode, uid_shift);
if (r < 0)
return r;
}
return mkdir_userns(path, mode, uid_shift);
}
int mount_all(const char *dest, int mount_all(const char *dest,
MountSettingsMask mount_settings, MountSettingsMask mount_settings,
uid_t uid_shift, uid_t uid_shift,
@ -545,33 +598,29 @@ int mount_all(const char *dest,
PROC_READ_ONLY("/proc/irq"), PROC_READ_ONLY("/proc/irq"),
PROC_READ_ONLY("/proc/scsi"), PROC_READ_ONLY("/proc/scsi"),
{ "mqueue", "/dev/mqueue", "mqueue", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, { "mqueue", "/dev/mqueue", "mqueue", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
MOUNT_IN_USERNS|MOUNT_MKDIR }, MOUNT_IN_USERNS|MOUNT_MKDIR },
/* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */ /* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */
{ "tmpfs", "/tmp", "tmpfs", "mode=1777" TMPFS_LIMITS_TMP, MS_NOSUID|MS_NODEV|MS_STRICTATIME, { "tmpfs", "/tmp", "tmpfs", "mode=1777" TMPFS_LIMITS_TMP, MS_NOSUID|MS_NODEV|MS_STRICTATIME,
MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP|MOUNT_MKDIR }, MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP|MOUNT_MKDIR },
{ "tmpfs", "/sys", "tmpfs", "mode=555" TMPFS_LIMITS_SYS, MS_NOSUID|MS_NOEXEC|MS_NODEV, { "tmpfs", "/sys", "tmpfs", "mode=555" TMPFS_LIMITS_SYS, MS_NOSUID|MS_NOEXEC|MS_NODEV,
MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS|MOUNT_MKDIR }, MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS|MOUNT_MKDIR },
{ "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,
MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO|MOUNT_MKDIR }, /* skipped if above was mounted */ MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO|MOUNT_MKDIR }, /* skipped if above was mounted */
{ "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
MOUNT_FATAL|MOUNT_MKDIR }, /* skipped if above was mounted */ MOUNT_FATAL|MOUNT_MKDIR }, /* skipped if above was mounted */
{ "tmpfs", "/dev", "tmpfs", "mode=755" TMPFS_LIMITS_DEV, MS_NOSUID|MS_STRICTATIME, { "tmpfs", "/dev", "tmpfs", "mode=755" TMPFS_LIMITS_DEV, MS_NOSUID|MS_STRICTATIME,
MOUNT_FATAL|MOUNT_MKDIR }, MOUNT_FATAL|MOUNT_MKDIR },
{ "tmpfs", "/dev/shm", "tmpfs", "mode=1777" TMPFS_LIMITS_DEV_SHM, MS_NOSUID|MS_NODEV|MS_STRICTATIME, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777" TMPFS_LIMITS_DEV_SHM, MS_NOSUID|MS_NODEV|MS_STRICTATIME,
MOUNT_FATAL|MOUNT_MKDIR }, MOUNT_FATAL|MOUNT_MKDIR },
{ "tmpfs", "/run", "tmpfs", "mode=755" TMPFS_LIMITS_RUN, MS_NOSUID|MS_NODEV|MS_STRICTATIME, { "tmpfs", "/run", "tmpfs", "mode=755" TMPFS_LIMITS_RUN, MS_NOSUID|MS_NODEV|MS_STRICTATIME,
MOUNT_FATAL|MOUNT_MKDIR }, MOUNT_FATAL|MOUNT_MKDIR },
{ "/usr/lib/os-release", "/run/host/usr/lib/os-release", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,
MOUNT_FATAL|MOUNT_MKDIR|MOUNT_TOUCH },
{ "/etc/os-release", "/run/host/etc/os-release", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,
MOUNT_MKDIR|MOUNT_TOUCH },
#if HAVE_SELINUX #if HAVE_SELINUX
{ "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,
MOUNT_MKDIR }, /* Bind mount first (mkdir/chown the mount point in case /sys/ is mounted as minimal skeleton tmpfs) */ MOUNT_MKDIR }, /* Bind mount first (mkdir/chown the mount point in case /sys/ is mounted as minimal skeleton tmpfs) */
{ NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
0 }, /* Then, make it r/o (don't mkdir/chown the mount point here, the previous entry already did that) */ 0 }, /* Then, make it r/o (don't mkdir/chown the mount point here, the previous entry already did that) */
#endif #endif
}; };
@ -587,7 +636,6 @@ int mount_all(const char *dest,
for (k = 0; k < ELEMENTSOF(mount_table); k++) { for (k = 0; k < ELEMENTSOF(mount_table); k++) {
_cleanup_free_ char *where = NULL, *options = NULL; _cleanup_free_ char *where = NULL, *options = NULL;
const char *o; const char *o;
struct stat source_st;
bool fatal = FLAGS_SET(mount_table[k].mount_settings, MOUNT_FATAL); bool fatal = FLAGS_SET(mount_table[k].mount_settings, MOUNT_FATAL);
if (in_userns != FLAGS_SET(mount_table[k].mount_settings, MOUNT_IN_USERNS)) if (in_userns != FLAGS_SET(mount_table[k].mount_settings, MOUNT_IN_USERNS))
@ -613,26 +661,10 @@ int mount_all(const char *dest,
return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where); return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where);
if (r > 0) if (r > 0)
continue; continue;
/* Shortcut for optional bind mounts: if the source can't be found skip ahead to avoid creating
* empty and unused directories. */
if (!fatal && FLAGS_SET(mount_table[k].mount_settings, MOUNT_MKDIR) && FLAGS_SET(mount_table[k].flags, MS_BIND)) {
r = stat(mount_table[k].what, &source_st);
if (r < 0) {
if (errno == ENOENT)
continue;
return log_error_errno(errno, "Failed to stat %s: %m", mount_table[k].what);
}
}
} }
if (FLAGS_SET(mount_table[k].mount_settings, MOUNT_MKDIR)) { if (FLAGS_SET(mount_table[k].mount_settings, MOUNT_MKDIR)) {
uid_t u = (use_userns && !in_userns) ? uid_shift : UID_INVALID; r = mkdir_userns_p(dest, where, 0755, (use_userns && !in_userns) ? uid_shift : UID_INVALID);
if (FLAGS_SET(mount_table[k].mount_settings, MOUNT_TOUCH))
r = mkdir_parents_safe(dest, where, 0755, u, u, 0);
else
r = mkdir_p_safe(dest, where, 0755, u, u, 0);
if (r < 0 && r != -EEXIST) { if (r < 0 && r != -EEXIST) {
if (fatal && r != -EROFS) if (fatal && r != -EROFS)
return log_error_errno(r, "Failed to create directory %s: %m", where); return log_error_errno(r, "Failed to create directory %s: %m", where);
@ -644,14 +676,6 @@ int mount_all(const char *dest,
if (r != -EROFS) if (r != -EROFS)
continue; continue;
} }
if (FLAGS_SET(mount_table[k].mount_settings, MOUNT_TOUCH)) {
r = touch(where);
if (r < 0 && r != -EEXIST) {
if (fatal)
return log_error_errno(r, "Failed to create mount point %s: %m", where);
log_debug_errno(r, "Failed to create mount point %s: %m", where);
}
}
} }
o = mount_table[k].options; o = mount_table[k].options;

View File

@ -17,7 +17,6 @@ typedef enum MountSettingsMask {
MOUNT_ROOT_ONLY = 1 << 6, /* if set, only root mounts are mounted */ MOUNT_ROOT_ONLY = 1 << 6, /* if set, only root mounts are mounted */
MOUNT_NON_ROOT_ONLY = 1 << 7, /* if set, only non-root mounts are mounted */ MOUNT_NON_ROOT_ONLY = 1 << 7, /* if set, only non-root mounts are mounted */
MOUNT_MKDIR = 1 << 8, /* if set, make directory to mount over first */ MOUNT_MKDIR = 1 << 8, /* if set, make directory to mount over first */
MOUNT_TOUCH = 1 << 9, /* if set, touch file to mount over first */
} MountSettingsMask; } MountSettingsMask;
typedef enum CustomMountType { typedef enum CustomMountType {

View File

@ -2931,8 +2931,7 @@ static int inner_child(
int kmsg_socket, int kmsg_socket,
int rtnl_socket, int rtnl_socket,
int master_pty_socket, int master_pty_socket,
FDSet *fds, FDSet *fds) {
char **os_release_pairs) {
_cleanup_free_ char *home = NULL; _cleanup_free_ char *home = NULL;
char as_uuid[ID128_UUID_STRING_MAX]; char as_uuid[ID128_UUID_STRING_MAX];
@ -3191,7 +3190,7 @@ static int inner_child(
if (asprintf((char **)(envp + n_env++), "NOTIFY_SOCKET=%s", NSPAWN_NOTIFY_SOCKET_PATH) < 0) if (asprintf((char **)(envp + n_env++), "NOTIFY_SOCKET=%s", NSPAWN_NOTIFY_SOCKET_PATH) < 0)
return log_oom(); return log_oom();
env_use = strv_env_merge(3, envp, arg_setenv, os_release_pairs); env_use = strv_env_merge(2, envp, arg_setenv);
if (!env_use) if (!env_use)
return log_oom(); return log_oom();
@ -3317,7 +3316,6 @@ static int outer_child(
FDSet *fds, FDSet *fds,
int netns_fd) { int netns_fd) {
_cleanup_strv_free_ char **os_release_pairs = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
const char *p; const char *p;
pid_t pid; pid_t pid;
@ -3339,10 +3337,6 @@ static int outer_child(
log_debug("Outer child is initializing."); log_debug("Outer child is initializing.");
r = load_os_release_pairs_with_prefix("/", "container_host_", &os_release_pairs);
if (r < 0)
log_debug_errno(r, "Failed to read os-release from host for container, ignoring: %m");
if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m"); return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m");
@ -3608,7 +3602,7 @@ static int outer_child(
return log_error_errno(r, "Failed to join network namespace: %m"); return log_error_errno(r, "Failed to join network namespace: %m");
} }
r = inner_child(barrier, directory, secondary, kmsg_socket, rtnl_socket, master_pty_socket, fds, os_release_pairs); r = inner_child(barrier, directory, secondary, kmsg_socket, rtnl_socket, master_pty_socket, fds);
if (r < 0) if (r < 0)
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);

View File

@ -701,7 +701,6 @@ static int install_chroot_dropin(
"[Service]\n", "[Service]\n",
IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage=", image_path, "\n" IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage=", image_path, "\n"
"Environment=PORTABLE=", basename(image_path), "\n" "Environment=PORTABLE=", basename(image_path), "\n"
"BindReadOnlyPaths=-/etc/os-release:/run/host/etc/os-release /usr/lib/os-release:/run/host/usr/lib/os-release\n"
"LogExtraFields=PORTABLE=", basename(image_path), "\n", "LogExtraFields=PORTABLE=", basename(image_path), "\n",
NULL)) NULL))

View File

@ -1236,7 +1236,8 @@ static int unit_file_load(
"%s: unit type %s cannot be templated, ignoring.", path, unit_type_to_string(type)); "%s: unit type %s cannot be templated, ignoring.", path, unit_type_to_string(type));
if (!(flags & SEARCH_LOAD)) { if (!(flags & SEARCH_LOAD)) {
if (lstat(path, &st) < 0) r = lstat(path, &st);
if (r < 0)
return -errno; return -errno;
if (null_or_empty(&st)) if (null_or_empty(&st))
@ -1323,40 +1324,26 @@ static int unit_file_load_or_readlink(
const char *path, const char *path,
const char *root_dir, const char *root_dir,
SearchFlags flags) { SearchFlags flags) {
_cleanup_free_ char *resolved = NULL;
struct stat st; _cleanup_free_ char *target = NULL;
int r; int r;
r = unit_file_load(c, info, path, root_dir, flags); r = unit_file_load(c, info, path, root_dir, flags);
if (r != -ELOOP || (flags & SEARCH_DROPIN)) if (r != -ELOOP || (flags & SEARCH_DROPIN))
return r; return r;
r = chase_symlinks(path, root_dir, CHASE_WARN | CHASE_NONEXISTENT, &resolved, NULL); /* This is a symlink, let's read it. */
if (r >= 0 &&
root_dir && r = readlink_malloc(path, &target);
path_equal_ptr(path_startswith(resolved, root_dir), "dev/null")) if (r < 0)
/* When looking under root_dir, we can't expect /dev/ to be mounted, return r;
* so let's see if the path is a (possibly dangling) symlink to /dev/null. */
if (path_equal(target, "/dev/null"))
info->type = UNIT_FILE_TYPE_MASKED; info->type = UNIT_FILE_TYPE_MASKED;
else if (r > 0 &&
stat(resolved, &st) >= 0 &&
null_or_empty(&st))
info->type = UNIT_FILE_TYPE_MASKED;
else { else {
_cleanup_free_ char *target = NULL;
const char *bn; const char *bn;
UnitType a, b; UnitType a, b;
/* This is a symlink, let's read it. We read the link again, because last time
* we followed the link until resolution, and here we need to do one step. */
r = readlink_malloc(path, &target);
if (r < 0)
return r;
bn = basename(target); bn = basename(target);
if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) { if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) {

View File

@ -9,7 +9,6 @@ static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
[NETDEV_MACVLAN_MODE_VEPA] = "vepa", [NETDEV_MACVLAN_MODE_VEPA] = "vepa",
[NETDEV_MACVLAN_MODE_BRIDGE] = "bridge", [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge",
[NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru", [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru",
[NETDEV_MACVLAN_MODE_SOURCE] = "source",
}; };
DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode); DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);

View File

@ -8,7 +8,6 @@ typedef enum MacVlanMode {
NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA, NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA,
NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE, NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE,
NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU, NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU,
NETDEV_MACVLAN_MODE_SOURCE = MACVLAN_MODE_SOURCE,
_NETDEV_MACVLAN_MODE_MAX, _NETDEV_MACVLAN_MODE_MAX,
_NETDEV_MACVLAN_MODE_INVALID = -1 _NETDEV_MACVLAN_MODE_INVALID = -1
} MacVlanMode; } MacVlanMode;

View File

@ -117,33 +117,3 @@ int load_os_release_pairs(const char *root, char ***ret) {
return load_env_file_pairs(f, p, ret); return load_env_file_pairs(f, p, ret);
} }
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret) {
_cleanup_strv_free_ char **os_release_pairs = NULL, **os_release_pairs_prefixed = NULL;
char **p, **q;
int r;
r = load_os_release_pairs(root, &os_release_pairs);
if (r < 0)
return r;
STRV_FOREACH_PAIR(p, q, os_release_pairs) {
char *line;
// We strictly return only the four main ID fields and ignore the rest
if (!STR_IN_SET(*p, "ID", "VERSION_ID", "BUILD_ID", "VARIANT_ID"))
continue;
ascii_strlower(*p);
line = strjoin(prefix, *p, "=", *q);
if (!line)
return -ENOMEM;
r = strv_consume(&os_release_pairs_prefixed, line);
if (r < 0)
return r;
}
*ret = TAKE_PTR(os_release_pairs_prefixed);
return 0;
}

View File

@ -10,4 +10,3 @@ int fopen_os_release(const char *root, char **ret_path, FILE **ret_file);
int parse_os_release(const char *root, ...) _sentinel_; int parse_os_release(const char *root, ...) _sentinel_;
int load_os_release_pairs(const char *root, char ***ret); int load_os_release_pairs(const char *root, char ***ret);
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);

View File

@ -4,7 +4,6 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h"
#include "install.h" #include "install.h"
#include "mkdir.h" #include "mkdir.h"
#include "rm-rf.h" #include "rm-rf.h"
@ -24,7 +23,6 @@ static void test_basic_mask_and_enable(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) == -ENOENT);
p = strjoina(root, "/usr/lib/systemd/system/a.service"); p = strjoina(root, "/usr/lib/systemd/system/a.service");
assert_se(write_string_file(p, assert_se(write_string_file(p,
@ -152,22 +150,6 @@ static void test_basic_mask_and_enable(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ALIAS); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ALIAS); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ALIAS); assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ALIAS);
/* Test masking with relative symlinks */
p = strjoina(root, "/usr/lib/systemd/system/e.service");
assert_se(symlink("../../../../../../dev/null", p) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", &state) >= 0 && state == UNIT_FILE_MASKED);
assert_se(unlink(p) == 0);
assert_se(symlink("/usr/../dev/null", p) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", NULL) >= 0);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "e.service", &state) >= 0 && state == UNIT_FILE_MASKED);
assert_se(unlink(p) == 0);
} }
static void test_linked_units(const char *root) { static void test_linked_units(const char *root) {

View File

@ -16,7 +16,7 @@ test_create_image() {
mask_supporting_services mask_supporting_services
../create-busybox-container $initdir/testsuite-13.nc-container ../create-busybox-container $initdir/testsuite-13.nc-container
initdir="$initdir/testsuite-13.nc-container" dracut_install nc ip md5sum initdir="$initdir/testsuite-13.nc-container" dracut_install nc ip
) )
} }

View File

@ -6,7 +6,6 @@ Id=
GVRP= GVRP=
[MACVLAN] [MACVLAN]
Mode= Mode=
SourceMACAddress=
[WireGuard] [WireGuard]
ListenPort= ListenPort=
PrivateKey= PrivateKey=
@ -15,7 +14,6 @@ FwMark=
FirewallMark= FirewallMark=
[MACVTAP] [MACVTAP]
Mode= Mode=
SourceMACAddress=
[Match] [Match]
Architecture= Architecture=
Host= Host=

View File

@ -60,18 +60,6 @@ function check_notification_socket {
systemd-nspawn --register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd" systemd-nspawn --register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd"
} }
function check_os_release {
local _cmd='. /tmp/os-release
if [ -n "${ID:+set}" ] && [ "${ID}" != "${container_host_id}" ]; then exit 1; fi
if [ -n "${VERSION_ID:+set}" ] && [ "${VERSION_ID}" != "${container_host_version_id}" ]; then exit 1; fi
if [ -n "${BUILD_ID:+set}" ] && [ "${BUILD_ID}" != "${container_host_build_id}" ]; then exit 1; fi
if [ -n "${VARIANT_ID:+set}" ] && [ "${VARIANT_ID}" != "${container_host_variant_id}" ]; then exit 1; fi
cd /tmp; (cd /run/host/usr/lib; md5sum os-release) | md5sum -c
'
systemd-nspawn --register=no -D /testsuite-13.nc-container --bind=/etc/os-release:/tmp/os-release /bin/sh -x -e -c "$_cmd"
}
function run { function run {
if [[ "$1" = "yes" && "$is_v2_supported" = "no" ]]; then if [[ "$1" = "yes" && "$is_v2_supported" = "no" ]]; then
printf "Unified cgroup hierarchy is not supported. Skipping.\n" >&2 printf "Unified cgroup hierarchy is not supported. Skipping.\n" >&2
@ -156,8 +144,6 @@ check_norbind
check_notification_socket check_notification_socket
check_os_release
for api_vfs_writable in yes no network; do for api_vfs_writable in yes no network; do
run no no $api_vfs_writable run no no $api_vfs_writable
run yes no $api_vfs_writable run yes no $api_vfs_writable