History

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace

Pull namespace updates from Eric Biederman: "This is a bunch of small changes built against 3.16-rc6. The most significant change for users is the first patch which makes setns drmatically faster by removing unneded rcu handling. The next chunk of changes are so that "mount -o remount,.." will not allow the user namespace root to drop flags on a mount set by the system wide root. Aks this forces read-only mounts to stay read-only, no-dev mounts to stay no-dev, no-suid mounts to stay no-suid, no-exec mounts to stay no exec and it prevents unprivileged users from messing with a mounts atime settings. I have included my test case as the last patch in this series so people performing backports can verify this change works correctly. The next change fixes a bug in NFS that was discovered while auditing nsproxy users for the first optimization. Today you can oops the kernel by reading /proc/fs/nfsfs/{servers,volumes} if you are clever with pid namespaces. I rebased and fixed the build of the !CONFIG_NFS_FS case yesterday when a build bot caught my typo. Given that no one to my knowledge bases anything on my tree fixing the typo in place seems more responsible that requiring a typo-fix to be backported as well. The last change is a small semantic cleanup introducing /proc/thread-self and pointing /proc/mounts and /proc/net at it. This prevents several kinds of problemantic corner cases. It is a user-visible change so it has a minute chance of causing regressions so the change to /proc/mounts and /proc/net are individual one line commits that can be trivially reverted. Unfortunately I lost and could not find the email of the original reporter so he is not credited. From at least one perspective this change to /proc/net is a refgression fix to allow pthread /proc/net uses that were broken by the introduction of the network namespace" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: proc: Point /proc/mounts at /proc/thread-self/mounts instead of /proc/self/mounts proc: Point /proc/net at /proc/thread-self/net instead of /proc/self/net proc: Implement /proc/thread-self to point at the directory of the current thread proc: Have net show up under /proc/<tgid>/task/<tid> NFS: Fix /proc/fs/nfsfs/servers and /proc/fs/nfsfs/volumes mnt: Add tests for unprivileged remount cases that have found to be faulty mnt: Change the default remount atime from relatime to the existing value mnt: Correct permission checks in do_remount mnt: Move the test for MNT_LOCK_READONLY from change_mount_flags into do_remount mnt: Only change user settable mount flags in remount namespaces: Use task_lock and not rcu to protect nsproxy

Linus Torvalds committed 12 years ago

Commit 77e40aa2 parents 96784de 344470c23 files · +537 −97Browse files

Unified · Split

23 files
  1. fs/namespace.c +55 −10
  2. fs/nfs/client.c +55 −40
  3. fs/nfs/inode.c +2 −1
  4. fs/nfs/internal.h +9 −0
  5. fs/nfs/netns.h +3 −0
  6. fs/proc/Makefile +1 −0
  7. fs/proc/base.c +13 −5
  8. fs/proc/inode.c +6 −1
  9. fs/proc/internal.h +6 −0
  10. fs/proc/proc_net.c +4 −2
  11. fs/proc/root.c +4 −1
  12. fs/proc/thread_self.c +85 −0
  13. fs/proc_namespace.c +3 −5
  14. include/linux/mount.h +8 −1
  15. include/linux/nsproxy.h +6 −10
  16. include/linux/pid_namespace.h +1 −0
  17. ipc/namespace.c +3 −3
  18. kernel/nsproxy.c +4 −11
  19. kernel/utsname.c +3 −3
  20. net/core/net_namespace.c +6 −4
  21. tools/testing/selftests/Makefile +1 −0
  22. tools/testing/selftests/mount/Makefile +17 −0
  23. tools/testing/selftests/mount/unprivileged-remount-test.c +242 −0
