Blame view

fs/namespace.c 83.8 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>
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
17
  #include <linux/idr.h>
57f150a58   Rob Landley   initmpfs: move ro...
18
  #include <linux/init.h>		/* init_rootfs */
d10577a8d   Al Viro   vfs: trim include...
19
20
21
  #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...
22
  #include <linux/proc_ns.h>
20b4fb485   Linus Torvalds   Merge branch 'for...
23
  #include <linux/magic.h>
0818bf27c   Al Viro   resizable namespa...
24
  #include <linux/bootmem.h>
9ea459e11   Al Viro   delayed mntput
25
  #include <linux/task_work.h>
07b20889e   Ram Pai   [PATCH] beginning...
26
  #include "pnode.h"
948730b0e   Adrian Bunk   fs/namespace.c sh...
27
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28

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

c7999c362   Al Viro   reduce m_start() ...
56
  static u64 event;
73cd49ecd   Miklos Szeredi   [patch 3/7] vfs: ...
57
  static DEFINE_IDA(mnt_id_ida);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
58
  static DEFINE_IDA(mnt_group_ida);
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
59
  static DEFINE_SPINLOCK(mnt_id_lock);
f21f62208   Al Viro   ... and the same ...
60
61
  static int mnt_id_start = 0;
  static int mnt_group_start = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

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

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

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

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

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

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

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

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

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

