282 lines
12 KiB
Diff
282 lines
12 KiB
Diff
|
From 66b1ee20b814b02cd0fb73fec4a2a9b11defc607 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||
|
Date: Fri, 20 Dec 2013 20:25:39 -0500
|
||
|
Subject: [PATCH] tmpfiles: introduce the concept of unsafe operations
|
||
|
|
||
|
Various operations done by systemd-tmpfiles may only be safely done at
|
||
|
boot (e.g. removal of X lockfiles in /tmp, creation of /run/nologin).
|
||
|
Other operations may be done at any point in time (e.g. setting the
|
||
|
ownership on /{run,var}/log/journal). This distinction is largely
|
||
|
orthogonal to the type of operation.
|
||
|
|
||
|
A new switch --unsafe is added, and operations which should only be
|
||
|
executed during bootup are marked with an exclamation mark in the
|
||
|
configuration files. systemd-tmpfiles.service is modified to use this
|
||
|
switch, and guards are added so it is hard to re-start it by mistake.
|
||
|
|
||
|
If we install a new version of systemd, we actually want to enforce
|
||
|
some changes to tmpfiles configuration immediately. This should now be
|
||
|
possible to do safely, so distribution packages can be modified to
|
||
|
execute the "safe" subset at package installation time.
|
||
|
|
||
|
/run/nologin creation is split out into a separate service, to make it
|
||
|
easy to override.
|
||
|
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1043212
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1045849
|
||
|
---
|
||
|
Makefile.am | 1 +
|
||
|
man/systemd-tmpfiles.xml | 6 ++++++
|
||
|
man/tmpfiles.d.xml | 25 +++++++++++++++++++++++++
|
||
|
src/tmpfiles/tmpfiles.c | 22 +++++++++++++++++++---
|
||
|
tmpfiles.d/legacy.conf | 6 +++---
|
||
|
tmpfiles.d/systemd-nologin.conf | 11 +++++++++++
|
||
|
tmpfiles.d/systemd.conf | 4 +---
|
||
|
tmpfiles.d/x11.conf | 2 +-
|
||
|
units/systemd-tmpfiles-setup.service.in | 6 ++++--
|
||
|
9 files changed, 71 insertions(+), 12 deletions(-)
|
||
|
create mode 100644 tmpfiles.d/systemd-nologin.conf
|
||
|
|
||
|
diff --git a/Makefile.am b/Makefile.am
|
||
|
index 16a5c3c..6233a7f 100644
|
||
|
--- a/Makefile.am
|
||
|
+++ b/Makefile.am
|
||
|
@@ -1599,6 +1599,7 @@ nodist_systemunit_DATA += \
|
||
|
|
||
|
dist_tmpfiles_DATA = \
|
||
|
tmpfiles.d/systemd.conf \
|
||
|
+ tmpfiles.d/systemd-nologin.conf \
|
||
|
tmpfiles.d/tmp.conf \
|
||
|
tmpfiles.d/x11.conf
|
||
|
|
||
|
diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml
|
||
|
index 91c0372..495247e 100644
|
||
|
--- a/man/systemd-tmpfiles.xml
|
||
|
+++ b/man/systemd-tmpfiles.xml
|
||
|
@@ -133,6 +133,12 @@
|
||
|
removed.</para></listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
+ <term><option>--unsafe</option></term>
|
||
|
+ <listitem><para>Also execute lines
|
||
|
+ with an exclamation mark.
|
||
|
+ </para></listitem>
|
||
|
+ </varlistentry>
|
||
|
+ <varlistentry>
|
||
|
<term><option>--prefix=PATH</option></term>
|
||
|
<listitem><para>Only apply rules that
|
||
|
apply to paths with the specified
|
||
|
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
|
||
|
index a00637b..39aa68d 100644
|
||
|
--- a/man/tmpfiles.d.xml
|
||
|
+++ b/man/tmpfiles.d.xml
|
||
|
@@ -113,6 +113,9 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||
|
<refsect2>
|
||
|
<title>Type</title>
|
||
|
|
||
|
+ <para>The type consists of a single letter and
|
||
|
+ optionally an exclamation mark.</para>
|
||
|
+
|
||
|
<para>The following line types are understood:</para>
|
||
|
|
||
|
<variablelist>
|
||
|
@@ -262,6 +265,28 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||
|
names.</para></listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
+
|
||
|
+ <para>If the exclamation mark is used, this
|
||
|
+ line is only safe of execute during boot, and
|
||
|
+ can break a running system. Lines without the
|
||
|
+ exclamation mark are presumed to be safe to
|
||
|
+ execute at any time, e.g. on package upgrades.
|
||
|
+ <command>systemd-tmpfiles</command> will
|
||
|
+ execute line with an exclamation mark only if
|
||
|
+ option <option>--unsafe</option> is given.
|
||
|
+ </para>
|
||
|
+
|
||
|
+ <para>For example:
|
||
|
+ <programlisting>
|
||
|
+# Make sure these are created by default so that nobody else can
|
||
|
+d /tmp/.X11-unix 1777 root root 10d
|
||
|
+
|
||
|
+# Unlink the X11 lock files
|
||
|
+r! /tmp/.X[0-9]*-lock
|
||
|
+ </programlisting>
|
||
|
+ The second line in contrast to the first one
|
||
|
+ would break a running system, and will only be
|
||
|
+ executed with <option>--unsafe</option>.</para>
|
||
|
</refsect2>
|
||
|
|
||
|
<refsect2>
|
||
|
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
|
||
|
index 00f74c2..30a8a55 100644
|
||
|
--- a/src/tmpfiles/tmpfiles.c
|
||
|
+++ b/src/tmpfiles/tmpfiles.c
|
||
|
@@ -106,6 +106,7 @@ static Set *unix_sockets = NULL;
|
||
|
static bool arg_create = false;
|
||
|
static bool arg_clean = false;
|
||
|
static bool arg_remove = false;
|
||
|
+static bool arg_unsafe = false;
|
||
|
|
||
|
static char **include_prefixes = NULL;
|
||
|
static char **exclude_prefixes = NULL;
|
||
|
@@ -1073,7 +1074,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
||
|
_cleanup_item_free_ Item *i = NULL;
|
||
|
Item *existing;
|
||
|
_cleanup_free_ char
|
||
|
- *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
|
||
|
+ *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
|
||
|
char type;
|
||
|
Hashmap *h;
|
||
|
int r, n = -1;
|
||
|
@@ -1083,8 +1084,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
||
|
assert(buffer);
|
||
|
|
||
|
r = sscanf(buffer,
|
||
|
- "%c %ms %ms %ms %ms %ms %n",
|
||
|
- &type,
|
||
|
+ "%ms %ms %ms %ms %ms %ms %n",
|
||
|
+ &action,
|
||
|
&path,
|
||
|
&mode,
|
||
|
&user,
|
||
|
@@ -1096,6 +1097,14 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
||
|
return -EIO;
|
||
|
}
|
||
|
|
||
|
+ if (strlen(action) > 2 || (strlen(action) > 1 && action[1] != '!')) {
|
||
|
+ log_error("[%s:%u] Unknown modifier '%s'", fname, line, action);
|
||
|
+ return -EINVAL;
|
||
|
+ } else if (strlen(action) > 1 && !arg_unsafe)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ type = action[0];
|
||
|
+
|
||
|
i = new0(Item, 1);
|
||
|
if (!i)
|
||
|
return log_oom();
|
||
|
@@ -1266,6 +1275,7 @@ static int help(void) {
|
||
|
" --create Create marked files/directories\n"
|
||
|
" --clean Clean up marked directories\n"
|
||
|
" --remove Remove marked files/directories\n"
|
||
|
+ " --unsafe Execute actions only safe at boot\n"
|
||
|
" --prefix=PATH Only apply rules that apply to paths with the specified prefix\n"
|
||
|
" --exclude-prefix=PATH Ignore rules that apply to paths with the specified prefix\n",
|
||
|
program_invocation_short_name);
|
||
|
@@ -1279,6 +1289,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||
|
ARG_CREATE,
|
||
|
ARG_CLEAN,
|
||
|
ARG_REMOVE,
|
||
|
+ ARG_UNSAFE,
|
||
|
ARG_PREFIX,
|
||
|
ARG_EXCLUDE_PREFIX,
|
||
|
};
|
||
|
@@ -1288,6 +1299,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||
|
{ "create", no_argument, NULL, ARG_CREATE },
|
||
|
{ "clean", no_argument, NULL, ARG_CLEAN },
|
||
|
{ "remove", no_argument, NULL, ARG_REMOVE },
|
||
|
+ { "unsafe", no_argument, NULL, ARG_UNSAFE },
|
||
|
{ "prefix", required_argument, NULL, ARG_PREFIX },
|
||
|
{ "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
|
||
|
{ NULL, 0, NULL, 0 }
|
||
|
@@ -1318,6 +1330,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||
|
arg_remove = true;
|
||
|
break;
|
||
|
|
||
|
+ case ARG_UNSAFE:
|
||
|
+ arg_unsafe = true;
|
||
|
+ break;
|
||
|
+
|
||
|
case ARG_PREFIX:
|
||
|
if (strv_extend(&include_prefixes, optarg) < 0)
|
||
|
return log_oom();
|
||
|
diff --git a/tmpfiles.d/legacy.conf b/tmpfiles.d/legacy.conf
|
||
|
index 3fff347..a165687 100644
|
||
|
--- a/tmpfiles.d/legacy.conf
|
||
|
+++ b/tmpfiles.d/legacy.conf
|
||
|
@@ -29,6 +29,6 @@ d /run/lock/lockdev 0775 root lock -
|
||
|
# kernel command line options 'fsck.mode=force', 'fsck.mode=skip' and
|
||
|
# 'quotacheck.mode=force'
|
||
|
|
||
|
-r /forcefsck
|
||
|
-r /fastboot
|
||
|
-r /forcequotacheck
|
||
|
+r! /forcefsck
|
||
|
+r! /fastboot
|
||
|
+r! /forcequotacheck
|
||
|
diff --git a/tmpfiles.d/systemd-nologin.conf b/tmpfiles.d/systemd-nologin.conf
|
||
|
new file mode 100644
|
||
|
index 0000000..d61232b
|
||
|
--- /dev/null
|
||
|
+++ b/tmpfiles.d/systemd-nologin.conf
|
||
|
@@ -0,0 +1,11 @@
|
||
|
+# This file is part of systemd.
|
||
|
+#
|
||
|
+# systemd is free software; you can redistribute it and/or modify it
|
||
|
+# under the terms of the GNU Lesser General Public License as published by
|
||
|
+# the Free Software Foundation; either version 2.1 of the License, or
|
||
|
+# (at your option) any later version.
|
||
|
+
|
||
|
+# See tmpfiles.d(5) and systemd-forbid-user-logins.service(5).
|
||
|
+# This file has special suffix so it is not run by mistake.
|
||
|
+
|
||
|
+F! /run/nologin 0644 - - - "System is booting up. See pam_nologin(8)"
|
||
|
diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf
|
||
|
index a05c657..7c6d6b9 100644
|
||
|
--- a/tmpfiles.d/systemd.conf
|
||
|
+++ b/tmpfiles.d/systemd.conf
|
||
|
@@ -8,7 +8,7 @@
|
||
|
# See tmpfiles.d(5) for details
|
||
|
|
||
|
d /run/user 0755 root root ~10d
|
||
|
-F /run/utmp 0664 root utmp -
|
||
|
+F! /run/utmp 0664 root utmp -
|
||
|
|
||
|
f /var/log/wtmp 0664 root utmp -
|
||
|
f /var/log/btmp 0600 root utmp -
|
||
|
@@ -22,8 +22,6 @@ d /run/systemd/users 0755 root root -
|
||
|
d /run/systemd/machines 0755 root root -
|
||
|
d /run/systemd/shutdown 0755 root root -
|
||
|
|
||
|
-F /run/nologin 0644 - - - "System is booting up. See pam_nologin(8)"
|
||
|
-
|
||
|
m /var/log/journal 2755 root systemd-journal - -
|
||
|
m /var/log/journal/%m 2755 root systemd-journal - -
|
||
|
m /run/log/journal 2755 root systemd-journal - -
|
||
|
diff --git a/tmpfiles.d/x11.conf b/tmpfiles.d/x11.conf
|
||
|
index ece6a5c..4c96a54 100644
|
||
|
--- a/tmpfiles.d/x11.conf
|
||
|
+++ b/tmpfiles.d/x11.conf
|
||
|
@@ -15,4 +15,4 @@ d /tmp/.font-unix 1777 root root 10d
|
||
|
d /tmp/.Test-unix 1777 root root 10d
|
||
|
|
||
|
# Unlink the X11 lock files
|
||
|
-r /tmp/.X[0-9]*-lock
|
||
|
+r! /tmp/.X[0-9]*-lock
|
||
|
diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in
|
||
|
index 3405e28..c2dcae0 100644
|
||
|
--- a/units/systemd-tmpfiles-setup.service.in
|
||
|
+++ b/units/systemd-tmpfiles-setup.service.in
|
||
|
@@ -6,7 +6,7 @@
|
||
|
# (at your option) any later version.
|
||
|
|
||
|
[Unit]
|
||
|
-Description=Recreate Volatile Files and Directories
|
||
|
+Description=Create Volatile Files and Directories
|
||
|
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
|
||
|
DefaultDependencies=no
|
||
|
Wants=local-fs.target
|
||
|
@@ -18,8 +18,10 @@ ConditionDirectoryNotEmpty=|/lib/tmpfiles.d
|
||
|
ConditionDirectoryNotEmpty=|/usr/local/lib/tmpfiles.d
|
||
|
ConditionDirectoryNotEmpty=|/etc/tmpfiles.d
|
||
|
ConditionDirectoryNotEmpty=|/run/tmpfiles.d
|
||
|
+RefuseManualStart=yes
|
||
|
+RefuseManualStop=yes
|
||
|
|
||
|
[Service]
|
||
|
Type=oneshot
|
||
|
RemainAfterExit=yes
|
||
|
-ExecStart=@rootbindir@/systemd-tmpfiles --create --remove --exclude-prefix=/dev
|
||
|
+ExecStart=@rootbindir@/systemd-tmpfiles --create --remove --unsafe --exclude-prefix=/dev
|