[systemd-devel] [PATCH 2/2] logind: chown+chmod /run/user/$UID if mount(tmpfs) fails with EPERM
Christian Seiler
christian at iwakd.de
Fri Jan 23 06:26:19 PST 2015
In containers without CAP_SYS_ADMIN, it is not possible to mount tmpfs
(or any filesystem for that matter) on top of /run/user/$UID.
Previously, logind just failed in such a situation.
Now, logind will resort to chown+chmod of the directory instead. This
allows logind still to work in those environments, although without the
guarantees it provides (i.e. users not being able to DOS /run or other
users' /run/user/$UID space) when CAP_SYS_ADMIN is available.
---
src/login/logind-user.c | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index d7930ad..3f7e3ce 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -335,12 +335,28 @@ static int user_mkdir_runtime_path(User *u) {
}
r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t);
- if (r < 0) {
+ if (r < 0 && errno != EPERM) {
/* try to clean up, but ignore errors */
r = -errno;
rmdir(p);
log_error_errno(r, "Failed to mount per-user tmpfs directory %s: %m", p);
goto fail;
+ } else if (r < 0 && errno == EPERM) {
+ /* we probably don't have CAP_SYS_ADMIN and are in a
+ * container, so just try to chown()/chmod() the
+ * directory. */
+ log_debug("Failed to mount per-user tmpfs directory %s, just setting permissions.", p);
+
+ r = chown(p, u->uid, u->gid);
+ if (r >= 0)
+ r = chmod(p, 0700);
+
+ if (r < 0) {
+ r = -errno;
+ rmdir(p);
+ log_error_errno(r, "Failed to change permissions of per-user tmpfs directory %s: %m", p);
+ goto fail;
+ }
}
}
@@ -513,8 +529,17 @@ static int user_remove_runtime_path(User *u) {
if (r < 0)
log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
- if (umount2(u->runtime_path, MNT_DETACH) < 0)
- log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
+ r = umount2(u->runtime_path, MNT_DETACH);
+ if (r < 0) {
+ r = -errno;
+ /* only log an error if the directory was a mount point,
+ * otherwise it could just be that we weren't able to
+ * mount it because we don't have CAP_SYS_AMDIN. */
+ if (path_is_mount_point(u->runtime_path, false) > 0)
+ log_error_errno(r, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
+ else
+ log_debug_errno(r, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
+ }
r = rm_rf(u->runtime_path, false, true, false);
if (r < 0)
--
2.1.4
More information about the systemd-devel
mailing list