83adc7532   Al Viro   vfs: spread struc...
514
  static void __mnt_unmake_readonly(struct mount *mnt)
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
515
  {
719ea2fbb   Al Viro   new helpers: lock...
516
  	lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
517
  	mnt->mnt.mnt_flags &= ~MNT_READONLY;
719ea2fbb   Al Viro   new helpers: lock...
518
  	unlock_mount_hash();
2e4b7fcd9   Dave Hansen   [PATCH] r/o bind ...
519
  }
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
520
521
522
523
  int sb_prepare_remount_readonly(struct super_block *sb)
  {
  	struct mount *mnt;
  	int err = 0;
8e8b87964   Miklos Szeredi   vfs: prevent remo...
524
525
526
  	/* 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...
527
  	lock_mount_hash();
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
528
529
530
531
532
533
534
535
536
537
  	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...
538
539
  	if (!err && atomic_long_read(&sb->s_remove_count))
  		err = -EBUSY;
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
540
541
542
543
544
545
546
547
  	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...
548
  	unlock_mount_hash();
4ed5e82fe   Miklos Szeredi   vfs: protect remo...
549
550
551
  
  	return err;
  }
b105e270b   Al Viro   vfs: spread struc...
552
  static void free_vfsmnt(struct mount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
  {
fcc139ae2   Andrzej Hajda   fs/namespace: con...
554
  	kfree_const(mnt->mnt_devname);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
555
  #ifdef CONFIG_SMP
68e8a9fea   Al Viro   vfs: all counters...
556
  	free_percpu(mnt->mnt_pcp);
d3ef3d735   npiggin@suse.de   fs: mnt_want_writ...
557
  #endif
b105e270b   Al Viro   vfs: spread struc...
558
  	kmem_cache_free(mnt_cache, mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
  }
8ffcb32e0   David Howells   VFS: Make delayed...
560
561
562
563
  static void delayed_free_vfsmnt(struct rcu_head *head)
  {
  	free_vfsmnt(container_of(head, struct mount, mnt_rcu));
  }
48a066e72   Al Viro   RCU'd vfsmounts
564
  /* call under rcu_read_lock */
294d71ff2   Al Viro   new helper: __leg...
565
  int __legitimize_mnt(struct vfsmount *bastard, unsigned seq)
48a066e72   Al Viro   RCU'd vfsmounts
566
567
568
  {
  	struct mount *mnt;
  	if (read_seqretry(&mount_lock, seq))
294d71ff2   Al Viro   new helper: __leg...
569
  		return 1;
48a066e72   Al Viro   RCU'd vfsmounts
570
  	if (bastard == NULL)
294d71ff2   Al Viro   new helper: __leg...
571
  		return 0;
48a066e72   Al Viro   RCU'd vfsmounts
572
573
574
  	mnt = real_mount(bastard);
  	mnt_add_count(mnt, 1);
  	if (likely(!read_seqretry(&mount_lock, seq)))
294d71ff2   Al Viro   new helper: __leg...
575
  		return 0;
48a066e72   Al Viro   RCU'd vfsmounts
576
577
  	if (bastard->mnt_flags & MNT_SYNC_UMOUNT) {
  		mnt_add_count(mnt, -1);
294d71ff2   Al Viro   new helper: __leg...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  		return 1;
  	}
  	return -1;
  }
  
  /* call under rcu_read_lock */
  bool legitimize_mnt(struct vfsmount *bastard, unsigned seq)
  {
  	int res = __legitimize_mnt(bastard, seq);
  	if (likely(!res))
  		return true;
  	if (unlikely(res < 0)) {
  		rcu_read_unlock();
  		mntput(bastard);
  		rcu_read_lock();
48a066e72   Al Viro   RCU'd vfsmounts
593
  	}
48a066e72   Al Viro   RCU'd vfsmounts
594
595
  	return false;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
  /*
474279dc0   Al Viro   split __lookup_mn...
597
   * find the first mount at @dentry on vfsmount @mnt.
48a066e72   Al Viro   RCU'd vfsmounts
598
   * call under rcu_read_lock()
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
   */
474279dc0   Al Viro   split __lookup_mn...
600
  struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  {
38129a13e   Al Viro   switch mnt_hash t...
602
  	struct hlist_head *head = m_hash(mnt, dentry);
474279dc0   Al Viro   split __lookup_mn...
603
  	struct mount *p;
38129a13e   Al Viro   switch mnt_hash t...
604
  	hlist_for_each_entry_rcu(p, head, mnt_hash)
474279dc0   Al Viro   split __lookup_mn...
605
606
607
608
609
610
611
  		if (&p->mnt_parent->mnt == mnt && p->mnt_mountpoint == dentry)
  			return p;
  	return NULL;
  }
  
  /*
   * find the last mount at @dentry on vfsmount @mnt.
48a066e72   Al Viro   RCU'd vfsmounts
612
   * mount_lock must be held.
474279dc0   Al Viro   split __lookup_mn...
613
614
615
   */
  struct mount *__lookup_mnt_last(struct vfsmount *mnt, struct dentry *dentry)
  {
411a938b5   Eric W. Biederman   mnt: Delay remova...
616
617
  	struct mount *p, *res = NULL;
  	p = __lookup_mnt(mnt, dentry);
38129a13e   Al Viro   switch mnt_hash t...
618
619
  	if (!p)
  		goto out;
411a938b5   Eric W. Biederman   mnt: Delay remova...
620
621
  	if (!(p->mnt.mnt_flags & MNT_UMOUNT))
  		res = p;
38129a13e   Al Viro   switch mnt_hash t...
622
  	hlist_for_each_entry_continue(p, mnt_hash) {
1d6a32acd   Al Viro   keep shadowed vfs...
623
624
  		if (&p->mnt_parent->mnt != mnt || p->mnt_mountpoint != dentry)
  			break;
411a938b5   Eric W. Biederman   mnt: Delay remova...
625
626
  		if (!(p->mnt.mnt_flags & MNT_UMOUNT))
  			res = p;
1d6a32acd   Al Viro   keep shadowed vfs...
627
  	}
38129a13e   Al Viro   switch mnt_hash t...
628
  out:
1d6a32acd   Al Viro   keep shadowed vfs...
629
  	return res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
  }
a05964f39   Ram Pai   [PATCH] shared mo...
631
  /*
f015f1267   David Howells   VFS: Comment moun...
632
633
634
635
636
637
638
639
640
641
642
643
644
645
   * 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...
646
   */
1c755af4d   Al Viro   switch lookup_mnt()
647
  struct vfsmount *lookup_mnt(struct path *path)
a05964f39   Ram Pai   [PATCH] shared mo...
648
  {
c71053659   Al Viro   vfs: spread struc...
649
  	struct mount *child_mnt;
48a066e72   Al Viro   RCU'd vfsmounts
650
651
  	struct vfsmount *m;
  	unsigned seq;
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
652

48a066e72   Al Viro   RCU'd vfsmounts
653
654
655
656
657
658
659
660
  	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...
661
  }
7af1364ff   Eric W. Biederman   vfs: Don't allow ...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
  /*
   * __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...
696
  static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
84d17192d   Al Viro   get rid of full-h...
697
  {
0818bf27c   Al Viro   resizable namespa...
698
  	struct hlist_head *chain = mp_hash(dentry);
84d17192d   Al Viro   get rid of full-h...
699
  	struct mountpoint *mp;
0818bf27c   Al Viro   resizable namespa...
700
  	hlist_for_each_entry(mp, chain, m_hash) {
84d17192d   Al Viro   get rid of full-h...
701
702
703
704
705
706
707
708
  		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...
709
710
  	return NULL;
  }
1a62a0f76   Eric W. Biederman   mnt: Protect the ...
711
  static struct mountpoint *get_mountpoint(struct dentry *dentry)
e2dfa9354   Eric W. Biederman   vfs: factor out l...
712
  {
1a62a0f76   Eric W. Biederman   mnt: Protect the ...
713
  	struct mountpoint *mp, *new = NULL;
e2dfa9354   Eric W. Biederman   vfs: factor out l...
714
  	int ret;
84d17192d   Al Viro   get rid of full-h...
715

1a62a0f76   Eric W. Biederman   mnt: Protect the ...
716
717
718
719
720
721
722
723
724
725
726
727
  	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...
728
  		return ERR_PTR(-ENOMEM);
1a62a0f76   Eric W. Biederman   mnt: Protect the ...
729
730
  
  	/* Exactly one processes may set d_mounted */
eed810076   Miklos Szeredi   vfs: check unlink...
731
  	ret = d_set_mounted(dentry);
eed810076   Miklos Szeredi   vfs: check unlink...
732

1a62a0f76   Eric W. Biederman   mnt: Protect the ...
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
  	/* 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...
754
755
756
757
758
759
760
  	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 ...
761
  		BUG_ON(!hlist_empty(&mp->m_list));
84d17192d   Al Viro   get rid of full-h...
762
763
764
  		spin_lock(&dentry->d_lock);
  		dentry->d_flags &= ~DCACHE_MOUNTED;
  		spin_unlock(&dentry->d_lock);
0818bf27c   Al Viro   resizable namespa...
765
  		hlist_del(&mp->m_hash);
84d17192d   Al Viro   get rid of full-h...
766
767
768
  		kfree(mp);
  	}
  }
143c8c91c   Al Viro   vfs: mnt_ns moved...
769
  static inline int check_mnt(struct mount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
  {
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
771
  	return mnt->mnt_ns == current->nsproxy->mnt_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
773
774
775
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
776
  static void touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
777
778
779
780
781
782
  {
  	if (ns) {
  		ns->event = ++event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
783
784
785
  /*
   * vfsmount lock must be held for write
   */
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
786
  static void __touch_mnt_namespace(struct mnt_namespace *ns)
5addc5dd8   Al Viro   [PATCH] make /pro...
787
788
789
790
791
792
  {
  	if (ns && ns->event != event) {
  		ns->event = event;
  		wake_up_interruptible(&ns->poll);
  	}
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
793
794
795
  /*
   * vfsmount lock must be held for write
   */
7bdb11de8   Eric W. Biederman   mnt: Factor out u...
796
  static void unhash_mnt(struct mount *mnt)
419148da6   Al Viro   vfs: spread struc...
797
  {
0714a5338   Al Viro   vfs: now it can b...
798
  	mnt->mnt_parent = mnt;
a73324da7   Al Viro   vfs: move mnt_mou...
799
  	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
6b41d536f   Al Viro   vfs: take mnt_chi...
800
  	list_del_init(&mnt->mnt_child);
38129a13e   Al Viro   switch mnt_hash t...
801
  	hlist_del_init_rcu(&mnt->mnt_hash);
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
802
  	hlist_del_init(&mnt->mnt_mp_list);
84d17192d   Al Viro   get rid of full-h...
803
804
  	put_mountpoint(mnt->mnt_mp);
  	mnt->mnt_mp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
806
807
808
  /*
   * vfsmount lock must be held for write
   */
7bdb11de8   Eric W. Biederman   mnt: Factor out u...
809
810
811
812
813
814
815
816
817
818
  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...
819
820
821
822
823
824
825
826
827
828
  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...
829
830
  void mnt_set_mountpoint(struct mount *mnt,
  			struct mountpoint *mp,
44d964d60   Al Viro   vfs: spread struc...
831
  			struct mount *child_mnt)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
832
  {
84d17192d   Al Viro   get rid of full-h...
833
  	mp->m_count++;
3a2393d71   Al Viro   vfs: opencode mnt...
834
  	mnt_add_count(mnt, 1);	/* essentially, that's mntget */
84d17192d   Al Viro   get rid of full-h...
835
  	child_mnt->mnt_mountpoint = dget(mp->m_dentry);
3a2393d71   Al Viro   vfs: opencode mnt...
836
  	child_mnt->mnt_parent = mnt;
84d17192d   Al Viro   get rid of full-h...
837
  	child_mnt->mnt_mp = mp;
0a5eb7c81   Eric W. Biederman   vfs: Keep a list ...
838
  	hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
839
  }
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
840
841
842
  /*
   * vfsmount lock must be held for write
   */
84d17192d   Al Viro   get rid of full-h...
843
844
845
  static void attach_mnt(struct mount *mnt,
  			struct mount *parent,
  			struct mountpoint *mp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  {
84d17192d   Al Viro   get rid of full-h...
847
  	mnt_set_mountpoint(parent, mp, mnt);
38129a13e   Al Viro   switch mnt_hash t...
848
  	hlist_add_head_rcu(&mnt->mnt_hash, m_hash(&parent->mnt, mp->m_dentry));
84d17192d   Al Viro   get rid of full-h...
849
  	list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
850
  }
12a5b5294   Al Viro   fix copy_tree() r...
851
852
853
854
855
  static void attach_shadowed(struct mount *mnt,
  			struct mount *parent,
  			struct mount *shadows)
  {
  	if (shadows) {
f6f993328   Linus Torvalds   Merge branch 'for...
856
  		hlist_add_behind_rcu(&mnt->mnt_hash, &shadows->mnt_hash);
12a5b5294   Al Viro   fix copy_tree() r...
857
858
859
860
861
862
863
  		list_add(&mnt->mnt_child, &shadows->mnt_child);
  	} else {
  		hlist_add_head_rcu(&mnt->mnt_hash,
  				m_hash(&parent->mnt, mnt->mnt_mountpoint));
  		list_add_tail(&mnt->mnt_child, &parent->mnt_mounts);
  	}
  }
b90fa9ae8   Ram Pai   [PATCH] shared mo...
864
  /*
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
865
   * vfsmount lock must be held for write
b90fa9ae8   Ram Pai   [PATCH] shared mo...
866
   */
1d6a32acd   Al Viro   keep shadowed vfs...
867
  static void commit_tree(struct mount *mnt, struct mount *shadows)
b90fa9ae8   Ram Pai   [PATCH] shared mo...
868
  {
0714a5338   Al Viro   vfs: now it can b...
869
  	struct mount *parent = mnt->mnt_parent;
83adc7532   Al Viro   vfs: spread struc...
870
  	struct mount *m;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
871
  	LIST_HEAD(head);
143c8c91c   Al Viro   vfs: mnt_ns moved...
872
  	struct mnt_namespace *n = parent->mnt_ns;
b90fa9ae8   Ram Pai   [PATCH] shared mo...
873

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

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

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

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

7a472ef4b   Eric W. Biederman   vfs: Only support...
953
  	if (flag & (CL_SLAVE | CL_PRIVATE | CL_SHARED_TO_SLAVE))
be34d1a3b   David Howells   VFS: Make clone_m...
954
955
956
  		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...
957

be34d1a3b   David Howells   VFS: Make clone_m...
958
959
960
961
  	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
962
  	}
be34d1a3b   David Howells   VFS: Make clone_m...
963

f2ebb3a92   Al Viro   smarter propagate...
964
  	mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED);
132c94e31   Eric W. Biederman   vfs: Carefully pr...
965
  	/* Don't allow unprivileged users to change mount flags */
9566d6742   Eric W. Biederman   mnt: Correct perm...
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
  	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...
981

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

7a472ef4b   Eric W. Biederman   vfs: Only support...
995
996
  	if ((flag & CL_SLAVE) ||
  	    ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
be34d1a3b   David Howells   VFS: Make clone_m...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
  		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;
  	}
  	if (flag & CL_MAKE_SHARED)
  		set_mnt_shared(mnt);
  
  	/* stick the duplicate mount on the same expiry list
  	 * as the original if that was on one */
  	if (flag & CL_EXPIRE) {
  		if (!list_empty(&old->mnt_expire))
  			list_add(&mnt->mnt_expire, &old->mnt_expire);
  	}
cb338d06e   Al Viro   vfs: spread struc...
1016
  	return mnt;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1017
1018
  
   out_free:
8ffcb32e0   David Howells   VFS: Make delayed...
1019
  	mnt_free_id(mnt);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1020
  	free_vfsmnt(mnt);
be34d1a3b   David Howells   VFS: Make clone_m...
1021
  	return ERR_PTR(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
  }
9ea459e11   Al Viro   delayed mntput
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
  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);
  	struct llist_node *next;
  
  	for (; node; node = next) {
  		next = llist_next(node);
  		cleanup_mnt(llist_entry(node, struct mount, mnt_llist));
  	}
  }
  static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput);
900148dca   Al Viro   vfs: spread struc...
1062
  static void mntput_no_expire(struct mount *mnt)
b3e19d924   Nick Piggin   fs: scale mntget/...
1063
  {
48a066e72   Al Viro   RCU'd vfsmounts
1064
1065
1066
1067
  	rcu_read_lock();
  	mnt_add_count(mnt, -1);
  	if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */
  		rcu_read_unlock();
f03c65993   Al Viro   sanitize vfsmount...
1068
  		return;
b3e19d924   Nick Piggin   fs: scale mntget/...
1069
  	}
719ea2fbb   Al Viro   new helpers: lock...
1070
  	lock_mount_hash();
b3e19d924   Nick Piggin   fs: scale mntget/...
1071
  	if (mnt_get_count(mnt)) {
48a066e72   Al Viro   RCU'd vfsmounts
1072
  		rcu_read_unlock();
719ea2fbb   Al Viro   new helpers: lock...
1073
  		unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1074
1075
  		return;
  	}
48a066e72   Al Viro   RCU'd vfsmounts
1076
1077
1078
1079
1080
1081
1082
  	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: ...
1083

39f7c4db1   Miklos Szeredi   vfs: keep list of...
1084
  	list_del(&mnt->mnt_instance);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1085
1086
1087
1088
1089
1090
1091
  
  	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...
1092
  	unlock_mount_hash();
649a795af   Al Viro   fold mntfree() in...
1093

9ea459e11   Al Viro   delayed mntput
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
  	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/...
1106
  }
