chiark / gitweb /
logind: fix /run/user/$UID creation in apparmor-confined containers (#4154)
authorTomáš Janoušek <tomi@nomi.cz>
Thu, 15 Sep 2016 23:26:31 +0000 (01:26 +0200)
committerSven Eden <yamakuzure@gmx.net>
Wed, 5 Jul 2017 06:50:53 +0000 (08:50 +0200)
When a docker container is confined with AppArmor [1] and happens to run
on top of a kernel that supports mount mediation [2], e.g. any Ubuntu
kernel, mount(2) returns EACCES instead of EPERM.  This then leads to:

    elogind-logind[33]: Failed to mount per-user tmpfs directory /run/user/1000: Permission denied
    login[42]: pam_elogind(login:session): Failed to create session: Access denied

and user sessions don't start.

This also applies to selinux that too returns EACCES on mount denial.

[1] https://github.com/docker/docker/blob/master/docs/security/apparmor.md#understand-the-policies
[2] http://bazaar.launchpad.net/~apparmor-dev/apparmor/master/view/head:/kernel-patches/4.7/0025-UBUNTU-SAUCE-apparmor-Add-the-ability-to-mediate-mou.patch

src/login/logind-user.c

index 8a84a8f80d5accd2fb62c971a1bfb1eefc48f497..304e6b512915f7ea4b00f7dabdf00737ff7b063c 100644 (file)
@@ -362,14 +362,12 @@ static int user_mkdir_runtime_path(User *u) {
 
                 r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
                 if (r < 0) {
-                        if (errno != EPERM) {
+                        if (errno != EPERM && errno != EACCES) {
                                 r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
                                 goto fail;
                         }
 
-                        /* Lacking permissions, maybe
-                         * CAP_SYS_ADMIN-less container? In this case,
-                         * just use a normal directory. */
+                        log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u->runtime_path);
 
                         r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid);
                         if (r < 0) {