1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

support chrooting/setting of ioprio when spawning

This commit is contained in:
Lennart Poettering 2010-01-29 20:46:22 +01:00
parent f94ea366d3
commit 9eba9da4bc
4 changed files with 155 additions and 13 deletions

View File

@ -15,6 +15,7 @@
#include "macro.h" #include "macro.h"
#include "util.h" #include "util.h"
#include "log.h" #include "log.h"
#include "ioprio.h"
static int close_fds(int except[], unsigned n_except) { static int close_fds(int except[], unsigned n_except) {
DIR *d; DIR *d;
@ -273,13 +274,13 @@ int exec_spawn(const ExecCommand *command, const ExecContext *context, int *fds,
goto fail; goto fail;
} }
umask(context->umask); if (setpgid(0, 0) < 0) {
r = EXIT_PGID;
if (chdir(context->directory ? context->directory : "/") < 0) {
r = EXIT_CHDIR;
goto fail; goto fail;
} }
umask(context->umask);
if (setup_output(context, file_name_from_path(command->path)) < 0) { if (setup_output(context, file_name_from_path(command->path)) < 0) {
r = EXIT_OUTPUT; r = EXIT_OUTPUT;
goto fail; goto fail;
@ -297,12 +298,29 @@ int exec_spawn(const ExecCommand *command, const ExecContext *context, int *fds,
} }
} }
if (context->root_directory)
if (chroot(context->root_directory) < 0) {
r = EXIT_CHROOT;
goto fail;
}
if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
r = EXIT_CHDIR;
goto fail;
}
if (context->nice_set) if (context->nice_set)
if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) { if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
r = EXIT_NICE; r = EXIT_NICE;
goto fail; goto fail;
} }
if (context->ioprio_set)
if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
r = EXIT_IOPRIO;
goto fail;
}
if (close_fds(fds, n_fds) < 0 || if (close_fds(fds, n_fds) < 0 ||
shift_fds(fds, n_fds) < 0 || shift_fds(fds, n_fds) < 0 ||
flags_fds(fds, n_fds) < 0) { flags_fds(fds, n_fds) < 0) {
@ -366,8 +384,13 @@ void exec_context_init(ExecContext *c) {
c->umask = 0002; c->umask = 0002;
cap_clear(c->capabilities); cap_clear(c->capabilities);
c->capabilities_set = false;
c->oom_adjust = 0; c->oom_adjust = 0;
c->oom_adjust_set = false;
c->nice = 0; c->nice = 0;
c->nice_set = false;
c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
c->ioprio_set = false;
c->output = 0; c->output = 0;
c->syslog_priority = LOG_DAEMON|LOG_INFO; c->syslog_priority = LOG_DAEMON|LOG_INFO;
@ -386,8 +409,10 @@ void exec_context_done(ExecContext *c) {
c->rlimit[l] = NULL; c->rlimit[l] = NULL;
} }
free(c->directory); free(c->working_directory);
c->directory = NULL; c->working_directory = NULL;
free(c->root_directory);
c->root_directory = NULL;
free(c->syslog_identifier); free(c->syslog_identifier);
c->syslog_identifier = NULL; c->syslog_identifier = NULL;
@ -424,6 +449,14 @@ void exec_command_free_array(ExecCommand **c, unsigned n) {
} }
void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
static const char * const table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
[IOPRIO_CLASS_BE] = "best-effort",
[IOPRIO_CLASS_IDLE] = "idle"
};
assert(c); assert(c);
assert(f); assert(f);
@ -432,9 +465,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
fprintf(f, fprintf(f,
"%sUmask: %04o\n" "%sUmask: %04o\n"
"%sDirectory: %s\n", "%sWorking Directory: %s\n"
"%sRoot Directory: %s\n",
prefix, c->umask, prefix, c->umask,
prefix, c->directory ? c->directory : "/"); prefix, c->working_directory ? c->working_directory : "/",
prefix, c->root_directory ? c->root_directory : "/");
if (c->nice_set) if (c->nice_set)
fprintf(f, fprintf(f,
@ -445,6 +480,13 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
fprintf(f, fprintf(f,
"%sOOMAdjust: %i\n", "%sOOMAdjust: %i\n",
prefix, c->oom_adjust); prefix, c->oom_adjust);
if (c->ioprio_set)
fprintf(f,
"%sIOSchedulingClass: %s\n"
"%sIOPriority: %i\n",
prefix, table[IOPRIO_PRIO_CLASS(c->ioprio)],
prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
} }
void exec_status_fill(ExecStatus *s, pid_t pid, int code, int status) { void exec_status_fill(ExecStatus *s, pid_t pid, int code, int status) {

View File

@ -44,12 +44,14 @@ struct ExecContext {
char **environment; char **environment;
mode_t umask; mode_t umask;
struct rlimit *rlimit[RLIMIT_NLIMITS]; /* FIXME: load-fragment parser missing */ struct rlimit *rlimit[RLIMIT_NLIMITS]; /* FIXME: load-fragment parser missing */
char *directory; char *working_directory, *root_directory;
int oom_adjust; int oom_adjust;
int nice; int nice;
int ioprio;
bool oom_adjust_set:1; bool oom_adjust_set:1;
bool nice_set:1; bool nice_set:1;
bool ioprio_set:1;
ExecOutput output; ExecOutput output;
int syslog_priority; int syslog_priority;
@ -91,7 +93,10 @@ typedef enum ExitStatus {
EXIT_LIMITS, EXIT_LIMITS,
EXIT_OOM_ADJUST, EXIT_OOM_ADJUST,
EXIT_SIGNAL_MASK, EXIT_SIGNAL_MASK,
EXIT_OUTPUT EXIT_OUTPUT,
EXIT_CHROOT,
EXIT_PGID,
EXIT_IOPRIO
} ExitStatus; } ExitStatus;
int exec_spawn(const ExecCommand *command, const ExecContext *context, int *fds, unsigned n_fds, pid_t *ret); int exec_spawn(const ExecCommand *command, const ExecContext *context, int *fds, unsigned n_fds, pid_t *ret);

11
fixme
View File

@ -27,9 +27,9 @@
- implement mount/automount - implement mount/automount
- more process attributes: chroot, cpu affinity, scheduling - more process attributes: cpu affinity, cpu scheduling
- create session/pgroup for child processes - create session/pgroup for child processes? handle input on console properly? interactive fsck? interactive luks password?
- fs namespaces - fs namespaces
@ -45,3 +45,10 @@
presumably uses the logging socket in blocking mode which might presumably uses the logging socket in blocking mode which might
trigger a deadlock if syslog does not process the socket anymore trigger a deadlock if syslog does not process the socket anymore
(maybe because it is restarted) and the socket buffer is full. (maybe because it is restarted) and the socket buffer is full.
- in udev/mount if properties change we need to delete the old
settings and install the new settings. Deleting the old settings is
currently missing.
- ability to kill services? i.e. in contrast to stopping them, go directly
into killing mode?

View File

@ -12,6 +12,7 @@
#include "conf-parser.h" #include "conf-parser.h"
#include "load-fragment.h" #include "load-fragment.h"
#include "log.h" #include "log.h"
#include "ioprio.h"
static int config_parse_deps( static int config_parse_deps(
const char *filename, const char *filename,
@ -625,6 +626,90 @@ int config_parse_level(
return 0; return 0;
} }
int config_parse_io_class(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
static const char * const table[] = {
[IOPRIO_CLASS_NONE] = NULL,
[IOPRIO_CLASS_RT] = "realtime",
[IOPRIO_CLASS_BE] = "best-effort",
[IOPRIO_CLASS_IDLE] = "idle",
};
ExecContext *c = data;
int i;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
for (i = 0; i < (int) ELEMENTSOF(table); i++) {
if (!table[i])
continue;
if (streq(rvalue, table[i])) {
c->ioprio = IOPRIO_PRIO_VALUE(i, IOPRIO_PRIO_DATA(c->ioprio));
break;
}
}
if (i >= (int) ELEMENTSOF(table)) {
/* Second try, let's see if this is a number. */
if (safe_atoi(rvalue, &i) >= 0 &&
i >= 0 &&
i < (int) ELEMENTSOF(table) &&
table[i])
c->ioprio = IOPRIO_PRIO_VALUE(i, IOPRIO_PRIO_DATA(c->ioprio));
else {
log_error("[%s:%u] Failed to parse io priority: %s", filename, line, rvalue);
return -EBADMSG;
}
}
c->ioprio_set = true;
return 0;
}
int config_parse_io_priority(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
int i;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (safe_atoi(rvalue, &i) >= 0 &&
i >= 0 &&
i < IOPRIO_BE_NR)
c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
else {
log_error("[%s:%u] Failed to parse io priority: %s", filename, line, rvalue);
return -EBADMSG;
}
c->ioprio_set = true;
return 0;
}
#define FOLLOW_MAX 8 #define FOLLOW_MAX 8
static int open_follow(char **filename, FILE **_f, Set *names, char **_id) { static int open_follow(char **filename, FILE **_f, Set *names, char **_id) {
@ -709,12 +794,15 @@ static int load_from_path(Unit *u, const char *path) {
}; };
#define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \ #define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
{ "Directory", config_parse_path, &(context).directory, section }, \ { "WorkingDirectory", config_parse_path, &(context).working_directory, section }, \
{ "RootDirectory", config_parse_path, &(context).root_directory, section }, \
{ "User", config_parse_string, &(context).user, section }, \ { "User", config_parse_string, &(context).user, section }, \
{ "Group", config_parse_string, &(context).group, section }, \ { "Group", config_parse_string, &(context).group, section }, \
{ "SupplementaryGroups", config_parse_strv, &(context).supplementary_groups, section }, \ { "SupplementaryGroups", config_parse_strv, &(context).supplementary_groups, section }, \
{ "Nice", config_parse_nice, &(context), section }, \ { "Nice", config_parse_nice, &(context), section }, \
{ "OOMAdjust", config_parse_oom_adjust, &(context), section }, \ { "OOMAdjust", config_parse_oom_adjust, &(context), section }, \
{ "IOPriority", config_parse_io_priority, &(context), section }, \
{ "IOSchedulingClass", config_parse_io_class, &(context), section }, \
{ "UMask", config_parse_umask, &(context).umask, section }, \ { "UMask", config_parse_umask, &(context).umask, section }, \
{ "Environment", config_parse_strv, &(context).environment, section }, \ { "Environment", config_parse_strv, &(context).environment, section }, \
{ "Output", config_parse_output, &(context).output, section }, \ { "Output", config_parse_output, &(context).output, section }, \