b3e19d924   Nick Piggin   fs: scale mntget/...
1107
1108
1109
1110
  
  void mntput(struct vfsmount *mnt)
  {
  	if (mnt) {
863d684f9   Al Viro   vfs: move the res...
1111
  		struct mount *m = real_mount(mnt);
b3e19d924   Nick Piggin   fs: scale mntget/...
1112
  		/* avoid cacheline pingpong, hope gcc doesn't get "smart" */
863d684f9   Al Viro   vfs: move the res...
1113
1114
1115
  		if (unlikely(m->mnt_expiry_mark))
  			m->mnt_expiry_mark = 0;
  		mntput_no_expire(m);
b3e19d924   Nick Piggin   fs: scale mntget/...
1116
1117
1118
1119
1120
1121
1122
  	}
  }
  EXPORT_SYMBOL(mntput);
  
  struct vfsmount *mntget(struct vfsmount *mnt)
  {
  	if (mnt)
83adc7532   Al Viro   vfs: spread struc...
1123
  		mnt_add_count(real_mount(mnt), 1);
b3e19d924   Nick Piggin   fs: scale mntget/...
1124
1125
1126
  	return mnt;
  }
  EXPORT_SYMBOL(mntget);
3064c3563   Al Viro   death to mnt_pinned
1127
  struct vfsmount *mnt_clone_internal(struct path *path)
