Blame view

fs/namespace.c 86.2 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
  {
  	int ret;
f473bf921   Greg Kroah-Hartman   Revert "vfs: fix ...
428
  	sb_start_write(file->f_path.mnt->mnt_sb);
eb04c2828   Jan Kara   fs: Add freezing ...
429
430
  	ret = __mnt_want_write_file(file);
  	if (ret)
f473bf921   Greg Kroah-Hartman   Revert "vfs: fix ...
431
  		sb_end_write(file->f_path.mnt->mnt_sb);
eb04c2828   Jan Kara   fs: Add freezing ...
432
433
  	return ret;
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  
  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...
450
451
452
  	if (upperdentry &&
  	    (file_inode(file) == d_inode(upperdentry) ||
  	     file_inode(file) == d_inode(dentry)))
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
453
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
  		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...
483
484
485
  EXPORT_SYMBOL_GPL(mnt_want_write_file);
  
  /**
eb04c2828   Jan Kara   fs: Add freezing ...
486
   * __mnt_drop_write - give up write access to a mount
8366025eb   Dave Hansen   [PATCH] r/o bind ...
487
488
489
490
   * @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 ...
491
   * __mnt_want_write() call above.
8366025eb   Dave Hansen   [PATCH] r/o bind ...
492
   */
eb04c2828   Jan Kara   fs: Add freezing ...
493
  void __mnt_drop_write(struct vfsmount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
494
  {
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
495
  	preempt_disable();
83adc7532   Al Viro   vfs: spread struc...
496
  	mnt_dec_writers(real_mount(mnt));
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
497
  	preempt_enable();
8366025eb   Dave Hansen   [PATCH] r/o bind ...
498
  }
eb04c2828   Jan Kara   fs: Add freezing ...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
  
  /**
   * 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 ...
513
  EXPORT_SYMBOL_GPL(mnt_drop_write);
eb04c2828   Jan Kara   fs: Add freezing ...
514
515
516
517
  void __mnt_drop_write_file(struct file *file)
  {
  	__mnt_drop_write(file->f_path.mnt);
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
518
  void mnt_drop_write_file_path(struct file *file)
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
519
  {
f473bf921   Greg Kroah-Hartman   Revert "vfs: fix ...
520
  	mnt_drop_write(file->f_path.mnt);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
521
  }
7c6893e3c   Miklos Szeredi   ovl: don't allow ...
522
523
524
525
526
527
  
  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...
528
  EXPORT_SYMBOL(mnt_drop_write_file);
83adc7532   Al Viro   vfs: spread struc...
529
  static int mnt_make_readonly(struct mount *mnt)
8366025eb   Dave Hansen   [PATCH] r/o bind ...
530
  {
3d733633a   Dave Hansen   [PATCH] r/o bind ...
531
  	int ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
532
  	lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
533
  	mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
3d733633a   Dave Hansen   [PATCH] r/o bind ...
534
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
535
536
  	 * 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 ...
537
  	 */
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
538
  	smp_mb();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
539
  	/*
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
540
541
542
543
544
545
546
547
548
549
550
551
552
553
  	 * 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 ...
554
  	 */
c6653a838   Nick Piggin   fs: rename vfsmou...
555
  	if (mnt_get_writers(mnt) > 0)
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
556
557
  		ret = -EBUSY;
  	else
83adc7532   Al Viro   vfs: spread struc...
558
  		mnt->mnt.mnt_flags |= MNT_READONLY;
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
559
560
561
562
563
  	/*
  	 * 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...
564
  	mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
719ea2fbb   Al Viro   new helpers: lock...
565
  	unlock_mount_hash();
3d733633a   Dave Hansen   [PATCH] r/o bind ...
566
  	return ret;
8366025eb   Dave Hansen   [PATCH] r/o bind ...
567
  }
8366025eb   Dave Hansen   [PATCH] r/o bind ...
568

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

48a066e72   Al Viro   RCU'd vfsmounts
696
697
698
699
700
701
702
703
  	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...
704
  }
7af1364ff   Eric W. Biederman   vfs: Don't allow ...
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
731
732
733
734
735
736
737
738
  /*
   * __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...
739
  static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
84d17192d   Al Viro   get rid of full-h...
740
  {
0818bf27c   Al Viro   resizable namespa...
741
  	struct hlist_head *chain = mp_hash(dentry);
84d17192d   Al Viro   get rid of full-h...
742
  	struct mountpoint *mp;
0818bf27c   Al Viro   resizable namespa...
743
  	hlist_for_each_entry(mp, chain, m_hash) {
84d17192d   Al Viro   get rid of full-h...
744
745
746
747
748
749
750
751
  		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...
752
753
  	return NULL;
  }
3895dbf89   Eric W. Biederman   mnt: Protect the ...
754
  static struct mountpoint *get_mountpoint(struct dentry *dentry)
e2dfa9354   Eric W. Biederman   vfs: factor out l...
755
  {
3895dbf89   Eric W. Biederman   mnt: Protect the ...
756
  	struct mountpoint *mp, *new = NULL;
e2dfa9354   Eric W. Biederman   vfs: factor out l...
757
  	int ret;
84d17192d   Al Viro   get rid of full-h...
758

3895dbf89   Eric W. Biederman   mnt: Protect the ...
759
760
761
762
763
764
765
766
767
768
769
770
  	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...
771
  		return ERR_PTR(-ENOMEM);
3895dbf89   Eric W. Biederman   mnt: Protect the ...
772
773
  
  	/* Exactly one processes may set d_mounted */
eed810076   Miklos Szeredi   vfs: check unlink...
774
  	ret = d_set_mounted(dentry);
eed810076   Miklos Szeredi   vfs: check unlink...
775

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

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

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

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

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

7a472ef4b   Eric W. Biederman   vfs: Only support...
1031
  	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
be34d1a3b   David Howells   VFS: Make clone_m...
1032
1033
1034
  		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...
1035

be34d1a3b   David Howells   VFS: Make clone_m...
1036
1037
1038
1039
  	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
1040
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
1041

d4d49cb1c   Al Viro   Don't leak MNT_IN...
1042
1043
  	mnt->mnt.mnt_flags = old->mnt.mnt_flags;
  	mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL);
132c94e31   Eric W. Biederman   vfs: Carefully pr...
1044
  	/* Don't allow unprivileged users to change mount flags */
9566d6742   Eric W. Biederman   mnt: Correct perm...
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
  	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...
1060

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

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

297857357   Byungchul Park   namespace.c: Don'...
1137
1138
  	llist_for_each_entry_safe(m, t, node, mnt_llist)
  		cleanup_mnt(m);
9ea459e11   Al Viro   delayed mntput
1139
1140
  }
  static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
