aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2016-07-23 12:20:44 -0400
committerEric W. Biederman <ebiederm@xmission.com>2016-07-23 15:51:26 -0400
commitaeaa4a79ff6a5ed912b7362f206cf8576fca538b (patch)
treecfdd5207fef5e23cf7dc84691cd3301faa9688ec
parent81754357770ebd900801231e7bc8d151ddc00498 (diff)
fs: Call d_automount with the filesystems creds
Seth Forshee reported a mount regression in nfs autmounts with "fs: Add user namespace member to struct super_block". It turns out that the assumption that current->cred is something reasonable during mount while necessary to improve support of unprivileged mounts is wrong in the automount path. To fix the existing filesystems override current->cred with the init_cred before calling d_automount and restore current->cred after d_automount completes. To support unprivileged mounts would require a more nuanced cred selection, so fail on unprivileged mounts for the time being. As none of the filesystems that currently set FS_USERNS_MOUNT implement d_automount this check is only good for preventing future problems. Fixes: 6e4eab577a0c ("fs: Add user namespace member to struct super_block") Tested-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--fs/namei.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 629823f19a6a..ef573df3297f 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -36,6 +36,7 @@
36#include <linux/posix_acl.h> 36#include <linux/posix_acl.h>
37#include <linux/hash.h> 37#include <linux/hash.h>
38#include <linux/bitops.h> 38#include <linux/bitops.h>
39#include <linux/init_task.h>
39#include <asm/uaccess.h> 40#include <asm/uaccess.h>
40 41
41#include "internal.h" 42#include "internal.h"
@@ -1099,6 +1100,7 @@ static int follow_automount(struct path *path, struct nameidata *nd,
1099 bool *need_mntput) 1100 bool *need_mntput)
1100{ 1101{
1101 struct vfsmount *mnt; 1102 struct vfsmount *mnt;
1103 const struct cred *old_cred;
1102 int err; 1104 int err;
1103 1105
1104 if (!path->dentry->d_op || !path->dentry->d_op->d_automount) 1106 if (!path->dentry->d_op || !path->dentry->d_op->d_automount)
@@ -1120,11 +1122,16 @@ static int follow_automount(struct path *path, struct nameidata *nd,
1120 path->dentry->d_inode) 1122 path->dentry->d_inode)
1121 return -EISDIR; 1123 return -EISDIR;
1122 1124
1125 if (path->dentry->d_sb->s_user_ns != &init_user_ns)
1126 return -EACCES;
1127
1123 nd->total_link_count++; 1128 nd->total_link_count++;
1124 if (nd->total_link_count >= 40) 1129 if (nd->total_link_count >= 40)
1125 return -ELOOP; 1130 return -ELOOP;
1126 1131
1132 old_cred = override_creds(&init_cred);
1127 mnt = path->dentry->d_op->d_automount(path); 1133 mnt = path->dentry->d_op->d_automount(path);
1134 revert_creds(old_cred);
1128 if (IS_ERR(mnt)) { 1135 if (IS_ERR(mnt)) {
1129 /* 1136 /*
1130 * The filesystem is allowed to return -EISDIR here to indicate 1137 * The filesystem is allowed to return -EISDIR here to indicate