7b7b1ace2   Al Viro   [PATCH] saner han...
1128
  {
3064c3563   Al Viro   death to mnt_pinned
1129
1130
1131
1132
1133
1134
  	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...
1135
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136

b3b304a23   Miklos Szeredi   mount options: ad...
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
  static inline void mangle(struct seq_file *m, const char *s)
  {
  	seq_escape(m, s, " \t
  \\");
  }
  
  /*
   * Simple .show_options callback for filesystems which don't want to
   * implement more complex mount option showing.
   *
   * See also save_mount_options().
   */
34c80b1d9   Al Viro   vfs: switch ->sho...
1149
  int generic_show_options(struct seq_file *m, struct dentry *root)
b3b304a23   Miklos Szeredi   mount options: ad...
1150
  {
2a32cebd6   Al Viro   Fix races around ...
1151
1152
1153
  	const char *options;
  
  	rcu_read_lock();
34c80b1d9   Al Viro   vfs: switch ->sho...
1154
  	options = rcu_dereference(root->d_sb->s_options);
b3b304a23   Miklos Szeredi   mount options: ad...
1155
1156
1157
1158
1159
  
  	if (options != NULL && options[0]) {
  		seq_putc(m, ',');
  		mangle(m, options);
  	}
2a32cebd6   Al Viro   Fix races around ...
1160
  	rcu_read_unlock();
b3b304a23   Miklos Szeredi   mount options: ad...
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
  
  	return 0;
  }
  EXPORT_SYMBOL(generic_show_options);
  
  /*
   * If filesystem uses generic_show_options(), this function should be
   * called from the fill_super() callback.
   *
   * The .remount_fs callback usually needs to be handled in a special
   * way, to make sure, that previous options are not overwritten if the
   * remount fails.
   *
   * Also note, that if the filesystem's .remount_fs function doesn't
   * reset all options to their default value, but changes only newly
   * given options, then the displayed options will not reflect reality
   * any more.
   */
  void save_mount_options(struct super_block *sb, char *options)
  {
2a32cebd6   Al Viro   Fix races around ...
1181
1182
  	BUG_ON(sb->s_options);
  	rcu_assign_pointer(sb->s_options, kstrdup(options, GFP_KERNEL));
b3b304a23   Miklos Szeredi   mount options: ad...
1183
1184
  }
  EXPORT_SYMBOL(save_mount_options);
2a32cebd6   Al Viro   Fix races around ...
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
  void replace_mount_options(struct super_block *sb, char *options)
  {
  	char *old = sb->s_options;
  	rcu_assign_pointer(sb->s_options, options);
  	if (old) {
  		synchronize_rcu();
  		kfree(old);
  	}
  }
  EXPORT_SYMBOL(replace_mount_options);
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1195
  #ifdef CONFIG_PROC_FS
0226f4923   Al Viro   vfs: take /proc/*...
1196
  /* iterator; we want it to have access to namespace_sem, thus here... */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
1198
  static void *m_start(struct seq_file *m, loff_t *pos)
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1199
  	struct proc_mounts *p = m->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1200

390c68436   Ram Pai   [PATCH] making na...
1201
  	down_read(&namespace_sem);
c7999c362   Al Viro   reduce m_start() ...
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
  	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
1216
1217
1218
1219
  }
  
  static void *m_next(struct seq_file *m, void *v, loff_t *pos)
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1220
  	struct proc_mounts *p = m->private;
b0765fb85   Pavel Emelianov   Make /proc/self/m...
1221

c7999c362   Al Viro   reduce m_start() ...
1222
1223
1224
  	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
1225
1226
1227
1228
  }
  
  static void m_stop(struct seq_file *m, void *v)
  {
390c68436   Ram Pai   [PATCH] making na...
1229
  	up_read(&namespace_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
  }
0226f4923   Al Viro   vfs: take /proc/*...
1231
  static int m_show(struct seq_file *m, void *v)
2d4d4864a   Ram Pai   [patch 6/7] vfs: ...
1232
  {
ede1bf0dc   Yann Droneaud   fs: use seq_open_...
1233
  	struct proc_mounts *p = m->private;
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
1234
  	struct mount *r = list_entry(v, struct mount, mnt_list);
0226f4923   Al Viro   vfs: take /proc/*...
1235
  	return p->show(m, &r->mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1236
  }
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1237
  const struct seq_operations mounts_op = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1238
1239
1240
  	.start	= m_start,
  	.next	= m_next,
  	.stop	= m_stop,
0226f4923   Al Viro   vfs: take /proc/*...
1241
  	.show	= m_show,
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1242
  };
a1a2c409b   Miklos Szeredi   [patch 5/7] vfs: ...
1243
  #endif  /* CONFIG_PROC_FS */
b4629fe2f   Chuck Lever   VFS: New /proc fi...
1244

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
1246
1247
1248
1249
1250
1251
1252
  /**
   * 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...
1253
  int may_umount_tree(struct vfsmount *m)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
  {
909b0a88e   Al Viro   vfs: spread struc...
1255
  	struct mount *mnt = real_mount(m);
36341f645   Ram Pai   [PATCH] mount exp...
1256
1257
  	int actual_refs = 0;
  	int minimum_refs = 0;
315fc83e5   Al Viro   vfs: spread struc...
1258
  	struct mount *p;
909b0a88e   Al Viro   vfs: spread struc...
1259
  	BUG_ON(!m);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260

b3e19d924   Nick Piggin   fs: scale mntget/...
1261
  	/* write lock needed for mnt_get_count */
719ea2fbb   Al Viro   new helpers: lock...
1262
  	lock_mount_hash();
909b0a88e   Al Viro   vfs: spread struc...
1263
  	for (p = mnt; p; p = next_mnt(p, mnt)) {
83adc7532   Al Viro   vfs: spread struc...
1264
  		actual_refs += mnt_get_count(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
  		minimum_refs += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1266
  	}
719ea2fbb   Al Viro   new helpers: lock...
1267
  	unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1268
1269
  
  	if (actual_refs > minimum_refs)
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1270
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271

e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1272
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
  }
  
  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: ...
1292
  	int ret = 1;
8ad08d8a0   Al Viro   may_umount() need...
1293
  	down_read(&namespace_sem);
719ea2fbb   Al Viro   new helpers: lock...
1294
  	lock_mount_hash();
1ab597386   Al Viro   vfs: spread struc...
1295
  	if (propagate_mount_busy(real_mount(mnt), 2))
e3474a8eb   Ian Kent   [PATCH] autofs4: ...
1296
  		ret = 0;
719ea2fbb   Al Viro   new helpers: lock...
1297
  	unlock_mount_hash();
8ad08d8a0   Al Viro   may_umount() need...
1298
  	up_read(&namespace_sem);
a05964f39   Ram Pai   [PATCH] shared mo...
1299
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
1301
1302
  }
  
  EXPORT_SYMBOL(may_umount);
