smack: introduce new SmackProcessLabel option

In service file, if the file has some of special SMACK label in
ExecStart= and systemd has no permission for the special SMACK label
then permission error will occurred. To resolve this, systemd should
be able to set its SMACK label to something accessible of ExecStart=.
So introduce new SmackProcessLabel. If label is specified with
SmackProcessLabel= then the child systemd will set its label to
that. To successfully execute the ExecStart=, accessible label should
be specified with SmackProcessLabel=.
Additionally, by SMACK policy, if the file in ExecStart= has no
SMACK64EXEC then the executed process will have given label by
SmackProcessLabel=. But if the file has SMACK64EXEC then the
SMACK64EXEC label will be overridden.

[zj: reword man page]
This commit is contained in:
WaLyong Cho 2014-11-24 20:46:20 +09:00 committed by Zbigniew Jędrzejewski-Szmek
parent 8086ffacdb
commit 2ca620c4ed
10 changed files with 140 additions and 2 deletions

View File

@ -1137,6 +1137,35 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SmackProcessLabel=</varname></term>
<listitem><para>Takes a
<option>SMACK64</option> security
label as argument. The process
executed by the unit will be started
under this label and SMACK will decide
whether the processes is allowed to
run or not based on it. The process
will continue to run under the label
specified here unless the executable
has its own
<option>SMACK64EXEC</option> label, in
which case the process will transition
to run under that label. When not
specified, the label that systemd is
running under is used. This directive
is ignored if SMACK is
disabled.</para>
<para>The value may be prefixed by
<literal>-</literal>, in which case
all errors will be ignored. An empty
value may be specified to unset
previous assignments.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>IgnoreSIGPIPE=</varname></term>

View File

@ -508,6 +508,24 @@ static int property_get_apparmor_profile(
return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
}
static int property_get_smack_process_label(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
ExecContext *c = userdata;
assert(bus);
assert(reply);
assert(c);
return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
}
static int property_get_personality(
sd_bus *bus,
const char *path,
@ -636,6 +654,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),

View File

@ -83,6 +83,7 @@
#include "af-list.h"
#include "mkdir.h"
#include "apparmor-util.h"
#include "smack-util.h"
#include "bus-kernel.h"
#include "label.h"
@ -1618,6 +1619,16 @@ static int exec_child(ExecCommand *command,
}
}
#ifdef HAVE_SMACK
if (context->smack_process_label) {
err = mac_smack_apply_pid(0, context->smack_process_label);
if (err < 0) {
*error = EXIT_SMACK_PROCESS_LABEL;
return err;
}
}
#endif
if (context->user) {
err = enforce_user(context, uid);
if (err < 0) {

View File

@ -142,6 +142,9 @@ struct ExecContext {
bool apparmor_profile_ignore;
char *apparmor_profile;
bool smack_process_label_ignore;
char *smack_process_label;
char **read_write_dirs, **read_only_dirs, **inaccessible_dirs;
unsigned long mount_flags;

View File

@ -95,8 +95,11 @@ m4_ifdef(`HAVE_SELINUX',
`$1.SELinuxContext, config_parse_exec_selinux_context, 0, offsetof($1, exec_context)',
`$1.SELinuxContext, config_parse_warn_compat, 0, 0')
m4_ifdef(`HAVE_APPARMOR',
`$1.AppArmorProfile, config_parse_exec_apparmor_profile,0, offsetof($1, exec_context)',
`$1.AppArmorProfile, config_parse_warn_compat, 0, 0')'
`$1.AppArmorProfile, config_parse_exec_apparmor_profile, 0, offsetof($1, exec_context)',
`$1.AppArmorProfile, config_parse_warn_compat, 0, 0')
m4_ifdef(`HAVE_SMACK',
`$1.SmackProcessLabel, config_parse_exec_smack_process_label, 0, offsetof($1, exec_context)',
`$1.SmackProcessLabel, config_parse_warn_compat, 0, 0')'
)m4_dnl
m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill)

View File

@ -1313,6 +1313,56 @@ int config_parse_exec_apparmor_profile(
return 0;
}
int config_parse_exec_smack_process_label(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
Unit *u = userdata;
bool ignore;
char *k;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
free(c->smack_process_label);
c->smack_process_label = NULL;
c->smack_process_label_ignore = false;
return 0;
}
if (rvalue[0] == '-') {
ignore = true;
rvalue++;
} else
ignore = false;
r = unit_name_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to resolve specifiers, ignoring: %s", strerror(-r));
return 0;
}
free(c->smack_process_label);
c->smack_process_label = k;
c->smack_process_label_ignore = ignore;
return 0;
}
int config_parse_timer(const char *unit,
const char *filename,
unsigned line,

View File

@ -94,6 +94,7 @@ int config_parse_job_mode_isolate(const char *unit, const char *filename, unsign
int config_parse_exec_selinux_context(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_personality(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_apparmor_profile(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_smack_process_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_address_families(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_runtime_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_set_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);

View File

@ -78,6 +78,7 @@ typedef enum ExitStatus {
EXIT_MAKE_STARTER,
EXIT_CHOWN,
EXIT_BUS_ENDPOINT,
EXIT_SMACK_PROCESS_LABEL,
} ExitStatus;
typedef enum ExitStatusLevel {

View File

@ -25,6 +25,7 @@
#include "util.h"
#include "path-util.h"
#include "fileio.h"
#include "smack-util.h"
#define SMACK_FLOOR_LABEL "_"
@ -123,6 +124,25 @@ int mac_smack_apply_ip_in_fd(int fd, const char *label) {
return r;
}
int mac_smack_apply_pid(pid_t pid, const char *label) {
int r = 0;
const char *p;
assert(label);
#ifdef HAVE_SMACK
if (!mac_smack_use())
return 0;
p = procfs_file_alloca(pid, "attr/current");
r = write_string_file(p, label);
if (r < 0)
return r;
#endif
return r;
}
int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
int r = 0;

View File

@ -31,5 +31,6 @@ int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
int mac_smack_apply(const char *path, const char *label);
int mac_smack_apply_fd(int fd, const char *label);
int mac_smack_apply_pid(pid_t pid, const char *label);
int mac_smack_apply_ip_in_fd(int fd, const char *label);
int mac_smack_apply_ip_out_fd(int fd, const char *label);