Blame view

fs/namespace.c 84.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   *  linux/fs/namespace.c
   *
   * (C) Copyright Al Viro 2000, 2001
   *	Released under GPL v2.
   *
   * 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
22
  #include <linux/fs_struct.h>	/* get_fs_root et.al. */
  #include <linux/fsnotify.h>	/* fsnotify_vfsmount_delete */
  #include <linux/uaccess.h>
0bb80f240   David Howells   proc: Split the n...
23
  #include <linux/proc_ns.h>
20b4fb485   Linus Torvalds   Merge branch 'for...
24
  #include <linux/magic.h>
0818bf27c   Al Viro   resizable namespa...
25
  #include <linux/bootmem.h>
9ea459e11   Al Viro   delayed mntput
26
  #include <linux/task_work.h>
9164bb4a1   Ingo Molnar   sched/headers: Pr...
27
  #include <linux/sched/task.h>
07b20889e   Ram Pai   [PATCH] beginning...
28
  #include "pnode.h"
948730b0e   Adrian Bunk   fs/namespace.c sh...
29
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30

d29216842   Eric W. Biederman   mnt: Add a per mo...
31
32
  /* Maximum number of mounts in a mount namespace */
  unsigned int sysctl_mount_max __read_mostly = 100000;
0818bf27c   Al Viro   resizable namespa...
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  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...
57

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

38129a13e   Al Viro   switch mnt_hash t...
62
  static struct hlist_head *mount_hashtable __read_mostly;
0818bf27c   Al Viro   resizable namespa...
63
  static struct hlist_head *mountpoint_hashtable __read_mostly;
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
64
  static struct kmem_cache *mnt_cache __read_mostly;
