Blame view

fs/namespace.c 85.5 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);
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
61
  static DEFINE_SPINLOCK(mnt_id_lock);
f21f62208   Al Viro   ... and the same ...
62
63
  static int mnt_id_start = 0;
  static int mnt_group_start = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

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

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

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

38129a13e   Al Viro   switch mnt_hash t...
84
  static inline struct hlist_head *m_hash(struct vfsmount *mnt, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  {
b58fed8b1   Ram Pai   [PATCH] lindent f...
86
87
  	unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES);
  	tmp += ((unsigned long)dentry / L1_CACHE_BYTES);
0818bf27c   Al Viro   resizable namespa...
88
89
90
91
92
93
94
95
96
  	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
97
  }
b105e270b   Al Viro   vfs: spread struc...
98
  static int mnt_alloc_id(struct mount *mnt)
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
99
100
101
102
103
  {
  	int res;
  
  retry:
  	ida_pre_get(&mnt_id_ida, GFP_KERNEL);
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
104
  	spin_lock(&mnt_id_lock);
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
105
  	res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id);
f21f62208   Al Viro   ... and the same ...
106
  	if (!res)
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
107
  		mnt_id_start = mnt->mnt_id + 1;
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
108
  	spin_unlock(&mnt_id_lock);
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
109
110
111
112
113
  	if (res == -EAGAIN)
  		goto retry;
  
  	return res;
  }
b105e270b   Al Viro   vfs: spread struc...
114
  static void mnt_free_id(struct mount *mnt)
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
115
  {
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
116
  	int id = mnt->mnt_id;
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
117
  	spin_lock(&mnt_id_lock);
f21f62208   Al Viro   ... and the same ...
118
119
120
  	ida_remove(&mnt_id_ida, id);
  	if (mnt_id_start > id)
  		mnt_id_start = id;
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
121
  	spin_unlock(&mnt_id_lock);
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
122
  }
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
123
124
125
126
127
  /*
   * Allocate a new peer group ID
   *
   * mnt_group_ida is protected by namespace_sem
   */
4b8b21f4f   Al Viro   vfs: spread struc...
128
  static int mnt_alloc_group_id(struct mount *mnt)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
129
  {
f21f62208   Al Viro   ... and the same ...
130
  	int res;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
131
132
  	if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
  		return -ENOMEM;
f21f62208   Al Viro   ... and the same ...
133
134
  	res = ida_get_new_above(&mnt_group_ida,
  				mnt_group_start,
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
135
  				&mnt->mnt_group_id);
f21f62208   Al Viro   ... and the same ...
136
  	if (!res)
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
137
  		mnt_group_start = mnt->mnt_group_id + 1;
f21f62208   Al Viro   ... and the same ...
138
139
  
  	return res;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
140
141
142
143
144
  }
  
  /*
   * Release a peer group ID
   */
4b8b21f4f   Al Viro   vfs: spread struc...
145
  void mnt_release_group_id(struct mount *mnt)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
