Blame view

fs/namespace.c 97 KB
59bd9ded4   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
  /*
   *  linux/fs/namespace.c
   *
   * (C) Copyright Al Viro 2000, 2001
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
   *
   * Based on code from fs/super.c, copyright Linus Torvalds and others.
   * Heavily rewritten.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/syscalls.h>
d10577a8d   Al Viro   vfs: trim include...
11
  #include <linux/export.h>
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
12
  #include <linux/capability.h>
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
13
  #include <linux/mnt_namespace.h>
771b13716   Eric W. Biederman   vfs: Add a user n...
14
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
  #include <linux/namei.h>
  #include <linux/security.h>
5b825c3af   Ingo Molnar   sched/headers: Pr...
17
  #include <linux/cred.h>
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
18
  #include <linux/idr.h>
57f150a58   Rob Landley   initmpfs: move ro...
19
  #include <linux/init.h>		/* init_rootfs */
d10577a8d   Al Viro   vfs: trim include...
20
21
  #include <linux/fs_struct.h>	/* get_fs_root et.al. */
  #include <linux/fsnotify.h>	/* fsnotify_vfsmount_delete */
a07b20004   Al Viro   vfs: syscall: Add...
22
  #include <linux/file.h>
d10577a8d   Al Viro   vfs: trim include...
23
  #include <linux/uaccess.h>
0bb80f240   David Howells   proc: Split the n...
24
  #include <linux/proc_ns.h>
20b4fb485   Linus Torvalds   Merge branch 'for...
25
  #include <linux/magic.h>
57c8a661d   Mike Rapoport   mm: remove includ...
26
  #include <linux/memblock.h>
9ea459e11   Al Viro   delayed mntput
27
  #include <linux/task_work.h>
9164bb4a1   Ingo Molnar   sched/headers: Pr...
28
  #include <linux/sched/task.h>
e262e32d6   David Howells   vfs: Suppress MS_...
29
  #include <uapi/linux/mount.h>
9bc61ab18   David Howells   vfs: Introduce fs...
30
  #include <linux/fs_context.h>
037f11b47   Al Viro   mnt_init(): call ...
31
  #include <linux/shmem_fs.h>
9164bb4a1   Ingo Molnar   sched/headers: Pr...
32

07b20889e   Ram Pai   [PATCH] beginning...
33
  #include "pnode.h"
948730b0e   Adrian Bunk   fs/namespace.c sh...
34
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

d29216842   Eric W. Biederman   mnt: Add a per mo...
36
37
  /* Maximum number of mounts in a mount namespace */
  unsigned int sysctl_mount_max __read_mostly = 100000;
0818bf27c   Al Viro   resizable namespa...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  static unsigned int m_hash_mask __read_mostly;
  static unsigned int m_hash_shift __read_mostly;
  static unsigned int mp_hash_mask __read_mostly;
  static unsigned int mp_hash_shift __read_mostly;
  
  static __initdata unsigned long mhash_entries;
  static int __init set_mhash_entries(char *str)
  {
  	if (!str)
  		return 0;
  	mhash_entries = simple_strtoul(str, &str, 0);
  	return 1;
  }
  __setup("mhash_entries=", set_mhash_entries);
  
  static __initdata unsigned long mphash_entries;
  static int __init set_mphash_entries(char *str)
  {
  	if (!str)
  		return 0;
  	mphash_entries = simple_strtoul(str, &str, 0);
  	return 1;
  }
  __setup("mphash_entries=", set_mphash_entries);
13f14b4d8   Eric Dumazet   Use ilog2() in fs...
62

c7999c362   Al Viro   reduce m_start() ...
63
  static u64 event;
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
64
  static DEFINE_IDA(mnt_id_ida);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
65
  static DEFINE_IDA(mnt_group_ida);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66

38129a13e   Al Viro   switch mnt_hash t...
67
  static struct hlist_head *mount_hashtable __read_mostly;
0818bf27c   Al Viro   resizable namespa...
68
  static struct hlist_head *mountpoint_hashtable __read_mostly;
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
69
  static struct kmem_cache *mnt_cache __read_mostly;
59aa0da8e   Al Viro   initialize namesp...
70
  static DECLARE_RWSEM(namespace_sem);
4edbe133f   Al Viro   make struct mount...
71
72
  static HLIST_HEAD(unmounted);	/* protected by namespace_sem */
  static LIST_HEAD(ex_mountpoints); /* protected by namespace_sem */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73

f87fd4c2a   Miklos Szeredi   [PATCH] add /sys/fs
74
  /* /sys/fs */
00d266662   Greg Kroah-Hartman   kobject: convert ...
75
76
  struct kobject *fs_kobj;
  EXPORT_SYMBOL_GPL(fs_kobj);
f87fd4c2a   Miklos Szeredi   [PATCH] add /sys/fs
77

99b7db7b8   Nick Piggin   fs: brlock vfsmou...
78
79
80
81
82
83
84
85
  /*
   * vfsmount lock may be taken for read to prevent changes to the
   * vfsmount hash, ie. during mountpoint lookups or walking back
   * up the tree.
   *
   * It should be taken for write in all cases where the vfsmount
   * tree or hash is modified or when a vfsmount structure is modified.
   */
48a066e72   Al Viro   RCU'd vfsmounts
86
  __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
87

38129a13e   Al Viro   switch mnt_hash t...
88
  static inline struct hlist_head *m_hash(struct vfsmount *mnt, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
b58fed8b1   Ram Pai   [PATCH] lindent f...
90
91
  	unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES);
  	tmp += ((unsigned long)dentry / L1_CACHE_BYTES);
0818bf27c   Al Viro   resizable namespa...
92
93
94
95
96
97
98
99
100
  	tmp = tmp + (tmp >> m_hash_shift);
  	return &mount_hashtable[tmp & m_hash_mask];
  }
  
  static inline struct hlist_head *mp_hash(struct dentry *dentry)
  {
  	unsigned long tmp = ((unsigned long)dentry / L1_CACHE_BYTES);
  	tmp = tmp + (tmp >> mp_hash_shift);
  	return &mountpoint_hashtable[tmp & mp_hash_mask];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
  }
b105e270b   Al Viro   vfs: spread struc...
102
  static int mnt_alloc_id(struct mount *mnt)
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
103
  {
169b480e4   Matthew Wilcox   fs: Convert names...
104
105
106
107
108
109
  	int res = ida_alloc(&mnt_id_ida, GFP_KERNEL);
  
  	if (res < 0)
  		return res;
  	mnt->mnt_id = res;
  	return 0;
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
110
  }
b105e270b   Al Viro   vfs: spread struc...
111
  static void mnt_free_id(struct mount *mnt)
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
112
  {
169b480e4   Matthew Wilcox   fs: Convert names...
113
  	ida_free(&mnt_id_ida, mnt->mnt_id);
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
114
  }
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
115
116
  /*
   * Allocate a new peer group ID
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
117
   */
4b8b21f4f   Al Viro   vfs: spread struc...
118
  static int mnt_alloc_group_id(struct mount *mnt)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
119
  {
169b480e4   Matthew Wilcox   fs: Convert names...
120
  	int res = ida_alloc_min(&mnt_group_ida, 1, GFP_KERNEL);
f21f62208   Al Viro   ... and the same ...
121

169b480e4   Matthew Wilcox   fs: Convert names...
122
123
124
125
  	if (res < 0)
  		return res;
  	mnt->mnt_group_id = res;
  	return 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
126
127
128
129
130
  }
  
  /*
   * Release a peer group ID
   */
4b8b21f4f   Al Viro   vfs: spread struc...
131
  void mnt_release_group_id(struct mount *mnt)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