fs/namespace.c+55−10
@@ -890,8 +890,21 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, · 889 unmodified lines
890890
891891 mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED);
892892 /* Don't allow unprivileged users to change mount flags */
893− if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))
894− mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
893+ if (flag & CL_UNPRIVILEGED) {
894+ mnt->mnt.mnt_flags |= MNT_LOCK_ATIME;
895+
896+ if (mnt->mnt.mnt_flags & MNT_READONLY)
897+ mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
898+
899+ if (mnt->mnt.mnt_flags & MNT_NODEV)
900+ mnt->mnt.mnt_flags |= MNT_LOCK_NODEV;
901+
902+ if (mnt->mnt.mnt_flags & MNT_NOSUID)
903+ mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID;
904+
905+ if (mnt->mnt.mnt_flags & MNT_NOEXEC)
906+ mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC;
907+ }
895908
896909 /* Don't allow unprivileged users to reveal what is under a mount */
897910 if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire))
@@ -1896,9 +1909,6 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags) · 998 unmodified lines
18961909 if (readonly_request == __mnt_is_readonly(mnt))
18971910 return 0;
18981911
1899− if (mnt->mnt_flags & MNT_LOCK_READONLY)
1900− return -EPERM;
1901−
19021912 if (readonly_request)
19031913 error = mnt_make_readonly(real_mount(mnt));
19041914 else
@@ -1924,6 +1934,33 @@ static int do_remount(struct path *path, int flags, int mnt_flags, · 19 unmodified lines
19241934 if (path->dentry != path->mnt->mnt_root)
19251935 return -EINVAL;
19261936
1937+ /* Don't allow changing of locked mnt flags.
1938+ *
1939+ * No locks need to be held here while testing the various
1940+ * MNT_LOCK flags because those flags can never be cleared
1941+ * once they are set.
1942+ */
1943+ if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) &&
1944+ !(mnt_flags & MNT_READONLY)) {
1945+ return -EPERM;
1946+ }
1947+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
1948+ !(mnt_flags & MNT_NODEV)) {
1949+ return -EPERM;
1950+ }
1951+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) &&
1952+ !(mnt_flags & MNT_NOSUID)) {
1953+ return -EPERM;
1954+ }
1955+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) &&
1956+ !(mnt_flags & MNT_NOEXEC)) {
1957+ return -EPERM;
1958+ }
1959+ if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) &&
1960+ ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) {
1961+ return -EPERM;
1962+ }
1963+
19271964 err = security_sb_remount(sb, data);
19281965 if (err)
19291966 return err;
@@ -1937,7 +1974,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags, · 7 unmodified lines
19371974 err = do_remount_sb(sb, flags, data, 0);
19381975 if (!err) {
19391976 lock_mount_hash();
1940− mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
1977+ mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
19411978 mnt->mnt.mnt_flags = mnt_flags;
19421979 touch_mnt_namespace(mnt->mnt_ns);
19431980 unlock_mount_hash();
@@ -2122,7 +2159,7 @@ static int do_new_mount(struct path *path, const char *fstype, int flags, · 178 unmodified lines
21222159 */
21232160 if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) {
21242161 flags |= MS_NODEV;
2125− mnt_flags |= MNT_NODEV;
2162+ mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
21262163 }
21272164 }
21282165
@@ -2436,6 +2473,14 @@ long do_mount(const char *dev_name, const char *dir_name, · 307 unmodified lines
24362473 if (flags & MS_RDONLY)
24372474 mnt_flags |= MNT_READONLY;
24382475
2476+ /* The default atime for remount is preservation */
2477+ if ((flags & MS_REMOUNT) &&
2478+ ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
2479+ MS_STRICTATIME)) == 0)) {
2480+ mnt_flags &= ~MNT_ATIME_MASK;
2481+ mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK;
2482+ }
2483+
24392484 flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
24402485 MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
24412486 MS_STRICTATIME);
@@ -2972,13 +3017,13 @@ static void *mntns_get(struct task_struct *task) · 530 unmodified lines
29723017 struct mnt_namespace *ns = NULL;
29733018 struct nsproxy *nsproxy;
29743019
2975− rcu_read_lock();
2976− nsproxy = task_nsproxy(task);
3020+ task_lock(task);
3021+ nsproxy = task->nsproxy;
29773022 if (nsproxy) {
29783023 ns = nsproxy->mnt_ns;
29793024 get_mnt_ns(ns);
29803025 }
2981− rcu_read_unlock();
3026+ task_unlock(task);
29823027
29833028 return ns;
29843029 }
fs/nfs/client.c+55−40
@@ -1205,7 +1205,7 @@ static const struct file_operations nfs_server_list_fops = { · 1204 unmodified lines
12051205 .open = nfs_server_list_open,
12061206 .read = seq_read,
12071207 .llseek = seq_lseek,
1208− .release = seq_release,
1208+ .release = seq_release_net,
12091209 .owner = THIS_MODULE,
12101210 };
12111211
@@ -1226,7 +1226,7 @@ static const struct file_operations nfs_volume_list_fops = { · 14 unmodified lines
12261226 .open = nfs_volume_list_open,
12271227 .read = seq_read,
12281228 .llseek = seq_lseek,
1229− .release = seq_release,
1229+ .release = seq_release_net,
12301230 .owner = THIS_MODULE,
12311231 };
12321232
@@ -1236,19 +1236,8 @@ static const struct file_operations nfs_volume_list_fops = { · 3 unmodified lines
12361236 */
12371237 static int nfs_server_list_open(struct inode *inode, struct file *file)
12381238 {
1239− struct seq_file *m;
1240− int ret;
1241− struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info;
1242− struct net *net = pid_ns->child_reaper->nsproxy->net_ns;
1243−
1244− ret = seq_open(file, &nfs_server_list_ops);
1245− if (ret < 0)
1246− return ret;
1247−
1248− m = file->private_data;
1249− m->private = net;
1250−
1251− return 0;
1239+ return seq_open_net(inode, file, &nfs_server_list_ops,
1240+ sizeof(struct seq_net_private));
12521241 }
12531242
12541243 /*
@@ -1256,7 +1245,7 @@ static int nfs_server_list_open(struct inode *inode, struct file *file) · 1 unmodified line
12561245 */
12571246 static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
12581247 {
1259− struct nfs_net *nn = net_generic(m->private, nfs_net_id);
1248+ struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
12601249
12611250 /* lock the list against modification */
12621251 spin_lock(&nn->nfs_client_lock);
@@ -1268,7 +1257,7 @@ static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) · 5 unmodified lines
12681257 */
12691258 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
12701259 {
1271− struct nfs_net *nn = net_generic(p->private, nfs_net_id);
1260+ struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
12721261
12731262 return seq_list_next(v, &nn->nfs_client_list, pos);
12741263 }
@@ -1278,7 +1267,7 @@ static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) · 3 unmodified lines
12781267 */
12791268 static void nfs_server_list_stop(struct seq_file *p, void *v)
12801269 {
1281− struct nfs_net *nn = net_generic(p->private, nfs_net_id);
1270+ struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
12821271
12831272 spin_unlock(&nn->nfs_client_lock);
12841273 }
@@ -1289,7 +1278,7 @@ static void nfs_server_list_stop(struct seq_file *p, void *v) · 4 unmodified lines
12891278 static int nfs_server_list_show(struct seq_file *m, void *v)
12901279 {
12911280 struct nfs_client *clp;
1292− struct nfs_net *nn = net_generic(m->private, nfs_net_id);
1281+ struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
12931282
12941283 /* display header on line 1 */
12951284 if (v == &nn->nfs_client_list) {
@@ -1321,19 +1310,8 @@ static int nfs_server_list_show(struct seq_file *m, void *v) · 25 unmodified lines
13211310 */
13221311 static int nfs_volume_list_open(struct inode *inode, struct file *file)
13231312 {
1324− struct seq_file *m;
1325− int ret;
1326− struct pid_namespace *pid_ns = file->f_dentry->d_sb->s_fs_info;
1327− struct net *net = pid_ns->child_reaper->nsproxy->net_ns;
1328−
1329− ret = seq_open(file, &nfs_volume_list_ops);
1330− if (ret < 0)
1331− return ret;
1332−
1333− m = file->private_data;
1334− m->private = net;
1335−
1336− return 0;
1313+ return seq_open_net(inode, file, &nfs_server_list_ops,
1314+ sizeof(struct seq_net_private));
13371315 }
13381316
13391317 /*
@@ -1341,7 +1319,7 @@ static int nfs_volume_list_open(struct inode *inode, struct file *file) · 1 unmodified line
13411319 */
13421320 static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
13431321 {
1344− struct nfs_net *nn = net_generic(m->private, nfs_net_id);
1322+ struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
13451323
13461324 /* lock the list against modification */
13471325 spin_lock(&nn->nfs_client_lock);
@@ -1353,7 +1331,7 @@ static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) · 5 unmodified lines
13531331 */
13541332 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
13551333 {
1356− struct nfs_net *nn = net_generic(p->private, nfs_net_id);
1334+ struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
13571335
13581336 return seq_list_next(v, &nn->nfs_volume_list, pos);
13591337 }
@@ -1363,7 +1341,7 @@ static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) · 3 unmodified lines
13631341 */
13641342 static void nfs_volume_list_stop(struct seq_file *p, void *v)
13651343 {
1366− struct nfs_net *nn = net_generic(p->private, nfs_net_id);
1344+ struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
13671345
13681346 spin_unlock(&nn->nfs_client_lock);
13691347 }
@@ -1376,7 +1354,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) · 6 unmodified lines
13761354 struct nfs_server *server;
13771355 struct nfs_client *clp;
13781356 char dev[8], fsid[17];
1379− struct nfs_net *nn = net_generic(m->private, nfs_net_id);
1357+ struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
13801358
13811359 /* display header on line 1 */
13821360 if (v == &nn->nfs_volume_list) {
@@ -1407,6 +1385,45 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) · 24 unmodified lines
14071385 return 0;
14081386 }
14091387
1388+int nfs_fs_proc_net_init(struct net *net)
1389+{
1390+ struct nfs_net *nn = net_generic(net, nfs_net_id);
1391+ struct proc_dir_entry *p;
1392+
1393+ nn->proc_nfsfs = proc_net_mkdir(net, "nfsfs", net->proc_net);
1394+ if (!nn->proc_nfsfs)
1395+ goto error_0;
1396+
1397+ /* a file of servers with which we're dealing */
1398+ p = proc_create("servers", S_IFREG|S_IRUGO,
1399+ nn->proc_nfsfs, &nfs_server_list_fops);
1400+ if (!p)
1401+ goto error_1;
1402+
1403+ /* a file of volumes that we have mounted */
1404+ p = proc_create("volumes", S_IFREG|S_IRUGO,
1405+ nn->proc_nfsfs, &nfs_volume_list_fops);
1406+ if (!p)
1407+ goto error_2;
1408+ return 0;
1409+
1410+error_2:
1411+ remove_proc_entry("servers", nn->proc_nfsfs);
1412+error_1:
1413+ remove_proc_entry("fs/nfsfs", NULL);
1414+error_0:
1415+ return -ENOMEM;
1416+}
1417+
1418+void nfs_fs_proc_net_exit(struct net *net)
1419+{
1420+ struct nfs_net *nn = net_generic(net, nfs_net_id);
1421+
1422+ remove_proc_entry("volumes", nn->proc_nfsfs);
1423+ remove_proc_entry("servers", nn->proc_nfsfs);
1424+ remove_proc_entry("fs/nfsfs", NULL);
1425+}
1426+
14101427 /*
14111428 * initialise the /proc/fs/nfsfs/ directory
14121429 */
@@ -1419,14 +1436,12 @@ int __init nfs_fs_proc_init(void) · 6 unmodified lines
14191436 goto error_0;
14201437
14211438 /* a file of servers with which we're dealing */
1422− p = proc_create("servers", S_IFREG|S_IRUGO,
1423− proc_fs_nfs, &nfs_server_list_fops);
1439+ p = proc_symlink("servers", proc_fs_nfs, "../../net/nfsfs/servers");
14241440 if (!p)
14251441 goto error_1;
14261442
14271443 /* a file of volumes that we have mounted */
1428− p = proc_create("volumes", S_IFREG|S_IRUGO,
1429− proc_fs_nfs, &nfs_volume_list_fops);
1444+ p = proc_symlink("volumes", proc_fs_nfs, "../../net/nfsfs/volumes");
14301445 if (!p)
14311446 goto error_2;
14321447 return 0;
fs/nfs/inode.c+2−1
@@ -1840,11 +1840,12 @@ EXPORT_SYMBOL_GPL(nfs_net_id); · 1839 unmodified lines
18401840 static int nfs_net_init(struct net *net)
18411841 {
18421842 nfs_clients_init(net);
1843− return 0;
1843+ return nfs_fs_proc_net_init(net);
18441844 }
18451845
18461846 static void nfs_net_exit(struct net *net)
18471847 {
1848+ nfs_fs_proc_net_exit(net);
18481849 nfs_cleanup_cb_ident_idr(net);
18491850 }
18501851
fs/nfs/internal.h+9−0
@@ -195,7 +195,16 @@ extern struct rpc_clnt *nfs4_find_or_create_ds_client(struct nfs_client *, · 194 unmodified lines
195195 #ifdef CONFIG_PROC_FS
196196 extern int __init nfs_fs_proc_init(void);
197197 extern void nfs_fs_proc_exit(void);
198+extern int nfs_fs_proc_net_init(struct net *net);
199+extern void nfs_fs_proc_net_exit(struct net *net);
198200 #else
201+static inline int nfs_fs_proc_net_init(struct net *net)
202+{
203+ return 0;
204+}
205+static inline void nfs_fs_proc_net_exit(struct net *net)
206+{
207+}
199208 static inline int nfs_fs_proc_init(void)
200209 {
201210 return 0;
fs/nfs/netns.h+3−0
@@ -29,6 +29,9 @@ struct nfs_net { · 28 unmodified lines
2929 #endif
3030 spinlock_t nfs_client_lock;
3131 struct timespec boot_time;
32+#ifdef CONFIG_PROC_FS
33+ struct proc_dir_entry *proc_nfsfs;
34+#endif
3235 };
3336
3437 extern int nfs_net_id;
fs/proc/Makefile+1−0
@@ -23,6 +23,7 @@ proc-y += version.o · 22 unmodified lines
2323 proc-y += softirqs.o
2424 proc-y += namespaces.o
2525 proc-y += self.o
26+proc-y += thread_self.o
2627 proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o
2728 proc-$(CONFIG_NET) += proc_net.o
2829 proc-$(CONFIG_PROC_KCORE) += kcore.o
fs/proc/base.c+13−5
@@ -2814,7 +2814,7 @@ retry: · 2813 unmodified lines
28142814 return iter;
28152815 }
28162816
2817−#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1)
2817+#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 2)
28182818
28192819 /* for the /proc/ directory itself, after non-process stuff has been done */
28202820 int proc_pid_readdir(struct file *file, struct dir_context *ctx)
@@ -2826,14 +2826,19 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx) · 5 unmodified lines
28262826 if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
28272827 return 0;
28282828
2829− if (pos == TGID_OFFSET - 1) {
2829+ if (pos == TGID_OFFSET - 2) {
28302830 struct inode *inode = ns->proc_self->d_inode;
28312831 if (!dir_emit(ctx, "self", 4, inode->i_ino, DT_LNK))
28322832 return 0;
2833− iter.tgid = 0;
2834− } else {
2835− iter.tgid = pos - TGID_OFFSET;
2833+ ctx->pos = pos = pos + 1;
2834+ }
2835+ if (pos == TGID_OFFSET - 1) {
2836+ struct inode *inode = ns->proc_thread_self->d_inode;
2837+ if (!dir_emit(ctx, "thread-self", 11, inode->i_ino, DT_LNK))
2838+ return 0;
2839+ ctx->pos = pos = pos + 1;
28362840 }
2841+ iter.tgid = pos - TGID_OFFSET;
28372842 iter.task = NULL;
28382843 for (iter = next_tgid(ns, iter);
28392844 iter.task;
@@ -2862,6 +2867,9 @@ static const struct pid_entry tid_base_stuff[] = { · 22 unmodified lines
28622867 DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
28632868 DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
28642869 DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
2870+#ifdef CONFIG_NET
2871+ DIR("net", S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
2872+#endif
28652873 REG("environ", S_IRUSR, proc_environ_operations),
28662874 ONE("auxv", S_IRUSR, proc_pid_auxv),
28672875 ONE("status", S_IRUGO, proc_pid_status),
fs/proc/inode.c+6−1
@@ -442,6 +442,7 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) · 441 unmodified lines
442442 int proc_fill_super(struct super_block *s)
443443 {
444444 struct inode *root_inode;
445+ int ret;
445446
446447 s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
447448 s->s_blocksize = 1024;
@@ -463,5 +464,9 @@ int proc_fill_super(struct super_block *s) · 15 unmodified lines
463464 return -ENOMEM;
464465 }
465466
466− return proc_setup_self(s);
467+ ret = proc_setup_self(s);
468+ if (ret) {
469+ return ret;
470+ }
471+ return proc_setup_thread_self(s);
467472 }
fs/proc/internal.h+6−0
@@ -230,6 +230,12 @@ static inline int proc_net_init(void) { return 0; } · 229 unmodified lines
230230 */
231231 extern int proc_setup_self(struct super_block *);
232232
233+/*
234+ * proc_thread_self.c
235+ */
236+extern int proc_setup_thread_self(struct super_block *);
237+extern void proc_thread_self_init(void);
238+
233239 /*
234240 * proc_sysctl.c
235241 */
fs/proc/proc_net.c+4−2
@@ -113,9 +113,11 @@ static struct net *get_proc_task_net(struct inode *dir) · 112 unmodified lines
113113 rcu_read_lock();
114114 task = pid_task(proc_pid(dir), PIDTYPE_PID);
115115 if (task != NULL) {
116− ns = task_nsproxy(task);
116+ task_lock(task);
117+ ns = task->nsproxy;
117118 if (ns != NULL)
118119 net = get_net(ns->net_ns);
120+ task_unlock(task);
119121 }
120122 rcu_read_unlock();
121123
@@ -224,7 +226,7 @@ static struct pernet_operations __net_initdata proc_net_ns_ops = { · 102 unmodified lines
224226
225227 int __init proc_net_init(void)
226228 {
227− proc_symlink("net", NULL, "self/net");
229+ proc_symlink("net", NULL, "thread-self/net");
228230
229231 return register_pernet_subsys(&proc_net_ns_ops);
230232 }
fs/proc/root.c+4−1
@@ -149,6 +149,8 @@ static void proc_kill_sb(struct super_block *sb) · 148 unmodified lines
149149 ns = (struct pid_namespace *)sb->s_fs_info;
150150 if (ns->proc_self)
151151 dput(ns->proc_self);
152+ if (ns->proc_thread_self)
153+ dput(ns->proc_thread_self);
152154 kill_anon_super(sb);
153155 put_pid_ns(ns);
154156 }
@@ -170,7 +172,8 @@ void __init proc_root_init(void) · 15 unmodified lines
170172 return;
171173
172174 proc_self_init();
173− proc_symlink("mounts", NULL, "self/mounts");
175+ proc_thread_self_init();
176+ proc_symlink("mounts", NULL, "thread-self/mounts");
174177
175178 proc_net_init();
176179
fs/proc/thread_self.c+85−0
@@ -0,0 +1,85 @@
1+#include <linux/sched.h>
2+#include <linux/namei.h>
3+#include <linux/slab.h>
4+#include <linux/pid_namespace.h>
5+#include "internal.h"
6+
7+/*
8+ * /proc/thread_self:
9+ */
10+static int proc_thread_self_readlink(struct dentry *dentry, char __user *buffer,
11+ int buflen)
12+{
13+ struct pid_namespace *ns = dentry->d_sb->s_fs_info;
14+ pid_t tgid = task_tgid_nr_ns(current, ns);
15+ pid_t pid = task_pid_nr_ns(current, ns);
16+ char tmp[PROC_NUMBUF + 6 + PROC_NUMBUF];
17+ if (!pid)
18+ return -ENOENT;
19+ sprintf(tmp, "%d/task/%d", tgid, pid);
20+ return readlink_copy(buffer, buflen, tmp);
21+}
22+
23+static void *proc_thread_self_follow_link(struct dentry *dentry, struct nameidata *nd)
24+{
25+ struct pid_namespace *ns = dentry->d_sb->s_fs_info;
26+ pid_t tgid = task_tgid_nr_ns(current, ns);
27+ pid_t pid = task_pid_nr_ns(current, ns);
28+ char *name = ERR_PTR(-ENOENT);
29+ if (pid) {
30+ name = kmalloc(PROC_NUMBUF + 6 + PROC_NUMBUF, GFP_KERNEL);
31+ if (!name)
32+ name = ERR_PTR(-ENOMEM);
33+ else
34+ sprintf(name, "%d/task/%d", tgid, pid);
35+ }
36+ nd_set_link(nd, name);
37+ return NULL;
38+}
39+
40+static const struct inode_operations proc_thread_self_inode_operations = {
41+ .readlink = proc_thread_self_readlink,
42+ .follow_link = proc_thread_self_follow_link,
43+ .put_link = kfree_put_link,
44+};
45+
46+static unsigned thread_self_inum;
47+
48+int proc_setup_thread_self(struct super_block *s)
49+{
50+ struct inode *root_inode = s->s_root->d_inode;
51+ struct pid_namespace *ns = s->s_fs_info;
52+ struct dentry *thread_self;
53+
54+ mutex_lock(&root_inode->i_mutex);
55+ thread_self = d_alloc_name(s->s_root, "thread-self");
56+ if (thread_self) {
57+ struct inode *inode = new_inode_pseudo(s);
58+ if (inode) {
59+ inode->i_ino = thread_self_inum;
60+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
61+ inode->i_mode = S_IFLNK | S_IRWXUGO;
62+ inode->i_uid = GLOBAL_ROOT_UID;
63+ inode->i_gid = GLOBAL_ROOT_GID;
64+ inode->i_op = &proc_thread_self_inode_operations;
65+ d_add(thread_self, inode);
66+ } else {
67+ dput(thread_self);
68+ thread_self = ERR_PTR(-ENOMEM);
69+ }
70+ } else {
71+ thread_self = ERR_PTR(-ENOMEM);
72+ }
73+ mutex_unlock(&root_inode->i_mutex);
74+ if (IS_ERR(thread_self)) {
75+ pr_err("proc_fill_super: can't allocate /proc/thread_self\n");
76+ return PTR_ERR(thread_self);
77+ }
78+ ns->proc_thread_self = thread_self;
79+ return 0;
80+}
81+
82+void __init proc_thread_self_init(void)
83+{
84+ proc_alloc_inum(&thread_self_inum);
85+}
fs/proc_namespace.c+3−5
@@ -232,17 +232,15 @@ static int mounts_open_common(struct inode *inode, struct file *file, · 231 unmodified lines
232232 if (!task)
233233 goto err;
234234
235− rcu_read_lock();
236− nsp = task_nsproxy(task);
235+ task_lock(task);
236+ nsp = task->nsproxy;
237237 if (!nsp || !nsp->mnt_ns) {
238− rcu_read_unlock();
238+ task_unlock(task);
239239 put_task_struct(task);
240240 goto err;
241241 }
242242 ns = nsp->mnt_ns;
243243 get_mnt_ns(ns);
244− rcu_read_unlock();
245− task_lock(task);
246244 if (!task->fs) {
247245 task_unlock(task);
248246 put_task_struct(task);
include/linux/mount.h+8−1
@@ -42,13 +42,20 @@ struct mnt_namespace; · 41 unmodified lines
4242 * flag, consider how it interacts with shared mounts.
4343 */
4444 #define MNT_SHARED_MASK (MNT_UNBINDABLE)
45−#define MNT_PROPAGATION_MASK (MNT_SHARED | MNT_UNBINDABLE)
45+#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \
46+ | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \
47+ | MNT_READONLY)
48+#define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME )
4649
4750 #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \
4851 MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED)
4952
5053 #define MNT_INTERNAL 0x4000
5154
55+#define MNT_LOCK_ATIME 0x040000
56+#define MNT_LOCK_NOEXEC 0x080000
57+#define MNT_LOCK_NOSUID 0x100000
58+#define MNT_LOCK_NODEV 0x200000
5259 #define MNT_LOCK_READONLY 0x400000
5360 #define MNT_LOCKED 0x800000
5461 #define MNT_DOOMED 0x1000000
include/linux/nsproxy.h+6−10
@@ -40,32 +40,28 @@ extern struct nsproxy init_nsproxy; · 39 unmodified lines
4040 * the namespaces access rules are:
4141 *
4242 * 1. only current task is allowed to change tsk->nsproxy pointer or
43− * any pointer on the nsproxy itself
43+ * any pointer on the nsproxy itself. Current must hold the task_lock
44+ * when changing tsk->nsproxy.
4445 *
4546 * 2. when accessing (i.e. reading) current task's namespaces - no
4647 * precautions should be taken - just dereference the pointers
4748 *
4849 * 3. the access to other task namespaces is performed like this
49− * rcu_read_lock();
50− * nsproxy = task_nsproxy(tsk);
50+ * task_lock(task);
51+ * nsproxy = task->nsproxy;
5152 * if (nsproxy != NULL) {
5253 * / *
5354 * * work with the namespaces here
5455 * * e.g. get the reference on one of them
5556 * * /
5657 * } / *
57− * * NULL task_nsproxy() means that this task is
58+ * * NULL task->nsproxy means that this task is
5859 * * almost dead (zombie)
5960 * * /
60− * rcu_read_unlock();
61+ * task_unlock(task);
6162 *
6263 */
6364
64−static inline struct nsproxy *task_nsproxy(struct task_struct *tsk)
65−{
66− return rcu_dereference(tsk->nsproxy);
67−}
68−
6965 int copy_namespaces(unsigned long flags, struct task_struct *tsk);
7066 void exit_task_namespaces(struct task_struct *tsk);
7167 void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
include/linux/pid_namespace.h+1−0
@@ -33,6 +33,7 @@ struct pid_namespace { · 32 unmodified lines
3333 #ifdef CONFIG_PROC_FS
3434 struct vfsmount *proc_mnt;
3535 struct dentry *proc_self;
36+ struct dentry *proc_thread_self;
3637 #endif
3738 #ifdef CONFIG_BSD_PROCESS_ACCT
3839 struct bsd_acct_struct *bacct;
ipc/namespace.c+3−3
@@ -154,11 +154,11 @@ static void *ipcns_get(struct task_struct *task) · 153 unmodified lines
154154 struct ipc_namespace *ns = NULL;
155155 struct nsproxy *nsproxy;
156156
157− rcu_read_lock();
158− nsproxy = task_nsproxy(task);
157+ task_lock(task);
158+ nsproxy = task->nsproxy;
159159 if (nsproxy)
160160 ns = get_ipc_ns(nsproxy->ipc_ns);
161− rcu_read_unlock();
161+ task_unlock(task);
162162
163163 return ns;
164164 }
kernel/nsproxy.c+4−11
@@ -204,20 +204,13 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new) · 203 unmodified lines
204204
205205 might_sleep();
206206
207+ task_lock(p);
207208 ns = p->nsproxy;
209+ p->nsproxy = new;
210+ task_unlock(p);
208211
209− rcu_assign_pointer(p->nsproxy, new);
210−
211− if (ns && atomic_dec_and_test(&ns->count)) {
212− /*
213− * wait for others to get what they want from this nsproxy.
214− *
215− * cannot release this nsproxy via the call_rcu() since
216− * put_mnt_ns() will want to sleep
217− */
218− synchronize_rcu();
212+ if (ns && atomic_dec_and_test(&ns->count))
219213 free_nsproxy(ns);
220− }
221214 }
222215
223216 void exit_task_namespaces(struct task_struct *p)
kernel/utsname.c+3−3
@@ -93,13 +93,13 @@ static void *utsns_get(struct task_struct *task) · 92 unmodified lines
9393 struct uts_namespace *ns = NULL;
9494 struct nsproxy *nsproxy;
9595
96− rcu_read_lock();
97− nsproxy = task_nsproxy(task);
96+ task_lock(task);
97+ nsproxy = task->nsproxy;
9898 if (nsproxy) {
9999 ns = nsproxy->uts_ns;
100100 get_uts_ns(ns);
101101 }
102− rcu_read_unlock();
102+ task_unlock(task);
103103
104104 return ns;
105105 }
net/core/net_namespace.c+6−4
@@ -373,9 +373,11 @@ struct net *get_net_ns_by_pid(pid_t pid) · 372 unmodified lines
373373 tsk = find_task_by_vpid(pid);
374374 if (tsk) {
375375 struct nsproxy *nsproxy;
376− nsproxy = task_nsproxy(tsk);
376+ task_lock(tsk);
377+ nsproxy = tsk->nsproxy;
377378 if (nsproxy)
378379 net = get_net(nsproxy->net_ns);
380+ task_unlock(tsk);
379381 }
380382 rcu_read_unlock();
381383 return net;
@@ -632,11 +634,11 @@ static void *netns_get(struct task_struct *task) · 250 unmodified lines
632634 struct net *net = NULL;
633635 struct nsproxy *nsproxy;
634636
635− rcu_read_lock();
636− nsproxy = task_nsproxy(task);
637+ task_lock(task);
638+ nsproxy = task->nsproxy;
637639 if (nsproxy)
638640 net = get_net(nsproxy->net_ns);
639− rcu_read_unlock();
641+ task_unlock(task);
640642
641643 return net;
642644 }
tools/testing/selftests/Makefile+1−0
@@ -5,6 +5,7 @@ TARGETS += kcmp · 4 unmodified lines
55 TARGETS += memfd
66 TARGETS += memory-hotplug
77 TARGETS += mqueue
8+TARGETS += mount
89 TARGETS += net
910 TARGETS += ptrace
1011 TARGETS += timers
tools/testing/selftests/mount/Makefile+17−0
@@ -0,0 +1,17 @@
1+# Makefile for mount selftests.
2+
3+all: unprivileged-remount-test
4+
5+unprivileged-remount-test: unprivileged-remount-test.c
6+ gcc -Wall -O2 unprivileged-remount-test.c -o unprivileged-remount-test
7+
8+# Allow specific tests to be selected.
9+test_unprivileged_remount: unprivileged-remount-test
10+ @if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi
11+
12+run_tests: all test_unprivileged_remount
13+
14+clean:
15+ rm -f unprivileged-remount-test
16+
17+.PHONY: all test_unprivileged_remount
tools/testing/selftests/mount/unprivileged-remount-test.c+242−0
@@ -0,0 +1,242 @@
1+#define _GNU_SOURCE
2+#include <sched.h>
3+#include <stdio.h>
4+#include <errno.h>
5+#include <string.h>
6+#include <sys/types.h>
7+#include <sys/mount.h>
8+#include <sys/wait.h>
9+#include <stdlib.h>
10+#include <unistd.h>
11+#include <fcntl.h>
12+#include <grp.h>
13+#include <stdbool.h>
14+#include <stdarg.h>
15+
16+#ifndef CLONE_NEWNS
17+# define CLONE_NEWNS 0x00020000
18+#endif
19+#ifndef CLONE_NEWUTS
20+# define CLONE_NEWUTS 0x04000000
21+#endif
22+#ifndef CLONE_NEWIPC
23+# define CLONE_NEWIPC 0x08000000
24+#endif
25+#ifndef CLONE_NEWNET
26+# define CLONE_NEWNET 0x40000000
27+#endif
28+#ifndef CLONE_NEWUSER
29+# define CLONE_NEWUSER 0x10000000
30+#endif
31+#ifndef CLONE_NEWPID
32+# define CLONE_NEWPID 0x20000000
33+#endif
34+
35+#ifndef MS_RELATIME
36+#define MS_RELATIME (1 << 21)
37+#endif
38+#ifndef MS_STRICTATIME
39+#define MS_STRICTATIME (1 << 24)
40+#endif
41+
42+static void die(char *fmt, ...)
43+{
44+ va_list ap;
45+ va_start(ap, fmt);
46+ vfprintf(stderr, fmt, ap);
47+ va_end(ap);
48+ exit(EXIT_FAILURE);
49+}
50+
51+static void write_file(char *filename, char *fmt, ...)
52+{
53+ char buf[4096];
54+ int fd;
55+ ssize_t written;
56+ int buf_len;
57+ va_list ap;
58+
59+ va_start(ap, fmt);
60+ buf_len = vsnprintf(buf, sizeof(buf), fmt, ap);
61+ va_end(ap);
62+ if (buf_len < 0) {
63+ die("vsnprintf failed: %s\n",
64+ strerror(errno));
65+ }
66+ if (buf_len >= sizeof(buf)) {
67+ die("vsnprintf output truncated\n");
68+ }
69+
70+ fd = open(filename, O_WRONLY);
71+ if (fd < 0) {
72+ die("open of %s failed: %s\n",
73+ filename, strerror(errno));
74+ }
75+ written = write(fd, buf, buf_len);
76+ if (written != buf_len) {
77+ if (written >= 0) {
78+ die("short write to %s\n", filename);
79+ } else {
80+ die("write to %s failed: %s\n",
81+ filename, strerror(errno));
82+ }
83+ }
84+ if (close(fd) != 0) {
85+ die("close of %s failed: %s\n",
86+ filename, strerror(errno));
87+ }
88+}
89+
90+static void create_and_enter_userns(void)
91+{
92+ uid_t uid;
93+ gid_t gid;
94+
95+ uid = getuid();
96+ gid = getgid();
97+
98+ if (unshare(CLONE_NEWUSER) !=0) {
99+ die("unshare(CLONE_NEWUSER) failed: %s\n",
100+ strerror(errno));
101+ }
102+
103+ write_file("/proc/self/uid_map", "0 %d 1", uid);
104+ write_file("/proc/self/gid_map", "0 %d 1", gid);
105+
106+ if (setgroups(0, NULL) != 0) {
107+ die("setgroups failed: %s\n",
108+ strerror(errno));
109+ }
110+ if (setgid(0) != 0) {
111+ die ("setgid(0) failed %s\n",
112+ strerror(errno));
113+ }
114+ if (setuid(0) != 0) {
115+ die("setuid(0) failed %s\n",
116+ strerror(errno));
117+ }
118+}
119+
120+static
121+bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags)
122+{
123+ pid_t child;
124+
125+ child = fork();
126+ if (child == -1) {
127+ die("fork failed: %s\n",
128+ strerror(errno));
129+ }
130+ if (child != 0) { /* parent */
131+ pid_t pid;
132+ int status;
133+ pid = waitpid(child, &status, 0);
134+ if (pid == -1) {
135+ die("waitpid failed: %s\n",
136+ strerror(errno));
137+ }
138+ if (pid != child) {
139+ die("waited for %d got %d\n",
140+ child, pid);
141+ }
142+ if (!WIFEXITED(status)) {
143+ die("child did not terminate cleanly\n");
144+ }
145+ return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false;
146+ }
147+
148+ create_and_enter_userns();
149+ if (unshare(CLONE_NEWNS) != 0) {
150+ die("unshare(CLONE_NEWNS) failed: %s\n",
151+ strerror(errno));
152+ }
153+
154+ if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) {
155+ die("mount of /tmp failed: %s\n",
156+ strerror(errno));
157+ }
158+
159+ create_and_enter_userns();
160+
161+ if (unshare(CLONE_NEWNS) != 0) {
162+ die("unshare(CLONE_NEWNS) failed: %s\n",
163+ strerror(errno));
164+ }
165+
166+ if (mount("/tmp", "/tmp", "none",
167+ MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) {
168+ /* system("cat /proc/self/mounts"); */
169+ die("remount of /tmp failed: %s\n",
170+ strerror(errno));
171+ }
172+
173+ if (mount("/tmp", "/tmp", "none",
174+ MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) {
175+ /* system("cat /proc/self/mounts"); */
176+ die("remount of /tmp with invalid flags "
177+ "succeeded unexpectedly\n");
178+ }
179+ exit(EXIT_SUCCESS);
180+}
181+
182+static bool test_unpriv_remount_simple(int mount_flags)
183+{
184+ return test_unpriv_remount(mount_flags, mount_flags, 0);
185+}
186+
187+static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags)
188+{
189+ return test_unpriv_remount(mount_flags, mount_flags, invalid_flags);
190+}
191+
192+int main(int argc, char **argv)
193+{
194+ if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) {
195+ die("MS_RDONLY malfunctions\n");
196+ }
197+ if (!test_unpriv_remount_simple(MS_NODEV)) {
198+ die("MS_NODEV malfunctions\n");
199+ }
200+ if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) {
201+ die("MS_NOSUID malfunctions\n");
202+ }
203+ if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) {
204+ die("MS_NOEXEC malfunctions\n");
205+ }
206+ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV,
207+ MS_NOATIME|MS_NODEV))
208+ {
209+ die("MS_RELATIME malfunctions\n");
210+ }
211+ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV,
212+ MS_NOATIME|MS_NODEV))
213+ {
214+ die("MS_STRICTATIME malfunctions\n");
215+ }
216+ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV,
217+ MS_STRICTATIME|MS_NODEV))
218+ {
219+ die("MS_RELATIME malfunctions\n");
220+ }
221+ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV,
222+ MS_NOATIME|MS_NODEV))
223+ {
224+ die("MS_RELATIME malfunctions\n");
225+ }
226+ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV,
227+ MS_NOATIME|MS_NODEV))
228+ {
229+ die("MS_RELATIME malfunctions\n");
230+ }
231+ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV,
232+ MS_STRICTATIME|MS_NODEV))
233+ {
234+ die("MS_RELATIME malfunctions\n");
235+ }
236+ if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV,
237+ MS_NOATIME|MS_NODEV))
238+ {
239+ die("Default atime malfunctions\n");
240+ }
241+ return EXIT_SUCCESS;
242+}