900148dca   Al Viro   vfs: spread struc...
1141
  static void mntput_no_expire(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
1142
  {
48a066e72   Al Viro   RCU'd vfsmounts
1143
  	rcu_read_lock();
d9d46a226   Al Viro   fix mntput/mntput...
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
  	if (likely(READ_ONCE(mnt->mnt_ns))) {
  		/*
  		 * Since we don't do lock_mount_hash() here,
  		 * ->mnt_ns can change under us.  However, if it's
  		 * non-NULL, then there's a reference that won't
  		 * be dropped until after an RCU delay done after
  		 * turning ->mnt_ns NULL.  So if we observe it
  		 * non-NULL under rcu_read_lock(), the reference
  		 * we are dropping is not the final one.
  		 */
  		mnt_add_count(mnt, -1);
48a066e72   Al Viro   RCU'd vfsmounts
1155
  		rcu_read_unlock();
f03c65993   Al Viro   sanitize vfsmount...
1156
  		return;
b3e19d924   Nick Piggin   fs: scale mntget/...
1157
  	}
719ea2fbb   Al Viro   new helpers: lock...
1158
  	lock_mount_hash();
e5751c844   Al Viro   fix __legitimize_...
1159
1160
1161
1162
1163
  	/*
  	 * make sure that if __legitimize_mnt() has not seen us grab
  	 * mount_lock, we'll see their refcount increment here.
  	 */
  	smp_mb();
d9d46a226   Al Viro   fix mntput/mntput...
1164
  	mnt_add_count(mnt, -1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1165
  	if (mnt_get_count(mnt)) {
48a066e72   Al Viro   RCU'd vfsmounts
1166
  		rcu_read_unlock();
719ea2fbb   Al Viro   new helpers: lock...
1167
  		unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1168
1169
  		return;
  	}
48a066e72   Al Viro   RCU'd vfsmounts
1170
1171
1172
1173
1174
1175
1176
  	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: ...
1177

39f7c4db1   Miklos Szeredi   vfs: keep list of...
1178
  	list_del(&mnt->mnt_instance);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1179
1180
1181
1182
1183
1184
1185
  
  	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...
1186
  	unlock_mount_hash();
649a795af   Al Viro   fold mntfree() in...
1187

9ea459e11   Al Viro   delayed mntput
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
  	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/...
1200
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
1201
1202
1203
1204
  
  void mntput(struct vfsmount *mnt)
  {
  	if (mnt) {
863d684f9   Al Viro   vfs: move the res...
1205
  		struct mount *m = real_mount(mnt);
b3e19d924   Nick Piggin   fs: scale mntget/...
1206
  		/* avoid cacheline pingpong, hope gcc doesn't get "smart" */
863d684f9   Al Viro   vfs: move the res...
1207
1208
1209
  		if (unlikely(m->mnt_expiry_mark))
  			m->mnt_expiry_mark = 0;
  		mntput_no_expire(m);
b3e19d924   Nick Piggin   fs: scale mntget/...
1210
1211
1212
1213
1214
1215
1216
  	}
  }
  EXPORT_SYMBOL(mntput);
  
  struct vfsmount *mntget(struct vfsmount *mnt)
  {
  	if (mnt)
83adc7532   Al Viro   vfs: spread struc...
1217
  		mnt_add_count(real_mount(mnt), 1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1218
1219
1220
  	return mnt;
  }
  EXPORT_SYMBOL(mntget);
c6609c0a1   Ian Kent   vfs: add path_is_...
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
  /* 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...
1249
  struct vfsmount *mnt_clone_internal(const struct path *path)
7b7b1ace2   Al Viro   [PATCH] saner han...
1250
  {
3064c3563   Al Viro   death to mnt_pinned
1251
1252
1253
1254
1255
1256
  	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...
1257
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1258

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

390c68436   Ram Pai   [PATCH] making na...
1265
  	down_read(&namespace_sem);
c7999c362   Al Viro   reduce m_start() ...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
  	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
1280
1281
1282
1283
  }
  
  static void *m_next(struct seq_file *m, void *v, loff_t *pos)
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1284
  	struct proc_mounts *p = m->private;
b0765fb85   Pavel Emelianov   Make /proc/self/m...
1285

c7999c362   Al Viro   reduce m_start() ...
1286
1287
1288
  	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
1289
1290
1291
1292
  }
  
  static void m_stop(struct seq_file *m, void *v)
  {
390c68436   Ram Pai   [PATCH] making na...
1293
  	up_read(&namespace_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
  }
0226f4923   Al Viro   vfs: take /proc/*...
1295
  static int m_show(struct seq_file *m, void *v)
2d4d4864a   Ram Pai   [patch 6/7] vfs: ...
1296
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1297
  	struct proc_mounts *p = m->private;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1298
  	struct mount *r = list_entry(v, struct mount, mnt_list);
0226f4923   Al Viro   vfs: take /proc/*...
1299
  	return p->show(m, &r->mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
  }
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1301
  const struct seq_operations mounts_op = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
  	.start	= m_start,
  	.next	= m_next,
  	.stop	= m_stop,
0226f4923   Al Viro   vfs: take /proc/*...
1305
  	.show	= m_show,
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1306
  };
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1307
  #endif  /* CONFIG_PROC_FS */
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1308

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1309
1310
1311
1312
1313
1314
1315
1316
  /**
   * 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...
1317
  int may_umount_tree(struct vfsmount *m)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  {
909b0a88e   Al Viro   vfs: spread struc...
1319
  	struct mount *mnt = real_mount(m);
36341f645   Ram Pai   [PATCH] mount exp...
1320
1321
  	int actual_refs = 0;
  	int minimum_refs = 0;
315fc83e5   Al Viro   vfs: spread struc...
1322
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
1323
  	BUG_ON(!m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324

b3e19d924   Nick Piggin   fs: scale mntget/...
1325
  	/* write lock needed for mnt_get_count */
719ea2fbb   Al Viro   new helpers: lock...
1326
  	lock_mount_hash();
909b0a88e   Al Viro   vfs: spread struc...
1327
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
83adc7532   Al Viro   vfs: spread struc...
1328
  		actual_refs += mnt_get_count(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
  		minimum_refs += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1330
  	}
719ea2fbb   Al Viro   new helpers: lock...
1331
  	unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1332
1333
  
  	if (actual_refs > minimum_refs)
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1334
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335

e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1336
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
  }
  
  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: ...
1356
  	int ret = 1;
8ad08d8a0   Al Viro   may_umount() need...
1357
  	down_read(&namespace_sem);
719ea2fbb   Al Viro   new helpers: lock...
1358
  	lock_mount_hash();
1ab597386   Al Viro   vfs: spread struc...
1359
  	if (propagate_mount_busy(real_mount(mnt), 2))
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1360
  		ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
1361
  	unlock_mount_hash();
8ad08d8a0   Al Viro   may_umount() need...
1362
  	up_read(&namespace_sem);
a05964f39   Ram Pai   [PATCH] shared mo...
1363
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
1365
1366
  }
  
  EXPORT_SYMBOL(may_umount);
38129a13e   Al Viro   switch mnt_hash t...
1367
  static HLIST_HEAD(unmounted);	/* protected by namespace_sem */
e3197d83d   Al Viro   saner umount_tree...
1368

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

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

97216be09   Al Viro   fold release_moun...
1375
  	up_write(&namespace_sem);
a3b3c5627   Eric W. Biederman   mnt: Use hlist_mo...
1376
1377
  	if (likely(hlist_empty(&head)))
  		return;
48a066e72   Al Viro   RCU'd vfsmounts
1378
  	synchronize_rcu();
87b95ce09   Al Viro   switch the IO-tri...
1379
  	group_pin_kill(&head);
70fbcdf4d   Ram Pai   [PATCH] umount_tr...
1380
  }
97216be09   Al Viro   fold release_moun...
1381
  static inline void namespace_lock(void)
e3197d83d   Al Viro   saner umount_tree...
1382
  {
97216be09   Al Viro   fold release_moun...
1383
  	down_write(&namespace_sem);
e3197d83d   Al Viro   saner umount_tree...
1384
  }
e819f1521   Eric W. Biederman   mnt: Improve the ...
1385
1386
1387
  enum umount_tree_flags {
  	UMOUNT_SYNC = 1,
  	UMOUNT_PROPAGATE = 2,
e0c9c0afd   Eric W. Biederman   mnt: Update detac...
1388
  	UMOUNT_CONNECTED = 4,
e819f1521   Eric W. Biederman   mnt: Improve the ...
1389
  };
f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
  
  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...
1419
  /*
48a066e72   Al Viro   RCU'd vfsmounts
1420
   * mount_lock must be held
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1421
1422
   * namespace_sem must be held for write
   */
e819f1521   Eric W. Biederman   mnt: Improve the ...
1423
  static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
  {
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1425
  	LIST_HEAD(tmp_list);
315fc83e5   Al Viro   vfs: spread struc...
1426
  	struct mount *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1427

5d88457eb   Eric W. Biederman   mnt: On an unmoun...
1428
1429
  	if (how & UMOUNT_PROPAGATE)
  		propagate_mount_unlock(mnt);
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1430
  	/* Gather the mounts to umount */
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1431
1432
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
  		p->mnt.mnt_flags |= MNT_UMOUNT;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1433
  		list_move(&p->mnt_list, &tmp_list);
590ce4bcb   Eric W. Biederman   mnt: Add MNT_UMOU...
1434
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435

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

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

c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1445
  	while (!list_empty(&tmp_list)) {
d29216842   Eric W. Biederman   mnt: Add a per mo...
1446
  		struct mnt_namespace *ns;
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1447
  		bool disconnect;
c003b26ff   Eric W. Biederman   mnt: In umount_tr...
1448
  		p = list_first_entry(&tmp_list, struct mount, mnt_list);
6776db3d3   Al Viro   vfs: take mnt_sha...
1449
  		list_del_init(&p->mnt_expire);
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1450
  		list_del_init(&p->mnt_list);
d29216842   Eric W. Biederman   mnt: Add a per mo...
1451
1452
1453
1454
1455
  		ns = p->mnt_ns;
  		if (ns) {
  			ns->mounts--;
  			__touch_mnt_namespace(ns);
  		}
143c8c91c   Al Viro   vfs: mnt_ns moved...
1456
  		p->mnt_ns = NULL;
e819f1521   Eric W. Biederman   mnt: Improve the ...
1457
  		if (how & UMOUNT_SYNC)
48a066e72   Al Viro   RCU'd vfsmounts
1458
  			p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
87b95ce09   Al Viro   switch the IO-tri...
1459

f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1460
  		disconnect = disconnect_mount(p, how);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1461
1462
1463
  
  		pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
  				 disconnect ? &unmounted : NULL);
676da58df   Al Viro   vfs: spread struc...
1464
  		if (mnt_has_parent(p)) {
81b6b0619   Al Viro   fix EBUSY on umou...
1465
  			mnt_add_count(p->mnt_parent, -1);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1466
1467
1468
1469
1470
1471
  			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...
1472
  		}
0f0afb1dc   Al Viro   vfs: spread struc...
1473
  		change_mnt_propagation(p, MS_PRIVATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
1475
  	}
  }
b54b9be78   Al Viro   get rid of the se...
1476
  static void shrink_submounts(struct mount *mnt);
c35038bec   Al Viro   [PATCH] do shrink...
1477

1ab597386   Al Viro   vfs: spread struc...
1478
  static int do_umount(struct mount *mnt, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
  {
1ab597386   Al Viro   vfs: spread struc...
1480
  	struct super_block *sb = mnt->mnt.mnt_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
  	int retval;
1ab597386   Al Viro   vfs: spread struc...
1482
  	retval = security_sb_umount(&mnt->mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
  	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...
1493
  		if (&mnt->mnt == current->fs->root.mnt ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
1495
  		    flags & (MNT_FORCE | MNT_DETACH))
  			return -EINVAL;
b3e19d924   Nick Piggin   fs: scale mntget/...
1496
1497
1498
1499
  		/*
  		 * 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...
1500
  		lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
1501
  		if (mnt_get_count(mnt) != 2) {
719ea2fbb   Al Viro   new helpers: lock...
1502
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
  			return -EBUSY;
b3e19d924   Nick Piggin   fs: scale mntget/...
1504
  		}
719ea2fbb   Al Viro   new helpers: lock...
1505
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1506

863d684f9   Al Viro   vfs: move the res...
1507
  		if (!xchg(&mnt->mnt_expiry_mark, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
  			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...
1520
  	if (flags & MNT_FORCE && sb->s_op->umount_begin) {
42faad996   Al Viro   [PATCH] restore s...
1521
  		sb->s_op->umount_begin(sb);
42faad996   Al Viro   [PATCH] restore s...
1522
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
  
  	/*
  	 * 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...
1533
  	if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
1535
1536
1537
  		/*
  		 * Special case for "unmounting" root ...
  		 * we just try to remount it readonly.
  		 */
a1480dcc3   Andy Lutomirski   fs: Add a missing...
1538
1539
  		if (!capable(CAP_SYS_ADMIN))
  			return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
  		down_write(&sb->s_umount);
bc98a42c1   David Howells   VFS: Convert sb->...
1541
  		if (!sb_rdonly(sb))
e462ec50c   David Howells   VFS: Differentiat...
1542
  			retval = do_remount_sb(sb, SB_RDONLY, NULL, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1543
1544
1545
  		up_write(&sb->s_umount);
  		return retval;
  	}
97216be09   Al Viro   fold release_moun...
1546
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1547
  	lock_mount_hash();
5addc5dd8   Al Viro   [PATCH] make /pro...
1548
  	event++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549

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

db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1629
1630
  	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
  		return -EINVAL;
9b40bc90a   Al Viro   get rid of unprot...
1631
1632
  	if (!may_mount())
  		return -EPERM;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1633
1634
  	if (!(flags & UMOUNT_NOFOLLOW))
  		lookup_flags |= LOOKUP_FOLLOW;
197df04c7   Al Viro   rename user_path_...
1635
  	retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1636
1637
  	if (retval)
  		goto out;
900148dca   Al Viro   vfs: spread struc...
1638
  	mnt = real_mount(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
  	retval = -EINVAL;
2d8f30380   Al Viro   [PATCH] sanitize ...
1640
  	if (path.dentry != path.mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1641
  		goto dput_and_out;
143c8c91c   Al Viro   vfs: mnt_ns moved...
1642
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1643
  		goto dput_and_out;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
1644
1645
  	if (mnt->mnt.mnt_flags & MNT_LOCKED)
  		goto dput_and_out;
b2f5d4dc3   Eric W. Biederman   umount: Disallow ...
1646
1647
1648
  	retval = -EPERM;
  	if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
  		goto dput_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1649

900148dca   Al Viro   vfs: spread struc...
1650
  	retval = do_umount(mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1651
  dput_and_out:
429731b15   Jan Blunck   Remove path_relea...
1652
  	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
2d8f30380   Al Viro   [PATCH] sanitize ...
1653
  	dput(path.dentry);
900148dca   Al Viro   vfs: spread struc...
1654
  	mntput_no_expire(mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1655
1656
1657
1658
1659
1660
1661
  out:
  	return retval;
  }
  
  #ifdef __ARCH_WANT_SYS_OLDUMOUNT
  
  /*
b58fed8b1   Ram Pai   [PATCH] lindent f...
1662
   *	The 2.0 compatible umount. No flags.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1663
   */
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
1664
  SYSCALL_DEFINE1(oldumount, char __user *, name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1665
  {
b58fed8b1   Ram Pai   [PATCH] lindent f...
1666
  	return sys_umount(name, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1667
1668
1669
  }
  
  #endif
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1670
  static bool is_mnt_ns_file(struct dentry *dentry)
8823c079b   Eric W. Biederman   vfs: Add setns su...
1671
  {
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1672
  	/* Is this a proxy for a mount namespace? */
e149ed2b8   Al Viro   take the targets ...
1673
1674
  	return dentry->d_op == &ns_dentry_operations &&
  	       dentry->d_fsdata == &mntns_operations;
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1675
  }
58be28256   Al Viro   make mntns ->get(...
1676
1677
1678
1679
  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...
1680
1681
1682
1683
1684
1685
1686
1687
  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_...
1688
  	mnt_ns = to_mnt_ns(get_proc_ns(dentry->d_inode));
8823c079b   Eric W. Biederman   vfs: Add setns su...
1689
1690
  	return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
  }
87129cc0e   Al Viro   vfs: spread struc...
1691
  struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
36341f645   Ram Pai   [PATCH] mount exp...
1692
  					int flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
  {
84d17192d   Al Viro   get rid of full-h...
1694
  	struct mount *res, *p, *q, *r, *parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695

4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1696
1697
1698
1699
  	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...
1700
  		return ERR_PTR(-EINVAL);
9676f0c63   Ram Pai   [PATCH] unbindabl...
1701

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

909b0a88e   Al Viro   vfs: spread struc...
1812
  	for (p = mnt; p != end; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
1813
  		if (p->mnt_group_id && !IS_MNT_SHARED(p))
4b8b21f4f   Al Viro   vfs: spread struc...
1814
  			mnt_release_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1815
1816
  	}
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1817
  static int invent_group_ids(struct mount *mnt, bool recurse)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1818
  {
315fc83e5   Al Viro   vfs: spread struc...
1819
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1820

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

1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1929
1930
1931
1932
1933
1934
  	/* 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...
1935
1936
1937
1938
1939
1940
  	/* 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...
1941
  	if (IS_MNT_SHARED(dest_mnt)) {
0fb54e505   Al Viro   vfs: spread struc...
1942
  		err = invent_group_ids(source_mnt, true);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1943
1944
  		if (err)
  			goto out;
0b1b901b5   Al Viro   don't bother with...
1945
  		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
f2ebb3a92   Al Viro   smarter propagate...
1946
  		lock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
1947
1948
  		if (err)
  			goto out_cleanup_ids;
909b0a88e   Al Viro   vfs: spread struc...
1949
  		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
0f0afb1dc   Al Viro   vfs: spread struc...
1950
  			set_mnt_shared(p);
0b1b901b5   Al Viro   don't bother with...
1951
1952
  	} else {
  		lock_mount_hash();
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1953
  	}
1a3906895   Al Viro   [PATCH] reduce st...
1954
  	if (parent_path) {
0fb54e505   Al Viro   vfs: spread struc...
1955
  		detach_mnt(source_mnt, parent_path);
84d17192d   Al Viro   get rid of full-h...
1956
  		attach_mnt(source_mnt, dest_mnt, dest_mp);
143c8c91c   Al Viro   vfs: mnt_ns moved...
1957
  		touch_mnt_namespace(source_mnt->mnt_ns);
214444032   Ram Pai   [PATCH] shared mo...
1958
  	} else {
84d17192d   Al Viro   get rid of full-h...
1959
  		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1960
  		commit_tree(source_mnt);
214444032   Ram Pai   [PATCH] shared mo...
1961
  	}
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1962

38129a13e   Al Viro   switch mnt_hash t...
1963
  	hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
1d6a32acd   Al Viro   keep shadowed vfs...
1964
  		struct mount *q;
38129a13e   Al Viro   switch mnt_hash t...
1965
  		hlist_del_init(&child->mnt_hash);
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1966
1967
1968
1969
1970
  		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...
1971
  	}
1064f874a   Eric W. Biederman   mnt: Tuck mounts ...
1972
  	put_mountpoint(smp);
719ea2fbb   Al Viro   new helpers: lock...
1973
  	unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1974

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

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

84d17192d   Al Viro   get rid of full-h...
2119
2120
2121
  	mp = lock_mount(path);
  	err = PTR_ERR(mp);
  	if (IS_ERR(mp))
b12cea919   Al Viro   change the lockin...
2122
  		goto out;
87129cc0e   Al Viro   vfs: spread struc...
2123
  	old = real_mount(old_path.mnt);
84d17192d   Al Viro   get rid of full-h...
2124
  	parent = real_mount(path->mnt);
87129cc0e   Al Viro   vfs: spread struc...
2125

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

e149ed2b8   Al Viro   take the targets ...
2130
2131
2132
2133
  	if (!check_mnt(parent))
  		goto out2;
  
  	if (!check_mnt(old) && old_path.dentry->d_op != &ns_dentry_operations)
b12cea919   Al Viro   change the lockin...
2134
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2136
2137
  	if (!recurse && has_locked_children(old, old_path.dentry))
  		goto out2;
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2138
  	if (recurse)
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2139
  		mnt = copy_tree(old, old_path.dentry, CL_COPY_MNT_NS_FILE);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2140
  	else
87129cc0e   Al Viro   vfs: spread struc...
2141
  		mnt = clone_mnt(old, old_path.dentry, 0);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2142

be34d1a3b   David Howells   VFS: Make clone_m...
2143
2144
  	if (IS_ERR(mnt)) {
  		err = PTR_ERR(mnt);
e9c5d8a56   Andrey Vagin   mnt: release lock...
2145
  		goto out2;
be34d1a3b   David Howells   VFS: Make clone_m...
2146
  	}
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2147

5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2148
  	mnt->mnt.mnt_flags &= ~MNT_LOCKED;
84d17192d   Al Viro   get rid of full-h...
2149
  	err = graft_tree(mnt, parent, mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2150
  	if (err) {
719ea2fbb   Al Viro   new helpers: lock...
2151
  		lock_mount_hash();
e819f1521   Eric W. Biederman   mnt: Improve the ...
2152
  		umount_tree(mnt, UMOUNT_SYNC);
719ea2fbb   Al Viro   new helpers: lock...
2153
  		unlock_mount_hash();
5b83d2c5c   Ram Pai   [PATCH] sanitize ...
2154
  	}
b12cea919   Al Viro   change the lockin...
2155
  out2:
84d17192d   Al Viro   get rid of full-h...
2156
  	unlock_mount(mp);
ccd48bc7f   Al Viro   [PATCH] cleanups ...
2157
  out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2158
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2159
2160
  	return err;
  }
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
  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...
2172
  		error = mnt_make_readonly(real_mount(mnt));
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2173
  	else
83adc7532   Al Viro   vfs: spread struc...
2174
  		__mnt_unmake_readonly(real_mount(mnt));
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2175
2176
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2177
2178
2179
2180
2181
  /*
   * 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...
2182
2183
  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
2184
2185
  {
  	int err;
2d92ab3c6   Al Viro   [PATCH] finally g...
2186
  	struct super_block *sb = path->mnt->mnt_sb;
143c8c91c   Al Viro   vfs: mnt_ns moved...
2187
  	struct mount *mnt = real_mount(path->mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2188

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2267
  	err = -EINVAL;
fc7be130c   Al Viro   vfs: switch pnode...
2268
  	if (!check_mnt(p) || !check_mnt(old))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2269
  		goto out1;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
2270
2271
  	if (old->mnt.mnt_flags & MNT_LOCKED)
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2272
  	err = -EINVAL;
2d92ab3c6   Al Viro   [PATCH] finally g...
2273
  	if (old_path.dentry != old_path.mnt->mnt_root)
214444032   Ram Pai   [PATCH] shared mo...
2274
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2275

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

e36cb0b89   David Howells   VFS: (Scripted) C...
2279
2280
  	if (d_is_dir(path->dentry) !=
  	      d_is_dir(old_path.dentry))
214444032   Ram Pai   [PATCH] shared mo...
2281
2282
2283
2284
  		goto out1;
  	/*
  	 * Don't move a mount residing in a shared parent.
  	 */
fc7be130c   Al Viro   vfs: switch pnode...
2285
  	if (IS_MNT_SHARED(old->mnt_parent))
214444032   Ram Pai   [PATCH] shared mo...
2286
  		goto out1;
9676f0c63   Ram Pai   [PATCH] unbindabl...
2287
2288
2289
2290
  	/*
  	 * Don't move a mount tree containing unbindable mounts to a destination
  	 * mount which is shared.
  	 */
fc7be130c   Al Viro   vfs: switch pnode...
2291
  	if (IS_MNT_SHARED(p) && tree_contains_unbindable(old))
9676f0c63   Ram Pai   [PATCH] unbindabl...
2292
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2293
  	err = -ELOOP;
fc7be130c   Al Viro   vfs: switch pnode...
2294
  	for (; mnt_has_parent(p); p = p->mnt_parent)
676da58df   Al Viro   vfs: spread struc...
2295
  		if (p == old)
214444032   Ram Pai   [PATCH] shared mo...
2296
  			goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2297

84d17192d   Al Viro   get rid of full-h...
2298
  	err = attach_recursive_mnt(old, real_mount(path->mnt), mp, &parent_path);
4ac913785   Jan Blunck   Embed a struct pa...
2299
  	if (err)
214444032   Ram Pai   [PATCH] shared mo...
2300
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2301
2302
2303
  
  	/* if the mount is moved, it should no longer be expire
  	 * automatically */
6776db3d3   Al Viro   vfs: take mnt_sha...
2304
  	list_del_init(&old->mnt_expire);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2305
  out1:
84d17192d   Al Viro   get rid of full-h...
2306
  	unlock_mount(mp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2307
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2308
  	if (!err)
1a3906895   Al Viro   [PATCH] reduce st...
2309
  		path_put(&parent_path);
2d92ab3c6   Al Viro   [PATCH] finally g...
2310
  	path_put(&old_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2311
2312
  	return err;
  }
9d412a43c   Al Viro   vfs: split off vf...
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
  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...
2335
2336
2337
  /*
   * add a mount into a namespace's mount tree
   */
95bc5f25c   Al Viro   vfs: spread struc...
2338
  static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
9d412a43c   Al Viro   vfs: split off vf...
2339
  {
84d17192d   Al Viro   get rid of full-h...
2340
2341
  	struct mountpoint *mp;
  	struct mount *parent;
9d412a43c   Al Viro   vfs: split off vf...
2342
  	int err;
f2ebb3a92   Al Viro   smarter propagate...
2343
  	mnt_flags &= ~MNT_INTERNAL_FLAGS;
9d412a43c   Al Viro   vfs: split off vf...
2344

84d17192d   Al Viro   get rid of full-h...
2345
2346
2347
  	mp = lock_mount(path);
  	if (IS_ERR(mp))
  		return PTR_ERR(mp);
9d412a43c   Al Viro   vfs: split off vf...
2348

84d17192d   Al Viro   get rid of full-h...
2349
  	parent = real_mount(path->mnt);
9d412a43c   Al Viro   vfs: split off vf...
2350
  	err = -EINVAL;
84d17192d   Al Viro   get rid of full-h...
2351
  	if (unlikely(!check_mnt(parent))) {
156cacb1d   Al Viro   do_add_mount()/um...
2352
2353
2354
2355
  		/* 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...
2356
  		if (!parent->mnt_ns)
156cacb1d   Al Viro   do_add_mount()/um...
2357
2358
  			goto unlock;
  	}
9d412a43c   Al Viro   vfs: split off vf...
2359
2360
2361
  
  	/* Refuse the same filesystem on the same mount point */
  	err = -EBUSY;
95bc5f25c   Al Viro   vfs: spread struc...
2362
  	if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
9d412a43c   Al Viro   vfs: split off vf...
2363
2364
2365
2366
  	    path->mnt->mnt_root == path->dentry)
  		goto unlock;
  
  	err = -EINVAL;
e36cb0b89   David Howells   VFS: (Scripted) C...
2367
  	if (d_is_symlink(newmnt->mnt.mnt_root))
9d412a43c   Al Viro   vfs: split off vf...
2368
  		goto unlock;
95bc5f25c   Al Viro   vfs: spread struc...
2369
  	newmnt->mnt.mnt_flags = mnt_flags;
84d17192d   Al Viro   get rid of full-h...
2370
  	err = graft_tree(newmnt, parent, mp);
9d412a43c   Al Viro   vfs: split off vf...
2371
2372
  
  unlock:
84d17192d   Al Viro   get rid of full-h...
2373
  	unlock_mount(mp);
9d412a43c   Al Viro   vfs: split off vf...
2374
2375
  	return err;
  }
b1e75df45   Al Viro   tidy up around fi...
2376

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2379
2380
2381
2382
  /*
   * create a new mount for userspace and request it to be added into the
   * namespace's tree
   */
e462ec50c   David Howells   VFS: Differentiat...
2383
  static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
808d4e3cf   Al Viro   consitify do_moun...
2384
  			int mnt_flags, const char *name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2385
  {
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2386
  	struct file_system_type *type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2387
  	struct vfsmount *mnt;
15f9a3f3e   Al Viro   don't drop newmnt...
2388
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2389

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2390
  	if (!fstype)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2391
  		return -EINVAL;
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2392
2393
2394
  	type = get_fs_type(fstype);
  	if (!type)
  		return -ENODEV;
e462ec50c   David Howells   VFS: Differentiat...
2395
  	mnt = vfs_kern_mount(type, sb_flags, name, data);
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
2396
2397
2398
2399
2400
  	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
2401
2402
  	if (IS_ERR(mnt))
  		return PTR_ERR(mnt);
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
2403
2404
2405
2406
  	if (mount_too_revealing(mnt, &mnt_flags)) {
  		mntput(mnt);
  		return -EPERM;
  	}
95bc5f25c   Al Viro   vfs: spread struc...
2407
  	err = do_add_mount(real_mount(mnt), path, mnt_flags);
15f9a3f3e   Al Viro   don't drop newmnt...
2408
2409
2410
  	if (err)
  		mntput(mnt);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2411
  }
19a167af7   Al Viro   Take the completi...
2412
2413
  int finish_automount(struct vfsmount *m, struct path *path)
  {
6776db3d3   Al Viro   vfs: take mnt_sha...
2414
  	struct mount *mnt = real_mount(m);
19a167af7   Al Viro   Take the completi...
2415
2416
2417
2418
  	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...
2419
  	BUG_ON(mnt_get_count(mnt) < 2);
19a167af7   Al Viro   Take the completi...
2420
2421
2422
  
  	if (m->mnt_sb == path->mnt->mnt_sb &&
  	    m->mnt_root == path->dentry) {
b1e75df45   Al Viro   tidy up around fi...
2423
2424
  		err = -ELOOP;
  		goto fail;
19a167af7   Al Viro   Take the completi...
2425
  	}
95bc5f25c   Al Viro   vfs: spread struc...
2426
  	err = do_add_mount(mnt, path, path->mnt->mnt_flags | MNT_SHRINKABLE);
b1e75df45   Al Viro   tidy up around fi...
2427
2428
2429
2430
  	if (!err)
  		return 0;
  fail:
  	/* remove m from any expiration list it may be on */
6776db3d3   Al Viro   vfs: take mnt_sha...
2431
  	if (!list_empty(&mnt->mnt_expire)) {
97216be09   Al Viro   fold release_moun...
2432
  		namespace_lock();
6776db3d3   Al Viro   vfs: take mnt_sha...
2433
  		list_del_init(&mnt->mnt_expire);
97216be09   Al Viro   fold release_moun...
2434
  		namespace_unlock();
19a167af7   Al Viro   Take the completi...
2435
  	}
b1e75df45   Al Viro   tidy up around fi...
2436
2437
  	mntput(m);
  	mntput(m);
19a167af7   Al Viro   Take the completi...
2438
2439
  	return err;
  }
ea5b778a8   David Howells   Unexport do_add_m...
2440
2441
2442
2443
2444
2445
2446
  /**
   * 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...
2447
  	namespace_lock();
ea5b778a8   David Howells   Unexport do_add_m...
2448

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

97216be09   Al Viro   fold release_moun...
2451
  	namespace_unlock();
ea5b778a8   David Howells   Unexport do_add_m...
2452
2453
2454
2455
  }
  EXPORT_SYMBOL(mnt_set_expiry);
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2456
2457
2458
2459
2460
2461
   * 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...
2462
  	struct mount *mnt, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2463
2464
2465
2466
  	LIST_HEAD(graveyard);
  
  	if (list_empty(mounts))
  		return;
97216be09   Al Viro   fold release_moun...
2467
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
2468
  	lock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2469
2470
2471
2472
2473
2474
2475
  
  	/* 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...
2476
  	list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
863d684f9   Al Viro   vfs: move the res...
2477
  		if (!xchg(&mnt->mnt_expiry_mark, 1) ||
1ab597386   Al Viro   vfs: spread struc...
2478
  			propagate_mount_busy(mnt, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2479
  			continue;
6776db3d3   Al Viro   vfs: take mnt_sha...
2480
  		list_move(&mnt->mnt_expire, &graveyard);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2481
  	}
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2482
  	while (!list_empty(&graveyard)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2483
  		mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2484
  		touch_mnt_namespace(mnt->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2485
  		umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2486
  	}
719ea2fbb   Al Viro   new helpers: lock...
2487
  	unlock_mount_hash();
3ab6abee5   Al Viro   more conversions ...
2488
  	namespace_unlock();
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
  }
  
  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...
2499
  static int select_submounts(struct mount *parent, struct list_head *graveyard)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2500
  {
692afc312   Al Viro   vfs: spread struc...
2501
  	struct mount *this_parent = parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2502
2503
2504
2505
  	struct list_head *next;
  	int found = 0;
  
  repeat:
6b41d536f   Al Viro   vfs: take mnt_chi...
2506
  	next = this_parent->mnt_mounts.next;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2507
  resume:
6b41d536f   Al Viro   vfs: take mnt_chi...
2508
  	while (next != &this_parent->mnt_mounts) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2509
  		struct list_head *tmp = next;
6b41d536f   Al Viro   vfs: take mnt_chi...
2510
  		struct mount *mnt = list_entry(tmp, struct mount, mnt_child);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2511
2512
  
  		next = tmp->next;
692afc312   Al Viro   vfs: spread struc...
2513
  		if (!(mnt->mnt.mnt_flags & MNT_SHRINKABLE))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2514
  			continue;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2515
2516
2517
  		/*
  		 * Descend a level if the d_mounts list is non-empty.
  		 */
6b41d536f   Al Viro   vfs: take mnt_chi...
2518
  		if (!list_empty(&mnt->mnt_mounts)) {
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2519
2520
2521
  			this_parent = mnt;
  			goto repeat;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2522

1ab597386   Al Viro   vfs: spread struc...
2523
  		if (!propagate_mount_busy(mnt, 1)) {
6776db3d3   Al Viro   vfs: take mnt_sha...
2524
  			list_move_tail(&mnt->mnt_expire, graveyard);
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2525
2526
  			found++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2527
  	}
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2528
2529
2530
2531
  	/*
  	 * All done at this level ... ascend and resume the search
  	 */
  	if (this_parent != parent) {
6b41d536f   Al Viro   vfs: take mnt_chi...
2532
  		next = this_parent->mnt_child.next;
0714a5338   Al Viro   vfs: now it can b...
2533
  		this_parent = this_parent->mnt_parent;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2534
2535
2536
2537
2538
2539
2540
2541
  		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...
2542
   *
48a066e72   Al Viro   RCU'd vfsmounts
2543
   * mount_lock must be held for write
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2544
   */
b54b9be78   Al Viro   get rid of the se...
2545
  static void shrink_submounts(struct mount *mnt)
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2546
2547
  {
  	LIST_HEAD(graveyard);
761d5c38e   Al Viro   vfs: spread struc...
2548
  	struct mount *m;
5528f911b   Trond Myklebust   VFS: Add shrink_s...
2549

5528f911b   Trond Myklebust   VFS: Add shrink_s...
2550
  	/* extract submounts of 'mountpoint' from the expiration list */
c35038bec   Al Viro   [PATCH] do shrink...
2551
  	while (select_submounts(mnt, &graveyard)) {
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2552
  		while (!list_empty(&graveyard)) {
761d5c38e   Al Viro   vfs: spread struc...
2553
  			m = list_first_entry(&graveyard, struct mount,
6776db3d3   Al Viro   vfs: take mnt_sha...
2554
  						mnt_expire);
143c8c91c   Al Viro   vfs: mnt_ns moved...
2555
  			touch_mnt_namespace(m->mnt_ns);
e819f1521   Eric W. Biederman   mnt: Improve the ...
2556
  			umount_tree(m, UMOUNT_PROPAGATE|UMOUNT_SYNC);
bcc5c7d2b   Al Viro   [PATCH] sanitize ...
2557
2558
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2559
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2560
2561
2562
2563
2564
2565
  /*
   * 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...
2566
2567
  static long exact_copy_from_user(void *to, const void __user * from,
  				 unsigned long n)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
  {
  	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...
2587
  void *copy_mount_options(const void __user * data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2588
2589
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2590
  	unsigned long size;
b40ef8696   Al Viro   saner calling con...
2591
  	char *copy;
b58fed8b1   Ram Pai   [PATCH] lindent f...
2592

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2593
  	if (!data)
b40ef8696   Al Viro   saner calling con...
2594
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2595

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2668
2669
2670
2671
2672
2673
2674
  	/* 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...
2675
2676
2677
2678
  	if (flags & MS_NOATIME)
  		mnt_flags |= MNT_NOATIME;
  	if (flags & MS_NODIRATIME)
  		mnt_flags |= MNT_NODIRATIME;
d0adde574   Matthew Garrett   Add a strictatime...
2679
2680
  	if (flags & MS_STRICTATIME)
  		mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
6bf379f26   David Howells   vfs: Undo an over...
2681
  	if (flags & MS_RDONLY)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
2682
  		mnt_flags |= MNT_READONLY;
fc33a7bb9   Christoph Hellwig   [PATCH] per-mount...
2683

ffbc6f0ea   Eric W. Biederman   mnt: Change the d...
2684
2685
2686
2687
2688
2689
2690
  	/* 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...
2691
2692
2693
2694
2695
  	sb_flags = flags & (SB_RDONLY |
  			    SB_SYNCHRONOUS |
  			    SB_MANDLOCK |
  			    SB_DIRSYNC |
  			    SB_SILENT |
917086ff2   Mimi Zohar   vfs: fix mounting...
2696
  			    SB_POSIXACL |
bdf19237e   Markus Trippelsdorf   VFS: Handle lazyt...
2697
  			    SB_LAZYTIME |
917086ff2   Mimi Zohar   vfs: fix mounting...
2698
  			    SB_I_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2699

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2700
  	if (flags & MS_REMOUNT)
e462ec50c   David Howells   VFS: Differentiat...
2701
  		retval = do_remount(&path, flags, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2702
2703
  				    data_page);
  	else if (flags & MS_BIND)
2d92ab3c6   Al Viro   [PATCH] finally g...
2704
  		retval = do_loopback(&path, dev_name, flags & MS_REC);
9676f0c63   Ram Pai   [PATCH] unbindabl...
2705
  	else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
2d92ab3c6   Al Viro   [PATCH] finally g...
2706
  		retval = do_change_type(&path, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2707
  	else if (flags & MS_MOVE)
2d92ab3c6   Al Viro   [PATCH] finally g...
2708
  		retval = do_move_mount(&path, dev_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2709
  	else
e462ec50c   David Howells   VFS: Differentiat...
2710
  		retval = do_new_mount(&path, type_page, sb_flags, mnt_flags,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2711
2712
  				      dev_name, data_page);
  dput_out:
2d92ab3c6   Al Viro   [PATCH] finally g...
2713
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2714
2715
  	return retval;
  }
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2716
2717
2718
2719
2720
2721
2722
2723
2724
  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...
2725
2726
  static void free_mnt_ns(struct mnt_namespace *ns)
  {
6344c433a   Al Viro   new helpers: ns_a...
2727
  	ns_free_inum(&ns->ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2728
  	dec_mnt_namespaces(ns->ucounts);
771b13716   Eric W. Biederman   vfs: Add a user n...
2729
2730
2731
  	put_user_ns(ns->user_ns);
  	kfree(ns);
  }
8823c079b   Eric W. Biederman   vfs: Add setns su...
2732
2733
2734
2735
2736
2737
2738
2739
  /*
   * 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...
2740
  static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2741
2742
  {
  	struct mnt_namespace *new_ns;
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2743
  	struct ucounts *ucounts;
98f842e67   Eric W. Biederman   proc: Usable inod...
2744
  	int ret;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2745

537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2746
2747
  	ucounts = inc_mnt_namespaces(user_ns);
  	if (!ucounts)
df75e7748   Eric W. Biederman   userns: When the ...
2748
  		return ERR_PTR(-ENOSPC);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2749

cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2750
  	new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2751
2752
  	if (!new_ns) {
  		dec_mnt_namespaces(ucounts);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2753
  		return ERR_PTR(-ENOMEM);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2754
  	}
6344c433a   Al Viro   new helpers: ns_a...
2755
  	ret = ns_alloc_inum(&new_ns->ns);
98f842e67   Eric W. Biederman   proc: Usable inod...
2756
2757
  	if (ret) {
  		kfree(new_ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2758
  		dec_mnt_namespaces(ucounts);
98f842e67   Eric W. Biederman   proc: Usable inod...
2759
2760
  		return ERR_PTR(ret);
  	}
33c429405   Al Viro   copy address of p...
2761
  	new_ns->ns.ops = &mntns_operations;
8823c079b   Eric W. Biederman   vfs: Add setns su...
2762
  	new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2763
2764
2765
2766
2767
  	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...
2768
  	new_ns->user_ns = get_user_ns(user_ns);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2769
  	new_ns->ucounts = ucounts;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2770
2771
  	new_ns->mounts = 0;
  	new_ns->pending_mounts = 0;
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2772
2773
  	return new_ns;
  }
0766f788e   Emese Revfy   latent_entropy: M...
2774
  __latent_entropy
9559f6891   Al Viro   fold dup_mnt_ns()...
2775
2776
  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
2777
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
2778
  	struct mnt_namespace *new_ns;
7f2da1e7d   Al Viro   [PATCH] kill altroot
2779
  	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
315fc83e5   Al Viro   vfs: spread struc...
2780
  	struct mount *p, *q;
9559f6891   Al Viro   fold dup_mnt_ns()...
2781
  	struct mount *old;
cb338d06e   Al Viro   vfs: spread struc...
2782
  	struct mount *new;
7a472ef4b   Eric W. Biederman   vfs: Only support...
2783
  	int copy_flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2784

9559f6891   Al Viro   fold dup_mnt_ns()...
2785
2786
2787
2788
2789
2790
2791
2792
  	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...
2793
  	new_ns = alloc_mnt_ns(user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2794
2795
  	if (IS_ERR(new_ns))
  		return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2796

97216be09   Al Viro   fold release_moun...
2797
  	namespace_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2798
  	/* First pass: copy the tree topology */
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2799
  	copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;
9559f6891   Al Viro   fold dup_mnt_ns()...
2800
  	if (user_ns != ns->user_ns)
132c94e31   Eric W. Biederman   vfs: Carefully pr...
2801
  		copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
7a472ef4b   Eric W. Biederman   vfs: Only support...
2802
  	new = copy_tree(old, old->mnt.mnt_root, copy_flags);
be34d1a3b   David Howells   VFS: Make clone_m...
2803
  	if (IS_ERR(new)) {
328e6d901   Al Viro   switch unlock_mou...
2804
  		namespace_unlock();
771b13716   Eric W. Biederman   vfs: Add a user n...
2805
  		free_mnt_ns(new_ns);
be34d1a3b   David Howells   VFS: Make clone_m...
2806
  		return ERR_CAST(new);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2807
  	}
be08d6d26   Al Viro   switch mnt_namesp...
2808
  	new_ns->root = new;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2809
  	list_add_tail(&new_ns->list, &new->mnt_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2810
2811
2812
2813
2814
2815
  
  	/*
  	 * 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...
2816
  	p = old;
cb338d06e   Al Viro   vfs: spread struc...
2817
  	q = new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2818
  	while (p) {
143c8c91c   Al Viro   vfs: mnt_ns moved...
2819
  		q->mnt_ns = new_ns;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2820
  		new_ns->mounts++;
9559f6891   Al Viro   fold dup_mnt_ns()...
2821
2822
2823
  		if (new_fs) {
  			if (&p->mnt == new_fs->root.mnt) {
  				new_fs->root.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
2824
  				rootmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2825
  			}
9559f6891   Al Viro   fold dup_mnt_ns()...
2826
2827
  			if (&p->mnt == new_fs->pwd.mnt) {
  				new_fs->pwd.mnt = mntget(&q->mnt);
315fc83e5   Al Viro   vfs: spread struc...
2828
  				pwdmnt = &p->mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2829
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2830
  		}
909b0a88e   Al Viro   vfs: spread struc...
2831
2832
  		p = next_mnt(p, old);
  		q = next_mnt(q, new);
4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
2833
2834
2835
2836
  		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
2837
  	}
328e6d901   Al Viro   switch unlock_mou...
2838
  	namespace_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2839

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2840
  	if (rootmnt)
f03c65993   Al Viro   sanitize vfsmount...
2841
  		mntput(rootmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2842
  	if (pwdmnt)
f03c65993   Al Viro   sanitize vfsmount...
2843
  		mntput(pwdmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2844

741a29513   JANAK DESAI   [PATCH] unshare s...
2845
  	return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2846
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2847
2848
2849
2850
  /**
   * 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...
2851
  static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2852
  {
771b13716   Eric W. Biederman   vfs: Add a user n...
2853
  	struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2854
  	if (!IS_ERR(new_ns)) {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2855
2856
  		struct mount *mnt = real_mount(m);
  		mnt->mnt_ns = new_ns;
be08d6d26   Al Viro   switch mnt_namesp...
2857
  		new_ns->root = mnt;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2858
  		new_ns->mounts++;
b1983cd89   Al Viro   create_mnt_ns: un...
2859
  		list_add(&mnt->mnt_list, &new_ns->list);
c13344958   Al Viro   switch create_mnt...
2860
  	} else {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2861
  		mntput(m);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2862
2863
2864
  	}
  	return new_ns;
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2865

ea441d110   Al Viro   new helper: mount...
2866
2867
2868
  struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
  {
  	struct mnt_namespace *ns;
d31da0f0b   Al Viro   mount_subtree() p...
2869
  	struct super_block *s;
ea441d110   Al Viro   new helper: mount...
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
  	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...
2886
2887
  	s = path.mnt->mnt_sb;
  	atomic_inc(&s->s_active);
ea441d110   Al Viro   new helper: mount...
2888
2889
  	mntput(path.mnt);
  	/* lock the sucker */
d31da0f0b   Al Viro   mount_subtree() p...
2890
  	down_write(&s->s_umount);
ea441d110   Al Viro   new helper: mount...
2891
2892
2893
2894
  	/* ... and return the root of (sub)tree on it */
  	return path.dentry;
  }
  EXPORT_SYMBOL(mount_subtree);
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
2895
2896
  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
2897
  {
eca6f534e   Vegard Nossum   fs: fix overflow ...
2898
2899
  	int ret;
  	char *kernel_type;
eca6f534e   Vegard Nossum   fs: fix overflow ...
2900
  	char *kernel_dev;
b40ef8696   Al Viro   saner calling con...
2901
  	void *options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2902

b8850d1fa   Tim Gardner   fs: namespace: su...
2903
2904
2905
  	kernel_type = copy_mount_string(type);
  	ret = PTR_ERR(kernel_type);
  	if (IS_ERR(kernel_type))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2906
  		goto out_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2907

b8850d1fa   Tim Gardner   fs: namespace: su...
2908
2909
2910
  	kernel_dev = copy_mount_string(dev_name);
  	ret = PTR_ERR(kernel_dev);
  	if (IS_ERR(kernel_dev))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2911
  		goto out_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2912

b40ef8696   Al Viro   saner calling con...
2913
2914
2915
  	options = copy_mount_options(data);
  	ret = PTR_ERR(options);
  	if (IS_ERR(options))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2916
  		goto out_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2917

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

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

2d8f30380   Al Viro   [PATCH] sanitize ...
2991
  	error = user_path_dir(put_old, &old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2992
2993
  	if (error)
  		goto out1;
2d8f30380   Al Viro   [PATCH] sanitize ...
2994
  	error = security_sb_pivotroot(&old, &new);
b12cea919   Al Viro   change the lockin...
2995
2996
  	if (error)
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2997

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

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3079
3080
3081
3082
3083
  	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
3084
3085
  	if (IS_ERR(mnt))
  		panic("Can't create rootfs");
b3e19d924   Nick Piggin   fs: scale mntget/...
3086

3b22edc57   Trond Myklebust   VFS: Switch init_...
3087
3088
  	ns = create_mnt_ns(mnt);
  	if (IS_ERR(ns))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3089
  		panic("Can't allocate initial namespace");
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3090
3091
3092
  
  	init_task.nsproxy->mnt_ns = ns;
  	get_mnt_ns(ns);
be08d6d26   Al Viro   switch mnt_namesp...
3093
3094
  	root.mnt = mnt;
  	root.dentry = mnt->mnt_root;
da362b09e   Eric W. Biederman   umount: Do not al...
3095
  	mnt->mnt_flags |= MNT_LOCKED;
ac748a09f   Jan Blunck   Make set_fs_{root...
3096
3097
3098
  
  	set_fs_pwd(current->fs, &root);
  	set_fs_root(current->fs, &root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3099
  }
74bf17cff   Denis Cheng   fs: remove the un...
3100
  void __init mnt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3101
  {
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3102
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3103

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

0818bf27c   Al Viro   resizable namespa...
3107
  	mount_hashtable = alloc_large_system_hash("Mount-cache",
38129a13e   Al Viro   switch mnt_hash t...
3108
  				sizeof(struct hlist_head),
0818bf27c   Al Viro   resizable namespa...
3109
  				mhash_entries, 19,
3d375d785   Pavel Tatashin   mm: update caller...
3110
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3111
3112
3113
3114
  				&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...
3115
  				HASH_ZERO,
0818bf27c   Al Viro   resizable namespa...
3116
  				&mp_hash_shift, &mp_hash_mask, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3117

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

3151527ee   Eric W. Biederman   userns: Don't al...
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
  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_...
3196
3197
  static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
  				int *new_mnt_flags)
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3198
  {
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3199
  	int new_flags = *new_mnt_flags;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3200
  	struct mount *mnt;
e51db7353   Eric W. Biederman   userns: Better re...
3201
  	bool visible = false;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3202

44bb4385c   Al Viro   fs_is_visible onl...
3203
  	down_read(&namespace_sem);
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3204
  	list_for_each_entry(mnt, &ns->list, mnt_list) {
e51db7353   Eric W. Biederman   userns: Better re...
3205
  		struct mount *child;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3206
  		int mnt_flags;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3207
  		if (mnt->mnt.mnt_sb->s_type != new->mnt_sb->s_type)
e51db7353   Eric W. Biederman   userns: Better re...
3208
  			continue;
7e96c1b0e   Eric W. Biederman   mnt: Fix fs_fully...
3209
3210
3211
3212
3213
  		/* 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...
3214
  		/* A local view of the mount flags */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3215
  		mnt_flags = mnt->mnt.mnt_flags;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3216

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

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3311
  	if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
c7b96acf1   Eric W. Biederman   userns: Kill nso...
3312
3313
  	    !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
  	    !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
ae11e0f18   Zhao Hongjiang   userns: fix retur...
3314
  		return -EPERM;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3315
3316
3317
3318
3319
  
  	if (fs->users != 1)
  		return -EINVAL;
  
  	get_mnt_ns(mnt_ns);
4f757f3cb   Al Viro   make sure that mn...
3320
  	old_mnt_ns = nsproxy->mnt_ns;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3321
3322
3323
  	nsproxy->mnt_ns = mnt_ns;
  
  	/* Find the root */
4f757f3cb   Al Viro   make sure that mn...
3324
3325
3326
3327
3328
3329
3330
3331
  	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...
3332

4068367c9   Andrei Vagin   fs: don't forget ...
3333
  	put_mnt_ns(old_mnt_ns);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3334
3335
3336
3337
3338
3339
3340
  	/* 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...
3341
3342
3343
3344
  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...
3345
3346
3347
3348
3349
3350
  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...
3351
  	.owner		= mntns_owner,
8823c079b   Eric W. Biederman   vfs: Add setns su...
3352
  };