mirror of
https://github.com/systemd/systemd.git
synced 2025-03-03 16:58:37 +03:00
New directives PrivateIPC and IPCNamespacePath
This commit is contained in:
parent
54c2459d56
commit
a70581ffb5
@ -2693,6 +2693,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateMounts = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateIPC = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHome = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectSystem = '...';
|
||||
@ -2777,6 +2779,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s IPCNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s KillMode = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly i KillSignal = ...;
|
||||
@ -3194,6 +3198,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<!--property PrivateMounts is not documented!-->
|
||||
|
||||
<!--property PrivateIPC is not documented!-->
|
||||
|
||||
<!--property ProtectHome is not documented!-->
|
||||
|
||||
<!--property ProtectSystem is not documented!-->
|
||||
@ -3278,6 +3284,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
|
||||
<!--property IPCNamespacePath is not documented!-->
|
||||
|
||||
<!--property KillMode is not documented!-->
|
||||
|
||||
<!--property KillSignal is not documented!-->
|
||||
@ -3772,6 +3780,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateMounts"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateIPC"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHome"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectSystem"/>
|
||||
@ -3856,6 +3866,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
|
||||
@ -4454,6 +4466,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateMounts = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateIPC = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHome = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectSystem = '...';
|
||||
@ -4538,6 +4552,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s IPCNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s KillMode = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly i KillSignal = ...;
|
||||
@ -4983,6 +4999,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
|
||||
<!--property PrivateMounts is not documented!-->
|
||||
|
||||
<!--property PrivateIPC is not documented!-->
|
||||
|
||||
<!--property ProtectHome is not documented!-->
|
||||
|
||||
<!--property ProtectSystem is not documented!-->
|
||||
@ -5067,6 +5085,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
|
||||
<!--property IPCNamespacePath is not documented!-->
|
||||
|
||||
<!--property KillMode is not documented!-->
|
||||
|
||||
<!--property KillSignal is not documented!-->
|
||||
@ -5559,6 +5579,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateMounts"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateIPC"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHome"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectSystem"/>
|
||||
@ -5643,6 +5665,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
|
||||
@ -6143,6 +6167,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateMounts = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateIPC = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHome = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectSystem = '...';
|
||||
@ -6227,6 +6253,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s IPCNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s KillMode = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly i KillSignal = ...;
|
||||
@ -6600,6 +6628,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<!--property PrivateMounts is not documented!-->
|
||||
|
||||
<!--property PrivateIPC is not documented!-->
|
||||
|
||||
<!--property ProtectHome is not documented!-->
|
||||
|
||||
<!--property ProtectSystem is not documented!-->
|
||||
@ -6684,6 +6714,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
|
||||
<!--property IPCNamespacePath is not documented!-->
|
||||
|
||||
<!--property KillMode is not documented!-->
|
||||
|
||||
<!--property KillSignal is not documented!-->
|
||||
@ -7094,6 +7126,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateMounts"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateIPC"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHome"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectSystem"/>
|
||||
@ -7178,6 +7212,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
|
||||
@ -7799,6 +7835,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateMounts = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b PrivateIPC = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectHome = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s ProtectSystem = '...';
|
||||
@ -7883,6 +7921,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NetworkNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s IPCNamespacePath = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s KillMode = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly i KillSignal = ...;
|
||||
@ -8242,6 +8282,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
|
||||
<!--property PrivateMounts is not documented!-->
|
||||
|
||||
<!--property PrivateIPC is not documented!-->
|
||||
|
||||
<!--property ProtectHome is not documented!-->
|
||||
|
||||
<!--property ProtectSystem is not documented!-->
|
||||
@ -8326,6 +8368,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
|
||||
<!--property NetworkNamespacePath is not documented!-->
|
||||
|
||||
<!--property IPCNamespacePath is not documented!-->
|
||||
|
||||
<!--property KillMode is not documented!-->
|
||||
|
||||
<!--property KillSignal is not documented!-->
|
||||
@ -8722,6 +8766,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateMounts"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateIPC"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectHome"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ProtectSystem"/>
|
||||
@ -8806,6 +8852,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NetworkNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="IPCNamespacePath"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
|
||||
|
@ -1603,6 +1603,53 @@ BindReadOnlyPaths=/var/lib/systemd</programlisting>
|
||||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>PrivateIPC=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. If true, sets up a new IPC namespace for the executed processes.
|
||||
Each IPC namespace has its own set of System V IPC identifiers and its own POSIX message queue file system.
|
||||
This is useful to avoid name clash of IPC identifiers. Defaults to false. It is possible to run two or
|
||||
more units within the same private IPC namespace by using the <varname>JoinsNamespaceOf=</varname> directive,
|
||||
see <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
details.</para>
|
||||
|
||||
<para>Note that IPC namespacing does not have an effect on
|
||||
<constant>AF_UNIX</constant> sockets, which are the most common
|
||||
form of IPC used on Linux. Instead, <constant>AF_UNIX</constant>
|
||||
sockets in the file system are subject to mount namespacing, and
|
||||
those in the abstract namespace are subject to network namespacing.
|
||||
IPC namespacing only has an effect on SysV IPC (which is mostly
|
||||
legacy) as well as POSIX message queues (for which
|
||||
<constant>AF_UNIX</constant>/<constant>SOCK_SEQPACKET</constant>
|
||||
sockets are typically a better replacement). IPC namespacing also
|
||||
has no effect on POSIX shared memory (which is subject to mount
|
||||
namespacing) either. See
|
||||
<citerefentry><refentrytitle>ipc_namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
the details.</para>
|
||||
|
||||
<para>Note that the implementation of this setting might be impossible (for example if IPC namespaces are
|
||||
not available), and the unit should be written in a way that does not solely rely on this setting for
|
||||
security.</para>
|
||||
|
||||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>IPCNamespacePath=</varname></term>
|
||||
|
||||
<listitem><para>Takes an absolute file system path refererring to a Linux IPC namespace
|
||||
pseudo-file (i.e. a file like <filename>/proc/$PID/ns/ipc</filename> or a bind mount or symlink to
|
||||
one). When set the invoked processes are added to the network namespace referenced by that path. The
|
||||
path has to point to a valid namespace file at the moment the processes are forked off. If this
|
||||
option is used <varname>PrivateIPC=</varname> has no effect. If this option is used together with
|
||||
<varname>JoinsNamespaceOf=</varname> then it only has an effect if this unit is started before any of
|
||||
the listed units that have <varname>PrivateIPC=</varname> or
|
||||
<varname>IPCNamespacePath=</varname> configured, as otherwise the network namespace of those
|
||||
units is reused.</para>
|
||||
|
||||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>PrivateUsers=</varname></term>
|
||||
|
||||
@ -3585,7 +3632,7 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
|
||||
<row>
|
||||
<entry>226</entry>
|
||||
<entry><constant>EXIT_NAMESPACE</constant></entry>
|
||||
<entry>Failed to set up mount namespacing. See <varname>ReadOnlyPaths=</varname> and related settings above.</entry>
|
||||
<entry>Failed to set up mount, UTS, or IPC namespacing. See <varname>ReadOnlyPaths=</varname>, <varname>ProtectHostname=</varname>, <varname>PrivateIPC=</varname>, and related settings above.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>227</entry>
|
||||
|
@ -799,14 +799,16 @@
|
||||
|
||||
<listitem><para>For units that start processes (such as service units), lists one or more other units
|
||||
whose network and/or temporary file namespace to join. This only applies to unit types which support
|
||||
the <varname>PrivateNetwork=</varname>, <varname>NetworkNamespacePath=</varname> and
|
||||
the <varname>PrivateNetwork=</varname>, <varname>NetworkNamespacePath=</varname>,
|
||||
<varname>PrivateIPC=</varname>, <varname>IPCNamespacePath=</varname>, and
|
||||
<varname>PrivateTmp=</varname> directives (see
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
details). If a unit that has this setting set is started, its processes will see the same
|
||||
<filename>/tmp/</filename>, <filename>/var/tmp/</filename> and network namespace as one listed unit
|
||||
that is started. If multiple listed units are already started, it is not defined which namespace is
|
||||
joined. Note that this setting only has an effect if
|
||||
<varname>PrivateNetwork=</varname>/<varname>NetworkNamespacePath=</varname> and/or
|
||||
<filename>/tmp/</filename>, <filename>/var/tmp/</filename>, IPC namespace and network namespace as
|
||||
one listed unit that is started. If multiple listed units are already started, it is not defined
|
||||
which namespace is joined. Note that this setting only has an effect if
|
||||
<varname>PrivateNetwork=</varname>/<varname>NetworkNamespacePath=</varname>,
|
||||
<varname>PrivateIPC=</varname>/<varname>IPCNamespacePath=</varname> and/or
|
||||
<varname>PrivateTmp=</varname> is enabled for both the unit that joins the namespace and the unit
|
||||
whose namespace is joined.</para></listitem>
|
||||
</varlistentry>
|
||||
|
@ -1162,6 +1162,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_bool, offsetof(ExecContext, private_mounts), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PrivateIPC", "b", bus_property_get_bool, offsetof(ExecContext, private_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -1204,6 +1205,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
/* Obsolete/redundant properties: */
|
||||
SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||
@ -1753,6 +1755,9 @@ int bus_exec_context_set_transient_property(
|
||||
if (streq(name, "PrivateNetwork"))
|
||||
return bus_set_transient_bool(u, name, &c->private_network, message, flags, error);
|
||||
|
||||
if (streq(name, "PrivateIPC"))
|
||||
return bus_set_transient_bool(u, name, &c->private_ipc, message, flags, error);
|
||||
|
||||
if (streq(name, "PrivateUsers"))
|
||||
return bus_set_transient_bool(u, name, &c->private_users, message, flags, error);
|
||||
|
||||
@ -1873,6 +1878,9 @@ int bus_exec_context_set_transient_property(
|
||||
if (streq(name, "NetworkNamespacePath"))
|
||||
return bus_set_transient_path(u, name, &c->network_namespace_path, message, flags, error);
|
||||
|
||||
if (streq(name, "IPCNamespacePath"))
|
||||
return bus_set_transient_path(u, name, &c->ipc_namespace_path, message, flags, error);
|
||||
|
||||
if (streq(name, "SupplementaryGroups")) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
char **p;
|
||||
|
@ -3476,8 +3476,10 @@ static int close_remaining_fds(
|
||||
n_dont_close += n_fds;
|
||||
}
|
||||
|
||||
if (runtime)
|
||||
if (runtime) {
|
||||
append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket);
|
||||
append_socket_pair(dont_close, &n_dont_close, runtime->ipcns_storage_socket);
|
||||
}
|
||||
|
||||
if (dcreds) {
|
||||
if (dcreds->user)
|
||||
@ -3925,6 +3927,14 @@ static int exec_child(
|
||||
}
|
||||
}
|
||||
|
||||
if (context->ipc_namespace_path && runtime && runtime->ipcns_storage_socket[0] >= 0) {
|
||||
r = open_shareable_ns_path(runtime->ipcns_storage_socket, context->ipc_namespace_path, CLONE_NEWIPC);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_NAMESPACE;
|
||||
return log_unit_error_errno(unit, r, "Failed to open IPC namespace path %s: %m", context->ipc_namespace_path);
|
||||
}
|
||||
}
|
||||
|
||||
r = setup_input(context, params, socket_fd, named_iofds);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_STDIN;
|
||||
@ -4211,6 +4221,25 @@ static int exec_child(
|
||||
log_unit_warning(unit, "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring.");
|
||||
}
|
||||
|
||||
if ((context->private_ipc || context->ipc_namespace_path) && runtime && runtime->ipcns_storage_socket[0] >= 0) {
|
||||
|
||||
if (ns_type_supported(NAMESPACE_IPC)) {
|
||||
r = setup_shareable_ns(runtime->ipcns_storage_socket, CLONE_NEWIPC);
|
||||
if (r == -EPERM)
|
||||
log_unit_warning_errno(unit, r,
|
||||
"PrivateIPC=yes is configured, but IPC namespace setup failed, ignoring: %m");
|
||||
else if (r < 0) {
|
||||
*exit_status = EXIT_NAMESPACE;
|
||||
return log_unit_error_errno(unit, r, "Failed to set up IPC namespacing: %m");
|
||||
}
|
||||
} else if (context->ipc_namespace_path) {
|
||||
*exit_status = EXIT_NAMESPACE;
|
||||
return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"IPCNamespacePath= is not supported, refusing.");
|
||||
} else
|
||||
log_unit_warning(unit, "PrivateIPC=yes is configured, but the kernel does not support IPC namespaces, ignoring.");
|
||||
}
|
||||
|
||||
needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime);
|
||||
if (needs_mount_namespace) {
|
||||
_cleanup_free_ char *error_path = NULL;
|
||||
@ -4314,7 +4343,7 @@ static int exec_child(
|
||||
#endif
|
||||
|
||||
/* We repeat the fd closing here, to make sure that nothing is leaked from the PAM modules. Note that we are
|
||||
* more aggressive this time since socket_fd and the netns fds we don't need anymore. We do keep the exec_fd
|
||||
* more aggressive this time since socket_fd and the netns and ipcns fds we don't need anymore. We do keep the exec_fd
|
||||
* however if we have it as we want to keep it open until the final execve(). */
|
||||
|
||||
r = close_all_fds(keep_fds, n_keep_fds);
|
||||
@ -6057,6 +6086,7 @@ static ExecRuntime* exec_runtime_free(ExecRuntime *rt, bool destroy) {
|
||||
rt->tmp_dir = mfree(rt->tmp_dir);
|
||||
rt->var_tmp_dir = mfree(rt->var_tmp_dir);
|
||||
safe_close_pair(rt->netns_storage_socket);
|
||||
safe_close_pair(rt->ipcns_storage_socket);
|
||||
return mfree(rt);
|
||||
}
|
||||
|
||||
@ -6081,6 +6111,7 @@ static int exec_runtime_allocate(ExecRuntime **ret, const char *id) {
|
||||
*n = (ExecRuntime) {
|
||||
.id = TAKE_PTR(id_copy),
|
||||
.netns_storage_socket = { -1, -1 },
|
||||
.ipcns_storage_socket = { -1, -1 },
|
||||
};
|
||||
|
||||
*ret = n;
|
||||
@ -6093,6 +6124,7 @@ static int exec_runtime_add(
|
||||
char **tmp_dir,
|
||||
char **var_tmp_dir,
|
||||
int netns_storage_socket[2],
|
||||
int ipcns_storage_socket[2],
|
||||
ExecRuntime **ret) {
|
||||
|
||||
_cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL;
|
||||
@ -6101,7 +6133,7 @@ static int exec_runtime_add(
|
||||
assert(m);
|
||||
assert(id);
|
||||
|
||||
/* tmp_dir, var_tmp_dir, netns_storage_socket fds are donated on success */
|
||||
/* tmp_dir, var_tmp_dir, {net,ipc}ns_storage_socket fds are donated on success */
|
||||
|
||||
r = exec_runtime_allocate(&rt, id);
|
||||
if (r < 0)
|
||||
@ -6120,6 +6152,11 @@ static int exec_runtime_add(
|
||||
rt->netns_storage_socket[1] = TAKE_FD(netns_storage_socket[1]);
|
||||
}
|
||||
|
||||
if (ipcns_storage_socket) {
|
||||
rt->ipcns_storage_socket[0] = TAKE_FD(ipcns_storage_socket[0]);
|
||||
rt->ipcns_storage_socket[1] = TAKE_FD(ipcns_storage_socket[1]);
|
||||
}
|
||||
|
||||
rt->manager = m;
|
||||
|
||||
if (ret)
|
||||
@ -6136,7 +6173,7 @@ static int exec_runtime_make(
|
||||
ExecRuntime **ret) {
|
||||
|
||||
_cleanup_(namespace_cleanup_tmpdirp) char *tmp_dir = NULL, *var_tmp_dir = NULL;
|
||||
_cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 };
|
||||
_cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 }, ipcns_storage_socket[2] = { -1, -1 };
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -6144,7 +6181,7 @@ static int exec_runtime_make(
|
||||
assert(id);
|
||||
|
||||
/* It is not necessary to create ExecRuntime object. */
|
||||
if (!c->private_network && !c->private_tmp && !c->network_namespace_path) {
|
||||
if (!c->private_network && !c->private_ipc && !c->private_tmp && !c->network_namespace_path) {
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
@ -6163,7 +6200,12 @@ static int exec_runtime_make(
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_storage_socket, ret);
|
||||
if (c->private_ipc || c->ipc_namespace_path) {
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, ipcns_storage_socket) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_storage_socket, ipcns_storage_socket, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -6254,6 +6296,26 @@ int exec_runtime_serialize(const Manager *m, FILE *f, FDSet *fds) {
|
||||
fprintf(f, " netns-socket-1=%i", copy);
|
||||
}
|
||||
|
||||
if (rt->ipcns_storage_socket[0] >= 0) {
|
||||
int copy;
|
||||
|
||||
copy = fdset_put_dup(fds, rt->ipcns_storage_socket[0]);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
fprintf(f, " ipcns-socket-0=%i", copy);
|
||||
}
|
||||
|
||||
if (rt->ipcns_storage_socket[1] >= 0) {
|
||||
int copy;
|
||||
|
||||
copy = fdset_put_dup(fds, rt->ipcns_storage_socket[1]);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
fprintf(f, " ipcns-socket-1=%i", copy);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
@ -6335,6 +6397,28 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value,
|
||||
|
||||
safe_close(rt->netns_storage_socket[1]);
|
||||
rt->netns_storage_socket[1] = fdset_remove(fds, fd);
|
||||
|
||||
} else if (streq(key, "ipcns-socket-0")) {
|
||||
int fd;
|
||||
|
||||
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
|
||||
log_unit_debug(u, "Failed to parse ipcns socket value: %s", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
safe_close(rt->ipcns_storage_socket[0]);
|
||||
rt->ipcns_storage_socket[0] = fdset_remove(fds, fd);
|
||||
|
||||
} else if (streq(key, "ipcns-socket-1")) {
|
||||
int fd;
|
||||
|
||||
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
|
||||
log_unit_debug(u, "Failed to parse ipcns socket value: %s", value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
safe_close(rt->ipcns_storage_socket[1]);
|
||||
rt->ipcns_storage_socket[1] = fdset_remove(fds, fd);
|
||||
} else
|
||||
return 0;
|
||||
|
||||
@ -6358,7 +6442,7 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value,
|
||||
int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
|
||||
_cleanup_free_ char *tmp_dir = NULL, *var_tmp_dir = NULL;
|
||||
char *id = NULL;
|
||||
int r, fdpair[] = {-1, -1};
|
||||
int r, netns_fdpair[] = {-1, -1}, ipcns_fdpair[] = {-1, -1};
|
||||
const char *p, *v = value;
|
||||
size_t n;
|
||||
|
||||
@ -6401,13 +6485,13 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
|
||||
n = strcspn(v, " ");
|
||||
buf = strndupa(v, n);
|
||||
|
||||
r = safe_atoi(buf, &fdpair[0]);
|
||||
r = safe_atoi(buf, &netns_fdpair[0]);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-0=%s: %m", buf);
|
||||
if (!fdset_contains(fds, fdpair[0]))
|
||||
if (!fdset_contains(fds, netns_fdpair[0]))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
|
||||
"exec-runtime specification netns-socket-0= refers to unknown fd %d: %m", fdpair[0]);
|
||||
fdpair[0] = fdset_remove(fds, fdpair[0]);
|
||||
"exec-runtime specification netns-socket-0= refers to unknown fd %d: %m", netns_fdpair[0]);
|
||||
netns_fdpair[0] = fdset_remove(fds, netns_fdpair[0]);
|
||||
if (v[n] != ' ')
|
||||
goto finalize;
|
||||
p = v + n + 1;
|
||||
@ -6419,17 +6503,56 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
|
||||
|
||||
n = strcspn(v, " ");
|
||||
buf = strndupa(v, n);
|
||||
r = safe_atoi(buf, &fdpair[1]);
|
||||
|
||||
r = safe_atoi(buf, &netns_fdpair[1]);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-1=%s: %m", buf);
|
||||
if (!fdset_contains(fds, fdpair[1]))
|
||||
if (!fdset_contains(fds, netns_fdpair[1]))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
|
||||
"exec-runtime specification netns-socket-1= refers to unknown fd %d: %m", fdpair[1]);
|
||||
fdpair[1] = fdset_remove(fds, fdpair[1]);
|
||||
"exec-runtime specification netns-socket-1= refers to unknown fd %d: %m", netns_fdpair[1]);
|
||||
netns_fdpair[1] = fdset_remove(fds, netns_fdpair[1]);
|
||||
if (v[n] != ' ')
|
||||
goto finalize;
|
||||
p = v + n + 1;
|
||||
}
|
||||
|
||||
v = startswith(p, "ipcns-socket-0=");
|
||||
if (v) {
|
||||
char *buf;
|
||||
|
||||
n = strcspn(v, " ");
|
||||
buf = strndupa(v, n);
|
||||
|
||||
r = safe_atoi(buf, &ipcns_fdpair[0]);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Unable to parse exec-runtime specification ipcns-socket-0=%s: %m", buf);
|
||||
if (!fdset_contains(fds, ipcns_fdpair[0]))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
|
||||
"exec-runtime specification ipcns-socket-0= refers to unknown fd %d: %m", ipcns_fdpair[0]);
|
||||
ipcns_fdpair[0] = fdset_remove(fds, ipcns_fdpair[0]);
|
||||
if (v[n] != ' ')
|
||||
goto finalize;
|
||||
p = v + n + 1;
|
||||
}
|
||||
|
||||
v = startswith(p, "ipcns-socket-1=");
|
||||
if (v) {
|
||||
char *buf;
|
||||
|
||||
n = strcspn(v, " ");
|
||||
buf = strndupa(v, n);
|
||||
|
||||
r = safe_atoi(buf, &ipcns_fdpair[1]);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Unable to parse exec-runtime specification ipcns-socket-1=%s: %m", buf);
|
||||
if (!fdset_contains(fds, ipcns_fdpair[1]))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
|
||||
"exec-runtime specification ipcns-socket-1= refers to unknown fd %d: %m", ipcns_fdpair[1]);
|
||||
ipcns_fdpair[1] = fdset_remove(fds, ipcns_fdpair[1]);
|
||||
}
|
||||
|
||||
finalize:
|
||||
r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, fdpair, NULL);
|
||||
r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_fdpair, ipcns_fdpair, NULL);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to add exec-runtime: %m");
|
||||
return 0;
|
||||
|
@ -117,6 +117,9 @@ struct ExecRuntime {
|
||||
/* An AF_UNIX socket pair, that contains a datagram containing a file descriptor referring to the network
|
||||
* namespace. */
|
||||
int netns_storage_socket[2];
|
||||
|
||||
/* Like netns_storage_socket, but the file descriptor is referring to the IPC namespace. */
|
||||
int ipcns_storage_socket[2];
|
||||
};
|
||||
|
||||
typedef enum ExecDirectoryType {
|
||||
@ -280,6 +283,7 @@ struct ExecContext {
|
||||
bool private_devices;
|
||||
bool private_users;
|
||||
bool private_mounts;
|
||||
bool private_ipc;
|
||||
bool protect_kernel_tunables;
|
||||
bool protect_kernel_modules;
|
||||
bool protect_kernel_logs;
|
||||
@ -314,6 +318,7 @@ struct ExecContext {
|
||||
Set *address_families;
|
||||
|
||||
char *network_namespace_path;
|
||||
char *ipc_namespace_path;
|
||||
|
||||
ExecDirectory directories[_EXEC_DIRECTORY_TYPE_MAX];
|
||||
ExecPreserveMode runtime_directory_preserve_mode;
|
||||
|
@ -133,10 +133,12 @@ $1.ProtectKernelLogs, config_parse_bool,
|
||||
$1.ProtectClock, config_parse_bool, 0, offsetof($1, exec_context.protect_clock)
|
||||
$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups)
|
||||
$1.NetworkNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.network_namespace_path)
|
||||
$1.IPCNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.ipc_namespace_path)
|
||||
$1.LogNamespace, config_parse_log_namespace, 0, offsetof($1, exec_context)
|
||||
$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
|
||||
$1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users)
|
||||
$1.PrivateMounts, config_parse_bool, 0, offsetof($1, exec_context.private_mounts)
|
||||
$1.PrivateIPC, config_parse_bool, 0, offsetof($1, exec_context.private_ipc)
|
||||
$1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context.protect_system)
|
||||
$1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context.protect_home)
|
||||
$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context.mount_flags)
|
||||
|
@ -1552,6 +1552,14 @@ static int socket_address_listen_in_cgroup(
|
||||
return log_unit_error_errno(UNIT(s), r, "Failed to open network namespace path %s: %m", s->exec_context.network_namespace_path);
|
||||
}
|
||||
|
||||
if (s->exec_context.ipc_namespace_path &&
|
||||
s->exec_runtime &&
|
||||
s->exec_runtime->ipcns_storage_socket[0] >= 0) {
|
||||
r = open_shareable_ns_path(s->exec_runtime->netns_storage_socket, s->exec_context.network_namespace_path, CLONE_NEWIPC);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(UNIT(s), r, "Failed to open IPC namespace path %s: %m", s->exec_context.ipc_namespace_path);
|
||||
}
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
|
||||
return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m");
|
||||
|
||||
|
@ -882,6 +882,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
"ProtectProc",
|
||||
"ProcSubset",
|
||||
"NetworkNamespacePath",
|
||||
"IPCNamespacePath",
|
||||
"LogNamespace"))
|
||||
return bus_append_string(m, field, eq);
|
||||
|
||||
@ -894,6 +895,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
"PrivateNetwork",
|
||||
"PrivateUsers",
|
||||
"PrivateMounts",
|
||||
"PrivateIPC",
|
||||
"NoNewPrivileges",
|
||||
"SyslogLevelPrefix",
|
||||
"MemoryDenyWriteExecute",
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/magic.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
|
@ -111,6 +111,7 @@ IOWriteIOPSMax=
|
||||
IPAccounting=
|
||||
IPAddressAllow=
|
||||
IPAddressDeny=
|
||||
IPCNamespacePath=
|
||||
IPTOS=
|
||||
IPTTL=
|
||||
IgnoreOnIsolate=
|
||||
@ -857,6 +858,7 @@ PivotRoot=
|
||||
Port=
|
||||
PowerKeyIgnoreInhibited=
|
||||
Private=
|
||||
PrivateIPC=
|
||||
PrivateDevices=
|
||||
PrivateNetwork=
|
||||
PrivateTmp=
|
||||
|
Loading…
x
Reference in New Issue
Block a user