exec: properly apply capability bounding set, add inverted bounding sets

This commit is contained in:
Lennart Poettering 2011-03-18 03:13:15 +01:00
parent 893844ed43
commit 260abb780a
6 changed files with 101 additions and 30 deletions

17
TODO
View File

@ -23,23 +23,26 @@ F15:
* 0595f9a1c182a84581749823ef47c5f292e545f9 is borked, freezes shutdown
(path: after installing inotify watches, recheck file again to fix race)
* capability_bounding_set_drop not used
* rework syslog.service being up logic in PID 1
* rsyslog.service should hook itself into syslog.target?
* syslog.target should be pulled in by multi-user.target?
* pull in .service from meta .targers AND vice versa too. i.e. syslog.target ←→ rsyslog.service, rpcbind similarly
* drop Names= option? Symlinks only should be used. We don't want to need to read all service files.
Features:
* hide passwords on TAB
* add switch to systemctl to show enabled but not running services. Or
another switch that shows service that have been running since
booting but aren't running anymore.
* reuse mkdtemp namespace dirs in /tmp?
* don't strip facility from kmsg log messages as soon as that is possible.
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=9d90c8d9cde929cbc575098e825d7c29d9f45054
* recreate systemd'd D-Bus private socket file on SIGUSR2
* recreate systemd's D-Bus private socket file on SIGUSR2
* be more specific what failed:
Unmounting file systems.

View File

@ -597,16 +597,34 @@
</varlistentry>
<varlistentry>
<term><varname>Capabilities=</varname></term>
<listitem><para>Controls the
<term><varname>CapabilityBoundingSet=</varname></term>
<listitem><para>Controls which
capabilities to include in the
capability bounding set for the
executed process. See
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
set for the executed process. Take a
capability string as described in
<citerefentry><refentrytitle>cap_from_text</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Note that this capability set is
usually influenced by the capabilities
attached to the executed
file.</para></listitem>
for details. Takes a whitespace
seperated list of capability names as
read by
<citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Capabilities listed will be included
in the bounding set, all others are
removed. If the list of capabilities
is prefixed with ~ all but the listed
capabilities will be included, the
effect of this assignment
inverted. Note that this option does
not actually set or unset any
capabilities in the effective,
permitted or inherited capability
sets. That's what
<varname>Capabilities=</varname> is
for. If this option is not used the
capability bounding set is not
modified on process execution, hence
no limits on the capabilities of the
process are enforced.</para></listitem>
</varlistentry>
<varlistentry>
@ -625,16 +643,21 @@
</varlistentry>
<varlistentry>
<term><varname>CapabilityBoundingSetDrop=</varname></term>
<term><varname>Capabilities=</varname></term>
<listitem><para>Controls the
capability bounding set drop set for
the executed process. See
<citerefentry><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details. Takes a list of
capability names as read by
<citerefentry><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
set for the executed process. Take a
capability string describing the
effective, permitted and inherited
capability sets as documented in
<citerefentry><refentrytitle>cap_from_text</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
Note that these capability sets are
usually influenced by the capabilities
attached to the executed file. Due to
that
<varname>CapabilityBoundingSet=</varname>
is probably the much more useful
setting.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -234,6 +234,24 @@ int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const ch
return 0;
}
int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
uint64_t normal, inverted;
assert(m);
assert(i);
assert(property);
assert(c);
/* We store this negated internally, to match the kernel, bu
* we expose it normalized. */
normal = *(uint64_t*) data;
inverted = ~normal;
return bus_property_append_uint64(m, i, property, &inverted);
}
int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data) {
ExecContext *c = data;
char *t = NULL;

View File

@ -131,7 +131,7 @@
{ interface, "SyslogLevelPrefix", bus_property_append_bool, "b", &(context).syslog_level_prefix }, \
{ interface, "Capabilities", bus_execute_append_capabilities, "s",&(context) }, \
{ interface, "SecureBits", bus_property_append_int, "i", &(context).secure_bits }, \
{ interface, "CapabilityBoundingSetDrop", bus_property_append_uint64, "t", &(context).capability_bounding_set_drop }, \
{ interface, "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", &(context).capability_bounding_set_drop }, \
{ interface, "User", bus_property_append_string, "s", (context).user }, \
{ interface, "Group", bus_property_append_string, "s", (context).group }, \
{ interface, "SupplementaryGroups", bus_property_append_strv, "as", (context).supplementary_groups }, \
@ -167,6 +167,7 @@ int bus_execute_append_cpu_sched_priority(Manager *m, DBusMessageIter *i, const
int bus_execute_append_affinity(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_timer_slack_nsec(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_capabilities(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_capability_bs(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_rlimits(Manager *m, DBusMessageIter *i, const char *property, void *data);
int bus_execute_append_command(Manager *m, DBusMessageIter *u, const char *property, void *data);
int bus_execute_append_kill_mode(Manager *m, DBusMessageIter *i, const char *property, void *data);

View File

@ -1249,6 +1249,15 @@ int exec_spawn(ExecCommand *command,
}
}
if (context->capability_bounding_set_drop)
for (i = 0; i <= CAP_LAST_CAP; i++)
if (context->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i)) {
if (prctl(PR_CAPBSET_DROP, i) < 0) {
r = EXIT_CAPABILITIES;
goto fail_child;
}
}
if (context->user)
if (enforce_user(context, uid) < 0) {
r = EXIT_USER;
@ -1664,15 +1673,15 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
(c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
if (c->capability_bounding_set_drop) {
fprintf(f, "%sCapabilityBoundingSetDrop:", prefix);
fprintf(f, "%sCapabilityBoundingSet:", prefix);
for (i = 0; i <= CAP_LAST_CAP; i++)
if (c->capability_bounding_set_drop & (1 << i)) {
if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i))) {
char *t;
if ((t = cap_to_name(i))) {
fprintf(f, " %s", t);
free(t);
cap_free(t);
}
}

View File

@ -852,12 +852,24 @@ static int config_parse_bounding_set(
char *w;
size_t l;
char *state;
bool invert = false;
uint64_t sum = 0;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (rvalue[0] == '~') {
invert = true;
rvalue++;
}
/* Note that we store this inverted internally, since the
* kernel wants it like this. But we actually expose it
* non-inverted everywhere to have a fully normalized
* interface. */
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
char *t;
int r;
@ -874,9 +886,14 @@ static int config_parse_bounding_set(
return 0;
}
c->capability_bounding_set_drop |= 1 << cap;
sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
}
if (invert)
c->capability_bounding_set_drop |= sum;
else
c->capability_bounding_set_drop |= ~sum;
return 0;
}
@ -1772,7 +1789,7 @@ static int load_from_path(Unit *u, const char *path) {
{ "SyslogLevelPrefix", config_parse_bool, &(context).syslog_level_prefix, section }, \
{ "Capabilities", config_parse_capabilities, &(context), section }, \
{ "SecureBits", config_parse_secure_bits, &(context), section }, \
{ "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context), section }, \
{ "CapabilityBoundingSet", config_parse_bounding_set, &(context), section }, \
{ "TimerSlackNSec", config_parse_timer_slack_nsec,&(context), section }, \
{ "LimitCPU", config_parse_limit, &(context).rlimit[RLIMIT_CPU], section }, \
{ "LimitFSIZE", config_parse_limit, &(context).rlimit[RLIMIT_FSIZE], section }, \