[systemd-commits] 4 commits - TODO man/systemd.exec.xml man/tmpfiles.d.xml src/cgroup-util.c src/cgroup-util.h src/cgroup.c src/cgroup.h src/conf-parser.c src/conf-parser.h src/dbus-execute.c src/execute.c src/execute.h src/journal src/load-fragment-gperf.gperf.m4 src/login src/manager.c src/tmpfiles.c src/util.c src/util.h
Lennart Poettering
lennart at kemper.freedesktop.org
Wed Jan 18 07:40:17 PST 2012
TODO | 5 +-
man/systemd.exec.xml | 15 ++++++++
man/tmpfiles.d.xml | 14 ++++++-
src/cgroup-util.c | 47 ++++++++++++++++++++++----
src/cgroup-util.h | 2 -
src/cgroup.c | 19 +++-------
src/cgroup.h | 8 ++--
src/conf-parser.c | 30 ++++++++++++++++
src/conf-parser.h | 1
src/dbus-execute.c | 1
src/execute.c | 17 ++++++++-
src/execute.h | 1
src/journal/journal-send.c | 5 ++
src/load-fragment-gperf.gperf.m4 | 3 +
src/login/logind-session.c | 2 -
src/manager.c | 7 ++-
src/tmpfiles.c | 70 ++++++++++++++++++++++++++++++++++-----
src/util.c | 27 +++++++++------
src/util.h | 2 -
19 files changed, 221 insertions(+), 55 deletions(-)
New commits:
commit 31ed59c51126fce7d958c188772a397e2a1ed010
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jan 18 16:39:04 2012 +0100
tmpfiles: support writing short strings to files, in order to support /sys manipulations at boot time, a la sysctl
diff --git a/TODO b/TODO
index 0c3cc9d..f3eb8c5 100644
--- a/TODO
+++ b/TODO
@@ -21,6 +21,8 @@ Bugfixes:
Features:
+* rework namespace support, don't use pivot_root, and mount things after creating the namespace, not before
+
* systemctl journal command
* journalctl: --cursor support, priority filtering
@@ -82,7 +84,6 @@ Features:
* service restart retry configuration
* tmpfiles: apply "x" on "D" too (see patch from William Douglas)
-* tmpfiles: support generation of char/block devices, symlinks and one-line files (think sysfs)
* don't set $HOME in services unless requested
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 080da66..25a7c9b 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -98,12 +98,17 @@ L /tmp/foobar - - - - /dev/null</programlisting>
<variablelist>
<varlistentry>
<term><varname>f</varname></term>
- <listitem><para>Create a file if it doesn't exist yet</para></listitem>
+ <listitem><para>Create a file if it doesn't exist yet (optionally writing a short string into it, if the argument parameter is passed)</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>F</varname></term>
- <listitem><para>Create or truncate a file</para></listitem>
+ <listitem><para>Create or truncate a file (optionally writing a short string into it, if the argument parameter is passed)</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>w</varname></term>
+ <listitem><para>Write the argument parameter to a file, if it exists.</para></listitem>
</varlistentry>
<varlistentry>
@@ -260,7 +265,10 @@ L /tmp/foobar - - - - /dev/null</programlisting>
path of the symlink. For c, b determines the
major/minor of the device node, with major and
minor formatted as integers, separated by :,
- e.g. "1:3". Ignored for all other lines.</para>
+ e.g. "1:3". For f, F, w may be used to specify
+ a short string that is written to the file,
+ suffixed by a newline. Ignored for all other
+ lines.</para>
</refsect2>
</refsect1>
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index 2096019..f3c38a8 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -54,6 +54,7 @@ typedef enum ItemType {
/* These ones take file names */
CREATE_FILE = 'f',
TRUNCATE_FILE = 'F',
+ WRITE_FILE = 'w',
CREATE_DIRECTORY = 'd',
TRUNCATE_DIRECTORY = 'D',
CREATE_FIFO = 'p',
@@ -574,19 +575,48 @@ static int create_item(Item *i) {
return 0;
case CREATE_FILE:
- case TRUNCATE_FILE: {
- int fd;
+ case TRUNCATE_FILE:
+ case WRITE_FILE: {
+ int fd, flags;
+
+ flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND :
+ i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
u = umask(0);
- fd = open(i->path, O_CREAT|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW|
- (i->type == TRUNCATE_FILE ? O_TRUNC : 0), i->mode);
+ fd = open(i->path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
umask(u);
if (fd < 0) {
+ if (i->type == WRITE_FILE && errno == ENOENT)
+ break;
+
log_error("Failed to create file %s: %m", i->path);
return -errno;
}
+ if (i->argument) {
+ ssize_t n;
+ size_t l;
+ struct iovec iovec[2];
+ static const char new_line = '\n';
+
+ l = strlen(i->argument);
+
+ zero(iovec);
+ iovec[0].iov_base = i->argument;
+ iovec[0].iov_len = l;
+
+ iovec[1].iov_base = (void*) &new_line;
+ iovec[1].iov_len = 1;
+
+ n = writev(fd, iovec, 2);
+ if (n < 0 || (size_t) n != l+1) {
+ log_error("Failed to write file %s: %s", i->path, n < 0 ? strerror(-n) : "Short");
+ close_nointr_nofail(fd);
+ return n < 0 ? n : -EIO;
+ }
+ }
+
close_nointr_nofail(fd);
if (stat(i->path, &st) < 0) {
@@ -752,6 +782,7 @@ static int remove_item_instance(Item *i, const char *instance) {
case IGNORE_PATH:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
+ case WRITE_FILE:
break;
case REMOVE_PATH:
@@ -793,6 +824,7 @@ static int remove_item(Item *i) {
case IGNORE_PATH:
case RELABEL_PATH:
case RECURSIVE_RELABEL_PATH:
+ case WRITE_FILE:
break;
case REMOVE_PATH:
@@ -857,7 +889,10 @@ static bool item_equal(Item *a, Item *b) {
(a->age_set && a->age != b->age))
return false;
- if (a->type == CREATE_SYMLINK &&
+ if ((a->type == CREATE_FILE ||
+ a->type == TRUNCATE_FILE ||
+ a->type == WRITE_FILE ||
+ a->type == CREATE_SYMLINK) &&
!streq(a->argument, b->argument))
return false;
@@ -874,7 +909,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
char *mode = NULL, *user = NULL, *group = NULL, *age = NULL;
char type;
Hashmap *h;
- int r;
+ int r, n = -1;
assert(fname);
assert(line >= 1);
@@ -893,19 +928,30 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
"%ms "
"%ms "
"%ms "
- "%ms",
+ "%n",
&type,
&i->path,
&mode,
&user,
&group,
&age,
- &i->argument) < 2) {
+ &n) < 2) {
log_error("[%s:%u] Syntax error.", fname, line);
r = -EIO;
goto finish;
}
+ if (n >= 0) {
+ n += strspn(buffer+n, WHITESPACE);
+ if (buffer[n] != 0 && (buffer[n] != '-' || buffer[n+1] != 0)) {
+ i->argument = unquote(buffer+n, "\"");
+ if (!i->argument) {
+ log_error("Out of memory");
+ return -ENOMEM;
+ }
+ }
+ }
+
switch(type) {
case CREATE_FILE:
@@ -928,6 +974,14 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
}
break;
+ case WRITE_FILE:
+ if (!i->argument) {
+ log_error("[%s:%u] Write file requires argument.", fname, line);
+ r = -EBADMSG;
+ goto finish;
+ }
+ break;
+
case CREATE_CHAR_DEVICE:
case CREATE_BLOCK_DEVICE: {
unsigned major, minor;
diff --git a/src/util.c b/src/util.c
index 8004beb..fbc37c4 100644
--- a/src/util.c
+++ b/src/util.c
@@ -4118,7 +4118,8 @@ char *unquote(const char *s, const char* quotes) {
size_t l;
assert(s);
- if ((l = strlen(s)) < 2)
+ l = strlen(s);
+ if (l < 2)
return strdup(s);
if (strchr(quotes, s[0]) && s[l-1] == s[0])
commit 88f06645623467f9c8db88afca64557d62e38c61
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jan 18 15:41:21 2012 +0100
manager: don't place units in the 'cpu' group when run as user instance, for now
diff --git a/src/manager.c b/src/manager.c
index bab1662..19e5441 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -247,8 +247,11 @@ int manager_new(ManagerRunningAs running_as, Manager **_m) {
if (!(m->environment = strv_copy(environ)))
goto fail;
- if (!(m->default_controllers = strv_new("cpu", NULL)))
- goto fail;
+ if (running_as == MANAGER_SYSTEM) {
+ m->default_controllers = strv_new("cpu", NULL);
+ if (!m->default_controllers)
+ goto fail;
+ }
if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
goto fail;
commit 9058851be7821edac08c1fa7ecafe5cba9ab9022
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jan 18 15:40:58 2012 +0100
journal: when sending journal data via file, place it in /dev/shm, to allow early boot operation, even if it sucks
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index 03bd170..00029fe 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -140,13 +140,16 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
int i, j = 0;
struct msghdr mh;
struct sockaddr_un sa;
- char path[] = "/tmp/journal.XXXXXX";
ssize_t k;
union {
struct cmsghdr cmsghdr;
uint8_t buf[CMSG_SPACE(sizeof(int))];
} control;
struct cmsghdr *cmsg;
+ /* We use /dev/shm instead of /tmp here, since we want this to
+ * be a tmpfs, and one that is available from early boot on
+ * and where unprivileged users can create files. */
+ char path[] = "/dev/shm/journal.XXXXXX";
if (!iov || n <= 0)
return -EINVAL;
commit 8d53b4534a5923721b5f1e9dd7e8f4a903d02d51
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Jan 18 15:40:21 2012 +0100
exec: introduce ControlGroupPersistant= to make cgroups persistant
diff --git a/TODO b/TODO
index e2a19ad..0c3cc9d 100644
--- a/TODO
+++ b/TODO
@@ -84,8 +84,6 @@ Features:
* tmpfiles: apply "x" on "D" too (see patch from William Douglas)
* tmpfiles: support generation of char/block devices, symlinks and one-line files (think sysfs)
-* Introduce ControlGroupPersistant=yes to set +t on the tasks file when creating the cgroup
-
* don't set $HOME in services unless requested
* hide PAM/TCPWrap options in fragment parser when compile time disabled
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index c1ab6b9..97bdbba 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -777,6 +777,21 @@
</varlistentry>
<varlistentry>
+ <term><varname>ControlGroupPersistant=</varname></term>
+ <listitem><para>Takes a boolean
+ argument. If true, the control groups
+ created for this unit will be marked
+ to be persistant, i.e. systemd will
+ not remove them when stopping the
+ unit. The default is false, meaning
+ that the control groups will be
+ removed when the unit is stopped. For
+ details about the semantics of this
+ logic see <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups">PaxControlGroups</ulink>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>ControlGroupAttribute=</varname></term>
<listitem><para>Set a specific control
diff --git a/src/cgroup-util.c b/src/cgroup-util.c
index f74280f..904d300 100644
--- a/src/cgroup-util.c
+++ b/src/cgroup-util.c
@@ -173,7 +173,7 @@ int cg_rmdir(const char *controller, const char *path, bool honour_sticky) {
return -ENOMEM;
}
- r = file_is_sticky(tasks);
+ r = file_is_priv_sticky(tasks);
free(tasks);
if (r > 0) {
@@ -571,7 +571,7 @@ static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct
return 1;
}
- is_sticky = file_is_sticky(p) > 0;
+ is_sticky = file_is_priv_sticky(p) > 0;
free(p);
if (is_sticky)
@@ -606,7 +606,7 @@ int cg_trim(const char *controller, const char *path, bool delete_root) {
return -ENOMEM;
}
- is_sticky = file_is_sticky(p) > 0;
+ is_sticky = file_is_priv_sticky(p) > 0;
free(p);
if (!is_sticky)
@@ -712,7 +712,11 @@ int cg_set_group_access(const char *controller, const char *path, mode_t mode, u
assert(controller);
assert(path);
- if ((r = cg_get_path(controller, path, NULL, &fs)) < 0)
+ if (mode != (mode_t) -1)
+ mode &= 0777;
+
+ r = cg_get_path(controller, path, NULL, &fs);
+ if (r < 0)
return r;
r = chmod_and_chown(fs, mode, uid, gid);
@@ -721,16 +725,47 @@ int cg_set_group_access(const char *controller, const char *path, mode_t mode, u
return r;
}
-int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
+int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky) {
char *fs;
int r;
assert(controller);
assert(path);
- if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0)
+ if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
+ return 0;
+
+ if (mode != (mode_t) -1)
+ mode &= 0666;
+
+ r = cg_get_path(controller, path, "tasks", &fs);
+ if (r < 0)
return r;
+ if (sticky >= 0 && mode != (mode_t) -1)
+ /* Both mode and sticky param are passed */
+ mode |= (sticky ? S_ISVTX : 0);
+ else if ((sticky >= 0 && mode == (mode_t) -1) ||
+ (mode != (mode_t) -1 && sticky < 0)) {
+ struct stat st;
+
+ /* Only one param is passed, hence read the current
+ * mode from the file itself */
+
+ r = lstat(fs, &st);
+ if (r < 0) {
+ free(fs);
+ return -errno;
+ }
+
+ if (mode == (mode_t) -1)
+ /* No mode set, we just shall set the sticky bit */
+ mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
+ else
+ /* Only mode set, leave sticky bit untouched */
+ mode = (st.st_mode & ~0777) | mode;
+ }
+
r = chmod_and_chown(fs, mode, uid, gid);
free(fs);
diff --git a/src/cgroup-util.h b/src/cgroup-util.h
index f09373b..37e4255 100644
--- a/src/cgroup-util.h
+++ b/src/cgroup-util.h
@@ -60,7 +60,7 @@ int cg_attach(const char *controller, const char *path, pid_t pid);
int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
-int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
+int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky);
int cg_install_release_agent(const char *controller, const char *agent);
diff --git a/src/cgroup.c b/src/cgroup.c
index e141b41..9aff02e 100644
--- a/src/cgroup.c
+++ b/src/cgroup.c
@@ -60,7 +60,7 @@ int cgroup_bonding_realize_list(CGroupBonding *first) {
return 0;
}
-void cgroup_bonding_free(CGroupBonding *b, bool remove_or_trim) {
+void cgroup_bonding_free(CGroupBonding *b, bool trim) {
assert(b);
if (b->unit) {
@@ -79,13 +79,8 @@ void cgroup_bonding_free(CGroupBonding *b, bool remove_or_trim) {
}
}
- if (b->realized && b->ours && remove_or_trim) {
-
- if (cgroup_bonding_is_empty(b) > 0)
- cg_delete(b->controller, b->path);
- else
- cg_trim(b->controller, b->path, false);
- }
+ if (b->realized && b->ours && trim)
+ cg_trim(b->controller, b->path, false);
free(b->controller);
free(b->path);
@@ -159,21 +154,21 @@ int cgroup_bonding_set_group_access_list(CGroupBonding *first, mode_t mode, uid_
return 0;
}
-int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid) {
+int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky) {
assert(b);
if (!b->realized)
return -EINVAL;
- return cg_set_task_access(b->controller, b->path, mode, uid, gid);
+ return cg_set_task_access(b->controller, b->path, mode, uid, gid, sticky);
}
-int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid) {
+int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t uid, gid_t gid, int sticky) {
CGroupBonding *b;
int r;
LIST_FOREACH(by_unit, b, first) {
- r = cgroup_bonding_set_task_access(b, mode, uid, gid);
+ r = cgroup_bonding_set_task_access(b, mode, uid, gid, sticky);
if (r < 0)
return r;
}
diff --git a/src/cgroup.h b/src/cgroup.h
index f33d844..db4feb9 100644
--- a/src/cgroup.h
+++ b/src/cgroup.h
@@ -53,8 +53,8 @@ struct CGroupBonding {
int cgroup_bonding_realize(CGroupBonding *b);
int cgroup_bonding_realize_list(CGroupBonding *first);
-void cgroup_bonding_free(CGroupBonding *b, bool remove_or_trim);
-void cgroup_bonding_free_list(CGroupBonding *first, bool remove_or_trim);
+void cgroup_bonding_free(CGroupBonding *b, bool trim);
+void cgroup_bonding_free_list(CGroupBonding *first, bool trim);
int cgroup_bonding_install(CGroupBonding *b, pid_t pid);
int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid);
@@ -62,8 +62,8 @@ int cgroup_bonding_install_list(CGroupBonding *first, pid_t pid);
int cgroup_bonding_set_group_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
int cgroup_bonding_set_group_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
-int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
-int cgroup_bonding_set_task_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid);
+int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
+int cgroup_bonding_set_task_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s);
int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s);
diff --git a/src/conf-parser.c b/src/conf-parser.c
index 3ccd1c0..ac8d9f5 100644
--- a/src/conf-parser.c
+++ b/src/conf-parser.c
@@ -509,6 +509,36 @@ int config_parse_bool(
return 0;
}
+int config_parse_tristate(
+ const char *filename,
+ unsigned line,
+ const char *section,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ int k;
+ int *b = data;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */
+
+ k = parse_boolean(rvalue);
+ if (k < 0) {
+ log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue);
+ return 0;
+ }
+
+ *b = !!k;
+ return 0;
+}
+
int config_parse_string(
const char *filename,
unsigned line,
diff --git a/src/conf-parser.h b/src/conf-parser.h
index e970ee2..35edcb6 100644
--- a/src/conf-parser.h
+++ b/src/conf-parser.h
@@ -95,6 +95,7 @@ int config_parse_long(const char *filename, unsigned line, const char *section,
int config_parse_uint64(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_size(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_bool(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_tristate(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_string(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_path(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/dbus-execute.c b/src/dbus-execute.c
index caeaf77..e02d61c 100644
--- a/src/dbus-execute.c
+++ b/src/dbus-execute.c
@@ -416,5 +416,6 @@ const BusProperty bus_exec_context_properties[] = {
{ "KillSignal", bus_property_append_int, "i", offsetof(ExecContext, kill_signal) },
{ "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
{ "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
+ { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_persistant) },
{ NULL, }
};
diff --git a/src/execute.c b/src/execute.c
index cacc8a7..650c6c1 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -993,7 +993,7 @@ int exec_spawn(ExecCommand *command,
char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
unsigned n_env = 0;
int saved_stdout = -1, saved_stdin = -1;
- bool keep_stdout = false, keep_stdin = false;
+ bool keep_stdout = false, keep_stdin = false, set_access = false;
/* child */
@@ -1218,11 +1218,21 @@ int exec_spawn(ExecCommand *command,
if (cgroup_bondings && context->control_group_modify) {
err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid);
if (err >= 0)
- err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid);
+ err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid, context->control_group_persistant);
if (err < 0) {
r = EXIT_CGROUP;
goto fail_child;
}
+
+ set_access = true;
+ }
+ }
+
+ if (cgroup_bondings && !set_access && context->control_group_persistant >= 0) {
+ err = cgroup_bonding_set_task_access_list(cgroup_bondings, (mode_t) -1, (uid_t) -1, (uid_t) -1, context->control_group_persistant);
+ if (err < 0) {
+ r = EXIT_CGROUP;
+ goto fail_child;
}
}
@@ -1488,6 +1498,7 @@ void exec_context_init(ExecContext *c) {
c->mount_flags = MS_SHARED;
c->kill_signal = SIGTERM;
c->send_sigkill = true;
+ c->control_group_persistant = -1;
}
void exec_context_done(ExecContext *c) {
@@ -1673,6 +1684,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
"%sNonBlocking: %s\n"
"%sPrivateTmp: %s\n"
"%sControlGroupModify: %s\n"
+ "%sControlGroupPersistant: %s\n"
"%sPrivateNetwork: %s\n",
prefix, c->umask,
prefix, c->working_directory ? c->working_directory : "/",
@@ -1680,6 +1692,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
prefix, yes_no(c->non_blocking),
prefix, yes_no(c->private_tmp),
prefix, yes_no(c->control_group_modify),
+ prefix, yes_no(c->control_group_persistant),
prefix, yes_no(c->private_network));
STRV_FOREACH(e, c->environment)
diff --git a/src/execute.h b/src/execute.h
index 187e8d2..ff33fa9 100644
--- a/src/execute.h
+++ b/src/execute.h
@@ -163,6 +163,7 @@ struct ExecContext {
bool private_network;
bool control_group_modify;
+ int control_group_persistant;
/* This is not exposed to the user but available
* internally. We need it to make sure that whenever we spawn
diff --git a/src/load-fragment-gperf.gperf.m4 b/src/load-fragment-gperf.gperf.m4
index c3f2957..8adedc5 100644
--- a/src/load-fragment-gperf.gperf.m4
+++ b/src/load-fragment-gperf.gperf.m4
@@ -86,7 +86,8 @@ $1.KillMode, config_parse_kill_mode, 0,
$1.KillSignal, config_parse_kill_signal, 0, offsetof($1, exec_context.kill_signal)
$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, exec_context.send_sigkill)
$1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id)
-$1.ControlGroupModify, config_parse_bool, 0, offsetof($1, exec_context.control_group_modify)'
+$1.ControlGroupModify, config_parse_bool, 0, offsetof($1, exec_context.control_group_modify)
+$1.ControlGroupPersistant, config_parse_tristate, 0, offsetof($1, exec_context.control_group_persistant)'
)m4_dnl
Unit.Names, config_parse_unit_names, 0, 0
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index bb802e5..5ea7e26 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -434,7 +434,7 @@ static int session_create_one_group(Session *s, const char *controller, const ch
if (r < 0)
return r;
- r = cg_set_task_access(controller, path, 0644, s->user->uid, s->user->gid);
+ r = cg_set_task_access(controller, path, 0644, s->user->uid, s->user->gid, -1);
if (r >= 0)
r = cg_set_group_access(controller, path, 0755, s->user->uid, s->user->gid);
diff --git a/src/util.c b/src/util.c
index b6e490d..8004beb 100644
--- a/src/util.c
+++ b/src/util.c
@@ -3483,7 +3483,9 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
}
if (honour_sticky)
- keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
+ keep_around =
+ (st.st_uid == 0 || st.st_uid == getuid()) &&
+ (st.st_mode & S_ISVTX);
is_dir = S_ISDIR(st.st_mode);
@@ -3497,7 +3499,9 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) {
continue;
}
- keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
+ keep_around =
+ (st.st_uid == 0 || st.st_uid == getuid()) &&
+ (st.st_mode & S_ISVTX);
}
is_dir = de->d_type == DT_DIR;
@@ -3559,7 +3563,7 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky
if (delete_root) {
- if (honour_sticky && file_is_sticky(path) > 0)
+ if (honour_sticky && file_is_priv_sticky(path) > 0)
return r;
if (rmdir(path) < 0 && errno != ENOENT) {
@@ -3578,11 +3582,13 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
* first change the access mode and only then hand out
* ownership to avoid a window where access is too open. */
- if (chmod(path, mode) < 0)
- return -errno;
+ if (mode != (mode_t) -1)
+ if (chmod(path, mode) < 0)
+ return -errno;
- if (chown(path, uid, gid) < 0)
- return -errno;
+ if (uid != (uid_t) -1 || gid != (gid_t) -1)
+ if (chown(path, uid, gid) < 0)
+ return -errno;
return 0;
}
@@ -5810,7 +5816,7 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
return -ENOENT;
}
-int file_is_sticky(const char *p) {
+int file_is_priv_sticky(const char *p) {
struct stat st;
assert(p);
@@ -5819,7 +5825,7 @@ int file_is_sticky(const char *p) {
return -errno;
return
- st.st_uid == 0 &&
+ (st.st_uid == 0 || st.st_uid == getuid()) &&
(st.st_mode & S_ISVTX);
}
diff --git a/src/util.h b/src/util.h
index 590dc17..6acfcc8 100644
--- a/src/util.h
+++ b/src/util.h
@@ -478,7 +478,7 @@ bool in_charset(const char *s, const char* charset);
int block_get_whole_disk(dev_t d, dev_t *ret);
-int file_is_sticky(const char *p);
+int file_is_priv_sticky(const char *p);
int strdup_or_null(const char *a, char **b);
More information about the systemd-commits
mailing list