59aa0da8e   Al Viro   initialize namesp...
65
  static DECLARE_RWSEM(namespace_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66

f87fd4c2a   Miklos Szeredi   [PATCH] add /sys/fs
67
  /* /sys/fs */
00d266662   Greg Kroah-Hartman   kobject: convert ...
68
69
  struct kobject *fs_kobj;
  EXPORT_SYMBOL_GPL(fs_kobj);
f87fd4c2a   Miklos Szeredi   [PATCH] add /sys/fs
70

99b7db7b8   Nick Piggin   fs: brlock vfsmou...
71
72
73
74
75
76
77
78
  /*
   * 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
79
  __cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
80

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

169b480e4   Matthew Wilcox   fs: Convert names...
115
116
117
118
  	if (res < 0)
  		return res;
  	mnt->mnt_group_id = res;
  	return 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
119
120
121
122
123
  }
  
  /*
   * Release a peer group ID
   */
4b8b21f4f   Al Viro   vfs: spread struc...
124
  void mnt_release_group_id(struct mount *mnt)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
125
  {
169b480e4   Matthew Wilcox   fs: Convert names...
126
  	ida_free(&mnt_group_ida, mnt->mnt_group_id);
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
127
  	mnt->mnt_group_id = 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
128
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
129
130
131
  /*
   * vfsmount lock must be held for read
   */
83adc7532   Al Viro   vfs: spread struc...
132
  static inline void mnt_add_count(struct mount *mnt, int n)
b3e19d924   Nick Piggin   fs: scale mntget/...
133
134
  {
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
135
  	this_cpu_add(mnt->mnt_pcp->mnt_count, n);
b3e19d924   Nick Piggin   fs: scale mntget/...
136
137
  #else
  	preempt_disable();
68e8a9fea   Al Viro   vfs: all counters...
138
  	mnt->mnt_count += n;
b3e19d924   Nick Piggin   fs: scale mntget/...
139
140
141
  	preempt_enable();
  #endif
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
142
143
144
  /*
   * vfsmount lock must be held for write
   */
83adc7532   Al Viro   vfs: spread struc...
145
  unsigned int mnt_get_count(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
146
147
  {
  #ifdef CONFIG_SMP
f03c65993   Al Viro   sanitize vfsmount...
148
  	unsigned int count = 0;
b3e19d924   Nick Piggin   fs: scale mntget/...
149
150
151
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
68e8a9fea   Al Viro   vfs: all counters...
152
  		count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count;
b3e19d924   Nick Piggin   fs: scale mntget/...
153
154
155
156
  	}
  
  	return count;
  #else
68e8a9fea   Al Viro   vfs: all counters...
157
  	return mnt->mnt_count;
b3e19d924   Nick Piggin   fs: scale mntget/...
158
159
  #endif
  }
87b95ce09   Al Viro   switch the IO-tri...
160
161
162
163
164
165
166
  static void drop_mountpoint(struct fs_pin *p)
  {
  	struct mount *m = container_of(p, struct mount, mnt_umount);
  	dput(m->mnt_ex_mountpoint);
  	pin_remove(p);
  	mntput(&m->mnt);
  }
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);
87b95ce09   Al Viro   switch the IO-tri...
200
  		init_fs_pin(&mnt->mnt_umount, drop_mountpoint);
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
233
234
  /*
   * __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.
   */
  int __mnt_is_readonly(struct vfsmount *mnt)
  {
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
235
236
  	if (mnt->mnt_flags & MNT_READONLY)
  		return 1;
bc98a42c1   David Howells   VFS: Convert sb->...
237
  	if (sb_rdonly(mnt->mnt_sb))
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
238
239
  		return 1;
  	return 0;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
240
241
  }
  EXPORT_SYMBOL_GPL(__mnt_is_readonly);
83adc7532   Al Viro   vfs: spread struc...
242
  static inline void mnt_inc_writers(struct mount *mnt)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
243
244
  {
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
245
  	this_cpu_inc(mnt->mnt_pcp->mnt_writers);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
246
  #else
68e8a9fea   Al Viro   vfs: all counters...
247
  	mnt->mnt_writers++;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
248
249
  #endif
  }
3d733633a   Dave Hansen   [PATCH] r/o bind ...
250

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

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

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
270
271
272
273
  	return count;
  #else
  	return mnt->mnt_writers;
  #endif
3d733633a   Dave Hansen   [PATCH] r/o bind ...
274
  }
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
275
276
277
278
279
280
281
282
  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 ...
283
  /*
eb04c2828   Jan Kara   fs: Add freezing ...
284
285
286
287
   * 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 ...
288
   */
8366025eb   Dave Hansen   [PATCH] r/o bind ...
289
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
290
   * __mnt_want_write - get write access to a mount without freeze protection
83adc7532   Al Viro   vfs: spread struc...
291
   * @m: the mount on which to take a write
8366025eb   Dave Hansen   [PATCH] r/o bind ...
292
   *
eb04c2828   Jan Kara   fs: Add freezing ...
293
294
295
296
297
   * 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 ...
298
   */
eb04c2828   Jan Kara   fs: Add freezing ...
299
  int __mnt_want_write(struct vfsmount *m)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
300
  {
83adc7532   Al Viro   vfs: spread struc...
301
  	struct mount *mnt = real_mount(m);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
302
  	int ret = 0;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
303

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
304
  	preempt_disable();
c6653a838   Nick Piggin   fs: rename vfsmou...
305
  	mnt_inc_writers(mnt);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
306
  	/*
c6653a838   Nick Piggin   fs: rename vfsmou...
307
  	 * The store to mnt_inc_writers must be visible before we pass
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
308
309
310
311
  	 * 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: ...
312
  	while (READ_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
313
314
315
316
317
318
319
  		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...
320
  	if (mnt_is_readonly(m)) {
c6653a838   Nick Piggin   fs: rename vfsmou...
321
  		mnt_dec_writers(mnt);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
322
  		ret = -EROFS;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
323
  	}
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
324
  	preempt_enable();
eb04c2828   Jan Kara   fs: Add freezing ...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  
  	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 ...
346
  	return ret;
8366025eb   Dave Hansen   [PATCH] r/o bind ...
347
348
349
350
  }
  EXPORT_SYMBOL_GPL(mnt_want_write);
  
  /**
96029c4e0   npiggin@suse.de   fs: introduce mnt...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
   * 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...
368
  	mnt_inc_writers(real_mount(mnt));
96029c4e0   npiggin@suse.de   fs: introduce mnt...
369
370
371
372
373
374
  	preempt_enable();
  	return 0;
  }
  EXPORT_SYMBOL_GPL(mnt_clone_write);
  
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
375
   * __mnt_want_write_file - get write access to a file's mount
96029c4e0   npiggin@suse.de   fs: introduce mnt...
376
377
   * @file: the file who's mount on which to take a write
   *
eb04c2828   Jan Kara   fs: Add freezing ...
378
   * This is like __mnt_want_write, but it takes a file and can
96029c4e0   npiggin@suse.de   fs: introduce mnt...
379
380
   * do some optimisations if the file is open for write already
   */
eb04c2828   Jan Kara   fs: Add freezing ...
381
  int __mnt_want_write_file(struct file *file)
96029c4e0   npiggin@suse.de   fs: introduce mnt...
382
  {
83f936c75   Al Viro   mark struct file ...
383
  	if (!(file->f_mode & FMODE_WRITER))
eb04c2828   Jan Kara   fs: Add freezing ...
384
  		return __mnt_want_write(file->f_path.mnt);
96029c4e0   npiggin@suse.de   fs: introduce mnt...
385
386
387
  	else
  		return mnt_clone_write(file->f_path.mnt);
  }
eb04c2828   Jan Kara   fs: Add freezing ...
388
389
  
  /**
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
390
391
392
393
394
   * 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 ...
395
396
397
398
   */
  int mnt_want_write_file(struct file *file)
  {
  	int ret;
a6795a585   Miklos Szeredi   vfs: fix freeze p...
399
  	sb_start_write(file_inode(file)->i_sb);
eb04c2828   Jan Kara   fs: Add freezing ...
400
401
  	ret = __mnt_want_write_file(file);
  	if (ret)
a6795a585   Miklos Szeredi   vfs: fix freeze p...
402
  		sb_end_write(file_inode(file)->i_sb);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
403
404
  	return ret;
  }
96029c4e0   npiggin@suse.de   fs: introduce mnt...
405
406
407
  EXPORT_SYMBOL_GPL(mnt_want_write_file);
  
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
408
   * __mnt_drop_write - give up write access to a mount
8366025eb   Dave Hansen   [PATCH] r/o bind ...
409
410
411
412
   * @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 ...
413
   * __mnt_want_write() call above.
8366025eb   Dave Hansen   [PATCH] r/o bind ...
414
   */
eb04c2828   Jan Kara   fs: Add freezing ...
415
  void __mnt_drop_write(struct vfsmount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
416
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
417
  	preempt_disable();
83adc7532   Al Viro   vfs: spread struc...
418
  	mnt_dec_writers(real_mount(mnt));
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
419
  	preempt_enable();
8366025eb   Dave Hansen   [PATCH] r/o bind ...
420
  }
eb04c2828   Jan Kara   fs: Add freezing ...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  
  /**
   * 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 ...
435
  EXPORT_SYMBOL_GPL(mnt_drop_write);
eb04c2828   Jan Kara   fs: Add freezing ...
436
437
438
439
  void __mnt_drop_write_file(struct file *file)
  {
  	__mnt_drop_write(file->f_path.mnt);
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
440
441
  void mnt_drop_write_file(struct file *file)
  {
a6795a585   Miklos Szeredi   vfs: fix freeze p...
442
  	__mnt_drop_write_file(file);
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
443
444
  	sb_end_write(file_inode(file)->i_sb);
  }
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
445
  EXPORT_SYMBOL(mnt_drop_write_file);
83adc7532   Al Viro   vfs: spread struc...
446
  static int mnt_make_readonly(struct mount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
447
  {
3d733633a   Dave Hansen   [PATCH] r/o bind ...
448
  	int ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
449
  	lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
450
  	mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
451
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
452
453
  	 * 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 ...
454
  	 */
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
455
  	smp_mb();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
456
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
  	 * 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 ...
471
  	 */
c6653a838   Nick Piggin   fs: rename vfsmou...
472
  	if (mnt_get_writers(mnt) > 0)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
473
474
  		ret = -EBUSY;
  	else
83adc7532   Al Viro   vfs: spread struc...
475
  		mnt->mnt.mnt_flags |= MNT_READONLY;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
476
477
478
479
480
  	/*
  	 * 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...
481
  	mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
719ea2fbb   Al Viro   new helpers: lock...
482
  	unlock_mount_hash();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
483
  	return ret;
8366025eb   Dave Hansen   [PATCH] r/o bind ...
484
  }
8366025eb   Dave Hansen   [PATCH] r/o bind ...
485

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

48a066e72   Al Viro   RCU'd vfsmounts
613
614
615
616
617
618
619
620
  	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...
621
  }
7af1364ff   Eric W. Biederman   vfs: Don't allow ...
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
653
654
655
  /*
   * __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...
656
  static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
84d17192d   Al Viro   get rid of full-h...
657
  {
0818bf27c   Al Viro   resizable namespa...
658
  	struct hlist_head *chain = mp_hash(dentry);
84d17192d   Al Viro   get rid of full-h...
659
  	struct mountpoint *mp;
0818bf27c   Al Viro   resizable namespa...
660
  	hlist_for_each_entry(mp, chain, m_hash) {
84d17192d   Al Viro   get rid of full-h...
661
  		if (mp->m_dentry == dentry) {
84d17192d   Al Viro   get rid of full-h...
662
663
664
665
  			mp->m_count++;
  			return mp;
  		}
  	}
e2dfa9354   Eric W. Biederman   vfs: factor out l...
666
667
  	return NULL;
  }
3895dbf89   Eric W. Biederman   mnt: Protect the ...
668
  static struct mountpoint *get_mountpoint(struct dentry *dentry)
e2dfa9354   Eric W. Biederman   vfs: factor out l...
669
  {
3895dbf89   Eric W. Biederman   mnt: Protect the ...
670
  	struct mountpoint *mp, *new = NULL;
e2dfa9354   Eric W. Biederman   vfs: factor out l...
671
  	int ret;
84d17192d   Al Viro   get rid of full-h...
672

3895dbf89   Eric W. Biederman   mnt: Protect the ...
673
  	if (d_mountpoint(dentry)) {
83eec9ad8   Benjamin Coddington   mnt: fix __detach...
674
675
676
  		/* might be worth a WARN_ON() */
  		if (d_unlinked(dentry))
  			return ERR_PTR(-ENOENT);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
677
678
679
680
681
682
683
684
685
686
687
  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...
688
  		return ERR_PTR(-ENOMEM);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
689
690
  
  	/* Exactly one processes may set d_mounted */
eed810076   Miklos Szeredi   vfs: check unlink...
691
  	ret = d_set_mounted(dentry);
eed810076   Miklos Szeredi   vfs: check unlink...
692

3895dbf89   Eric W. Biederman   mnt: Protect the ...
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
  	/* 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);
  	new->m_dentry = dentry;
  	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...
714
715
716
717
718
719
720
  	return mp;
  }
  
  static void put_mountpoint(struct mountpoint *mp)
  {
  	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);
0818bf27c   Al Viro   resizable namespa...
725
  		hlist_del(&mp->m_hash);
84d17192d   Al Viro   get rid of full-h...
726
727
728
  		kfree(mp);
  	}
  }
143c8c91c   Al Viro   vfs: mnt_ns moved...
729
  static inline int check_mnt(struct mount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
731
  	return mnt->mnt_ns == current->nsproxy->mnt_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
733
734
735
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
736
  static void touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
737
738
739
740
741
742
  {
  	if (ns) {
  		ns->event = ++event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
743
744
745
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
746
  static void __touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
747
748
749
750
751
752
  {
  	if (ns && ns->event != event) {
  		ns->event = event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
753
754
755
  /*
   * vfsmount lock must be held for write
   */
7bdb11de8   Eric W. Biederman   mnt: Factor out u...
756
  static void unhash_mnt(struct mount *mnt)
419148da6   Al Viro   vfs: spread struc...
757
  {
0714a5338   Al Viro   vfs: now it can b...
758
  	mnt->mnt_parent = mnt;
a73324da7   Al Viro   vfs: move mnt_mou...
759
  	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
6b41d536f   Al Viro   vfs: take mnt_chi...
760
  	list_del_init(&mnt->mnt_child);
38129a13e   Al Viro   switch mnt_hash t...
761
  	hlist_del_init_rcu(&mnt->mnt_hash);
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
762
  	hlist_del_init(&mnt->mnt_mp_list);
84d17192d   Al Viro   get rid of full-h...
763
764
  	put_mountpoint(mnt->mnt_mp);
  	mnt->mnt_mp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
766
767
768
  /*
   * vfsmount lock must be held for write
   */
7bdb11de8   Eric W. Biederman   mnt: Factor out u...
769
770
771
772
773
774
775
776
777
778
  static void detach_mnt(struct mount *mnt, struct path *old_path)
  {
  	old_path->dentry = mnt->mnt_mountpoint;
  	old_path->mnt = &mnt->mnt_parent->mnt;
  	unhash_mnt(mnt);
  }
  
  /*
   * vfsmount lock must be held for write
   */
6a46c5735   Eric W. Biederman   mnt: Factor umoun...
779
780
781
782
783
784
785
786
787
788
  static void umount_mnt(struct mount *mnt)
  {
  	/* old mountpoint will be dropped when we can do that */
  	mnt->mnt_ex_mountpoint = mnt->mnt_mountpoint;
  	unhash_mnt(mnt);
  }
  
  /*
   * vfsmount lock must be held for write
   */
84d17192d   Al Viro   get rid of full-h...
789
790
  void mnt_set_mountpoint(struct mount *mnt,
  			struct mountpoint *mp,
44d964d60   Al Viro   vfs: spread struc...
791
  			struct mount *child_mnt)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
792
  {
84d17192d   Al Viro   get rid of full-h...
793
  	mp->m_count++;
3a2393d71   Al Viro   vfs: opencode mnt...
794
  	mnt_add_count(mnt, 1);	/* essentially, that's mntget */
84d17192d   Al Viro   get rid of full-h...
795
  	child_mnt->mnt_mountpoint = dget(mp->m_dentry);
3a2393d71   Al Viro   vfs: opencode mnt...
796
  	child_mnt->mnt_parent = mnt;
84d17192d   Al Viro   get rid of full-h...
797
  	child_mnt->mnt_mp = mp;
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
798
  	hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
799
  }
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
800
801
802
803
804
805
  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...
806
807
808
  /*
   * vfsmount lock must be held for write
   */
84d17192d   Al Viro   get rid of full-h...
809
810
811
  static void attach_mnt(struct mount *mnt,
  			struct mount *parent,
  			struct mountpoint *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
  {
84d17192d   Al Viro   get rid of full-h...
813
  	mnt_set_mountpoint(parent, mp, mnt);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
814
  	__attach_mnt(mnt, parent);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
815
  }
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
816
  void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct mount *mnt)
12a5b5294   Al Viro   fix copy_tree() r...
817
  {
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
  	struct mountpoint *old_mp = mnt->mnt_mp;
  	struct dentry *old_mountpoint = mnt->mnt_mountpoint;
  	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);
  
  	/*
  	 * Safely avoid even the suggestion this code might sleep or
  	 * lock the mount hash by taking advantage of the knowledge that
  	 * mnt_change_mountpoint will not release the final reference
  	 * to a mountpoint.
  	 *
  	 * During mounting, the mount passed in as the parent mount will
  	 * continue to use the old mountpoint and during unmounting, the
  	 * old mountpoint will continue to exist until namespace_unlock,
  	 * which happens well after mnt_change_mountpoint.
  	 */
  	spin_lock(&old_mountpoint->d_lock);
  	old_mountpoint->d_lockref.count--;
  	spin_unlock(&old_mountpoint->d_lock);
  
  	mnt_add_count(old_parent, -1);
12a5b5294   Al Viro   fix copy_tree() r...
846
  }
b90fa9ae8   Ram Pai   [PATCH] shared mo...
847
  /*
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
848
   * vfsmount lock must be held for write
b90fa9ae8   Ram Pai   [PATCH] shared mo...
849
   */
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
850
  static void commit_tree(struct mount *mnt)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
851
  {
0714a5338   Al Viro   vfs: now it can b...
852
  	struct mount *parent = mnt->mnt_parent;
83adc7532   Al Viro   vfs: spread struc...
853
  	struct mount *m;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
854
  	LIST_HEAD(head);
143c8c91c   Al Viro   vfs: mnt_ns moved...
855
  	struct mnt_namespace *n = parent->mnt_ns;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
856

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

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

b90fa9ae8   Ram Pai   [PATCH] shared mo...
863
  	list_splice(&head, n->list.prev);
d29216842   Eric W. Biederman   mnt: Add a per mo...
864
865
  	n->mounts += n->pending_mounts;
  	n->pending_mounts = 0;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
866
  	__attach_mnt(mnt, parent);
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
867
  	touch_mnt_namespace(n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  }
909b0a88e   Al Viro   vfs: spread struc...
869
  static struct mount *next_mnt(struct mount *p, struct mount *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870
  {
6b41d536f   Al Viro   vfs: take mnt_chi...
871
872
  	struct list_head *next = p->mnt_mounts.next;
  	if (next == &p->mnt_mounts) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
  		while (1) {
909b0a88e   Al Viro   vfs: spread struc...
874
  			if (p == root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
  				return NULL;
6b41d536f   Al Viro   vfs: take mnt_chi...
876
877
  			next = p->mnt_child.next;
  			if (next != &p->mnt_parent->mnt_mounts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
  				break;
0714a5338   Al Viro   vfs: now it can b...
879
  			p = p->mnt_parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
  		}
  	}
6b41d536f   Al Viro   vfs: take mnt_chi...
882
  	return list_entry(next, struct mount, mnt_child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
  }
315fc83e5   Al Viro   vfs: spread struc...
884
  static struct mount *skip_mnt_tree(struct mount *p)
9676f0c63   Ram Pai   [PATCH] unbindabl...
885
  {
6b41d536f   Al Viro   vfs: take mnt_chi...
886
887
888
889
  	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...
890
891
892
  	}
  	return p;
  }
9d412a43c   Al Viro   vfs: split off vf...
893
894
895
  struct vfsmount *
  vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
  {
b105e270b   Al Viro   vfs: spread struc...
896
  	struct mount *mnt;
9d412a43c   Al Viro   vfs: split off vf...
897
898
899
900
901
902
903
904
  	struct dentry *root;
  
  	if (!type)
  		return ERR_PTR(-ENODEV);
  
  	mnt = alloc_vfsmnt(name);
  	if (!mnt)
  		return ERR_PTR(-ENOMEM);
e462ec50c   David Howells   VFS: Differentiat...
905
  	if (flags & SB_KERNMOUNT)
b105e270b   Al Viro   vfs: spread struc...
906
  		mnt->mnt.mnt_flags = MNT_INTERNAL;
9d412a43c   Al Viro   vfs: split off vf...
907
908
909
  
  	root = mount_fs(type, flags, name, data);
  	if (IS_ERR(root)) {
8ffcb32e0   David Howells   VFS: Make delayed...
910
  		mnt_free_id(mnt);
9d412a43c   Al Viro   vfs: split off vf...
911
912
913
  		free_vfsmnt(mnt);
  		return ERR_CAST(root);
  	}
b105e270b   Al Viro   vfs: spread struc...
914
915
  	mnt->mnt.mnt_root = root;
  	mnt->mnt.mnt_sb = root->d_sb;
a73324da7   Al Viro   vfs: move mnt_mou...
916
  	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
0714a5338   Al Viro   vfs: now it can b...
917
  	mnt->mnt_parent = mnt;
719ea2fbb   Al Viro   new helpers: lock...
918
  	lock_mount_hash();
39f7c4db1   Miklos Szeredi   vfs: keep list of...
919
  	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
719ea2fbb   Al Viro   new helpers: lock...
920
  	unlock_mount_hash();
b105e270b   Al Viro   vfs: spread struc...
921
  	return &mnt->mnt;
9d412a43c   Al Viro   vfs: split off vf...
922
923
  }
  EXPORT_SYMBOL_GPL(vfs_kern_mount);
93faccbbf   Eric W. Biederman   fs: Better permis...
924
925
926
927
928
929
930
931
932
933
  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...
934
  	return vfs_kern_mount(type, SB_SUBMOUNT, name, data);
93faccbbf   Eric W. Biederman   fs: Better permis...
935
936
  }
  EXPORT_SYMBOL_GPL(vfs_submount);
87129cc0e   Al Viro   vfs: spread struc...
937
  static struct mount *clone_mnt(struct mount *old, struct dentry *root,
36341f645   Ram Pai   [PATCH] mount exp...
938
  					int flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  {
87129cc0e   Al Viro   vfs: spread struc...
940
  	struct super_block *sb = old->mnt.mnt_sb;
be34d1a3b   David Howells   VFS: Make clone_m...
941
942
  	struct mount *mnt;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943

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

7a472ef4b   Eric W. Biederman   vfs: Only support...
948
  	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
be34d1a3b   David Howells   VFS: Make clone_m...
949
950
951
  		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...
952

be34d1a3b   David Howells   VFS: Make clone_m...
953
954
955
956
  	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
957
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
958

16a34adb9   Al Viro   Don't leak MNT_IN...
959
960
  	mnt->mnt.mnt_flags = old->mnt.mnt_flags;
  	mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL);
132c94e31   Eric W. Biederman   vfs: Carefully pr...
961
  	/* Don't allow unprivileged users to change mount flags */
9566d6742   Eric W. Biederman   mnt: Correct perm...
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
  	if (flag & CL_UNPRIVILEGED) {
  		mnt->mnt.mnt_flags |= MNT_LOCK_ATIME;
  
  		if (mnt->mnt.mnt_flags & MNT_READONLY)
  			mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
  
  		if (mnt->mnt.mnt_flags & MNT_NODEV)
  			mnt->mnt.mnt_flags |= MNT_LOCK_NODEV;
  
  		if (mnt->mnt.mnt_flags & MNT_NOSUID)
  			mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID;
  
  		if (mnt->mnt.mnt_flags & MNT_NOEXEC)
  			mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC;
  	}
132c94e31   Eric W. Biederman   vfs: Carefully pr...
977

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
978
  	/* Don't allow unprivileged users to reveal what is under a mount */
381cacb12   Eric W. Biederman   mnt: Carefully se...
979
980
  	if ((flag & CL_UNPRIVILEGED) &&
  	    (!(flag & CL_EXPIRE) || list_empty(&old->mnt_expire)))
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
981
  		mnt->mnt.mnt_flags |= MNT_LOCKED;
be34d1a3b   David Howells   VFS: Make clone_m...
982
983
984
985
986
  	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...
987
  	lock_mount_hash();
be34d1a3b   David Howells   VFS: Make clone_m...
988
  	list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
719ea2fbb   Al Viro   new helpers: lock...
989
  	unlock_mount_hash();
be34d1a3b   David Howells   VFS: Make clone_m...
990

7a472ef4b   Eric W. Biederman   vfs: Only support...
991
992
  	if ((flag & CL_SLAVE) ||
  	    ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
be34d1a3b   David Howells   VFS: Make clone_m...
993
994
995
996
997
998
999
1000
1001
  		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...
1002
1003
  	} else {
  		CLEAR_MNT_SHARED(mnt);
be34d1a3b   David Howells   VFS: Make clone_m...
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
  	}
  	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...
1014
  	return mnt;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1015
1016
  
   out_free:
8ffcb32e0   David Howells   VFS: Make delayed...
1017
  	mnt_free_id(mnt);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1018
  	free_vfsmnt(mnt);
be34d1a3b   David Howells   VFS: Make clone_m...
1019
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
  }
9ea459e11   Al Viro   delayed mntput
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
  static void cleanup_mnt(struct mount *mnt)
  {
  	/*
  	 * This 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.
  	 */
  	/*
  	 * 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);
  	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'...
1052
  	struct mount *m, *t;
9ea459e11   Al Viro   delayed mntput
1053

297857357   Byungchul Park   namespace.c: Don'...
1054
1055
  	llist_for_each_entry_safe(m, t, node, mnt_llist)
  		cleanup_mnt(m);
9ea459e11   Al Viro   delayed mntput
1056
1057
  }
  static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
900148dca   Al Viro   vfs: spread struc...
1058
  static void mntput_no_expire(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
1059
  {
48a066e72   Al Viro   RCU'd vfsmounts
1060
  	rcu_read_lock();
9ea0a46ca   Al Viro   fix mntput/mntput...
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
  	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
1072
  		rcu_read_unlock();
f03c65993   Al Viro   sanitize vfsmount...
1073
  		return;
b3e19d924   Nick Piggin   fs: scale mntget/...
1074
  	}
719ea2fbb   Al Viro   new helpers: lock...
1075
  	lock_mount_hash();
119e1ef80   Al Viro   fix __legitimize_...
1076
1077
1078
1079
1080
  	/*
  	 * 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...
1081
  	mnt_add_count(mnt, -1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1082
  	if (mnt_get_count(mnt)) {
48a066e72   Al Viro   RCU'd vfsmounts
1083
  		rcu_read_unlock();
719ea2fbb   Al Viro   new helpers: lock...
1084
  		unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1085
1086
  		return;
  	}
48a066e72   Al Viro   RCU'd vfsmounts
1087
1088
1089
1090
1091
1092
1093
  	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: ...
1094

39f7c4db1   Miklos Szeredi   vfs: keep list of...
1095
  	list_del(&mnt->mnt_instance);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1096
1097
1098
1099
1100
1101
1102
  
  	if (unlikely(!list_empty(&mnt->mnt_mounts))) {
  		struct mount *p, *tmp;
  		list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts,  mnt_child) {
  			umount_mnt(p);
  		}
  	}
719ea2fbb   Al Viro   new helpers: lock...
1103
  	unlock_mount_hash();
649a795af   Al Viro   fold mntfree() in...
1104

9ea459e11   Al Viro   delayed mntput
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
  	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/...
1117
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
1118
1119
1120
1121
  
  void mntput(struct vfsmount *mnt)
  {
  	if (mnt) {
863d684f9   Al Viro   vfs: move the res...
1122
  		struct mount *m = real_mount(mnt);
b3e19d924   Nick Piggin   fs: scale mntget/...
1123
  		/* avoid cacheline pingpong, hope gcc doesn't get "smart" */
863d684f9   Al Viro   vfs: move the res...
1124
1125
1126
  		if (unlikely(m->mnt_expiry_mark))
  			m->mnt_expiry_mark = 0;
  		mntput_no_expire(m);
b3e19d924   Nick Piggin   fs: scale mntget/...
1127
1128
1129
1130
1131
1132
1133
  	}
  }
  EXPORT_SYMBOL(mntput);
  
  struct vfsmount *mntget(struct vfsmount *mnt)
  {
  	if (mnt)
83adc7532   Al Viro   vfs: spread struc...
1134
  		mnt_add_count(real_mount(mnt), 1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1135
1136
1137
  	return mnt;
  }
  EXPORT_SYMBOL(mntget);
c6609c0a1   Ian Kent   vfs: add path_is_...
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  /* 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...
1166
  struct vfsmount *mnt_clone_internal(const struct path *path)
7b7b1ace2   Al Viro   [PATCH] saner han...
1167
  {
3064c3563   Al Viro   death to mnt_pinned
1168
1169
1170
1171
1172
1173
  	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...
1174
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175

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

390c68436   Ram Pai   [PATCH] making na...
1182
  	down_read(&namespace_sem);
c7999c362   Al Viro   reduce m_start() ...
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
  	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
1197
1198
1199
1200
  }
  
  static void *m_next(struct seq_file *m, void *v, loff_t *pos)
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1201
  	struct proc_mounts *p = m->private;
b0765fb85   Pavel Emelianov   Make /proc/self/m...
1202

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
1228
1229
1230
1231
1232
1233
  /**
   * 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...
1234
  int may_umount_tree(struct vfsmount *m)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  {
909b0a88e   Al Viro   vfs: spread struc...
1236
  	struct mount *mnt = real_mount(m);
36341f645   Ram Pai   [PATCH] mount exp...
1237
1238
  	int actual_refs = 0;
  	int minimum_refs = 0;
315fc83e5   Al Viro   vfs: spread struc...
1239
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
1240
  	BUG_ON(!m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241

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

e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1253
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
  }
  
  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: ...
1273
  	int ret = 1;
8ad08d8a0   Al Viro   may_umount() need...
1274
  	down_read(&namespace_sem);
719ea2fbb   Al Viro   new helpers: lock...
1275
  	lock_mount_hash();
1ab597386   Al Viro   vfs: spread struc...
1276
  	if (propagate_mount_busy(real_mount(mnt), 2))
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1277
  		ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
1278
  	unlock_mount_hash();
8ad08d8a0   Al Viro   may_umount() need...
1279
  	up_read(&namespace_sem);
a05964f39   Ram Pai   [PATCH] shared mo...
1280
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
1282
1283
  }
  
  EXPORT_SYMBOL(may_umount);
38129a13e   Al Viro   switch mnt_hash t...
1284
  static HLIST_HEAD(unmounted);	/* protected by namespace_sem */
e3197d83d   Al Viro   saner umount_tree...
1285

97216be09   Al Viro   fold release_moun...
1286
  static void namespace_unlock(void)
70fbcdf4d   Ram Pai   [PATCH] umount_tr...
1287
  {
a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1288
  	struct hlist_head head;
97216be09   Al Viro   fold release_moun...
1289

a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1290
  	hlist_move_list(&unmounted, &head);
97216be09   Al Viro   fold release_moun...
1291

97216be09   Al Viro   fold release_moun...
1292
  	up_write(&namespace_sem);
a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1293
1294
  	if (likely(hlist_empty(&head)))
  		return;
48a066e72   Al Viro   RCU'd vfsmounts
1295
  	synchronize_rcu();
87b95ce09   Al Viro   switch the IO-tri...
1296
  	group_pin_kill(&head);
70fbcdf4d   Ram Pai   [PATCH] umount_tr...
1297
  }
97216be09   Al Viro   fold release_moun...
1298
  static inline void namespace_lock(void)
e3197d83d   Al Viro   saner umount_tree...
1299
  {
97216be09   Al Viro   fold release_moun...
1300
  	down_write(&namespace_sem);
e3197d83d   Al Viro   saner umount_tree...
1301
  }
e819f1521   Eric W. Biederman   mnt: Improve the ...
1302
1303
1304
  enum umount_tree_flags {
  	UMOUNT_SYNC = 1,
  	UMOUNT_PROPAGATE = 2,
e0c9c0afd   Eric W. Biederman   mnt: Update detac...
1305
  	UMOUNT_CONNECTED = 4,
e819f1521   Eric W. Biederman   mnt: Improve the ...
1306
  };
f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
  
  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...
1336
  /*
48a066e72   Al Viro   RCU'd vfsmounts
1337
   * mount_lock must be held
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1338
1339
   * namespace_sem must be held for write
   */
e819f1521   Eric W. Biederman   mnt: Improve the ...
1340
  static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
  {
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1342
  	LIST_HEAD(tmp_list);
315fc83e5   Al Viro   vfs: spread struc...
1343
  	struct mount *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344

5d88457eb   Eric W. Biederman   mnt: On an unmoun...
1345
1346
  	if (how & UMOUNT_PROPAGATE)
  		propagate_mount_unlock(mnt);
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1347
  	/* Gather the mounts to umount */
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1348
1349
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
  		p->mnt.mnt_flags |= MNT_UMOUNT;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1350
  		list_move(&p->mnt_list, &tmp_list);
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1351
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352

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

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

c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1362
  	while (!list_empty(&tmp_list)) {
d29216842   Eric W. Biederman   mnt: Add a per mo...
1363
  		struct mnt_namespace *ns;
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1364
  		bool disconnect;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1365
  		p = list_first_entry(&tmp_list, struct mount, mnt_list);
6776db3d3   Al Viro   vfs: take mnt_sha...
1366
  		list_del_init(&p->mnt_expire);
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1367
  		list_del_init(&p->mnt_list);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1368
1369
1370
1371
1372
  		ns = p->mnt_ns;
  		if (ns) {
  			ns->mounts--;
  			__touch_mnt_namespace(ns);
  		}
143c8c91c   Al Viro   vfs: mnt_ns moved...
1373
  		p->mnt_ns = NULL;
e819f1521   Eric W. Biederman   mnt: Improve the ...
1374
  		if (how & UMOUNT_SYNC)
48a066e72   Al Viro   RCU'd vfsmounts
1375
  			p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
87b95ce09   Al Viro   switch the IO-tri...
1376

f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1377
  		disconnect = disconnect_mount(p, how);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1378
1379
1380
  
  		pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
  				 disconnect ? &unmounted : NULL);
676da58df   Al Viro   vfs: spread struc...
1381
  		if (mnt_has_parent(p)) {
81b6b0619   Al Viro   fix EBUSY on umou...
1382
  			mnt_add_count(p->mnt_parent, -1);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1383
1384
1385
1386
1387
1388
  			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...
1389
  		}
0f0afb1dc   Al Viro   vfs: spread struc...
1390
  		change_mnt_propagation(p, MS_PRIVATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
1392
  	}
  }
b54b9be78   Al Viro   get rid of the se...
1393
  static void shrink_submounts(struct mount *mnt);
c35038bec   Al Viro   [PATCH] do shrink...
1394

1ab597386   Al Viro   vfs: spread struc...
1395
  static int do_umount(struct mount *mnt, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
  {
1ab597386   Al Viro   vfs: spread struc...
1397
  	struct super_block *sb = mnt->mnt.mnt_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
  	int retval;
1ab597386   Al Viro   vfs: spread struc...
1399
  	retval = security_sb_umount(&mnt->mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
  	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...
1410
  		if (&mnt->mnt == current->fs->root.mnt ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
1412
  		    flags & (MNT_FORCE | MNT_DETACH))
  			return -EINVAL;
b3e19d924   Nick Piggin   fs: scale mntget/...
1413
1414
1415
1416
  		/*
  		 * 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...
1417
  		lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
1418
  		if (mnt_get_count(mnt) != 2) {
719ea2fbb   Al Viro   new helpers: lock...
1419
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1420
  			return -EBUSY;
b3e19d924   Nick Piggin   fs: scale mntget/...
1421
  		}
719ea2fbb   Al Viro   new helpers: lock...
1422
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1423

863d684f9   Al Viro   vfs: move the res...
1424
  		if (!xchg(&mnt->mnt_expiry_mark, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
  			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...
1437
  	if (flags & MNT_FORCE && sb->s_op->umount_begin) {
42faad996   Al Viro   [PATCH] restore s...
1438
  		sb->s_op->umount_begin(sb);
42faad996   Al Viro   [PATCH] restore s...
1439
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
  
  	/*
  	 * 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...
1450
  	if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1451
1452
1453
1454
  		/*
  		 * Special case for "unmounting" root ...
  		 * we just try to remount it readonly.
  		 */
bc6155d13   Eric W. Biederman   fs: Allow superbl...
1455
  		if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
a1480dcc3   Andy Lutomirski   fs: Add a missing...
1456
  			return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
  		down_write(&sb->s_umount);
bc98a42c1   David Howells   VFS: Convert sb->...
1458
  		if (!sb_rdonly(sb))
e462ec50c   David Howells   VFS: Differentiat...
1459
  			retval = do_remount_sb(sb, SB_RDONLY, NULL, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
1462
  		up_write(&sb->s_umount);
  		return retval;
  	}
97216be09   Al Viro   fold release_moun...
1463
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1464
  	lock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465

32224b874   Eric W. Biederman   mount: Retest MNT...
1466
1467
1468
1469
1470
1471
  	/* 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
1472
  	if (flags & MNT_DETACH) {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1473
  		if (!list_empty(&mnt->mnt_list))
e819f1521   Eric W. Biederman   mnt: Improve the ...
1474
  			umount_tree(mnt, UMOUNT_PROPAGATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
  		retval = 0;
48a066e72   Al Viro   RCU'd vfsmounts
1476
1477
1478
1479
1480
  	} 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 ...
1481
  				umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
48a066e72   Al Viro   RCU'd vfsmounts
1482
1483
  			retval = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
  	}
32224b874   Eric W. Biederman   mount: Retest MNT...
1485
  out:
719ea2fbb   Al Viro   new helpers: lock...
1486
  	unlock_mount_hash();
e3197d83d   Al Viro   saner umount_tree...
1487
  	namespace_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
1489
  	return retval;
  }
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
  /*
   * __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 ...
1506
  	lock_mount_hash();
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1507
  	mp = lookup_mountpoint(dentry);
f53e57975   Eric W. Biederman   mnt: Fix the erro...
1508
  	if (IS_ERR_OR_NULL(mp))
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1509
  		goto out_unlock;
e06b933e6   Andrey Ulanov   namespace: update...
1510
  	event++;
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1511
1512
  	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...
1513
  		if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
fe78fcc85   Eric W. Biederman   mnt: In detach_mo...
1514
1515
  			hlist_add_head(&mnt->mnt_umount.s_list, &unmounted);
  			umount_mnt(mnt);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1516
  		}
e0c9c0afd   Eric W. Biederman   mnt: Update detac...
1517
  		else umount_tree(mnt, UMOUNT_CONNECTED);
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1518
  	}
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1519
1520
  	put_mountpoint(mp);
  out_unlock:
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1521
  	unlock_mount_hash();
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1522
1523
  	namespace_unlock();
  }
dd111b31e   David Howells   VFS: Clean up whi...
1524
  /*
9b40bc90a   Al Viro   get rid of unprot...
1525
1526
1527
1528
1529
1530
   * 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);
  }
9e8925b67   Jeff Layton   locks: Allow disa...
1531
1532
1533
1534
1535
  static inline bool may_mandlock(void)
  {
  #ifndef	CONFIG_MANDATORY_FILE_LOCKING
  	return false;
  #endif
95ace7541   Eric W. Biederman   locks: Don't allo...
1536
  	return capable(CAP_SYS_ADMIN);
9e8925b67   Jeff Layton   locks: Allow disa...
1537
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
1539
1540
1541
1542
1543
1544
  /*
   * 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...
1545
  int ksys_umount(char __user *name, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1546
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
1547
  	struct path path;
900148dca   Al Viro   vfs: spread struc...
1548
  	struct mount *mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
  	int retval;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1550
  	int lookup_flags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1551

db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1552
1553
  	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
  		return -EINVAL;
9b40bc90a   Al Viro   get rid of unprot...
1554
1555
  	if (!may_mount())
  		return -EPERM;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1556
1557
  	if (!(flags & UMOUNT_NOFOLLOW))
  		lookup_flags |= LOOKUP_FOLLOW;
197df04c7   Al Viro   rename user_path_...
1558
  	retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1559
1560
  	if (retval)
  		goto out;
900148dca   Al Viro   vfs: spread struc...
1561
  	mnt = real_mount(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1562
  	retval = -EINVAL;
2d8f30380   Al Viro   [PATCH] sanitize ...
1563
  	if (path.dentry != path.mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1564
  		goto dput_and_out;
143c8c91c   Al Viro   vfs: mnt_ns moved...
1565
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1566
  		goto dput_and_out;
32224b874   Eric W. Biederman   mount: Retest MNT...
1567
  	if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
1568
  		goto dput_and_out;
b2f5d4dc3   Eric W. Biederman   umount: Disallow ...
1569
1570
1571
  	retval = -EPERM;
  	if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
  		goto dput_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572

900148dca   Al Viro   vfs: spread struc...
1573
  	retval = do_umount(mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1574
  dput_and_out:
429731b15   Jan Blunck   Remove path_relea...
1575
  	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
2d8f30380   Al Viro   [PATCH] sanitize ...
1576
  	dput(path.dentry);
900148dca   Al Viro   vfs: spread struc...
1577
  	mntput_no_expire(mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1578
1579
1580
  out:
  	return retval;
  }
3a18ef5c1   Dominik Brodowski   fs: add ksys_umou...
1581
1582
1583
1584
  SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
  {
  	return ksys_umount(name, flags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585
1586
1587
  #ifdef __ARCH_WANT_SYS_OLDUMOUNT
  
  /*
b58fed8b1   Ram Pai   [PATCH] lindent f...
1588
   *	The 2.0 compatible umount. No flags.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
   */
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
1590
  SYSCALL_DEFINE1(oldumount, char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
  {
3a18ef5c1   Dominik Brodowski   fs: add ksys_umou...
1592
  	return ksys_umount(name, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
1594
1595
  }
  
  #endif
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1596
  static bool is_mnt_ns_file(struct dentry *dentry)
8823c079b   Eric W. Biederman   vfs: Add setns su...
1597
  {
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1598
  	/* Is this a proxy for a mount namespace? */
e149ed2b8   Al Viro   take the targets ...
1599
1600
  	return dentry->d_op == &ns_dentry_operations &&
  	       dentry->d_fsdata == &mntns_operations;
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1601
  }
58be28256   Al Viro   make mntns ->get(...
1602
1603
1604
1605
  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...
1606
1607
1608
1609
1610
1611
1612
1613
  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_...
1614
  	mnt_ns = to_mnt_ns(get_proc_ns(dentry->d_inode));
8823c079b   Eric W. Biederman   vfs: Add setns su...
1615
1616
  	return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
  }
87129cc0e   Al Viro   vfs: spread struc...
1617
  struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
36341f645   Ram Pai   [PATCH] mount exp...
1618
  					int flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
  {
84d17192d   Al Viro   get rid of full-h...
1620
  	struct mount *res, *p, *q, *r, *parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1621

4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1622
1623
1624
1625
  	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...
1626
  		return ERR_PTR(-EINVAL);
9676f0c63   Ram Pai   [PATCH] unbindabl...
1627

36341f645   Ram Pai   [PATCH] mount exp...
1628
  	res = q = clone_mnt(mnt, dentry, flag);
be34d1a3b   David Howells   VFS: Make clone_m...
1629
1630
  	if (IS_ERR(q))
  		return q;
a73324da7   Al Viro   vfs: move mnt_mou...
1631
  	q->mnt_mountpoint = mnt->mnt_mountpoint;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632
1633
  
  	p = mnt;
6b41d536f   Al Viro   vfs: take mnt_chi...
1634
  	list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
315fc83e5   Al Viro   vfs: spread struc...
1635
  		struct mount *s;
7ec02ef15   Jan Blunck   vfs: remove lives...
1636
  		if (!is_subdir(r->mnt_mountpoint, dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1637
  			continue;
909b0a88e   Al Viro   vfs: spread struc...
1638
  		for (s = r; s; s = next_mnt(s, r)) {
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1639
1640
  			if (!(flag & CL_COPY_UNBINDABLE) &&
  			    IS_MNT_UNBINDABLE(s)) {
14e4bec18   Eric W. Biederman   mount: Don't allo...
1641
1642
1643
1644
1645
1646
1647
1648
  				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...
1649
1650
1651
  			}
  			if (!(flag & CL_COPY_MNT_NS_FILE) &&
  			    is_mnt_ns_file(s->mnt.mnt_root)) {
9676f0c63   Ram Pai   [PATCH] unbindabl...
1652
1653
1654
  				s = skip_mnt_tree(s);
  				continue;
  			}
0714a5338   Al Viro   vfs: now it can b...
1655
1656
1657
  			while (p != s->mnt_parent) {
  				p = p->mnt_parent;
  				q = q->mnt_parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1658
  			}
87129cc0e   Al Viro   vfs: spread struc...
1659
  			p = s;
84d17192d   Al Viro   get rid of full-h...
1660
  			parent = q;
87129cc0e   Al Viro   vfs: spread struc...
1661
  			q = clone_mnt(p, p->mnt.mnt_root, flag);
be34d1a3b   David Howells   VFS: Make clone_m...
1662
1663
  			if (IS_ERR(q))
  				goto out;
719ea2fbb   Al Viro   new helpers: lock...
1664
  			lock_mount_hash();
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1665
  			list_add_tail(&q->mnt_list, &res->mnt_list);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1666
  			attach_mnt(q, parent, p->mnt_mp);
719ea2fbb   Al Viro   new helpers: lock...
1667
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668
1669
1670
  		}
  	}
  	return res;
be34d1a3b   David Howells   VFS: Make clone_m...
1671
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
  	if (res) {
719ea2fbb   Al Viro   new helpers: lock...
1673
  		lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
1674
  		umount_tree(res, UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
1675
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
1677
  	return q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
  }
be34d1a3b   David Howells   VFS: Make clone_m...
1679
  /* Caller should check returned pointer for errors */
ca71cf71e   Al Viro   namespace.c: cons...
1680
  struct vfsmount *collect_mounts(const struct path *path)
8aec08094   Al Viro   [PATCH] new helpe...
1681
  {
cb338d06e   Al Viro   vfs: spread struc...
1682
  	struct mount *tree;
97216be09   Al Viro   fold release_moun...
1683
  	namespace_lock();
cd4a40174   Eric W. Biederman   mnt: Fail collect...
1684
1685
1686
1687
1688
  	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...
1689
  	namespace_unlock();
be34d1a3b   David Howells   VFS: Make clone_m...
1690
  	if (IS_ERR(tree))
52e220d35   Dan Carpenter   VFS: collect_moun...
1691
  		return ERR_CAST(tree);
be34d1a3b   David Howells   VFS: Make clone_m...
1692
  	return &tree->mnt;
8aec08094   Al Viro   [PATCH] new helpe...
1693
1694
1695
1696
  }
  
  void drop_collected_mounts(struct vfsmount *mnt)
  {
97216be09   Al Viro   fold release_moun...
1697
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1698
  	lock_mount_hash();
a7861ef89   Eric W. Biederman   mount: Prevent MN...
1699
  	umount_tree(real_mount(mnt), 0);
719ea2fbb   Al Viro   new helpers: lock...
1700
  	unlock_mount_hash();
3ab6abee5   Al Viro   more conversions ...
1701
  	namespace_unlock();
8aec08094   Al Viro   [PATCH] new helpe...
1702
  }
c771d683a   Miklos Szeredi   vfs: introduce cl...
1703
1704
1705
1706
1707
1708
1709
1710
1711
  /**
   * 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...
1712
  struct vfsmount *clone_private_mount(const struct path *path)
c771d683a   Miklos Szeredi   vfs: introduce cl...
1713
1714
1715
1716
1717
1718
  {
  	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...
1719
  	new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
c771d683a   Miklos Szeredi   vfs: introduce cl...
1720
1721
1722
1723
1724
1725
  	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...
1726
1727
1728
  int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
  		   struct vfsmount *root)
  {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1729
  	struct mount *mnt;
1f707137b   Al Viro   new helper: itera...
1730
1731
1732
  	int res = f(root, arg);
  	if (res)
  		return res;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1733
1734
  	list_for_each_entry(mnt, &real_mount(root)->mnt_list, mnt_list) {
  		res = f(&mnt->mnt, arg);
1f707137b   Al Viro   new helper: itera...
1735
1736
1737
1738
1739
  		if (res)
  			return res;
  	}
  	return 0;
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1740
  static void cleanup_group_ids(struct mount *mnt, struct mount *end)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1741
  {
315fc83e5   Al Viro   vfs: spread struc...
1742
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1743

909b0a88e   Al Viro   vfs: spread struc...
1744
  	for (p = mnt; p != end; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
1745
  		if (p->mnt_group_id && !IS_MNT_SHARED(p))
4b8b21f4f   Al Viro   vfs: spread struc...
1746
  			mnt_release_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1747
1748
  	}
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1749
  static int invent_group_ids(struct mount *mnt, bool recurse)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1750
  {
315fc83e5   Al Viro   vfs: spread struc...
1751
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1752

909b0a88e   Al Viro   vfs: spread struc...
1753
  	for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) {
fc7be130c   Al Viro   vfs: switch pnode...
1754
  		if (!p->mnt_group_id && !IS_MNT_SHARED(p)) {
4b8b21f4f   Al Viro   vfs: spread struc...
1755
  			int err = mnt_alloc_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1756
  			if (err) {
4b8b21f4f   Al Viro   vfs: spread struc...
1757
  				cleanup_group_ids(mnt, p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1758
1759
1760
1761
1762
1763
1764
  				return err;
  			}
  		}
  	}
  
  	return 0;
  }
d29216842   Eric W. Biederman   mnt: Add a per mo...
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
  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...
1786
1787
  /*
   *  @source_mnt : mount tree to be attached
214444032   Ram Pai   [PATCH] shared mo...
1788
1789
1790
1791
   *  @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...
1792
1793
1794
   *
   *  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...
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
   * ---------------------------------------------------------------------------
   * |         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...
1807
1808
1809
1810
1811
1812
1813
1814
1815
   * 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 ...
1816
1817
1818
1819
1820
1821
1822
   * (+++) 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...
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
   * ---------------------------------------------------------------------------
   * |         		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 ...
1835
1836
1837
   *
   * (+)  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...
1838
   * (+*)  the mount is moved to the destination.
5afe00221   Ram Pai   [PATCH] handling ...
1839
1840
1841
1842
   * (+++)  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...
1843
1844
1845
1846
1847
1848
   *
   * 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...
1849
  static int attach_recursive_mnt(struct mount *source_mnt,
84d17192d   Al Viro   get rid of full-h...
1850
1851
1852
  			struct mount *dest_mnt,
  			struct mountpoint *dest_mp,
  			struct path *parent_path)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1853
  {
38129a13e   Al Viro   switch mnt_hash t...
1854
  	HLIST_HEAD(tree_list);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1855
  	struct mnt_namespace *ns = dest_mnt->mnt_ns;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1856
  	struct mountpoint *smp;
315fc83e5   Al Viro   vfs: spread struc...
1857
  	struct mount *child, *p;
38129a13e   Al Viro   switch mnt_hash t...
1858
  	struct hlist_node *n;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1859
  	int err;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1860

1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1861
1862
1863
1864
1865
1866
  	/* 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...
1867
1868
1869
1870
1871
1872
  	/* Is there space to add these mounts to the mount namespace? */
  	if (!parent_path) {
  		err = count_mounts(ns, source_mnt);
  		if (err)
  			goto out;
  	}
fc7be130c   Al Viro   vfs: switch pnode...
1873
  	if (IS_MNT_SHARED(dest_mnt)) {
0fb54e505   Al Viro   vfs: spread struc...
1874
  		err = invent_group_ids(source_mnt, true);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1875
1876
  		if (err)
  			goto out;
0b1b901b5   Al Viro   don't bother with...
1877
  		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
f2ebb3a92   Al Viro   smarter propagate...
1878
  		lock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
1879
1880
  		if (err)
  			goto out_cleanup_ids;
909b0a88e   Al Viro   vfs: spread struc...
1881
  		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
0f0afb1dc   Al Viro   vfs: spread struc...
1882
  			set_mnt_shared(p);
0b1b901b5   Al Viro   don't bother with...
1883
1884
  	} else {
  		lock_mount_hash();
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1885
  	}
1a3906895   Al Viro   [PATCH] reduce st...
1886
  	if (parent_path) {
0fb54e505   Al Viro   vfs: spread struc...
1887
  		detach_mnt(source_mnt, parent_path);
84d17192d   Al Viro   get rid of full-h...
1888
  		attach_mnt(source_mnt, dest_mnt, dest_mp);
143c8c91c   Al Viro   vfs: mnt_ns moved...
1889
  		touch_mnt_namespace(source_mnt->mnt_ns);
214444032   Ram Pai   [PATCH] shared mo...
1890
  	} else {
84d17192d   Al Viro   get rid of full-h...
1891
  		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1892
  		commit_tree(source_mnt);
214444032   Ram Pai   [PATCH] shared mo...
1893
  	}
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1894

38129a13e   Al Viro   switch mnt_hash t...
1895
  	hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
1d6a32acd   Al Viro   keep shadowed vfs...
1896
  		struct mount *q;
38129a13e   Al Viro   switch mnt_hash t...
1897
  		hlist_del_init(&child->mnt_hash);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1898
1899
1900
1901
1902
  		q = __lookup_mnt(&child->mnt_parent->mnt,
  				 child->mnt_mountpoint);
  		if (q)
  			mnt_change_mountpoint(child, smp, q);
  		commit_tree(child);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1903
  	}
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1904
  	put_mountpoint(smp);
719ea2fbb   Al Viro   new helpers: lock...
1905
  	unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1906

b90fa9ae8   Ram Pai   [PATCH] shared mo...
1907
  	return 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1908
1909
  
   out_cleanup_ids:
f2ebb3a92   Al Viro   smarter propagate...
1910
1911
  	while (!hlist_empty(&tree_list)) {
  		child = hlist_entry(tree_list.first, struct mount, mnt_hash);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1912
  		child->mnt_parent->mnt_ns->pending_mounts = 0;
e819f1521   Eric W. Biederman   mnt: Improve the ...
1913
  		umount_tree(child, UMOUNT_SYNC);
f2ebb3a92   Al Viro   smarter propagate...
1914
1915
  	}
  	unlock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
1916
  	cleanup_group_ids(source_mnt, NULL);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1917
   out:
d29216842   Eric W. Biederman   mnt: Add a per mo...
1918
  	ns->pending_mounts = 0;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1919
1920
1921
1922
  
  	read_seqlock_excl(&mount_lock);
  	put_mountpoint(smp);
  	read_sequnlock_excl(&mount_lock);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1923
  	return err;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1924
  }
84d17192d   Al Viro   get rid of full-h...
1925
  static struct mountpoint *lock_mount(struct path *path)
b12cea919   Al Viro   change the lockin...
1926
1927
  {
  	struct vfsmount *mnt;
84d17192d   Al Viro   get rid of full-h...
1928
  	struct dentry *dentry = path->dentry;
b12cea919   Al Viro   change the lockin...
1929
  retry:
5955102c9   Al Viro   wrappers for ->i_...
1930
  	inode_lock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
1931
  	if (unlikely(cant_mount(dentry))) {
5955102c9   Al Viro   wrappers for ->i_...
1932
  		inode_unlock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
1933
  		return ERR_PTR(-ENOENT);
b12cea919   Al Viro   change the lockin...
1934
  	}
97216be09   Al Viro   fold release_moun...
1935
  	namespace_lock();
b12cea919   Al Viro   change the lockin...
1936
  	mnt = lookup_mnt(path);
84d17192d   Al Viro   get rid of full-h...
1937
  	if (likely(!mnt)) {
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1938
  		struct mountpoint *mp = get_mountpoint(dentry);
84d17192d   Al Viro   get rid of full-h...
1939
  		if (IS_ERR(mp)) {
97216be09   Al Viro   fold release_moun...
1940
  			namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
1941
  			inode_unlock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
1942
1943
1944
1945
  			return mp;
  		}
  		return mp;
  	}
97216be09   Al Viro   fold release_moun...
1946
  	namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
1947
  	inode_unlock(path->dentry->d_inode);
b12cea919   Al Viro   change the lockin...
1948
1949
  	path_put(path);
  	path->mnt = mnt;
84d17192d   Al Viro   get rid of full-h...
1950
  	dentry = path->dentry = dget(mnt->mnt_root);
b12cea919   Al Viro   change the lockin...
1951
1952
  	goto retry;
  }
84d17192d   Al Viro   get rid of full-h...
1953
  static void unlock_mount(struct mountpoint *where)
b12cea919   Al Viro   change the lockin...
1954
  {
84d17192d   Al Viro   get rid of full-h...
1955
  	struct dentry *dentry = where->m_dentry;
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1956
1957
  
  	read_seqlock_excl(&mount_lock);
84d17192d   Al Viro   get rid of full-h...
1958
  	put_mountpoint(where);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1959
  	read_sequnlock_excl(&mount_lock);
328e6d901   Al Viro   switch unlock_mou...
1960
  	namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
1961
  	inode_unlock(dentry->d_inode);
b12cea919   Al Viro   change the lockin...
1962
  }
84d17192d   Al Viro   get rid of full-h...
1963
  static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1964
  {
e462ec50c   David Howells   VFS: Differentiat...
1965
  	if (mnt->mnt.mnt_sb->s_flags & SB_NOUSER)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1966
  		return -EINVAL;
e36cb0b89   David Howells   VFS: (Scripted) C...
1967
1968
  	if (d_is_dir(mp->m_dentry) !=
  	      d_is_dir(mnt->mnt.mnt_root))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1969
  		return -ENOTDIR;
84d17192d   Al Viro   get rid of full-h...
1970
  	return attach_recursive_mnt(mnt, p, mp, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1971
1972
1973
  }
  
  /*
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
1974
1975
   * Sanity check the flags to change_mnt_propagation.
   */
e462ec50c   David Howells   VFS: Differentiat...
1976
  static int flags_to_propagation_type(int ms_flags)
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
1977
  {
e462ec50c   David Howells   VFS: Differentiat...
1978
  	int type = ms_flags & ~(MS_REC | MS_SILENT);
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
  
  	/* 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...
1990
1991
   * recursively change the type of the mountpoint.
   */
e462ec50c   David Howells   VFS: Differentiat...
1992
  static int do_change_type(struct path *path, int ms_flags)
07b20889e   Ram Pai   [PATCH] beginning...
1993
  {
315fc83e5   Al Viro   vfs: spread struc...
1994
  	struct mount *m;
4b8b21f4f   Al Viro   vfs: spread struc...
1995
  	struct mount *mnt = real_mount(path->mnt);
e462ec50c   David Howells   VFS: Differentiat...
1996
  	int recurse = ms_flags & MS_REC;
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
1997
  	int type;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1998
  	int err = 0;
07b20889e   Ram Pai   [PATCH] beginning...
1999

2d92ab3c6   Al Viro   [PATCH] finally g...
2000
  	if (path->dentry != path->mnt->mnt_root)
07b20889e   Ram Pai   [PATCH] beginning...
2001
  		return -EINVAL;
e462ec50c   David Howells   VFS: Differentiat...
2002
  	type = flags_to_propagation_type(ms_flags);
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2003
2004
  	if (!type)
  		return -EINVAL;
97216be09   Al Viro   fold release_moun...
2005
  	namespace_lock();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2006
2007
2008
2009
2010
  	if (type == MS_SHARED) {
  		err = invent_group_ids(mnt, recurse);
  		if (err)
  			goto out_unlock;
  	}
719ea2fbb   Al Viro   new helpers: lock...
2011
  	lock_mount_hash();
909b0a88e   Al Viro   vfs: spread struc...
2012
  	for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
0f0afb1dc   Al Viro   vfs: spread struc...
2013
  		change_mnt_propagation(m, type);
719ea2fbb   Al Viro   new helpers: lock...
2014
  	unlock_mount_hash();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2015
2016
  
   out_unlock:
97216be09   Al Viro   fold release_moun...
2017
  	namespace_unlock();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2018
  	return err;
07b20889e   Ram Pai   [PATCH] beginning...
2019
  }
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
  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;
  }
07b20889e   Ram Pai   [PATCH] beginning...
2032
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2033
2034
   * do loopback mount.
   */
808d4e3cf   Al Viro   consitify do_moun...
2035
  static int do_loopback(struct path *path, const char *old_name,
2dafe1c4d   Eric Sandeen   reduce large do_m...
2036
  				int recurse)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2037
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2038
  	struct path old_path;
84d17192d   Al Viro   get rid of full-h...
2039
2040
  	struct mount *mnt = NULL, *old, *parent;
  	struct mountpoint *mp;
57eccb830   Al Viro   mount: consolidat...
2041
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2042
2043
  	if (!old_name || !*old_name)
  		return -EINVAL;
815d405ce   Trond Myklebust   VFS: Fix the rema...
2044
  	err = kern_path(old_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2045
2046
  	if (err)
  		return err;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2047
  	err = -EINVAL;
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2048
  	if (mnt_ns_loop(old_path.dentry))
dd111b31e   David Howells   VFS: Clean up whi...
2049
  		goto out;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2050

84d17192d   Al Viro   get rid of full-h...
2051
2052
2053
  	mp = lock_mount(path);
  	err = PTR_ERR(mp);
  	if (IS_ERR(mp))
b12cea919   Al Viro   change the lockin...
2054
  		goto out;
87129cc0e   Al Viro   vfs: spread struc...
2055
  	old = real_mount(old_path.mnt);
84d17192d   Al Viro   get rid of full-h...
2056
  	parent = real_mount(path->mnt);
87129cc0e   Al Viro   vfs: spread struc...
2057

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
  	err = -EINVAL;
fc7be130c   Al Viro   vfs: switch pnode...
2059
  	if (IS_MNT_UNBINDABLE(old))
b12cea919   Al Viro   change the lockin...
2060
  		goto out2;
9676f0c63   Ram Pai   [PATCH] unbindabl...
2061

e149ed2b8   Al Viro   take the targets ...
2062
2063
2064
2065
  	if (!check_mnt(parent))
  		goto out2;
  
  	if (!check_mnt(old) && old_path.dentry->d_op != &ns_dentry_operations)
b12cea919   Al Viro   change the lockin...
2066
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2067

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2068
2069
  	if (!recurse && has_locked_children(old, old_path.dentry))
  		goto out2;
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2070
  	if (recurse)
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2071
  		mnt = copy_tree(old, old_path.dentry, CL_COPY_MNT_NS_FILE);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2072
  	else
87129cc0e   Al Viro   vfs: spread struc...
2073
  		mnt = clone_mnt(old, old_path.dentry, 0);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2074

be34d1a3b   David Howells   VFS: Make clone_m...
2075
2076
  	if (IS_ERR(mnt)) {
  		err = PTR_ERR(mnt);
e9c5d8a56   Andrey Vagin   mnt: release lock...
2077
  		goto out2;
be34d1a3b   David Howells   VFS: Make clone_m...
2078
  	}
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2079

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2080
  	mnt->mnt.mnt_flags &= ~MNT_LOCKED;
84d17192d   Al Viro   get rid of full-h...
2081
  	err = graft_tree(mnt, parent, mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2082
  	if (err) {
719ea2fbb   Al Viro   new helpers: lock...
2083
  		lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
2084
  		umount_tree(mnt, UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
2085
  		unlock_mount_hash();
5b83d2c5c   Ram Pai   [PATCH] sanitize ...
2086
  	}
b12cea919   Al Viro   change the lockin...
2087
  out2:
84d17192d   Al Viro   get rid of full-h...
2088
  	unlock_mount(mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2089
  out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2090
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2091
2092
  	return err;
  }
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
  static int change_mount_flags(struct vfsmount *mnt, int ms_flags)
  {
  	int error = 0;
  	int readonly_request = 0;
  
  	if (ms_flags & MS_RDONLY)
  		readonly_request = 1;
  	if (readonly_request == __mnt_is_readonly(mnt))
  		return 0;
  
  	if (readonly_request)
83adc7532   Al Viro   vfs: spread struc...
2104
  		error = mnt_make_readonly(real_mount(mnt));
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2105
  	else
83adc7532   Al Viro   vfs: spread struc...
2106
  		__mnt_unmake_readonly(real_mount(mnt));
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2107
2108
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2109
2110
2111
2112
2113
  /*
   * 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...
2114
2115
  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
2116
2117
  {
  	int err;
2d92ab3c6   Al Viro   [PATCH] finally g...
2118
  	struct super_block *sb = path->mnt->mnt_sb;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2119
  	struct mount *mnt = real_mount(path->mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2120

143c8c91c   Al Viro   vfs: mnt_ns moved...
2121
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122
  		return -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2123
  	if (path->dentry != path->mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2124
  		return -EINVAL;
07b645589   Eric W. Biederman   mnt: Move the tes...
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
  	/* Don't allow changing of locked mnt flags.
  	 *
  	 * 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.
  	 */
  	if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) &&
  	    !(mnt_flags & MNT_READONLY)) {
  		return -EPERM;
  	}
9566d6742   Eric W. Biederman   mnt: Correct perm...
2135
2136
  	if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
  	    !(mnt_flags & MNT_NODEV)) {
67690f937   Eric W. Biederman   userns: Remove im...
2137
  		return -EPERM;
9566d6742   Eric W. Biederman   mnt: Correct perm...
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
  	}
  	if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) &&
  	    !(mnt_flags & MNT_NOSUID)) {
  		return -EPERM;
  	}
  	if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) &&
  	    !(mnt_flags & MNT_NOEXEC)) {
  		return -EPERM;
  	}
  	if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) &&
  	    ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) {
  		return -EPERM;
  	}
ff36fe2c8   Eric Paris   LSM: Pass -o remo...
2151
2152
2153
  	err = security_sb_remount(sb, data);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2154
  	down_write(&sb->s_umount);
e462ec50c   David Howells   VFS: Differentiat...
2155
2156
  	if (ms_flags & MS_BIND)
  		err = change_mount_flags(path->mnt, ms_flags);
bc6155d13   Eric W. Biederman   fs: Allow superbl...
2157
  	else if (!ns_capable(sb->s_user_ns, CAP_SYS_ADMIN))
57eccb830   Al Viro   mount: consolidat...
2158
  		err = -EPERM;
4aa98cf76   Al Viro   Push BKL down int...
2159
  	else
e462ec50c   David Howells   VFS: Differentiat...
2160
  		err = do_remount_sb(sb, sb_flags, data, 0);
7b43a79f3   Al Viro   mnt_flags fixes i...
2161
  	if (!err) {
719ea2fbb   Al Viro   new helpers: lock...
2162
  		lock_mount_hash();
a6138db81   Eric W. Biederman   mnt: Only change ...
2163
  		mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2164
  		mnt->mnt.mnt_flags = mnt_flags;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2165
  		touch_mnt_namespace(mnt->mnt_ns);
719ea2fbb   Al Viro   new helpers: lock...
2166
  		unlock_mount_hash();
0e55a7cca   Dan Williams   [RFC PATCH] touch...
2167
  	}
6339dab86   Al Viro   do_remount(): pul...
2168
  	up_write(&sb->s_umount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2169
2170
  	return err;
  }
cbbe362cd   Al Viro   vfs: spread struc...
2171
  static inline int tree_contains_unbindable(struct mount *mnt)
9676f0c63   Ram Pai   [PATCH] unbindabl...
2172
  {
315fc83e5   Al Viro   vfs: spread struc...
2173
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
2174
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
2175
  		if (IS_MNT_UNBINDABLE(p))
9676f0c63   Ram Pai   [PATCH] unbindabl...
2176
2177
2178
2179
  			return 1;
  	}
  	return 0;
  }
808d4e3cf   Al Viro   consitify do_moun...
2180
  static int do_move_mount(struct path *path, const char *old_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2181
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2182
  	struct path old_path, parent_path;
676da58df   Al Viro   vfs: spread struc...
2183
  	struct mount *p;
0fb54e505   Al Viro   vfs: spread struc...
2184
  	struct mount *old;
84d17192d   Al Viro   get rid of full-h...
2185
  	struct mountpoint *mp;
57eccb830   Al Viro   mount: consolidat...
2186
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2187
2188
  	if (!old_name || !*old_name)
  		return -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2189
  	err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2190
2191
  	if (err)
  		return err;
84d17192d   Al Viro   get rid of full-h...
2192
2193
2194
  	mp = lock_mount(path);
  	err = PTR_ERR(mp);
  	if (IS_ERR(mp))
cc53ce53c   David Howells   Add a dentry op t...
2195
  		goto out;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2196
  	old = real_mount(old_path.mnt);
fc7be130c   Al Viro   vfs: switch pnode...
2197
  	p = real_mount(path->mnt);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2198

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2199
  	err = -EINVAL;
fc7be130c   Al Viro   vfs: switch pnode...
2200
  	if (!check_mnt(p) || !check_mnt(old))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2201
  		goto out1;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2202
2203
  	if (old->mnt.mnt_flags & MNT_LOCKED)
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2204
  	err = -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2205
  	if (old_path.dentry != old_path.mnt->mnt_root)
214444032   Ram Pai   [PATCH] shared mo...
2206
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2207

676da58df   Al Viro   vfs: spread struc...
2208
  	if (!mnt_has_parent(old))
214444032   Ram Pai   [PATCH] shared mo...
2209
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2210

e36cb0b89   David Howells   VFS: (Scripted) C...
2211
2212
  	if (d_is_dir(path->dentry) !=
  	      d_is_dir(old_path.dentry))
214444032   Ram Pai   [PATCH] shared mo...
2213
2214
2215
2216
  		goto out1;
  	/*
  	 * Don't move a mount residing in a shared parent.
  	 */
fc7be130c   Al Viro   vfs: switch pnode...
2217
  	if (IS_MNT_SHARED(old->mnt_parent))
214444032   Ram Pai   [PATCH] shared mo...
2218
  		goto out1;
9676f0c63   Ram Pai   [PATCH] unbindabl...
2219
2220
2221
2222
  	/*
  	 * Don't move a mount tree containing unbindable mounts to a destination
  	 * mount which is shared.
  	 */
fc7be130c   Al Viro   vfs: switch pnode...
2223
  	if (IS_MNT_SHARED(p) && tree_contains_unbindable(old))
9676f0c63   Ram Pai   [PATCH] unbindabl...
2224
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2225
  	err = -ELOOP;
fc7be130c   Al Viro   vfs: switch pnode...
2226
  	for (; mnt_has_parent(p); p = p->mnt_parent)
676da58df   Al Viro   vfs: spread struc...
2227
  		if (p == old)
214444032   Ram Pai   [PATCH] shared mo...
2228
  			goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2229

84d17192d   Al Viro   get rid of full-h...
2230
  	err = attach_recursive_mnt(old, real_mount(path->mnt), mp, &parent_path);
4ac913785   Jan Blunck   Embed a struct pa...
2231
  	if (err)
214444032   Ram Pai   [PATCH] shared mo...
2232
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2233
2234
2235
  
  	/* if the mount is moved, it should no longer be expire
  	 * automatically */
6776db3d3   Al Viro   vfs: take mnt_sha...
2236
  	list_del_init(&old->mnt_expire);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2237
  out1:
84d17192d   Al Viro   get rid of full-h...
2238
  	unlock_mount(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2239
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2240
  	if (!err)
1a3906895   Al Viro   [PATCH] reduce st...
2241
  		path_put(&parent_path);
2d92ab3c6   Al Viro   [PATCH] finally g...
2242
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2243
2244
  	return err;
  }
9d412a43c   Al Viro   vfs: split off vf...
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
  static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
  {
  	int err;
  	const char *subtype = strchr(fstype, '.');
  	if (subtype) {
  		subtype++;
  		err = -EINVAL;
  		if (!subtype[0])
  			goto err;
  	} else
  		subtype = "";
  
  	mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
  	err = -ENOMEM;
  	if (!mnt->mnt_sb->s_subtype)
  		goto err;
  	return mnt;
  
   err:
  	mntput(mnt);
  	return ERR_PTR(err);
  }
9d412a43c   Al Viro   vfs: split off vf...
2267
2268
2269
  /*
   * add a mount into a namespace's mount tree
   */
95bc5f25c   Al Viro   vfs: spread struc...
2270
  static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
9d412a43c   Al Viro   vfs: split off vf...
2271
  {
84d17192d   Al Viro   get rid of full-h...
2272
2273
  	struct mountpoint *mp;
  	struct mount *parent;
9d412a43c   Al Viro   vfs: split off vf...
2274
  	int err;
f2ebb3a92   Al Viro   smarter propagate...
2275
  	mnt_flags &= ~MNT_INTERNAL_FLAGS;
9d412a43c   Al Viro   vfs: split off vf...
2276

84d17192d   Al Viro   get rid of full-h...
2277
2278
2279
  	mp = lock_mount(path);
  	if (IS_ERR(mp))
  		return PTR_ERR(mp);
9d412a43c   Al Viro   vfs: split off vf...
2280

84d17192d   Al Viro   get rid of full-h...
2281
  	parent = real_mount(path->mnt);
9d412a43c   Al Viro   vfs: split off vf...
2282
  	err = -EINVAL;
84d17192d   Al Viro   get rid of full-h...
2283
  	if (unlikely(!check_mnt(parent))) {
156cacb1d   Al Viro   do_add_mount()/um...
2284
2285
2286
2287
  		/* 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...
2288
  		if (!parent->mnt_ns)
156cacb1d   Al Viro   do_add_mount()/um...
2289
2290
  			goto unlock;
  	}
9d412a43c   Al Viro   vfs: split off vf...
2291
2292
2293
  
  	/* Refuse the same filesystem on the same mount point */
  	err = -EBUSY;
95bc5f25c   Al Viro   vfs: spread struc...
2294
  	if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
9d412a43c   Al Viro   vfs: split off vf...
2295
2296
2297
2298
  	    path->mnt->mnt_root == path->dentry)
  		goto unlock;
  
  	err = -EINVAL;
e36cb0b89   David Howells   VFS: (Scripted) C...
2299
  	if (d_is_symlink(newmnt->mnt.mnt_root))
9d412a43c   Al Viro   vfs: split off vf...
2300
  		goto unlock;
95bc5f25c   Al Viro   vfs: spread struc...
2301
  	newmnt->mnt.mnt_flags = mnt_flags;
84d17192d   Al Viro   get rid of full-h...
2302
  	err = graft_tree(newmnt, parent, mp);
9d412a43c   Al Viro   vfs: split off vf...
2303
2304
  
  unlock:
84d17192d   Al Viro   get rid of full-h...
2305
  	unlock_mount(mp);
9d412a43c   Al Viro   vfs: split off vf...
2306
2307
  	return err;
  }
b1e75df45   Al Viro   tidy up around fi...
2308

8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
2309
  static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags);
1b852bceb   Eric W. Biederman   mnt: Refactor the...
2310

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2311
2312
2313
2314
  /*
   * create a new mount for userspace and request it to be added into the
   * namespace's tree
   */
e462ec50c   David Howells   VFS: Differentiat...
2315
  static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
808d4e3cf   Al Viro   consitify do_moun...
2316
  			int mnt_flags, const char *name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2317
  {
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2318
  	struct file_system_type *type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2319
  	struct vfsmount *mnt;
15f9a3f3e   Al Viro   don't drop newmnt...
2320
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2321

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2322
  	if (!fstype)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2323
  		return -EINVAL;
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2324
2325
2326
  	type = get_fs_type(fstype);
  	if (!type)
  		return -ENODEV;
e462ec50c   David Howells   VFS: Differentiat...
2327
  	mnt = vfs_kern_mount(type, sb_flags, name, data);
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2328
2329
2330
2331
2332
  	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
  	    !mnt->mnt_sb->s_subtype)
  		mnt = fs_set_subtype(mnt, fstype);
  
  	put_filesystem(type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2333
2334
  	if (IS_ERR(mnt))
  		return PTR_ERR(mnt);
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
2335
2336
2337
2338
  	if (mount_too_revealing(mnt, &mnt_flags)) {
  		mntput(mnt);
  		return -EPERM;
  	}
95bc5f25c   Al Viro   vfs: spread struc...
2339
  	err = do_add_mount(real_mount(mnt), path, mnt_flags);
15f9a3f3e   Al Viro   don't drop newmnt...
2340
2341
2342
  	if (err)
  		mntput(mnt);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2343
  }
19a167af7   Al Viro   Take the completi...
2344
2345
  int finish_automount(struct vfsmount *m, struct path *path)
  {
6776db3d3   Al Viro   vfs: take mnt_sha...
2346
  	struct mount *mnt = real_mount(m);
19a167af7   Al Viro   Take the completi...
2347
2348
2349
2350
  	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...
2351
  	BUG_ON(mnt_get_count(mnt) < 2);
19a167af7   Al Viro   Take the completi...
2352
2353
2354
  
  	if (m->mnt_sb == path->mnt->mnt_sb &&
  	    m->mnt_root == path->dentry) {
b1e75df45   Al Viro   tidy up around fi...
2355
2356
  		err = -ELOOP;
  		goto fail;
19a167af7   Al Viro   Take the completi...
2357
  	}
95bc5f25c   Al Viro   vfs: spread struc...
2358
  	err = do_add_mount(mnt, path, path->mnt->mnt_flags | MNT_SHRINKABLE);
b1e75df45   Al Viro   tidy up around fi...
2359
2360
2361
2362
  	if (!err)
  		return 0;
  fail:
  	/* remove m from any expiration list it may be on */
6776db3d3   Al Viro   vfs: take mnt_sha...
2363
  	if (!list_empty(&mnt->mnt_expire)) {
97216be09   Al Viro   fold release_moun...
2364
  		namespace_lock();
6776db3d3   Al Viro   vfs: take mnt_sha...
2365
  		list_del_init(&mnt->mnt_expire);
97216be09   Al Viro   fold release_moun...
2366
  		namespace_unlock();
19a167af7   Al Viro   Take the completi...
2367
  	}
b1e75df45   Al Viro   tidy up around fi...
2368
2369
  	mntput(m);
  	mntput(m);
19a167af7   Al Viro   Take the completi...
2370
2371
  	return err;
  }
ea5b778a8   David Howells   Unexport do_add_m...
2372
2373
2374
2375
2376
2377
2378
  /**
   * 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...
2379
  	namespace_lock();
ea5b778a8   David Howells   Unexport do_add_m...
2380

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

97216be09   Al Viro   fold release_moun...
2383
  	namespace_unlock();
ea5b778a8   David Howells   Unexport do_add_m...
2384
2385
2386
2387
  }
  EXPORT_SYMBOL(mnt_set_expiry);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2388
2389
2390
2391
2392
2393
   * 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...
2394
  	struct mount *mnt, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2395
2396
2397
2398
  	LIST_HEAD(graveyard);
  
  	if (list_empty(mounts))
  		return;
97216be09   Al Viro   fold release_moun...
2399
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
2400
  	lock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2401
2402
2403
2404
2405
2406
2407
  
  	/* 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...
2408
  	list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
863d684f9   Al Viro   vfs: move the res...
2409
  		if (!xchg(&mnt->mnt_expiry_mark, 1) ||
1ab597386   Al Viro   vfs: spread struc...
2410
  			propagate_mount_busy(mnt, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2411
  			continue;
6776db3d3   Al Viro   vfs: take mnt_sha...
2412
  		list_move(&mnt->mnt_expire, &graveyard);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2413
  	}
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2414
  	while (!list_empty(&graveyard)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2415
  		mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2416
  		touch_mnt_namespace(mnt->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2417
  		umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2418
  	}
719ea2fbb   Al Viro   new helpers: lock...
2419
  	unlock_mount_hash();
3ab6abee5   Al Viro   more conversions ...
2420
  	namespace_unlock();
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
  }
  
  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...
2431
  static int select_submounts(struct mount *parent, struct list_head *graveyard)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2432
  {
692afc312   Al Viro   vfs: spread struc...
2433
  	struct mount *this_parent = parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2434
2435
2436
2437
  	struct list_head *next;
  	int found = 0;
  
  repeat:
6b41d536f   Al Viro   vfs: take mnt_chi...
2438
  	next = this_parent->mnt_mounts.next;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2439
  resume:
6b41d536f   Al Viro   vfs: take mnt_chi...
2440
  	while (next != &this_parent->mnt_mounts) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2441
  		struct list_head *tmp = next;
6b41d536f   Al Viro   vfs: take mnt_chi...
2442
  		struct mount *mnt = list_entry(tmp, struct mount, mnt_child);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2443
2444
  
  		next = tmp->next;
692afc312   Al Viro   vfs: spread struc...
2445
  		if (!(mnt->mnt.mnt_flags & MNT_SHRINKABLE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2446
  			continue;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2447
2448
2449
  		/*
  		 * Descend a level if the d_mounts list is non-empty.
  		 */
6b41d536f   Al Viro   vfs: take mnt_chi...
2450
  		if (!list_empty(&mnt->mnt_mounts)) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2451
2452
2453
  			this_parent = mnt;
  			goto repeat;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2454

1ab597386   Al Viro   vfs: spread struc...
2455
  		if (!propagate_mount_busy(mnt, 1)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2456
  			list_move_tail(&mnt->mnt_expire, graveyard);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2457
2458
  			found++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2459
  	}
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2460
2461
2462
2463
  	/*
  	 * All done at this level ... ascend and resume the search
  	 */
  	if (this_parent != parent) {
6b41d536f   Al Viro   vfs: take mnt_chi...
2464
  		next = this_parent->mnt_child.next;
0714a5338   Al Viro   vfs: now it can b...
2465
  		this_parent = this_parent->mnt_parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2466
2467
2468
2469
2470
2471
2472
2473
  		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...
2474
   *
48a066e72   Al Viro   RCU'd vfsmounts
2475
   * mount_lock must be held for write
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2476
   */
b54b9be78   Al Viro   get rid of the se...
2477
  static void shrink_submounts(struct mount *mnt)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2478
2479
  {
  	LIST_HEAD(graveyard);
761d5c38e   Al Viro   vfs: spread struc...
2480
  	struct mount *m;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2481

5528f911b   Trond Myklebust   VFS: Add shrink_s...
2482
  	/* extract submounts of 'mountpoint' from the expiration list */
c35038bec   Al Viro   [PATCH] do shrink...
2483
  	while (select_submounts(mnt, &graveyard)) {
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2484
  		while (!list_empty(&graveyard)) {
761d5c38e   Al Viro   vfs: spread struc...
2485
  			m = list_first_entry(&graveyard, struct mount,
6776db3d3   Al Viro   vfs: take mnt_sha...
2486
  						mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2487
  			touch_mnt_namespace(m->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2488
  			umount_tree(m, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2489
2490
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2491
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2492
2493
2494
2495
2496
2497
  /*
   * 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...
2498
2499
  static long exact_copy_from_user(void *to, const void __user * from,
  				 unsigned long n)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
  {
  	char *t = to;
  	const char __user *f = from;
  	char c;
  
  	if (!access_ok(VERIFY_READ, from, n))
  		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...
2519
  void *copy_mount_options(const void __user * data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2520
2521
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2522
  	unsigned long size;
b40ef8696   Al Viro   saner calling con...
2523
  	char *copy;
b58fed8b1   Ram Pai   [PATCH] lindent f...
2524

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2525
  	if (!data)
b40ef8696   Al Viro   saner calling con...
2526
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2527

b40ef8696   Al Viro   saner calling con...
2528
2529
2530
  	copy = kmalloc(PAGE_SIZE, GFP_KERNEL);
  	if (!copy)
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2531
2532
2533
2534
2535
2536
2537
2538
2539
  
  	/* 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 ! */
  	size = TASK_SIZE - (unsigned long)data;
  	if (size > PAGE_SIZE)
  		size = PAGE_SIZE;
b40ef8696   Al Viro   saner calling con...
2540
  	i = size - exact_copy_from_user(copy, data, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2541
  	if (!i) {
b40ef8696   Al Viro   saner calling con...
2542
2543
  		kfree(copy);
  		return ERR_PTR(-EFAULT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2544
2545
  	}
  	if (i != PAGE_SIZE)
b40ef8696   Al Viro   saner calling con...
2546
2547
  		memset(copy + i, 0, PAGE_SIZE - i);
  	return copy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2548
  }
b8850d1fa   Tim Gardner   fs: namespace: su...
2549
  char *copy_mount_string(const void __user *data)
eca6f534e   Vegard Nossum   fs: fix overflow ...
2550
  {
b8850d1fa   Tim Gardner   fs: namespace: su...
2551
  	return data ? strndup_user(data, PAGE_SIZE) : NULL;
eca6f534e   Vegard Nossum   fs: fix overflow ...
2552
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
  /*
   * 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...
2567
  long do_mount(const char *dev_name, const char __user *dir_name,
808d4e3cf   Al Viro   consitify do_moun...
2568
  		const char *type_page, unsigned long flags, void *data_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2569
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2570
  	struct path path;
e462ec50c   David Howells   VFS: Differentiat...
2571
  	unsigned int mnt_flags = 0, sb_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2572
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2573
2574
2575
2576
2577
2578
  
  	/* 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
2579
2580
  	if (data_page)
  		((char *)data_page)[PAGE_SIZE - 1] = 0;
e462ec50c   David Howells   VFS: Differentiat...
2581
2582
  	if (flags & MS_NOUSER)
  		return -EINVAL;
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2583
  	/* ... and get the mountpoint */
5e6123f34   Seunghun Lee   vfs: move getname...
2584
  	retval = user_path(dir_name, &path);
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2585
2586
2587
2588
2589
  	if (retval)
  		return retval;
  
  	retval = security_sb_mount(dev_name, &path,
  				   type_page, flags, data_page);
0d5cadb87   Al Viro   do_mount(): fix a...
2590
2591
  	if (!retval && !may_mount())
  		retval = -EPERM;
e462ec50c   David Howells   VFS: Differentiat...
2592
  	if (!retval && (flags & SB_MANDLOCK) && !may_mandlock())
9e8925b67   Jeff Layton   locks: Allow disa...
2593
  		retval = -EPERM;
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2594
2595
  	if (retval)
  		goto dput_out;
613cbe3d4   Andi Kleen   Don't set relatim...
2596
2597
2598
  	/* Default to relatime unless overriden */
  	if (!(flags & MS_NOATIME))
  		mnt_flags |= MNT_RELATIME;
0a1c01c94   Matthew Garrett   Make relatime def...
2599

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2600
2601
2602
2603
2604
2605
2606
  	/* 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...
2607
2608
2609
2610
  	if (flags & MS_NOATIME)
  		mnt_flags |= MNT_NOATIME;
  	if (flags & MS_NODIRATIME)
  		mnt_flags |= MNT_NODIRATIME;
d0adde574   Matthew Garrett   Add a strictatime...
2611
2612
  	if (flags & MS_STRICTATIME)
  		mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
a9e5b7328   David Howells   vfs: Undo an over...
2613
  	if (flags & MS_RDONLY)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2614
  		mnt_flags |= MNT_READONLY;
fc33a7bb9   Christoph Hellwig   [PATCH] per-mount...
2615

ffbc6f0ea   Eric W. Biederman   mnt: Change the d...
2616
2617
2618
2619
2620
2621
2622
  	/* 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...
2623
2624
2625
2626
2627
  	sb_flags = flags & (SB_RDONLY |
  			    SB_SYNCHRONOUS |
  			    SB_MANDLOCK |
  			    SB_DIRSYNC |
  			    SB_SILENT |
917086ff2   Mimi Zohar   vfs: fix mounting...
2628
  			    SB_POSIXACL |
d7ee94694   Markus Trippelsdorf   VFS: Handle lazyt...
2629
  			    SB_LAZYTIME |
917086ff2   Mimi Zohar   vfs: fix mounting...
2630
  			    SB_I_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2631

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2632
  	if (flags & MS_REMOUNT)
e462ec50c   David Howells   VFS: Differentiat...
2633
  		retval = do_remount(&path, flags, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2634
2635
  				    data_page);
  	else if (flags & MS_BIND)
2d92ab3c6   Al Viro   [PATCH] finally g...
2636
  		retval = do_loopback(&path, dev_name, flags & MS_REC);
9676f0c63   Ram Pai   [PATCH] unbindabl...
2637
  	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
2d92ab3c6   Al Viro   [PATCH] finally g...
2638
  		retval = do_change_type(&path, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2639
  	else if (flags & MS_MOVE)
2d92ab3c6   Al Viro   [PATCH] finally g...
2640
  		retval = do_move_mount(&path, dev_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2641
  	else
e462ec50c   David Howells   VFS: Differentiat...
2642
  		retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2643
2644
  				      dev_name, data_page);
  dput_out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2645
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2646
2647
  	return retval;
  }
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2648
2649
2650
2651
2652
2653
2654
2655
2656
  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...
2657
2658
  static void free_mnt_ns(struct mnt_namespace *ns)
  {
6344c433a   Al Viro   new helpers: ns_a...
2659
  	ns_free_inum(&ns->ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2660
  	dec_mnt_namespaces(ns->ucounts);
771b13716   Eric W. Biederman   vfs: Add a user n...
2661
2662
2663
  	put_user_ns(ns->user_ns);
  	kfree(ns);
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
2664
2665
2666
2667
2668
2669
2670
2671
  /*
   * 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);
771b13716   Eric W. Biederman   vfs: Add a user n...
2672
  static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2673
2674
  {
  	struct mnt_namespace *new_ns;
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2675
  	struct ucounts *ucounts;
98f842e67   Eric W. Biederman   proc: Usable inod...
2676
  	int ret;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2677

537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2678
2679
  	ucounts = inc_mnt_namespaces(user_ns);
  	if (!ucounts)
df75e7748   Eric W. Biederman   userns: When the ...
2680
  		return ERR_PTR(-ENOSPC);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2681

cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2682
  	new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2683
2684
  	if (!new_ns) {
  		dec_mnt_namespaces(ucounts);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2685
  		return ERR_PTR(-ENOMEM);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2686
  	}
6344c433a   Al Viro   new helpers: ns_a...
2687
  	ret = ns_alloc_inum(&new_ns->ns);
98f842e67   Eric W. Biederman   proc: Usable inod...
2688
2689
  	if (ret) {
  		kfree(new_ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2690
  		dec_mnt_namespaces(ucounts);
98f842e67   Eric W. Biederman   proc: Usable inod...
2691
2692
  		return ERR_PTR(ret);
  	}
33c429405   Al Viro   copy address of p...
2693
  	new_ns->ns.ops = &mntns_operations;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2694
  	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2695
2696
2697
2698
2699
  	atomic_set(&new_ns->count, 1);
  	new_ns->root = NULL;
  	INIT_LIST_HEAD(&new_ns->list);
  	init_waitqueue_head(&new_ns->poll);
  	new_ns->event = 0;
771b13716   Eric W. Biederman   vfs: Add a user n...
2700
  	new_ns->user_ns = get_user_ns(user_ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2701
  	new_ns->ucounts = ucounts;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2702
2703
  	new_ns->mounts = 0;
  	new_ns->pending_mounts = 0;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2704
2705
  	return new_ns;
  }
0766f788e   Emese Revfy   latent_entropy: M...
2706
  __latent_entropy
9559f6891   Al Viro   fold dup_mnt_ns()...
2707
2708
  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
2709
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
2710
  	struct mnt_namespace *new_ns;
7f2da1e7d   Al Viro   [PATCH] kill altroot
2711
  	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
315fc83e5   Al Viro   vfs: spread struc...
2712
  	struct mount *p, *q;
9559f6891   Al Viro   fold dup_mnt_ns()...
2713
  	struct mount *old;
cb338d06e   Al Viro   vfs: spread struc...
2714
  	struct mount *new;
7a472ef4b   Eric W. Biederman   vfs: Only support...
2715
  	int copy_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2716

9559f6891   Al Viro   fold dup_mnt_ns()...
2717
2718
2719
2720
2721
2722
2723
2724
  	BUG_ON(!ns);
  
  	if (likely(!(flags & CLONE_NEWNS))) {
  		get_mnt_ns(ns);
  		return ns;
  	}
  
  	old = ns->root;
771b13716   Eric W. Biederman   vfs: Add a user n...
2725
  	new_ns = alloc_mnt_ns(user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2726
2727
  	if (IS_ERR(new_ns))
  		return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2728

97216be09   Al Viro   fold release_moun...
2729
  	namespace_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2730
  	/* First pass: copy the tree topology */
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2731
  	copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
9559f6891   Al Viro   fold dup_mnt_ns()...
2732
  	if (user_ns != ns->user_ns)
132c94e31   Eric W. Biederman   vfs: Carefully pr...
2733
  		copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
7a472ef4b   Eric W. Biederman   vfs: Only support...
2734
  	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
be34d1a3b   David Howells   VFS: Make clone_m...
2735
  	if (IS_ERR(new)) {
328e6d901   Al Viro   switch unlock_mou...
2736
  		namespace_unlock();
771b13716   Eric W. Biederman   vfs: Add a user n...
2737
  		free_mnt_ns(new_ns);
be34d1a3b   David Howells   VFS: Make clone_m...
2738
  		return ERR_CAST(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2739
  	}
be08d6d26   Al Viro   switch mnt_namesp...
2740
  	new_ns->root = new;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2741
  	list_add_tail(&new_ns->list, &new->mnt_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2742
2743
2744
2745
2746
2747
  
  	/*
  	 * 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...
2748
  	p = old;
cb338d06e   Al Viro   vfs: spread struc...
2749
  	q = new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2750
  	while (p) {
143c8c91c   Al Viro   vfs: mnt_ns moved...
2751
  		q->mnt_ns = new_ns;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2752
  		new_ns->mounts++;
9559f6891   Al Viro   fold dup_mnt_ns()...
2753
2754
2755
  		if (new_fs) {
  			if (&p->mnt == new_fs->root.mnt) {
  				new_fs->root.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
2756
  				rootmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2757
  			}
9559f6891   Al Viro   fold dup_mnt_ns()...
2758
2759
  			if (&p->mnt == new_fs->pwd.mnt) {
  				new_fs->pwd.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
2760
  				pwdmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2761
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2762
  		}
909b0a88e   Al Viro   vfs: spread struc...
2763
2764
  		p = next_mnt(p, old);
  		q = next_mnt(q, new);
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2765
2766
2767
2768
  		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
2769
  	}
328e6d901   Al Viro   switch unlock_mou...
2770
  	namespace_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2771

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2772
  	if (rootmnt)
f03c65993   Al Viro   sanitize vfsmount...
2773
  		mntput(rootmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2774
  	if (pwdmnt)
f03c65993   Al Viro   sanitize vfsmount...
2775
  		mntput(pwdmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2776

741a29513   JANAK DESAI   [PATCH] unshare s...
2777
  	return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2778
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2779
2780
2781
2782
  /**
   * create_mnt_ns - creates a private namespace and adds a root filesystem
   * @mnt: pointer to the new root filesystem mountpoint
   */
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2783
  static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2784
  {
771b13716   Eric W. Biederman   vfs: Add a user n...
2785
  	struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2786
  	if (!IS_ERR(new_ns)) {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2787
2788
  		struct mount *mnt = real_mount(m);
  		mnt->mnt_ns = new_ns;
be08d6d26   Al Viro   switch mnt_namesp...
2789
  		new_ns->root = mnt;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2790
  		new_ns->mounts++;
b1983cd89   Al Viro   create_mnt_ns: un...
2791
  		list_add(&mnt->mnt_list, &new_ns->list);
c13344958   Al Viro   switch create_mnt...
2792
  	} else {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2793
  		mntput(m);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2794
2795
2796
  	}
  	return new_ns;
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2797

ea441d110   Al Viro   new helper: mount...
2798
2799
2800
  struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
  {
  	struct mnt_namespace *ns;
d31da0f0b   Al Viro   mount_subtree() p...
2801
  	struct super_block *s;
ea441d110   Al Viro   new helper: mount...
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
  	struct path path;
  	int err;
  
  	ns = create_mnt_ns(mnt);
  	if (IS_ERR(ns))
  		return ERR_CAST(ns);
  
  	err = vfs_path_lookup(mnt->mnt_root, mnt,
  			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...
2818
2819
  	s = path.mnt->mnt_sb;
  	atomic_inc(&s->s_active);
ea441d110   Al Viro   new helper: mount...
2820
2821
  	mntput(path.mnt);
  	/* lock the sucker */
d31da0f0b   Al Viro   mount_subtree() p...
2822
  	down_write(&s->s_umount);
ea441d110   Al Viro   new helper: mount...
2823
2824
2825
2826
  	/* ... and return the root of (sub)tree on it */
  	return path.dentry;
  }
  EXPORT_SYMBOL(mount_subtree);
312db1aa1   Dominik Brodowski   fs: add ksys_moun...
2827
2828
  int ksys_mount(char __user *dev_name, char __user *dir_name, char __user *type,
  	       unsigned long flags, void __user *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2829
  {
eca6f534e   Vegard Nossum   fs: fix overflow ...
2830
2831
  	int ret;
  	char *kernel_type;
eca6f534e   Vegard Nossum   fs: fix overflow ...
2832
  	char *kernel_dev;
b40ef8696   Al Viro   saner calling con...
2833
  	void *options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2834

b8850d1fa   Tim Gardner   fs: namespace: su...
2835
2836
2837
  	kernel_type = copy_mount_string(type);
  	ret = PTR_ERR(kernel_type);
  	if (IS_ERR(kernel_type))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2838
  		goto out_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2839

b8850d1fa   Tim Gardner   fs: namespace: su...
2840
2841
2842
  	kernel_dev = copy_mount_string(dev_name);
  	ret = PTR_ERR(kernel_dev);
  	if (IS_ERR(kernel_dev))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2843
  		goto out_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2844

b40ef8696   Al Viro   saner calling con...
2845
2846
2847
  	options = copy_mount_options(data);
  	ret = PTR_ERR(options);
  	if (IS_ERR(options))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2848
  		goto out_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2849

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

b40ef8696   Al Viro   saner calling con...
2852
  	kfree(options);
eca6f534e   Vegard Nossum   fs: fix overflow ...
2853
2854
2855
  out_data:
  	kfree(kernel_dev);
  out_dev:
eca6f534e   Vegard Nossum   fs: fix overflow ...
2856
2857
2858
  	kfree(kernel_type);
  out_type:
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2859
  }
312db1aa1   Dominik Brodowski   fs: add ksys_moun...
2860
2861
2862
2863
2864
  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
2865
  /*
afac7cba7   Al Viro   vfs: more mnt_par...
2866
2867
   * Return true if path is reachable from root
   *
48a066e72   Al Viro   RCU'd vfsmounts
2868
   * namespace_sem or mount_lock is held
afac7cba7   Al Viro   vfs: more mnt_par...
2869
   */
643822b41   Al Viro   vfs: spread struc...
2870
  bool is_path_reachable(struct mount *mnt, struct dentry *dentry,
afac7cba7   Al Viro   vfs: more mnt_par...
2871
2872
  			 const struct path *root)
  {
643822b41   Al Viro   vfs: spread struc...
2873
  	while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) {
a73324da7   Al Viro   vfs: move mnt_mou...
2874
  		dentry = mnt->mnt_mountpoint;
0714a5338   Al Viro   vfs: now it can b...
2875
  		mnt = mnt->mnt_parent;
afac7cba7   Al Viro   vfs: more mnt_par...
2876
  	}
643822b41   Al Viro   vfs: spread struc...
2877
  	return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry);
afac7cba7   Al Viro   vfs: more mnt_par...
2878
  }
640eb7e7b   Mickaël Salaün   fs: Constify path...
2879
  bool path_is_under(const struct path *path1, const struct path *path2)
afac7cba7   Al Viro   vfs: more mnt_par...
2880
  {
25ab4c9b1   Yaowei Bai   fs/namespace.c: p...
2881
  	bool res;
48a066e72   Al Viro   RCU'd vfsmounts
2882
  	read_seqlock_excl(&mount_lock);
643822b41   Al Viro   vfs: spread struc...
2883
  	res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
48a066e72   Al Viro   RCU'd vfsmounts
2884
  	read_sequnlock_excl(&mount_lock);
afac7cba7   Al Viro   vfs: more mnt_par...
2885
2886
2887
2888
2889
  	return res;
  }
  EXPORT_SYMBOL(path_is_under);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
   * 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...
2902
2903
2904
2905
   * 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
2906
2907
2908
2909
2910
2911
2912
2913
   * 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...
2914
2915
  SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
  		const char __user *, put_old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2916
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
2917
  	struct path new, old, parent_path, root_parent, root;
84d17192d   Al Viro   get rid of full-h...
2918
2919
  	struct mount *new_mnt, *root_mnt, *old_mnt;
  	struct mountpoint *old_mp, *root_mp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2920
  	int error;
9b40bc90a   Al Viro   get rid of unprot...
2921
  	if (!may_mount())
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2922
  		return -EPERM;
2d8f30380   Al Viro   [PATCH] sanitize ...
2923
  	error = user_path_dir(new_root, &new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2924
2925
  	if (error)
  		goto out0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2926

2d8f30380   Al Viro   [PATCH] sanitize ...
2927
  	error = user_path_dir(put_old, &old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2928
2929
  	if (error)
  		goto out1;
2d8f30380   Al Viro   [PATCH] sanitize ...
2930
  	error = security_sb_pivotroot(&old, &new);
b12cea919   Al Viro   change the lockin...
2931
2932
  	if (error)
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2933

f7ad3c6be   Miklos Szeredi   vfs: add helpers ...
2934
  	get_fs_root(current->fs, &root);
84d17192d   Al Viro   get rid of full-h...
2935
2936
2937
  	old_mp = lock_mount(&old);
  	error = PTR_ERR(old_mp);
  	if (IS_ERR(old_mp))
b12cea919   Al Viro   change the lockin...
2938
  		goto out3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2939
  	error = -EINVAL;
419148da6   Al Viro   vfs: spread struc...
2940
2941
  	new_mnt = real_mount(new.mnt);
  	root_mnt = real_mount(root.mnt);
84d17192d   Al Viro   get rid of full-h...
2942
2943
  	old_mnt = real_mount(old.mnt);
  	if (IS_MNT_SHARED(old_mnt) ||
fc7be130c   Al Viro   vfs: switch pnode...
2944
2945
  		IS_MNT_SHARED(new_mnt->mnt_parent) ||
  		IS_MNT_SHARED(root_mnt->mnt_parent))
b12cea919   Al Viro   change the lockin...
2946
  		goto out4;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2947
  	if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
b12cea919   Al Viro   change the lockin...
2948
  		goto out4;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2949
2950
  	if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
  		goto out4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2951
  	error = -ENOENT;
f3da392e9   Alexey Dobriyan   dcache: extrace a...
2952
  	if (d_unlinked(new.dentry))
b12cea919   Al Viro   change the lockin...
2953
  		goto out4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2954
  	error = -EBUSY;
84d17192d   Al Viro   get rid of full-h...
2955
  	if (new_mnt == root_mnt || old_mnt == root_mnt)
b12cea919   Al Viro   change the lockin...
2956
  		goto out4; /* loop, on the same file system  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2957
  	error = -EINVAL;
8c3ee42e8   Al Viro   [PATCH] get rid o...
2958
  	if (root.mnt->mnt_root != root.dentry)
b12cea919   Al Viro   change the lockin...
2959
  		goto out4; /* not a mountpoint */
676da58df   Al Viro   vfs: spread struc...
2960
  	if (!mnt_has_parent(root_mnt))
b12cea919   Al Viro   change the lockin...
2961
  		goto out4; /* not attached */
84d17192d   Al Viro   get rid of full-h...
2962
  	root_mp = root_mnt->mnt_mp;
2d8f30380   Al Viro   [PATCH] sanitize ...
2963
  	if (new.mnt->mnt_root != new.dentry)
b12cea919   Al Viro   change the lockin...
2964
  		goto out4; /* not a mountpoint */
676da58df   Al Viro   vfs: spread struc...
2965
  	if (!mnt_has_parent(new_mnt))
b12cea919   Al Viro   change the lockin...
2966
  		goto out4; /* not attached */
4ac913785   Jan Blunck   Embed a struct pa...
2967
  	/* make sure we can reach put_old from new_root */
84d17192d   Al Viro   get rid of full-h...
2968
  	if (!is_path_reachable(old_mnt, old.dentry, &new))
b12cea919   Al Viro   change the lockin...
2969
  		goto out4;
0d0826019   Eric W. Biederman   mnt: Prevent pivo...
2970
2971
2972
  	/* make certain new is below the root */
  	if (!is_path_reachable(new_mnt, new.dentry, &root))
  		goto out4;
84d17192d   Al Viro   get rid of full-h...
2973
  	root_mp->m_count++; /* pin it so it won't go away */
719ea2fbb   Al Viro   new helpers: lock...
2974
  	lock_mount_hash();
419148da6   Al Viro   vfs: spread struc...
2975
2976
  	detach_mnt(new_mnt, &parent_path);
  	detach_mnt(root_mnt, &root_parent);
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2977
2978
2979
2980
  	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...
2981
  	/* mount old root on put_old */
84d17192d   Al Viro   get rid of full-h...
2982
  	attach_mnt(root_mnt, old_mnt, old_mp);
4ac913785   Jan Blunck   Embed a struct pa...
2983
  	/* mount new_root on / */
84d17192d   Al Viro   get rid of full-h...
2984
  	attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
2985
  	touch_mnt_namespace(current->nsproxy->mnt_ns);
4fed655c4   Eric W. Biederman   mnt: Clear mnt_ex...
2986
2987
  	/* A moved mount should not expire automatically */
  	list_del_init(&new_mnt->mnt_expire);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
2988
  	put_mountpoint(root_mp);
719ea2fbb   Al Viro   new helpers: lock...
2989
  	unlock_mount_hash();
2d8f30380   Al Viro   [PATCH] sanitize ...
2990
  	chroot_fs_refs(&root, &new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2991
  	error = 0;
b12cea919   Al Viro   change the lockin...
2992
  out4:
84d17192d   Al Viro   get rid of full-h...
2993
  	unlock_mount(old_mp);
b12cea919   Al Viro   change the lockin...
2994
2995
2996
2997
2998
  	if (!error) {
  		path_put(&root_parent);
  		path_put(&parent_path);
  	}
  out3:
8c3ee42e8   Al Viro   [PATCH] get rid o...
2999
  	path_put(&root);
b12cea919   Al Viro   change the lockin...
3000
  out2:
2d8f30380   Al Viro   [PATCH] sanitize ...
3001
  	path_put(&old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3002
  out1:
2d8f30380   Al Viro   [PATCH] sanitize ...
3003
  	path_put(&new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3004
  out0:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3005
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3006
3007
3008
3009
3010
  }
  
  static void __init init_mount_tree(void)
  {
  	struct vfsmount *mnt;
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3011
  	struct mnt_namespace *ns;
ac748a09f   Jan Blunck   Make set_fs_{root...
3012
  	struct path root;
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3013
  	struct file_system_type *type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3014

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3015
3016
3017
3018
3019
  	type = get_fs_type("rootfs");
  	if (!type)
  		panic("Can't find rootfs type");
  	mnt = vfs_kern_mount(type, 0, "rootfs", NULL);
  	put_filesystem(type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3020
3021
  	if (IS_ERR(mnt))
  		panic("Can't create rootfs");
b3e19d924   Nick Piggin   fs: scale mntget/...
3022

3b22edc57   Trond Myklebust   VFS: Switch init_...
3023
3024
  	ns = create_mnt_ns(mnt);
  	if (IS_ERR(ns))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3025
  		panic("Can't allocate initial namespace");
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3026
3027
3028
  
  	init_task.nsproxy->mnt_ns = ns;
  	get_mnt_ns(ns);
be08d6d26   Al Viro   switch mnt_namesp...
3029
3030
  	root.mnt = mnt;
  	root.dentry = mnt->mnt_root;
da362b09e   Eric W. Biederman   umount: Do not al...
3031
  	mnt->mnt_flags |= MNT_LOCKED;
ac748a09f   Jan Blunck   Make set_fs_{root...
3032
3033
3034
  
  	set_fs_pwd(current->fs, &root);
  	set_fs_root(current->fs, &root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3035
  }
74bf17cff   Denis Cheng   fs: remove the un...
3036
  void __init mnt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3037
  {
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3038
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3039

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

0818bf27c   Al Viro   resizable namespa...
3043
  	mount_hashtable = alloc_large_system_hash("Mount-cache",
38129a13e   Al Viro   switch mnt_hash t...
3044
  				sizeof(struct hlist_head),
0818bf27c   Al Viro   resizable namespa...
3045
  				mhash_entries, 19,
3d375d785   Pavel Tatashin   mm: update caller...
3046
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3047
3048
3049
3050
  				&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...
3051
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3052
  				&mp_hash_shift, &mp_hash_mask, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3053

84d17192d   Al Viro   get rid of full-h...
3054
  	if (!mount_hashtable || !mountpoint_hashtable)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3055
3056
  		panic("Failed to allocate mount hash table
  ");
4b93dc9b1   Tejun Heo   sysfs, kernfs: pr...
3057
  	kernfs_init();
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3058
3059
3060
3061
  	err = sysfs_init();
  	if (err)
  		printk(KERN_WARNING "%s: sysfs_init error: %d
  ",
8e24eea72   Harvey Harrison   fs: replace remai...
3062
  			__func__, err);
00d266662   Greg Kroah-Hartman   kobject: convert ...
3063
3064
  	fs_kobj = kobject_create_and_add("fs", NULL);
  	if (!fs_kobj)
8e24eea72   Harvey Harrison   fs: replace remai...
3065
3066
  		printk(KERN_WARNING "%s: kobj create error
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3067
3068
3069
  	init_rootfs();
  	init_mount_tree();
  }
616511d03   Trond Myklebust   VFS: Uninline the...
3070
  void put_mnt_ns(struct mnt_namespace *ns)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3071
  {
d498b25a4   Al Viro   get rid of useles...
3072
  	if (!atomic_dec_and_test(&ns->count))
616511d03   Trond Myklebust   VFS: Uninline the...
3073
  		return;
7b00ed6fe   Al Viro   put_mnt_ns(): use...
3074
  	drop_collected_mounts(&ns->root->mnt);
771b13716   Eric W. Biederman   vfs: Add a user n...
3075
  	free_mnt_ns(ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3076
  }
9d412a43c   Al Viro   vfs: split off vf...
3077
3078
3079
  
  struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
  {
423e0ab08   Tim Chen   VFS : mount lock ...
3080
  	struct vfsmount *mnt;
e462ec50c   David Howells   VFS: Differentiat...
3081
  	mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, data);
423e0ab08   Tim Chen   VFS : mount lock ...
3082
3083
3084
3085
3086
  	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_...
3087
  		real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL;
423e0ab08   Tim Chen   VFS : mount lock ...
3088
3089
  	}
  	return mnt;
9d412a43c   Al Viro   vfs: split off vf...
3090
3091
  }
  EXPORT_SYMBOL_GPL(kern_mount_data);
423e0ab08   Tim Chen   VFS : mount lock ...
3092
3093
3094
3095
3096
  
  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_...
3097
  		real_mount(mnt)->mnt_ns = NULL;
48a066e72   Al Viro   RCU'd vfsmounts
3098
  		synchronize_rcu();	/* yecchhh... */
423e0ab08   Tim Chen   VFS : mount lock ...
3099
3100
3101
3102
  		mntput(mnt);
  	}
  }
  EXPORT_SYMBOL(kern_unmount);
02125a826   Al Viro   fix apparmor dere...
3103
3104
3105
  
  bool our_mnt(struct vfsmount *mnt)
  {
143c8c91c   Al Viro   vfs: mnt_ns moved...
3106
  	return check_mnt(real_mount(mnt));
02125a826   Al Viro   fix apparmor dere...
3107
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
3108

3151527ee   Eric W. Biederman   userns: Don't al...
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
  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;
  }
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3132
3133
  static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
  				int *new_mnt_flags)
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3134
  {
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3135
  	int new_flags = *new_mnt_flags;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3136
  	struct mount *mnt;
e51db7353   Eric W. Biederman   userns: Better re...
3137
  	bool visible = false;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3138

44bb4385c   Al Viro   fs_is_visible onl...
3139
  	down_read(&namespace_sem);
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3140
  	list_for_each_entry(mnt, &ns->list, mnt_list) {
e51db7353   Eric W. Biederman   userns: Better re...
3141
  		struct mount *child;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3142
  		int mnt_flags;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3143
  		if (mnt->mnt.mnt_sb->s_type != new->mnt_sb->s_type)
e51db7353   Eric W. Biederman   userns: Better re...
3144
  			continue;
7e96c1b0e   Eric W. Biederman   mnt: Fix fs_fully...
3145
3146
3147
3148
3149
  		/* 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...
3150
  		/* A local view of the mount flags */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3151
  		mnt_flags = mnt->mnt.mnt_flags;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3152

695e9df01   Eric W. Biederman   mnt: Account for ...
3153
  		/* Don't miss readonly hidden in the superblock flags */
bc98a42c1   David Howells   VFS: Convert sb->...
3154
  		if (sb_rdonly(mnt->mnt.mnt_sb))
695e9df01   Eric W. Biederman   mnt: Account for ...
3155
  			mnt_flags |= MNT_LOCK_READONLY;
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3156
3157
3158
  		/* Verify the mount flags are equal to or more permissive
  		 * than the proposed new mount.
  		 */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3159
  		if ((mnt_flags & MNT_LOCK_READONLY) &&
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3160
3161
  		    !(new_flags & MNT_READONLY))
  			continue;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3162
3163
  		if ((mnt_flags & MNT_LOCK_ATIME) &&
  		    ((mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3164
  			continue;
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3165
3166
3167
  		/* 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...
3168
3169
3170
  		 */
  		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...
3171
  			/* Only worry about locked mounts */
d71ed6c93   Eric W. Biederman   mnt: fs_fully_vis...
3172
  			if (!(child->mnt.mnt_flags & MNT_LOCKED))
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3173
  				continue;
7236c85e1   Eric W. Biederman   mnt: Update fs_fu...
3174
3175
  			/* Is the directory permanetly empty? */
  			if (!is_empty_dir_inode(inode))
e51db7353   Eric W. Biederman   userns: Better re...
3176
  				goto next;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3177
  		}
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3178
  		/* Preserve the locked attributes */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3179
  		*new_mnt_flags |= mnt_flags & (MNT_LOCK_READONLY | \
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3180
  					       MNT_LOCK_ATIME);
e51db7353   Eric W. Biederman   userns: Better re...
3181
3182
3183
  		visible = true;
  		goto found;
  	next:	;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3184
  	}
e51db7353   Eric W. Biederman   userns: Better re...
3185
  found:
44bb4385c   Al Viro   fs_is_visible onl...
3186
  	up_read(&namespace_sem);
e51db7353   Eric W. Biederman   userns: Better re...
3187
  	return visible;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3188
  }
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3189
3190
  static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
  {
a1935c173   Eric W. Biederman   mnt: Simplify mou...
3191
  	const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
  	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? */
  	s_iflags = mnt->mnt_sb->s_iflags;
  	if (!(s_iflags & SB_I_USERNS_VISIBLE))
  		return false;
a1935c173   Eric W. Biederman   mnt: Simplify mou...
3202
3203
3204
3205
3206
3207
  	if ((s_iflags & required_iflags) != required_iflags) {
  		WARN_ONCE(1, "Expected s_iflags to contain 0x%lx
  ",
  			  required_iflags);
  		return true;
  	}
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3208
3209
  	return !mnt_already_visible(ns, mnt, new_mnt_flags);
  }
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
  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...
3222
  static struct ns_common *mntns_get(struct task_struct *task)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3223
  {
58be28256   Al Viro   make mntns ->get(...
3224
  	struct ns_common *ns = NULL;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3225
  	struct nsproxy *nsproxy;
728dba3a3   Eric W. Biederman   namespaces: Use t...
3226
3227
  	task_lock(task);
  	nsproxy = task->nsproxy;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3228
  	if (nsproxy) {
58be28256   Al Viro   make mntns ->get(...
3229
3230
  		ns = &nsproxy->mnt_ns->ns;
  		get_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3231
  	}
728dba3a3   Eric W. Biederman   namespaces: Use t...
3232
  	task_unlock(task);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3233
3234
3235
  
  	return ns;
  }
64964528b   Al Viro   make proc_ns_oper...
3236
  static void mntns_put(struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3237
  {
58be28256   Al Viro   make mntns ->get(...
3238
  	put_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3239
  }
64964528b   Al Viro   make proc_ns_oper...
3240
  static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3241
3242
  {
  	struct fs_struct *fs = current->fs;
4f757f3cb   Al Viro   make sure that mn...
3243
  	struct mnt_namespace *mnt_ns = to_mnt_ns(ns), *old_mnt_ns;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3244
  	struct path root;
4f757f3cb   Al Viro   make sure that mn...
3245
  	int err;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3246

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3247
  	if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
c7b96acf1   Eric W. Biederman   userns: Kill nso...
3248
3249
  	    !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
  	    !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
ae11e0f18   Zhao Hongjiang   userns: fix retur...
3250
  		return -EPERM;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3251
3252
3253
3254
3255
  
  	if (fs->users != 1)
  		return -EINVAL;
  
  	get_mnt_ns(mnt_ns);
4f757f3cb   Al Viro   make sure that mn...
3256
  	old_mnt_ns = nsproxy->mnt_ns;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3257
3258
3259
  	nsproxy->mnt_ns = mnt_ns;
  
  	/* Find the root */
4f757f3cb   Al Viro   make sure that mn...
3260
3261
3262
3263
3264
3265
3266
3267
  	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...
3268

4068367c9   Andrei Vagin   fs: don't forget ...
3269
  	put_mnt_ns(old_mnt_ns);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3270
3271
3272
3273
3274
3275
3276
  	/* 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...
3277
3278
3279
3280
  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...
3281
3282
3283
3284
3285
3286
  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...
3287
  	.owner		= mntns_owner,
8823c079b   Eric W. Biederman   vfs: Add setns su...
3288
  };