[systemd-devel] [PATCH v3] Refuse mount on symlink

Timofey Titovets nefelim4ag at gmail.com
Thu Aug 14 15:43:17 PDT 2014


Just complete TODO:
* refuse mounting on symlinks

I not add this TODO, but i think what it avoid potential security 
{and/or} bug issues

v2 -> v3:
Rebase on latest git
Add message <unit>: Mount on symlink <path> not allowed.

if systemd try mounting entry from fstab on symlink, user get:
$ systemctl status symlink.mount 
 
           [1:29:45]
● symlink.mount - /symlink
    Loaded: loaded (/etc/fstab)
    Active: failed (Result: resources)
     Where: /symlink
      What: /dev/sda2
      Docs: man:fstab(5)
            man:systemd-fstab-generator(8)

Aug 15 01:26:47 beplan.lan systemd[1]: Mounting /symlink...
Aug 15 01:26:47 beplan.lan systemd[1]: symlink.mount: Mount on symlink 
/symlink not allowed.
Aug 15 01:26:47 beplan.lan systemd[1]: symlink.mount failed to run 
'mount' task: Too many levels of symbolic links
Aug 15 01:26:47 beplan.lan systemd[1]: Failed to mount /symlink.
Aug 15 01:26:47 beplan.lan systemd[1]: Unit symlink.mount entered failed 
state.

can be pulled from:
https://github.com/Nefelim4ag/systemd.git

----
  TODO              |  2 --
  src/core/mount.c  | 21 +++++++++++++++++++++
  src/core/mount.h  |  2 ++
  src/shared/util.c | 12 ++++++++++++
  src/shared/util.h |  2 ++
  5 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/TODO b/TODO
index d58da71..c8e9f27 100644
--- a/TODO
+++ b/TODO
@@ -93,8 +93,6 @@ Features:

  * Add a new verb "systemctl top"

-* refuse mounting on symlinks
-
  * logind: allow users to kill or lock their own sessions

  * add new gpt type for btrfs volumes
diff --git a/src/core/mount.c b/src/core/mount.c
index 39a9aaf..f51e0f3 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -827,6 +827,23 @@ void warn_if_dir_nonempty(const char *unit, const 
char* where) {
                     NULL);
  }

+int fail_if_symlink(const char *unit, const char* where) {
+        assert(where);
+
+        if (is_symlink(where) > 0) {
+                log_struct_unit(LOG_WARNING,
+                                unit,
+                                "MESSAGE=%s: Mount on symlink %s not 
allowed.",
+                                unit, where,
+                                "WHERE=%s", where,
+                                MESSAGE_ID(SD_MESSAGE_OVERMOUNTING),
+                                NULL);
+
+                return -ELOOP;
+        }
+        return 0;
+}
+
  static void mount_enter_unmounting(Mount *m) {
          int r;

@@ -877,6 +894,10 @@ static void mount_enter_mounting(Mount *m) {
          if (p && mount_is_bind(p))
                  mkdir_p_label(p->what, m->directory_mode);

+        r = fail_if_symlink(m->meta.id, m->where);
+        if (r < 0)
+                goto fail;
+
          if (m->from_fragment)
                  r = exec_command_set(
                                  m->control_command,
diff --git a/src/core/mount.h b/src/core/mount.h
index 2dcb663..5fc1fe1 100644
--- a/src/core/mount.h
+++ b/src/core/mount.h
@@ -128,3 +128,5 @@ const char* mount_result_to_string(MountResult i) 
_const_;
  MountResult mount_result_from_string(const char *s) _pure_;

  void warn_if_dir_nonempty(const char *unit, const char* where);
+
+int fail_if_symlink(const char *unit, const char* where);
\ No newline at end of file
diff --git a/src/shared/util.c b/src/shared/util.c
index 3d16cd1..0db4bd9 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -6918,3 +6918,15 @@ int take_password_lock(const char *root) {

          return fd;
  }
+
+int is_symlink(const char *path) {
+        struct stat info;
+
+        if (lstat(path, &info) < 0)
+                return -errno;
+
+        if (S_ISLNK(info.st_mode))
+                return 1;
+
+        return 0;
+}
\ No newline at end of file
diff --git a/src/shared/util.h b/src/shared/util.h
index 101d2df..bd8bbb2 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -966,3 +966,5 @@ char *tempfn_random(const char *p);
  bool is_localhost(const char *hostname);

  int take_password_lock(const char *root);
+
+int is_symlink(const char *path);
\ No newline at end of file



More information about the systemd-devel mailing list