[systemd-devel] [PATCH 2/2] logind: chown+chmod /run/user/$UID if mount(tmpfs) fails with EPERM
Lennart Poettering
lennart at poettering.net
Tue Jan 27 10:02:53 PST 2015
On Fri, 23.01.15 15:26, Christian Seiler (christian at iwakd.de) wrote:
> 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.
Merged this one too, made some changes first howver. I reworked this
to use our chmod_and_chown() helper, and removed the bit that checks
whether the mount point actually was a mount point after umount2(). I
really prefer if we can just check the return value of the syscall and
decide on that.
Please check if this all works for you now!
Thanks!
> ---
> 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
>
>
Lennart
--
Lennart Poettering, Red Hat
More information about the systemd-devel
mailing list