mirror of
https://github.com/systemd/systemd.git
synced 2024-11-27 12:13:33 +08:00
core: add Personality= option for units to set the personality for spawned processes
This commit is contained in:
parent
49a356c258
commit
ac45f971a1
@ -1063,9 +1063,9 @@
|
||||
is triggered, instead of terminating
|
||||
the process immediately. Takes an
|
||||
error name such as
|
||||
<literal>EPERM</literal>,
|
||||
<literal>EACCES</literal> or
|
||||
<literal>EUCLEAN</literal>. When this
|
||||
<constant>EPERM</constant>,
|
||||
<constant>EACCES</constant> or
|
||||
<constant>EUCLEAN</constant>. When this
|
||||
setting is not used, or when the empty
|
||||
string is assigned, the process will be
|
||||
terminated immediately when the filter
|
||||
@ -1080,12 +1080,12 @@
|
||||
identifiers to include in the system
|
||||
call filter. The known architecture
|
||||
identifiers are
|
||||
<literal>x86</literal>,
|
||||
<literal>x86-64</literal>,
|
||||
<literal>x32</literal>,
|
||||
<literal>arm</literal> as well as the
|
||||
<constant>x86</constant>,
|
||||
<constant>x86-64</constant>,
|
||||
<constant>x32</constant>,
|
||||
<constant>arm</constant> as well as the
|
||||
special identifier
|
||||
<literal>native</literal>. Only system
|
||||
<constant>native</constant>. Only system
|
||||
calls of the specified architectures
|
||||
will be permitted to processes of this
|
||||
unit. This is an effective way to
|
||||
@ -1094,20 +1094,37 @@
|
||||
example to prohibit execution of
|
||||
32-bit x86 binaries on 64-bit x86-64
|
||||
systems. The special
|
||||
<literal>native</literal> identifier
|
||||
<constant>native</constant> identifier
|
||||
implicitly maps to the native
|
||||
architecture of the system (or more
|
||||
strictly: to the architecture the
|
||||
system manager is compiled for). Note
|
||||
that setting this option to a
|
||||
non-empty list implies that
|
||||
<literal>native</literal> is included
|
||||
<constant>native</constant> is included
|
||||
too. By default, this option is set to
|
||||
the empty list, i.e. no architecture
|
||||
system call filtering is
|
||||
applied.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Personality=</varname></term>
|
||||
|
||||
<listitem><para>Controls which
|
||||
kernel architecture
|
||||
<citerefentry><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
shall report, when invoked by unit
|
||||
processes. Takes one of
|
||||
<constant>x86</constant> and
|
||||
<constant>x86-64</constant>. This is
|
||||
useful when running 32bit services on
|
||||
a 64bit host system. If not specified
|
||||
the personality is left unmodified and
|
||||
thus reflects the personality of the
|
||||
host system's
|
||||
kernel.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -482,6 +482,24 @@ static int property_get_selinux_context(
|
||||
return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
|
||||
}
|
||||
|
||||
static int property_get_personality(
|
||||
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, "s", personality_to_string(c->personality));
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -547,6 +565,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <linux/oom.h>
|
||||
#include <sys/poll.h>
|
||||
#include <glob.h>
|
||||
#include <sys/personality.h>
|
||||
#include <libgen.h>
|
||||
#undef basename
|
||||
|
||||
@ -1372,6 +1373,13 @@ int exec_spawn(ExecCommand *command,
|
||||
goto fail_child;
|
||||
}
|
||||
|
||||
if (context->personality != 0xffffffffUL)
|
||||
if (personality(context->personality) < 0) {
|
||||
err = -errno;
|
||||
r = EXIT_PERSONALITY;
|
||||
goto fail_child;
|
||||
}
|
||||
|
||||
if (context->utmp_id)
|
||||
utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
|
||||
|
||||
@ -1683,6 +1691,7 @@ void exec_context_init(ExecContext *c) {
|
||||
c->syslog_level_prefix = true;
|
||||
c->ignore_sigpipe = true;
|
||||
c->timer_slack_nsec = (nsec_t) -1;
|
||||
c->personality = 0xffffffffUL;
|
||||
}
|
||||
|
||||
void exec_context_done(ExecContext *c) {
|
||||
@ -2130,6 +2139,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
|
||||
"%sSELinuxContext: %s%s\n",
|
||||
prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
|
||||
|
||||
if (c->personality != 0xffffffffUL)
|
||||
fprintf(f,
|
||||
"%sPersonality: %s\n",
|
||||
prefix, strna(personality_to_string(c->personality)));
|
||||
|
||||
if (c->syscall_filter) {
|
||||
#ifdef HAVE_SECCOMP
|
||||
Iterator j;
|
||||
|
@ -168,6 +168,8 @@ struct ExecContext {
|
||||
* don't enter a trigger loop. */
|
||||
bool same_pgrp;
|
||||
|
||||
unsigned long personality;
|
||||
|
||||
Set *syscall_filter;
|
||||
Set *syscall_archs;
|
||||
int syscall_errno;
|
||||
|
@ -79,6 +79,7 @@ $1.PrivateTmp, config_parse_bool, 0,
|
||||
$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network)
|
||||
$1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices)
|
||||
$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context)
|
||||
$1.Personality, config_parse_personality, 0, offsetof($1, exec_context.personality)
|
||||
m4_ifdef(`HAVE_LIBWRAP',
|
||||
`$1.TCPWrapName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.tcpwrap_name)',
|
||||
`$1.TCPWrapName, config_parse_warn_compat, 0, 0')
|
||||
|
@ -2566,6 +2566,36 @@ int config_parse_job_mode_isolate(
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
unsigned long *personality = data, p;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(personality);
|
||||
|
||||
p = personality_from_string(rvalue);
|
||||
if (p == 0xffffffffUL) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
|
||||
"Failed to parse personality, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*personality = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FOLLOW_MAX 8
|
||||
|
||||
static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
|
||||
|
@ -88,6 +88,7 @@ int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsig
|
||||
int config_parse_job_mode(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_job_mode_isolate(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_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);
|
||||
|
||||
/* gperf prototypes */
|
||||
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length);
|
||||
|
@ -480,7 +480,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
case ARG_PERSONALITY:
|
||||
|
||||
arg_personality = parse_personality(optarg);
|
||||
arg_personality = personality_from_string(optarg);
|
||||
if (arg_personality == 0xffffffffLU) {
|
||||
log_error("Unknown or unsupported personality '%s'.", optarg);
|
||||
return -EINVAL;
|
||||
|
@ -133,6 +133,9 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
|
||||
|
||||
case EXIT_SELINUX_CONTEXT:
|
||||
return "SELINUX_CONTEXT";
|
||||
|
||||
case EXIT_PERSONALITY:
|
||||
return "PERSONALITY";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,8 @@ typedef enum ExitStatus {
|
||||
EXIT_NAMESPACE,
|
||||
EXIT_NO_NEW_PRIVILEGES,
|
||||
EXIT_SECCOMP,
|
||||
EXIT_SELINUX_CONTEXT
|
||||
EXIT_SELINUX_CONTEXT,
|
||||
EXIT_PERSONALITY /* 230 */
|
||||
} ExitStatus;
|
||||
|
||||
typedef enum ExitStatusLevel {
|
||||
|
@ -6194,7 +6194,7 @@ int fd_warn_permissions(const char *path, int fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long parse_personality(const char *p) {
|
||||
unsigned long personality_from_string(const char *p) {
|
||||
|
||||
/* Parse a personality specifier. We introduce our own
|
||||
* identifiers that indicate specific ABIs, rather than just
|
||||
@ -6222,3 +6222,22 @@ unsigned long parse_personality(const char *p) {
|
||||
* as error indicator. */
|
||||
return 0xffffffffUL;
|
||||
}
|
||||
|
||||
const char* personality_to_string(unsigned long p) {
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
if (p == PER_LINUX32)
|
||||
return "x86";
|
||||
|
||||
if (p == PER_LINUX)
|
||||
return "x86-64";
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
if (p == PER_LINUX)
|
||||
return "x86";
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -871,4 +871,5 @@ int open_tmpfile(const char *path, int flags);
|
||||
|
||||
int fd_warn_permissions(const char *path, int fd);
|
||||
|
||||
unsigned long parse_personality(const char *p);
|
||||
unsigned long personality_from_string(const char *p);
|
||||
const char *personality_to_string(unsigned long);
|
||||
|
Loading…
Reference in New Issue
Block a user