132
  {
169b480e4   Matthew Wilcox   fs: Convert names...
133
  	ida_free(&mnt_group_ida, mnt->mnt_group_id);
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
134
  	mnt->mnt_group_id = 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
135
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
136
137
138
  /*
   * vfsmount lock must be held for read
   */
83adc7532   Al Viro   vfs: spread struc...
139
  static inline void mnt_add_count(struct mount *mnt, int n)
b3e19d924   Nick Piggin   fs: scale mntget/...
140
141
  {
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
142
  	this_cpu_add(mnt->mnt_pcp->mnt_count, n);
b3e19d924   Nick Piggin   fs: scale mntget/...
143
144
  #else
  	preempt_disable();
68e8a9fea   Al Viro   vfs: all counters...
145
  	mnt->mnt_count += n;
b3e19d924   Nick Piggin   fs: scale mntget/...
146
147
148
  	preempt_enable();
  #endif
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
149
150
151
  /*
   * vfsmount lock must be held for write
   */
83adc7532   Al Viro   vfs: spread struc...
152
  unsigned int mnt_get_count(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
153
154
  {
  #ifdef CONFIG_SMP
f03c65993   Al Viro   sanitize vfsmount...
155
  	unsigned int count = 0;
b3e19d924   Nick Piggin   fs: scale mntget/...
156
157
158
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
68e8a9fea   Al Viro   vfs: all counters...
159
  		count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count;
b3e19d924   Nick Piggin   fs: scale mntget/...
160
161
162
163
  	}
  
  	return count;
  #else
68e8a9fea   Al Viro   vfs: all counters...
164
  	return mnt->mnt_count;
b3e19d924   Nick Piggin   fs: scale mntget/...
165
166
  #endif
  }
b105e270b   Al Viro   vfs: spread struc...
167
  static struct mount *alloc_vfsmnt(const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
  {
c63181e6b   Al Viro   vfs: move fsnotif...
169
170
  	struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
  	if (mnt) {
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
171
  		int err;
c63181e6b   Al Viro   vfs: move fsnotif...
172
  		err = mnt_alloc_id(mnt);
88b387824   Li Zefan   [PATCH] vfs: use ...
173
174
175
176
  		if (err)
  			goto out_free_cache;
  
  		if (name) {
fcc139ae2   Andrzej Hajda   fs/namespace: con...
177
  			mnt->mnt_devname = kstrdup_const(name, GFP_KERNEL);
c63181e6b   Al Viro   vfs: move fsnotif...
178
  			if (!mnt->mnt_devname)
88b387824   Li Zefan   [PATCH] vfs: use ...
179
  				goto out_free_id;
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
180
  		}
b3e19d924   Nick Piggin   fs: scale mntget/...
181
  #ifdef CONFIG_SMP
c63181e6b   Al Viro   vfs: move fsnotif...
182
183
  		mnt->mnt_pcp = alloc_percpu(struct mnt_pcp);
  		if (!mnt->mnt_pcp)
b3e19d924   Nick Piggin   fs: scale mntget/...
184
  			goto out_free_devname;
c63181e6b   Al Viro   vfs: move fsnotif...
185
  		this_cpu_add(mnt->mnt_pcp->mnt_count, 1);
b3e19d924   Nick Piggin   fs: scale mntget/...
186
  #else
c63181e6b   Al Viro   vfs: move fsnotif...
187
188
  		mnt->mnt_count = 1;
  		mnt->mnt_writers = 0;
b3e19d924   Nick Piggin   fs: scale mntget/...
189
  #endif
38129a13e   Al Viro   switch mnt_hash t...
190
  		INIT_HLIST_NODE(&mnt->mnt_hash);
c63181e6b   Al Viro   vfs: move fsnotif...
191
192
193
194
195
196
197
  		INIT_LIST_HEAD(&mnt->mnt_child);
  		INIT_LIST_HEAD(&mnt->mnt_mounts);
  		INIT_LIST_HEAD(&mnt->mnt_list);
  		INIT_LIST_HEAD(&mnt->mnt_expire);
  		INIT_LIST_HEAD(&mnt->mnt_share);
  		INIT_LIST_HEAD(&mnt->mnt_slave_list);
  		INIT_LIST_HEAD(&mnt->mnt_slave);
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
198
  		INIT_HLIST_NODE(&mnt->mnt_mp_list);
99b19d164   Eric W. Biederman   mnt: In propgate_...
199
  		INIT_LIST_HEAD(&mnt->mnt_umounting);
56cbb429d   Al Viro   switch the remnan...
200
  		INIT_HLIST_HEAD(&mnt->mnt_stuck_children);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  	}
c63181e6b   Al Viro   vfs: move fsnotif...
202
  	return mnt;
88b387824   Li Zefan   [PATCH] vfs: use ...
203

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
204
205
  #ifdef CONFIG_SMP
  out_free_devname:
fcc139ae2   Andrzej Hajda   fs/namespace: con...
206
  	kfree_const(mnt->mnt_devname);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
207
  #endif
88b387824   Li Zefan   [PATCH] vfs: use ...
208
  out_free_id:
c63181e6b   Al Viro   vfs: move fsnotif...
209
  	mnt_free_id(mnt);
88b387824   Li Zefan   [PATCH] vfs: use ...
210
  out_free_cache:
c63181e6b   Al Viro   vfs: move fsnotif...
211
  	kmem_cache_free(mnt_cache, mnt);
88b387824   Li Zefan   [PATCH] vfs: use ...
212
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  }
8366025eb   Dave Hansen   [PATCH] r/o bind ...
214
215
216
217
218
219
220
221
  /*
   * Most r/o checks on a fs are for operations that take
   * discrete amounts of time, like a write() or unlink().
   * We must keep track of when those operations start
   * (for permission checks) and when they end, so that
   * we can determine when writes are able to occur to
   * a filesystem.
   */
3d733633a   Dave Hansen   [PATCH] r/o bind ...
222
223
224
225
226
227
228
229
230
231
232
  /*
   * __mnt_is_readonly: check whether a mount is read-only
   * @mnt: the mount to check for its write status
   *
   * This shouldn't be used directly ouside of the VFS.
   * It does not guarantee that the filesystem will stay
   * r/w, just that it is right *now*.  This can not and
   * should not be used in place of IS_RDONLY(inode).
   * mnt_want/drop_write() will _keep_ the filesystem
   * r/w.
   */
43f5e655e   David Howells   vfs: Separate cha...
233
  bool __mnt_is_readonly(struct vfsmount *mnt)
3d733633a   Dave Hansen   [PATCH] r/o bind ...
234
  {
43f5e655e   David Howells   vfs: Separate cha...
235
  	return (mnt->mnt_flags & MNT_READONLY) || sb_rdonly(mnt->mnt_sb);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
236
237
  }
  EXPORT_SYMBOL_GPL(__mnt_is_readonly);
83adc7532   Al Viro   vfs: spread struc...
238
  static inline void mnt_inc_writers(struct mount *mnt)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
239
240
  {
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
241
  	this_cpu_inc(mnt->mnt_pcp->mnt_writers);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
242
  #else
68e8a9fea   Al Viro   vfs: all counters...
243
  	mnt->mnt_writers++;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
244
245
  #endif
  }
3d733633a   Dave Hansen   [PATCH] r/o bind ...
246

83adc7532   Al Viro   vfs: spread struc...
247
  static inline void mnt_dec_writers(struct mount *mnt)
3d733633a   Dave Hansen   [PATCH] r/o bind ...
248
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
249
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
250
  	this_cpu_dec(mnt->mnt_pcp->mnt_writers);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
251
  #else
68e8a9fea   Al Viro   vfs: all counters...
252
  	mnt->mnt_writers--;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
253
  #endif
3d733633a   Dave Hansen   [PATCH] r/o bind ...
254
  }
3d733633a   Dave Hansen   [PATCH] r/o bind ...
255

83adc7532   Al Viro   vfs: spread struc...
256
  static unsigned int mnt_get_writers(struct mount *mnt)
3d733633a   Dave Hansen   [PATCH] r/o bind ...
257
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
258
259
  #ifdef CONFIG_SMP
  	unsigned int count = 0;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
260
  	int cpu;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
261
262
  
  	for_each_possible_cpu(cpu) {
68e8a9fea   Al Viro   vfs: all counters...
263
  		count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_writers;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
264
  	}
3d733633a   Dave Hansen   [PATCH] r/o bind ...
265

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
266
267
268
269
  	return count;
  #else
  	return mnt->mnt_writers;
  #endif
3d733633a   Dave Hansen   [PATCH] r/o bind ...
270
  }
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
271
272
273
274
275
276
277
278
  static int mnt_is_readonly(struct vfsmount *mnt)
  {
  	if (mnt->mnt_sb->s_readonly_remount)
  		return 1;
  	/* Order wrt setting s_flags/s_readonly_remount in do_remount() */
  	smp_rmb();
  	return __mnt_is_readonly(mnt);
  }
3d733633a   Dave Hansen   [PATCH] r/o bind ...
279
  /*
eb04c2828   Jan Kara   fs: Add freezing ...
280
281
282
283
   * Most r/o & frozen checks on a fs are for operations that take discrete
   * amounts of time, like a write() or unlink().  We must keep track of when
   * those operations start (for permission checks) and when they end, so that we
   * can determine when writes are able to occur to a filesystem.
3d733633a   Dave Hansen   [PATCH] r/o bind ...
284
   */
8366025eb   Dave Hansen   [PATCH] r/o bind ...
285
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
286
   * __mnt_want_write - get write access to a mount without freeze protection
83adc7532   Al Viro   vfs: spread struc...
287
   * @m: the mount on which to take a write
8366025eb   Dave Hansen   [PATCH] r/o bind ...
288
   *
eb04c2828   Jan Kara   fs: Add freezing ...
289
290
291
292
293
   * This tells the low-level filesystem that a write is about to be performed to
   * it, and makes sure that writes are allowed (mnt it read-write) before
   * returning success. This operation does not protect against filesystem being
   * frozen. When the write operation is finished, __mnt_drop_write() must be
   * called. This is effectively a refcount.
8366025eb   Dave Hansen   [PATCH] r/o bind ...
294
   */
eb04c2828   Jan Kara   fs: Add freezing ...
295
  int __mnt_want_write(struct vfsmount *m)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
296
  {
83adc7532   Al Viro   vfs: spread struc...
297
  	struct mount *mnt = real_mount(m);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
298
  	int ret = 0;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
299

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
300
  	preempt_disable();
c6653a838   Nick Piggin   fs: rename vfsmou...
301
  	mnt_inc_writers(mnt);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
302
  	/*
c6653a838   Nick Piggin   fs: rename vfsmou...
303
  	 * The store to mnt_inc_writers must be visible before we pass
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
304
305
306
307
  	 * MNT_WRITE_HOLD loop below, so that the slowpath can see our
  	 * incremented count after it has set MNT_WRITE_HOLD.
  	 */
  	smp_mb();
6aa7de059   Mark Rutland   locking/atomics: ...
308
  	while (READ_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
309
310
311
312
313
314
315
  		cpu_relax();
  	/*
  	 * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will
  	 * be set to match its requirements. So we must not load that until
  	 * MNT_WRITE_HOLD is cleared.
  	 */
  	smp_rmb();
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
316
  	if (mnt_is_readonly(m)) {
c6653a838   Nick Piggin   fs: rename vfsmou...
317
  		mnt_dec_writers(mnt);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
318
  		ret = -EROFS;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
319
  	}
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
320
  	preempt_enable();
eb04c2828   Jan Kara   fs: Add freezing ...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  
  	return ret;
  }
  
  /**
   * mnt_want_write - get write access to a mount
   * @m: the mount on which to take a write
   *
   * This tells the low-level filesystem that a write is about to be performed to
   * it, and makes sure that writes are allowed (mount is read-write, filesystem
   * is not frozen) before returning success.  When the write operation is
   * finished, mnt_drop_write() must be called.  This is effectively a refcount.
   */
  int mnt_want_write(struct vfsmount *m)
  {
  	int ret;
  
  	sb_start_write(m->mnt_sb);
  	ret = __mnt_want_write(m);
  	if (ret)
  		sb_end_write(m->mnt_sb);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
342
  	return ret;
8366025eb   Dave Hansen   [PATCH] r/o bind ...
343
344
345
346
  }
  EXPORT_SYMBOL_GPL(mnt_want_write);
  
  /**
96029c4e0   npiggin@suse.de   fs: introduce mnt...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
   * mnt_clone_write - get write access to a mount
   * @mnt: the mount on which to take a write
   *
   * This is effectively like mnt_want_write, except
   * it must only be used to take an extra write reference
   * on a mountpoint that we already know has a write reference
   * on it. This allows some optimisation.
   *
   * After finished, mnt_drop_write must be called as usual to
   * drop the reference.
   */
  int mnt_clone_write(struct vfsmount *mnt)
  {
  	/* superblock may be r/o */
  	if (__mnt_is_readonly(mnt))
  		return -EROFS;
  	preempt_disable();
83adc7532   Al Viro   vfs: spread struc...
364
  	mnt_inc_writers(real_mount(mnt));
96029c4e0   npiggin@suse.de   fs: introduce mnt...
365
366
367
368
369
370
  	preempt_enable();
  	return 0;
  }
  EXPORT_SYMBOL_GPL(mnt_clone_write);
  
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
371
   * __mnt_want_write_file - get write access to a file's mount
96029c4e0   npiggin@suse.de   fs: introduce mnt...
372
373
   * @file: the file who's mount on which to take a write
   *
eb04c2828   Jan Kara   fs: Add freezing ...
374
   * This is like __mnt_want_write, but it takes a file and can
96029c4e0   npiggin@suse.de   fs: introduce mnt...
375
376
   * do some optimisations if the file is open for write already
   */
eb04c2828   Jan Kara   fs: Add freezing ...
377
  int __mnt_want_write_file(struct file *file)
96029c4e0   npiggin@suse.de   fs: introduce mnt...
378
  {
83f936c75   Al Viro   mark struct file ...
379
  	if (!(file->f_mode & FMODE_WRITER))
eb04c2828   Jan Kara   fs: Add freezing ...
380
  		return __mnt_want_write(file->f_path.mnt);
96029c4e0   npiggin@suse.de   fs: introduce mnt...
381
382
383
  	else
  		return mnt_clone_write(file->f_path.mnt);
  }
eb04c2828   Jan Kara   fs: Add freezing ...
384
385
  
  /**
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
386
387
388
389
390
   * mnt_want_write_file - get write access to a file's mount
   * @file: the file who's mount on which to take a write
   *
   * This is like mnt_want_write, but it takes a file and can
   * do some optimisations if the file is open for write already
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
391
392
393
394
   */
  int mnt_want_write_file(struct file *file)
  {
  	int ret;
a6795a585   Miklos Szeredi   vfs: fix freeze p...
395
  	sb_start_write(file_inode(file)->i_sb);
eb04c2828   Jan Kara   fs: Add freezing ...
396
397
  	ret = __mnt_want_write_file(file);
  	if (ret)
a6795a585   Miklos Szeredi   vfs: fix freeze p...
398
  		sb_end_write(file_inode(file)->i_sb);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
399
400
  	return ret;
  }
96029c4e0   npiggin@suse.de   fs: introduce mnt...
401
402
403
  EXPORT_SYMBOL_GPL(mnt_want_write_file);
  
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
404
   * __mnt_drop_write - give up write access to a mount
8366025eb   Dave Hansen   [PATCH] r/o bind ...
405
406
407
408
   * @mnt: the mount on which to give up write access
   *
   * Tells the low-level filesystem that we are done
   * performing writes to it.  Must be matched with
eb04c2828   Jan Kara   fs: Add freezing ...
409
   * __mnt_want_write() call above.
8366025eb   Dave Hansen   [PATCH] r/o bind ...
410
   */
eb04c2828   Jan Kara   fs: Add freezing ...
411
  void __mnt_drop_write(struct vfsmount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
412
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
413
  	preempt_disable();
83adc7532   Al Viro   vfs: spread struc...
414
  	mnt_dec_writers(real_mount(mnt));
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
415
  	preempt_enable();
8366025eb   Dave Hansen   [PATCH] r/o bind ...
416
  }
eb04c2828   Jan Kara   fs: Add freezing ...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
  
  /**
   * mnt_drop_write - give up write access to a mount
   * @mnt: the mount on which to give up write access
   *
   * Tells the low-level filesystem that we are done performing writes to it and
   * also allows filesystem to be frozen again.  Must be matched with
   * mnt_want_write() call above.
   */
  void mnt_drop_write(struct vfsmount *mnt)
  {
  	__mnt_drop_write(mnt);
  	sb_end_write(mnt->mnt_sb);
  }
8366025eb   Dave Hansen   [PATCH] r/o bind ...
431
  EXPORT_SYMBOL_GPL(mnt_drop_write);
eb04c2828   Jan Kara   fs: Add freezing ...
432
433
434
435
  void __mnt_drop_write_file(struct file *file)
  {
  	__mnt_drop_write(file->f_path.mnt);
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
436
437
  void mnt_drop_write_file(struct file *file)
  {
a6795a585   Miklos Szeredi   vfs: fix freeze p...
438
  	__mnt_drop_write_file(file);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
439
440
  	sb_end_write(file_inode(file)->i_sb);
  }
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
441
  EXPORT_SYMBOL(mnt_drop_write_file);
83adc7532   Al Viro   vfs: spread struc...
442
  static int mnt_make_readonly(struct mount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
443
  {
3d733633a   Dave Hansen   [PATCH] r/o bind ...
444
  	int ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
445
  	lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
446
  	mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
447
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
448
449
  	 * After storing MNT_WRITE_HOLD, we'll read the counters. This store
  	 * should be visible before we do.
3d733633a   Dave Hansen   [PATCH] r/o bind ...
450
  	 */
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
451
  	smp_mb();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
452
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  	 * With writers on hold, if this value is zero, then there are
  	 * definitely no active writers (although held writers may subsequently
  	 * increment the count, they'll have to wait, and decrement it after
  	 * seeing MNT_READONLY).
  	 *
  	 * It is OK to have counter incremented on one CPU and decremented on
  	 * another: the sum will add up correctly. The danger would be when we
  	 * sum up each counter, if we read a counter before it is incremented,
  	 * but then read another CPU's count which it has been subsequently
  	 * decremented from -- we would see more decrements than we should.
  	 * MNT_WRITE_HOLD protects against this scenario, because
  	 * mnt_want_write first increments count, then smp_mb, then spins on
  	 * MNT_WRITE_HOLD, so it can't be decremented by another CPU while
  	 * we're counting up here.
3d733633a   Dave Hansen   [PATCH] r/o bind ...
467
  	 */
c6653a838   Nick Piggin   fs: rename vfsmou...
468
  	if (mnt_get_writers(mnt) > 0)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
469
470
  		ret = -EBUSY;
  	else
83adc7532   Al Viro   vfs: spread struc...
471
  		mnt->mnt.mnt_flags |= MNT_READONLY;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
472
473
474
475
476
  	/*
  	 * MNT_READONLY must become visible before ~MNT_WRITE_HOLD, so writers
  	 * that become unheld will see MNT_READONLY.
  	 */
  	smp_wmb();
83adc7532   Al Viro   vfs: spread struc...
477
  	mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
719ea2fbb   Al Viro   new helpers: lock...
478
  	unlock_mount_hash();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
479
  	return ret;
8366025eb   Dave Hansen   [PATCH] r/o bind ...
480
  }
8366025eb   Dave Hansen   [PATCH] r/o bind ...
481

43f5e655e   David Howells   vfs: Separate cha...
482
  static int __mnt_unmake_readonly(struct mount *mnt)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
483
  {
719ea2fbb   Al Viro   new helpers: lock...
484
  	lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
485
  	mnt->mnt.mnt_flags &= ~MNT_READONLY;
719ea2fbb   Al Viro   new helpers: lock...
486
  	unlock_mount_hash();
43f5e655e   David Howells   vfs: Separate cha...
487
  	return 0;
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
488
  }
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
489
490
491
492
  int sb_prepare_remount_readonly(struct super_block *sb)
  {
  	struct mount *mnt;
  	int err = 0;
8e8b87964   Miklos Szeredi   vfs: prevent remo...
493
494
495
  	/* Racy optimization.  Recheck the counter under MNT_WRITE_HOLD */
  	if (atomic_long_read(&sb->s_remove_count))
  		return -EBUSY;
719ea2fbb   Al Viro   new helpers: lock...
496
  	lock_mount_hash();
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
497
498
499
500
501
502
503
504
505
506
  	list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
  		if (!(mnt->mnt.mnt_flags & MNT_READONLY)) {
  			mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
  			smp_mb();
  			if (mnt_get_writers(mnt) > 0) {
  				err = -EBUSY;
  				break;
  			}
  		}
  	}
8e8b87964   Miklos Szeredi   vfs: prevent remo...
507
508
  	if (!err && atomic_long_read(&sb->s_remove_count))
  		err = -EBUSY;
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
509
510
511
512
513
514
515
516
  	if (!err) {
  		sb->s_readonly_remount = 1;
  		smp_wmb();
  	}
  	list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
  		if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD)
  			mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
  	}
719ea2fbb   Al Viro   new helpers: lock...
517
  	unlock_mount_hash();
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
518
519
520
  
  	return err;
  }
b105e270b   Al Viro   vfs: spread struc...
521
  static void free_vfsmnt(struct mount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  {
fcc139ae2   Andrzej Hajda   fs/namespace: con...
523
  	kfree_const(mnt->mnt_devname);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
524
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
525
  	free_percpu(mnt->mnt_pcp);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
526
  #endif
b105e270b   Al Viro   vfs: spread struc...
527
  	kmem_cache_free(mnt_cache, mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
  }
8ffcb32e0   David Howells   VFS: Make delayed...
529
530
531
532
  static void delayed_free_vfsmnt(struct rcu_head *head)
  {
  	free_vfsmnt(container_of(head, struct mount, mnt_rcu));
  }
48a066e72   Al Viro   RCU'd vfsmounts
533
  /* call under rcu_read_lock */
294d71ff2   Al Viro   new helper: __leg...
534
  int __legitimize_mnt(struct vfsmount *bastard, unsigned seq)
48a066e72   Al Viro   RCU'd vfsmounts
535
536
537
  {
  	struct mount *mnt;
  	if (read_seqretry(&mount_lock, seq))
294d71ff2   Al Viro   new helper: __leg...
538
  		return 1;
48a066e72   Al Viro   RCU'd vfsmounts
539
  	if (bastard == NULL)
294d71ff2   Al Viro   new helper: __leg...
540
  		return 0;
48a066e72   Al Viro   RCU'd vfsmounts
541
542
  	mnt = real_mount(bastard);
  	mnt_add_count(mnt, 1);
119e1ef80   Al Viro   fix __legitimize_...
543
  	smp_mb();			// see mntput_no_expire()
48a066e72   Al Viro   RCU'd vfsmounts
544
  	if (likely(!read_seqretry(&mount_lock, seq)))
294d71ff2   Al Viro   new helper: __leg...
545
  		return 0;
48a066e72   Al Viro   RCU'd vfsmounts
546
547
  	if (bastard->mnt_flags & MNT_SYNC_UMOUNT) {
  		mnt_add_count(mnt, -1);
294d71ff2   Al Viro   new helper: __leg...
548
549
  		return 1;
  	}
119e1ef80   Al Viro   fix __legitimize_...
550
551
552
553
554
555
556
557
  	lock_mount_hash();
  	if (unlikely(bastard->mnt_flags & MNT_DOOMED)) {
  		mnt_add_count(mnt, -1);
  		unlock_mount_hash();
  		return 1;
  	}
  	unlock_mount_hash();
  	/* caller will mntput() */
294d71ff2   Al Viro   new helper: __leg...
558
559
560
561
562
563
564
565
566
567
568
569
570
  	return -1;
  }
  
  /* call under rcu_read_lock */
  bool legitimize_mnt(struct vfsmount *bastard, unsigned seq)
  {
  	int res = __legitimize_mnt(bastard, seq);
  	if (likely(!res))
  		return true;
  	if (unlikely(res < 0)) {
  		rcu_read_unlock();
  		mntput(bastard);
  		rcu_read_lock();
48a066e72   Al Viro   RCU'd vfsmounts
571
  	}
48a066e72   Al Viro   RCU'd vfsmounts
572
573
  	return false;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  /*
474279dc0   Al Viro   split __lookup_mn...
575
   * find the first mount at @dentry on vfsmount @mnt.
48a066e72   Al Viro   RCU'd vfsmounts
576
   * call under rcu_read_lock()
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
   */
474279dc0   Al Viro   split __lookup_mn...
578
  struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  {
38129a13e   Al Viro   switch mnt_hash t...
580
  	struct hlist_head *head = m_hash(mnt, dentry);
474279dc0   Al Viro   split __lookup_mn...
581
  	struct mount *p;
38129a13e   Al Viro   switch mnt_hash t...
582
  	hlist_for_each_entry_rcu(p, head, mnt_hash)
474279dc0   Al Viro   split __lookup_mn...
583
584
585
586
587
588
  		if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
  			return p;
  	return NULL;
  }
  
  /*
f015f1267   David Howells   VFS: Comment moun...
589
590
591
592
593
594
595
596
597
598
599
600
601
602
   * lookup_mnt - Return the first child mount mounted at path
   *
   * "First" means first mounted chronologically.  If you create the
   * following mounts:
   *
   * mount /dev/sda1 /mnt
   * mount /dev/sda2 /mnt
   * mount /dev/sda3 /mnt
   *
   * Then lookup_mnt() on the base /mnt dentry in the root mount will
   * return successively the root dentry and vfsmount of /dev/sda1, then
   * /dev/sda2, then /dev/sda3, then NULL.
   *
   * lookup_mnt takes a reference to the found vfsmount.
a05964f39   Ram Pai   [PATCH] shared mo...
603
   */
ca71cf71e   Al Viro   namespace.c: cons...
604
  struct vfsmount *lookup_mnt(const struct path *path)
a05964f39   Ram Pai   [PATCH] shared mo...
605
  {
c71053659   Al Viro   vfs: spread struc...
606
  	struct mount *child_mnt;
48a066e72   Al Viro   RCU'd vfsmounts
607
608
  	struct vfsmount *m;
  	unsigned seq;
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
609

48a066e72   Al Viro   RCU'd vfsmounts
610
611
612
613
614
615
616
617
  	rcu_read_lock();
  	do {
  		seq = read_seqbegin(&mount_lock);
  		child_mnt = __lookup_mnt(path->mnt, path->dentry);
  		m = child_mnt ? &child_mnt->mnt : NULL;
  	} while (!legitimize_mnt(m, seq));
  	rcu_read_unlock();
  	return m;
a05964f39   Ram Pai   [PATCH] shared mo...
618
  }
7af1364ff   Eric W. Biederman   vfs: Don't allow ...
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
  /*
   * __is_local_mountpoint - Test to see if dentry is a mountpoint in the
   *                         current mount namespace.
   *
   * The common case is dentries are not mountpoints at all and that
   * test is handled inline.  For the slow case when we are actually
   * dealing with a mountpoint of some kind, walk through all of the
   * mounts in the current mount namespace and test to see if the dentry
   * is a mountpoint.
   *
   * The mount_hashtable is not usable in the context because we
   * need to identify all mounts that may be in the current mount
   * namespace not just a mount that happens to have some specified
   * parent mount.
   */
  bool __is_local_mountpoint(struct dentry *dentry)
  {
  	struct mnt_namespace *ns = current->nsproxy->mnt_ns;
  	struct mount *mnt;
  	bool is_covered = false;
  
  	if (!d_mountpoint(dentry))
  		goto out;
  
  	down_read(&namespace_sem);
  	list_for_each_entry(mnt, &ns->list, mnt_list) {
  		is_covered = (mnt->mnt_mountpoint == dentry);
  		if (is_covered)
  			break;
  	}
  	up_read(&namespace_sem);
  out:
  	return is_covered;
  }
e2dfa9354   Eric W. Biederman   vfs: factor out l...
653
  static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
84d17192d   Al Viro   get rid of full-h...
654
  {
0818bf27c   Al Viro   resizable namespa...
655
  	struct hlist_head *chain = mp_hash(dentry);
84d17192d   Al Viro   get rid of full-h...
656
  	struct mountpoint *mp;
0818bf27c   Al Viro   resizable namespa...
657
  	hlist_for_each_entry(mp, chain, m_hash) {
84d17192d   Al Viro   get rid of full-h...
658
  		if (mp->m_dentry == dentry) {
84d17192d   Al Viro   get rid of full-h...
659
660
661
662
  			mp->m_count++;
  			return mp;
  		}
  	}
e2dfa9354   Eric W. Biederman   vfs: factor out l...
663
664
  	return NULL;
  }
3895dbf89   Eric W. Biederman   mnt: Protect the ...
665
  static struct mountpoint *get_mountpoint(struct dentry *dentry)
e2dfa9354   Eric W. Biederman   vfs: factor out l...
666
  {
3895dbf89   Eric W. Biederman   mnt: Protect the ...
667
  	struct mountpoint *mp, *new = NULL;
e2dfa9354   Eric W. Biederman   vfs: factor out l...
668
  	int ret;
84d17192d   Al Viro   get rid of full-h...
669

3895dbf89   Eric W. Biederman   mnt: Protect the ...
670
  	if (d_mountpoint(dentry)) {
1e9c75fb9   Benjamin Coddington   mnt: fix __detach...
671
672
673
  		/* might be worth a WARN_ON() */
  		if (d_unlinked(dentry))
  			return ERR_PTR(-ENOENT);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
674
675
676
677
678
679
680
681
682
683
684
  mountpoint:
  		read_seqlock_excl(&mount_lock);
  		mp = lookup_mountpoint(dentry);
  		read_sequnlock_excl(&mount_lock);
  		if (mp)
  			goto done;
  	}
  
  	if (!new)
  		new = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
  	if (!new)
84d17192d   Al Viro   get rid of full-h...
685
  		return ERR_PTR(-ENOMEM);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
686
687
  
  	/* Exactly one processes may set d_mounted */
eed810076   Miklos Szeredi   vfs: check unlink...
688
  	ret = d_set_mounted(dentry);
eed810076   Miklos Szeredi   vfs: check unlink...
689

3895dbf89   Eric W. Biederman   mnt: Protect the ...
690
691
692
693
694
695
696
697
698
699
700
  	/* Someone else set d_mounted? */
  	if (ret == -EBUSY)
  		goto mountpoint;
  
  	/* The dentry is not available as a mountpoint? */
  	mp = ERR_PTR(ret);
  	if (ret)
  		goto done;
  
  	/* Add the new mountpoint to the hash table */
  	read_seqlock_excl(&mount_lock);
4edbe133f   Al Viro   make struct mount...
701
  	new->m_dentry = dget(dentry);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
702
703
704
705
706
707
708
709
710
  	new->m_count = 1;
  	hlist_add_head(&new->m_hash, mp_hash(dentry));
  	INIT_HLIST_HEAD(&new->m_list);
  	read_sequnlock_excl(&mount_lock);
  
  	mp = new;
  	new = NULL;
  done:
  	kfree(new);
84d17192d   Al Viro   get rid of full-h...
711
712
  	return mp;
  }
4edbe133f   Al Viro   make struct mount...
713
714
715
716
717
  /*
   * vfsmount lock must be held.  Additionally, the caller is responsible
   * for serializing calls for given disposal list.
   */
  static void __put_mountpoint(struct mountpoint *mp, struct list_head *list)
84d17192d   Al Viro   get rid of full-h...
718
719
720
  {
  	if (!--mp->m_count) {
  		struct dentry *dentry = mp->m_dentry;
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
721
  		BUG_ON(!hlist_empty(&mp->m_list));
84d17192d   Al Viro   get rid of full-h...
722
723
724
  		spin_lock(&dentry->d_lock);
  		dentry->d_flags &= ~DCACHE_MOUNTED;
  		spin_unlock(&dentry->d_lock);
4edbe133f   Al Viro   make struct mount...
725
  		dput_to_list(dentry, list);
0818bf27c   Al Viro   resizable namespa...
726
  		hlist_del(&mp->m_hash);
84d17192d   Al Viro   get rid of full-h...
727
728
729
  		kfree(mp);
  	}
  }
4edbe133f   Al Viro   make struct mount...
730
731
732
733
734
  /* called with namespace_lock and vfsmount lock */
  static void put_mountpoint(struct mountpoint *mp)
  {
  	__put_mountpoint(mp, &ex_mountpoints);
  }
143c8c91c   Al Viro   vfs: mnt_ns moved...
735
  static inline int check_mnt(struct mount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
737
  	return mnt->mnt_ns == current->nsproxy->mnt_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
739
740
741
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
742
  static void touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
743
744
745
746
747
748
  {
  	if (ns) {
  		ns->event = ++event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
749
750
751
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
752
  static void __touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
753
754
755
756
757
758
  {
  	if (ns && ns->event != event) {
  		ns->event = event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
759
760
761
  /*
   * vfsmount lock must be held for write
   */
e4e59906c   Al Viro   fs/namespace.c: s...
762
  static struct mountpoint *unhash_mnt(struct mount *mnt)
419148da6   Al Viro   vfs: spread struc...
763
  {
e4e59906c   Al Viro   fs/namespace.c: s...
764
  	struct mountpoint *mp;
0714a5338   Al Viro   vfs: now it can b...
765
  	mnt->mnt_parent = mnt;
a73324da7   Al Viro   vfs: move mnt_mou...
766
  	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
6b41d536f   Al Viro   vfs: take mnt_chi...
767
  	list_del_init(&mnt->mnt_child);
38129a13e   Al Viro   switch mnt_hash t...
768
  	hlist_del_init_rcu(&mnt->mnt_hash);
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
769
  	hlist_del_init(&mnt->mnt_mp_list);
e4e59906c   Al Viro   fs/namespace.c: s...
770
  	mp = mnt->mnt_mp;
84d17192d   Al Viro   get rid of full-h...
771
  	mnt->mnt_mp = NULL;
e4e59906c   Al Viro   fs/namespace.c: s...
772
  	return mp;
7bdb11de8   Eric W. Biederman   mnt: Factor out u...
773
774
775
776
777
  }
  
  /*
   * vfsmount lock must be held for write
   */
6a46c5735   Eric W. Biederman   mnt: Factor umoun...
778
779
  static void umount_mnt(struct mount *mnt)
  {
e4e59906c   Al Viro   fs/namespace.c: s...
780
  	put_mountpoint(unhash_mnt(mnt));
6a46c5735   Eric W. Biederman   mnt: Factor umoun...
781
782
783
784
785
  }
  
  /*
   * vfsmount lock must be held for write
   */
84d17192d   Al Viro   get rid of full-h...
786
787
  void mnt_set_mountpoint(struct mount *mnt,
  			struct mountpoint *mp,
44d964d60   Al Viro   vfs: spread struc...
788
  			struct mount *child_mnt)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
789
  {
84d17192d   Al Viro   get rid of full-h...
790
  	mp->m_count++;
3a2393d71   Al Viro   vfs: opencode mnt...
791
  	mnt_add_count(mnt, 1);	/* essentially, that's mntget */
4edbe133f   Al Viro   make struct mount...
792
  	child_mnt->mnt_mountpoint = mp->m_dentry;
3a2393d71   Al Viro   vfs: opencode mnt...
793
  	child_mnt->mnt_parent = mnt;
84d17192d   Al Viro   get rid of full-h...
794
  	child_mnt->mnt_mp = mp;
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
795
  	hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
796
  }
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
797
798
799
800
801
802
  static void __attach_mnt(struct mount *mnt, struct mount *parent)
  {
  	hlist_add_head_rcu(&mnt->mnt_hash,
  			   m_hash(&parent->mnt, mnt->mnt_mountpoint));
  	list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
803
804
805
  /*
   * vfsmount lock must be held for write
   */
84d17192d   Al Viro   get rid of full-h...
806
807
808
  static void attach_mnt(struct mount *mnt,
  			struct mount *parent,
  			struct mountpoint *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
  {
84d17192d   Al Viro   get rid of full-h...
810
  	mnt_set_mountpoint(parent, mp, mnt);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
811
  	__attach_mnt(mnt, parent);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
812
  }
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
813
  void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct mount *mnt)
12a5b5294   Al Viro   fix copy_tree() r...
814
  {
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
815
  	struct mountpoint *old_mp = mnt->mnt_mp;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
816
817
818
819
820
821
822
823
824
  	struct mount *old_parent = mnt->mnt_parent;
  
  	list_del_init(&mnt->mnt_child);
  	hlist_del_init(&mnt->mnt_mp_list);
  	hlist_del_init_rcu(&mnt->mnt_hash);
  
  	attach_mnt(mnt, parent, mp);
  
  	put_mountpoint(old_mp);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
825
  	mnt_add_count(old_parent, -1);
12a5b5294   Al Viro   fix copy_tree() r...
826
  }
b90fa9ae8   Ram Pai   [PATCH] shared mo...
827
  /*
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
828
   * vfsmount lock must be held for write
b90fa9ae8   Ram Pai   [PATCH] shared mo...
829
   */
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
830
  static void commit_tree(struct mount *mnt)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
831
  {
0714a5338   Al Viro   vfs: now it can b...
832
  	struct mount *parent = mnt->mnt_parent;
83adc7532   Al Viro   vfs: spread struc...
833
  	struct mount *m;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
834
  	LIST_HEAD(head);
143c8c91c   Al Viro   vfs: mnt_ns moved...
835
  	struct mnt_namespace *n = parent->mnt_ns;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
836

0714a5338   Al Viro   vfs: now it can b...
837
  	BUG_ON(parent == mnt);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
838

1a4eeaf2a   Al Viro   vfs: move mnt_lis...
839
  	list_add_tail(&head, &mnt->mnt_list);
f7a99c5b7   Al Viro   get rid of ->mnt_...
840
  	list_for_each_entry(m, &head, mnt_list)
143c8c91c   Al Viro   vfs: mnt_ns moved...
841
  		m->mnt_ns = n;
f03c65993   Al Viro   sanitize vfsmount...
842

b90fa9ae8   Ram Pai   [PATCH] shared mo...
843
  	list_splice(&head, n->list.prev);
d29216842   Eric W. Biederman   mnt: Add a per mo...
844
845
  	n->mounts += n->pending_mounts;
  	n->pending_mounts = 0;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
846
  	__attach_mnt(mnt, parent);
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
847
  	touch_mnt_namespace(n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
  }
909b0a88e   Al Viro   vfs: spread struc...
849
  static struct mount *next_mnt(struct mount *p, struct mount *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
  {
6b41d536f   Al Viro   vfs: take mnt_chi...
851
852
  	struct list_head *next = p->mnt_mounts.next;
  	if (next == &p->mnt_mounts) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
  		while (1) {
909b0a88e   Al Viro   vfs: spread struc...
854
  			if (p == root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  				return NULL;
6b41d536f   Al Viro   vfs: take mnt_chi...
856
857
  			next = p->mnt_child.next;
  			if (next != &p->mnt_parent->mnt_mounts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
  				break;
0714a5338   Al Viro   vfs: now it can b...
859
  			p = p->mnt_parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
  		}
  	}
6b41d536f   Al Viro   vfs: take mnt_chi...
862
  	return list_entry(next, struct mount, mnt_child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
  }
315fc83e5   Al Viro   vfs: spread struc...
864
  static struct mount *skip_mnt_tree(struct mount *p)
9676f0c63   Ram Pai   [PATCH] unbindabl...
865
  {
6b41d536f   Al Viro   vfs: take mnt_chi...
866
867
868
869
  	struct list_head *prev = p->mnt_mounts.prev;
  	while (prev != &p->mnt_mounts) {
  		p = list_entry(prev, struct mount, mnt_child);
  		prev = p->mnt_mounts.prev;
9676f0c63   Ram Pai   [PATCH] unbindabl...
870
871
872
  	}
  	return p;
  }
8f2918898   Al Viro   new helpers: vfs_...
873
874
875
876
877
878
879
880
881
882
  /**
   * vfs_create_mount - Create a mount for a configured superblock
   * @fc: The configuration context with the superblock attached
   *
   * Create a mount to an already configured superblock.  If necessary, the
   * caller should invoke vfs_get_tree() before calling this.
   *
   * Note that this does not attach the mount to anything.
   */
  struct vfsmount *vfs_create_mount(struct fs_context *fc)
9d412a43c   Al Viro   vfs: split off vf...
883
  {
b105e270b   Al Viro   vfs: spread struc...
884
  	struct mount *mnt;
9d412a43c   Al Viro   vfs: split off vf...
885

8f2918898   Al Viro   new helpers: vfs_...
886
887
  	if (!fc->root)
  		return ERR_PTR(-EINVAL);
9d412a43c   Al Viro   vfs: split off vf...
888

8f2918898   Al Viro   new helpers: vfs_...
889
  	mnt = alloc_vfsmnt(fc->source ?: "none");
9d412a43c   Al Viro   vfs: split off vf...
890
891
  	if (!mnt)
  		return ERR_PTR(-ENOMEM);
8f2918898   Al Viro   new helpers: vfs_...
892
  	if (fc->sb_flags & SB_KERNMOUNT)
b105e270b   Al Viro   vfs: spread struc...
893
  		mnt->mnt.mnt_flags = MNT_INTERNAL;
9d412a43c   Al Viro   vfs: split off vf...
894

8f2918898   Al Viro   new helpers: vfs_...
895
896
897
898
899
  	atomic_inc(&fc->root->d_sb->s_active);
  	mnt->mnt.mnt_sb		= fc->root->d_sb;
  	mnt->mnt.mnt_root	= dget(fc->root);
  	mnt->mnt_mountpoint	= mnt->mnt.mnt_root;
  	mnt->mnt_parent		= mnt;
9d412a43c   Al Viro   vfs: split off vf...
900

719ea2fbb   Al Viro   new helpers: lock...
901
  	lock_mount_hash();
8f2918898   Al Viro   new helpers: vfs_...
902
  	list_add_tail(&mnt->mnt_instance, &mnt->mnt.mnt_sb->s_mounts);
719ea2fbb   Al Viro   new helpers: lock...
903
  	unlock_mount_hash();
b105e270b   Al Viro   vfs: spread struc...
904
  	return &mnt->mnt;
9d412a43c   Al Viro   vfs: split off vf...
905
  }
8f2918898   Al Viro   new helpers: vfs_...
906
907
908
909
910
911
912
913
914
915
916
917
  EXPORT_SYMBOL(vfs_create_mount);
  
  struct vfsmount *fc_mount(struct fs_context *fc)
  {
  	int err = vfs_get_tree(fc);
  	if (!err) {
  		up_write(&fc->root->d_sb->s_umount);
  		return vfs_create_mount(fc);
  	}
  	return ERR_PTR(err);
  }
  EXPORT_SYMBOL(fc_mount);
9bc61ab18   David Howells   vfs: Introduce fs...
918
919
920
  struct vfsmount *vfs_kern_mount(struct file_system_type *type,
  				int flags, const char *name,
  				void *data)
9d412a43c   Al Viro   vfs: split off vf...
921
  {
9bc61ab18   David Howells   vfs: Introduce fs...
922
  	struct fs_context *fc;
8f2918898   Al Viro   new helpers: vfs_...
923
  	struct vfsmount *mnt;
9bc61ab18   David Howells   vfs: Introduce fs...
924
  	int ret = 0;
9d412a43c   Al Viro   vfs: split off vf...
925
926
  
  	if (!type)
3e1aeb00e   David Howells   vfs: Implement a ...
927
  		return ERR_PTR(-EINVAL);
9d412a43c   Al Viro   vfs: split off vf...
928

9bc61ab18   David Howells   vfs: Introduce fs...
929
930
931
  	fc = fs_context_for_mount(type, flags);
  	if (IS_ERR(fc))
  		return ERR_CAST(fc);
3e1aeb00e   David Howells   vfs: Implement a ...
932
933
934
  	if (name)
  		ret = vfs_parse_fs_string(fc, "source",
  					  name, strlen(name));
9bc61ab18   David Howells   vfs: Introduce fs...
935
936
937
  	if (!ret)
  		ret = parse_monolithic_mount_data(fc, data);
  	if (!ret)
8f2918898   Al Viro   new helpers: vfs_...
938
939
940
  		mnt = fc_mount(fc);
  	else
  		mnt = ERR_PTR(ret);
9d412a43c   Al Viro   vfs: split off vf...
941

9bc61ab18   David Howells   vfs: Introduce fs...
942
  	put_fs_context(fc);
8f2918898   Al Viro   new helpers: vfs_...
943
  	return mnt;
9d412a43c   Al Viro   vfs: split off vf...
944
945
  }
  EXPORT_SYMBOL_GPL(vfs_kern_mount);
93faccbbf   Eric W. Biederman   fs: Better permis...
946
947
948
949
950
951
952
953
954
955
  struct vfsmount *
  vfs_submount(const struct dentry *mountpoint, struct file_system_type *type,
  	     const char *name, void *data)
  {
  	/* Until it is worked out how to pass the user namespace
  	 * through from the parent mount to the submount don't support
  	 * unprivileged mounts with submounts.
  	 */
  	if (mountpoint->d_sb->s_user_ns != &init_user_ns)
  		return ERR_PTR(-EPERM);
e462ec50c   David Howells   VFS: Differentiat...
956
  	return vfs_kern_mount(type, SB_SUBMOUNT, name, data);
93faccbbf   Eric W. Biederman   fs: Better permis...
957
958
  }
  EXPORT_SYMBOL_GPL(vfs_submount);
87129cc0e   Al Viro   vfs: spread struc...
959
  static struct mount *clone_mnt(struct mount *old, struct dentry *root,
36341f645   Ram Pai   [PATCH] mount exp...
960
  					int flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  {
87129cc0e   Al Viro   vfs: spread struc...
962
  	struct super_block *sb = old->mnt.mnt_sb;
be34d1a3b   David Howells   VFS: Make clone_m...
963
964
  	struct mount *mnt;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965

be34d1a3b   David Howells   VFS: Make clone_m...
966
967
968
  	mnt = alloc_vfsmnt(old->mnt_devname);
  	if (!mnt)
  		return ERR_PTR(-ENOMEM);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
969

7a472ef4b   Eric W. Biederman   vfs: Only support...
970
  	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
be34d1a3b   David Howells   VFS: Make clone_m...
971
972
973
  		mnt->mnt_group_id = 0; /* not a peer of original */
  	else
  		mnt->mnt_group_id = old->mnt_group_id;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
974

be34d1a3b   David Howells   VFS: Make clone_m...
975
976
977
978
  	if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) {
  		err = mnt_alloc_group_id(mnt);
  		if (err)
  			goto out_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
980

16a34adb9   Al Viro   Don't leak MNT_IN...
981
982
  	mnt->mnt.mnt_flags = old->mnt.mnt_flags;
  	mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL);
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
983

be34d1a3b   David Howells   VFS: Make clone_m...
984
985
986
987
988
  	atomic_inc(&sb->s_active);
  	mnt->mnt.mnt_sb = sb;
  	mnt->mnt.mnt_root = dget(root);
  	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
  	mnt->mnt_parent = mnt;
719ea2fbb   Al Viro   new helpers: lock...
989
  	lock_mount_hash();
be34d1a3b   David Howells   VFS: Make clone_m...
990
  	list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
719ea2fbb   Al Viro   new helpers: lock...
991
  	unlock_mount_hash();
be34d1a3b   David Howells   VFS: Make clone_m...
992

7a472ef4b   Eric W. Biederman   vfs: Only support...
993
994
  	if ((flag & CL_SLAVE) ||
  	    ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
be34d1a3b   David Howells   VFS: Make clone_m...
995
996
997
998
999
1000
1001
1002
1003
  		list_add(&mnt->mnt_slave, &old->mnt_slave_list);
  		mnt->mnt_master = old;
  		CLEAR_MNT_SHARED(mnt);
  	} else if (!(flag & CL_PRIVATE)) {
  		if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
  			list_add(&mnt->mnt_share, &old->mnt_share);
  		if (IS_MNT_SLAVE(old))
  			list_add(&mnt->mnt_slave, &old->mnt_slave);
  		mnt->mnt_master = old->mnt_master;
5235d448c   Al Viro   reorganize do_mak...
1004
1005
  	} else {
  		CLEAR_MNT_SHARED(mnt);
be34d1a3b   David Howells   VFS: Make clone_m...
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
  	}
  	if (flag & CL_MAKE_SHARED)
  		set_mnt_shared(mnt);
  
  	/* stick the duplicate mount on the same expiry list
  	 * as the original if that was on one */
  	if (flag & CL_EXPIRE) {
  		if (!list_empty(&old->mnt_expire))
  			list_add(&mnt->mnt_expire, &old->mnt_expire);
  	}
cb338d06e   Al Viro   vfs: spread struc...
1016
  	return mnt;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1017
1018
  
   out_free:
8ffcb32e0   David Howells   VFS: Make delayed...
1019
  	mnt_free_id(mnt);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1020
  	free_vfsmnt(mnt);
be34d1a3b   David Howells   VFS: Make clone_m...
1021
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
  }
9ea459e11   Al Viro   delayed mntput
1023
1024
  static void cleanup_mnt(struct mount *mnt)
  {
56cbb429d   Al Viro   switch the remnan...
1025
1026
  	struct hlist_node *p;
  	struct mount *m;
9ea459e11   Al Viro   delayed mntput
1027
  	/*
56cbb429d   Al Viro   switch the remnan...
1028
1029
1030
  	 * The warning here probably indicates that somebody messed
  	 * up a mnt_want/drop_write() pair.  If this happens, the
  	 * filesystem was probably unable to make r/w->r/o transitions.
9ea459e11   Al Viro   delayed mntput
1031
1032
1033
1034
1035
1036
  	 * The locking used to deal with mnt_count decrement provides barriers,
  	 * so mnt_get_writers() below is safe.
  	 */
  	WARN_ON(mnt_get_writers(mnt));
  	if (unlikely(mnt->mnt_pins.first))
  		mnt_pin_kill(mnt);
56cbb429d   Al Viro   switch the remnan...
1037
1038
1039
1040
  	hlist_for_each_entry_safe(m, p, &mnt->mnt_stuck_children, mnt_umount) {
  		hlist_del(&m->mnt_umount);
  		mntput(&m->mnt);
  	}
9ea459e11   Al Viro   delayed mntput
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
  	fsnotify_vfsmount_delete(&mnt->mnt);
  	dput(mnt->mnt.mnt_root);
  	deactivate_super(mnt->mnt.mnt_sb);
  	mnt_free_id(mnt);
  	call_rcu(&mnt->mnt_rcu, delayed_free_vfsmnt);
  }
  
  static void __cleanup_mnt(struct rcu_head *head)
  {
  	cleanup_mnt(container_of(head, struct mount, mnt_rcu));
  }
  
  static LLIST_HEAD(delayed_mntput_list);
  static void delayed_mntput(struct work_struct *unused)
  {
  	struct llist_node *node = llist_del_all(&delayed_mntput_list);
297857357   Byungchul Park   namespace.c: Don'...
1057
  	struct mount *m, *t;
9ea459e11   Al Viro   delayed mntput
1058

297857357   Byungchul Park   namespace.c: Don'...
1059
1060
  	llist_for_each_entry_safe(m, t, node, mnt_llist)
  		cleanup_mnt(m);
9ea459e11   Al Viro   delayed mntput
1061
1062
  }
  static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
900148dca   Al Viro   vfs: spread struc...
1063
  static void mntput_no_expire(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
1064
  {
4edbe133f   Al Viro   make struct mount...
1065
  	LIST_HEAD(list);
48a066e72   Al Viro   RCU'd vfsmounts
1066
  	rcu_read_lock();
9ea0a46ca   Al Viro   fix mntput/mntput...
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  	if (likely(READ_ONCE(mnt->mnt_ns))) {
  		/*
  		 * Since we don't do lock_mount_hash() here,
  		 * ->mnt_ns can change under us.  However, if it's
  		 * non-NULL, then there's a reference that won't
  		 * be dropped until after an RCU delay done after
  		 * turning ->mnt_ns NULL.  So if we observe it
  		 * non-NULL under rcu_read_lock(), the reference
  		 * we are dropping is not the final one.
  		 */
  		mnt_add_count(mnt, -1);
48a066e72   Al Viro   RCU'd vfsmounts
1078
  		rcu_read_unlock();
f03c65993   Al Viro   sanitize vfsmount...
1079
  		return;
b3e19d924   Nick Piggin   fs: scale mntget/...
1080
  	}
719ea2fbb   Al Viro   new helpers: lock...
1081
  	lock_mount_hash();
119e1ef80   Al Viro   fix __legitimize_...
1082
1083
1084
1085
1086
  	/*
  	 * make sure that if __legitimize_mnt() has not seen us grab
  	 * mount_lock, we'll see their refcount increment here.
  	 */
  	smp_mb();
9ea0a46ca   Al Viro   fix mntput/mntput...
1087
  	mnt_add_count(mnt, -1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1088
  	if (mnt_get_count(mnt)) {
48a066e72   Al Viro   RCU'd vfsmounts
1089
  		rcu_read_unlock();
719ea2fbb   Al Viro   new helpers: lock...
1090
  		unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1091
1092
  		return;
  	}
48a066e72   Al Viro   RCU'd vfsmounts
1093
1094
1095
1096
1097
1098
1099
  	if (unlikely(mnt->mnt.mnt_flags & MNT_DOOMED)) {
  		rcu_read_unlock();
  		unlock_mount_hash();
  		return;
  	}
  	mnt->mnt.mnt_flags |= MNT_DOOMED;
  	rcu_read_unlock();
962830df3   Andi Kleen   brlocks/lglocks: ...
1100

39f7c4db1   Miklos Szeredi   vfs: keep list of...
1101
  	list_del(&mnt->mnt_instance);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1102
1103
1104
1105
  
  	if (unlikely(!list_empty(&mnt->mnt_mounts))) {
  		struct mount *p, *tmp;
  		list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts,  mnt_child) {
4edbe133f   Al Viro   make struct mount...
1106
  			__put_mountpoint(unhash_mnt(p), &list);
56cbb429d   Al Viro   switch the remnan...
1107
  			hlist_add_head(&p->mnt_umount, &mnt->mnt_stuck_children);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1108
1109
  		}
  	}
719ea2fbb   Al Viro   new helpers: lock...
1110
  	unlock_mount_hash();
4edbe133f   Al Viro   make struct mount...
1111
  	shrink_dentry_list(&list);
649a795af   Al Viro   fold mntfree() in...
1112

9ea459e11   Al Viro   delayed mntput
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
  	if (likely(!(mnt->mnt.mnt_flags & MNT_INTERNAL))) {
  		struct task_struct *task = current;
  		if (likely(!(task->flags & PF_KTHREAD))) {
  			init_task_work(&mnt->mnt_rcu, __cleanup_mnt);
  			if (!task_work_add(task, &mnt->mnt_rcu, true))
  				return;
  		}
  		if (llist_add(&mnt->mnt_llist, &delayed_mntput_list))
  			schedule_delayed_work(&delayed_mntput_work, 1);
  		return;
  	}
  	cleanup_mnt(mnt);
b3e19d924   Nick Piggin   fs: scale mntget/...
1125
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
1126
1127
1128
1129
  
  void mntput(struct vfsmount *mnt)
  {
  	if (mnt) {
863d684f9   Al Viro   vfs: move the res...
1130
  		struct mount *m = real_mount(mnt);
b3e19d924   Nick Piggin   fs: scale mntget/...
1131
  		/* avoid cacheline pingpong, hope gcc doesn't get "smart" */
863d684f9   Al Viro   vfs: move the res...
1132
1133
1134
  		if (unlikely(m->mnt_expiry_mark))
  			m->mnt_expiry_mark = 0;
  		mntput_no_expire(m);
b3e19d924   Nick Piggin   fs: scale mntget/...
1135
1136
1137
1138
1139
1140
1141
  	}
  }
  EXPORT_SYMBOL(mntput);
  
  struct vfsmount *mntget(struct vfsmount *mnt)
  {
  	if (mnt)
83adc7532   Al Viro   vfs: spread struc...
1142
  		mnt_add_count(real_mount(mnt), 1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1143
1144
1145
  	return mnt;
  }
  EXPORT_SYMBOL(mntget);
c6609c0a1   Ian Kent   vfs: add path_is_...
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
  /* path_is_mountpoint() - Check if path is a mount in the current
   *                          namespace.
   *
   *  d_mountpoint() can only be used reliably to establish if a dentry is
   *  not mounted in any namespace and that common case is handled inline.
   *  d_mountpoint() isn't aware of the possibility there may be multiple
   *  mounts using a given dentry in a different namespace. This function
   *  checks if the passed in path is a mountpoint rather than the dentry
   *  alone.
   */
  bool path_is_mountpoint(const struct path *path)
  {
  	unsigned seq;
  	bool res;
  
  	if (!d_mountpoint(path->dentry))
  		return false;
  
  	rcu_read_lock();
  	do {
  		seq = read_seqbegin(&mount_lock);
  		res = __path_is_mountpoint(path);
  	} while (read_seqretry(&mount_lock, seq));
  	rcu_read_unlock();
  
  	return res;
  }
  EXPORT_SYMBOL(path_is_mountpoint);
ca71cf71e   Al Viro   namespace.c: cons...
1174
  struct vfsmount *mnt_clone_internal(const struct path *path)
7b7b1ace2   Al Viro   [PATCH] saner han...
1175
  {
3064c3563   Al Viro   death to mnt_pinned
1176
1177
1178
1179
1180
1181
  	struct mount *p;
  	p = clone_mnt(real_mount(path->mnt), path->dentry, CL_PRIVATE);
  	if (IS_ERR(p))
  		return ERR_CAST(p);
  	p->mnt.mnt_flags |= MNT_INTERNAL;
  	return &p->mnt;
7b7b1ace2   Al Viro   [PATCH] saner han...
1182
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183

a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1184
  #ifdef CONFIG_PROC_FS
0226f4923   Al Viro   vfs: take /proc/*...
1185
  /* iterator; we want it to have access to namespace_sem, thus here... */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
1187
  static void *m_start(struct seq_file *m, loff_t *pos)
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1188
  	struct proc_mounts *p = m->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1189

390c68436   Ram Pai   [PATCH] making na...
1190
  	down_read(&namespace_sem);
c7999c362   Al Viro   reduce m_start() ...
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
  	if (p->cached_event == p->ns->event) {
  		void *v = p->cached_mount;
  		if (*pos == p->cached_index)
  			return v;
  		if (*pos == p->cached_index + 1) {
  			v = seq_list_next(v, &p->ns->list, &p->cached_index);
  			return p->cached_mount = v;
  		}
  	}
  
  	p->cached_event = p->ns->event;
  	p->cached_mount = seq_list_start(&p->ns->list, *pos);
  	p->cached_index = *pos;
  	return p->cached_mount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
1208
  }
  
  static void *m_next(struct seq_file *m, void *v, loff_t *pos)
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1209
  	struct proc_mounts *p = m->private;
b0765fb85   Pavel Emelianov   Make /proc/self/m...
1210

c7999c362   Al Viro   reduce m_start() ...
1211
1212
1213
  	p->cached_mount = seq_list_next(v, &p->ns->list, pos);
  	p->cached_index = *pos;
  	return p->cached_mount;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
1216
1217
  }
  
  static void m_stop(struct seq_file *m, void *v)
  {
390c68436   Ram Pai   [PATCH] making na...
1218
  	up_read(&namespace_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219
  }
0226f4923   Al Viro   vfs: take /proc/*...
1220
  static int m_show(struct seq_file *m, void *v)
2d4d4864a   Ram Pai   [patch 6/7] vfs: ...
1221
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1222
  	struct proc_mounts *p = m->private;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1223
  	struct mount *r = list_entry(v, struct mount, mnt_list);
0226f4923   Al Viro   vfs: take /proc/*...
1224
  	return p->show(m, &r->mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225
  }
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1226
  const struct seq_operations mounts_op = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
1229
  	.start	= m_start,
  	.next	= m_next,
  	.stop	= m_stop,
0226f4923   Al Viro   vfs: take /proc/*...
1230
  	.show	= m_show,
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1231
  };
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1232
  #endif  /* CONFIG_PROC_FS */
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1233

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
1235
1236
1237
1238
1239
1240
1241
  /**
   * may_umount_tree - check if a mount tree is busy
   * @mnt: root of mount tree
   *
   * This is called to check if a tree of mounts has any
   * open files, pwds, chroots or sub mounts that are
   * busy.
   */
909b0a88e   Al Viro   vfs: spread struc...
1242
  int may_umount_tree(struct vfsmount *m)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
  {
909b0a88e   Al Viro   vfs: spread struc...
1244
  	struct mount *mnt = real_mount(m);
36341f645   Ram Pai   [PATCH] mount exp...
1245
1246
  	int actual_refs = 0;
  	int minimum_refs = 0;
315fc83e5   Al Viro   vfs: spread struc...
1247
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
1248
  	BUG_ON(!m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249

b3e19d924   Nick Piggin   fs: scale mntget/...
1250
  	/* write lock needed for mnt_get_count */
719ea2fbb   Al Viro   new helpers: lock...
1251
  	lock_mount_hash();
909b0a88e   Al Viro   vfs: spread struc...
1252
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
83adc7532   Al Viro   vfs: spread struc...
1253
  		actual_refs += mnt_get_count(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
  		minimum_refs += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
  	}
719ea2fbb   Al Viro   new helpers: lock...
1256
  	unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1257
1258
  
  	if (actual_refs > minimum_refs)
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1259
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260

e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1261
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
  }
  
  EXPORT_SYMBOL(may_umount_tree);
  
  /**
   * may_umount - check if a mount point is busy
   * @mnt: root of mount
   *
   * This is called to check if a mount point has any
   * open files, pwds, chroots or sub mounts. If the
   * mount has sub mounts this will return busy
   * regardless of whether the sub mounts are busy.
   *
   * Doesn't take quota and stuff into account. IOW, in some cases it will
   * give false negatives. The main reason why it's here is that we need
   * a non-destructive way to look for easily umountable filesystems.
   */
  int may_umount(struct vfsmount *mnt)
  {
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1281
  	int ret = 1;
8ad08d8a0   Al Viro   may_umount() need...
1282
  	down_read(&namespace_sem);
719ea2fbb   Al Viro   new helpers: lock...
1283
  	lock_mount_hash();
1ab597386   Al Viro   vfs: spread struc...
1284
  	if (propagate_mount_busy(real_mount(mnt), 2))
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1285
  		ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
1286
  	unlock_mount_hash();
8ad08d8a0   Al Viro   may_umount() need...
1287
  	up_read(&namespace_sem);
a05964f39   Ram Pai   [PATCH] shared mo...
1288
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
1290
1291
  }
  
  EXPORT_SYMBOL(may_umount);
97216be09   Al Viro   fold release_moun...
1292
  static void namespace_unlock(void)
70fbcdf4d   Ram Pai   [PATCH] umount_tr...
1293
  {
a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1294
  	struct hlist_head head;
56cbb429d   Al Viro   switch the remnan...
1295
1296
  	struct hlist_node *p;
  	struct mount *m;
4edbe133f   Al Viro   make struct mount...
1297
  	LIST_HEAD(list);
97216be09   Al Viro   fold release_moun...
1298

a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1299
  	hlist_move_list(&unmounted, &head);
4edbe133f   Al Viro   make struct mount...
1300
  	list_splice_init(&ex_mountpoints, &list);
97216be09   Al Viro   fold release_moun...
1301

97216be09   Al Viro   fold release_moun...
1302
  	up_write(&namespace_sem);
4edbe133f   Al Viro   make struct mount...
1303
  	shrink_dentry_list(&list);
a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1304
1305
  	if (likely(hlist_empty(&head)))
  		return;
22cb7405f   NeilBrown   VFS: use synchron...
1306
  	synchronize_rcu_expedited();
48a066e72   Al Viro   RCU'd vfsmounts
1307

56cbb429d   Al Viro   switch the remnan...
1308
1309
1310
1311
  	hlist_for_each_entry_safe(m, p, &head, mnt_umount) {
  		hlist_del(&m->mnt_umount);
  		mntput(&m->mnt);
  	}
70fbcdf4d   Ram Pai   [PATCH] umount_tr...
1312
  }
97216be09   Al Viro   fold release_moun...
1313
  static inline void namespace_lock(void)
e3197d83d   Al Viro   saner umount_tree...
1314
  {
97216be09   Al Viro   fold release_moun...
1315
  	down_write(&namespace_sem);
e3197d83d   Al Viro   saner umount_tree...
1316
  }
e819f1521   Eric W. Biederman   mnt: Improve the ...
1317
1318
1319
  enum umount_tree_flags {
  	UMOUNT_SYNC = 1,
  	UMOUNT_PROPAGATE = 2,
e0c9c0afd   Eric W. Biederman   mnt: Update detac...
1320
  	UMOUNT_CONNECTED = 4,
e819f1521   Eric W. Biederman   mnt: Improve the ...
1321
  };
f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
  
  static bool disconnect_mount(struct mount *mnt, enum umount_tree_flags how)
  {
  	/* Leaving mounts connected is only valid for lazy umounts */
  	if (how & UMOUNT_SYNC)
  		return true;
  
  	/* A mount without a parent has nothing to be connected to */
  	if (!mnt_has_parent(mnt))
  		return true;
  
  	/* Because the reference counting rules change when mounts are
  	 * unmounted and connected, umounted mounts may not be
  	 * connected to mounted mounts.
  	 */
  	if (!(mnt->mnt_parent->mnt.mnt_flags & MNT_UMOUNT))
  		return true;
  
  	/* Has it been requested that the mount remain connected? */
  	if (how & UMOUNT_CONNECTED)
  		return false;
  
  	/* Is the mount locked such that it needs to remain connected? */
  	if (IS_MNT_LOCKED(mnt))
  		return false;
  
  	/* By default disconnect the mount */
  	return true;
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1351
  /*
48a066e72   Al Viro   RCU'd vfsmounts
1352
   * mount_lock must be held
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1353
1354
   * namespace_sem must be held for write
   */
e819f1521   Eric W. Biederman   mnt: Improve the ...
1355
  static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
  {
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1357
  	LIST_HEAD(tmp_list);
315fc83e5   Al Viro   vfs: spread struc...
1358
  	struct mount *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359

5d88457eb   Eric W. Biederman   mnt: On an unmoun...
1360
1361
  	if (how & UMOUNT_PROPAGATE)
  		propagate_mount_unlock(mnt);
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1362
  	/* Gather the mounts to umount */
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1363
1364
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
  		p->mnt.mnt_flags |= MNT_UMOUNT;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1365
  		list_move(&p->mnt_list, &tmp_list);
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1366
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367

411a938b5   Eric W. Biederman   mnt: Delay remova...
1368
  	/* Hide the mounts from mnt_mounts */
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1369
  	list_for_each_entry(p, &tmp_list, mnt_list) {
88b368f27   Al Viro   get rid of propag...
1370
  		list_del_init(&p->mnt_child);
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1371
  	}
88b368f27   Al Viro   get rid of propag...
1372

c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1373
  	/* Add propogated mounts to the tmp_list */
e819f1521   Eric W. Biederman   mnt: Improve the ...
1374
  	if (how & UMOUNT_PROPAGATE)
7b8a53fd8   Al Viro   fix old umount_tr...
1375
  		propagate_umount(&tmp_list);
a05964f39   Ram Pai   [PATCH] shared mo...
1376

c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1377
  	while (!list_empty(&tmp_list)) {
d29216842   Eric W. Biederman   mnt: Add a per mo...
1378
  		struct mnt_namespace *ns;
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1379
  		bool disconnect;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1380
  		p = list_first_entry(&tmp_list, struct mount, mnt_list);
6776db3d3   Al Viro   vfs: take mnt_sha...
1381
  		list_del_init(&p->mnt_expire);
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1382
  		list_del_init(&p->mnt_list);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1383
1384
1385
1386
1387
  		ns = p->mnt_ns;
  		if (ns) {
  			ns->mounts--;
  			__touch_mnt_namespace(ns);
  		}
143c8c91c   Al Viro   vfs: mnt_ns moved...
1388
  		p->mnt_ns = NULL;
e819f1521   Eric W. Biederman   mnt: Improve the ...
1389
  		if (how & UMOUNT_SYNC)
48a066e72   Al Viro   RCU'd vfsmounts
1390
  			p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
87b95ce09   Al Viro   switch the IO-tri...
1391

f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1392
  		disconnect = disconnect_mount(p, how);
676da58df   Al Viro   vfs: spread struc...
1393
  		if (mnt_has_parent(p)) {
81b6b0619   Al Viro   fix EBUSY on umou...
1394
  			mnt_add_count(p->mnt_parent, -1);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1395
1396
1397
1398
1399
1400
  			if (!disconnect) {
  				/* Don't forget about p */
  				list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts);
  			} else {
  				umount_mnt(p);
  			}
7c4b93d82   Al Viro   [PATCH] count gho...
1401
  		}
0f0afb1dc   Al Viro   vfs: spread struc...
1402
  		change_mnt_propagation(p, MS_PRIVATE);
19a1c4092   Al Viro   fix the struct mo...
1403
1404
  		if (disconnect)
  			hlist_add_head(&p->mnt_umount, &unmounted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
1406
  	}
  }
b54b9be78   Al Viro   get rid of the se...
1407
  static void shrink_submounts(struct mount *mnt);
c35038bec   Al Viro   [PATCH] do shrink...
1408

8d0347f6c   David Howells   convert do_remoun...
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
  static int do_umount_root(struct super_block *sb)
  {
  	int ret = 0;
  
  	down_write(&sb->s_umount);
  	if (!sb_rdonly(sb)) {
  		struct fs_context *fc;
  
  		fc = fs_context_for_reconfigure(sb->s_root, SB_RDONLY,
  						SB_RDONLY);
  		if (IS_ERR(fc)) {
  			ret = PTR_ERR(fc);
  		} else {
  			ret = parse_monolithic_mount_data(fc, NULL);
  			if (!ret)
  				ret = reconfigure_super(fc);
  			put_fs_context(fc);
  		}
  	}
  	up_write(&sb->s_umount);
  	return ret;
  }
1ab597386   Al Viro   vfs: spread struc...
1431
  static int do_umount(struct mount *mnt, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432
  {
1ab597386   Al Viro   vfs: spread struc...
1433
  	struct super_block *sb = mnt->mnt.mnt_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1434
  	int retval;
1ab597386   Al Viro   vfs: spread struc...
1435
  	retval = security_sb_umount(&mnt->mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  	if (retval)
  		return retval;
  
  	/*
  	 * Allow userspace to request a mountpoint be expired rather than
  	 * unmounting unconditionally. Unmount only happens if:
  	 *  (1) the mark is already set (the mark is cleared by mntput())
  	 *  (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount]
  	 */
  	if (flags & MNT_EXPIRE) {
1ab597386   Al Viro   vfs: spread struc...
1446
  		if (&mnt->mnt == current->fs->root.mnt ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
1448
  		    flags & (MNT_FORCE | MNT_DETACH))
  			return -EINVAL;
b3e19d924   Nick Piggin   fs: scale mntget/...
1449
1450
1451
1452
  		/*
  		 * probably don't strictly need the lock here if we examined
  		 * all race cases, but it's a slowpath.
  		 */
719ea2fbb   Al Viro   new helpers: lock...
1453
  		lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
1454
  		if (mnt_get_count(mnt) != 2) {
719ea2fbb   Al Viro   new helpers: lock...
1455
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1456
  			return -EBUSY;
b3e19d924   Nick Piggin   fs: scale mntget/...
1457
  		}
719ea2fbb   Al Viro   new helpers: lock...
1458
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459

863d684f9   Al Viro   vfs: move the res...
1460
  		if (!xchg(&mnt->mnt_expiry_mark, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  			return -EAGAIN;
  	}
  
  	/*
  	 * If we may have to abort operations to get out of this
  	 * mount, and they will themselves hold resources we must
  	 * allow the fs to do things. In the Unix tradition of
  	 * 'Gee thats tricky lets do it in userspace' the umount_begin
  	 * might fail to complete on the first run through as other tasks
  	 * must return, and the like. Thats for the mount program to worry
  	 * about for the moment.
  	 */
42faad996   Al Viro   [PATCH] restore s...
1473
  	if (flags & MNT_FORCE && sb->s_op->umount_begin) {
42faad996   Al Viro   [PATCH] restore s...
1474
  		sb->s_op->umount_begin(sb);
42faad996   Al Viro   [PATCH] restore s...
1475
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
  
  	/*
  	 * No sense to grab the lock for this test, but test itself looks
  	 * somewhat bogus. Suggestions for better replacement?
  	 * Ho-hum... In principle, we might treat that as umount + switch
  	 * to rootfs. GC would eventually take care of the old vfsmount.
  	 * Actually it makes sense, especially if rootfs would contain a
  	 * /reboot - static binary that would close all descriptors and
  	 * call reboot(9). Then init(8) could umount root and exec /reboot.
  	 */
1ab597386   Al Viro   vfs: spread struc...
1486
  	if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1487
1488
1489
1490
  		/*
  		 * Special case for "unmounting" root ...
  		 * we just try to remount it readonly.
  		 */
bc6155d13   Eric W. Biederman   fs: Allow superbl...
1491
  		if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
a1480dcc3   Andy Lutomirski   fs: Add a missing...
1492
  			return -EPERM;
8d0347f6c   David Howells   convert do_remoun...
1493
  		return do_umount_root(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
  	}
97216be09   Al Viro   fold release_moun...
1495
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1496
  	lock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1497

25d202ed8   Eric W. Biederman   mount: Retest MNT...
1498
1499
1500
1501
1502
1503
  	/* Recheck MNT_LOCKED with the locks held */
  	retval = -EINVAL;
  	if (mnt->mnt.mnt_flags & MNT_LOCKED)
  		goto out;
  
  	event++;
48a066e72   Al Viro   RCU'd vfsmounts
1504
  	if (flags & MNT_DETACH) {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1505
  		if (!list_empty(&mnt->mnt_list))
e819f1521   Eric W. Biederman   mnt: Improve the ...
1506
  			umount_tree(mnt, UMOUNT_PROPAGATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1507
  		retval = 0;
48a066e72   Al Viro   RCU'd vfsmounts
1508
1509
1510
1511
1512
  	} else {
  		shrink_submounts(mnt);
  		retval = -EBUSY;
  		if (!propagate_mount_busy(mnt, 2)) {
  			if (!list_empty(&mnt->mnt_list))
e819f1521   Eric W. Biederman   mnt: Improve the ...
1513
  				umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
48a066e72   Al Viro   RCU'd vfsmounts
1514
1515
  			retval = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1516
  	}
25d202ed8   Eric W. Biederman   mount: Retest MNT...
1517
  out:
719ea2fbb   Al Viro   new helpers: lock...
1518
  	unlock_mount_hash();
e3197d83d   Al Viro   saner umount_tree...
1519
  	namespace_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1520
1521
  	return retval;
  }
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
  /*
   * __detach_mounts - lazily unmount all mounts on the specified dentry
   *
   * During unlink, rmdir, and d_drop it is possible to loose the path
   * to an existing mountpoint, and wind up leaking the mount.
   * detach_mounts allows lazily unmounting those mounts instead of
   * leaking them.
   *
   * The caller may hold dentry->d_inode->i_mutex.
   */
  void __detach_mounts(struct dentry *dentry)
  {
  	struct mountpoint *mp;
  	struct mount *mnt;
  
  	namespace_lock();
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1538
  	lock_mount_hash();
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1539
  	mp = lookup_mountpoint(dentry);
adc9b5c09   Al Viro   __detach_mounts()...
1540
  	if (!mp)
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1541
  		goto out_unlock;
e06b933e6   Andrey Ulanov   namespace: update...
1542
  	event++;
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1543
1544
  	while (!hlist_empty(&mp->m_list)) {
  		mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1545
  		if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
fe78fcc85   Eric W. Biederman   mnt: In detach_mo...
1546
  			umount_mnt(mnt);
56cbb429d   Al Viro   switch the remnan...
1547
  			hlist_add_head(&mnt->mnt_umount, &unmounted);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1548
  		}
e0c9c0afd   Eric W. Biederman   mnt: Update detac...
1549
  		else umount_tree(mnt, UMOUNT_CONNECTED);
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1550
  	}
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1551
1552
  	put_mountpoint(mp);
  out_unlock:
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1553
  	unlock_mount_hash();
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1554
1555
  	namespace_unlock();
  }
dd111b31e   David Howells   VFS: Clean up whi...
1556
  /*
9b40bc90a   Al Viro   get rid of unprot...
1557
1558
1559
1560
1561
1562
   * Is the caller allowed to modify his namespace?
   */
  static inline bool may_mount(void)
  {
  	return ns_capable(current->nsproxy->mnt_ns->user_ns, CAP_SYS_ADMIN);
  }
df2474a22   Jeff Layton   locks: print a wa...
1563
  #ifdef	CONFIG_MANDATORY_FILE_LOCKING
9e8925b67   Jeff Layton   locks: Allow disa...
1564
1565
  static inline bool may_mandlock(void)
  {
95ace7541   Eric W. Biederman   locks: Don't allo...
1566
  	return capable(CAP_SYS_ADMIN);
9e8925b67   Jeff Layton   locks: Allow disa...
1567
  }
df2474a22   Jeff Layton   locks: print a wa...
1568
1569
1570
1571
1572
1573
1574
  #else
  static inline bool may_mandlock(void)
  {
  	pr_warn("VFS: \"mand\" mount option not supported");
  	return false;
  }
  #endif
9e8925b67   Jeff Layton   locks: Allow disa...
1575

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
1577
1578
1579
1580
1581
1582
  /*
   * Now umount can handle mount points as well as block devices.
   * This is important for filesystems which use unnamed block devices.
   *
   * We now support a flag for forced unmount like the other 'big iron'
   * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
   */
3a18ef5c1   Dominik Brodowski   fs: add ksys_umou...
1583
  int ksys_umount(char __user *name, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1584
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
1585
  	struct path path;
900148dca   Al Viro   vfs: spread struc...
1586
  	struct mount *mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
  	int retval;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1588
  	int lookup_flags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589

db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1590
1591
  	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
  		return -EINVAL;
9b40bc90a   Al Viro   get rid of unprot...
1592
1593
  	if (!may_mount())
  		return -EPERM;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1594
1595
  	if (!(flags & UMOUNT_NOFOLLOW))
  		lookup_flags |= LOOKUP_FOLLOW;
197df04c7   Al Viro   rename user_path_...
1596
  	retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597
1598
  	if (retval)
  		goto out;
900148dca   Al Viro   vfs: spread struc...
1599
  	mnt = real_mount(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1600
  	retval = -EINVAL;
2d8f30380   Al Viro   [PATCH] sanitize ...
1601
  	if (path.dentry != path.mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
  		goto dput_and_out;
143c8c91c   Al Viro   vfs: mnt_ns moved...
1603
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604
  		goto dput_and_out;
25d202ed8   Eric W. Biederman   mount: Retest MNT...
1605
  	if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
1606
  		goto dput_and_out;
b2f5d4dc3   Eric W. Biederman   umount: Disallow ...
1607
1608
1609
  	retval = -EPERM;
  	if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
  		goto dput_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610

900148dca   Al Viro   vfs: spread struc...
1611
  	retval = do_umount(mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
  dput_and_out:
429731b15   Jan Blunck   Remove path_relea...
1613
  	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
2d8f30380   Al Viro   [PATCH] sanitize ...
1614
  	dput(path.dentry);
900148dca   Al Viro   vfs: spread struc...
1615
  	mntput_no_expire(mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1616
1617
1618
  out:
  	return retval;
  }
3a18ef5c1   Dominik Brodowski   fs: add ksys_umou...
1619
1620
1621
1622
  SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
  {
  	return ksys_umount(name, flags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1623
1624
1625
  #ifdef __ARCH_WANT_SYS_OLDUMOUNT
  
  /*
b58fed8b1   Ram Pai   [PATCH] lindent f...
1626
   *	The 2.0 compatible umount. No flags.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1627
   */
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
1628
  SYSCALL_DEFINE1(oldumount, char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
  {
3a18ef5c1   Dominik Brodowski   fs: add ksys_umou...
1630
  	return ksys_umount(name, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1631
1632
1633
  }
  
  #endif
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1634
  static bool is_mnt_ns_file(struct dentry *dentry)
8823c079b   Eric W. Biederman   vfs: Add setns su...
1635
  {
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1636
  	/* Is this a proxy for a mount namespace? */
e149ed2b8   Al Viro   take the targets ...
1637
1638
  	return dentry->d_op == &ns_dentry_operations &&
  	       dentry->d_fsdata == &mntns_operations;
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1639
  }
58be28256   Al Viro   make mntns ->get(...
1640
1641
1642
1643
  struct mnt_namespace *to_mnt_ns(struct ns_common *ns)
  {
  	return container_of(ns, struct mnt_namespace, ns);
  }
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1644
1645
1646
1647
1648
1649
1650
1651
  static bool mnt_ns_loop(struct dentry *dentry)
  {
  	/* Could bind mounting the mount namespace inode cause a
  	 * mount namespace loop?
  	 */
  	struct mnt_namespace *mnt_ns;
  	if (!is_mnt_ns_file(dentry))
  		return false;
f77c80142   Al Viro   bury struct proc_...
1652
  	mnt_ns = to_mnt_ns(get_proc_ns(dentry->d_inode));
8823c079b   Eric W. Biederman   vfs: Add setns su...
1653
1654
  	return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
  }
87129cc0e   Al Viro   vfs: spread struc...
1655
  struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
36341f645   Ram Pai   [PATCH] mount exp...
1656
  					int flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1657
  {
84d17192d   Al Viro   get rid of full-h...
1658
  	struct mount *res, *p, *q, *r, *parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1659

4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1660
1661
1662
1663
  	if (!(flag & CL_COPY_UNBINDABLE) && IS_MNT_UNBINDABLE(mnt))
  		return ERR_PTR(-EINVAL);
  
  	if (!(flag & CL_COPY_MNT_NS_FILE) && is_mnt_ns_file(dentry))
be34d1a3b   David Howells   VFS: Make clone_m...
1664
  		return ERR_PTR(-EINVAL);
9676f0c63   Ram Pai   [PATCH] unbindabl...
1665

36341f645   Ram Pai   [PATCH] mount exp...
1666
  	res = q = clone_mnt(mnt, dentry, flag);
be34d1a3b   David Howells   VFS: Make clone_m...
1667
1668
  	if (IS_ERR(q))
  		return q;
a73324da7   Al Viro   vfs: move mnt_mou...
1669
  	q->mnt_mountpoint = mnt->mnt_mountpoint;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
1671
  
  	p = mnt;
6b41d536f   Al Viro   vfs: take mnt_chi...
1672
  	list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
315fc83e5   Al Viro   vfs: spread struc...
1673
  		struct mount *s;
7ec02ef15   Jan Blunck   vfs: remove lives...
1674
  		if (!is_subdir(r->mnt_mountpoint, dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1675
  			continue;
909b0a88e   Al Viro   vfs: spread struc...
1676
  		for (s = r; s; s = next_mnt(s, r)) {
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1677
1678
  			if (!(flag & CL_COPY_UNBINDABLE) &&
  			    IS_MNT_UNBINDABLE(s)) {
df7342b24   Eric W. Biederman   mount: Don't allo...
1679
1680
1681
1682
1683
1684
1685
1686
  				if (s->mnt.mnt_flags & MNT_LOCKED) {
  					/* Both unbindable and locked. */
  					q = ERR_PTR(-EPERM);
  					goto out;
  				} else {
  					s = skip_mnt_tree(s);
  					continue;
  				}
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1687
1688
1689
  			}
  			if (!(flag & CL_COPY_MNT_NS_FILE) &&
  			    is_mnt_ns_file(s->mnt.mnt_root)) {
9676f0c63   Ram Pai   [PATCH] unbindabl...
1690
1691
1692
  				s = skip_mnt_tree(s);
  				continue;
  			}
0714a5338   Al Viro   vfs: now it can b...
1693
1694
1695
  			while (p != s->mnt_parent) {
  				p = p->mnt_parent;
  				q = q->mnt_parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1696
  			}
87129cc0e   Al Viro   vfs: spread struc...
1697
  			p = s;
84d17192d   Al Viro   get rid of full-h...
1698
  			parent = q;
87129cc0e   Al Viro   vfs: spread struc...
1699
  			q = clone_mnt(p, p->mnt.mnt_root, flag);
be34d1a3b   David Howells   VFS: Make clone_m...
1700
1701
  			if (IS_ERR(q))
  				goto out;
719ea2fbb   Al Viro   new helpers: lock...
1702
  			lock_mount_hash();
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1703
  			list_add_tail(&q->mnt_list, &res->mnt_list);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1704
  			attach_mnt(q, parent, p->mnt_mp);
719ea2fbb   Al Viro   new helpers: lock...
1705
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
1707
1708
  		}
  	}
  	return res;
be34d1a3b   David Howells   VFS: Make clone_m...
1709
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1710
  	if (res) {
719ea2fbb   Al Viro   new helpers: lock...
1711
  		lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
1712
  		umount_tree(res, UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
1713
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1714
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
1715
  	return q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1716
  }
be34d1a3b   David Howells   VFS: Make clone_m...
1717
  /* Caller should check returned pointer for errors */
ca71cf71e   Al Viro   namespace.c: cons...
1718
  struct vfsmount *collect_mounts(const struct path *path)
8aec08094   Al Viro   [PATCH] new helpe...
1719
  {
cb338d06e   Al Viro   vfs: spread struc...
1720
  	struct mount *tree;
97216be09   Al Viro   fold release_moun...
1721
  	namespace_lock();
cd4a40174   Eric W. Biederman   mnt: Fail collect...
1722
1723
1724
1725
1726
  	if (!check_mnt(real_mount(path->mnt)))
  		tree = ERR_PTR(-EINVAL);
  	else
  		tree = copy_tree(real_mount(path->mnt), path->dentry,
  				 CL_COPY_ALL | CL_PRIVATE);
328e6d901   Al Viro   switch unlock_mou...
1727
  	namespace_unlock();
be34d1a3b   David Howells   VFS: Make clone_m...
1728
  	if (IS_ERR(tree))
52e220d35   Dan Carpenter   VFS: collect_moun...
1729
  		return ERR_CAST(tree);
be34d1a3b   David Howells   VFS: Make clone_m...
1730
  	return &tree->mnt;
8aec08094   Al Viro   [PATCH] new helpe...
1731
  }
a07b20004   Al Viro   vfs: syscall: Add...
1732
1733
1734
1735
1736
1737
1738
1739
1740
  static void free_mnt_ns(struct mnt_namespace *);
  static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *, bool);
  
  void dissolve_on_fput(struct vfsmount *mnt)
  {
  	struct mnt_namespace *ns;
  	namespace_lock();
  	lock_mount_hash();
  	ns = real_mount(mnt)->mnt_ns;
44dfd84a6   David Howells   teach move_mount(...
1741
1742
1743
1744
1745
1746
  	if (ns) {
  		if (is_anon_ns(ns))
  			umount_tree(real_mount(mnt), UMOUNT_CONNECTED);
  		else
  			ns = NULL;
  	}
a07b20004   Al Viro   vfs: syscall: Add...
1747
1748
  	unlock_mount_hash();
  	namespace_unlock();
44dfd84a6   David Howells   teach move_mount(...
1749
1750
  	if (ns)
  		free_mnt_ns(ns);
a07b20004   Al Viro   vfs: syscall: Add...
1751
  }
8aec08094   Al Viro   [PATCH] new helpe...
1752
1753
  void drop_collected_mounts(struct vfsmount *mnt)
  {
97216be09   Al Viro   fold release_moun...
1754
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1755
  	lock_mount_hash();
9c8e0a1b6   Eric W. Biederman   mount: Prevent MN...
1756
  	umount_tree(real_mount(mnt), 0);
719ea2fbb   Al Viro   new helpers: lock...
1757
  	unlock_mount_hash();
3ab6abee5   Al Viro   more conversions ...
1758
  	namespace_unlock();
8aec08094   Al Viro   [PATCH] new helpe...
1759
  }
c771d683a   Miklos Szeredi   vfs: introduce cl...
1760
1761
1762
1763
1764
1765
1766
1767
1768
  /**
   * clone_private_mount - create a private clone of a path
   *
   * This creates a new vfsmount, which will be the clone of @path.  The new will
   * not be attached anywhere in the namespace and will be private (i.e. changes
   * to the originating mount won't be propagated into this).
   *
   * Release with mntput().
   */
ca71cf71e   Al Viro   namespace.c: cons...
1769
  struct vfsmount *clone_private_mount(const struct path *path)
c771d683a   Miklos Szeredi   vfs: introduce cl...
1770
1771
1772
1773
1774
1775
  {
  	struct mount *old_mnt = real_mount(path->mnt);
  	struct mount *new_mnt;
  
  	if (IS_MNT_UNBINDABLE(old_mnt))
  		return ERR_PTR(-EINVAL);
c771d683a   Miklos Szeredi   vfs: introduce cl...
1776
  	new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
c771d683a   Miklos Szeredi   vfs: introduce cl...
1777
1778
1779
1780
1781
1782
  	if (IS_ERR(new_mnt))
  		return ERR_CAST(new_mnt);
  
  	return &new_mnt->mnt;
  }
  EXPORT_SYMBOL_GPL(clone_private_mount);
1f707137b   Al Viro   new helper: itera...
1783
1784
1785
  int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
  		   struct vfsmount *root)
  {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1786
  	struct mount *mnt;
1f707137b   Al Viro   new helper: itera...
1787
1788
1789
  	int res = f(root, arg);
  	if (res)
  		return res;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1790
1791
  	list_for_each_entry(mnt, &real_mount(root)->mnt_list, mnt_list) {
  		res = f(&mnt->mnt, arg);
1f707137b   Al Viro   new helper: itera...
1792
1793
1794
1795
1796
  		if (res)
  			return res;
  	}
  	return 0;
  }
3bd045cc9   Al Viro   separate copying ...
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
  static void lock_mnt_tree(struct mount *mnt)
  {
  	struct mount *p;
  
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
  		int flags = p->mnt.mnt_flags;
  		/* Don't allow unprivileged users to change mount flags */
  		flags |= MNT_LOCK_ATIME;
  
  		if (flags & MNT_READONLY)
  			flags |= MNT_LOCK_READONLY;
  
  		if (flags & MNT_NODEV)
  			flags |= MNT_LOCK_NODEV;
  
  		if (flags & MNT_NOSUID)
  			flags |= MNT_LOCK_NOSUID;
  
  		if (flags & MNT_NOEXEC)
  			flags |= MNT_LOCK_NOEXEC;
  		/* Don't allow unprivileged users to reveal what is under a mount */
  		if (list_empty(&p->mnt_expire))
  			flags |= MNT_LOCKED;
  		p->mnt.mnt_flags = flags;
  	}
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1823
  static void cleanup_group_ids(struct mount *mnt, struct mount *end)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1824
  {
315fc83e5   Al Viro   vfs: spread struc...
1825
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1826

909b0a88e   Al Viro   vfs: spread struc...
1827
  	for (p = mnt; p != end; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
1828
  		if (p->mnt_group_id && !IS_MNT_SHARED(p))
4b8b21f4f   Al Viro   vfs: spread struc...
1829
  			mnt_release_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1830
1831
  	}
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1832
  static int invent_group_ids(struct mount *mnt, bool recurse)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1833
  {
315fc83e5   Al Viro   vfs: spread struc...
1834
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1835

909b0a88e   Al Viro   vfs: spread struc...
1836
  	for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) {
fc7be130c   Al Viro   vfs: switch pnode...
1837
  		if (!p->mnt_group_id && !IS_MNT_SHARED(p)) {
4b8b21f4f   Al Viro   vfs: spread struc...
1838
  			int err = mnt_alloc_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1839
  			if (err) {
4b8b21f4f   Al Viro   vfs: spread struc...
1840
  				cleanup_group_ids(mnt, p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1841
1842
1843
1844
1845
1846
1847
  				return err;
  			}
  		}
  	}
  
  	return 0;
  }
d29216842   Eric W. Biederman   mnt: Add a per mo...
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
  int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
  {
  	unsigned int max = READ_ONCE(sysctl_mount_max);
  	unsigned int mounts = 0, old, pending, sum;
  	struct mount *p;
  
  	for (p = mnt; p; p = next_mnt(p, mnt))
  		mounts++;
  
  	old = ns->mounts;
  	pending = ns->pending_mounts;
  	sum = old + pending;
  	if ((old > sum) ||
  	    (pending > sum) ||
  	    (max < sum) ||
  	    (mounts > (max - sum)))
  		return -ENOSPC;
  
  	ns->pending_mounts = pending + mounts;
  	return 0;
  }
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1869
1870
  /*
   *  @source_mnt : mount tree to be attached
214444032   Ram Pai   [PATCH] shared mo...
1871
1872
1873
1874
   *  @nd         : place the mount tree @source_mnt is attached
   *  @parent_nd  : if non-null, detach the source_mnt from its parent and
   *  		   store the parent mount and mountpoint dentry.
   *  		   (done when source_mnt is moved)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1875
1876
1877
   *
   *  NOTE: in the table below explains the semantics when a source mount
   *  of a given type is attached to a destination mount of a given type.
9676f0c63   Ram Pai   [PATCH] unbindabl...
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
   * ---------------------------------------------------------------------------
   * |         BIND MOUNT OPERATION                                            |
   * |**************************************************************************
   * | source-->| shared        |       private  |       slave    | unbindable |
   * | dest     |               |                |                |            |
   * |   |      |               |                |                |            |
   * |   v      |               |                |                |            |
   * |**************************************************************************
   * |  shared  | shared (++)   |     shared (+) |     shared(+++)|  invalid   |
   * |          |               |                |                |            |
   * |non-shared| shared (+)    |      private   |      slave (*) |  invalid   |
   * ***************************************************************************
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1890
1891
1892
1893
1894
1895
1896
1897
1898
   * A bind operation clones the source mount and mounts the clone on the
   * destination mount.
   *
   * (++)  the cloned mount is propagated to all the mounts in the propagation
   * 	 tree of the destination mount and the cloned mount is added to
   * 	 the peer group of the source mount.
   * (+)   the cloned mount is created under the destination mount and is marked
   *       as shared. The cloned mount is added to the peer group of the source
   *       mount.
5afe00221   Ram Pai   [PATCH] handling ...
1899
1900
1901
1902
1903
1904
1905
   * (+++) the mount is propagated to all the mounts in the propagation tree
   *       of the destination mount and the cloned mount is made slave
   *       of the same master as that of the source mount. The cloned mount
   *       is marked as 'shared and slave'.
   * (*)   the cloned mount is made a slave of the same master as that of the
   * 	 source mount.
   *
9676f0c63   Ram Pai   [PATCH] unbindabl...
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
   * ---------------------------------------------------------------------------
   * |         		MOVE MOUNT OPERATION                                 |
   * |**************************************************************************
   * | source-->| shared        |       private  |       slave    | unbindable |
   * | dest     |               |                |                |            |
   * |   |      |               |                |                |            |
   * |   v      |               |                |                |            |
   * |**************************************************************************
   * |  shared  | shared (+)    |     shared (+) |    shared(+++) |  invalid   |
   * |          |               |                |                |            |
   * |non-shared| shared (+*)   |      private   |    slave (*)   | unbindable |
   * ***************************************************************************
5afe00221   Ram Pai   [PATCH] handling ...
1918
1919
1920
   *
   * (+)  the mount is moved to the destination. And is then propagated to
   * 	all the mounts in the propagation tree of the destination mount.
214444032   Ram Pai   [PATCH] shared mo...
1921
   * (+*)  the mount is moved to the destination.
5afe00221   Ram Pai   [PATCH] handling ...
1922
1923
1924
1925
   * (+++)  the mount is moved to the destination and is then propagated to
   * 	all the mounts belonging to the destination mount's propagation tree.
   * 	the mount is marked as 'shared and slave'.
   * (*)	the mount continues to be a slave at the new location.
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1926
1927
1928
1929
1930
1931
   *
   * if the source mount is a tree, the operations explained above is
   * applied to each mount in the tree.
   * Must be called without spinlocks held, since this function can sleep
   * in allocations.
   */
0fb54e505   Al Viro   vfs: spread struc...
1932
  static int attach_recursive_mnt(struct mount *source_mnt,
84d17192d   Al Viro   get rid of full-h...
1933
1934
  			struct mount *dest_mnt,
  			struct mountpoint *dest_mp,
2763d1191   Al Viro   get rid of detach...
1935
  			bool moving)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1936
  {
3bd045cc9   Al Viro   separate copying ...
1937
  	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
38129a13e   Al Viro   switch mnt_hash t...
1938
  	HLIST_HEAD(tree_list);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1939
  	struct mnt_namespace *ns = dest_mnt->mnt_ns;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1940
  	struct mountpoint *smp;
315fc83e5   Al Viro   vfs: spread struc...
1941
  	struct mount *child, *p;
38129a13e   Al Viro   switch mnt_hash t...
1942
  	struct hlist_node *n;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1943
  	int err;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1944

1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1945
1946
1947
1948
1949
1950
  	/* Preallocate a mountpoint in case the new mounts need
  	 * to be tucked under other mounts.
  	 */
  	smp = get_mountpoint(source_mnt->mnt.mnt_root);
  	if (IS_ERR(smp))
  		return PTR_ERR(smp);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1951
  	/* Is there space to add these mounts to the mount namespace? */
2763d1191   Al Viro   get rid of detach...
1952
  	if (!moving) {
d29216842   Eric W. Biederman   mnt: Add a per mo...
1953
1954
1955
1956
  		err = count_mounts(ns, source_mnt);
  		if (err)
  			goto out;
  	}
fc7be130c   Al Viro   vfs: switch pnode...
1957
  	if (IS_MNT_SHARED(dest_mnt)) {
0fb54e505   Al Viro   vfs: spread struc...
1958
  		err = invent_group_ids(source_mnt, true);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1959
1960
  		if (err)
  			goto out;
0b1b901b5   Al Viro   don't bother with...
1961
  		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
f2ebb3a92   Al Viro   smarter propagate...
1962
  		lock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
1963
1964
  		if (err)
  			goto out_cleanup_ids;
909b0a88e   Al Viro   vfs: spread struc...
1965
  		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
0f0afb1dc   Al Viro   vfs: spread struc...
1966
  			set_mnt_shared(p);
0b1b901b5   Al Viro   don't bother with...
1967
1968
  	} else {
  		lock_mount_hash();
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1969
  	}
2763d1191   Al Viro   get rid of detach...
1970
1971
  	if (moving) {
  		unhash_mnt(source_mnt);
84d17192d   Al Viro   get rid of full-h...
1972
  		attach_mnt(source_mnt, dest_mnt, dest_mp);
143c8c91c   Al Viro   vfs: mnt_ns moved...
1973
  		touch_mnt_namespace(source_mnt->mnt_ns);
214444032   Ram Pai   [PATCH] shared mo...
1974
  	} else {
44dfd84a6   David Howells   teach move_mount(...
1975
1976
1977
1978
  		if (source_mnt->mnt_ns) {
  			/* move from anon - the caller will destroy */
  			list_del_init(&source_mnt->mnt_ns->list);
  		}
84d17192d   Al Viro   get rid of full-h...
1979
  		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1980
  		commit_tree(source_mnt);
214444032   Ram Pai   [PATCH] shared mo...
1981
  	}
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1982

38129a13e   Al Viro   switch mnt_hash t...
1983
  	hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
1d6a32acd   Al Viro   keep shadowed vfs...
1984
  		struct mount *q;
38129a13e   Al Viro   switch mnt_hash t...
1985
  		hlist_del_init(&child->mnt_hash);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1986
1987
1988
1989
  		q = __lookup_mnt(&child->mnt_parent->mnt,
  				 child->mnt_mountpoint);
  		if (q)
  			mnt_change_mountpoint(child, smp, q);
3bd045cc9   Al Viro   separate copying ...
1990
1991
1992
  		/* Notice when we are propagating across user namespaces */
  		if (child->mnt_parent->mnt_ns->user_ns != user_ns)
  			lock_mnt_tree(child);
d728cf791   Christian Brauner   fs/namespace: fix...
1993
  		child->mnt.mnt_flags &= ~MNT_LOCKED;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1994
  		commit_tree(child);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1995
  	}
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1996
  	put_mountpoint(smp);
719ea2fbb   Al Viro   new helpers: lock...
1997
  	unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1998

b90fa9ae8   Ram Pai   [PATCH] shared mo...
1999
  	return 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2000
2001
  
   out_cleanup_ids:
f2ebb3a92   Al Viro   smarter propagate...
2002
2003
  	while (!hlist_empty(&tree_list)) {
  		child = hlist_entry(tree_list.first, struct mount, mnt_hash);
d29216842   Eric W. Biederman   mnt: Add a per mo...
2004
  		child->mnt_parent->mnt_ns->pending_mounts = 0;
e819f1521   Eric W. Biederman   mnt: Improve the ...
2005
  		umount_tree(child, UMOUNT_SYNC);
f2ebb3a92   Al Viro   smarter propagate...
2006
2007
  	}
  	unlock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
2008
  	cleanup_group_ids(source_mnt, NULL);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2009
   out:
d29216842   Eric W. Biederman   mnt: Add a per mo...
2010
  	ns->pending_mounts = 0;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
2011
2012
2013
2014
  
  	read_seqlock_excl(&mount_lock);
  	put_mountpoint(smp);
  	read_sequnlock_excl(&mount_lock);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2015
  	return err;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
2016
  }
84d17192d   Al Viro   get rid of full-h...
2017
  static struct mountpoint *lock_mount(struct path *path)
b12cea919   Al Viro   change the lockin...
2018
2019
  {
  	struct vfsmount *mnt;
84d17192d   Al Viro   get rid of full-h...
2020
  	struct dentry *dentry = path->dentry;
b12cea919   Al Viro   change the lockin...
2021
  retry:
5955102c9   Al Viro   wrappers for ->i_...
2022
  	inode_lock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
2023
  	if (unlikely(cant_mount(dentry))) {
5955102c9   Al Viro   wrappers for ->i_...
2024
  		inode_unlock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
2025
  		return ERR_PTR(-ENOENT);
b12cea919   Al Viro   change the lockin...
2026
  	}
97216be09   Al Viro   fold release_moun...
2027
  	namespace_lock();
b12cea919   Al Viro   change the lockin...
2028
  	mnt = lookup_mnt(path);
84d17192d   Al Viro   get rid of full-h...
2029
  	if (likely(!mnt)) {
3895dbf89   Eric W. Biederman   mnt: Protect the ...
2030
  		struct mountpoint *mp = get_mountpoint(dentry);
84d17192d   Al Viro   get rid of full-h...
2031
  		if (IS_ERR(mp)) {
97216be09   Al Viro   fold release_moun...
2032
  			namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
2033
  			inode_unlock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
2034
2035
2036
2037
  			return mp;
  		}
  		return mp;
  	}
97216be09   Al Viro   fold release_moun...
2038
  	namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
2039
  	inode_unlock(path->dentry->d_inode);
b12cea919   Al Viro   change the lockin...
2040
2041
  	path_put(path);
  	path->mnt = mnt;
84d17192d   Al Viro   get rid of full-h...
2042
  	dentry = path->dentry = dget(mnt->mnt_root);
b12cea919   Al Viro   change the lockin...
2043
2044
  	goto retry;
  }
84d17192d   Al Viro   get rid of full-h...
2045
  static void unlock_mount(struct mountpoint *where)
b12cea919   Al Viro   change the lockin...
2046
  {
84d17192d   Al Viro   get rid of full-h...
2047
  	struct dentry *dentry = where->m_dentry;
3895dbf89   Eric W. Biederman   mnt: Protect the ...
2048
2049
  
  	read_seqlock_excl(&mount_lock);
84d17192d   Al Viro   get rid of full-h...
2050
  	put_mountpoint(where);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
2051
  	read_sequnlock_excl(&mount_lock);
328e6d901   Al Viro   switch unlock_mou...
2052
  	namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
2053
  	inode_unlock(dentry->d_inode);
b12cea919   Al Viro   change the lockin...
2054
  }
84d17192d   Al Viro   get rid of full-h...
2055
  static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2056
  {
e462ec50c   David Howells   VFS: Differentiat...
2057
  	if (mnt->mnt.mnt_sb->s_flags & SB_NOUSER)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
  		return -EINVAL;
e36cb0b89   David Howells   VFS: (Scripted) C...
2059
2060
  	if (d_is_dir(mp->m_dentry) !=
  	      d_is_dir(mnt->mnt.mnt_root))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2061
  		return -ENOTDIR;
2763d1191   Al Viro   get rid of detach...
2062
  	return attach_recursive_mnt(mnt, p, mp, false);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2063
2064
2065
  }
  
  /*
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2066
2067
   * Sanity check the flags to change_mnt_propagation.
   */
e462ec50c   David Howells   VFS: Differentiat...
2068
  static int flags_to_propagation_type(int ms_flags)
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2069
  {
e462ec50c   David Howells   VFS: Differentiat...
2070
  	int type = ms_flags & ~(MS_REC | MS_SILENT);
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
  
  	/* Fail if any non-propagation flags are set */
  	if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
  		return 0;
  	/* Only one propagation flag should be set */
  	if (!is_power_of_2(type))
  		return 0;
  	return type;
  }
  
  /*
07b20889e   Ram Pai   [PATCH] beginning...
2082
2083
   * recursively change the type of the mountpoint.
   */
e462ec50c   David Howells   VFS: Differentiat...
2084
  static int do_change_type(struct path *path, int ms_flags)
07b20889e   Ram Pai   [PATCH] beginning...
2085
  {
315fc83e5   Al Viro   vfs: spread struc...
2086
  	struct mount *m;
4b8b21f4f   Al Viro   vfs: spread struc...
2087
  	struct mount *mnt = real_mount(path->mnt);
e462ec50c   David Howells   VFS: Differentiat...
2088
  	int recurse = ms_flags & MS_REC;
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2089
  	int type;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2090
  	int err = 0;
07b20889e   Ram Pai   [PATCH] beginning...
2091

2d92ab3c6   Al Viro   [PATCH] finally g...
2092
  	if (path->dentry != path->mnt->mnt_root)
07b20889e   Ram Pai   [PATCH] beginning...
2093
  		return -EINVAL;
e462ec50c   David Howells   VFS: Differentiat...
2094
  	type = flags_to_propagation_type(ms_flags);
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2095
2096
  	if (!type)
  		return -EINVAL;
97216be09   Al Viro   fold release_moun...
2097
  	namespace_lock();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2098
2099
2100
2101
2102
  	if (type == MS_SHARED) {
  		err = invent_group_ids(mnt, recurse);
  		if (err)
  			goto out_unlock;
  	}
719ea2fbb   Al Viro   new helpers: lock...
2103
  	lock_mount_hash();
909b0a88e   Al Viro   vfs: spread struc...
2104
  	for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
0f0afb1dc   Al Viro   vfs: spread struc...
2105
  		change_mnt_propagation(m, type);
719ea2fbb   Al Viro   new helpers: lock...
2106
  	unlock_mount_hash();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2107
2108
  
   out_unlock:
97216be09   Al Viro   fold release_moun...
2109
  	namespace_unlock();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2110
  	return err;
07b20889e   Ram Pai   [PATCH] beginning...
2111
  }
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
  static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
  {
  	struct mount *child;
  	list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
  		if (!is_subdir(child->mnt_mountpoint, dentry))
  			continue;
  
  		if (child->mnt.mnt_flags & MNT_LOCKED)
  			return true;
  	}
  	return false;
  }
a07b20004   Al Viro   vfs: syscall: Add...
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
  static struct mount *__do_loopback(struct path *old_path, int recurse)
  {
  	struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt);
  
  	if (IS_MNT_UNBINDABLE(old))
  		return mnt;
  
  	if (!check_mnt(old) && old_path->dentry->d_op != &ns_dentry_operations)
  		return mnt;
  
  	if (!recurse && has_locked_children(old, old_path->dentry))
  		return mnt;
  
  	if (recurse)
  		mnt = copy_tree(old, old_path->dentry, CL_COPY_MNT_NS_FILE);
  	else
  		mnt = clone_mnt(old, old_path->dentry, 0);
  
  	if (!IS_ERR(mnt))
  		mnt->mnt.mnt_flags &= ~MNT_LOCKED;
  
  	return mnt;
  }
07b20889e   Ram Pai   [PATCH] beginning...
2147
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2148
2149
   * do loopback mount.
   */
808d4e3cf   Al Viro   consitify do_moun...
2150
  static int do_loopback(struct path *path, const char *old_name,
2dafe1c4d   Eric Sandeen   reduce large do_m...
2151
  				int recurse)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2152
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2153
  	struct path old_path;
a07b20004   Al Viro   vfs: syscall: Add...
2154
  	struct mount *mnt = NULL, *parent;
84d17192d   Al Viro   get rid of full-h...
2155
  	struct mountpoint *mp;
57eccb830   Al Viro   mount: consolidat...
2156
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2157
2158
  	if (!old_name || !*old_name)
  		return -EINVAL;
815d405ce   Trond Myklebust   VFS: Fix the rema...
2159
  	err = kern_path(old_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2160
2161
  	if (err)
  		return err;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2162
  	err = -EINVAL;
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2163
  	if (mnt_ns_loop(old_path.dentry))
dd111b31e   David Howells   VFS: Clean up whi...
2164
  		goto out;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2165

84d17192d   Al Viro   get rid of full-h...
2166
  	mp = lock_mount(path);
a07b20004   Al Viro   vfs: syscall: Add...
2167
2168
  	if (IS_ERR(mp)) {
  		err = PTR_ERR(mp);
b12cea919   Al Viro   change the lockin...
2169
  		goto out;
a07b20004   Al Viro   vfs: syscall: Add...
2170
  	}
b12cea919   Al Viro   change the lockin...
2171

84d17192d   Al Viro   get rid of full-h...
2172
  	parent = real_mount(path->mnt);
e149ed2b8   Al Viro   take the targets ...
2173
2174
  	if (!check_mnt(parent))
  		goto out2;
a07b20004   Al Viro   vfs: syscall: Add...
2175
  	mnt = __do_loopback(&old_path, recurse);
be34d1a3b   David Howells   VFS: Make clone_m...
2176
2177
  	if (IS_ERR(mnt)) {
  		err = PTR_ERR(mnt);
e9c5d8a56   Andrey Vagin   mnt: release lock...
2178
  		goto out2;
be34d1a3b   David Howells   VFS: Make clone_m...
2179
  	}
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2180

84d17192d   Al Viro   get rid of full-h...
2181
  	err = graft_tree(mnt, parent, mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2182
  	if (err) {
719ea2fbb   Al Viro   new helpers: lock...
2183
  		lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
2184
  		umount_tree(mnt, UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
2185
  		unlock_mount_hash();
5b83d2c5c   Ram Pai   [PATCH] sanitize ...
2186
  	}
b12cea919   Al Viro   change the lockin...
2187
  out2:
84d17192d   Al Viro   get rid of full-h...
2188
  	unlock_mount(mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2189
  out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2190
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
2192
  	return err;
  }
a07b20004   Al Viro   vfs: syscall: Add...
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
  static struct file *open_detached_copy(struct path *path, bool recursive)
  {
  	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
  	struct mnt_namespace *ns = alloc_mnt_ns(user_ns, true);
  	struct mount *mnt, *p;
  	struct file *file;
  
  	if (IS_ERR(ns))
  		return ERR_CAST(ns);
  
  	namespace_lock();
  	mnt = __do_loopback(path, recursive);
  	if (IS_ERR(mnt)) {
  		namespace_unlock();
  		free_mnt_ns(ns);
  		return ERR_CAST(mnt);
  	}
  
  	lock_mount_hash();
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
  		p->mnt_ns = ns;
  		ns->mounts++;
  	}
  	ns->root = mnt;
  	list_add_tail(&ns->list, &mnt->mnt_list);
  	mntget(&mnt->mnt);
  	unlock_mount_hash();
  	namespace_unlock();
  
  	mntput(path->mnt);
  	path->mnt = &mnt->mnt;
  	file = dentry_open(path, O_PATH, current_cred());
  	if (IS_ERR(file))
  		dissolve_on_fput(path->mnt);
  	else
  		file->f_mode |= FMODE_NEED_UNMOUNT;
  	return file;
  }
  
  SYSCALL_DEFINE3(open_tree, int, dfd, const char *, filename, unsigned, flags)
  {
  	struct file *file;
  	struct path path;
  	int lookup_flags = LOOKUP_AUTOMOUNT | LOOKUP_FOLLOW;
  	bool detached = flags & OPEN_TREE_CLONE;
  	int error;
  	int fd;
  
  	BUILD_BUG_ON(OPEN_TREE_CLOEXEC != O_CLOEXEC);
  
  	if (flags & ~(AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_RECURSIVE |
  		      AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLONE |
  		      OPEN_TREE_CLOEXEC))
  		return -EINVAL;
  
  	if ((flags & (AT_RECURSIVE | OPEN_TREE_CLONE)) == AT_RECURSIVE)
  		return -EINVAL;
  
  	if (flags & AT_NO_AUTOMOUNT)
  		lookup_flags &= ~LOOKUP_AUTOMOUNT;
  	if (flags & AT_SYMLINK_NOFOLLOW)
  		lookup_flags &= ~LOOKUP_FOLLOW;
  	if (flags & AT_EMPTY_PATH)
  		lookup_flags |= LOOKUP_EMPTY;
  
  	if (detached && !may_mount())
  		return -EPERM;
  
  	fd = get_unused_fd_flags(flags & O_CLOEXEC);
  	if (fd < 0)
  		return fd;
  
  	error = user_path_at(dfd, filename, lookup_flags, &path);
  	if (unlikely(error)) {
  		file = ERR_PTR(error);
  	} else {
  		if (detached)
  			file = open_detached_copy(&path, flags & AT_RECURSIVE);
  		else
  			file = dentry_open(&path, O_PATH, current_cred());
  		path_put(&path);
  	}
  	if (IS_ERR(file)) {
  		put_unused_fd(fd);
  		return PTR_ERR(file);
  	}
  	fd_install(fd, file);
  	return fd;
  }
43f5e655e   David Howells   vfs: Separate cha...
2282
2283
2284
2285
2286
2287
2288
  /*
   * Don't allow locked mount flags to be cleared.
   *
   * No locks need to be held here while testing the various MNT_LOCK
   * flags because those flags can never be cleared once they are set.
   */
  static bool can_change_locked_flags(struct mount *mnt, unsigned int mnt_flags)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2289
  {
43f5e655e   David Howells   vfs: Separate cha...
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
  	unsigned int fl = mnt->mnt.mnt_flags;
  
  	if ((fl & MNT_LOCK_READONLY) &&
  	    !(mnt_flags & MNT_READONLY))
  		return false;
  
  	if ((fl & MNT_LOCK_NODEV) &&
  	    !(mnt_flags & MNT_NODEV))
  		return false;
  
  	if ((fl & MNT_LOCK_NOSUID) &&
  	    !(mnt_flags & MNT_NOSUID))
  		return false;
  
  	if ((fl & MNT_LOCK_NOEXEC) &&
  	    !(mnt_flags & MNT_NOEXEC))
  		return false;
  
  	if ((fl & MNT_LOCK_ATIME) &&
  	    ((fl & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK)))
  		return false;
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2311

43f5e655e   David Howells   vfs: Separate cha...
2312
2313
2314
2315
  	return true;
  }
  
  static int change_mount_ro_state(struct mount *mnt, unsigned int mnt_flags)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2316
  {
43f5e655e   David Howells   vfs: Separate cha...
2317
  	bool readonly_request = (mnt_flags & MNT_READONLY);
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2318

43f5e655e   David Howells   vfs: Separate cha...
2319
  	if (readonly_request == __mnt_is_readonly(&mnt->mnt))
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2320
2321
2322
  		return 0;
  
  	if (readonly_request)
43f5e655e   David Howells   vfs: Separate cha...
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
  		return mnt_make_readonly(mnt);
  
  	return __mnt_unmake_readonly(mnt);
  }
  
  /*
   * Update the user-settable attributes on a mount.  The caller must hold
   * sb->s_umount for writing.
   */
  static void set_mount_attributes(struct mount *mnt, unsigned int mnt_flags)
  {
  	lock_mount_hash();
  	mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
  	mnt->mnt.mnt_flags = mnt_flags;
  	touch_mnt_namespace(mnt->mnt_ns);
  	unlock_mount_hash();
  }
f8b92ba67   Deepa Dinamani   mount: Add mount ...
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
  static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount *mnt)
  {
  	struct super_block *sb = mnt->mnt_sb;
  
  	if (!__mnt_is_readonly(mnt) &&
  	   (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) {
  		char *buf = (char *)__get_free_page(GFP_KERNEL);
  		char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM);
  		struct tm tm;
  
  		time64_to_tm(sb->s_time_max, 0, &tm);
0ecee6699   Eric Biggers   fs/namespace.c: f...
2351
2352
2353
2354
2355
  		pr_warn("%s filesystem being %s at %s supports timestamps until %04ld (0x%llx)
  ",
  			sb->s_type->name,
  			is_mounted(mnt) ? "remounted" : "mounted",
  			mntpath,
f8b92ba67   Deepa Dinamani   mount: Add mount ...
2356
2357
2358
2359
2360
  			tm.tm_year+1900, (unsigned long long)sb->s_time_max);
  
  		free_page((unsigned long)buf);
  	}
  }
43f5e655e   David Howells   vfs: Separate cha...
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
  /*
   * Handle reconfiguration of the mountpoint only without alteration of the
   * superblock it refers to.  This is triggered by specifying MS_REMOUNT|MS_BIND
   * to mount(2).
   */
  static int do_reconfigure_mnt(struct path *path, unsigned int mnt_flags)
  {
  	struct super_block *sb = path->mnt->mnt_sb;
  	struct mount *mnt = real_mount(path->mnt);
  	int ret;
  
  	if (!check_mnt(mnt))
  		return -EINVAL;
  
  	if (path->dentry != mnt->mnt.mnt_root)
  		return -EINVAL;
  
  	if (!can_change_locked_flags(mnt, mnt_flags))
  		return -EPERM;
  
  	down_write(&sb->s_umount);
  	ret = change_mount_ro_state(mnt, mnt_flags);
  	if (ret == 0)
  		set_mount_attributes(mnt, mnt_flags);
  	up_write(&sb->s_umount);
f8b92ba67   Deepa Dinamani   mount: Add mount ...
2386
2387
  
  	mnt_warn_timestamp_expiry(path, &mnt->mnt);
43f5e655e   David Howells   vfs: Separate cha...
2388
  	return ret;
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2389
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2390
2391
2392
2393
2394
  /*
   * change filesystem flags. dir should be a physical root of filesystem.
   * If you've mounted a non-root directory somewhere and want to do remount
   * on it - tough luck.
   */
e462ec50c   David Howells   VFS: Differentiat...
2395
2396
  static int do_remount(struct path *path, int ms_flags, int sb_flags,
  		      int mnt_flags, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2397
2398
  {
  	int err;
2d92ab3c6   Al Viro   [PATCH] finally g...
2399
  	struct super_block *sb = path->mnt->mnt_sb;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2400
  	struct mount *mnt = real_mount(path->mnt);
8d0347f6c   David Howells   convert do_remoun...
2401
  	struct fs_context *fc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2402

143c8c91c   Al Viro   vfs: mnt_ns moved...
2403
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2404
  		return -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2405
  	if (path->dentry != path->mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2406
  		return -EINVAL;
43f5e655e   David Howells   vfs: Separate cha...
2407
  	if (!can_change_locked_flags(mnt, mnt_flags))
9566d6742   Eric W. Biederman   mnt: Correct perm...
2408
  		return -EPERM;
9566d6742   Eric W. Biederman   mnt: Correct perm...
2409

8d0347f6c   David Howells   convert do_remoun...
2410
2411
2412
  	fc = fs_context_for_reconfigure(path->dentry, sb_flags, MS_RMT_MASK);
  	if (IS_ERR(fc))
  		return PTR_ERR(fc);
ff36fe2c8   Eric Paris   LSM: Pass -o remo...
2413

8d0347f6c   David Howells   convert do_remoun...
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
  	err = parse_monolithic_mount_data(fc, data);
  	if (!err) {
  		down_write(&sb->s_umount);
  		err = -EPERM;
  		if (ns_capable(sb->s_user_ns, CAP_SYS_ADMIN)) {
  			err = reconfigure_super(fc);
  			if (!err)
  				set_mount_attributes(mnt, mnt_flags);
  		}
  		up_write(&sb->s_umount);
0e55a7cca   Dan Williams   [RFC PATCH] touch...
2424
  	}
f8b92ba67   Deepa Dinamani   mount: Add mount ...
2425
2426
  
  	mnt_warn_timestamp_expiry(path, &mnt->mnt);
8d0347f6c   David Howells   convert do_remoun...
2427
  	put_fs_context(fc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2428
2429
  	return err;
  }
cbbe362cd   Al Viro   vfs: spread struc...
2430
  static inline int tree_contains_unbindable(struct mount *mnt)
9676f0c63   Ram Pai   [PATCH] unbindabl...
2431
  {
315fc83e5   Al Viro   vfs: spread struc...
2432
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
2433
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
2434
  		if (IS_MNT_UNBINDABLE(p))
9676f0c63   Ram Pai   [PATCH] unbindabl...
2435
2436
2437
2438
  			return 1;
  	}
  	return 0;
  }
44dfd84a6   David Howells   teach move_mount(...
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
  /*
   * Check that there aren't references to earlier/same mount namespaces in the
   * specified subtree.  Such references can act as pins for mount namespaces
   * that aren't checked by the mount-cycle checking code, thereby allowing
   * cycles to be made.
   */
  static bool check_for_nsfs_mounts(struct mount *subtree)
  {
  	struct mount *p;
  	bool ret = false;
  
  	lock_mount_hash();
  	for (p = subtree; p; p = next_mnt(p, subtree))
  		if (mnt_ns_loop(p->mnt.mnt_root))
  			goto out;
  
  	ret = true;
  out:
  	unlock_mount_hash();
  	return ret;
  }
2db154b3e   David Howells   vfs: syscall: Add...
2460
  static int do_move_mount(struct path *old_path, struct path *new_path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2461
  {
44dfd84a6   David Howells   teach move_mount(...
2462
  	struct mnt_namespace *ns;
676da58df   Al Viro   vfs: spread struc...
2463
  	struct mount *p;
0fb54e505   Al Viro   vfs: spread struc...
2464
  	struct mount *old;
2763d1191   Al Viro   get rid of detach...
2465
2466
  	struct mount *parent;
  	struct mountpoint *mp, *old_mp;
57eccb830   Al Viro   mount: consolidat...
2467
  	int err;
44dfd84a6   David Howells   teach move_mount(...
2468
  	bool attached;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2469

2db154b3e   David Howells   vfs: syscall: Add...
2470
  	mp = lock_mount(new_path);
84d17192d   Al Viro   get rid of full-h...
2471
  	if (IS_ERR(mp))
2db154b3e   David Howells   vfs: syscall: Add...
2472
  		return PTR_ERR(mp);
cc53ce53c   David Howells   Add a dentry op t...
2473

2db154b3e   David Howells   vfs: syscall: Add...
2474
2475
  	old = real_mount(old_path->mnt);
  	p = real_mount(new_path->mnt);
2763d1191   Al Viro   get rid of detach...
2476
  	parent = old->mnt_parent;
44dfd84a6   David Howells   teach move_mount(...
2477
  	attached = mnt_has_parent(old);
2763d1191   Al Viro   get rid of detach...
2478
  	old_mp = old->mnt_mp;
44dfd84a6   David Howells   teach move_mount(...
2479
  	ns = old->mnt_ns;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2480

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2481
  	err = -EINVAL;
44dfd84a6   David Howells   teach move_mount(...
2482
2483
  	/* The mountpoint must be in our namespace. */
  	if (!check_mnt(p))
2db154b3e   David Howells   vfs: syscall: Add...
2484
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2485

570d7a98e   Eric Biggers   vfs: move_mount: ...
2486
2487
  	/* The thing moved must be mounted... */
  	if (!is_mounted(&old->mnt))
44dfd84a6   David Howells   teach move_mount(...
2488
  		goto out;
570d7a98e   Eric Biggers   vfs: move_mount: ...
2489
2490
  	/* ... and either ours or the root of anon namespace */
  	if (!(attached ? check_mnt(old) : is_anon_ns(ns)))
2db154b3e   David Howells   vfs: syscall: Add...
2491
  		goto out;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2492

2db154b3e   David Howells   vfs: syscall: Add...
2493
2494
  	if (old->mnt.mnt_flags & MNT_LOCKED)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2495

2db154b3e   David Howells   vfs: syscall: Add...
2496
2497
  	if (old_path->dentry != old_path->mnt->mnt_root)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2498

2db154b3e   David Howells   vfs: syscall: Add...
2499
2500
2501
  	if (d_is_dir(new_path->dentry) !=
  	    d_is_dir(old_path->dentry))
  		goto out;
214444032   Ram Pai   [PATCH] shared mo...
2502
2503
2504
  	/*
  	 * Don't move a mount residing in a shared parent.
  	 */
2763d1191   Al Viro   get rid of detach...
2505
  	if (attached && IS_MNT_SHARED(parent))
2db154b3e   David Howells   vfs: syscall: Add...
2506
  		goto out;
9676f0c63   Ram Pai   [PATCH] unbindabl...
2507
2508
2509
2510
  	/*
  	 * Don't move a mount tree containing unbindable mounts to a destination
  	 * mount which is shared.
  	 */
fc7be130c   Al Viro   vfs: switch pnode...
2511
  	if (IS_MNT_SHARED(p) && tree_contains_unbindable(old))
2db154b3e   David Howells   vfs: syscall: Add...
2512
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2513
  	err = -ELOOP;
44dfd84a6   David Howells   teach move_mount(...
2514
2515
  	if (!check_for_nsfs_mounts(old))
  		goto out;
fc7be130c   Al Viro   vfs: switch pnode...
2516
  	for (; mnt_has_parent(p); p = p->mnt_parent)
676da58df   Al Viro   vfs: spread struc...
2517
  		if (p == old)
2db154b3e   David Howells   vfs: syscall: Add...
2518
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2519

2db154b3e   David Howells   vfs: syscall: Add...
2520
  	err = attach_recursive_mnt(old, real_mount(new_path->mnt), mp,
2763d1191   Al Viro   get rid of detach...
2521
  				   attached);
4ac913785   Jan Blunck   Embed a struct pa...
2522
  	if (err)
2db154b3e   David Howells   vfs: syscall: Add...
2523
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2524
2525
2526
  
  	/* if the mount is moved, it should no longer be expire
  	 * automatically */
6776db3d3   Al Viro   vfs: take mnt_sha...
2527
  	list_del_init(&old->mnt_expire);
2763d1191   Al Viro   get rid of detach...
2528
2529
  	if (attached)
  		put_mountpoint(old_mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2530
  out:
2db154b3e   David Howells   vfs: syscall: Add...
2531
  	unlock_mount(mp);
44dfd84a6   David Howells   teach move_mount(...
2532
  	if (!err) {
2763d1191   Al Viro   get rid of detach...
2533
2534
2535
  		if (attached)
  			mntput_no_expire(parent);
  		else
44dfd84a6   David Howells   teach move_mount(...
2536
2537
  			free_mnt_ns(ns);
  	}
2db154b3e   David Howells   vfs: syscall: Add...
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
  	return err;
  }
  
  static int do_move_mount_old(struct path *path, const char *old_name)
  {
  	struct path old_path;
  	int err;
  
  	if (!old_name || !*old_name)
  		return -EINVAL;
  
  	err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
  	if (err)
  		return err;
  
  	err = do_move_mount(&old_path, path);
2d92ab3c6   Al Viro   [PATCH] finally g...
2554
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2555
2556
  	return err;
  }
9d412a43c   Al Viro   vfs: split off vf...
2557
2558
2559
  /*
   * add a mount into a namespace's mount tree
   */
95bc5f25c   Al Viro   vfs: spread struc...
2560
  static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
9d412a43c   Al Viro   vfs: split off vf...
2561
  {
84d17192d   Al Viro   get rid of full-h...
2562
2563
  	struct mountpoint *mp;
  	struct mount *parent;
9d412a43c   Al Viro   vfs: split off vf...
2564
  	int err;
f2ebb3a92   Al Viro   smarter propagate...
2565
  	mnt_flags &= ~MNT_INTERNAL_FLAGS;
9d412a43c   Al Viro   vfs: split off vf...
2566

84d17192d   Al Viro   get rid of full-h...
2567
2568
2569
  	mp = lock_mount(path);
  	if (IS_ERR(mp))
  		return PTR_ERR(mp);
9d412a43c   Al Viro   vfs: split off vf...
2570

84d17192d   Al Viro   get rid of full-h...
2571
  	parent = real_mount(path->mnt);
9d412a43c   Al Viro   vfs: split off vf...
2572
  	err = -EINVAL;
84d17192d   Al Viro   get rid of full-h...
2573
  	if (unlikely(!check_mnt(parent))) {
156cacb1d   Al Viro   do_add_mount()/um...
2574
2575
2576
2577
  		/* that's acceptable only for automounts done in private ns */
  		if (!(mnt_flags & MNT_SHRINKABLE))
  			goto unlock;
  		/* ... and for those we'd better have mountpoint still alive */
84d17192d   Al Viro   get rid of full-h...
2578
  		if (!parent->mnt_ns)
156cacb1d   Al Viro   do_add_mount()/um...
2579
2580
  			goto unlock;
  	}
9d412a43c   Al Viro   vfs: split off vf...
2581
2582
2583
  
  	/* Refuse the same filesystem on the same mount point */
  	err = -EBUSY;
95bc5f25c   Al Viro   vfs: spread struc...
2584
  	if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
9d412a43c   Al Viro   vfs: split off vf...
2585
2586
2587
2588
  	    path->mnt->mnt_root == path->dentry)
  		goto unlock;
  
  	err = -EINVAL;
e36cb0b89   David Howells   VFS: (Scripted) C...
2589
  	if (d_is_symlink(newmnt->mnt.mnt_root))
9d412a43c   Al Viro   vfs: split off vf...
2590
  		goto unlock;
95bc5f25c   Al Viro   vfs: spread struc...
2591
  	newmnt->mnt.mnt_flags = mnt_flags;
84d17192d   Al Viro   get rid of full-h...
2592
  	err = graft_tree(newmnt, parent, mp);
9d412a43c   Al Viro   vfs: split off vf...
2593
2594
  
  unlock:
84d17192d   Al Viro   get rid of full-h...
2595
  	unlock_mount(mp);
9d412a43c   Al Viro   vfs: split off vf...
2596
2597
  	return err;
  }
b1e75df45   Al Viro   tidy up around fi...
2598

132e46084   David Howells   new helper: do_ne...
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
  static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags);
  
  /*
   * Create a new mount using a superblock configuration and request it
   * be added to the namespace tree.
   */
  static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
  			   unsigned int mnt_flags)
  {
  	struct vfsmount *mnt;
  	struct super_block *sb = fc->root->d_sb;
  	int error;
c9ce29ed7   Al Viro   vfs_get_tree(): e...
2611
2612
2613
2614
2615
2616
2617
  	error = security_sb_kern_mount(sb);
  	if (!error && mount_too_revealing(sb, &mnt_flags))
  		error = -EPERM;
  
  	if (unlikely(error)) {
  		fc_drop_locked(fc);
  		return error;
132e46084   David Howells   new helper: do_ne...
2618
2619
2620
2621
2622
2623
2624
  	}
  
  	up_write(&sb->s_umount);
  
  	mnt = vfs_create_mount(fc);
  	if (IS_ERR(mnt))
  		return PTR_ERR(mnt);
f8b92ba67   Deepa Dinamani   mount: Add mount ...
2625
  	mnt_warn_timestamp_expiry(mountpoint, mnt);
0ecee6699   Eric Biggers   fs/namespace.c: f...
2626
2627
2628
  	error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags);
  	if (error < 0)
  		mntput(mnt);
132e46084   David Howells   new helper: do_ne...
2629
2630
  	return error;
  }
1b852bceb   Eric W. Biederman   mnt: Refactor the...
2631

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2632
2633
2634
2635
  /*
   * create a new mount for userspace and request it to be added into the
   * namespace's tree
   */
e462ec50c   David Howells   VFS: Differentiat...
2636
  static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
808d4e3cf   Al Viro   consitify do_moun...
2637
  			int mnt_flags, const char *name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2638
  {
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2639
  	struct file_system_type *type;
a0c9a8b8f   Al Viro   teach vfs_get_tre...
2640
2641
2642
  	struct fs_context *fc;
  	const char *subtype = NULL;
  	int err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2643

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2644
  	if (!fstype)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2645
  		return -EINVAL;
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2646
2647
2648
  	type = get_fs_type(fstype);
  	if (!type)
  		return -ENODEV;
a0c9a8b8f   Al Viro   teach vfs_get_tre...
2649
2650
2651
2652
2653
2654
2655
2656
  	if (type->fs_flags & FS_HAS_SUBTYPE) {
  		subtype = strchr(fstype, '.');
  		if (subtype) {
  			subtype++;
  			if (!*subtype) {
  				put_filesystem(type);
  				return -EINVAL;
  			}
a0c9a8b8f   Al Viro   teach vfs_get_tre...
2657
2658
  		}
  	}
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2659

a0c9a8b8f   Al Viro   teach vfs_get_tre...
2660
  	fc = fs_context_for_mount(type, sb_flags);
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2661
  	put_filesystem(type);
a0c9a8b8f   Al Viro   teach vfs_get_tre...
2662
2663
  	if (IS_ERR(fc))
  		return PTR_ERR(fc);
3e1aeb00e   David Howells   vfs: Implement a ...
2664
2665
2666
2667
2668
  	if (subtype)
  		err = vfs_parse_fs_string(fc, "subtype",
  					  subtype, strlen(subtype));
  	if (!err && name)
  		err = vfs_parse_fs_string(fc, "source", name, strlen(name));
a0c9a8b8f   Al Viro   teach vfs_get_tre...
2669
2670
  	if (!err)
  		err = parse_monolithic_mount_data(fc, data);
c3aabf078   Al Viro   move mount_capabl...
2671
2672
  	if (!err && !mount_capable(fc))
  		err = -EPERM;
a0c9a8b8f   Al Viro   teach vfs_get_tre...
2673
2674
  	if (!err)
  		err = vfs_get_tree(fc);
132e46084   David Howells   new helper: do_ne...
2675
2676
  	if (!err)
  		err = do_new_mount_fc(fc, path, mnt_flags);
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
2677

a0c9a8b8f   Al Viro   teach vfs_get_tre...
2678
  	put_fs_context(fc);
15f9a3f3e   Al Viro   don't drop newmnt...
2679
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2680
  }
19a167af7   Al Viro   Take the completi...
2681
2682
  int finish_automount(struct vfsmount *m, struct path *path)
  {
6776db3d3   Al Viro   vfs: take mnt_sha...
2683
  	struct mount *mnt = real_mount(m);
19a167af7   Al Viro   Take the completi...
2684
2685
2686
2687
  	int err;
  	/* The new mount record should have at least 2 refs to prevent it being
  	 * expired before we get a chance to add it
  	 */
6776db3d3   Al Viro   vfs: take mnt_sha...
2688
  	BUG_ON(mnt_get_count(mnt) < 2);
19a167af7   Al Viro   Take the completi...
2689
2690
2691
  
  	if (m->mnt_sb == path->mnt->mnt_sb &&
  	    m->mnt_root == path->dentry) {
b1e75df45   Al Viro   tidy up around fi...
2692
2693
  		err = -ELOOP;
  		goto fail;
19a167af7   Al Viro   Take the completi...
2694
  	}
95bc5f25c   Al Viro   vfs: spread struc...
2695
  	err = do_add_mount(mnt, path, path->mnt->mnt_flags | MNT_SHRINKABLE);
b1e75df45   Al Viro   tidy up around fi...
2696
2697
2698
2699
  	if (!err)
  		return 0;
  fail:
  	/* remove m from any expiration list it may be on */
6776db3d3   Al Viro   vfs: take mnt_sha...
2700
  	if (!list_empty(&mnt->mnt_expire)) {
97216be09   Al Viro   fold release_moun...
2701
  		namespace_lock();
6776db3d3   Al Viro   vfs: take mnt_sha...
2702
  		list_del_init(&mnt->mnt_expire);
97216be09   Al Viro   fold release_moun...
2703
  		namespace_unlock();
19a167af7   Al Viro   Take the completi...
2704
  	}
b1e75df45   Al Viro   tidy up around fi...
2705
2706
  	mntput(m);
  	mntput(m);
19a167af7   Al Viro   Take the completi...
2707
2708
  	return err;
  }
ea5b778a8   David Howells   Unexport do_add_m...
2709
2710
2711
2712
2713
2714
2715
  /**
   * mnt_set_expiry - Put a mount on an expiration list
   * @mnt: The mount to list.
   * @expiry_list: The list to add the mount to.
   */
  void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
  {
97216be09   Al Viro   fold release_moun...
2716
  	namespace_lock();
ea5b778a8   David Howells   Unexport do_add_m...
2717

6776db3d3   Al Viro   vfs: take mnt_sha...
2718
  	list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
ea5b778a8   David Howells   Unexport do_add_m...
2719

97216be09   Al Viro   fold release_moun...
2720
  	namespace_unlock();
ea5b778a8   David Howells   Unexport do_add_m...
2721
2722
2723
2724
  }
  EXPORT_SYMBOL(mnt_set_expiry);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2725
2726
2727
2728
2729
2730
   * process a list of expirable mountpoints with the intent of discarding any
   * mountpoints that aren't in use and haven't been touched since last we came
   * here
   */
  void mark_mounts_for_expiry(struct list_head *mounts)
  {
761d5c38e   Al Viro   vfs: spread struc...
2731
  	struct mount *mnt, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2732
2733
2734
2735
  	LIST_HEAD(graveyard);
  
  	if (list_empty(mounts))
  		return;
97216be09   Al Viro   fold release_moun...
2736
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
2737
  	lock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2738
2739
2740
2741
2742
2743
2744
  
  	/* extract from the expiration list every vfsmount that matches the
  	 * following criteria:
  	 * - only referenced by its parent vfsmount
  	 * - still marked for expiry (marked on the last call here; marks are
  	 *   cleared by mntput())
  	 */
6776db3d3   Al Viro   vfs: take mnt_sha...
2745
  	list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
863d684f9   Al Viro   vfs: move the res...
2746
  		if (!xchg(&mnt->mnt_expiry_mark, 1) ||
1ab597386   Al Viro   vfs: spread struc...
2747
  			propagate_mount_busy(mnt, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2748
  			continue;
6776db3d3   Al Viro   vfs: take mnt_sha...
2749
  		list_move(&mnt->mnt_expire, &graveyard);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2750
  	}
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2751
  	while (!list_empty(&graveyard)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2752
  		mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2753
  		touch_mnt_namespace(mnt->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2754
  		umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2755
  	}
719ea2fbb   Al Viro   new helpers: lock...
2756
  	unlock_mount_hash();
3ab6abee5   Al Viro   more conversions ...
2757
  	namespace_unlock();
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
  }
  
  EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
  
  /*
   * Ripoff of 'select_parent()'
   *
   * search the list of submounts for a given mountpoint, and move any
   * shrinkable submounts to the 'graveyard' list.
   */
692afc312   Al Viro   vfs: spread struc...
2768
  static int select_submounts(struct mount *parent, struct list_head *graveyard)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2769
  {
692afc312   Al Viro   vfs: spread struc...
2770
  	struct mount *this_parent = parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2771
2772
2773
2774
  	struct list_head *next;
  	int found = 0;
  
  repeat:
6b41d536f   Al Viro   vfs: take mnt_chi...
2775
  	next = this_parent->mnt_mounts.next;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2776
  resume:
6b41d536f   Al Viro   vfs: take mnt_chi...
2777
  	while (next != &this_parent->mnt_mounts) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2778
  		struct list_head *tmp = next;
6b41d536f   Al Viro   vfs: take mnt_chi...
2779
  		struct mount *mnt = list_entry(tmp, struct mount, mnt_child);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2780
2781
  
  		next = tmp->next;
692afc312   Al Viro   vfs: spread struc...
2782
  		if (!(mnt->mnt.mnt_flags & MNT_SHRINKABLE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2783
  			continue;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2784
2785
2786
  		/*
  		 * Descend a level if the d_mounts list is non-empty.
  		 */
6b41d536f   Al Viro   vfs: take mnt_chi...
2787
  		if (!list_empty(&mnt->mnt_mounts)) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2788
2789
2790
  			this_parent = mnt;
  			goto repeat;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2791

1ab597386   Al Viro   vfs: spread struc...
2792
  		if (!propagate_mount_busy(mnt, 1)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2793
  			list_move_tail(&mnt->mnt_expire, graveyard);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2794
2795
  			found++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2796
  	}
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2797
2798
2799
2800
  	/*
  	 * All done at this level ... ascend and resume the search
  	 */
  	if (this_parent != parent) {
6b41d536f   Al Viro   vfs: take mnt_chi...
2801
  		next = this_parent->mnt_child.next;
0714a5338   Al Viro   vfs: now it can b...
2802
  		this_parent = this_parent->mnt_parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2803
2804
2805
2806
2807
2808
2809
2810
  		goto resume;
  	}
  	return found;
  }
  
  /*
   * process a list of expirable mountpoints with the intent of discarding any
   * submounts of a specific parent mountpoint
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
2811
   *
48a066e72   Al Viro   RCU'd vfsmounts
2812
   * mount_lock must be held for write
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2813
   */
b54b9be78   Al Viro   get rid of the se...
2814
  static void shrink_submounts(struct mount *mnt)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2815
2816
  {
  	LIST_HEAD(graveyard);
761d5c38e   Al Viro   vfs: spread struc...
2817
  	struct mount *m;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2818

5528f911b   Trond Myklebust   VFS: Add shrink_s...
2819
  	/* extract submounts of 'mountpoint' from the expiration list */
c35038bec   Al Viro   [PATCH] do shrink...
2820
  	while (select_submounts(mnt, &graveyard)) {
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2821
  		while (!list_empty(&graveyard)) {
761d5c38e   Al Viro   vfs: spread struc...
2822
  			m = list_first_entry(&graveyard, struct mount,
6776db3d3   Al Viro   vfs: take mnt_sha...
2823
  						mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2824
  			touch_mnt_namespace(m->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2825
  			umount_tree(m, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2826
2827
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2828
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2829
2830
2831
2832
2833
2834
  /*
   * Some copy_from_user() implementations do not return the exact number of
   * bytes remaining to copy on a fault.  But copy_mount_options() requires that.
   * Note that this function differs from copy_from_user() in that it will oops
   * on bad values of `to', rather than returning a short copy.
   */
b58fed8b1   Ram Pai   [PATCH] lindent f...
2835
2836
  static long exact_copy_from_user(void *to, const void __user * from,
  				 unsigned long n)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2837
2838
2839
2840
  {
  	char *t = to;
  	const char __user *f = from;
  	char c;
96d4f267e   Linus Torvalds   Remove 'type' arg...
2841
  	if (!access_ok(from, n))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
  		return n;
  
  	while (n) {
  		if (__get_user(c, f)) {
  			memset(t, 0, n);
  			break;
  		}
  		*t++ = c;
  		f++;
  		n--;
  	}
  	return n;
  }
b40ef8696   Al Viro   saner calling con...
2855
  void *copy_mount_options(const void __user * data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2856
2857
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2858
  	unsigned long size;
b40ef8696   Al Viro   saner calling con...
2859
  	char *copy;
b58fed8b1   Ram Pai   [PATCH] lindent f...
2860

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2861
  	if (!data)
b40ef8696   Al Viro   saner calling con...
2862
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2863

b40ef8696   Al Viro   saner calling con...
2864
2865
2866
  	copy = kmalloc(PAGE_SIZE, GFP_KERNEL);
  	if (!copy)
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2867
2868
2869
2870
2871
2872
  
  	/* We only care that *some* data at the address the user
  	 * gave us is valid.  Just in case, we'll zero
  	 * the remainder of the page.
  	 */
  	/* copy_from_user cannot cross TASK_SIZE ! */
ed8a66b83   Andrey Konovalov   fs/namespace: unt...
2873
  	size = TASK_SIZE - (unsigned long)untagged_addr(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2874
2875
  	if (size > PAGE_SIZE)
  		size = PAGE_SIZE;
b40ef8696   Al Viro   saner calling con...
2876
  	i = size - exact_copy_from_user(copy, data, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2877
  	if (!i) {
b40ef8696   Al Viro   saner calling con...
2878
2879
  		kfree(copy);
  		return ERR_PTR(-EFAULT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2880
2881
  	}
  	if (i != PAGE_SIZE)
b40ef8696   Al Viro   saner calling con...
2882
2883
  		memset(copy + i, 0, PAGE_SIZE - i);
  	return copy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2884
  }
b8850d1fa   Tim Gardner   fs: namespace: su...
2885
  char *copy_mount_string(const void __user *data)
eca6f534e   Vegard Nossum   fs: fix overflow ...
2886
  {
fbdb44013   Chandan Rajendra   copy_mount_string...
2887
  	return data ? strndup_user(data, PATH_MAX) : NULL;
eca6f534e   Vegard Nossum   fs: fix overflow ...
2888
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
  /*
   * Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
   * be given to the mount() call (ie: read-only, no-dev, no-suid etc).
   *
   * data is a (void *) that can point to any structure up to
   * PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
   * information (or be NULL).
   *
   * Pre-0.97 versions of mount() didn't have a flags word.
   * When the flags word was introduced its top half was required
   * to have the magic value 0xC0ED, and this remained so until 2.4.0-test9.
   * Therefore, if this magic number is present, it carries no information
   * and must be discarded.
   */
5e6123f34   Seunghun Lee   vfs: move getname...
2903
  long do_mount(const char *dev_name, const char __user *dir_name,
808d4e3cf   Al Viro   consitify do_moun...
2904
  		const char *type_page, unsigned long flags, void *data_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2905
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2906
  	struct path path;
e462ec50c   David Howells   VFS: Differentiat...
2907
  	unsigned int mnt_flags = 0, sb_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2908
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2909
2910
2911
2912
2913
2914
  
  	/* Discard magic */
  	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
  		flags &= ~MS_MGC_MSK;
  
  	/* Basic sanity checks */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2915
2916
  	if (data_page)
  		((char *)data_page)[PAGE_SIZE - 1] = 0;
e462ec50c   David Howells   VFS: Differentiat...
2917
2918
  	if (flags & MS_NOUSER)
  		return -EINVAL;
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2919
  	/* ... and get the mountpoint */
ce6595a28   Al Viro   kill the last use...
2920
  	retval = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2921
2922
2923
2924
2925
  	if (retval)
  		return retval;
  
  	retval = security_sb_mount(dev_name, &path,
  				   type_page, flags, data_page);
0d5cadb87   Al Viro   do_mount(): fix a...
2926
2927
  	if (!retval && !may_mount())
  		retval = -EPERM;
e462ec50c   David Howells   VFS: Differentiat...
2928
  	if (!retval && (flags & SB_MANDLOCK) && !may_mandlock())
9e8925b67   Jeff Layton   locks: Allow disa...
2929
  		retval = -EPERM;
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2930
2931
  	if (retval)
  		goto dput_out;
613cbe3d4   Andi Kleen   Don't set relatim...
2932
2933
2934
  	/* Default to relatime unless overriden */
  	if (!(flags & MS_NOATIME))
  		mnt_flags |= MNT_RELATIME;
0a1c01c94   Matthew Garrett   Make relatime def...
2935

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2936
2937
2938
2939
2940
2941
2942
  	/* Separate the per-mountpoint flags */
  	if (flags & MS_NOSUID)
  		mnt_flags |= MNT_NOSUID;
  	if (flags & MS_NODEV)
  		mnt_flags |= MNT_NODEV;
  	if (flags & MS_NOEXEC)
  		mnt_flags |= MNT_NOEXEC;
fc33a7bb9   Christoph Hellwig   [PATCH] per-mount...
2943
2944
2945
2946
  	if (flags & MS_NOATIME)
  		mnt_flags |= MNT_NOATIME;
  	if (flags & MS_NODIRATIME)
  		mnt_flags |= MNT_NODIRATIME;
d0adde574   Matthew Garrett   Add a strictatime...
2947
2948
  	if (flags & MS_STRICTATIME)
  		mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
a9e5b7328   David Howells   vfs: Undo an over...
2949
  	if (flags & MS_RDONLY)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2950
  		mnt_flags |= MNT_READONLY;
fc33a7bb9   Christoph Hellwig   [PATCH] per-mount...
2951

ffbc6f0ea   Eric W. Biederman   mnt: Change the d...
2952
2953
2954
2955
2956
2957
2958
  	/* The default atime for remount is preservation */
  	if ((flags & MS_REMOUNT) &&
  	    ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
  		       MS_STRICTATIME)) == 0)) {
  		mnt_flags &= ~MNT_ATIME_MASK;
  		mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK;
  	}
e462ec50c   David Howells   VFS: Differentiat...
2959
2960
2961
2962
2963
  	sb_flags = flags & (SB_RDONLY |
  			    SB_SYNCHRONOUS |
  			    SB_MANDLOCK |
  			    SB_DIRSYNC |
  			    SB_SILENT |
917086ff2   Mimi Zohar   vfs: fix mounting...
2964
  			    SB_POSIXACL |
d7ee94694   Markus Trippelsdorf   VFS: Handle lazyt...
2965
  			    SB_LAZYTIME |
917086ff2   Mimi Zohar   vfs: fix mounting...
2966
  			    SB_I_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2967

43f5e655e   David Howells   vfs: Separate cha...
2968
2969
2970
  	if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
  		retval = do_reconfigure_mnt(&path, mnt_flags);
  	else if (flags & MS_REMOUNT)
e462ec50c   David Howells   VFS: Differentiat...
2971
  		retval = do_remount(&path, flags, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2972
2973
  				    data_page);
  	else if (flags & MS_BIND)
2d92ab3c6   Al Viro   [PATCH] finally g...
2974
  		retval = do_loopback(&path, dev_name, flags & MS_REC);
9676f0c63   Ram Pai   [PATCH] unbindabl...
2975
  	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
2d92ab3c6   Al Viro   [PATCH] finally g...
2976
  		retval = do_change_type(&path, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2977
  	else if (flags & MS_MOVE)
2db154b3e   David Howells   vfs: syscall: Add...
2978
  		retval = do_move_mount_old(&path, dev_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2979
  	else
e462ec50c   David Howells   VFS: Differentiat...
2980
  		retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2981
2982
  				      dev_name, data_page);
  dput_out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2983
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2984
2985
  	return retval;
  }
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2986
2987
2988
2989
2990
2991
2992
2993
2994
  static struct ucounts *inc_mnt_namespaces(struct user_namespace *ns)
  {
  	return inc_ucount(ns, current_euid(), UCOUNT_MNT_NAMESPACES);
  }
  
  static void dec_mnt_namespaces(struct ucounts *ucounts)
  {
  	dec_ucount(ucounts, UCOUNT_MNT_NAMESPACES);
  }
771b13716   Eric W. Biederman   vfs: Add a user n...
2995
2996
  static void free_mnt_ns(struct mnt_namespace *ns)
  {
74e831221   Al Viro   saner handling of...
2997
2998
  	if (!is_anon_ns(ns))
  		ns_free_inum(&ns->ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2999
  	dec_mnt_namespaces(ns->ucounts);
771b13716   Eric W. Biederman   vfs: Add a user n...
3000
3001
3002
  	put_user_ns(ns->user_ns);
  	kfree(ns);
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
3003
3004
3005
3006
3007
3008
3009
3010
  /*
   * Assign a sequence number so we can detect when we attempt to bind
   * mount a reference to an older mount namespace into the current
   * mount namespace, preventing reference counting loops.  A 64bit
   * number incrementing at 10Ghz will take 12,427 years to wrap which
   * is effectively never, so we can ignore the possibility.
   */
  static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
74e831221   Al Viro   saner handling of...
3011
  static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool anon)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
3012
3013
  {
  	struct mnt_namespace *new_ns;
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
3014
  	struct ucounts *ucounts;
98f842e67   Eric W. Biederman   proc: Usable inod...
3015
  	int ret;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
3016

537f7ccb3   Eric W. Biederman   mntns: Add a limi...
3017
3018
  	ucounts = inc_mnt_namespaces(user_ns);
  	if (!ucounts)
df75e7748   Eric W. Biederman   userns: When the ...
3019
  		return ERR_PTR(-ENOSPC);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
3020

74e831221   Al Viro   saner handling of...
3021
  	new_ns = kzalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
3022
3023
  	if (!new_ns) {
  		dec_mnt_namespaces(ucounts);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
3024
  		return ERR_PTR(-ENOMEM);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
3025
  	}
74e831221   Al Viro   saner handling of...
3026
3027
3028
3029
3030
3031
3032
  	if (!anon) {
  		ret = ns_alloc_inum(&new_ns->ns);
  		if (ret) {
  			kfree(new_ns);
  			dec_mnt_namespaces(ucounts);
  			return ERR_PTR(ret);
  		}
98f842e67   Eric W. Biederman   proc: Usable inod...
3033
  	}
33c429405   Al Viro   copy address of p...
3034
  	new_ns->ns.ops = &mntns_operations;
74e831221   Al Viro   saner handling of...
3035
3036
  	if (!anon)
  		new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
3037
  	atomic_set(&new_ns->count, 1);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
3038
3039
  	INIT_LIST_HEAD(&new_ns->list);
  	init_waitqueue_head(&new_ns->poll);
771b13716   Eric W. Biederman   vfs: Add a user n...
3040
  	new_ns->user_ns = get_user_ns(user_ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
3041
  	new_ns->ucounts = ucounts;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
3042
3043
  	return new_ns;
  }
0766f788e   Emese Revfy   latent_entropy: M...
3044
  __latent_entropy
9559f6891   Al Viro   fold dup_mnt_ns()...
3045
3046
  struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
  		struct user_namespace *user_ns, struct fs_struct *new_fs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3047
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3048
  	struct mnt_namespace *new_ns;
7f2da1e7d   Al Viro   [PATCH] kill altroot
3049
  	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
315fc83e5   Al Viro   vfs: spread struc...
3050
  	struct mount *p, *q;
9559f6891   Al Viro   fold dup_mnt_ns()...
3051
  	struct mount *old;
cb338d06e   Al Viro   vfs: spread struc...
3052
  	struct mount *new;
7a472ef4b   Eric W. Biederman   vfs: Only support...
3053
  	int copy_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3054

9559f6891   Al Viro   fold dup_mnt_ns()...
3055
3056
3057
3058
3059
3060
3061
3062
  	BUG_ON(!ns);
  
  	if (likely(!(flags & CLONE_NEWNS))) {
  		get_mnt_ns(ns);
  		return ns;
  	}
  
  	old = ns->root;
74e831221   Al Viro   saner handling of...
3063
  	new_ns = alloc_mnt_ns(user_ns, false);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
3064
3065
  	if (IS_ERR(new_ns))
  		return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3066

97216be09   Al Viro   fold release_moun...
3067
  	namespace_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3068
  	/* First pass: copy the tree topology */
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
3069
  	copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
9559f6891   Al Viro   fold dup_mnt_ns()...
3070
  	if (user_ns != ns->user_ns)
3bd045cc9   Al Viro   separate copying ...
3071
  		copy_flags |= CL_SHARED_TO_SLAVE;
7a472ef4b   Eric W. Biederman   vfs: Only support...
3072
  	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
be34d1a3b   David Howells   VFS: Make clone_m...
3073
  	if (IS_ERR(new)) {
328e6d901   Al Viro   switch unlock_mou...
3074
  		namespace_unlock();
771b13716   Eric W. Biederman   vfs: Add a user n...
3075
  		free_mnt_ns(new_ns);
be34d1a3b   David Howells   VFS: Make clone_m...
3076
  		return ERR_CAST(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3077
  	}
3bd045cc9   Al Viro   separate copying ...
3078
3079
3080
3081
3082
  	if (user_ns != ns->user_ns) {
  		lock_mount_hash();
  		lock_mnt_tree(new);
  		unlock_mount_hash();
  	}
be08d6d26   Al Viro   switch mnt_namesp...
3083
  	new_ns->root = new;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
3084
  	list_add_tail(&new_ns->list, &new->mnt_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3085
3086
3087
3088
3089
3090
  
  	/*
  	 * Second pass: switch the tsk->fs->* elements and mark new vfsmounts
  	 * as belonging to new namespace.  We have already acquired a private
  	 * fs_struct, so tsk->fs->lock is not needed.
  	 */
909b0a88e   Al Viro   vfs: spread struc...
3091
  	p = old;
cb338d06e   Al Viro   vfs: spread struc...
3092
  	q = new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3093
  	while (p) {
143c8c91c   Al Viro   vfs: mnt_ns moved...
3094
  		q->mnt_ns = new_ns;
d29216842   Eric W. Biederman   mnt: Add a per mo...
3095
  		new_ns->mounts++;
9559f6891   Al Viro   fold dup_mnt_ns()...
3096
3097
3098
  		if (new_fs) {
  			if (&p->mnt == new_fs->root.mnt) {
  				new_fs->root.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
3099
  				rootmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3100
  			}
9559f6891   Al Viro   fold dup_mnt_ns()...
3101
3102
  			if (&p->mnt == new_fs->pwd.mnt) {
  				new_fs->pwd.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
3103
  				pwdmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3104
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3105
  		}
909b0a88e   Al Viro   vfs: spread struc...
3106
3107
  		p = next_mnt(p, old);
  		q = next_mnt(q, new);
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
3108
3109
3110
3111
  		if (!q)
  			break;
  		while (p->mnt.mnt_root != q->mnt.mnt_root)
  			p = next_mnt(p, old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3112
  	}
328e6d901   Al Viro   switch unlock_mou...
3113
  	namespace_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3114

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3115
  	if (rootmnt)
f03c65993   Al Viro   sanitize vfsmount...
3116
  		mntput(rootmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3117
  	if (pwdmnt)
f03c65993   Al Viro   sanitize vfsmount...
3118
  		mntput(pwdmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3119

741a29513   JANAK DESAI   [PATCH] unshare s...
3120
  	return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3121
  }
74e831221   Al Viro   saner handling of...
3122
  struct dentry *mount_subtree(struct vfsmount *m, const char *name)
ea441d110   Al Viro   new helper: mount...
3123
  {
74e831221   Al Viro   saner handling of...
3124
  	struct mount *mnt = real_mount(m);
ea441d110   Al Viro   new helper: mount...
3125
  	struct mnt_namespace *ns;
d31da0f0b   Al Viro   mount_subtree() p...
3126
  	struct super_block *s;
ea441d110   Al Viro   new helper: mount...
3127
3128
  	struct path path;
  	int err;
74e831221   Al Viro   saner handling of...
3129
3130
3131
  	ns = alloc_mnt_ns(&init_user_ns, true);
  	if (IS_ERR(ns)) {
  		mntput(m);
ea441d110   Al Viro   new helper: mount...
3132
  		return ERR_CAST(ns);
74e831221   Al Viro   saner handling of...
3133
3134
3135
3136
3137
  	}
  	mnt->mnt_ns = ns;
  	ns->root = mnt;
  	ns->mounts++;
  	list_add(&mnt->mnt_list, &ns->list);
ea441d110   Al Viro   new helper: mount...
3138

74e831221   Al Viro   saner handling of...
3139
  	err = vfs_path_lookup(m->mnt_root, m,
ea441d110   Al Viro   new helper: mount...
3140
3141
3142
3143
3144
3145
3146
3147
  			name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
  
  	put_mnt_ns(ns);
  
  	if (err)
  		return ERR_PTR(err);
  
  	/* trade a vfsmount reference for active sb one */
d31da0f0b   Al Viro   mount_subtree() p...
3148
3149
  	s = path.mnt->mnt_sb;
  	atomic_inc(&s->s_active);
ea441d110   Al Viro   new helper: mount...
3150
3151
  	mntput(path.mnt);
  	/* lock the sucker */
d31da0f0b   Al Viro   mount_subtree() p...
3152
  	down_write(&s->s_umount);
ea441d110   Al Viro   new helper: mount...
3153
3154
3155
3156
  	/* ... and return the root of (sub)tree on it */
  	return path.dentry;
  }
  EXPORT_SYMBOL(mount_subtree);
33488845f   Al Viro   constify ksys_mou...
3157
3158
  int ksys_mount(const char __user *dev_name, const char __user *dir_name,
  	       const char __user *type, unsigned long flags, void __user *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3159
  {
eca6f534e   Vegard Nossum   fs: fix overflow ...
3160
3161
  	int ret;
  	char *kernel_type;
eca6f534e   Vegard Nossum   fs: fix overflow ...
3162
  	char *kernel_dev;
b40ef8696   Al Viro   saner calling con...
3163
  	void *options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3164

b8850d1fa   Tim Gardner   fs: namespace: su...
3165
3166
3167
  	kernel_type = copy_mount_string(type);
  	ret = PTR_ERR(kernel_type);
  	if (IS_ERR(kernel_type))
eca6f534e   Vegard Nossum   fs: fix overflow ...
3168
  		goto out_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3169

b8850d1fa   Tim Gardner   fs: namespace: su...
3170
3171
3172
  	kernel_dev = copy_mount_string(dev_name);
  	ret = PTR_ERR(kernel_dev);
  	if (IS_ERR(kernel_dev))
eca6f534e   Vegard Nossum   fs: fix overflow ...
3173
  		goto out_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3174

b40ef8696   Al Viro   saner calling con...
3175
3176
3177
  	options = copy_mount_options(data);
  	ret = PTR_ERR(options);
  	if (IS_ERR(options))
eca6f534e   Vegard Nossum   fs: fix overflow ...
3178
  		goto out_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3179

b40ef8696   Al Viro   saner calling con...
3180
  	ret = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3181

b40ef8696   Al Viro   saner calling con...
3182
  	kfree(options);
eca6f534e   Vegard Nossum   fs: fix overflow ...
3183
3184
3185
  out_data:
  	kfree(kernel_dev);
  out_dev:
eca6f534e   Vegard Nossum   fs: fix overflow ...
3186
3187
3188
  	kfree(kernel_type);
  out_type:
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3189
  }
312db1aa1   Dominik Brodowski   fs: add ksys_moun...
3190
3191
3192
3193
3194
  SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
  		char __user *, type, unsigned long, flags, void __user *, data)
  {
  	return ksys_mount(dev_name, dir_name, type, flags, data);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3195
  /*
93766fbd2   David Howells   vfs: syscall: Add...
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
   * Create a kernel mount representation for a new, prepared superblock
   * (specified by fs_fd) and attach to an open_tree-like file descriptor.
   */
  SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags,
  		unsigned int, attr_flags)
  {
  	struct mnt_namespace *ns;
  	struct fs_context *fc;
  	struct file *file;
  	struct path newmount;
  	struct mount *mnt;
  	struct fd f;
  	unsigned int mnt_flags = 0;
  	long ret;
  
  	if (!may_mount())
  		return -EPERM;
  
  	if ((flags & ~(FSMOUNT_CLOEXEC)) != 0)
  		return -EINVAL;
  
  	if (attr_flags & ~(MOUNT_ATTR_RDONLY |
  			   MOUNT_ATTR_NOSUID |
  			   MOUNT_ATTR_NODEV |
  			   MOUNT_ATTR_NOEXEC |
  			   MOUNT_ATTR__ATIME |
  			   MOUNT_ATTR_NODIRATIME))
  		return -EINVAL;
  
  	if (attr_flags & MOUNT_ATTR_RDONLY)
  		mnt_flags |= MNT_READONLY;
  	if (attr_flags & MOUNT_ATTR_NOSUID)
  		mnt_flags |= MNT_NOSUID;
  	if (attr_flags & MOUNT_ATTR_NODEV)
  		mnt_flags |= MNT_NODEV;
  	if (attr_flags & MOUNT_ATTR_NOEXEC)
  		mnt_flags |= MNT_NOEXEC;
  	if (attr_flags & MOUNT_ATTR_NODIRATIME)
  		mnt_flags |= MNT_NODIRATIME;
  
  	switch (attr_flags & MOUNT_ATTR__ATIME) {
  	case MOUNT_ATTR_STRICTATIME:
  		break;
  	case MOUNT_ATTR_NOATIME:
  		mnt_flags |= MNT_NOATIME;
  		break;
  	case MOUNT_ATTR_RELATIME:
  		mnt_flags |= MNT_RELATIME;
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	f = fdget(fs_fd);
  	if (!f.file)
  		return -EBADF;
  
  	ret = -EINVAL;
  	if (f.file->f_op != &fscontext_fops)
  		goto err_fsfd;
  
  	fc = f.file->private_data;
  
  	ret = mutex_lock_interruptible(&fc->uapi_mutex);
  	if (ret < 0)
  		goto err_fsfd;
  
  	/* There must be a valid superblock or we can't mount it */
  	ret = -EINVAL;
  	if (!fc->root)
  		goto err_unlock;
  
  	ret = -EPERM;
  	if (mount_too_revealing(fc->root->d_sb, &mnt_flags)) {
  		pr_warn("VFS: Mount too revealing
  ");
  		goto err_unlock;
  	}
  
  	ret = -EBUSY;
  	if (fc->phase != FS_CONTEXT_AWAITING_MOUNT)
  		goto err_unlock;
  
  	ret = -EPERM;
  	if ((fc->sb_flags & SB_MANDLOCK) && !may_mandlock())
  		goto err_unlock;
  
  	newmount.mnt = vfs_create_mount(fc);
  	if (IS_ERR(newmount.mnt)) {
  		ret = PTR_ERR(newmount.mnt);
  		goto err_unlock;
  	}
  	newmount.dentry = dget(fc->root);
  	newmount.mnt->mnt_flags = mnt_flags;
  
  	/* We've done the mount bit - now move the file context into more or
  	 * less the same state as if we'd done an fspick().  We don't want to
  	 * do any memory allocation or anything like that at this point as we
  	 * don't want to have to handle any errors incurred.
  	 */
  	vfs_clean_context(fc);
  
  	ns = alloc_mnt_ns(current->nsproxy->mnt_ns->user_ns, true);
  	if (IS_ERR(ns)) {
  		ret = PTR_ERR(ns);
  		goto err_path;
  	}
  	mnt = real_mount(newmount.mnt);
  	mnt->mnt_ns = ns;
  	ns->root = mnt;
  	ns->mounts = 1;
  	list_add(&mnt->mnt_list, &ns->list);
1b0b9cc8d   Eric Biggers   vfs: fsmount: add...
3308
  	mntget(newmount.mnt);
93766fbd2   David Howells   vfs: syscall: Add...
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
  
  	/* Attach to an apparent O_PATH fd with a note that we need to unmount
  	 * it, not just simply put it.
  	 */
  	file = dentry_open(&newmount, O_PATH, fc->cred);
  	if (IS_ERR(file)) {
  		dissolve_on_fput(newmount.mnt);
  		ret = PTR_ERR(file);
  		goto err_path;
  	}
  	file->f_mode |= FMODE_NEED_UNMOUNT;
  
  	ret = get_unused_fd_flags((flags & FSMOUNT_CLOEXEC) ? O_CLOEXEC : 0);
  	if (ret >= 0)
  		fd_install(ret, file);
  	else
  		fput(file);
  
  err_path:
  	path_put(&newmount);
  err_unlock:
  	mutex_unlock(&fc->uapi_mutex);
  err_fsfd:
  	fdput(f);
  	return ret;
  }
  
  /*
   * Move a mount from one place to another.  In combination with
   * fsopen()/fsmount() this is used to install a new mount and in combination
   * with open_tree(OPEN_TREE_CLONE [| AT_RECURSIVE]) it can be used to copy
   * a mount subtree.
2db154b3e   David Howells   vfs: syscall: Add...
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
   *
   * Note the flags value is a combination of MOVE_MOUNT_* flags.
   */
  SYSCALL_DEFINE5(move_mount,
  		int, from_dfd, const char *, from_pathname,
  		int, to_dfd, const char *, to_pathname,
  		unsigned int, flags)
  {
  	struct path from_path, to_path;
  	unsigned int lflags;
  	int ret = 0;
  
  	if (!may_mount())
  		return -EPERM;
  
  	if (flags & ~MOVE_MOUNT__MASK)
  		return -EINVAL;
  
  	/* If someone gives a pathname, they aren't permitted to move
  	 * from an fd that requires unmount as we can't get at the flag
  	 * to clear it afterwards.
  	 */
  	lflags = 0;
  	if (flags & MOVE_MOUNT_F_SYMLINKS)	lflags |= LOOKUP_FOLLOW;
  	if (flags & MOVE_MOUNT_F_AUTOMOUNTS)	lflags |= LOOKUP_AUTOMOUNT;
  	if (flags & MOVE_MOUNT_F_EMPTY_PATH)	lflags |= LOOKUP_EMPTY;
  
  	ret = user_path_at(from_dfd, from_pathname, lflags, &from_path);
  	if (ret < 0)
  		return ret;
  
  	lflags = 0;
  	if (flags & MOVE_MOUNT_T_SYMLINKS)	lflags |= LOOKUP_FOLLOW;
  	if (flags & MOVE_MOUNT_T_AUTOMOUNTS)	lflags |= LOOKUP_AUTOMOUNT;
  	if (flags & MOVE_MOUNT_T_EMPTY_PATH)	lflags |= LOOKUP_EMPTY;
  
  	ret = user_path_at(to_dfd, to_pathname, lflags, &to_path);
  	if (ret < 0)
  		goto out_from;
  
  	ret = security_move_mount(&from_path, &to_path);
  	if (ret < 0)
  		goto out_to;
  
  	ret = do_move_mount(&from_path, &to_path);
  
  out_to:
  	path_put(&to_path);
  out_from:
  	path_put(&from_path);
  	return ret;
  }
  
  /*
afac7cba7   Al Viro   vfs: more mnt_par...
3395
3396
   * Return true if path is reachable from root
   *
48a066e72   Al Viro   RCU'd vfsmounts
3397
   * namespace_sem or mount_lock is held
afac7cba7   Al Viro   vfs: more mnt_par...
3398
   */
643822b41   Al Viro   vfs: spread struc...
3399
  bool is_path_reachable(struct mount *mnt, struct dentry *dentry,
afac7cba7   Al Viro   vfs: more mnt_par...
3400
3401
  			 const struct path *root)
  {
643822b41   Al Viro   vfs: spread struc...
3402
  	while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) {
a73324da7   Al Viro   vfs: move mnt_mou...
3403
  		dentry = mnt->mnt_mountpoint;
0714a5338   Al Viro   vfs: now it can b...
3404
  		mnt = mnt->mnt_parent;
afac7cba7   Al Viro   vfs: more mnt_par...
3405
  	}
643822b41   Al Viro   vfs: spread struc...
3406
  	return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry);
afac7cba7   Al Viro   vfs: more mnt_par...
3407
  }
640eb7e7b   Mickaël Salaün   fs: Constify path...
3408
  bool path_is_under(const struct path *path1, const struct path *path2)
afac7cba7   Al Viro   vfs: more mnt_par...
3409
  {
25ab4c9b1   Yaowei Bai   fs/namespace.c: p...
3410
  	bool res;
48a066e72   Al Viro   RCU'd vfsmounts
3411
  	read_seqlock_excl(&mount_lock);
643822b41   Al Viro   vfs: spread struc...
3412
  	res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
48a066e72   Al Viro   RCU'd vfsmounts
3413
  	read_sequnlock_excl(&mount_lock);
afac7cba7   Al Viro   vfs: more mnt_par...
3414
3415
3416
3417
3418
  	return res;
  }
  EXPORT_SYMBOL(path_is_under);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
   * pivot_root Semantics:
   * Moves the root file system of the current process to the directory put_old,
   * makes new_root as the new root file system of the current process, and sets
   * root/cwd of all processes which had them on the current root to new_root.
   *
   * Restrictions:
   * The new_root and put_old must be directories, and  must not be on the
   * same file  system as the current process root. The put_old  must  be
   * underneath new_root,  i.e. adding a non-zero number of /.. to the string
   * pointed to by put_old must yield the same directory as new_root. No other
   * file system may be mounted on put_old. After all, new_root is a mountpoint.
   *
4a0d11fae   Neil Brown   [PATCH] pivot_roo...
3431
3432
3433
3434
   * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
   * See Documentation/filesystems/ramfs-rootfs-initramfs.txt for alternatives
   * in this situation.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3435
3436
3437
3438
3439
3440
3441
3442
   * Notes:
   *  - we don't move root/cwd if they are not at the root (reason: if something
   *    cared enough to change them, it's probably wrong to force them elsewhere)
   *  - it's okay to pick a root that isn't the root of a file system, e.g.
   *    /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
   *    though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
   *    first.
   */
3480b2574   Heiko Carstens   [CVE-2009-0029] S...
3443
3444
  SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
  		const char __user *, put_old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3445
  {
2763d1191   Al Viro   get rid of detach...
3446
3447
  	struct path new, old, root;
  	struct mount *new_mnt, *root_mnt, *old_mnt, *root_parent, *ex_parent;
84d17192d   Al Viro   get rid of full-h...
3448
  	struct mountpoint *old_mp, *root_mp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3449
  	int error;
9b40bc90a   Al Viro   get rid of unprot...
3450
  	if (!may_mount())
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3451
  		return -EPERM;
ce6595a28   Al Viro   kill the last use...
3452
3453
  	error = user_path_at(AT_FDCWD, new_root,
  			     LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3454
3455
  	if (error)
  		goto out0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3456

ce6595a28   Al Viro   kill the last use...
3457
3458
  	error = user_path_at(AT_FDCWD, put_old,
  			     LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3459
3460
  	if (error)
  		goto out1;
2d8f30380   Al Viro   [PATCH] sanitize ...
3461
  	error = security_sb_pivotroot(&old, &new);
b12cea919   Al Viro   change the lockin...
3462
3463
  	if (error)
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3464

f7ad3c6be   Miklos Szeredi   vfs: add helpers ...
3465
  	get_fs_root(current->fs, &root);
84d17192d   Al Viro   get rid of full-h...
3466
3467
3468
  	old_mp = lock_mount(&old);
  	error = PTR_ERR(old_mp);
  	if (IS_ERR(old_mp))
b12cea919   Al Viro   change the lockin...
3469
  		goto out3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3470
  	error = -EINVAL;
419148da6   Al Viro   vfs: spread struc...
3471
3472
  	new_mnt = real_mount(new.mnt);
  	root_mnt = real_mount(root.mnt);
84d17192d   Al Viro   get rid of full-h...
3473
  	old_mnt = real_mount(old.mnt);
2763d1191   Al Viro   get rid of detach...
3474
3475
  	ex_parent = new_mnt->mnt_parent;
  	root_parent = root_mnt->mnt_parent;
84d17192d   Al Viro   get rid of full-h...
3476
  	if (IS_MNT_SHARED(old_mnt) ||
2763d1191   Al Viro   get rid of detach...
3477
3478
  		IS_MNT_SHARED(ex_parent) ||
  		IS_MNT_SHARED(root_parent))
b12cea919   Al Viro   change the lockin...
3479
  		goto out4;
143c8c91c   Al Viro   vfs: mnt_ns moved...
3480
  	if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
b12cea919   Al Viro   change the lockin...
3481
  		goto out4;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
3482
3483
  	if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
  		goto out4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3484
  	error = -ENOENT;
f3da392e9   Alexey Dobriyan   dcache: extrace a...
3485
  	if (d_unlinked(new.dentry))
b12cea919   Al Viro   change the lockin...
3486
  		goto out4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3487
  	error = -EBUSY;
84d17192d   Al Viro   get rid of full-h...
3488
  	if (new_mnt == root_mnt || old_mnt == root_mnt)
b12cea919   Al Viro   change the lockin...
3489
  		goto out4; /* loop, on the same file system  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3490
  	error = -EINVAL;
8c3ee42e8   Al Viro   [PATCH] get rid o...
3491
  	if (root.mnt->mnt_root != root.dentry)
b12cea919   Al Viro   change the lockin...
3492
  		goto out4; /* not a mountpoint */
676da58df   Al Viro   vfs: spread struc...
3493
  	if (!mnt_has_parent(root_mnt))
b12cea919   Al Viro   change the lockin...
3494
  		goto out4; /* not attached */
2d8f30380   Al Viro   [PATCH] sanitize ...
3495
  	if (new.mnt->mnt_root != new.dentry)
b12cea919   Al Viro   change the lockin...
3496
  		goto out4; /* not a mountpoint */
676da58df   Al Viro   vfs: spread struc...
3497
  	if (!mnt_has_parent(new_mnt))
b12cea919   Al Viro   change the lockin...
3498
  		goto out4; /* not attached */
4ac913785   Jan Blunck   Embed a struct pa...
3499
  	/* make sure we can reach put_old from new_root */
84d17192d   Al Viro   get rid of full-h...
3500
  	if (!is_path_reachable(old_mnt, old.dentry, &new))
b12cea919   Al Viro   change the lockin...
3501
  		goto out4;
0d0826019   Eric W. Biederman   mnt: Prevent pivo...
3502
3503
3504
  	/* make certain new is below the root */
  	if (!is_path_reachable(new_mnt, new.dentry, &root))
  		goto out4;
719ea2fbb   Al Viro   new helpers: lock...
3505
  	lock_mount_hash();
2763d1191   Al Viro   get rid of detach...
3506
3507
  	umount_mnt(new_mnt);
  	root_mp = unhash_mnt(root_mnt);  /* we'll need its mountpoint */
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
3508
3509
3510
3511
  	if (root_mnt->mnt.mnt_flags & MNT_LOCKED) {
  		new_mnt->mnt.mnt_flags |= MNT_LOCKED;
  		root_mnt->mnt.mnt_flags &= ~MNT_LOCKED;
  	}
4ac913785   Jan Blunck   Embed a struct pa...
3512
  	/* mount old root on put_old */
84d17192d   Al Viro   get rid of full-h...
3513
  	attach_mnt(root_mnt, old_mnt, old_mp);
4ac913785   Jan Blunck   Embed a struct pa...
3514
  	/* mount new_root on / */
2763d1191   Al Viro   get rid of detach...
3515
3516
  	attach_mnt(new_mnt, root_parent, root_mp);
  	mnt_add_count(root_parent, -1);
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3517
  	touch_mnt_namespace(current->nsproxy->mnt_ns);
4fed655c4   Eric W. Biederman   mnt: Clear mnt_ex...
3518
3519
  	/* A moved mount should not expire automatically */
  	list_del_init(&new_mnt->mnt_expire);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
3520
  	put_mountpoint(root_mp);
719ea2fbb   Al Viro   new helpers: lock...
3521
  	unlock_mount_hash();
2d8f30380   Al Viro   [PATCH] sanitize ...
3522
  	chroot_fs_refs(&root, &new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3523
  	error = 0;
b12cea919   Al Viro   change the lockin...
3524
  out4:
84d17192d   Al Viro   get rid of full-h...
3525
  	unlock_mount(old_mp);
2763d1191   Al Viro   get rid of detach...
3526
3527
  	if (!error)
  		mntput_no_expire(ex_parent);
b12cea919   Al Viro   change the lockin...
3528
  out3:
8c3ee42e8   Al Viro   [PATCH] get rid o...
3529
  	path_put(&root);
b12cea919   Al Viro   change the lockin...
3530
  out2:
2d8f30380   Al Viro   [PATCH] sanitize ...
3531
  	path_put(&old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3532
  out1:
2d8f30380   Al Viro   [PATCH] sanitize ...
3533
  	path_put(&new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3534
  out0:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3535
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3536
3537
3538
3539
3540
  }
  
  static void __init init_mount_tree(void)
  {
  	struct vfsmount *mnt;
74e831221   Al Viro   saner handling of...
3541
  	struct mount *m;
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3542
  	struct mnt_namespace *ns;
ac748a09f   Jan Blunck   Make set_fs_{root...
3543
  	struct path root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3544

fd3e007f6   Al Viro   don't bother with...
3545
  	mnt = vfs_kern_mount(&rootfs_fs_type, 0, "rootfs", NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3546
3547
  	if (IS_ERR(mnt))
  		panic("Can't create rootfs");
b3e19d924   Nick Piggin   fs: scale mntget/...
3548

74e831221   Al Viro   saner handling of...
3549
  	ns = alloc_mnt_ns(&init_user_ns, false);
3b22edc57   Trond Myklebust   VFS: Switch init_...
3550
  	if (IS_ERR(ns))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3551
  		panic("Can't allocate initial namespace");
74e831221   Al Viro   saner handling of...
3552
3553
3554
3555
3556
  	m = real_mount(mnt);
  	m->mnt_ns = ns;
  	ns->root = m;
  	ns->mounts = 1;
  	list_add(&m->mnt_list, &ns->list);
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3557
3558
  	init_task.nsproxy->mnt_ns = ns;
  	get_mnt_ns(ns);
be08d6d26   Al Viro   switch mnt_namesp...
3559
3560
  	root.mnt = mnt;
  	root.dentry = mnt->mnt_root;
da362b09e   Eric W. Biederman   umount: Do not al...
3561
  	mnt->mnt_flags |= MNT_LOCKED;
ac748a09f   Jan Blunck   Make set_fs_{root...
3562
3563
3564
  
  	set_fs_pwd(current->fs, &root);
  	set_fs_root(current->fs, &root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3565
  }
74bf17cff   Denis Cheng   fs: remove the un...
3566
  void __init mnt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3567
  {
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3568
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3569

7d6fec45a   Al Viro   vfs: start hiding...
3570
  	mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
20c2df83d   Paul Mundt   mm: Remove slab d...
3571
  			0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3572

0818bf27c   Al Viro   resizable namespa...
3573
  	mount_hashtable = alloc_large_system_hash("Mount-cache",
38129a13e   Al Viro   switch mnt_hash t...
3574
  				sizeof(struct hlist_head),
0818bf27c   Al Viro   resizable namespa...
3575
  				mhash_entries, 19,
3d375d785   Pavel Tatashin   mm: update caller...
3576
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3577
3578
3579
3580
  				&m_hash_shift, &m_hash_mask, 0, 0);
  	mountpoint_hashtable = alloc_large_system_hash("Mountpoint-cache",
  				sizeof(struct hlist_head),
  				mphash_entries, 19,
3d375d785   Pavel Tatashin   mm: update caller...
3581
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3582
  				&mp_hash_shift, &mp_hash_mask, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3583

84d17192d   Al Viro   get rid of full-h...
3584
  	if (!mount_hashtable || !mountpoint_hashtable)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3585
3586
  		panic("Failed to allocate mount hash table
  ");
4b93dc9b1   Tejun Heo   sysfs, kernfs: pr...
3587
  	kernfs_init();
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3588
3589
3590
3591
  	err = sysfs_init();
  	if (err)
  		printk(KERN_WARNING "%s: sysfs_init error: %d
  ",
8e24eea72   Harvey Harrison   fs: replace remai...
3592
  			__func__, err);
00d266662   Greg Kroah-Hartman   kobject: convert ...
3593
3594
  	fs_kobj = kobject_create_and_add("fs", NULL);
  	if (!fs_kobj)
8e24eea72   Harvey Harrison   fs: replace remai...
3595
3596
  		printk(KERN_WARNING "%s: kobj create error
  ", __func__);
037f11b47   Al Viro   mnt_init(): call ...
3597
  	shmem_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3598
3599
3600
  	init_rootfs();
  	init_mount_tree();
  }
616511d03   Trond Myklebust   VFS: Uninline the...
3601
  void put_mnt_ns(struct mnt_namespace *ns)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3602
  {
d498b25a4   Al Viro   get rid of useles...
3603
  	if (!atomic_dec_and_test(&ns->count))
616511d03   Trond Myklebust   VFS: Uninline the...
3604
  		return;
7b00ed6fe   Al Viro   put_mnt_ns(): use...
3605
  	drop_collected_mounts(&ns->root->mnt);
771b13716   Eric W. Biederman   vfs: Add a user n...
3606
  	free_mnt_ns(ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3607
  }
9d412a43c   Al Viro   vfs: split off vf...
3608

d911b4585   David Howells   vfs: Remove kern_...
3609
  struct vfsmount *kern_mount(struct file_system_type *type)
9d412a43c   Al Viro   vfs: split off vf...
3610
  {
423e0ab08   Tim Chen   VFS : mount lock ...
3611
  	struct vfsmount *mnt;
d911b4585   David Howells   vfs: Remove kern_...
3612
  	mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, NULL);
423e0ab08   Tim Chen   VFS : mount lock ...
3613
3614
3615
3616
3617
  	if (!IS_ERR(mnt)) {
  		/*
  		 * it is a longterm mount, don't release mnt until
  		 * we unmount before file sys is unregistered
  		*/
f7a99c5b7   Al Viro   get rid of ->mnt_...
3618
  		real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL;
423e0ab08   Tim Chen   VFS : mount lock ...
3619
3620
  	}
  	return mnt;
9d412a43c   Al Viro   vfs: split off vf...
3621
  }
d911b4585   David Howells   vfs: Remove kern_...
3622
  EXPORT_SYMBOL_GPL(kern_mount);
423e0ab08   Tim Chen   VFS : mount lock ...
3623
3624
3625
3626
3627
  
  void kern_unmount(struct vfsmount *mnt)
  {
  	/* release long term mount so mount point can be released */
  	if (!IS_ERR_OR_NULL(mnt)) {
f7a99c5b7   Al Viro   get rid of ->mnt_...
3628
  		real_mount(mnt)->mnt_ns = NULL;
48a066e72   Al Viro   RCU'd vfsmounts
3629
  		synchronize_rcu();	/* yecchhh... */
423e0ab08   Tim Chen   VFS : mount lock ...
3630
3631
3632
3633
  		mntput(mnt);
  	}
  }
  EXPORT_SYMBOL(kern_unmount);
02125a826   Al Viro   fix apparmor dere...
3634
3635
3636
  
  bool our_mnt(struct vfsmount *mnt)
  {
143c8c91c   Al Viro   vfs: mnt_ns moved...
3637
  	return check_mnt(real_mount(mnt));
02125a826   Al Viro   fix apparmor dere...
3638
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
3639

3151527ee   Eric W. Biederman   userns: Don't al...
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
  bool current_chrooted(void)
  {
  	/* Does the current process have a non-standard root */
  	struct path ns_root;
  	struct path fs_root;
  	bool chrooted;
  
  	/* Find the namespace root */
  	ns_root.mnt = &current->nsproxy->mnt_ns->root->mnt;
  	ns_root.dentry = ns_root.mnt->mnt_root;
  	path_get(&ns_root);
  	while (d_mountpoint(ns_root.dentry) && follow_down_one(&ns_root))
  		;
  
  	get_fs_root(current->fs, &fs_root);
  
  	chrooted = !path_equal(&fs_root, &ns_root);
  
  	path_put(&fs_root);
  	path_put(&ns_root);
  
  	return chrooted;
  }
132e46084   David Howells   new helper: do_ne...
3663
3664
  static bool mnt_already_visible(struct mnt_namespace *ns,
  				const struct super_block *sb,
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3665
  				int *new_mnt_flags)
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3666
  {
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3667
  	int new_flags = *new_mnt_flags;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3668
  	struct mount *mnt;
e51db7353   Eric W. Biederman   userns: Better re...
3669
  	bool visible = false;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3670

44bb4385c   Al Viro   fs_is_visible onl...
3671
  	down_read(&namespace_sem);
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3672
  	list_for_each_entry(mnt, &ns->list, mnt_list) {
e51db7353   Eric W. Biederman   userns: Better re...
3673
  		struct mount *child;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3674
  		int mnt_flags;
132e46084   David Howells   new helper: do_ne...
3675
  		if (mnt->mnt.mnt_sb->s_type != sb->s_type)
e51db7353   Eric W. Biederman   userns: Better re...
3676
  			continue;
7e96c1b0e   Eric W. Biederman   mnt: Fix fs_fully...
3677
3678
3679
3680
3681
  		/* This mount is not fully visible if it's root directory
  		 * is not the root directory of the filesystem.
  		 */
  		if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root)
  			continue;
a1935c173   Eric W. Biederman   mnt: Simplify mou...
3682
  		/* A local view of the mount flags */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3683
  		mnt_flags = mnt->mnt.mnt_flags;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3684

695e9df01   Eric W. Biederman   mnt: Account for ...
3685
  		/* Don't miss readonly hidden in the superblock flags */
bc98a42c1   David Howells   VFS: Convert sb->...
3686
  		if (sb_rdonly(mnt->mnt.mnt_sb))
695e9df01   Eric W. Biederman   mnt: Account for ...
3687
  			mnt_flags |= MNT_LOCK_READONLY;
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3688
3689
3690
  		/* Verify the mount flags are equal to or more permissive
  		 * than the proposed new mount.
  		 */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3691
  		if ((mnt_flags & MNT_LOCK_READONLY) &&
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3692
3693
  		    !(new_flags & MNT_READONLY))
  			continue;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3694
3695
  		if ((mnt_flags & MNT_LOCK_ATIME) &&
  		    ((mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3696
  			continue;
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3697
3698
3699
  		/* This mount is not fully visible if there are any
  		 * locked child mounts that cover anything except for
  		 * empty directories.
e51db7353   Eric W. Biederman   userns: Better re...
3700
3701
3702
  		 */
  		list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
  			struct inode *inode = child->mnt_mountpoint->d_inode;
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3703
  			/* Only worry about locked mounts */
d71ed6c93   Eric W. Biederman   mnt: fs_fully_vis...
3704
  			if (!(child->mnt.mnt_flags & MNT_LOCKED))
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3705
  				continue;
7236c85e1   Eric W. Biederman   mnt: Update fs_fu...
3706
3707
  			/* Is the directory permanetly empty? */
  			if (!is_empty_dir_inode(inode))
e51db7353   Eric W. Biederman   userns: Better re...
3708
  				goto next;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3709
  		}
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3710
  		/* Preserve the locked attributes */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3711
  		*new_mnt_flags |= mnt_flags & (MNT_LOCK_READONLY | \
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3712
  					       MNT_LOCK_ATIME);
e51db7353   Eric W. Biederman   userns: Better re...
3713
3714
3715
  		visible = true;
  		goto found;
  	next:	;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3716
  	}
e51db7353   Eric W. Biederman   userns: Better re...
3717
  found:
44bb4385c   Al Viro   fs_is_visible onl...
3718
  	up_read(&namespace_sem);
e51db7353   Eric W. Biederman   userns: Better re...
3719
  	return visible;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3720
  }
132e46084   David Howells   new helper: do_ne...
3721
  static bool mount_too_revealing(const struct super_block *sb, int *new_mnt_flags)
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3722
  {
a1935c173   Eric W. Biederman   mnt: Simplify mou...
3723
  	const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3724
3725
3726
3727
3728
3729
3730
  	struct mnt_namespace *ns = current->nsproxy->mnt_ns;
  	unsigned long s_iflags;
  
  	if (ns->user_ns == &init_user_ns)
  		return false;
  
  	/* Can this filesystem be too revealing? */
132e46084   David Howells   new helper: do_ne...
3731
  	s_iflags = sb->s_iflags;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3732
3733
  	if (!(s_iflags & SB_I_USERNS_VISIBLE))
  		return false;
a1935c173   Eric W. Biederman   mnt: Simplify mou...
3734
3735
3736
3737
3738
3739
  	if ((s_iflags & required_iflags) != required_iflags) {
  		WARN_ONCE(1, "Expected s_iflags to contain 0x%lx
  ",
  			  required_iflags);
  		return true;
  	}
132e46084   David Howells   new helper: do_ne...
3740
  	return !mnt_already_visible(ns, sb, new_mnt_flags);
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3741
  }
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
  bool mnt_may_suid(struct vfsmount *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(real_mount(mnt)) &&
  	       current_in_userns(mnt->mnt_sb->s_user_ns);
  }
64964528b   Al Viro   make proc_ns_oper...
3754
  static struct ns_common *mntns_get(struct task_struct *task)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3755
  {
58be28256   Al Viro   make mntns ->get(...
3756
  	struct ns_common *ns = NULL;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3757
  	struct nsproxy *nsproxy;
728dba3a3   Eric W. Biederman   namespaces: Use t...
3758
3759
  	task_lock(task);
  	nsproxy = task->nsproxy;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3760
  	if (nsproxy) {
58be28256   Al Viro   make mntns ->get(...
3761
3762
  		ns = &nsproxy->mnt_ns->ns;
  		get_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3763
  	}
728dba3a3   Eric W. Biederman   namespaces: Use t...
3764
  	task_unlock(task);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3765
3766
3767
  
  	return ns;
  }
64964528b   Al Viro   make proc_ns_oper...
3768
  static void mntns_put(struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3769
  {
58be28256   Al Viro   make mntns ->get(...
3770
  	put_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3771
  }
64964528b   Al Viro   make proc_ns_oper...
3772
  static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3773
3774
  {
  	struct fs_struct *fs = current->fs;
4f757f3cb   Al Viro   make sure that mn...
3775
  	struct mnt_namespace *mnt_ns = to_mnt_ns(ns), *old_mnt_ns;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3776
  	struct path root;
4f757f3cb   Al Viro   make sure that mn...
3777
  	int err;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3778

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3779
  	if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
c7b96acf1   Eric W. Biederman   userns: Kill nso...
3780
3781
  	    !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
  	    !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
ae11e0f18   Zhao Hongjiang   userns: fix retur...
3782
  		return -EPERM;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3783

74e831221   Al Viro   saner handling of...
3784
3785
  	if (is_anon_ns(mnt_ns))
  		return -EINVAL;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3786
3787
3788
3789
  	if (fs->users != 1)
  		return -EINVAL;
  
  	get_mnt_ns(mnt_ns);
4f757f3cb   Al Viro   make sure that mn...
3790
  	old_mnt_ns = nsproxy->mnt_ns;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3791
3792
3793
  	nsproxy->mnt_ns = mnt_ns;
  
  	/* Find the root */
4f757f3cb   Al Viro   make sure that mn...
3794
3795
3796
3797
3798
3799
3800
3801
  	err = vfs_path_lookup(mnt_ns->root->mnt.mnt_root, &mnt_ns->root->mnt,
  				"/", LOOKUP_DOWN, &root);
  	if (err) {
  		/* revert to old namespace */
  		nsproxy->mnt_ns = old_mnt_ns;
  		put_mnt_ns(mnt_ns);
  		return err;
  	}
8823c079b   Eric W. Biederman   vfs: Add setns su...
3802

4068367c9   Andrei Vagin   fs: don't forget ...
3803
  	put_mnt_ns(old_mnt_ns);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3804
3805
3806
3807
3808
3809
3810
  	/* Update the pwd and root */
  	set_fs_pwd(fs, &root);
  	set_fs_root(fs, &root);
  
  	path_put(&root);
  	return 0;
  }
bcac25a58   Andrey Vagin   kernel: add a hel...
3811
3812
3813
3814
  static struct user_namespace *mntns_owner(struct ns_common *ns)
  {
  	return to_mnt_ns(ns)->user_ns;
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
3815
3816
3817
3818
3819
3820
  const struct proc_ns_operations mntns_operations = {
  	.name		= "mnt",
  	.type		= CLONE_NEWNS,
  	.get		= mntns_get,
  	.put		= mntns_put,
  	.install	= mntns_install,
bcac25a58   Andrey Vagin   kernel: add a hel...
3821
  	.owner		= mntns_owner,
8823c079b   Eric W. Biederman   vfs: Add setns su...
3822
  };