xref: /linux/fs/fs_struct.c (revision b7d3622a39fde7658170b7f3cf6c6889bb8db30d)
1630d9c47SPaul Gortmaker #include <linux/export.h>
23e93cd67SAl Viro #include <linux/sched.h>
33e93cd67SAl Viro #include <linux/fs.h>
43e93cd67SAl Viro #include <linux/path.h>
53e93cd67SAl Viro #include <linux/slab.h>
65ad4e53bSAl Viro #include <linux/fs_struct.h>
7f03c6599SAl Viro #include "internal.h"
8f03c6599SAl Viro 
93e93cd67SAl Viro /*
103e93cd67SAl Viro  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
113e93cd67SAl Viro  * It can block.
123e93cd67SAl Viro  */
13dcf787f3SAl Viro void set_fs_root(struct fs_struct *fs, const struct path *path)
143e93cd67SAl Viro {
153e93cd67SAl Viro 	struct path old_root;
163e93cd67SAl Viro 
17f7a99c5bSAl Viro 	path_get(path);
182a4419b5SNick Piggin 	spin_lock(&fs->lock);
19c28cc364SNick Piggin 	write_seqcount_begin(&fs->seq);
203e93cd67SAl Viro 	old_root = fs->root;
213e93cd67SAl Viro 	fs->root = *path;
22c28cc364SNick Piggin 	write_seqcount_end(&fs->seq);
232a4419b5SNick Piggin 	spin_unlock(&fs->lock);
243e93cd67SAl Viro 	if (old_root.dentry)
25f7a99c5bSAl Viro 		path_put(&old_root);
263e93cd67SAl Viro }
273e93cd67SAl Viro 
283e93cd67SAl Viro /*
293e93cd67SAl Viro  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
303e93cd67SAl Viro  * It can block.
313e93cd67SAl Viro  */
32dcf787f3SAl Viro void set_fs_pwd(struct fs_struct *fs, const struct path *path)
333e93cd67SAl Viro {
343e93cd67SAl Viro 	struct path old_pwd;
353e93cd67SAl Viro 
36f7a99c5bSAl Viro 	path_get(path);
372a4419b5SNick Piggin 	spin_lock(&fs->lock);
38c28cc364SNick Piggin 	write_seqcount_begin(&fs->seq);
393e93cd67SAl Viro 	old_pwd = fs->pwd;
403e93cd67SAl Viro 	fs->pwd = *path;
41c28cc364SNick Piggin 	write_seqcount_end(&fs->seq);
422a4419b5SNick Piggin 	spin_unlock(&fs->lock);
433e93cd67SAl Viro 
443e93cd67SAl Viro 	if (old_pwd.dentry)
45f7a99c5bSAl Viro 		path_put(&old_pwd);
463e93cd67SAl Viro }
473e93cd67SAl Viro 
4882234e61SAl Viro static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
4982234e61SAl Viro {
5082234e61SAl Viro 	if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
5182234e61SAl Viro 		return 0;
5282234e61SAl Viro 	*p = *new;
5382234e61SAl Viro 	return 1;
5482234e61SAl Viro }
5582234e61SAl Viro 
56dcf787f3SAl Viro void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
573e93cd67SAl Viro {
583e93cd67SAl Viro 	struct task_struct *g, *p;
593e93cd67SAl Viro 	struct fs_struct *fs;
603e93cd67SAl Viro 	int count = 0;
613e93cd67SAl Viro 
623e93cd67SAl Viro 	read_lock(&tasklist_lock);
633e93cd67SAl Viro 	do_each_thread(g, p) {
643e93cd67SAl Viro 		task_lock(p);
653e93cd67SAl Viro 		fs = p->fs;
663e93cd67SAl Viro 		if (fs) {
6782234e61SAl Viro 			int hits = 0;
682a4419b5SNick Piggin 			spin_lock(&fs->lock);
69c28cc364SNick Piggin 			write_seqcount_begin(&fs->seq);
7082234e61SAl Viro 			hits += replace_path(&fs->root, old_root, new_root);
7182234e61SAl Viro 			hits += replace_path(&fs->pwd, old_root, new_root);
72c28cc364SNick Piggin 			write_seqcount_end(&fs->seq);
7382234e61SAl Viro 			while (hits--) {
7482234e61SAl Viro 				count++;
75f7a99c5bSAl Viro 				path_get(new_root);
7682234e61SAl Viro 			}
772a4419b5SNick Piggin 			spin_unlock(&fs->lock);
783e93cd67SAl Viro 		}
793e93cd67SAl Viro 		task_unlock(p);
803e93cd67SAl Viro 	} while_each_thread(g, p);
813e93cd67SAl Viro 	read_unlock(&tasklist_lock);
823e93cd67SAl Viro 	while (count--)
83f7a99c5bSAl Viro 		path_put(old_root);
843e93cd67SAl Viro }
853e93cd67SAl Viro 
86498052bbSAl Viro void free_fs_struct(struct fs_struct *fs)
873e93cd67SAl Viro {
88f7a99c5bSAl Viro 	path_put(&fs->root);
89f7a99c5bSAl Viro 	path_put(&fs->pwd);
903e93cd67SAl Viro 	kmem_cache_free(fs_cachep, fs);
913e93cd67SAl Viro }
923e93cd67SAl Viro 
933e93cd67SAl Viro void exit_fs(struct task_struct *tsk)
943e93cd67SAl Viro {
953e93cd67SAl Viro 	struct fs_struct *fs = tsk->fs;
963e93cd67SAl Viro 
973e93cd67SAl Viro 	if (fs) {
98498052bbSAl Viro 		int kill;
993e93cd67SAl Viro 		task_lock(tsk);
1002a4419b5SNick Piggin 		spin_lock(&fs->lock);
1013e93cd67SAl Viro 		tsk->fs = NULL;
102498052bbSAl Viro 		kill = !--fs->users;
1032a4419b5SNick Piggin 		spin_unlock(&fs->lock);
1043e93cd67SAl Viro 		task_unlock(tsk);
105498052bbSAl Viro 		if (kill)
106498052bbSAl Viro 			free_fs_struct(fs);
1073e93cd67SAl Viro 	}
1083e93cd67SAl Viro }
1093e93cd67SAl Viro 
1103e93cd67SAl Viro struct fs_struct *copy_fs_struct(struct fs_struct *old)
1113e93cd67SAl Viro {
1123e93cd67SAl Viro 	struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
1133e93cd67SAl Viro 	/* We don't need to lock fs - think why ;-) */
1143e93cd67SAl Viro 	if (fs) {
115498052bbSAl Viro 		fs->users = 1;
116498052bbSAl Viro 		fs->in_exec = 0;
1172a4419b5SNick Piggin 		spin_lock_init(&fs->lock);
118c28cc364SNick Piggin 		seqcount_init(&fs->seq);
1193e93cd67SAl Viro 		fs->umask = old->umask;
120b3e19d92SNick Piggin 
121b3e19d92SNick Piggin 		spin_lock(&old->lock);
122b3e19d92SNick Piggin 		fs->root = old->root;
123f7a99c5bSAl Viro 		path_get(&fs->root);
124b3e19d92SNick Piggin 		fs->pwd = old->pwd;
125f7a99c5bSAl Viro 		path_get(&fs->pwd);
126b3e19d92SNick Piggin 		spin_unlock(&old->lock);
1273e93cd67SAl Viro 	}
1283e93cd67SAl Viro 	return fs;
1293e93cd67SAl Viro }
1303e93cd67SAl Viro 
1313e93cd67SAl Viro int unshare_fs_struct(void)
1323e93cd67SAl Viro {
133498052bbSAl Viro 	struct fs_struct *fs = current->fs;
134498052bbSAl Viro 	struct fs_struct *new_fs = copy_fs_struct(fs);
135498052bbSAl Viro 	int kill;
136498052bbSAl Viro 
137498052bbSAl Viro 	if (!new_fs)
1383e93cd67SAl Viro 		return -ENOMEM;
139498052bbSAl Viro 
140498052bbSAl Viro 	task_lock(current);
1412a4419b5SNick Piggin 	spin_lock(&fs->lock);
142498052bbSAl Viro 	kill = !--fs->users;
143498052bbSAl Viro 	current->fs = new_fs;
1442a4419b5SNick Piggin 	spin_unlock(&fs->lock);
145498052bbSAl Viro 	task_unlock(current);
146498052bbSAl Viro 
147498052bbSAl Viro 	if (kill)
148498052bbSAl Viro 		free_fs_struct(fs);
149498052bbSAl Viro 
1503e93cd67SAl Viro 	return 0;
1513e93cd67SAl Viro }
1523e93cd67SAl Viro EXPORT_SYMBOL_GPL(unshare_fs_struct);
1533e93cd67SAl Viro 
154ce3b0f8dSAl Viro int current_umask(void)
155ce3b0f8dSAl Viro {
156ce3b0f8dSAl Viro 	return current->fs->umask;
157ce3b0f8dSAl Viro }
158ce3b0f8dSAl Viro EXPORT_SYMBOL(current_umask);
159ce3b0f8dSAl Viro 
1603e93cd67SAl Viro /* to be mentioned only in INIT_TASK */
1613e93cd67SAl Viro struct fs_struct init_fs = {
162498052bbSAl Viro 	.users		= 1,
1632a4419b5SNick Piggin 	.lock		= __SPIN_LOCK_UNLOCKED(init_fs.lock),
164*1ca7d67cSJohn Stultz 	.seq		= SEQCNT_ZERO(init_fs.seq),
1653e93cd67SAl Viro 	.umask		= 0022,
1663e93cd67SAl Viro };
167