[systemd-commits] 4 commits - TODO src/core src/shared src/tmpfiles

Lennart Poettering lennart at kemper.freedesktop.org
Tue Jul 10 10:07:16 PDT 2012


 TODO                    |   14 ++++++-
 src/core/mount.c        |    6 ++-
 src/shared/util.c       |   96 +++++++++++++++++++++++++++++++++++++++++++-----
 src/shared/util.h       |    2 +
 src/tmpfiles/tmpfiles.c |    2 -
 5 files changed, 106 insertions(+), 14 deletions(-)

New commits:
commit 94163dd54328780b4539e7296eb0ba75b7290367
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jul 10 19:06:59 2012 +0200

    update TODO

diff --git a/TODO b/TODO
index 3d55f8a..a016c29 100644
--- a/TODO
+++ b/TODO
@@ -34,8 +34,6 @@ Bugfixes:
 
 Features:
 
-* switch-root add extra safety check
-
 * switch-root: reopen /dev/console before switching root
 
 * switch-root: sockets need relabelling

commit f56d5db919902851535ac1591d5c95ebcd3a0b17
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jul 10 19:05:58 2012 +0200

    util: rm_rf() refuse cleaning non-memory file systems, as extra paranoia

diff --git a/src/shared/util.c b/src/shared/util.c
index 8caac7b..62121b5 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -3243,7 +3243,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
         return 0;
 }
 
-int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
+int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
         DIR *d;
         int ret = 0;
 
@@ -3335,14 +3335,43 @@ int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root
         return ret;
 }
 
-int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
-        int fd;
-        int r;
+int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) {
+        struct statfs s;
+
+        assert(fd >= 0);
+
+        if (fstatfs(fd, &s) < 0) {
+                close_nointr_nofail(fd);
+                return -errno;
+        }
+
+        /* We refuse to clean disk file systems with this call. This
+         * is extra paranoia just to be sure we never ever remove
+         * non-state data */
+
+        if (s.f_type != TMPFS_MAGIC &&
+            s.f_type != RAMFS_MAGIC) {
+                log_error("Attempted to remove disk file system, and we can't allow that.");
+                close_nointr_nofail(fd);
+                return -EPERM;
+        }
+
+        return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
+}
+
+static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
+        int fd, r;
+        struct statfs s;
 
         assert(path);
 
-        /* Be paranoid */
-        assert(!streq(path, "/"));
+        /* We refuse to clean the root file system with this
+         * call. This is extra paranoia to never cause a really
+         * seriously broken system. */
+        if (path_equal(path, "/")) {
+                log_error("Attempted to remove entire root file system, and we can't allow that.");
+                return -EPERM;
+        }
 
         fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
         if (fd < 0) {
@@ -3350,6 +3379,17 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky
                 if (errno != ENOTDIR)
                         return -errno;
 
+                if (!dangerous) {
+                        if (statfs(path, &s) < 0)
+                                return -errno;
+
+                        if (s.f_type != TMPFS_MAGIC &&
+                            s.f_type != RAMFS_MAGIC) {
+                                log_error("Attempted to remove disk file system, and we can't allow that.");
+                                return -EPERM;
+                        }
+                }
+
                 if (delete_root && !only_dirs)
                         if (unlink(path) < 0 && errno != ENOENT)
                                 return -errno;
@@ -3357,8 +3397,21 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky
                 return 0;
         }
 
-        r = rm_rf_children(fd, only_dirs, honour_sticky, NULL);
+        if (!dangerous) {
+                if (fstatfs(fd, &s) < 0) {
+                        close_nointr_nofail(fd);
+                        return -errno;
+                }
+
+                if (s.f_type != TMPFS_MAGIC &&
+                    s.f_type != RAMFS_MAGIC) {
+                        log_error("Attempted to remove disk file system, and we can't allow that.");
+                        close_nointr_nofail(fd);
+                        return -EPERM;
+                }
+        }
 
+        r = rm_rf_children_dangerous(fd, only_dirs, honour_sticky, NULL);
         if (delete_root) {
 
                 if (honour_sticky && file_is_priv_sticky(path) > 0)
@@ -3373,6 +3426,14 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky
         return r;
 }
 
+int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
+        return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, false);
+}
+
+int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky) {
+        return rm_rf_internal(path, only_dirs, delete_root, honour_sticky, true);
+}
+
 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
         assert(path);
 
diff --git a/src/shared/util.h b/src/shared/util.h
index 47497b5..89e9a00 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -358,7 +358,9 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
 int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
 
 int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev);
+int rm_rf_children_dangerous(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev);
 int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