38129a13e   Al Viro   switch mnt_hash t...
1303
  static HLIST_HEAD(unmounted);	/* protected by namespace_sem */
e3197d83d   Al Viro   saner umount_tree...
1304

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

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

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

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

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

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

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

f2d0a123b   Eric W. Biederman   mnt: Clarify and ...
1396
  		disconnect = disconnect_mount(p, how);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1397
1398
1399
  
  		pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
  				 disconnect ? &unmounted : NULL);
676da58df   Al Viro   vfs: spread struc...
1400
  		if (mnt_has_parent(p)) {
81b6b0619   Al Viro   fix EBUSY on umou...
1401
  			mnt_add_count(p->mnt_parent, -1);
ce07d891a   Eric W. Biederman   mnt: Honor MNT_LO...
1402
1403
1404
1405
1406
1407
  			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...
1408
  		}
0f0afb1dc   Al Viro   vfs: spread struc...
1409
  		change_mnt_propagation(p, MS_PRIVATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1410
1411
  	}
  }
b54b9be78   Al Viro   get rid of the se...
1412
  static void shrink_submounts(struct mount *mnt);
c35038bec   Al Viro   [PATCH] do shrink...
1413

1ab597386   Al Viro   vfs: spread struc...
1414
  static int do_umount(struct mount *mnt, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
  {
1ab597386   Al Viro   vfs: spread struc...
1416
  	struct super_block *sb = mnt->mnt.mnt_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
  	int retval;
1ab597386   Al Viro   vfs: spread struc...
1418
  	retval = security_sb_umount(&mnt->mnt, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
  	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...
1429
  		if (&mnt->mnt == current->fs->root.mnt ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
1431
  		    flags & (MNT_FORCE | MNT_DETACH))
  			return -EINVAL;
b3e19d924   Nick Piggin   fs: scale mntget/...
1432
1433
1434
1435
  		/*
  		 * 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...
1436
  		lock_mount_hash();
83adc7532   Al Viro   vfs: spread struc...
1437
  		if (mnt_get_count(mnt) != 2) {
719ea2fbb   Al Viro   new helpers: lock...
1438
  			unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1439
  			return -EBUSY;
b3e19d924   Nick Piggin   fs: scale mntget/...
1440
  		}
719ea2fbb   Al Viro   new helpers: lock...
1441
  		unlock_mount_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442

863d684f9   Al Viro   vfs: move the res...
1443
  		if (!xchg(&mnt->mnt_expiry_mark, 1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
  			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...
1456
  	if (flags & MNT_FORCE && sb->s_op->umount_begin) {
42faad996   Al Viro   [PATCH] restore s...
1457
  		sb->s_op->umount_begin(sb);
42faad996   Al Viro   [PATCH] restore s...
1458
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
  
  	/*
  	 * 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...
1469
  	if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1470
1471
1472
1473
  		/*
  		 * Special case for "unmounting" root ...
  		 * we just try to remount it readonly.
  		 */
a1480dcc3   Andy Lutomirski   fs: Add a missing...
1474
1475
  		if (!capable(CAP_SYS_ADMIN))
  			return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
  		down_write(&sb->s_umount);
4aa98cf76   Al Viro   Push BKL down int...
1477
  		if (!(sb->s_flags & MS_RDONLY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  			retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
1480
1481
  		up_write(&sb->s_umount);
  		return retval;
  	}
97216be09   Al Viro   fold release_moun...
1482
  	namespace_lock();
719ea2fbb   Al Viro   new helpers: lock...
1483
  	lock_mount_hash();
5addc5dd8   Al Viro   [PATCH] make /pro...
1484
  	event++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485

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

db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1565
1566
  	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
  		return -EINVAL;
9b40bc90a   Al Viro   get rid of unprot...
1567
1568
  	if (!may_mount())
  		return -EPERM;
db1f05bb8   Miklos Szeredi   vfs: add NOFOLLOW...
1569
1570
  	if (!(flags & UMOUNT_NOFOLLOW))
  		lookup_flags |= LOOKUP_FOLLOW;
197df04c7   Al Viro   rename user_path_...
1571
  	retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572
1573
  	if (retval)
  		goto out;
900148dca   Al Viro   vfs: spread struc...
1574
  	mnt = real_mount(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575
  	retval = -EINVAL;
2d8f30380   Al Viro   [PATCH] sanitize ...
1576
  	if (path.dentry != path.mnt->mnt_root)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
  		goto dput_and_out;
143c8c91c   Al Viro   vfs: mnt_ns moved...
1578
  	if (!check_mnt(mnt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1579
  		goto dput_and_out;
5ff9d8a65   Eric W. Biederman   vfs: Lock in plac...
1580
1581
  	if (mnt->mnt.mnt_flags & MNT_LOCKED)
  		goto dput_and_out;
b2f5d4dc3   Eric W. Biederman   umount: Disallow ...
1582
1583
1584
  	retval = -EPERM;
  	if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
  		goto dput_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585

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

4ce5d2b1a   Eric W. Biederman   vfs: Don't copy m...
1632
1633
1634
1635
  	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...
1636
  		return ERR_PTR(-EINVAL);
9676f0c63   Ram Pai   [PATCH] unbindabl...
1637

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

909b0a88e   Al Viro   vfs: spread struc...
1759
  	for (p = mnt; p != end; p = next_mnt(p, mnt)) {
fc7be130c   Al Viro   vfs: switch pnode...
1760
  		if (p->mnt_group_id && !IS_MNT_SHARED(p))
4b8b21f4f   Al Viro   vfs: spread struc...
1761
  			mnt_release_group_id(p);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1762
1763
  	}
  }
4b8b21f4f   Al Viro   vfs: spread struc...
1764
  static int invent_group_ids(struct mount *mnt, bool recurse)
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1765
  {
315fc83e5   Al Viro   vfs: spread struc...
1766
  	struct mount *p;
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1767

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

d29216842   Eric W. Biederman   mnt: Add a per mo...
1875
1876
1877
1878
1879
1880
  	/* 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...
1881
  	if (IS_MNT_SHARED(dest_mnt)) {
0fb54e505   Al Viro   vfs: spread struc...
1882
  		err = invent_group_ids(source_mnt, true);
719f5d7f0   Miklos Szeredi   [patch 4/7] vfs: ...
1883
1884
  		if (err)
  			goto out;
0b1b901b5   Al Viro   don't bother with...
1885
  		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
f2ebb3a92   Al Viro   smarter propagate...
1886
  		lock_mount_hash();
0b1b901b5   Al Viro   don't bother with...
1887
1888
  		if (err)
  			goto out_cleanup_ids;
909b0a88e   Al Viro   vfs: spread struc...
1889
  		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
0f0afb1dc   Al Viro   vfs: spread struc...
1890
  			set_mnt_shared(p);
0b1b901b5   Al Viro   don't bother with...
1891
1892
  	} else {
  		lock_mount_hash();
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1893
  	}
1a3906895   Al Viro   [PATCH] reduce st...
1894
  	if (parent_path) {
0fb54e505   Al Viro   vfs: spread struc...
1895
  		detach_mnt(source_mnt, parent_path);
84d17192d   Al Viro   get rid of full-h...
1896
  		attach_mnt(source_mnt, dest_mnt, dest_mp);
143c8c91c   Al Viro   vfs: mnt_ns moved...
1897
  		touch_mnt_namespace(source_mnt->mnt_ns);
214444032   Ram Pai   [PATCH] shared mo...
1898
  	} else {
84d17192d   Al Viro   get rid of full-h...
1899
  		mnt_set_mountpoint(dest_mnt, dest_mp, source_mnt);
1d6a32acd   Al Viro   keep shadowed vfs...
1900
  		commit_tree(source_mnt, NULL);
214444032   Ram Pai   [PATCH] shared mo...
1901
  	}
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1902

38129a13e   Al Viro   switch mnt_hash t...
1903
  	hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) {
1d6a32acd   Al Viro   keep shadowed vfs...
1904
  		struct mount *q;
38129a13e   Al Viro   switch mnt_hash t...
1905
  		hlist_del_init(&child->mnt_hash);
1d6a32acd   Al Viro   keep shadowed vfs...
1906
1907
1908
  		q = __lookup_mnt_last(&child->mnt_parent->mnt,
  				      child->mnt_mountpoint);
  		commit_tree(child, q);
b90fa9ae8   Ram Pai   [PATCH] shared mo...
1909
  	}
719ea2fbb   Al Viro   new helpers: lock...
1910
  	unlock_mount_hash();
99b7db7b8   Nick Piggin   fs: brlock vfsmou...
1911

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ffbc6f0ea   Eric W. Biederman   mnt: Change the d...
2615
2616
2617
2618
2619
2620
2621
  	/* 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;
  	}
7a4dec538   Al Viro   Fix sget() race w...
2622
  	flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
d0adde574   Matthew Garrett   Add a strictatime...
2623
  		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
c568d6834   Miklos Szeredi   locks: fix file l...
2624
  		   MS_STRICTATIME | MS_NOREMOTELOCK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2625

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

537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2672
2673
  	ucounts = inc_mnt_namespaces(user_ns);
  	if (!ucounts)
df75e7748   Eric W. Biederman   userns: When the ...
2674
  		return ERR_PTR(-ENOSPC);
537f7ccb3   Eric W. Biederman   mntns: Add a limi...
2675

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

9559f6891   Al Viro   fold dup_mnt_ns()...
2711
2712
2713
2714
2715
2716
2717
2718
  	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...
2719
  	new_ns = alloc_mnt_ns(user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2720
2721
  	if (IS_ERR(new_ns))
  		return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2722

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2766
  	if (rootmnt)
f03c65993   Al Viro   sanitize vfsmount...
2767
  		mntput(rootmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2768
  	if (pwdmnt)
f03c65993   Al Viro   sanitize vfsmount...
2769
  		mntput(pwdmnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2770

741a29513   JANAK DESAI   [PATCH] unshare s...
2771
  	return new_ns;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2772
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2773
2774
2775
2776
  /**
   * 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...
2777
  static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2778
  {
771b13716   Eric W. Biederman   vfs: Add a user n...
2779
  	struct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2780
  	if (!IS_ERR(new_ns)) {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2781
2782
  		struct mount *mnt = real_mount(m);
  		mnt->mnt_ns = new_ns;
be08d6d26   Al Viro   switch mnt_namesp...
2783
  		new_ns->root = mnt;
d29216842   Eric W. Biederman   mnt: Add a per mo...
2784
  		new_ns->mounts++;
b1983cd89   Al Viro   create_mnt_ns: un...
2785
  		list_add(&mnt->mnt_list, &new_ns->list);
c13344958   Al Viro   switch create_mnt...
2786
  	} else {
1a4eeaf2a   Al Viro   vfs: move mnt_lis...
2787
  		mntput(m);
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2788
2789
2790
  	}
  	return new_ns;
  }
cf8d2c11c   Trond Myklebust   VFS: Add VFS help...
2791

ea441d110   Al Viro   new helper: mount...
2792
2793
2794
  struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
  {
  	struct mnt_namespace *ns;
d31da0f0b   Al Viro   mount_subtree() p...
2795
  	struct super_block *s;
ea441d110   Al Viro   new helper: mount...
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
  	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...
2812
2813
  	s = path.mnt->mnt_sb;
  	atomic_inc(&s->s_active);
ea441d110   Al Viro   new helper: mount...
2814
2815
  	mntput(path.mnt);
  	/* lock the sucker */
d31da0f0b   Al Viro   mount_subtree() p...
2816
  	down_write(&s->s_umount);
ea441d110   Al Viro   new helper: mount...
2817
2818
2819
2820
  	/* ... and return the root of (sub)tree on it */
  	return path.dentry;
  }
  EXPORT_SYMBOL(mount_subtree);
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
2821
2822
  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
2823
  {
eca6f534e   Vegard Nossum   fs: fix overflow ...
2824
2825
  	int ret;
  	char *kernel_type;
eca6f534e   Vegard Nossum   fs: fix overflow ...
2826
  	char *kernel_dev;
b40ef8696   Al Viro   saner calling con...
2827
  	void *options;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2828

b8850d1fa   Tim Gardner   fs: namespace: su...
2829
2830
2831
  	kernel_type = copy_mount_string(type);
  	ret = PTR_ERR(kernel_type);
  	if (IS_ERR(kernel_type))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2832
  		goto out_type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2833

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

b40ef8696   Al Viro   saner calling con...
2839
2840
2841
  	options = copy_mount_options(data);
  	ret = PTR_ERR(options);
  	if (IS_ERR(options))
eca6f534e   Vegard Nossum   fs: fix overflow ...
2842
  		goto out_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2843

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

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

2d8f30380   Al Viro   [PATCH] sanitize ...
2917
  	error = user_path_dir(put_old, &old);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2918
2919
  	if (error)
  		goto out1;
2d8f30380   Al Viro   [PATCH] sanitize ...
2920
  	error = security_sb_pivotroot(&old, &new);
b12cea919   Al Viro   change the lockin...
2921
2922
  	if (error)
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2923

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

0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3005
3006
3007
3008
3009
  	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
3010
3011
  	if (IS_ERR(mnt))
  		panic("Can't create rootfs");
b3e19d924   Nick Piggin   fs: scale mntget/...
3012

3b22edc57   Trond Myklebust   VFS: Switch init_...
3013
3014
  	ns = create_mnt_ns(mnt);
  	if (IS_ERR(ns))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3015
  		panic("Can't allocate initial namespace");
6b3286ed1   Kirill Korotaev   [PATCH] rename st...
3016
3017
3018
  
  	init_task.nsproxy->mnt_ns = ns;
  	get_mnt_ns(ns);
be08d6d26   Al Viro   switch mnt_namesp...
3019
3020
  	root.mnt = mnt;
  	root.dentry = mnt->mnt_root;
da362b09e   Eric W. Biederman   umount: Do not al...
3021
  	mnt->mnt_flags |= MNT_LOCKED;
ac748a09f   Jan Blunck   Make set_fs_{root...
3022
3023
3024
  
  	set_fs_pwd(current->fs, &root);
  	set_fs_root(current->fs, &root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3025
  }
74bf17cff   Denis Cheng   fs: remove the un...
3026
  void __init mnt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3027
  {
13f14b4d8   Eric Dumazet   Use ilog2() in fs...
3028
  	unsigned u;
15a67dd8c   Randy Dunlap   [PATCH] fs/namesp...
3029
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3030

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

0818bf27c   Al Viro   resizable namespa...
3034
  	mount_hashtable = alloc_large_system_hash("Mount-cache",
38129a13e   Al Viro   switch mnt_hash t...
3035
  				sizeof(struct hlist_head),
0818bf27c   Al Viro   resizable namespa...
3036
3037
3038
3039
3040
3041
3042
3043
  				mhash_entries, 19,
  				0,
  				&m_hash_shift, &m_hash_mask, 0, 0);
  	mountpoint_hashtable = alloc_large_system_hash("Mountpoint-cache",
  				sizeof(struct hlist_head),
  				mphash_entries, 19,
  				0,
  				&mp_hash_shift, &mp_hash_mask, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3044

84d17192d   Al Viro   get rid of full-h...
3045
  	if (!mount_hashtable || !mountpoint_hashtable)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3046
3047
  		panic("Failed to allocate mount hash table
  ");
0818bf27c   Al Viro   resizable namespa...
3048
  	for (u = 0; u <= m_hash_mask; u++)
38129a13e   Al Viro   switch mnt_hash t...
3049
  		INIT_HLIST_HEAD(&mount_hashtable[u]);
0818bf27c   Al Viro   resizable namespa...
3050
3051
  	for (u = 0; u <= mp_hash_mask; u++)
  		INIT_HLIST_HEAD(&mountpoint_hashtable[u]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3052

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

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

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

695e9df01   Eric W. Biederman   mnt: Account for ...
3149
3150
3151
  		/* Don't miss readonly hidden in the superblock flags */
  		if (mnt->mnt.mnt_sb->s_flags & MS_RDONLY)
  			mnt_flags |= MNT_LOCK_READONLY;
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3152
3153
3154
  		/* Verify the mount flags are equal to or more permissive
  		 * than the proposed new mount.
  		 */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3155
  		if ((mnt_flags & MNT_LOCK_READONLY) &&
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3156
3157
  		    !(new_flags & MNT_READONLY))
  			continue;
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3158
3159
  		if ((mnt_flags & MNT_LOCK_ATIME) &&
  		    ((mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3160
  			continue;
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3161
3162
3163
  		/* 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...
3164
3165
3166
  		 */
  		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...
3167
  			/* Only worry about locked mounts */
d71ed6c93   Eric W. Biederman   mnt: fs_fully_vis...
3168
  			if (!(child->mnt.mnt_flags & MNT_LOCKED))
ceeb0e5d3   Eric W. Biederman   vfs: Ignore unloc...
3169
  				continue;
7236c85e1   Eric W. Biederman   mnt: Update fs_fu...
3170
3171
  			/* Is the directory permanetly empty? */
  			if (!is_empty_dir_inode(inode))
e51db7353   Eric W. Biederman   userns: Better re...
3172
  				goto next;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3173
  		}
8c6cf9cc8   Eric W. Biederman   mnt: Modify fs_fu...
3174
  		/* Preserve the locked attributes */
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3175
  		*new_mnt_flags |= mnt_flags & (MNT_LOCK_READONLY | \
77b1a97d2   Eric W. Biederman   mnt: fs_fully_vis...
3176
  					       MNT_LOCK_ATIME);
e51db7353   Eric W. Biederman   userns: Better re...
3177
3178
3179
  		visible = true;
  		goto found;
  	next:	;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3180
  	}
e51db7353   Eric W. Biederman   userns: Better re...
3181
  found:
44bb4385c   Al Viro   fs_is_visible onl...
3182
  	up_read(&namespace_sem);
e51db7353   Eric W. Biederman   userns: Better re...
3183
  	return visible;
87a8ebd63   Eric W. Biederman   userns: Restrict ...
3184
  }
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3185
3186
  static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
  {
a1935c173   Eric W. Biederman   mnt: Simplify mou...
3187
  	const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
8654df4e2   Eric W. Biederman   mnt: Refactor fs_...
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
  	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...
3198
3199
3200
3201
3202
3203
  	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_...
3204
3205
  	return !mnt_already_visible(ns, mnt, new_mnt_flags);
  }
380cf5ba6   Andy Lutomirski   fs: Treat foreign...
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
  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...
3218
  static struct ns_common *mntns_get(struct task_struct *task)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3219
  {
58be28256   Al Viro   make mntns ->get(...
3220
  	struct ns_common *ns = NULL;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3221
  	struct nsproxy *nsproxy;
728dba3a3   Eric W. Biederman   namespaces: Use t...
3222
3223
  	task_lock(task);
  	nsproxy = task->nsproxy;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3224
  	if (nsproxy) {
58be28256   Al Viro   make mntns ->get(...
3225
3226
  		ns = &nsproxy->mnt_ns->ns;
  		get_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3227
  	}
728dba3a3   Eric W. Biederman   namespaces: Use t...
3228
  	task_unlock(task);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3229
3230
3231
  
  	return ns;
  }
64964528b   Al Viro   make proc_ns_oper...
3232
  static void mntns_put(struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3233
  {
58be28256   Al Viro   make mntns ->get(...
3234
  	put_mnt_ns(to_mnt_ns(ns));
8823c079b   Eric W. Biederman   vfs: Add setns su...
3235
  }
64964528b   Al Viro   make proc_ns_oper...
3236
  static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
8823c079b   Eric W. Biederman   vfs: Add setns su...
3237
3238
  {
  	struct fs_struct *fs = current->fs;
58be28256   Al Viro   make mntns ->get(...
3239
  	struct mnt_namespace *mnt_ns = to_mnt_ns(ns);
8823c079b   Eric W. Biederman   vfs: Add setns su...
3240
  	struct path root;
0c55cfc41   Eric W. Biederman   vfs: Allow unpriv...
3241
  	if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
c7b96acf1   Eric W. Biederman   userns: Kill nso...
3242
3243
  	    !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
  	    !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
ae11e0f18   Zhao Hongjiang   userns: fix retur...
3244
  		return -EPERM;
8823c079b   Eric W. Biederman   vfs: Add setns su...
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
  
  	if (fs->users != 1)
  		return -EINVAL;
  
  	get_mnt_ns(mnt_ns);
  	put_mnt_ns(nsproxy->mnt_ns);
  	nsproxy->mnt_ns = mnt_ns;
  
  	/* Find the root */
  	root.mnt    = &mnt_ns->root->mnt;
  	root.dentry = mnt_ns->root->mnt.mnt_root;
  	path_get(&root);
  	while(d_mountpoint(root.dentry) && follow_down_one(&root))
  		;
  
  	/* 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...
3267
3268
3269
3270
  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...
3271
3272
3273
3274
3275
3276
  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...
3277
  	.owner		= mntns_owner,
8823c079b   Eric W. Biederman   vfs: Add setns su...
3278
  };