diff options
author | Christian Brauner <christian.brauner@ubuntu.com> | 2021-01-21 14:19:42 +0100 |
---|---|---|
committer | Christian Brauner <christian.brauner@ubuntu.com> | 2021-01-24 14:27:19 +0100 |
commit | 1ab29965b30599c797266eb3b970b4e6c8de3672 (patch) | |
tree | 3fcc302263b0b5a129712eef9716e1cf9ef9e2ff | |
parent | 435ac6214e00eab191296cd6cfdc316aa07e7794 (diff) | |
download | lwn-1ab29965b30599c797266eb3b970b4e6c8de3672.tar.gz lwn-1ab29965b30599c797266eb3b970b4e6c8de3672.zip |
exec: handle idmapped mounts
When executing a setuid binary the kernel will verify in bprm_fill_uid()
that the inode has a mapping in the caller's user namespace before
setting the callers uid and gid. Let bprm_fill_uid() handle idmapped
mounts. If the inode is accessed through an idmapped mount it is mapped
according to the mount's user namespace. Afterwards the checks are
identical to non-idmapped mounts. If the initial user namespace is
passed nothing changes so non-idmapped mounts will see identical
behavior as before.
Link: https://lore.kernel.org/r/20210121131959.646623-24-christian.brauner@ubuntu.com
Cc: Christoph Hellwig <hch@lst.de>
Cc: David Howells <dhowells@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-fsdevel@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: James Morris <jamorris@linux.microsoft.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
-rw-r--r-- | fs/exec.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/exec.c b/fs/exec.c index d803227805f6..48d1e8b1610b 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1580,6 +1580,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm) static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) { /* Handle suid and sgid on files */ + struct user_namespace *mnt_userns; struct inode *inode; unsigned int mode; kuid_t uid; @@ -1596,13 +1597,15 @@ static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file) if (!(mode & (S_ISUID|S_ISGID))) return; + mnt_userns = file_mnt_user_ns(file); + /* Be careful if suid/sgid is set */ inode_lock(inode); /* reload atomically mode/uid/gid now that lock held */ mode = inode->i_mode; - uid = inode->i_uid; - gid = inode->i_gid; + uid = i_uid_into_mnt(mnt_userns, inode); + gid = i_gid_into_mnt(mnt_userns, inode); inode_unlock(inode); /* We ignore suid/sgid if there are no mappings for them in the ns */ |