mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
systemd-nspawn: Allow setting ambient capability set
The old code was only able to pass the value 0 for the inheritable and ambient capability set when a non-root user was specified. However, sometimes it is useful to run a program in its own container with a user specification and some capabilities set. This is needed when the capabilities cannot be provided by file capabilities (because the file system is mounted with MS_NOSUID for additional security). This commit introduces the option --ambient-capability and the config file option AmbientCapability=. Both are used in a similar way to the existing Capability= setting. It changes the inheritable and ambient set (which is 0 by default). The code also checks that the settings for the bounding set (as defined by Capability= and DropCapability=) and the setting for the ambient set (as defined by AmbientCapability=) are compatible. Otherwise, the operation would fail in any way. Due to the current use of -1 to indicate no support for ambient capability set the special value "all" cannot be supported. Also, the setting of ambient capability is restricted to running a single program in the container payload.
This commit is contained in:
parent
bf20d93750
commit
88fc9c9bad
@ -1002,7 +1002,11 @@
|
||||
If the special value <literal>all</literal> is passed, all capabilities are retained.</para>
|
||||
|
||||
<para>If the special value of <literal>help</literal> is passed, the program will print known
|
||||
capability names and exit.</para></listitem>
|
||||
capability names and exit.</para>
|
||||
|
||||
<para>This option sets the bounding set of capabilities which
|
||||
also limits the ambient capabilities as given with the
|
||||
<option>--ambient-capability=</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -1014,7 +1018,32 @@
|
||||
above).</para>
|
||||
|
||||
<para>If the special value of <literal>help</literal> is passed, the program will print known
|
||||
capability names and exit.</para></listitem>
|
||||
capability names and exit.</para>
|
||||
|
||||
<para>This option sets the bounding set of capabilities which
|
||||
also limits the ambient capabilities as given with the
|
||||
<option>--ambient-capability=</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--ambient-capability=</option></term>
|
||||
|
||||
<listitem><para>Specify one or more additional capabilities to
|
||||
pass in the inheritable and ambient set to the program started
|
||||
within the container. The value <literal>all</literal> is not
|
||||
supported for this setting.</para>
|
||||
|
||||
<para>All capabilities specified here must be in the set
|
||||
allowed with the <option>--capability=</option> and
|
||||
<option>--drop-capability=</option> options. Otherwise, an
|
||||
error message will be shown.</para>
|
||||
|
||||
<para>This option cannot be combined with the boot mode of the
|
||||
container (as requested via <option>--boot</option>).</para>
|
||||
|
||||
<para>If the special value of <literal>help</literal> is
|
||||
passed, the program will print known capability names and
|
||||
exit.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -190,7 +190,34 @@
|
||||
<filename>/run/system/nspawn/</filename> (see above). On the
|
||||
other hand, <varname>DropCapability=</varname> takes effect in
|
||||
all cases. If the special value <literal>all</literal> is passed, all
|
||||
capabilities are retained (or dropped).</para></listitem>
|
||||
capabilities are retained (or dropped).</para>
|
||||
<para>These settings change the bounding set of capabilities which
|
||||
also limits the ambient capabilities as given with the
|
||||
<varname>AmbientCapability=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>AmbientCapability=</varname></term>
|
||||
<listitem><para>Takes a space-separated list of Linux process
|
||||
capabilities (see
|
||||
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for details). The <varname>AmbientCapability=</varname> setting
|
||||
specifies capability which will be passed to to started program
|
||||
in the inheritable and ambient capability sets. This will grant
|
||||
these capabilities to this process. This setting correspond to
|
||||
the <option>--ambient-capability=</option> command line switch.
|
||||
</para>
|
||||
|
||||
<para>The value <literal>all</literal> is not supported for this
|
||||
setting.</para>
|
||||
|
||||
<para>The setting of <varname>AmbientCapability=</varname> must
|
||||
be covered by the bounding set settings which were established by
|
||||
<varname>Capability=</varname> and <varname>DropCapability=</varname>.
|
||||
</para>
|
||||
|
||||
<para>Note that <varname>AmbientCapability=</varname> is a privileged
|
||||
setting (see above).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -25,6 +25,7 @@ Exec.Parameters, config_parse_strv, 0, of
|
||||
Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
|
||||
Exec.User, config_parse_string, 0, offsetof(Settings, user)
|
||||
Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
|
||||
Exec.AmbientCapability, config_parse_capability, 0, offsetof(Settings, ambient_capability)
|
||||
Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
|
||||
Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
|
||||
Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
|
||||
|
@ -157,6 +157,7 @@ typedef struct Settings {
|
||||
char *user;
|
||||
uint64_t capability;
|
||||
uint64_t drop_capability;
|
||||
uint64_t ambient_capability;
|
||||
int kill_signal;
|
||||
unsigned long personality;
|
||||
sd_id128_t machine_id;
|
||||
|
@ -165,6 +165,7 @@ static uint64_t arg_caps_retain =
|
||||
(1ULL << CAP_SYS_PTRACE) |
|
||||
(1ULL << CAP_SYS_RESOURCE) |
|
||||
(1ULL << CAP_SYS_TTY_CONFIG);
|
||||
static uint64_t arg_caps_ambient = 0;
|
||||
static CapabilityQuintet arg_full_capabilities = CAPABILITY_QUINTET_NULL;
|
||||
static CustomMount *arg_custom_mounts = NULL;
|
||||
static size_t arg_n_custom_mounts = 0;
|
||||
@ -379,6 +380,9 @@ static int help(void) {
|
||||
" --capability=CAP In addition to the default, retain specified\n"
|
||||
" capability\n"
|
||||
" --drop-capability=CAP Drop the specified capability from the default set\n"
|
||||
" --ambient-capability=CAP\n"
|
||||
" Sets the specified capability for the started\n"
|
||||
" process. Not useful if booting a machine.\n"
|
||||
" --no-new-privileges Set PR_SET_NO_NEW_PRIVS flag for container payload\n"
|
||||
" --system-call-filter=LIST|~LIST\n"
|
||||
" Permit/prohibit specific system calls\n"
|
||||
@ -648,6 +652,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_UUID,
|
||||
ARG_READ_ONLY,
|
||||
ARG_CAPABILITY,
|
||||
ARG_AMBIENT_CAPABILITY,
|
||||
ARG_DROP_CAPABILITY,
|
||||
ARG_LINK_JOURNAL,
|
||||
ARG_BIND,
|
||||
@ -709,6 +714,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "uuid", required_argument, NULL, ARG_UUID },
|
||||
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
|
||||
{ "capability", required_argument, NULL, ARG_CAPABILITY },
|
||||
{ "ambient-capability", required_argument, NULL, ARG_AMBIENT_CAPABILITY },
|
||||
{ "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY },
|
||||
{ "no-new-privileges", required_argument, NULL, ARG_NO_NEW_PRIVILEGES },
|
||||
{ "link-journal", required_argument, NULL, ARG_LINK_JOURNAL },
|
||||
@ -1018,6 +1024,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_settings_mask |= SETTING_READ_ONLY;
|
||||
break;
|
||||
|
||||
case ARG_AMBIENT_CAPABILITY: {
|
||||
uint64_t m;
|
||||
r = parse_capability_spec(optarg, &m);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
arg_caps_ambient |= m;
|
||||
arg_settings_mask |= SETTING_CAPABILITY;
|
||||
break;
|
||||
}
|
||||
case ARG_CAPABILITY:
|
||||
case ARG_DROP_CAPABILITY: {
|
||||
uint64_t m;
|
||||
@ -1760,6 +1775,17 @@ static int verify_arguments(void) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--port= is not supported, compiled without libiptc support.");
|
||||
#endif
|
||||
|
||||
if (arg_caps_ambient) {
|
||||
if (arg_caps_ambient == (uint64_t)-1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "AmbientCapability= does not support the value all.");
|
||||
|
||||
if ((arg_caps_ambient & arg_caps_retain) != arg_caps_ambient)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "AmbientCapability= setting is not fully covered by Capability= setting.");
|
||||
|
||||
if (arg_start_mode == START_BOOT)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "AmbientCapability= setting is not useful for boot mode.");
|
||||
}
|
||||
|
||||
r = custom_mount_check_all();
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2622,13 +2648,13 @@ static int drop_capabilities(uid_t uid) {
|
||||
q.effective = uid == 0 ? q.bounding : 0;
|
||||
|
||||
if (q.inheritable == (uint64_t) -1)
|
||||
q.inheritable = uid == 0 ? q.bounding : 0;
|
||||
q.inheritable = uid == 0 ? q.bounding : arg_caps_ambient;
|
||||
|
||||
if (q.permitted == (uint64_t) -1)
|
||||
q.permitted = uid == 0 ? q.bounding : 0;
|
||||
q.permitted = uid == 0 ? q.bounding : arg_caps_ambient;
|
||||
|
||||
if (q.ambient == (uint64_t) -1 && ambient_capabilities_supported())
|
||||
q.ambient = 0;
|
||||
q.ambient = arg_caps_ambient;
|
||||
|
||||
if (capability_quintet_mangle(&q))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Cannot set capabilities that are not in the current bounding set.");
|
||||
@ -2637,9 +2663,9 @@ static int drop_capabilities(uid_t uid) {
|
||||
q = (CapabilityQuintet) {
|
||||
.bounding = arg_caps_retain,
|
||||
.effective = uid == 0 ? arg_caps_retain : 0,
|
||||
.inheritable = uid == 0 ? arg_caps_retain : 0,
|
||||
.permitted = uid == 0 ? arg_caps_retain : 0,
|
||||
.ambient = ambient_capabilities_supported() ? 0 : (uint64_t) -1,
|
||||
.inheritable = uid == 0 ? arg_caps_retain : arg_caps_ambient,
|
||||
.permitted = uid == 0 ? arg_caps_retain : arg_caps_ambient,
|
||||
.ambient = ambient_capabilities_supported() ? arg_caps_ambient : (uint64_t) -1,
|
||||
};
|
||||
|
||||
/* If we're not using OCI, proceed with mangled capabilities (so we don't error out)
|
||||
@ -4070,6 +4096,7 @@ static int merge_settings(Settings *settings, const char *path) {
|
||||
if ((arg_settings_mask & SETTING_CAPABILITY) == 0) {
|
||||
uint64_t plus, minus;
|
||||
uint64_t network_minus = 0;
|
||||
uint64_t ambient;
|
||||
|
||||
/* Note that we copy both the simple plus/minus caps here, and the full quintet from the
|
||||
* Settings structure */
|
||||
@ -4101,6 +4128,12 @@ static int merge_settings(Settings *settings, const char *path) {
|
||||
else
|
||||
arg_full_capabilities = settings->full_capabilities;
|
||||
}
|
||||
|
||||
ambient = settings->ambient_capability;
|
||||
if (!arg_settings_trusted && ambient != 0)
|
||||
log_warning("Ignoring AmbientCapability= setting, file %s is not trusted.", path);
|
||||
else
|
||||
arg_caps_ambient |= ambient;
|
||||
}
|
||||
|
||||
if ((arg_settings_mask & SETTING_KILL_SIGNAL) == 0 &&
|
||||
|
Loading…
Reference in New Issue
Block a user