+int rm_rf_dangerous(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
 
 int pipe_eof(int fd);
 
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index e0b0e94..2d5d90d 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -845,7 +845,7 @@ static int remove_item_instance(Item *i, const char *instance) {
         case RECURSIVE_REMOVE_PATH:
                 /* FIXME: we probably should use dir_cleanup() here
                  * instead of rm_rf() so that 'x' is honoured. */
-                r = rm_rf(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
+                r = rm_rf_dangerous(instance, false, i->type == RECURSIVE_REMOVE_PATH, false);
                 if (r < 0 && r != -ENOENT) {
                         log_error("rm_rf(%s): %s", instance, strerror(-r));
                         return r;

commit 825c6fe5eb362437aa46faa52b683a62eede9a13
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jul 10 18:46:26 2012 +0200

    util: add extra safety check to in_initrd()
    
    initrds can only be on tmpfs or ramfs, so check for that

diff --git a/TODO b/TODO
index 96db4a5..3d55f8a 100644
--- a/TODO
+++ b/TODO
@@ -20,6 +20,18 @@ Bugfixes:
 * we pull src/core/manager.h into src/shared/src/shared/path-lookup.c which is the wrong direction
    rename enum "ManagerRunningAs" to "SystemdRunningAs" and move it to shared/
 
+* crash happens when running a service as forking and then changing it to simple and reloading.
+
+  Jul 09 18:20:57 mop systemd[1]: usbmuxd.service operation timed out. Terminating.
+  Jul 09 18:20:57 mop systemd[1]: Unit usbmuxd.service entered failed state.
+  Jul 09 18:22:24 mop systemd[1]: PID 21814 read from file /var/run/usbmuxd.pid does not exist.
+  Jul 09 18:22:24 mop systemd[1]: Unit usbmuxd.service entered failed state.
+  Jul 09 18:22:33 mop systemd[1]: Reloading.
+  Jul 09 18:22:37 mop systemd[1]: Assertion 's->type == SERVICE_FORKING' failed at src/core/service.c:3007, function service_sigchld_eve...Aborting.
+  Jul 09 18:22:37 mop systemd[1]: Caught <ABRT>, dumped core as pid 21865.
+  Jul 09 18:22:37 mop systemd[1]: Freezing execution.
+  Jul 09 18:22:37 mop [21866]: Process 21865 (systemd) dumped core.
+
 Features:
 
 * switch-root add extra safety check
diff --git a/src/shared/util.c b/src/shared/util.c
index 41505b2..8caac7b 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -54,6 +54,8 @@
 #include <glob.h>
 #include <grp.h>
 #include <sys/mman.h>
+#include <sys/vfs.h>
+#include <linux/magic.h>
 
 #include "macro.h"
 #include "util.h"
@@ -5738,9 +5740,24 @@ bool is_valid_documentation_url(const char *url) {
 
 bool in_initrd(void) {
         static int saved = -1;
+        struct statfs s;
 
-        if (saved < 0)
-                saved = access("/etc/initrd-release", F_OK) >= 0;
+        if (saved >= 0)
+                return saved;
+
+        /* We make two checks here:
+         *
+         * 1. the flag file /etc/initrd-release must exist
+         * 2. the root file system must be a memory file system
+         *
+         * The second check is extra paranoia, since misdetecting an
+         * initrd can have bad bad consequences due the initrd
+         * emptying when transititioning to the main systemd.
+         */
+
+        saved = access("/etc/initrd-release", F_OK) >= 0 &&
+                statfs("/", &s) >= 0 &&
+                (s.f_type == TMPFS_MAGIC || s.f_type == RAMFS_MAGIC);
 
         return saved;
 }

commit 36fcd77e02cedf300e2f45f2449e7e091ef5a7ab
Author: Malte Starostik <m-starostik at versanet.de>
Date:   Tue Jun 5 21:10:28 2012 +0200

    mount: fix for complex automounts
    
    If accessing an automount point triggers more changes to
    /proc/self/mountinfo than just to add the directly wanted mount, these
    changes can lead to spurious -ENODEV notifications on the automount unit
    causing the request to fail when in fact the mount will be setup right
    afterwards.

diff --git a/src/core/mount.c b/src/core/mount.c
index 69cb6e2..fab922e 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -687,8 +687,10 @@ static void mount_set_state(Mount *m, MountState state) {
                  state == MOUNT_REMOUNTING_SIGKILL ||
                  state == MOUNT_UNMOUNTING_SIGTERM ||
                  state == MOUNT_UNMOUNTING_SIGKILL ||
-                 state == MOUNT_FAILED)
-                mount_notify_automount(m, -ENODEV);
+                 state == MOUNT_FAILED) {
+		if (state != old_state)
+			mount_notify_automount(m, -ENODEV);
+	}
 
         if (state != old_state)
                 log_debug("%s changed %s -> %s",



More information about the systemd-commits mailing list