From: Serge Hallyn <serge.hallyn@ubuntu.com>
To: Djalal Harouni <tixxdz@gmail.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>,
Chris Mason <clm@fb.com>,
tytso@mit.edu, Serge Hallyn <serge.hallyn@canonical.com>,
Josh Triplett <josh@joshtriplett.org>,
"Eric W. Biederman" <ebiederm@xmission.com>,
Andy Lutomirski <luto@kernel.org>,
Seth Forshee <seth.forshee@canonical.com>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org,
Dongsu Park <dongsu@endocode.com>,
David Herrmann <dh.herrmann@googlemail.com>,
Miklos Szeredi <mszeredi@redhat.com>,
Alban Crequy <alban.crequy@gmail.com>,
Djalal Harouni <tixxdz@opendz.org>
Subject: Re: [RFC v2 PATCH 3/8] fs: Treat foreign mounts as nosuid
Date: Wed, 4 May 2016 23:19:04 +0000 [thread overview]
Message-ID: <20160504231904.GA17801@ubuntumail> (raw)
In-Reply-To: <1462372014-3786-4-git-send-email-tixxdz@gmail.com>
Quoting Djalal Harouni (tixxdz@gmail.com):
> If a process gets access to a mount from a different user
> namespace, that process should not be able to take advantage of
> setuid files or selinux entrypoints from that filesystem. Prevent
> this by treating mounts from other mount namespaces and those not
> owned by current_user_ns() or an ancestor as nosuid.
>
> This patch was just adapted from the original one that was written
> by Andy Lutomirski <luto@amacapital.net>
> https://www.redhat.com/archives/dm-devel/2016-April/msg00374.html
I'm not sure that this makes sense given what you're doing. In the
case of Seth's set, a filesystem is mounted specifically (and privately)
in a user namespace. We don't want for instance the initial user ns
to find a link to a setuid-root exploit left in the container-mounted
filesystem.
But you are having a parent user namespace mount the fs so that its
children can all access the fs, uid-shifted for convenience. Not
allowing the child namespaces to make use of setuid-root does not
seem applicable here.
> Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
> ---
> fs/exec.c | 2 +-
> fs/namespace.c | 15 +++++++++++++++
> include/linux/mount.h | 1 +
> include/linux/user_namespace.h | 8 ++++++++
> kernel/user_namespace.c | 13 +++++++++++++
> security/commoncap.c | 2 +-
> security/selinux/hooks.c | 2 +-
> 7 files changed, 40 insertions(+), 3 deletions(-)
>
> diff --git a/fs/exec.c b/fs/exec.c
> index c4010b8..706088d 100644
> --- a/fs/exec.c
> +++ b/fs/exec.c
> @@ -1391,7 +1391,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
> bprm->cred->euid = current_euid();
> bprm->cred->egid = current_egid();
>
> - if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
> + if (!mnt_may_suid(bprm->file->f_path.mnt))
> return;
>
> if (task_no_new_privs(current))
> diff --git a/fs/namespace.c b/fs/namespace.c
> index de02b39..a8820fb 100644
> --- a/fs/namespace.c
> +++ b/fs/namespace.c
> @@ -3374,6 +3374,21 @@ found:
> return visible;
> }
>
> +bool mnt_may_suid(struct vfsmount *mnt)
> +{
> + struct mount *m = real_mount(mnt);
> +
> + /*
> + * Foreign mounts (accessed via fchdir or through /proc
> + * symlinks) are always treated as if they are nosuid. This
> + * prevents namespaces from trusting potentially unsafe
> + * suid/sgid bits, file caps, or security labels that originate
> + * in other namespaces.
> + */
> + return !(mnt->mnt_flags & MNT_NOSUID) && check_mnt(m) &&
> + in_userns(current_user_ns(), m->mnt_ns->user_ns);
> +}
> +
> static struct ns_common *mntns_get(struct task_struct *task)
> {
> struct ns_common *ns = NULL;
> diff --git a/include/linux/mount.h b/include/linux/mount.h
> index f822c3c..54a594d 100644
> --- a/include/linux/mount.h
> +++ b/include/linux/mount.h
> @@ -81,6 +81,7 @@ extern void mntput(struct vfsmount *mnt);
> extern struct vfsmount *mntget(struct vfsmount *mnt);
> extern struct vfsmount *mnt_clone_internal(struct path *path);
> extern int __mnt_is_readonly(struct vfsmount *mnt);
> +extern bool mnt_may_suid(struct vfsmount *mnt);
>
> struct path;
> extern struct vfsmount *clone_private_mount(struct path *path);
> diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
> index 8297e5b..a43faa7 100644
> --- a/include/linux/user_namespace.h
> +++ b/include/linux/user_namespace.h
> @@ -72,6 +72,8 @@ extern ssize_t proc_projid_map_write(struct file *, const char __user *, size_t,
> extern ssize_t proc_setgroups_write(struct file *, const char __user *, size_t, loff_t *);
> extern int proc_setgroups_show(struct seq_file *m, void *v);
> extern bool userns_may_setgroups(const struct user_namespace *ns);
> +extern bool in_userns(const struct user_namespace *ns,
> + const struct user_namespace *target_ns);
> #else
>
> static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
> @@ -100,6 +102,12 @@ static inline bool userns_may_setgroups(const struct user_namespace *ns)
> {
> return true;
> }
> +
> +static inline bool in_userns(const struct user_namespace *ns,
> + const struct user_namespace *target_ns)
> +{
> + return true;
> +}
> #endif
>
> #endif /* _LINUX_USER_H */
> diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
> index 9bafc21..9a496a8 100644
> --- a/kernel/user_namespace.c
> +++ b/kernel/user_namespace.c
> @@ -938,6 +938,19 @@ bool userns_may_setgroups(const struct user_namespace *ns)
> return allowed;
> }
>
> +/*
> + * Returns true if @ns is the same namespace as or a descendant of
> + * @target_ns.
> + */
> +bool in_userns(const struct user_namespace *ns,
> + const struct user_namespace *target_ns)
> +{
> + for (; ns; ns = ns->parent) {
> + if (ns == target_ns)
> + return true;
> + }
> +}
> +
> static inline struct user_namespace *to_user_ns(struct ns_common *ns)
> {
> return container_of(ns, struct user_namespace, ns);
> diff --git a/security/commoncap.c b/security/commoncap.c
> index 48071ed..6c082d2 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -453,7 +453,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
> if (!file_caps_enabled)
> return 0;
>
> - if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
> + if (!mnt_may_suid(bprm->file->f_path.mnt))
> return 0;
>
> rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps);
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 912deee..1350167 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -2234,7 +2234,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
> const struct task_security_struct *new_tsec)
> {
> int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
> - int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
> + int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
> int rc;
>
> if (!nnp && !nosuid)
> --
> 2.5.5
>
next prev parent reply other threads:[~2016-05-04 23:19 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-04 14:26 [RFC v2 PATCH 0/8] VFS:userns: support portable root filesystems Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 1/8] VFS: add CLONE_MNTNS_SHIFT_UIDGID flag to allow mounts to shift their UIDs/GIDs Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 2/8] VFS:uidshift: add flags and helpers to shift UIDs and GIDs to virtual view Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 3/8] fs: Treat foreign mounts as nosuid Djalal Harouni
2016-05-04 23:19 ` Serge Hallyn [this message]
2016-05-05 13:05 ` Seth Forshee
2016-05-05 22:40 ` Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 4/8] VFS:userns: shift UID/GID to virtual view during permission access Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 5/8] VFS:userns: add helpers to shift UIDs and GIDs into on-disk view Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 6/8] VFS:userns: shift UID/GID to on-disk view before any write to disk Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 7/8] ext4: add support for vfs_shift_uids and vfs_shift_gids mount options Djalal Harouni
2016-05-04 14:26 ` [RFC v2 PATCH 8/8] btrfs: " Djalal Harouni
2016-05-04 16:34 ` [RFC v2 PATCH 0/8] VFS:userns: support portable root filesystems Josh Triplett
2016-05-04 21:06 ` James Bottomley
2016-05-05 7:36 ` Djalal Harouni
2016-05-05 11:56 ` James Bottomley
2016-05-05 21:49 ` Djalal Harouni
2016-05-05 22:08 ` James Bottomley
2016-05-10 23:36 ` James Bottomley
2016-05-11 0:38 ` Al Viro
2016-05-11 0:53 ` Al Viro
2016-05-11 3:47 ` James Bottomley
2016-05-11 16:42 ` Djalal Harouni
2016-05-11 18:33 ` James Bottomley
2016-05-12 19:55 ` Djalal Harouni
2016-05-12 22:24 ` James Bottomley
2016-05-14 9:53 ` Djalal Harouni
2016-05-14 13:46 ` James Bottomley
2016-05-15 2:21 ` Eric W. Biederman
2016-05-15 15:04 ` James Bottomley
2016-05-16 14:12 ` Seth Forshee
2016-05-16 16:42 ` Eric W. Biederman
2016-05-16 18:25 ` Seth Forshee
2016-05-16 19:13 ` James Bottomley
2016-05-17 22:40 ` Eric W. Biederman
2016-05-17 11:42 ` Djalal Harouni
2016-05-17 15:42 ` Djalal Harouni
2016-05-04 23:30 ` Serge Hallyn
2016-05-06 14:38 ` Djalal Harouni
2016-05-09 16:26 ` Serge Hallyn
2016-05-10 10:33 ` Djalal Harouni
2016-05-05 0:23 ` Dave Chinner
2016-05-05 1:44 ` Andy Lutomirski
2016-05-05 2:25 ` Dave Chinner
2016-05-05 3:29 ` Andy Lutomirski
2016-05-05 22:34 ` Djalal Harouni
2016-05-05 22:24 ` Djalal Harouni
2016-05-06 2:50 ` Dave Chinner
2016-05-12 19:47 ` Djalal Harouni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160504231904.GA17801@ubuntumail \
--to=serge.hallyn@ubuntu.com \
--cc=alban.crequy@gmail.com \
--cc=clm@fb.com \
--cc=dh.herrmann@googlemail.com \
--cc=dongsu@endocode.com \
--cc=ebiederm@xmission.com \
--cc=josh@joshtriplett.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mszeredi@redhat.com \
--cc=serge.hallyn@canonical.com \
--cc=seth.forshee@canonical.com \
--cc=tixxdz@gmail.com \
--cc=tixxdz@opendz.org \
--cc=tytso@mit.edu \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).