146
  {
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
147
  	int id = mnt->mnt_group_id;
f21f62208   Al Viro   ... and the same ...
148
149
150
  	ida_remove(&mnt_group_ida, id);
  	if (mnt_group_start > id)
  		mnt_group_start = id;
15169fe78   Al Viro   vfs: mnt_id/mnt_g...
151
  	mnt->mnt_group_id = 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
152
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
153
154
155
  /*
   * vfsmount lock must be held for read
   */
83adc7532   Al Viro   vfs: spread struc...
156
  static inline void mnt_add_count(struct mount *mnt, int n)
b3e19d924   Nick Piggin   fs: scale mntget/...
157
158
  {
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
159
  	this_cpu_add(mnt->mnt_pcp->mnt_count, n);
b3e19d924   Nick Piggin   fs: scale mntget/...
160
161
  #else
  	preempt_disable();
68e8a9fea   Al Viro   vfs: all counters...
162
  	mnt->mnt_count += n;
b3e19d924   Nick Piggin   fs: scale mntget/...
163
164
165
  	preempt_enable();
  #endif
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
166
167
168
  /*
   * vfsmount lock must be held for write
   */
83adc7532   Al Viro   vfs: spread struc...
169
  unsigned int mnt_get_count(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
170
171
  {
  #ifdef CONFIG_SMP
f03c65993   Al Viro   sanitize vfsmount...
172
  	unsigned int count = 0;
b3e19d924   Nick Piggin   fs: scale mntget/...
173
174
175
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
68e8a9fea   Al Viro   vfs: all counters...
176
  		count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count;
b3e19d924   Nick Piggin   fs: scale mntget/...
177
178
179
180
  	}
  
  	return count;
  #else
68e8a9fea   Al Viro   vfs: all counters...
181
  	return mnt->mnt_count;
b3e19d924   Nick Piggin   fs: scale mntget/...
182
183
  #endif
  }
87b95ce09   Al Viro   switch the IO-tri...
184
185
186
187
188
189
190
  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...
191
  static struct mount *alloc_vfsmnt(const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  {
c63181e6b   Al Viro   vfs: move fsnotif...
193
194
  	struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
  	if (mnt) {
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
195
  		int err;
c63181e6b   Al Viro   vfs: move fsnotif...
196
  		err = mnt_alloc_id(mnt);
88b387824   Li Zefan   [PATCH] vfs: use ...
197
198
199
200
  		if (err)
  			goto out_free_cache;
  
  		if (name) {
fcc139ae2   Andrzej Hajda   fs/namespace: con...
201
  			mnt->mnt_devname = kstrdup_const(name, GFP_KERNEL);
c63181e6b   Al Viro   vfs: move fsnotif...
202
  			if (!mnt->mnt_devname)
88b387824   Li Zefan   [PATCH] vfs: use ...
203
  				goto out_free_id;
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
204
  		}
b3e19d924   Nick Piggin   fs: scale mntget/...
205
  #ifdef CONFIG_SMP
c63181e6b   Al Viro   vfs: move fsnotif...
206
207
  		mnt->mnt_pcp = alloc_percpu(struct mnt_pcp);
  		if (!mnt->mnt_pcp)
b3e19d924   Nick Piggin   fs: scale mntget/...
208
  			goto out_free_devname;
c63181e6b   Al Viro   vfs: move fsnotif...
209
  		this_cpu_add(mnt->mnt_pcp->mnt_count, 1);
b3e19d924   Nick Piggin   fs: scale mntget/...
210
  #else
c63181e6b   Al Viro   vfs: move fsnotif...
211
212
  		mnt->mnt_count = 1;
  		mnt->mnt_writers = 0;
b3e19d924   Nick Piggin   fs: scale mntget/...
213
  #endif
38129a13e   Al Viro   switch mnt_hash t...
214
  		INIT_HLIST_NODE(&mnt->mnt_hash);
c63181e6b   Al Viro   vfs: move fsnotif...
215
216
217
218
219
220
221
  		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 ...
222
  		INIT_HLIST_NODE(&mnt->mnt_mp_list);
99b19d164   Eric W. Biederman   mnt: In propgate_...
223
  		INIT_LIST_HEAD(&mnt->mnt_umounting);
87b95ce09   Al Viro   switch the IO-tri...
224
  		init_fs_pin(&mnt->mnt_umount, drop_mountpoint);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  	}
c63181e6b   Al Viro   vfs: move fsnotif...
226
  	return mnt;
88b387824   Li Zefan   [PATCH] vfs: use ...
227

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
228
229
  #ifdef CONFIG_SMP
  out_free_devname:
fcc139ae2   Andrzej Hajda   fs/namespace: con...
230
  	kfree_const(mnt->mnt_devname);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
231
  #endif
88b387824   Li Zefan   [PATCH] vfs: use ...
232
  out_free_id:
c63181e6b   Al Viro   vfs: move fsnotif...
233
  	mnt_free_id(mnt);
88b387824   Li Zefan   [PATCH] vfs: use ...
234
  out_free_cache:
c63181e6b   Al Viro   vfs: move fsnotif...
235
  	kmem_cache_free(mnt_cache, mnt);
88b387824   Li Zefan   [PATCH] vfs: use ...
236
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
  }
8366025eb   Dave Hansen   [PATCH] r/o bind ...
238
239
240
241
242
243
244
245
  /*
   * 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 ...
246
247
248
249
250
251
252
253
254
255
256
257
258
  /*
   * __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 ...
259
260
  	if (mnt->mnt_flags & MNT_READONLY)
  		return 1;
bc98a42c1   David Howells   VFS: Convert sb->...
261
  	if (sb_rdonly(mnt->mnt_sb))
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
262
263
  		return 1;
  	return 0;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
264
265
  }
  EXPORT_SYMBOL_GPL(__mnt_is_readonly);
83adc7532   Al Viro   vfs: spread struc...
266
  static inline void mnt_inc_writers(struct mount *mnt)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
267
268
  {
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
269
  	this_cpu_inc(mnt->mnt_pcp->mnt_writers);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
270
  #else
68e8a9fea   Al Viro   vfs: all counters...
271
  	mnt->mnt_writers++;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
272
273
  #endif
  }
3d733633a   Dave Hansen   [PATCH] r/o bind ...
274

83adc7532   Al Viro   vfs: spread struc...
275
  static inline void mnt_dec_writers(struct mount *mnt)
3d733633a   Dave Hansen   [PATCH] r/o bind ...
276
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
277
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
278
  	this_cpu_dec(mnt->mnt_pcp->mnt_writers);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
279
  #else
68e8a9fea   Al Viro   vfs: all counters...
280
  	mnt->mnt_writers--;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
281
  #endif
3d733633a   Dave Hansen   [PATCH] r/o bind ...
282
  }
3d733633a   Dave Hansen   [PATCH] r/o bind ...
283

83adc7532   Al Viro   vfs: spread struc...
284
  static unsigned int mnt_get_writers(struct mount *mnt)
3d733633a   Dave Hansen   [PATCH] r/o bind ...
285
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
286
287
  #ifdef CONFIG_SMP
  	unsigned int count = 0;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
288
  	int cpu;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
289
290
  
  	for_each_possible_cpu(cpu) {
68e8a9fea   Al Viro   vfs: all counters...
291
  		count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_writers;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
292
  	}
3d733633a   Dave Hansen   [PATCH] r/o bind ...
293

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
294
295
296
297
  	return count;
  #else
  	return mnt->mnt_writers;
  #endif
3d733633a   Dave Hansen   [PATCH] r/o bind ...
298
  }
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
299
300
301
302
303
304
305
306
  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 ...
307
  /*
eb04c2828   Jan Kara   fs: Add freezing ...
308
309
310
311
   * 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 ...
312
   */
8366025eb   Dave Hansen   [PATCH] r/o bind ...
313
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
314
   * __mnt_want_write - get write access to a mount without freeze protection
83adc7532   Al Viro   vfs: spread struc...
315
   * @m: the mount on which to take a write
8366025eb   Dave Hansen   [PATCH] r/o bind ...
316
   *
eb04c2828   Jan Kara   fs: Add freezing ...
317
318
319
320
321
   * 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 ...
322
   */
eb04c2828   Jan Kara   fs: Add freezing ...
323
  int __mnt_want_write(struct vfsmount *m)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
324
  {
83adc7532   Al Viro   vfs: spread struc...
325
  	struct mount *mnt = real_mount(m);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
326
  	int ret = 0;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
327

d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
328
  	preempt_disable();
c6653a838   Nick Piggin   fs: rename vfsmou...
329
  	mnt_inc_writers(mnt);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
330
  	/*
c6653a838   Nick Piggin   fs: rename vfsmou...
331
  	 * The store to mnt_inc_writers must be visible before we pass
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
332
333
334
335
  	 * MNT_WRITE_HOLD loop below, so that the slowpath can see our
  	 * incremented count after it has set MNT_WRITE_HOLD.
  	 */
  	smp_mb();
1e75529e3   Miao Xie   vfs, freeze: use ...
336
  	while (ACCESS_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
337
338
339
340
341
342
343
  		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...
344
  	if (mnt_is_readonly(m)) {
c6653a838   Nick Piggin   fs: rename vfsmou...
345
  		mnt_dec_writers(mnt);
3d733633a   Dave Hansen   [PATCH] r/o bind ...
346
  		ret = -EROFS;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
347
  	}
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
348
  	preempt_enable();
eb04c2828   Jan Kara   fs: Add freezing ...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  
  	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 ...
370
  	return ret;
8366025eb   Dave Hansen   [PATCH] r/o bind ...
371
372
373
374
  }
  EXPORT_SYMBOL_GPL(mnt_want_write);
  
  /**
96029c4e0   npiggin@suse.de   fs: introduce mnt...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
   * 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...
392
  	mnt_inc_writers(real_mount(mnt));
96029c4e0   npiggin@suse.de   fs: introduce mnt...
393
394
395
396
397
398
  	preempt_enable();
  	return 0;
  }
  EXPORT_SYMBOL_GPL(mnt_clone_write);
  
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
399
   * __mnt_want_write_file - get write access to a file's mount
96029c4e0   npiggin@suse.de   fs: introduce mnt...
400
401
   * @file: the file who's mount on which to take a write
   *
eb04c2828   Jan Kara   fs: Add freezing ...
402
   * This is like __mnt_want_write, but it takes a file and can
96029c4e0   npiggin@suse.de   fs: introduce mnt...
403
404
   * do some optimisations if the file is open for write already
   */
eb04c2828   Jan Kara   fs: Add freezing ...
405
  int __mnt_want_write_file(struct file *file)
96029c4e0   npiggin@suse.de   fs: introduce mnt...
406
  {
83f936c75   Al Viro   mark struct file ...
407
  	if (!(file->f_mode & FMODE_WRITER))
eb04c2828   Jan Kara   fs: Add freezing ...
408
  		return __mnt_want_write(file->f_path.mnt);
96029c4e0   npiggin@suse.de   fs: introduce mnt...
409
410
411
  	else
  		return mnt_clone_write(file->f_path.mnt);
  }
eb04c2828   Jan Kara   fs: Add freezing ...
412
413
  
  /**
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
414
   * mnt_want_write_file_path - get write access to a file's mount
eb04c2828   Jan Kara   fs: Add freezing ...
415
416
417
418
   * @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 ...
419
420
421
422
423
   *
   * Called by the vfs for cases when we have an open file at hand, but will do an
   * inode operation on it (important distinction for files opened on overlayfs,
   * since the file operations will come from the real underlying file, while
   * inode operations come from the overlay).
eb04c2828   Jan Kara   fs: Add freezing ...
424
   */
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
425
  int mnt_want_write_file_path(struct file *file)
eb04c2828   Jan Kara   fs: Add freezing ...
426
427
428
429
430
431
432
433
434
  {
  	int ret;
  
  	sb_start_write(file->f_path.mnt->mnt_sb);
  	ret = __mnt_want_write_file(file);
  	if (ret)
  		sb_end_write(file->f_path.mnt->mnt_sb);
  	return ret;
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
  
  static inline int may_write_real(struct file *file)
  {
  	struct dentry *dentry = file->f_path.dentry;
  	struct dentry *upperdentry;
  
  	/* Writable file? */
  	if (file->f_mode & FMODE_WRITER)
  		return 0;
  
  	/* Not overlayfs? */
  	if (likely(!(dentry->d_flags & DCACHE_OP_REAL)))
  		return 0;
  
  	/* File refers to upper, writable layer? */
  	upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER);
954c736f8   Amir Goldstein   ovl: fix may_writ...
451
452
453
  	if (upperdentry &&
  	    (file_inode(file) == d_inode(upperdentry) ||
  	     file_inode(file) == d_inode(dentry)))
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  		return 0;
  
  	/* Lower layer: can't write to real file, sorry... */
  	return -EPERM;
  }
  
  /**
   * 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
   *
   * Mostly called by filesystems from their ioctl operation before performing
   * modification.  On overlayfs this needs to check if the file is on a read-only
   * lower layer and deny access in that case.
   */
  int mnt_want_write_file(struct file *file)
  {
  	int ret;
  
  	ret = may_write_real(file);
  	if (!ret) {
  		sb_start_write(file_inode(file)->i_sb);
  		ret = __mnt_want_write_file(file);
  		if (ret)
  			sb_end_write(file_inode(file)->i_sb);
  	}
  	return ret;
  }
96029c4e0   npiggin@suse.de   fs: introduce mnt...
484
485
486
  EXPORT_SYMBOL_GPL(mnt_want_write_file);
  
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
487
   * __mnt_drop_write - give up write access to a mount
8366025eb   Dave Hansen   [PATCH] r/o bind ...
488
489
490
491
   * @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 ...
492
   * __mnt_want_write() call above.
8366025eb   Dave Hansen   [PATCH] r/o bind ...
493
   */
eb04c2828   Jan Kara   fs: Add freezing ...
494
  void __mnt_drop_write(struct vfsmount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
495
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
496
  	preempt_disable();
83adc7532   Al Viro   vfs: spread struc...
497
  	mnt_dec_writers(real_mount(mnt));
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
498
  	preempt_enable();
8366025eb   Dave Hansen   [PATCH] r/o bind ...
499
  }
eb04c2828   Jan Kara   fs: Add freezing ...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  
  /**
   * 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 ...
514
  EXPORT_SYMBOL_GPL(mnt_drop_write);
eb04c2828   Jan Kara   fs: Add freezing ...
515
516
517
518
  void __mnt_drop_write_file(struct file *file)
  {
  	__mnt_drop_write(file->f_path.mnt);
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
519
  void mnt_drop_write_file_path(struct file *file)
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
520
521
522
  {
  	mnt_drop_write(file->f_path.mnt);
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
523
524
525
526
527
528
  
  void mnt_drop_write_file(struct file *file)
  {
  	__mnt_drop_write(file->f_path.mnt);
  	sb_end_write(file_inode(file)->i_sb);
  }
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
529
  EXPORT_SYMBOL(mnt_drop_write_file);
83adc7532   Al Viro   vfs: spread struc...
530
  static int mnt_make_readonly(struct mount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
531
  {
3d733633a   Dave Hansen   [PATCH] r/o bind ...
532
  	int ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
533
  	lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
534
  	mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
535
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
536
537
  	 * 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 ...
538
  	 */
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
539
  	smp_mb();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
540
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  	 * 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 ...
555
  	 */
c6653a838   Nick Piggin   fs: rename vfsmou...
556
  	if (mnt_get_writers(mnt) > 0)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
557
558
  		ret = -EBUSY;
  	else
83adc7532   Al Viro   vfs: spread struc...
559
  		mnt->mnt.mnt_flags |= MNT_READONLY;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
560
561
562
563
564
  	/*
  	 * 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...
565
  	mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
719ea2fbb   Al Viro   new helpers: lock...
566
  	unlock_mount_hash();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
567
  	return ret;
8366025eb   Dave Hansen   [PATCH] r/o bind ...
568
  }
8366025eb   Dave Hansen   [PATCH] r/o bind ...
569

83adc7532   Al Viro   vfs: spread struc...
570
  static void __mnt_unmake_readonly(struct mount *mnt)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
571
  {
719ea2fbb   Al Viro   new helpers: lock...
572
  	lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
573
  	mnt->mnt.mnt_flags &= ~MNT_READONLY;
719ea2fbb   Al Viro   new helpers: lock...
574
  	unlock_mount_hash();
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
575
  }
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
576
577
578
579
  int sb_prepare_remount_readonly(struct super_block *sb)
  {
  	struct mount *mnt;
  	int err = 0;
8e8b87964   Miklos Szeredi   vfs: prevent remo...
580
581
582
  	/* 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...
583
  	lock_mount_hash();
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
584
585
586
587
588
589
590
591
592
593
  	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...
594
595
  	if (!err && atomic_long_read(&sb->s_remove_count))
  		err = -EBUSY;
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
596
597
598
599
600
601
602
603
  	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...
604
  	unlock_mount_hash();
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
605
606
607
  
  	return err;
  }
b105e270b   Al Viro   vfs: spread struc...
608
  static void free_vfsmnt(struct mount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  {
fcc139ae2   Andrzej Hajda   fs/namespace: con...
610
  	kfree_const(mnt->mnt_devname);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
611
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
612
  	free_percpu(mnt->mnt_pcp);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
613
  #endif
b105e270b   Al Viro   vfs: spread struc...
614
  	kmem_cache_free(mnt_cache, mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
  }
8ffcb32e0   David Howells   VFS: Make delayed...
616
617
618
619
  static void delayed_free_vfsmnt(struct rcu_head *head)
  {
  	free_vfsmnt(container_of(head, struct mount, mnt_rcu));
  }
48a066e72   Al Viro   RCU'd vfsmounts
620
  /* call under rcu_read_lock */
294d71ff2   Al Viro   new helper: __leg...
621
  int __legitimize_mnt(struct vfsmount *bastard, unsigned seq)
48a066e72   Al Viro   RCU'd vfsmounts
622
623
624
  {
  	struct mount *mnt;
  	if (read_seqretry(&mount_lock, seq))
294d71ff2   Al Viro   new helper: __leg...
625
  		return 1;
48a066e72   Al Viro   RCU'd vfsmounts
626
  	if (bastard == NULL)
294d71ff2   Al Viro   new helper: __leg...
627
  		return 0;
48a066e72   Al Viro   RCU'd vfsmounts
628
629
630
  	mnt = real_mount(bastard);
  	mnt_add_count(mnt, 1);
  	if (likely(!read_seqretry(&mount_lock, seq)))
294d71ff2   Al Viro   new helper: __leg...
631
  		return 0;
48a066e72   Al Viro   RCU'd vfsmounts
632
633
  	if (bastard->mnt_flags & MNT_SYNC_UMOUNT) {
  		mnt_add_count(mnt, -1);
294d71ff2   Al Viro   new helper: __leg...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  		return 1;
  	}
  	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
649
  	}
48a066e72   Al Viro   RCU'd vfsmounts
650
651
  	return false;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  /*
474279dc0   Al Viro   split __lookup_mn...
653
   * find the first mount at @dentry on vfsmount @mnt.
48a066e72   Al Viro   RCU'd vfsmounts
654
   * call under rcu_read_lock()
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
   */
474279dc0   Al Viro   split __lookup_mn...
656
  struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  {
38129a13e   Al Viro   switch mnt_hash t...
658
  	struct hlist_head *head = m_hash(mnt, dentry);
474279dc0   Al Viro   split __lookup_mn...
659
  	struct mount *p;
38129a13e   Al Viro   switch mnt_hash t...
660
  	hlist_for_each_entry_rcu(p, head, mnt_hash)
474279dc0   Al Viro   split __lookup_mn...
661
662
663
664
665
666
  		if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
  			return p;
  	return NULL;
  }
  
  /*
f015f1267   David Howells   VFS: Comment moun...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
   * 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...
681
   */
ca71cf71e   Al Viro   namespace.c: cons...
682
  struct vfsmount *lookup_mnt(const struct path *path)
a05964f39   Ram Pai   [PATCH] shared mo...
683
  {
c71053659   Al Viro   vfs: spread struc...
684
  	struct mount *child_mnt;
48a066e72   Al Viro   RCU'd vfsmounts
685
686
  	struct vfsmount *m;
  	unsigned seq;
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
687

48a066e72   Al Viro   RCU'd vfsmounts
688
689
690
691
692
693
694
695
  	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...
696
  }
7af1364ff   Eric W. Biederman   vfs: Don't allow ...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
  /*
   * __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...
731
  static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
84d17192d   Al Viro   get rid of full-h...
732
  {
0818bf27c   Al Viro   resizable namespa...
733
  	struct hlist_head *chain = mp_hash(dentry);
84d17192d   Al Viro   get rid of full-h...
734
  	struct mountpoint *mp;
0818bf27c   Al Viro   resizable namespa...
735
  	hlist_for_each_entry(mp, chain, m_hash) {
84d17192d   Al Viro   get rid of full-h...
736
737
738
739
740
741
742
743
  		if (mp->m_dentry == dentry) {
  			/* might be worth a WARN_ON() */
  			if (d_unlinked(dentry))
  				return ERR_PTR(-ENOENT);
  			mp->m_count++;
  			return mp;
  		}
  	}
e2dfa9354   Eric W. Biederman   vfs: factor out l...
744
745
  	return NULL;
  }
3895dbf89   Eric W. Biederman   mnt: Protect the ...
746
  static struct mountpoint *get_mountpoint(struct dentry *dentry)
e2dfa9354   Eric W. Biederman   vfs: factor out l...
747
  {
3895dbf89   Eric W. Biederman   mnt: Protect the ...
748
  	struct mountpoint *mp, *new = NULL;
e2dfa9354   Eric W. Biederman   vfs: factor out l...
749
  	int ret;
84d17192d   Al Viro   get rid of full-h...
750

3895dbf89   Eric W. Biederman   mnt: Protect the ...
751
752
753
754
755
756
757
758
759
760
761
762
  	if (d_mountpoint(dentry)) {
  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...
763
  		return ERR_PTR(-ENOMEM);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
764
765
  
  	/* Exactly one processes may set d_mounted */
eed810076   Miklos Szeredi   vfs: check unlink...
766
  	ret = d_set_mounted(dentry);
eed810076   Miklos Szeredi   vfs: check unlink...
767

3895dbf89   Eric W. Biederman   mnt: Protect the ...
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
  	/* 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...
789
790
791
792
793
794
795
  	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 ...
796
  		BUG_ON(!hlist_empty(&mp->m_list));
84d17192d   Al Viro   get rid of full-h...
797
798
799
  		spin_lock(&dentry->d_lock);
  		dentry->d_flags &= ~DCACHE_MOUNTED;
  		spin_unlock(&dentry->d_lock);
0818bf27c   Al Viro   resizable namespa...
800
  		hlist_del(&mp->m_hash);
84d17192d   Al Viro   get rid of full-h...
801
802
803
  		kfree(mp);
  	}
  }
143c8c91c   Al Viro   vfs: mnt_ns moved...
804
  static inline int check_mnt(struct mount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
806
  	return mnt->mnt_ns == current->nsproxy->mnt_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
808
809
810
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
811
  static void touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
812
813
814
815
816
817
  {
  	if (ns) {
  		ns->event = ++event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
818
819
820
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
821
  static void __touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
822
823
824
825
826
827
  {
  	if (ns && ns->event != event) {
  		ns->event = event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
828
829
830
  /*
   * vfsmount lock must be held for write
   */
7bdb11de8   Eric W. Biederman   mnt: Factor out u...
831
  static void unhash_mnt(struct mount *mnt)
419148da6   Al Viro   vfs: spread struc...
832
  {
0714a5338   Al Viro   vfs: now it can b...
833
  	mnt->mnt_parent = mnt;
a73324da7   Al Viro   vfs: move mnt_mou...
834
  	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
6b41d536f   Al Viro   vfs: take mnt_chi...
835
  	list_del_init(&mnt->mnt_child);
38129a13e   Al Viro   switch mnt_hash t...
836
  	hlist_del_init_rcu(&mnt->mnt_hash);
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
837
  	hlist_del_init(&mnt->mnt_mp_list);
84d17192d   Al Viro   get rid of full-h...
838
839
  	put_mountpoint(mnt->mnt_mp);
  	mnt->mnt_mp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
841
842
843
  /*
   * vfsmount lock must be held for write
   */
7bdb11de8   Eric W. Biederman   mnt: Factor out u...
844
845
846
847
848
849
850
851
852
853
  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...
854
855
856
857
858
859
860
861
862
863
  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...
864
865
  void mnt_set_mountpoint(struct mount *mnt,
  			struct mountpoint *mp,
44d964d60   Al Viro   vfs: spread struc...
866
  			struct mount *child_mnt)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
867
  {
84d17192d   Al Viro   get rid of full-h...
868
  	mp->m_count++;
3a2393d71   Al Viro   vfs: opencode mnt...
869
  	mnt_add_count(mnt, 1);	/* essentially, that's mntget */
84d17192d   Al Viro   get rid of full-h...
870
  	child_mnt->mnt_mountpoint = dget(mp->m_dentry);
3a2393d71   Al Viro   vfs: opencode mnt...
871
  	child_mnt->mnt_parent = mnt;
84d17192d   Al Viro   get rid of full-h...
872
  	child_mnt->mnt_mp = mp;
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
873
  	hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
874
  }
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
875
876
877
878
879
880
  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...
881
882
883
  /*
   * vfsmount lock must be held for write
   */
84d17192d   Al Viro   get rid of full-h...
884
885
886
  static void attach_mnt(struct mount *mnt,
  			struct mount *parent,
  			struct mountpoint *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
887
  {
84d17192d   Al Viro   get rid of full-h...
888
  	mnt_set_mountpoint(parent, mp, mnt);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
889
  	__attach_mnt(mnt, parent);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
890
  }
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
891
  void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct mount *mnt)
12a5b5294   Al Viro   fix copy_tree() r...
892
  {
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
  	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...
921
  }
b90fa9ae8   Ram Pai   [PATCH] shared mo...
922
  /*
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
923
   * vfsmount lock must be held for write
b90fa9ae8   Ram Pai   [PATCH] shared mo...
924
   */
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
925
  static void commit_tree(struct mount *mnt)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
926
  {
0714a5338   Al Viro   vfs: now it can b...
927
  	struct mount *parent = mnt->mnt_parent;
83adc7532   Al Viro   vfs: spread struc...
928
  	struct mount *m;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
929
  	LIST_HEAD(head);
143c8c91c   Al Viro   vfs: mnt_ns moved...
930
  	struct mnt_namespace *n = parent->mnt_ns;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
931

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

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

b90fa9ae8   Ram Pai   [PATCH] shared mo...
938
  	list_splice(&head, n->list.prev);
d29216842   Eric W. Biederman   mnt: Add a per mo...
939
940
  	n->mounts += n->pending_mounts;
  	n->pending_mounts = 0;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
941
  	__attach_mnt(mnt, parent);
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
942
  	touch_mnt_namespace(n);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
  }
909b0a88e   Al Viro   vfs: spread struc...
944
  static struct mount *next_mnt(struct mount *p, struct mount *root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
  {
6b41d536f   Al Viro   vfs: take mnt_chi...
946
947
  	struct list_head *next = p->mnt_mounts.next;
  	if (next == &p->mnt_mounts) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
  		while (1) {
909b0a88e   Al Viro   vfs: spread struc...
949
  			if (p == root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
  				return NULL;
6b41d536f   Al Viro   vfs: take mnt_chi...
951
952
  			next = p->mnt_child.next;
  			if (next != &p->mnt_parent->mnt_mounts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
  				break;
0714a5338   Al Viro   vfs: now it can b...
954
  			p = p->mnt_parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
956
  		}
  	}
6b41d536f   Al Viro   vfs: take mnt_chi...
957
  	return list_entry(next, struct mount, mnt_child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  }
315fc83e5   Al Viro   vfs: spread struc...
959
  static struct mount *skip_mnt_tree(struct mount *p)
9676f0c63   Ram Pai   [PATCH] unbindabl...
960
  {
6b41d536f   Al Viro   vfs: take mnt_chi...
961
962
963
964
  	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...
965
966
967
  	}
  	return p;
  }
9d412a43c   Al Viro   vfs: split off vf...
968
969
970
  struct vfsmount *
  vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
  {
b105e270b   Al Viro   vfs: spread struc...
971
  	struct mount *mnt;
9d412a43c   Al Viro   vfs: split off vf...
972
973
974
975
976
977
978
979
  	struct dentry *root;
  
  	if (!type)
  		return ERR_PTR(-ENODEV);
  
  	mnt = alloc_vfsmnt(name);
  	if (!mnt)
  		return ERR_PTR(-ENOMEM);
e462ec50c   David Howells   VFS: Differentiat...
980
  	if (flags & SB_KERNMOUNT)
b105e270b   Al Viro   vfs: spread struc...
981
  		mnt->mnt.mnt_flags = MNT_INTERNAL;
9d412a43c   Al Viro   vfs: split off vf...
982
983
984
  
  	root = mount_fs(type, flags, name, data);
  	if (IS_ERR(root)) {
8ffcb32e0   David Howells   VFS: Make delayed...
985
  		mnt_free_id(mnt);
9d412a43c   Al Viro   vfs: split off vf...
986
987
988
  		free_vfsmnt(mnt);
  		return ERR_CAST(root);
  	}
b105e270b   Al Viro   vfs: spread struc...
989
990
  	mnt->mnt.mnt_root = root;
  	mnt->mnt.mnt_sb = root->d_sb;
a73324da7   Al Viro   vfs: move mnt_mou...
991
  	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
0714a5338   Al Viro   vfs: now it can b...
992
  	mnt->mnt_parent = mnt;
719ea2fbb   Al Viro   new helpers: lock...
993
  	lock_mount_hash();
39f7c4db1   Miklos Szeredi   vfs: keep list of...
994
  	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
719ea2fbb   Al Viro   new helpers: lock...
995
  	unlock_mount_hash();
b105e270b   Al Viro   vfs: spread struc...
996
  	return &mnt->mnt;
9d412a43c   Al Viro   vfs: split off vf...
997
998
  }
  EXPORT_SYMBOL_GPL(vfs_kern_mount);
93faccbbf   Eric W. Biederman   fs: Better permis...
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  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...
1009
  	return vfs_kern_mount(type, SB_SUBMOUNT, name, data);
93faccbbf   Eric W. Biederman   fs: Better permis...
1010
1011
  }
  EXPORT_SYMBOL_GPL(vfs_submount);
87129cc0e   Al Viro   vfs: spread struc...
1012
  static struct mount *clone_mnt(struct mount *old, struct dentry *root,
36341f645   Ram Pai   [PATCH] mount exp...
1013
  					int flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
  {
87129cc0e   Al Viro   vfs: spread struc...
1015
  	struct super_block *sb = old->mnt.mnt_sb;
be34d1a3b   David Howells   VFS: Make clone_m...
1016
1017
  	struct mount *mnt;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018

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

7a472ef4b   Eric W. Biederman   vfs: Only support...
1023
  	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
be34d1a3b   David Howells   VFS: Make clone_m...
1024
1025
1026
  		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...
1027

be34d1a3b   David Howells   VFS: Make clone_m...
1028
1029
1030
1031
  	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
1032
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
1033

f2ebb3a92   Al Viro   smarter propagate...
1034
  	mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED);
132c94e31   Eric W. Biederman   vfs: Carefully pr...
1035
  	/* Don't allow unprivileged users to change mount flags */
9566d6742   Eric W. Biederman   mnt: Correct perm...
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
  	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...
1051

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
1052
  	/* Don't allow unprivileged users to reveal what is under a mount */
381cacb12   Eric W. Biederman   mnt: Carefully se...
1053
1054
  	if ((flag & CL_UNPRIVILEGED) &&
  	    (!(flag & CL_EXPIRE) || list_empty(&old->mnt_expire)))
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
1055
  		mnt->mnt.mnt_flags |= MNT_LOCKED;
be34d1a3b   David Howells   VFS: Make clone_m...
1056
1057
1058
1059
1060
  	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...
1061
  	lock_mount_hash();
be34d1a3b   David Howells   VFS: Make clone_m...
1062
  	list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
719ea2fbb   Al Viro   new helpers: lock...
1063
  	unlock_mount_hash();
be34d1a3b   David Howells   VFS: Make clone_m...
1064

7a472ef4b   Eric W. Biederman   vfs: Only support...
1065
1066
  	if ((flag & CL_SLAVE) ||
  	    ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
be34d1a3b   David Howells   VFS: Make clone_m...
1067
1068
1069
1070
1071
1072
1073
1074
1075
  		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...
1076
1077
  	} else {
  		CLEAR_MNT_SHARED(mnt);
be34d1a3b   David Howells   VFS: Make clone_m...
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
  	}
  	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...
1088
  	return mnt;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1089
1090
  
   out_free:
8ffcb32e0   David Howells   VFS: Make delayed...
1091
  	mnt_free_id(mnt);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1092
  	free_vfsmnt(mnt);
be34d1a3b   David Howells   VFS: Make clone_m...
1093
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
  }
9ea459e11   Al Viro   delayed mntput
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
  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'...
1126
  	struct mount *m, *t;
9ea459e11   Al Viro   delayed mntput
1127

297857357   Byungchul Park   namespace.c: Don'...
1128
1129
  	llist_for_each_entry_safe(m, t, node, mnt_llist)
  		cleanup_mnt(m);
9ea459e11   Al Viro   delayed mntput
1130
1131
  }
  static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
900148dca   Al Viro   vfs: spread struc...
1132
  static void mntput_no_expire(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
1133
  {
48a066e72   Al Viro   RCU'd vfsmounts
1134
1135
1136
1137
  	rcu_read_lock();
  	mnt_add_count(mnt, -1);
  	if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */
  		rcu_read_unlock();
f03c65993   Al Viro   sanitize vfsmount...
1138
  		return;
b3e19d924   Nick Piggin   fs: scale mntget/...
1139
  	}
719ea2fbb   Al Viro   new helpers: lock...
1140
  	lock_mount_hash();
b3e19d924   Nick Piggin   fs: scale mntget/...
1141
  	if (mnt_get_count(mnt)) {
48a066e72   Al Viro   RCU'd vfsmounts
1142
  		rcu_read_unlock();
719ea2fbb   Al Viro   new helpers: lock...
1143
  		unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1144
1145
  		return;
  	}
48a066e72   Al Viro   RCU'd vfsmounts
1146
1147
1148
1149
1150
1151
1152
  	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: ...
1153

39f7c4db1   Miklos Szeredi   vfs: keep list of...
1154
  	list_del(&mnt->mnt_instance);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1155
1156
1157
1158
1159
1160
1161
  
  	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...
1162
  	unlock_mount_hash();
649a795af   Al Viro   fold mntfree() in...
1163

9ea459e11   Al Viro   delayed mntput
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
  	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/...
1176
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
1177
1178
1179
1180
  
  void mntput(struct vfsmount *mnt)
  {
  	if (mnt) {
863d684f9   Al Viro   vfs: move the res...
1181
  		struct mount *m = real_mount(mnt);
b3e19d924   Nick Piggin   fs: scale mntget/...
1182
  		/* avoid cacheline pingpong, hope gcc doesn't get "smart" */
863d684f9   Al Viro   vfs: move the res...
1183
1184
1185
  		if (unlikely(m->mnt_expiry_mark))
  			m->mnt_expiry_mark = 0;
  		mntput_no_expire(m);
b3e19d924   Nick Piggin   fs: scale mntget/...
1186
1187
1188
1189
1190
1191
1192
  	}
  }
  EXPORT_SYMBOL(mntput);
  
  struct vfsmount *mntget(struct vfsmount *mnt)
  {
  	if (mnt)
83adc7532   Al Viro   vfs: spread struc...
1193
  		mnt_add_count(real_mount(mnt), 1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1194
1195
1196
  	return mnt;
  }
  EXPORT_SYMBOL(mntget);
c6609c0a1   Ian Kent   vfs: add path_is_...
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
  /* 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...
1225
  struct vfsmount *mnt_clone_internal(const struct path *path)
7b7b1ace2   Al Viro   [PATCH] saner han...
1226
  {
3064c3563   Al Viro   death to mnt_pinned
1227
1228
1229
1230
1231
1232
  	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...
1233
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234

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

390c68436   Ram Pai   [PATCH] making na...
1241
  	down_read(&namespace_sem);
c7999c362   Al Viro   reduce m_start() ...
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
  	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
1256
1257
1258
1259
  }
  
  static void *m_next(struct seq_file *m, void *v, loff_t *pos)
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1260
  	struct proc_mounts *p = m->private;
b0765fb85   Pavel Emelianov   Make /proc/self/m...
1261

c7999c362   Al Viro   reduce m_start() ...
1262
1263
1264
  	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
1265
1266
1267
1268
  }
  
  static void m_stop(struct seq_file *m, void *v)
  {
390c68436   Ram Pai   [PATCH] making na...
1269
  	up_read(&namespace_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
  }
0226f4923   Al Viro   vfs: take /proc/*...
1271
  static int m_show(struct seq_file *m, void *v)
2d4d4864a   Ram Pai   [patch 6/7] vfs: ...
1272
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1273
  	struct proc_mounts *p = m->private;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1274
  	struct mount *r = list_entry(v, struct mount, mnt_list);
0226f4923   Al Viro   vfs: take /proc/*...
1275
  	return p->show(m, &r->mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276
  }
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1277
  const struct seq_operations mounts_op = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
1279
1280
  	.start	= m_start,
  	.next	= m_next,
  	.stop	= m_stop,
0226f4923   Al Viro   vfs: take /proc/*...
1281
  	.show	= m_show,
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1282
  };
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1283
  #endif  /* CONFIG_PROC_FS */
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1284

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
1286
1287
1288
1289
1290
1291
1292
  /**
   * 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...
1293
  int may_umount_tree(struct vfsmount *m)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
  {
909b0a88e   Al Viro   vfs: spread struc...
1295
  	struct mount *mnt = real_mount(m);
36341f645   Ram Pai   [PATCH] mount exp...
1296
1297
  	int actual_refs = 0;
  	int minimum_refs = 0;
315fc83e5   Al Viro   vfs: spread struc...
1298
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
1299
  	BUG_ON(!m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300

b3e19d924   Nick Piggin   fs: scale mntget/...
1301
  	/* write lock needed for mnt_get_count */
719ea2fbb   Al Viro   new helpers: lock...
1302
  	lock_mount_hash();
909b0a88e   Al Viro   vfs: spread struc...
1303
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
83adc7532   Al Viro   vfs: spread struc...
1304
  		actual_refs += mnt_get_count(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1305
  		minimum_refs += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
  	}
719ea2fbb   Al Viro   new helpers: lock...
1307
  	unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
  
  	if (actual_refs > minimum_refs)
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1310
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1311

e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1312
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
  }
  
  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: ...
1332
  	int ret = 1;
8ad08d8a0   Al Viro   may_umount() need...
1333
  	down_read(&namespace_sem);
719ea2fbb   Al Viro   new helpers: lock...
1334
  	lock_mount_hash();
1ab597386   Al Viro   vfs: spread struc...
1335
  	if (propagate_mount_busy(real_mount(mnt), 2))
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1336
  		ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
1337
  	unlock_mount_hash();
8ad08d8a0   Al Viro   may_umount() need...
1338
  	up_read(&namespace_sem);
a05964f39   Ram Pai   [PATCH] shared mo...
1339
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
1342
  }
  
  EXPORT_SYMBOL(may_umount);
38129a13e   Al Viro   switch mnt_hash t...
1343
  static HLIST_HEAD(unmounted);	/* protected by namespace_sem */
e3197d83d   Al Viro   saner umount_tree...
1344

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

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

97216be09   Al Viro   fold release_moun...
1351
  	up_write(&namespace_sem);
a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1352
1353
  	if (likely(hlist_empty(&head)))
  		return;
48a066e72   Al Viro   RCU'd vfsmounts
1354
  	synchronize_rcu();
87b95ce09   Al Viro   switch the IO-tri...
1355
  	group_pin_kill(&head);
70fbcdf4d   Ram Pai   [PATCH] umount_tr...
1356
  }
97216be09   Al Viro   fold release_moun...
1357
  static inline void namespace_lock(void)
e3197d83d   Al Viro   saner umount_tree...
1358
  {
97216be09   Al Viro   fold release_moun...
1359
  	down_write(&namespace_sem);
e3197d83d   Al Viro   saner umount_tree...
1360
  }
e819f1521   Eric W. Biederman   mnt: Improve the ...
1361
1362
1363
  enum umount_tree_flags {
  	UMOUNT_SYNC = 1,
  	UMOUNT_PROPAGATE = 2,
e0c9c0afd   Eric W. Biederman   mnt: Update detac...
1364
  	UMOUNT_CONNECTED = 4,
e819f1521   Eric W. Biederman   mnt: Improve the ...
1365
  };
f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
  
  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...
1395
  /*
48a066e72   Al Viro   RCU'd vfsmounts
1396
   * mount_lock must be held
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1397
1398
   * namespace_sem must be held for write
   */
e819f1521   Eric W. Biederman   mnt: Improve the ...
1399
  static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1400
  {
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1401
  	LIST_HEAD(tmp_list);
315fc83e5   Al Viro   vfs: spread struc...
1402
  	struct mount *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403

5d88457eb   Eric W. Biederman   mnt: On an unmoun...
1404
1405
  	if (how & UMOUNT_PROPAGATE)
  		propagate_mount_unlock(mnt);
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1406
  	/* Gather the mounts to umount */
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1407
1408
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
  		p->mnt.mnt_flags |= MNT_UMOUNT;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1409
  		list_move(&p->mnt_list, &tmp_list);
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1410
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411

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

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

c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1421
  	while (!list_empty(&tmp_list)) {
d29216842   Eric W. Biederman   mnt: Add a per mo...
1422
  		struct mnt_namespace *ns;
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1423
  		bool disconnect;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1424
  		p = list_first_entry(&tmp_list, struct mount, mnt_list);
6776db3d3   Al Viro   vfs: take mnt_sha...
1425
  		list_del_init(&p->mnt_expire);
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1426
  		list_del_init(&p->mnt_list);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1427
1428
1429
1430
1431
  		ns = p->mnt_ns;
  		if (ns) {
  			ns->mounts--;
  			__touch_mnt_namespace(ns);
  		}
143c8c91c   Al Viro   vfs: mnt_ns moved...
1432
  		p->mnt_ns = NULL;
e819f1521   Eric W. Biederman   mnt: Improve the ...
1433
  		if (how & UMOUNT_SYNC)
48a066e72   Al Viro   RCU'd vfsmounts
1434
  			p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
87b95ce09   Al Viro   switch the IO-tri...
1435

f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1436
  		disconnect = disconnect_mount(p, how);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1437
1438
1439
  
  		pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
  				 disconnect ? &unmounted : NULL);
676da58df   Al Viro   vfs: spread struc...
1440
  		if (mnt_has_parent(p)) {
81b6b0619   Al Viro   fix EBUSY on umou...
1441
  			mnt_add_count(p->mnt_parent, -1);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1442
1443
1444
1445
1446
1447
  			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...
1448
  		}
0f0afb1dc   Al Viro   vfs: spread struc...
1449
  		change_mnt_propagation(p, MS_PRIVATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1450
1451
  	}
  }
b54b9be78   Al Viro   get rid of the se...
1452
  static void shrink_submounts(struct mount *mnt);
c35038bec   Al Viro   [PATCH] do shrink...
1453

1ab597386   Al Viro   vfs: spread struc...
1454
  static int do_umount(struct mount *mnt, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
  {
1ab597386   Al Viro   vfs: spread struc...
1456
  	struct super_block *sb = mnt->mnt.mnt_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1457
  	int retval;
1ab597386   Al Viro   vfs: spread struc...
1458
  	retval = security_sb_umount(&mnt->mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
  	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...
1469
  		if (&mnt->mnt == current->fs->root.mnt ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
1471
  		    flags & (MNT_FORCE | MNT_DETACH))
  			return -EINVAL;
b3e19d924   Nick Piggin   fs: scale mntget/...
1472
1473
1474
1475
  		/*
  		 * 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...
1476
  		lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
1477
  		if (mnt_get_count(mnt) != 2) {
719ea2fbb   Al Viro   new helpers: lock...
1478
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
  			return -EBUSY;
b3e19d924   Nick Piggin   fs: scale mntget/...
1480
  		}
719ea2fbb   Al Viro   new helpers: lock...
1481
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482

863d684f9   Al Viro   vfs: move the res...
1483
  		if (!xchg(&mnt->mnt_expiry_mark, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
  			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...
1496
  	if (flags & MNT_FORCE && sb->s_op->umount_begin) {
42faad996   Al Viro   [PATCH] restore s...
1497
  		sb->s_op->umount_begin(sb);
42faad996   Al Viro   [PATCH] restore s...
1498
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
  
  	/*
  	 * 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...
1509
  	if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510
1511
1512
1513
  		/*
  		 * Special case for "unmounting" root ...
  		 * we just try to remount it readonly.
  		 */
a1480dcc3   Andy Lutomirski   fs: Add a missing...
1514
1515
  		if (!capable(CAP_SYS_ADMIN))
  			return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1516
  		down_write(&sb->s_umount);
bc98a42c1   David Howells   VFS: Convert sb->...
1517
  		if (!sb_rdonly(sb))
e462ec50c   David Howells   VFS: Differentiat...
1518
  			retval = do_remount_sb(sb, SB_RDONLY, NULL, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1519
1520
1521
  		up_write(&sb->s_umount);
  		return retval;
  	}
97216be09   Al Viro   fold release_moun...
1522
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1523
  	lock_mount_hash();
5addc5dd8   Al Viro   [PATCH] make /pro...
1524
  	event++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1525

48a066e72   Al Viro   RCU'd vfsmounts
1526
  	if (flags & MNT_DETACH) {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1527
  		if (!list_empty(&mnt->mnt_list))
e819f1521   Eric W. Biederman   mnt: Improve the ...
1528
  			umount_tree(mnt, UMOUNT_PROPAGATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1529
  		retval = 0;
48a066e72   Al Viro   RCU'd vfsmounts
1530
1531
1532
1533
1534
  	} 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 ...
1535
  				umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
48a066e72   Al Viro   RCU'd vfsmounts
1536
1537
  			retval = 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538
  	}
719ea2fbb   Al Viro   new helpers: lock...
1539
  	unlock_mount_hash();
e3197d83d   Al Viro   saner umount_tree...
1540
  	namespace_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
1542
  	return retval;
  }
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
  /*
   * __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 ...
1559
  	lock_mount_hash();
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1560
  	mp = lookup_mountpoint(dentry);
f53e57975   Eric W. Biederman   mnt: Fix the erro...
1561
  	if (IS_ERR_OR_NULL(mp))
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1562
  		goto out_unlock;
e06b933e6   Andrey Ulanov   namespace: update...
1563
  	event++;
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1564
1565
  	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...
1566
  		if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
fe78fcc85   Eric W. Biederman   mnt: In detach_mo...
1567
1568
  			hlist_add_head(&mnt->mnt_umount.s_list, &unmounted);
  			umount_mnt(mnt);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1569
  		}
e0c9c0afd   Eric W. Biederman   mnt: Update detac...
1570
  		else umount_tree(mnt, UMOUNT_CONNECTED);
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1571
  	}
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1572
1573
  	put_mountpoint(mp);
  out_unlock:
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1574
  	unlock_mount_hash();
80b5dce8c   Eric W. Biederman   vfs: Add a functi...
1575
1576
  	namespace_unlock();
  }
dd111b31e   David Howells   VFS: Clean up whi...
1577
  /*
9b40bc90a   Al Viro   get rid of unprot...
1578
1579
1580
1581
1582
1583
   * 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...
1584
1585
1586
1587
1588
  static inline bool may_mandlock(void)
  {
  #ifndef	CONFIG_MANDATORY_FILE_LOCKING
  	return false;
  #endif
95ace7541   Eric W. Biederman   locks: Don't allo...
1589
  	return capable(CAP_SYS_ADMIN);
9e8925b67   Jeff Layton   locks: Allow disa...
1590
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
1592
1593
1594
1595
1596
1597
  /*
   * 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
   */
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
1598
  SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1599
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
1600
  	struct path path;
900148dca   Al Viro   vfs: spread struc...
1601
  	struct mount *mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
  	int retval;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1603
  	int lookup_flags = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604

db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1605
1606
  	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
  		return -EINVAL;
9b40bc90a   Al Viro   get rid of unprot...
1607
1608
  	if (!may_mount())
  		return -EPERM;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1609
1610
  	if (!(flags & UMOUNT_NOFOLLOW))
  		lookup_flags |= LOOKUP_FOLLOW;
197df04c7   Al Viro   rename user_path_...
1611
  	retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1612
1613
  	if (retval)
  		goto out;
900148dca   Al Viro   vfs: spread struc...
1614
  	mnt = real_mount(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
  	retval = -EINVAL;
2d8f30380   Al Viro   [PATCH] sanitize ...
1616
  	if (path.dentry != path.mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617
  		goto dput_and_out;
143c8c91c   Al Viro   vfs: mnt_ns moved...
1618
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
  		goto dput_and_out;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
1620
1621
  	if (mnt->mnt.mnt_flags & MNT_LOCKED)
  		goto dput_and_out;
b2f5d4dc3   Eric W. Biederman   umount: Disallow ...
1622
1623
1624
  	retval = -EPERM;
  	if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
  		goto dput_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1625

900148dca   Al Viro   vfs: spread struc...
1626
  	retval = do_umount(mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1627
  dput_and_out:
429731b15   Jan Blunck   Remove path_relea...
1628
  	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
2d8f30380   Al Viro   [PATCH] sanitize ...
1629
  	dput(path.dentry);
900148dca   Al Viro   vfs: spread struc...
1630
  	mntput_no_expire(mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1631
1632
1633
1634
1635
1636
1637
  out:
  	return retval;
  }
  
  #ifdef __ARCH_WANT_SYS_OLDUMOUNT
  
  /*
b58fed8b1   Ram Pai   [PATCH] lindent f...
1638
   *	The 2.0 compatible umount. No flags.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
   */
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
1640
  SYSCALL_DEFINE1(oldumount, char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1641
  {
b58fed8b1   Ram Pai   [PATCH] lindent f...
1642
  	return sys_umount(name, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
1644
1645
  }
  
  #endif
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1646
  static bool is_mnt_ns_file(struct dentry *dentry)
8823c079b   Eric W. Biederman   vfs: Add setns su...
1647
  {
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1648
  	/* Is this a proxy for a mount namespace? */
e149ed2b8   Al Viro   take the targets ...
1649
1650
  	return dentry->d_op == &ns_dentry_operations &&
  	       dentry->d_fsdata == &mntns_operations;
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1651
  }
58be28256   Al Viro   make mntns ->get(...
1652
1653
1654
1655
  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...
1656
1657
1658
1659
1660
1661
1662
1663
  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_...
1664
  	mnt_ns = to_mnt_ns(get_proc_ns(dentry->d_inode));
8823c079b   Eric W. Biederman   vfs: Add setns su...
1665
1666
  	return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
  }
87129cc0e   Al Viro   vfs: spread struc...
1667
  struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
36341f645   Ram Pai   [PATCH] mount exp...
1668
  					int flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
  {
84d17192d   Al Viro   get rid of full-h...
1670
  	struct mount *res, *p, *q, *r, *parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1671

4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1672
1673
1674
1675
  	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...
1676
  		return ERR_PTR(-EINVAL);
9676f0c63   Ram Pai   [PATCH] unbindabl...
1677

36341f645   Ram Pai   [PATCH] mount exp...
1678
  	res = q = clone_mnt(mnt, dentry, flag);
be34d1a3b   David Howells   VFS: Make clone_m...
1679
1680
  	if (IS_ERR(q))
  		return q;
a73324da7   Al Viro   vfs: move mnt_mou...
1681
  	q->mnt_mountpoint = mnt->mnt_mountpoint;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
1683
  
  	p = mnt;
6b41d536f   Al Viro   vfs: take mnt_chi...
1684
  	list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
315fc83e5   Al Viro   vfs: spread struc...
1685
  		struct mount *s;
7ec02ef15   Jan Blunck   vfs: remove lives...
1686
  		if (!is_subdir(r->mnt_mountpoint, dentry))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687
  			continue;
909b0a88e   Al Viro   vfs: spread struc...
1688
  		for (s = r; s; s = next_mnt(s, r)) {
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1689
1690
1691
1692
1693
1694
1695
  			if (!(flag & CL_COPY_UNBINDABLE) &&
  			    IS_MNT_UNBINDABLE(s)) {
  				s = skip_mnt_tree(s);
  				continue;
  			}
  			if (!(flag & CL_COPY_MNT_NS_FILE) &&
  			    is_mnt_ns_file(s->mnt.mnt_root)) {
9676f0c63   Ram Pai   [PATCH] unbindabl...
1696
1697
1698
  				s = skip_mnt_tree(s);
  				continue;
  			}
0714a5338   Al Viro   vfs: now it can b...
1699
1700
1701
  			while (p != s->mnt_parent) {
  				p = p->mnt_parent;
  				q = q->mnt_parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
  			}
87129cc0e   Al Viro   vfs: spread struc...
1703
  			p = s;
84d17192d   Al Viro   get rid of full-h...
1704
  			parent = q;
87129cc0e   Al Viro   vfs: spread struc...
1705
  			q = clone_mnt(p, p->mnt.mnt_root, flag);
be34d1a3b   David Howells   VFS: Make clone_m...
1706
1707
  			if (IS_ERR(q))
  				goto out;
719ea2fbb   Al Viro   new helpers: lock...
1708
  			lock_mount_hash();
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1709
  			list_add_tail(&q->mnt_list, &res->mnt_list);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1710
  			attach_mnt(q, parent, p->mnt_mp);
719ea2fbb   Al Viro   new helpers: lock...
1711
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1712
1713
1714
  		}
  	}
  	return res;
be34d1a3b   David Howells   VFS: Make clone_m...
1715
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1716
  	if (res) {
719ea2fbb   Al Viro   new helpers: lock...
1717
  		lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
1718
  		umount_tree(res, UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
1719
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
1721
  	return q;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1722
  }
be34d1a3b   David Howells   VFS: Make clone_m...
1723
  /* Caller should check returned pointer for errors */
ca71cf71e   Al Viro   namespace.c: cons...
1724
  struct vfsmount *collect_mounts(const struct path *path)
8aec08094   Al Viro   [PATCH] new helpe...
1725
  {
cb338d06e   Al Viro   vfs: spread struc...
1726
  	struct mount *tree;
97216be09   Al Viro   fold release_moun...
1727
  	namespace_lock();
cd4a40174   Eric W. Biederman   mnt: Fail collect...
1728
1729
1730
1731
1732
  	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...
1733
  	namespace_unlock();
be34d1a3b   David Howells   VFS: Make clone_m...
1734
  	if (IS_ERR(tree))
52e220d35   Dan Carpenter   VFS: collect_moun...
1735
  		return ERR_CAST(tree);
be34d1a3b   David Howells   VFS: Make clone_m...
1736
  	return &tree->mnt;
8aec08094   Al Viro   [PATCH] new helpe...
1737
1738
1739
1740
  }
  
  void drop_collected_mounts(struct vfsmount *mnt)
  {
97216be09   Al Viro   fold release_moun...
1741
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1742
  	lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
1743
  	umount_tree(real_mount(mnt), UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
1744
  	unlock_mount_hash();
3ab6abee5   Al Viro   more conversions ...
1745
  	namespace_unlock();
8aec08094   Al Viro   [PATCH] new helpe...
1746
  }
c771d683a   Miklos Szeredi   vfs: introduce cl...
1747
1748
1749
1750
1751
1752
1753
1754
1755
  /**
   * 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...
1756
  struct vfsmount *clone_private_mount(const struct path *path)
c771d683a   Miklos Szeredi   vfs: introduce cl...
1757
1758
1759
1760
1761
1762
  {
  	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...
1763
  	new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
c771d683a   Miklos Szeredi   vfs: introduce cl...
1764
1765
1766
1767
1768
1769
  	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...
1770
1771
1772
  int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
  		   struct vfsmount *root)
  {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1773
  	struct mount *mnt;
1f707137b   Al Viro   new helper: itera...
1774
1775
1776
  	int res = f(root, arg);
  	if (res)
  		return res;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1777
1778
  	list_for_each_entry(mnt, &real_mount(root)->mnt_list, mnt_list) {
  		res = f(&mnt->mnt, arg);
1f707137b   Al Viro   new helper: itera...
1779
1780
1781
1782
1783
  		if (res)
  			return res;
  	}
  	return 0;
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1784
  static void cleanup_group_ids(struct mount *mnt, struct mount *end)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1785
  {
315fc83e5   Al Viro   vfs: spread struc...
1786
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1787

909b0a88e   Al Viro   vfs: spread struc...
1788
  	for (p = mnt; p != end; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
1789
  		if (p->mnt_group_id && !IS_MNT_SHARED(p))
4b8b21f4f   Al Viro   vfs: spread struc...
1790
  			mnt_release_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1791
1792
  	}
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1793
  static int invent_group_ids(struct mount *mnt, bool recurse)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1794
  {
315fc83e5   Al Viro   vfs: spread struc...
1795
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1796

909b0a88e   Al Viro   vfs: spread struc...
1797
  	for (p = mnt; p; p = recurse ? next_mnt(p, mnt) : NULL) {
fc7be130c   Al Viro   vfs: switch pnode...
1798
  		if (!p->mnt_group_id && !IS_MNT_SHARED(p)) {
4b8b21f4f   Al Viro   vfs: spread struc...
1799
  			int err = mnt_alloc_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1800
  			if (err) {
4b8b21f4f   Al Viro   vfs: spread struc...
1801
  				cleanup_group_ids(mnt, p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1802
1803
1804
1805
1806
1807
1808
  				return err;
  			}
  		}
  	}
  
  	return 0;
  }
d29216842   Eric W. Biederman   mnt: Add a per mo...
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
  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...
1830
1831
  /*
   *  @source_mnt : mount tree to be attached
214444032   Ram Pai   [PATCH] shared mo...
1832
1833
1834
1835
   *  @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...
1836
1837
1838
   *
   *  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...
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
   * ---------------------------------------------------------------------------
   * |         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...
1851
1852
1853
1854
1855
1856
1857
1858
1859
   * 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 ...
1860
1861
1862
1863
1864
1865
1866
   * (+++) 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...
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
   * ---------------------------------------------------------------------------
   * |         		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 ...
1879
1880
1881
   *
   * (+)  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...
1882
   * (+*)  the mount is moved to the destination.
5afe00221   Ram Pai   [PATCH] handling ...
1883
1884
1885
1886
   * (+++)  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...
1887
1888
1889
1890
1891
1892
   *
   * 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...
1893
  static int attach_recursive_mnt(struct mount *source_mnt,
84d17192d   Al Viro   get rid of full-h...
1894
1895
1896
  			struct mount *dest_mnt,
  			struct mountpoint *dest_mp,
  			struct path *parent_path)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1897
  {
38129a13e   Al Viro   switch mnt_hash t...
1898
  	HLIST_HEAD(tree_list);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1899
  	struct mnt_namespace *ns = dest_mnt->mnt_ns;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1900
  	struct mountpoint *smp;
315fc83e5   Al Viro   vfs: spread struc...
1901
  	struct mount *child, *p;
38129a13e   Al Viro   switch mnt_hash t...
1902
  	struct hlist_node *n;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1903
  	int err;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1904

1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1905
1906
1907
1908
1909
1910
  	/* 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...
1911
1912
1913
1914
1915
1916
  	/* 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...
1917
  	if (IS_MNT_SHARED(dest_mnt)) {
0fb54e505   Al Viro   vfs: spread struc...
1918
  		err = invent_group_ids(source_mnt, true);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1919
1920
  		if (err)
  			goto out;
0b1b901b5   Al Viro   don't bother with...
1921
  		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
f2ebb3a92   Al Viro   smarter propagate...
1922
  		lock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
1923
1924
  		if (err)
  			goto out_cleanup_ids;
909b0a88e   Al Viro   vfs: spread struc...
1925
  		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
0f0afb1dc   Al Viro   vfs: spread struc...
1926
  			set_mnt_shared(p);
0b1b901b5   Al Viro   don't bother with...
1927
1928
  	} else {
  		lock_mount_hash();
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1929
  	}
1a3906895   Al Viro   [PATCH] reduce st...
1930
  	if (parent_path) {
0fb54e505   Al Viro   vfs: spread struc...
1931
  		detach_mnt(source_mnt, parent_path);
84d17192d   Al Viro   get rid of full-h...
1932
  		attach_mnt(source_mnt, dest_mnt, dest_mp);
143c8c91c   Al Viro   vfs: mnt_ns moved...
1933
  		touch_mnt_namespace(source_mnt->mnt_ns);
214444032   Ram Pai   [PATCH] shared mo...
1934
  	} else {
84d17192d   Al Viro   get rid of full-h...
1935
  		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1936
  		commit_tree(source_mnt);
214444032   Ram Pai   [PATCH] shared mo...
1937
  	}
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1938

38129a13e   Al Viro   switch mnt_hash t...
1939
  	hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
1d6a32acd   Al Viro   keep shadowed vfs...
1940
  		struct mount *q;
38129a13e   Al Viro   switch mnt_hash t...
1941
  		hlist_del_init(&child->mnt_hash);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1942
1943
1944
1945
1946
  		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...
1947
  	}
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1948
  	put_mountpoint(smp);
719ea2fbb   Al Viro   new helpers: lock...
1949
  	unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1950

b90fa9ae8   Ram Pai   [PATCH] shared mo...
1951
  	return 0;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1952
1953
  
   out_cleanup_ids:
f2ebb3a92   Al Viro   smarter propagate...
1954
1955
  	while (!hlist_empty(&tree_list)) {
  		child = hlist_entry(tree_list.first, struct mount, mnt_hash);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1956
  		child->mnt_parent->mnt_ns->pending_mounts = 0;
e819f1521   Eric W. Biederman   mnt: Improve the ...
1957
  		umount_tree(child, UMOUNT_SYNC);
f2ebb3a92   Al Viro   smarter propagate...
1958
1959
  	}
  	unlock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
1960
  	cleanup_group_ids(source_mnt, NULL);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1961
   out:
d29216842   Eric W. Biederman   mnt: Add a per mo...
1962
  	ns->pending_mounts = 0;
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1963
1964
1965
1966
  
  	read_seqlock_excl(&mount_lock);
  	put_mountpoint(smp);
  	read_sequnlock_excl(&mount_lock);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1967
  	return err;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1968
  }
84d17192d   Al Viro   get rid of full-h...
1969
  static struct mountpoint *lock_mount(struct path *path)
b12cea919   Al Viro   change the lockin...
1970
1971
  {
  	struct vfsmount *mnt;
84d17192d   Al Viro   get rid of full-h...
1972
  	struct dentry *dentry = path->dentry;
b12cea919   Al Viro   change the lockin...
1973
  retry:
5955102c9   Al Viro   wrappers for ->i_...
1974
  	inode_lock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
1975
  	if (unlikely(cant_mount(dentry))) {
5955102c9   Al Viro   wrappers for ->i_...
1976
  		inode_unlock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
1977
  		return ERR_PTR(-ENOENT);
b12cea919   Al Viro   change the lockin...
1978
  	}
97216be09   Al Viro   fold release_moun...
1979
  	namespace_lock();
b12cea919   Al Viro   change the lockin...
1980
  	mnt = lookup_mnt(path);
84d17192d   Al Viro   get rid of full-h...
1981
  	if (likely(!mnt)) {
3895dbf89   Eric W. Biederman   mnt: Protect the ...
1982
  		struct mountpoint *mp = get_mountpoint(dentry);
84d17192d   Al Viro   get rid of full-h...
1983
  		if (IS_ERR(mp)) {
97216be09   Al Viro   fold release_moun...
1984
  			namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
1985
  			inode_unlock(dentry->d_inode);
84d17192d   Al Viro   get rid of full-h...
1986
1987
1988
1989
  			return mp;
  		}
  		return mp;
  	}
97216be09   Al Viro   fold release_moun...
1990
  	namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
1991
  	inode_unlock(path->dentry->d_inode);
b12cea919   Al Viro   change the lockin...
1992
1993
  	path_put(path);
  	path->mnt = mnt;
84d17192d   Al Viro   get rid of full-h...
1994
  	dentry = path->dentry = dget(mnt->mnt_root);
b12cea919   Al Viro   change the lockin...
1995
1996
  	goto retry;
  }
84d17192d   Al Viro   get rid of full-h...
1997
  static void unlock_mount(struct mountpoint *where)
b12cea919   Al Viro   change the lockin...
1998
  {
84d17192d   Al Viro   get rid of full-h...
1999
  	struct dentry *dentry = where->m_dentry;
3895dbf89   Eric W. Biederman   mnt: Protect the ...
2000
2001
  
  	read_seqlock_excl(&mount_lock);
84d17192d   Al Viro   get rid of full-h...
2002
  	put_mountpoint(where);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
2003
  	read_sequnlock_excl(&mount_lock);
328e6d901   Al Viro   switch unlock_mou...
2004
  	namespace_unlock();
5955102c9   Al Viro   wrappers for ->i_...
2005
  	inode_unlock(dentry->d_inode);
b12cea919   Al Viro   change the lockin...
2006
  }
84d17192d   Al Viro   get rid of full-h...
2007
  static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2008
  {
e462ec50c   David Howells   VFS: Differentiat...
2009
  	if (mnt->mnt.mnt_sb->s_flags & SB_NOUSER)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2010
  		return -EINVAL;
e36cb0b89   David Howells   VFS: (Scripted) C...
2011
2012
  	if (d_is_dir(mp->m_dentry) !=
  	      d_is_dir(mnt->mnt.mnt_root))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2013
  		return -ENOTDIR;
84d17192d   Al Viro   get rid of full-h...
2014
  	return attach_recursive_mnt(mnt, p, mp, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2015
2016
2017
  }
  
  /*
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2018
2019
   * Sanity check the flags to change_mnt_propagation.
   */
e462ec50c   David Howells   VFS: Differentiat...
2020
  static int flags_to_propagation_type(int ms_flags)
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2021
  {
e462ec50c   David Howells   VFS: Differentiat...
2022
  	int type = ms_flags & ~(MS_REC | MS_SILENT);
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
  
  	/* 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...
2034
2035
   * recursively change the type of the mountpoint.
   */
e462ec50c   David Howells   VFS: Differentiat...
2036
  static int do_change_type(struct path *path, int ms_flags)
07b20889e   Ram Pai   [PATCH] beginning...
2037
  {
315fc83e5   Al Viro   vfs: spread struc...
2038
  	struct mount *m;
4b8b21f4f   Al Viro   vfs: spread struc...
2039
  	struct mount *mnt = real_mount(path->mnt);
e462ec50c   David Howells   VFS: Differentiat...
2040
  	int recurse = ms_flags & MS_REC;
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2041
  	int type;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2042
  	int err = 0;
07b20889e   Ram Pai   [PATCH] beginning...
2043

2d92ab3c6   Al Viro   [PATCH] finally g...
2044
  	if (path->dentry != path->mnt->mnt_root)
07b20889e   Ram Pai   [PATCH] beginning...
2045
  		return -EINVAL;
e462ec50c   David Howells   VFS: Differentiat...
2046
  	type = flags_to_propagation_type(ms_flags);
7a2e8a8fa   Valerie Aurora   VFS: Sanity check...
2047
2048
  	if (!type)
  		return -EINVAL;
97216be09   Al Viro   fold release_moun...
2049
  	namespace_lock();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2050
2051
2052
2053
2054
  	if (type == MS_SHARED) {
  		err = invent_group_ids(mnt, recurse);
  		if (err)
  			goto out_unlock;
  	}
719ea2fbb   Al Viro   new helpers: lock...
2055
  	lock_mount_hash();
909b0a88e   Al Viro   vfs: spread struc...
2056
  	for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
0f0afb1dc   Al Viro   vfs: spread struc...
2057
  		change_mnt_propagation(m, type);
719ea2fbb   Al Viro   new helpers: lock...
2058
  	unlock_mount_hash();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2059
2060
  
   out_unlock:
97216be09   Al Viro   fold release_moun...
2061
  	namespace_unlock();
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
2062
  	return err;
07b20889e   Ram Pai   [PATCH] beginning...
2063
  }
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
  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...
2076
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2077
2078
   * do loopback mount.
   */
808d4e3cf   Al Viro   consitify do_moun...
2079
  static int do_loopback(struct path *path, const char *old_name,
2dafe1c4d   Eric Sandeen   reduce large do_m...
2080
  				int recurse)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2081
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2082
  	struct path old_path;
84d17192d   Al Viro   get rid of full-h...
2083
2084
  	struct mount *mnt = NULL, *old, *parent;
  	struct mountpoint *mp;
57eccb830   Al Viro   mount: consolidat...
2085
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2086
2087
  	if (!old_name || !*old_name)
  		return -EINVAL;
815d405ce   Trond Myklebust   VFS: Fix the rema...
2088
  	err = kern_path(old_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
2090
  	if (err)
  		return err;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2091
  	err = -EINVAL;
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2092
  	if (mnt_ns_loop(old_path.dentry))
dd111b31e   David Howells   VFS: Clean up whi...
2093
  		goto out;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2094

84d17192d   Al Viro   get rid of full-h...
2095
2096
2097
  	mp = lock_mount(path);
  	err = PTR_ERR(mp);
  	if (IS_ERR(mp))
b12cea919   Al Viro   change the lockin...
2098
  		goto out;
87129cc0e   Al Viro   vfs: spread struc...
2099
  	old = real_mount(old_path.mnt);
84d17192d   Al Viro   get rid of full-h...
2100
  	parent = real_mount(path->mnt);
87129cc0e   Al Viro   vfs: spread struc...
2101

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

e149ed2b8   Al Viro   take the targets ...
2106
2107
2108
2109
  	if (!check_mnt(parent))
  		goto out2;
  
  	if (!check_mnt(old) && old_path.dentry->d_op != &ns_dentry_operations)
b12cea919   Al Viro   change the lockin...
2110
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2111

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2112
2113
  	if (!recurse && has_locked_children(old, old_path.dentry))
  		goto out2;
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2114
  	if (recurse)
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2115
  		mnt = copy_tree(old, old_path.dentry, CL_COPY_MNT_NS_FILE);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2116
  	else
87129cc0e   Al Viro   vfs: spread struc...
2117
  		mnt = clone_mnt(old, old_path.dentry, 0);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2118

be34d1a3b   David Howells   VFS: Make clone_m...
2119
2120
  	if (IS_ERR(mnt)) {
  		err = PTR_ERR(mnt);
e9c5d8a56   Andrey Vagin   mnt: release lock...
2121
  		goto out2;
be34d1a3b   David Howells   VFS: Make clone_m...
2122
  	}
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2123

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2124
  	mnt->mnt.mnt_flags &= ~MNT_LOCKED;
84d17192d   Al Viro   get rid of full-h...
2125
  	err = graft_tree(mnt, parent, mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2126
  	if (err) {
719ea2fbb   Al Viro   new helpers: lock...
2127
  		lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
2128
  		umount_tree(mnt, UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
2129
  		unlock_mount_hash();
5b83d2c5c   Ram Pai   [PATCH] sanitize ...
2130
  	}
b12cea919   Al Viro   change the lockin...
2131
  out2:
84d17192d   Al Viro   get rid of full-h...
2132
  	unlock_mount(mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2133
  out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2134
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135
2136
  	return err;
  }
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
  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...
2148
  		error = mnt_make_readonly(real_mount(mnt));
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2149
  	else
83adc7532   Al Viro   vfs: spread struc...
2150
  		__mnt_unmake_readonly(real_mount(mnt));
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2151
2152
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2153
2154
2155
2156
2157
  /*
   * 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...
2158
2159
  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
2160
2161
  {
  	int err;
2d92ab3c6   Al Viro   [PATCH] finally g...
2162
  	struct super_block *sb = path->mnt->mnt_sb;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2163
  	struct mount *mnt = real_mount(path->mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164

143c8c91c   Al Viro   vfs: mnt_ns moved...
2165
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2166
  		return -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2167
  	if (path->dentry != path->mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2168
  		return -EINVAL;
07b645589   Eric W. Biederman   mnt: Move the tes...
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
  	/* 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...
2179
2180
  	if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
  	    !(mnt_flags & MNT_NODEV)) {
67690f937   Eric W. Biederman   userns: Remove im...
2181
  		return -EPERM;
9566d6742   Eric W. Biederman   mnt: Correct perm...
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
  	}
  	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...
2195
2196
2197
  	err = security_sb_remount(sb, data);
  	if (err)
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2198
  	down_write(&sb->s_umount);
e462ec50c   David Howells   VFS: Differentiat...
2199
2200
  	if (ms_flags & MS_BIND)
  		err = change_mount_flags(path->mnt, ms_flags);
57eccb830   Al Viro   mount: consolidat...
2201
2202
  	else if (!capable(CAP_SYS_ADMIN))
  		err = -EPERM;
4aa98cf76   Al Viro   Push BKL down int...
2203
  	else
e462ec50c   David Howells   VFS: Differentiat...
2204
  		err = do_remount_sb(sb, sb_flags, data, 0);
7b43a79f3   Al Viro   mnt_flags fixes i...
2205
  	if (!err) {
719ea2fbb   Al Viro   new helpers: lock...
2206
  		lock_mount_hash();
a6138db81   Eric W. Biederman   mnt: Only change ...
2207
  		mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2208
  		mnt->mnt.mnt_flags = mnt_flags;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2209
  		touch_mnt_namespace(mnt->mnt_ns);
719ea2fbb   Al Viro   new helpers: lock...
2210
  		unlock_mount_hash();
0e55a7cca   Dan Williams   [RFC PATCH] touch...
2211
  	}
6339dab86   Al Viro   do_remount(): pul...
2212
  	up_write(&sb->s_umount);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2213
2214
  	return err;
  }
cbbe362cd   Al Viro   vfs: spread struc...
2215
  static inline int tree_contains_unbindable(struct mount *mnt)
9676f0c63   Ram Pai   [PATCH] unbindabl...
2216
  {
315fc83e5   Al Viro   vfs: spread struc...
2217
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
2218
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
2219
  		if (IS_MNT_UNBINDABLE(p))
9676f0c63   Ram Pai   [PATCH] unbindabl...
2220
2221
2222
2223
  			return 1;
  	}
  	return 0;
  }
808d4e3cf   Al Viro   consitify do_moun...
2224
  static int do_move_mount(struct path *path, const char *old_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2225
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2226
  	struct path old_path, parent_path;
676da58df   Al Viro   vfs: spread struc...
2227
  	struct mount *p;
0fb54e505   Al Viro   vfs: spread struc...
2228
  	struct mount *old;
84d17192d   Al Viro   get rid of full-h...
2229
  	struct mountpoint *mp;
57eccb830   Al Viro   mount: consolidat...
2230
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2231
2232
  	if (!old_name || !*old_name)
  		return -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2233
  	err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2234
2235
  	if (err)
  		return err;
84d17192d   Al Viro   get rid of full-h...
2236
2237
2238
  	mp = lock_mount(path);
  	err = PTR_ERR(mp);
  	if (IS_ERR(mp))
cc53ce53c   David Howells   Add a dentry op t...
2239
  		goto out;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2240
  	old = real_mount(old_path.mnt);
fc7be130c   Al Viro   vfs: switch pnode...
2241
  	p = real_mount(path->mnt);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2242

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2243
  	err = -EINVAL;
fc7be130c   Al Viro   vfs: switch pnode...
2244
  	if (!check_mnt(p) || !check_mnt(old))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2245
  		goto out1;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2246
2247
  	if (old->mnt.mnt_flags & MNT_LOCKED)
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2248
  	err = -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2249
  	if (old_path.dentry != old_path.mnt->mnt_root)
214444032   Ram Pai   [PATCH] shared mo...
2250
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2251

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

e36cb0b89   David Howells   VFS: (Scripted) C...
2255
2256
  	if (d_is_dir(path->dentry) !=
  	      d_is_dir(old_path.dentry))
214444032   Ram Pai   [PATCH] shared mo...
2257
2258
2259
2260
  		goto out1;
  	/*
  	 * Don't move a mount residing in a shared parent.
  	 */
fc7be130c   Al Viro   vfs: switch pnode...
2261
  	if (IS_MNT_SHARED(old->mnt_parent))
214444032   Ram Pai   [PATCH] shared mo...
2262
  		goto out1;
9676f0c63   Ram Pai   [PATCH] unbindabl...
2263
2264
2265
2266
  	/*
  	 * Don't move a mount tree containing unbindable mounts to a destination
  	 * mount which is shared.
  	 */
fc7be130c   Al Viro   vfs: switch pnode...
2267
  	if (IS_MNT_SHARED(p) && tree_contains_unbindable(old))
9676f0c63   Ram Pai   [PATCH] unbindabl...
2268
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2269
  	err = -ELOOP;
fc7be130c   Al Viro   vfs: switch pnode...
2270
  	for (; mnt_has_parent(p); p = p->mnt_parent)
676da58df   Al Viro   vfs: spread struc...
2271
  		if (p == old)
214444032   Ram Pai   [PATCH] shared mo...
2272
  			goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2273

84d17192d   Al Viro   get rid of full-h...
2274
  	err = attach_recursive_mnt(old, real_mount(path->mnt), mp, &parent_path);
4ac913785   Jan Blunck   Embed a struct pa...
2275
  	if (err)
214444032   Ram Pai   [PATCH] shared mo...
2276
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2277
2278
2279
  
  	/* if the mount is moved, it should no longer be expire
  	 * automatically */
6776db3d3   Al Viro   vfs: take mnt_sha...
2280
  	list_del_init(&old->mnt_expire);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2281
  out1:
84d17192d   Al Viro   get rid of full-h...
2282
  	unlock_mount(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2283
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2284
  	if (!err)
1a3906895   Al Viro   [PATCH] reduce st...
2285
  		path_put(&parent_path);
2d92ab3c6   Al Viro   [PATCH] finally g...
2286
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2287
2288
  	return err;
  }
9d412a43c   Al Viro   vfs: split off vf...
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
  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...
2311
2312
2313
  /*
   * add a mount into a namespace's mount tree
   */
95bc5f25c   Al Viro   vfs: spread struc...
2314
  static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
9d412a43c   Al Viro   vfs: split off vf...
2315
  {
84d17192d   Al Viro   get rid of full-h...
2316
2317
  	struct mountpoint *mp;
  	struct mount *parent;
9d412a43c   Al Viro   vfs: split off vf...
2318
  	int err;
f2ebb3a92   Al Viro   smarter propagate...
2319
  	mnt_flags &= ~MNT_INTERNAL_FLAGS;
9d412a43c   Al Viro   vfs: split off vf...
2320

84d17192d   Al Viro   get rid of full-h...
2321
2322
2323
  	mp = lock_mount(path);
  	if (IS_ERR(mp))
  		return PTR_ERR(mp);
9d412a43c   Al Viro   vfs: split off vf...
2324

84d17192d   Al Viro   get rid of full-h...
2325
  	parent = real_mount(path->mnt);
9d412a43c   Al Viro   vfs: split off vf...
2326
  	err = -EINVAL;
84d17192d   Al Viro   get rid of full-h...
2327
  	if (unlikely(!check_mnt(parent))) {
156cacb1d   Al Viro   do_add_mount()/um...
2328
2329
2330
2331
  		/* 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...
2332
  		if (!parent->mnt_ns)
156cacb1d   Al Viro   do_add_mount()/um...
2333
2334
  			goto unlock;
  	}
9d412a43c   Al Viro   vfs: split off vf...
2335
2336
2337
  
  	/* Refuse the same filesystem on the same mount point */
  	err = -EBUSY;
95bc5f25c   Al Viro   vfs: spread struc...
2338
  	if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
9d412a43c   Al Viro   vfs: split off vf...
2339
2340
2341
2342
  	    path->mnt->mnt_root == path->dentry)
  		goto unlock;
  
  	err = -EINVAL;
e36cb0b89   David Howells   VFS: (Scripted) C...
2343
  	if (d_is_symlink(newmnt->mnt.mnt_root))
9d412a43c   Al Viro   vfs: split off vf...
2344
  		goto unlock;
95bc5f25c   Al Viro   vfs: spread struc...
2345
  	newmnt->mnt.mnt_flags = mnt_flags;
84d17192d   Al Viro   get rid of full-h...
2346
  	err = graft_tree(newmnt, parent, mp);
9d412a43c   Al Viro   vfs: split off vf...
2347
2348
  
  unlock:
84d17192d   Al Viro   get rid of full-h...
2349
  	unlock_mount(mp);
9d412a43c   Al Viro   vfs: split off vf...
2350
2351
  	return err;
  }
b1e75df45   Al Viro   tidy up around fi...
2352

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2355
2356
2357
2358
  /*
   * create a new mount for userspace and request it to be added into the
   * namespace's tree
   */
e462ec50c   David Howells   VFS: Differentiat...
2359
  static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
808d4e3cf   Al Viro   consitify do_moun...
2360
  			int mnt_flags, const char *name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2361
  {
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2362
  	struct file_system_type *type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2363
  	struct vfsmount *mnt;
15f9a3f3e   Al Viro   don't drop newmnt...
2364
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2365

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2366
  	if (!fstype)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2367
  		return -EINVAL;
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2368
2369
2370
  	type = get_fs_type(fstype);
  	if (!type)
  		return -ENODEV;
e462ec50c   David Howells   VFS: Differentiat...
2371
  	mnt = vfs_kern_mount(type, sb_flags, name, data);
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2372
2373
2374
2375
2376
  	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
2377
2378
  	if (IS_ERR(mnt))
  		return PTR_ERR(mnt);
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
2379
2380
2381
2382
  	if (mount_too_revealing(mnt, &mnt_flags)) {
  		mntput(mnt);
  		return -EPERM;
  	}
95bc5f25c   Al Viro   vfs: spread struc...
2383
  	err = do_add_mount(real_mount(mnt), path, mnt_flags);
15f9a3f3e   Al Viro   don't drop newmnt...
2384
2385
2386
  	if (err)
  		mntput(mnt);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2387
  }
19a167af7   Al Viro   Take the completi...
2388
2389
  int finish_automount(struct vfsmount *m, struct path *path)
  {
6776db3d3   Al Viro   vfs: take mnt_sha...
2390
  	struct mount *mnt = real_mount(m);
19a167af7   Al Viro   Take the completi...
2391
2392
2393
2394
  	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...
2395
  	BUG_ON(mnt_get_count(mnt) < 2);
19a167af7   Al Viro   Take the completi...
2396
2397
2398
  
  	if (m->mnt_sb == path->mnt->mnt_sb &&
  	    m->mnt_root == path->dentry) {
b1e75df45   Al Viro   tidy up around fi...
2399
2400
  		err = -ELOOP;
  		goto fail;
19a167af7   Al Viro   Take the completi...
2401
  	}
95bc5f25c   Al Viro   vfs: spread struc...
2402
  	err = do_add_mount(mnt, path, path->mnt->mnt_flags | MNT_SHRINKABLE);
b1e75df45   Al Viro   tidy up around fi...
2403
2404
2405
2406
  	if (!err)
  		return 0;
  fail:
  	/* remove m from any expiration list it may be on */
6776db3d3   Al Viro   vfs: take mnt_sha...
2407
  	if (!list_empty(&mnt->mnt_expire)) {
97216be09   Al Viro   fold release_moun...
2408
  		namespace_lock();
6776db3d3   Al Viro   vfs: take mnt_sha...
2409
  		list_del_init(&mnt->mnt_expire);
97216be09   Al Viro   fold release_moun...
2410
  		namespace_unlock();
19a167af7   Al Viro   Take the completi...
2411
  	}
b1e75df45   Al Viro   tidy up around fi...
2412
2413
  	mntput(m);
  	mntput(m);
19a167af7   Al Viro   Take the completi...
2414
2415
  	return err;
  }
ea5b778a8   David Howells   Unexport do_add_m...
2416
2417
2418
2419
2420
2421
2422
  /**
   * 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...
2423
  	namespace_lock();
ea5b778a8   David Howells   Unexport do_add_m...
2424

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

97216be09   Al Viro   fold release_moun...
2427
  	namespace_unlock();
ea5b778a8   David Howells   Unexport do_add_m...
2428
2429
2430
2431
  }
  EXPORT_SYMBOL(mnt_set_expiry);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2432
2433
2434
2435
2436
2437
   * 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...
2438
  	struct mount *mnt, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2439
2440
2441
2442
  	LIST_HEAD(graveyard);
  
  	if (list_empty(mounts))
  		return;
97216be09   Al Viro   fold release_moun...
2443
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
2444
  	lock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
2446
2447
2448
2449
2450
2451
  
  	/* 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...
2452
  	list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
863d684f9   Al Viro   vfs: move the res...
2453
  		if (!xchg(&mnt->mnt_expiry_mark, 1) ||
1ab597386   Al Viro   vfs: spread struc...
2454
  			propagate_mount_busy(mnt, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2455
  			continue;
6776db3d3   Al Viro   vfs: take mnt_sha...
2456
  		list_move(&mnt->mnt_expire, &graveyard);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2457
  	}
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2458
  	while (!list_empty(&graveyard)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2459
  		mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2460
  		touch_mnt_namespace(mnt->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2461
  		umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2462
  	}
719ea2fbb   Al Viro   new helpers: lock...
2463
  	unlock_mount_hash();
3ab6abee5   Al Viro   more conversions ...
2464
  	namespace_unlock();
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
  }
  
  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...
2475
  static int select_submounts(struct mount *parent, struct list_head *graveyard)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2476
  {
692afc312   Al Viro   vfs: spread struc...
2477
  	struct mount *this_parent = parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2478
2479
2480
2481
  	struct list_head *next;
  	int found = 0;
  
  repeat:
6b41d536f   Al Viro   vfs: take mnt_chi...
2482
  	next = this_parent->mnt_mounts.next;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2483
  resume:
6b41d536f   Al Viro   vfs: take mnt_chi...
2484
  	while (next != &this_parent->mnt_mounts) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2485
  		struct list_head *tmp = next;
6b41d536f   Al Viro   vfs: take mnt_chi...
2486
  		struct mount *mnt = list_entry(tmp, struct mount, mnt_child);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2487
2488
  
  		next = tmp->next;
692afc312   Al Viro   vfs: spread struc...
2489
  		if (!(mnt->mnt.mnt_flags & MNT_SHRINKABLE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2490
  			continue;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2491
2492
2493
  		/*
  		 * Descend a level if the d_mounts list is non-empty.
  		 */
6b41d536f   Al Viro   vfs: take mnt_chi...
2494
  		if (!list_empty(&mnt->mnt_mounts)) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2495
2496
2497
  			this_parent = mnt;
  			goto repeat;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2498

1ab597386   Al Viro   vfs: spread struc...
2499
  		if (!propagate_mount_busy(mnt, 1)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2500
  			list_move_tail(&mnt->mnt_expire, graveyard);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2501
2502
  			found++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2503
  	}
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2504
2505
2506
2507
  	/*
  	 * All done at this level ... ascend and resume the search
  	 */
  	if (this_parent != parent) {
6b41d536f   Al Viro   vfs: take mnt_chi...
2508
  		next = this_parent->mnt_child.next;
0714a5338   Al Viro   vfs: now it can b...
2509
  		this_parent = this_parent->mnt_parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2510
2511
2512
2513
2514
2515
2516
2517
  		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...
2518
   *
48a066e72   Al Viro   RCU'd vfsmounts
2519
   * mount_lock must be held for write
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2520
   */
b54b9be78   Al Viro   get rid of the se...
2521
  static void shrink_submounts(struct mount *mnt)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2522
2523
  {
  	LIST_HEAD(graveyard);
761d5c38e   Al Viro   vfs: spread struc...
2524
  	struct mount *m;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2525

5528f911b   Trond Myklebust   VFS: Add shrink_s...
2526
  	/* extract submounts of 'mountpoint' from the expiration list */
c35038bec   Al Viro   [PATCH] do shrink...
2527
  	while (select_submounts(mnt, &graveyard)) {
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2528
  		while (!list_empty(&graveyard)) {
761d5c38e   Al Viro   vfs: spread struc...
2529
  			m = list_first_entry(&graveyard, struct mount,
6776db3d3   Al Viro   vfs: take mnt_sha...
2530
  						mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2531
  			touch_mnt_namespace(m->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2532
  			umount_tree(m, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2533
2534
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2535
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2536
2537
2538
2539
2540
2541
  /*
   * 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...
2542
2543
  static long exact_copy_from_user(void *to, const void __user * from,
  				 unsigned long n)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
  {
  	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...
2563
  void *copy_mount_options(const void __user * data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2564
2565
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2566
  	unsigned long size;
b40ef8696   Al Viro   saner calling con...
2567
  	char *copy;
b58fed8b1   Ram Pai   [PATCH] lindent f...
2568

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2569
  	if (!data)
b40ef8696   Al Viro   saner calling con...
2570
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2571

b40ef8696   Al Viro   saner calling con...
2572
2573
2574
  	copy = kmalloc(PAGE_SIZE, GFP_KERNEL);
  	if (!copy)
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2575
2576
2577
2578
2579
2580
2581
2582
2583
  
  	/* 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...
2584
  	i = size - exact_copy_from_user(copy, data, size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2585
  	if (!i) {
b40ef8696   Al Viro   saner calling con...
2586
2587
  		kfree(copy);
  		return ERR_PTR(-EFAULT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2588
2589
  	}
  	if (i != PAGE_SIZE)
b40ef8696   Al Viro   saner calling con...
2590
2591
  		memset(copy + i, 0, PAGE_SIZE - i);
  	return copy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2592
  }
b8850d1fa   Tim Gardner   fs: namespace: su...
2593
  char *copy_mount_string(const void __user *data)
eca6f534e   Vegard Nossum   fs: fix overflow ...
2594
  {
b8850d1fa   Tim Gardner   fs: namespace: su...
2595
  	return data ? strndup_user(data, PAGE_SIZE) : NULL;
eca6f534e   Vegard Nossum   fs: fix overflow ...
2596
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
  /*
   * 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...
2611
  long do_mount(const char *dev_name, const char __user *dir_name,
808d4e3cf   Al Viro   consitify do_moun...
2612
  		const char *type_page, unsigned long flags, void *data_page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2613
  {
2d92ab3c6   Al Viro   [PATCH] finally g...
2614
  	struct path path;
e462ec50c   David Howells   VFS: Differentiat...
2615
  	unsigned int mnt_flags = 0, sb_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2616
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2617
2618
2619
2620
2621
2622
  
  	/* 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
2623
2624
  	if (data_page)
  		((char *)data_page)[PAGE_SIZE - 1] = 0;
e462ec50c   David Howells   VFS: Differentiat...
2625
2626
  	if (flags & MS_NOUSER)
  		return -EINVAL;
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2627
  	/* ... and get the mountpoint */
5e6123f34   Seunghun Lee   vfs: move getname...
2628
  	retval = user_path(dir_name, &path);
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2629
2630
2631
2632
2633
  	if (retval)
  		return retval;
  
  	retval = security_sb_mount(dev_name, &path,
  				   type_page, flags, data_page);
0d5cadb87   Al Viro   do_mount(): fix a...
2634
2635
  	if (!retval && !may_mount())
  		retval = -EPERM;
e462ec50c   David Howells   VFS: Differentiat...
2636
  	if (!retval && (flags & SB_MANDLOCK) && !may_mandlock())
9e8925b67   Jeff Layton   locks: Allow disa...
2637
  		retval = -EPERM;
a27ab9f26   Tetsuo Handa   LSM: Pass origina...
2638
2639
  	if (retval)
  		goto dput_out;
613cbe3d4   Andi Kleen   Don't set relatim...
2640
2641
2642
  	/* Default to relatime unless overriden */
  	if (!(flags & MS_NOATIME))
  		mnt_flags |= MNT_RELATIME;
0a1c01c94   Matthew Garrett   Make relatime def...
2643

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2644
2645
2646
2647
2648
2649
2650
  	/* 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...
2651
2652
2653
2654
  	if (flags & MS_NOATIME)
  		mnt_flags |= MNT_NOATIME;
  	if (flags & MS_NODIRATIME)
  		mnt_flags |= MNT_NODIRATIME;
d0adde574   Matthew Garrett   Add a strictatime...
2655
2656
  	if (flags & MS_STRICTATIME)
  		mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
e462ec50c   David Howells   VFS: Differentiat...
2657
  	if (flags & SB_RDONLY)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2658
  		mnt_flags |= MNT_READONLY;
fc33a7bb9   Christoph Hellwig   [PATCH] per-mount...
2659

ffbc6f0ea   Eric W. Biederman   mnt: Change the d...
2660
2661
2662
2663
2664
2665
2666
  	/* 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...
2667
2668
2669
2670
2671
  	sb_flags = flags & (SB_RDONLY |
  			    SB_SYNCHRONOUS |
  			    SB_MANDLOCK |
  			    SB_DIRSYNC |
  			    SB_SILENT |
917086ff2   Mimi Zohar   vfs: fix mounting...
2672
2673
  			    SB_POSIXACL |
  			    SB_I_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2674

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2675
  	if (flags & MS_REMOUNT)
e462ec50c   David Howells   VFS: Differentiat...
2676
  		retval = do_remount(&path, flags, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2677
2678
  				    data_page);
  	else if (flags & MS_BIND)
2d92ab3c6   Al Viro   [PATCH] finally g...
2679
  		retval = do_loopback(&path, dev_name, flags & MS_REC);
9676f0c63   Ram Pai   [PATCH] unbindabl...
2680
  	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
2d92ab3c6   Al Viro   [PATCH] finally g...
2681
  		retval = do_change_type(&path, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2682
  	else if (flags & MS_MOVE)
2d92ab3c6   Al Viro   [PATCH] finally g...
2683
  		retval = do_move_mount(&path, dev_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2684
  	else
e462ec50c   David Howells   VFS: Differentiat...
2685
  		retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2686
2687
  				      dev_name, data_page);
  dput_out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2688
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2689
2690
  	return retval;
  }
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2691
2692
2693
2694
2695
2696
2697
2698
2699
  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...
2700
2701
  static void free_mnt_ns(struct mnt_namespace *ns)
  {
6344c433a   Al Viro   new helpers: ns_a...
2702
  	ns_free_inum(&ns->ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2703
  	dec_mnt_namespaces(ns->ucounts);
771b13716   Eric W. Biederman   vfs: Add a user n...
2704
2705
2706
  	put_user_ns(ns->user_ns);
  	kfree(ns);
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
2707
2708
2709
2710
2711
2712
2713
2714
  /*
   * 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...
2715
  static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2716
2717
  {
  	struct mnt_namespace *new_ns;
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2718
  	struct ucounts *ucounts;
98f842e67   Eric W. Biederman   proc: Usable inod...
2719
  	int ret;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2720

537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2721
2722
  	ucounts = inc_mnt_namespaces(user_ns);
  	if (!ucounts)
df75e7748   Eric W. Biederman   userns: When the ...
2723
  		return ERR_PTR(-ENOSPC);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2724

cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2725
  	new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2726
2727
  	if (!new_ns) {
  		dec_mnt_namespaces(ucounts);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2728
  		return ERR_PTR(-ENOMEM);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2729
  	}
6344c433a   Al Viro   new helpers: ns_a...
2730
  	ret = ns_alloc_inum(&new_ns->ns);
98f842e67   Eric W. Biederman   proc: Usable inod...
2731
2732
  	if (ret) {
  		kfree(new_ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2733
  		dec_mnt_namespaces(ucounts);
98f842e67   Eric W. Biederman   proc: Usable inod...
2734
2735
  		return ERR_PTR(ret);
  	}
33c429405   Al Viro   copy address of p...
2736
  	new_ns->ns.ops = &mntns_operations;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2737
  	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2738
2739
2740
2741
2742
  	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...
2743
  	new_ns->user_ns = get_user_ns(user_ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2744
  	new_ns->ucounts = ucounts;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2745
2746
  	new_ns->mounts = 0;
  	new_ns->pending_mounts = 0;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2747
2748
  	return new_ns;
  }
0766f788e   Emese Revfy   latent_entropy: M...
2749
  __latent_entropy
9559f6891   Al Viro   fold dup_mnt_ns()...
2750
2751
  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
2752
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
2753
  	struct mnt_namespace *new_ns;
7f2da1e7d   Al Viro   [PATCH] kill altroot
2754
  	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
315fc83e5   Al Viro   vfs: spread struc...
2755
  	struct mount *p, *q;
9559f6891   Al Viro   fold dup_mnt_ns()...
2756
  	struct mount *old;
cb338d06e   Al Viro   vfs: spread struc...
2757
  	struct mount *new;
7a472ef4b   Eric W. Biederman   vfs: Only support...
2758
  	int copy_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2759

9559f6891   Al Viro   fold dup_mnt_ns()...
2760
2761
2762
2763
2764
2765
2766
2767
  	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...
2768
  	new_ns = alloc_mnt_ns(user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2769
2770
  	if (IS_ERR(new_ns))
  		return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2771

97216be09   Al Viro   fold release_moun...
2772
  	namespace_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2773
  	/* First pass: copy the tree topology */
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2774
  	copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
9559f6891   Al Viro   fold dup_mnt_ns()...
2775
  	if (user_ns != ns->user_ns)
132c94e31   Eric W. Biederman   vfs: Carefully pr...
2776
  		copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
7a472ef4b   Eric W. Biederman   vfs: Only support...
2777
  	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
be34d1a3b   David Howells   VFS: Make clone_m...
2778
  	if (IS_ERR(new)) {
328e6d901   Al Viro   switch unlock_mou...
2779
  		namespace_unlock();
771b13716   Eric W. Biederman   vfs: Add a user n...
2780
  		free_mnt_ns(new_ns);
be34d1a3b   David Howells   VFS: Make clone_m...
2781
  		return ERR_CAST(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2782
  	}
be08d6d26   Al Viro   switch mnt_namesp...
2783
  	new_ns->root = new;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2784
  	list_add_tail(&new_ns->list, &new->mnt_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2785
2786
2787
2788
2789
2790
  
  	/*
  	 * 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...
2791
  	p = old;
cb338d06e   Al Viro   vfs: spread struc...
2792
  	q = new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2793
  	while (p) {
143c8c91c   Al Viro   vfs: mnt_ns moved...
2794
  		q->mnt_ns = new_ns;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2795
  		new_ns->mounts++;
9559f6891   Al Viro   fold dup_mnt_ns()...
2796
2797
2798
  		if (new_fs) {
  			if (&p->mnt == new_fs->root.mnt) {
  				new_fs->root.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
2799
  				rootmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2800
  			}
9559f6891   Al Viro   fold dup_mnt_ns()...
2801
2802
  			if (&p->mnt == new_fs->pwd.mnt) {
  				new_fs->pwd.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
2803
  				pwdmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2804
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2805
  		}
909b0a88e   Al Viro   vfs: spread struc...
2806
2807
  		p = next_mnt(p, old);
  		q = next_mnt(q, new);
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2808
2809
2810
2811
  		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
2812
  	}
328e6d901   Al Viro   switch unlock_mou...
2813
  	namespace_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2814

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2815
  	if (rootmnt)
f03c65993   Al Viro   sanitize vfsmount...
2816
  		mntput(rootmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2817
  	if (pwdmnt)
f03c65993   Al Viro   sanitize vfsmount...
2818
  		mntput(pwdmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2819

741a29513   JANAK DESAI   [PATCH] unshare s...
2820
  	return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2821
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2822
2823
2824
2825
  /**
   * 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...
2826
  static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2827
  {
771b13716   Eric W. Biederman   vfs: Add a user n...
2828
  	struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2829
  	if (!IS_ERR(new_ns)) {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2830
2831
  		struct mount *mnt = real_mount(m);
  		mnt->mnt_ns = new_ns;
be08d6d26   Al Viro   switch mnt_namesp...
2832
  		new_ns->root = mnt;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2833
  		new_ns->mounts++;
b1983cd89   Al Viro   create_mnt_ns: un...
2834
  		list_add(&mnt->mnt_list, &new_ns->list);
c13344958   Al Viro   switch create_mnt...
2835
  	} else {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2836
  		mntput(m);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2837
2838
2839
  	}
  	return new_ns;
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2840

ea441d110   Al Viro   new helper: mount...
2841
2842
2843
  struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
  {
  	struct mnt_namespace *ns;
d31da0f0b   Al Viro   mount_subtree() p...
2844
  	struct super_block *s;
ea441d110   Al Viro   new helper: mount...
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
  	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...
2861
2862
  	s = path.mnt->mnt_sb;
  	atomic_inc(&s->s_active);
ea441d110   Al Viro   new helper: mount...
2863
2864
  	mntput(path.mnt);
  	/* lock the sucker */
d31da0f0b   Al Viro   mount_subtree() p...
2865
  	down_write(&s->s_umount);
ea441d110   Al Viro   new helper: mount...
2866
2867
2868
2869
  	/* ... and return the root of (sub)tree on it */
  	return path.dentry;
  }
  EXPORT_SYMBOL(mount_subtree);
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
2870
2871
  SYSCALL_DEFINE5(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
2872
  {
eca6f534e   Vegard Nossum   fs: fix overflow ...
2873
2874
  	int ret;
  	char *kernel_type;
eca6f534e   Vegard Nossum   fs: fix overflow ...
2875
  	char *kernel_dev;
b40ef8696   Al Viro   saner calling con...
2876
  	void *options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2877

b8850d1fa   Tim Gardner   fs: namespace: su...
2878
2879
2880
  	kernel_type = copy_mount_string(type);
  	ret = PTR_ERR(kernel_type);
  	if (IS_ERR(kernel_type))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2881
  		goto out_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2882

b8850d1fa   Tim Gardner   fs: namespace: su...
2883
2884
2885
  	kernel_dev = copy_mount_string(dev_name);
  	ret = PTR_ERR(kernel_dev);
  	if (IS_ERR(kernel_dev))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2886
  		goto out_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2887

b40ef8696   Al Viro   saner calling con...
2888
2889
2890
  	options = copy_mount_options(data);
  	ret = PTR_ERR(options);
  	if (IS_ERR(options))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2891
  		goto out_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2892

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

b40ef8696   Al Viro   saner calling con...
2895
  	kfree(options);
eca6f534e   Vegard Nossum   fs: fix overflow ...
2896
2897
2898
  out_data:
  	kfree(kernel_dev);
  out_dev:
eca6f534e   Vegard Nossum   fs: fix overflow ...
2899
2900
2901
  	kfree(kernel_type);
  out_type:
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2902
2903
2904
  }
  
  /*
afac7cba7   Al Viro   vfs: more mnt_par...
2905
2906
   * Return true if path is reachable from root
   *
48a066e72   Al Viro   RCU'd vfsmounts
2907
   * namespace_sem or mount_lock is held
afac7cba7   Al Viro   vfs: more mnt_par...
2908
   */
643822b41   Al Viro   vfs: spread struc...
2909
  bool is_path_reachable(struct mount *mnt, struct dentry *dentry,
afac7cba7   Al Viro   vfs: more mnt_par...
2910
2911
  			 const struct path *root)
  {
643822b41   Al Viro   vfs: spread struc...
2912
  	while (&mnt->mnt != root->mnt && mnt_has_parent(mnt)) {
a73324da7   Al Viro   vfs: move mnt_mou...
2913
  		dentry = mnt->mnt_mountpoint;
0714a5338   Al Viro   vfs: now it can b...
2914
  		mnt = mnt->mnt_parent;
afac7cba7   Al Viro   vfs: more mnt_par...
2915
  	}
643822b41   Al Viro   vfs: spread struc...
2916
  	return &mnt->mnt == root->mnt && is_subdir(dentry, root->dentry);
afac7cba7   Al Viro   vfs: more mnt_par...
2917
  }
640eb7e7b   Mickaël Salaün   fs: Constify path...
2918
  bool path_is_under(const struct path *path1, const struct path *path2)
afac7cba7   Al Viro   vfs: more mnt_par...
2919
  {
25ab4c9b1   Yaowei Bai   fs/namespace.c: p...
2920
  	bool res;
48a066e72   Al Viro   RCU'd vfsmounts
2921
  	read_seqlock_excl(&mount_lock);
643822b41   Al Viro   vfs: spread struc...
2922
  	res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
48a066e72   Al Viro   RCU'd vfsmounts
2923
  	read_sequnlock_excl(&mount_lock);
afac7cba7   Al Viro   vfs: more mnt_par...
2924
2925
2926
2927
2928
  	return res;
  }
  EXPORT_SYMBOL(path_is_under);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
   * 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...
2941
2942
2943
2944
   * 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
2945
2946
2947
2948
2949
2950
2951
2952
   * 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...
2953
2954
  SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
  		const char __user *, put_old)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2955
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
2956
  	struct path new, old, parent_path, root_parent, root;
84d17192d   Al Viro   get rid of full-h...
2957
2958
  	struct mount *new_mnt, *root_mnt, *old_mnt;
  	struct mountpoint *old_mp, *root_mp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2959
  	int error;
9b40bc90a   Al Viro   get rid of unprot...
2960
  	if (!may_mount())
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2961
  		return -EPERM;
2d8f30380   Al Viro   [PATCH] sanitize ...
2962
  	error = user_path_dir(new_root, &new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2963
2964
  	if (error)
  		goto out0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2965

2d8f30380   Al Viro   [PATCH] sanitize ...
2966
  	error = user_path_dir(put_old, &old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2967
2968
  	if (error)
  		goto out1;
2d8f30380   Al Viro   [PATCH] sanitize ...
2969
  	error = security_sb_pivotroot(&old, &new);
b12cea919   Al Viro   change the lockin...
2970
2971
  	if (error)
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2972

f7ad3c6be   Miklos Szeredi   vfs: add helpers ...
2973
  	get_fs_root(current->fs, &root);
84d17192d   Al Viro   get rid of full-h...
2974
2975
2976
  	old_mp = lock_mount(&old);
  	error = PTR_ERR(old_mp);
  	if (IS_ERR(old_mp))
b12cea919   Al Viro   change the lockin...
2977
  		goto out3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2978
  	error = -EINVAL;
419148da6   Al Viro   vfs: spread struc...
2979
2980
  	new_mnt = real_mount(new.mnt);
  	root_mnt = real_mount(root.mnt);
84d17192d   Al Viro   get rid of full-h...
2981
2982
  	old_mnt = real_mount(old.mnt);
  	if (IS_MNT_SHARED(old_mnt) ||
fc7be130c   Al Viro   vfs: switch pnode...
2983
2984
  		IS_MNT_SHARED(new_mnt->mnt_parent) ||
  		IS_MNT_SHARED(root_mnt->mnt_parent))
b12cea919   Al Viro   change the lockin...
2985
  		goto out4;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2986
  	if (!check_mnt(root_mnt) || !check_mnt(new_mnt))
b12cea919   Al Viro   change the lockin...
2987
  		goto out4;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2988
2989
  	if (new_mnt->mnt.mnt_flags & MNT_LOCKED)
  		goto out4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2990
  	error = -ENOENT;
f3da392e9   Alexey Dobriyan   dcache: extrace a...
2991
  	if (d_unlinked(new.dentry))
b12cea919   Al Viro   change the lockin...
2992
  		goto out4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2993
  	error = -EBUSY;
84d17192d   Al Viro   get rid of full-h...
2994
  	if (new_mnt == root_mnt || old_mnt == root_mnt)
b12cea919   Al Viro   change the lockin...
2995
  		goto out4; /* loop, on the same file system  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2996
  	error = -EINVAL;
8c3ee42e8   Al Viro   [PATCH] get rid o...
2997
  	if (root.mnt->mnt_root != root.dentry)
b12cea919   Al Viro   change the lockin...
2998
  		goto out4; /* not a mountpoint */
676da58df   Al Viro   vfs: spread struc...
2999
  	if (!mnt_has_parent(root_mnt))
b12cea919   Al Viro   change the lockin...
3000
  		goto out4; /* not attached */
84d17192d   Al Viro   get rid of full-h...
3001
  	root_mp = root_mnt->mnt_mp;
2d8f30380   Al Viro   [PATCH] sanitize ...
3002
  	if (new.mnt->mnt_root != new.dentry)
b12cea919   Al Viro   change the lockin...
3003
  		goto out4; /* not a mountpoint */
676da58df   Al Viro   vfs: spread struc...
3004
  	if (!mnt_has_parent(new_mnt))
b12cea919   Al Viro   change the lockin...
3005
  		goto out4; /* not attached */
4ac913785   Jan Blunck   Embed a struct pa...
3006
  	/* make sure we can reach put_old from new_root */
84d17192d   Al Viro   get rid of full-h...
3007
  	if (!is_path_reachable(old_mnt, old.dentry, &new))
b12cea919   Al Viro   change the lockin...
3008
  		goto out4;
0d0826019   Eric W. Biederman   mnt: Prevent pivo...
3009
3010
3011
  	/* 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...
3012
  	root_mp->m_count++; /* pin it so it won't go away */
719ea2fbb   Al Viro   new helpers: lock...
3013
  	lock_mount_hash();
419148da6   Al Viro   vfs: spread struc...
3014
3015
  	detach_mnt(new_mnt, &parent_path);
  	detach_mnt(root_mnt, &root_parent);
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
3016
3017
3018
3019
  	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...
3020
  	/* mount old root on put_old */
84d17192d   Al Viro   get rid of full-h...
3021
  	attach_mnt(root_mnt, old_mnt, old_mp);
4ac913785   Jan Blunck   Embed a struct pa...
3022
  	/* mount new_root on / */
84d17192d   Al Viro   get rid of full-h...
3023
  	attach_mnt(new_mnt, real_mount(root_parent.mnt), root_mp);
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3024
  	touch_mnt_namespace(current->nsproxy->mnt_ns);
4fed655c4   Eric W. Biederman   mnt: Clear mnt_ex...
3025
3026
  	/* A moved mount should not expire automatically */
  	list_del_init(&new_mnt->mnt_expire);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
3027
  	put_mountpoint(root_mp);
719ea2fbb   Al Viro   new helpers: lock...
3028
  	unlock_mount_hash();
2d8f30380   Al Viro   [PATCH] sanitize ...
3029
  	chroot_fs_refs(&root, &new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3030
  	error = 0;
b12cea919   Al Viro   change the lockin...
3031
  out4:
84d17192d   Al Viro   get rid of full-h...
3032
  	unlock_mount(old_mp);
b12cea919   Al Viro   change the lockin...
3033
3034
3035
3036
3037
  	if (!error) {
  		path_put(&root_parent);
  		path_put(&parent_path);
  	}
  out3:
8c3ee42e8   Al Viro   [PATCH] get rid o...
3038
  	path_put(&root);
b12cea919   Al Viro   change the lockin...
3039
  out2:
2d8f30380   Al Viro   [PATCH] sanitize ...
3040
  	path_put(&old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3041
  out1:
2d8f30380   Al Viro   [PATCH] sanitize ...
3042
  	path_put(&new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3043
  out0:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3044
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3045
3046
3047
3048
3049
  }
  
  static void __init init_mount_tree(void)
  {
  	struct vfsmount *mnt;
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3050
  	struct mnt_namespace *ns;
ac748a09f   Jan Blunck   Make set_fs_{root...
3051
  	struct path root;
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3052
  	struct file_system_type *type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3053

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3054
3055
3056
3057
3058
  	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
3059
3060
  	if (IS_ERR(mnt))
  		panic("Can't create rootfs");
b3e19d924   Nick Piggin   fs: scale mntget/...
3061

3b22edc57   Trond Myklebust   VFS: Switch init_...
3062
3063
  	ns = create_mnt_ns(mnt);
  	if (IS_ERR(ns))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3064
  		panic("Can't allocate initial namespace");
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3065
3066
3067
  
  	init_task.nsproxy->mnt_ns = ns;
  	get_mnt_ns(ns);
be08d6d26   Al Viro   switch mnt_namesp...
3068
3069
  	root.mnt = mnt;
  	root.dentry = mnt->mnt_root;
da362b09e   Eric W. Biederman   umount: Do not al...
3070
  	mnt->mnt_flags |= MNT_LOCKED;
ac748a09f   Jan Blunck   Make set_fs_{root...
3071
3072
3073
  
  	set_fs_pwd(current->fs, &root);
  	set_fs_root(current->fs, &root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3074
  }
74bf17cff   Denis Cheng   fs: remove the un...
3075
  void __init mnt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3076
  {
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3077
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3078

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

0818bf27c   Al Viro   resizable namespa...
3082
  	mount_hashtable = alloc_large_system_hash("Mount-cache",
38129a13e   Al Viro   switch mnt_hash t...
3083
  				sizeof(struct hlist_head),
0818bf27c   Al Viro   resizable namespa...
3084
  				mhash_entries, 19,
3d375d785   Pavel Tatashin   mm: update caller...
3085
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3086
3087
3088
3089
  				&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...
3090
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3091
  				&mp_hash_shift, &mp_hash_mask, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3092

84d17192d   Al Viro   get rid of full-h...
3093
  	if (!mount_hashtable || !mountpoint_hashtable)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3094
3095
  		panic("Failed to allocate mount hash table
  ");
4b93dc9b1   Tejun Heo   sysfs, kernfs: pr...
3096
  	kernfs_init();
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3097
3098
3099
3100
  	err = sysfs_init();
  	if (err)
  		printk(KERN_WARNING "%s: sysfs_init error: %d
  ",
8e24eea72   Harvey Harrison   fs: replace remai...
3101
  			__func__, err);
00d266662   Greg Kroah-Hartman   kobject: convert ...
3102
3103
  	fs_kobj = kobject_create_and_add("fs", NULL);
  	if (!fs_kobj)
8e24eea72   Harvey Harrison   fs: replace remai...
3104
3105
  		printk(KERN_WARNING "%s: kobj create error
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3106
3107
3108
  	init_rootfs();
  	init_mount_tree();
  }
616511d03   Trond Myklebust   VFS: Uninline the...
3109
  void put_mnt_ns(struct mnt_namespace *ns)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3110
  {
d498b25a4   Al Viro   get rid of useles...
3111
  	if (!atomic_dec_and_test(&ns->count))
616511d03   Trond Myklebust   VFS: Uninline the...
3112
  		return;
7b00ed6fe   Al Viro   put_mnt_ns(): use...
3113
  	drop_collected_mounts(&ns->root->mnt);
771b13716   Eric W. Biederman   vfs: Add a user n...
3114
  	free_mnt_ns(ns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3115
  }
9d412a43c   Al Viro   vfs: split off vf...
3116
3117
3118
  
  struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
  {
423e0ab08   Tim Chen   VFS : mount lock ...
3119
  	struct vfsmount *mnt;
e462ec50c   David Howells   VFS: Differentiat...
3120
  	mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, data);
423e0ab08   Tim Chen   VFS : mount lock ...
3121
3122
3123
3124
3125
  	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_...
3126
  		real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL;
423e0ab08   Tim Chen   VFS : mount lock ...
3127
3128
  	}
  	return mnt;
9d412a43c   Al Viro   vfs: split off vf...
3129
3130
  }
  EXPORT_SYMBOL_GPL(kern_mount_data);
423e0ab08   Tim Chen   VFS : mount lock ...
3131
3132
3133
3134
3135
  
  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_...
3136
  		real_mount(mnt)->mnt_ns = NULL;
48a066e72   Al Viro   RCU'd vfsmounts
3137
  		synchronize_rcu();	/* yecchhh... */
423e0ab08   Tim Chen   VFS : mount lock ...
3138
3139
3140
3141
  		mntput(mnt);
  	}
  }
  EXPORT_SYMBOL(kern_unmount);
02125a826   Al Viro   fix apparmor dere...
3142
3143
3144
  
  bool our_mnt(struct vfsmount *mnt)
  {
143c8c91c   Al Viro   vfs: mnt_ns moved...
3145
  	return check_mnt(real_mount(mnt));
02125a826   Al Viro   fix apparmor dere...
3146
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
3147

3151527ee   Eric W. Biederman   userns: Don't al...
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
  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_...
3171
3172
  static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
  				int *new_mnt_flags)
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3173
  {
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3174
  	int new_flags = *new_mnt_flags;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3175
  	struct mount *mnt;
e51db7353   Eric W. Biederman   userns: Better re...
3176
  	bool visible = false;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3177

44bb4385c   Al Viro   fs_is_visible onl...
3178
  	down_read(&namespace_sem);
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3179
  	list_for_each_entry(mnt, &ns->list, mnt_list) {
e51db7353   Eric W. Biederman   userns: Better re...
3180
  		struct mount *child;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3181
  		int mnt_flags;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3182
  		if (mnt->mnt.mnt_sb->s_type != new->mnt_sb->s_type)
e51db7353   Eric W. Biederman   userns: Better re...
3183
  			continue;
7e96c1b0e   Eric W. Biederman   mnt: Fix fs_fully...
3184
3185
3186
3187
3188
  		/* 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...
3189
  		/* A local view of the mount flags */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3190
  		mnt_flags = mnt->mnt.mnt_flags;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3191

695e9df01   Eric W. Biederman   mnt: Account for ...
3192
  		/* Don't miss readonly hidden in the superblock flags */
bc98a42c1   David Howells   VFS: Convert sb->...
3193
  		if (sb_rdonly(mnt->mnt.mnt_sb))
695e9df01   Eric W. Biederman   mnt: Account for ...
3194
  			mnt_flags |= MNT_LOCK_READONLY;
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3195
3196
3197
  		/* Verify the mount flags are equal to or more permissive
  		 * than the proposed new mount.
  		 */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3198
  		if ((mnt_flags & MNT_LOCK_READONLY) &&
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3199
3200
  		    !(new_flags & MNT_READONLY))
  			continue;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3201
3202
  		if ((mnt_flags & MNT_LOCK_ATIME) &&
  		    ((mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3203
  			continue;
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3204
3205
3206
  		/* 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...
3207
3208
3209
  		 */
  		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...
3210
  			/* Only worry about locked mounts */
d71ed6c93   Eric W. Biederman   mnt: fs_fully_vis...
3211
  			if (!(child->mnt.mnt_flags & MNT_LOCKED))
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3212
  				continue;
7236c85e1   Eric W. Biederman   mnt: Update fs_fu...
3213
3214
  			/* Is the directory permanetly empty? */
  			if (!is_empty_dir_inode(inode))
e51db7353   Eric W. Biederman   userns: Better re...
3215
  				goto next;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3216
  		}
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3217
  		/* Preserve the locked attributes */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3218
  		*new_mnt_flags |= mnt_flags & (MNT_LOCK_READONLY | \
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3219
  					       MNT_LOCK_ATIME);
e51db7353   Eric W. Biederman   userns: Better re...
3220
3221
3222
  		visible = true;
  		goto found;
  	next:	;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3223
  	}
e51db7353   Eric W. Biederman   userns: Better re...
3224
  found:
44bb4385c   Al Viro   fs_is_visible onl...
3225
  	up_read(&namespace_sem);
e51db7353   Eric W. Biederman   userns: Better re...
3226
  	return visible;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3227
  }
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3228
3229
  static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
  {
a1935c173   Eric W. Biederman   mnt: Simplify mou...
3230
  	const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
  	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...
3241
3242
3243
3244
3245
3246
  	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_...
3247
3248
  	return !mnt_already_visible(ns, mnt, new_mnt_flags);
  }
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
  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...
3261
  static struct ns_common *mntns_get(struct task_struct *task)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3262
  {
58be28256   Al Viro   make mntns ->get(...
3263
  	struct ns_common *ns = NULL;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3264
  	struct nsproxy *nsproxy;
728dba3a3   Eric W. Biederman   namespaces: Use t...
3265
3266
  	task_lock(task);
  	nsproxy = task->nsproxy;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3267
  	if (nsproxy) {
58be28256   Al Viro   make mntns ->get(...
3268
3269
  		ns = &nsproxy->mnt_ns->ns;
  		get_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3270
  	}
728dba3a3   Eric W. Biederman   namespaces: Use t...
3271
  	task_unlock(task);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3272
3273
3274
  
  	return ns;
  }
64964528b   Al Viro   make proc_ns_oper...
3275
  static void mntns_put(struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3276
  {
58be28256   Al Viro   make mntns ->get(...
3277
  	put_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3278
  }
64964528b   Al Viro   make proc_ns_oper...
3279
  static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3280
3281
  {
  	struct fs_struct *fs = current->fs;
4f757f3cb   Al Viro   make sure that mn...
3282
  	struct mnt_namespace *mnt_ns = to_mnt_ns(ns), *old_mnt_ns;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3283
  	struct path root;
4f757f3cb   Al Viro   make sure that mn...
3284
  	int err;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3285

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3286
  	if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
c7b96acf1   Eric W. Biederman   userns: Kill nso...
3287
3288
  	    !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
  	    !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
ae11e0f18   Zhao Hongjiang   userns: fix retur...
3289
  		return -EPERM;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3290
3291
3292
3293
3294
  
  	if (fs->users != 1)
  		return -EINVAL;
  
  	get_mnt_ns(mnt_ns);
4f757f3cb   Al Viro   make sure that mn...
3295
  	old_mnt_ns = nsproxy->mnt_ns;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3296
3297
3298
  	nsproxy->mnt_ns = mnt_ns;
  
  	/* Find the root */
4f757f3cb   Al Viro   make sure that mn...
3299
3300
3301
3302
3303
3304
3305
3306
  	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...
3307

4068367c9   Andrei Vagin   fs: don't forget ...
3308
  	put_mnt_ns(old_mnt_ns);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3309
3310
3311
3312
3313
3314
3315
  	/* 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...
3316
3317
3318
3319
  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...
3320
3321
3322
3323
3324
3325
  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...
3326
  	.owner		= mntns_owner,
8823c079b   Eric W. Biederman   vfs: Add setns su...
3327
  };