xref: /linux/fs/fs_struct.c (revision c28cc36469554dc55540f059fbdc7fa22a2c31fc)
13e93cd67SAl Viro #include <linux/module.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>
73e93cd67SAl Viro 
83e93cd67SAl Viro /*
93e93cd67SAl Viro  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
103e93cd67SAl Viro  * It can block.
113e93cd67SAl Viro  */
123e93cd67SAl Viro void set_fs_root(struct fs_struct *fs, struct path *path)
133e93cd67SAl Viro {
143e93cd67SAl Viro 	struct path old_root;
153e93cd67SAl Viro 
162a4419b5SNick Piggin 	spin_lock(&fs->lock);
17*c28cc364SNick Piggin 	write_seqcount_begin(&fs->seq);
183e93cd67SAl Viro 	old_root = fs->root;
193e93cd67SAl Viro 	fs->root = *path;
203e93cd67SAl Viro 	path_get(path);
21*c28cc364SNick Piggin 	write_seqcount_end(&fs->seq);
222a4419b5SNick Piggin 	spin_unlock(&fs->lock);
233e93cd67SAl Viro 	if (old_root.dentry)
243e93cd67SAl Viro 		path_put(&old_root);
253e93cd67SAl Viro }
263e93cd67SAl Viro 
273e93cd67SAl Viro /*
283e93cd67SAl Viro  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
293e93cd67SAl Viro  * It can block.
303e93cd67SAl Viro  */
313e93cd67SAl Viro void set_fs_pwd(struct fs_struct *fs, struct path *path)
323e93cd67SAl Viro {
333e93cd67SAl Viro 	struct path old_pwd;
343e93cd67SAl Viro 
352a4419b5SNick Piggin 	spin_lock(&fs->lock);
36*c28cc364SNick Piggin 	write_seqcount_begin(&fs->seq);
373e93cd67SAl Viro 	old_pwd = fs->pwd;
383e93cd67SAl Viro 	fs->pwd = *path;
393e93cd67SAl Viro 	path_get(path);
40*c28cc364SNick Piggin 	write_seqcount_end(&fs->seq);
412a4419b5SNick Piggin 	spin_unlock(&fs->lock);
423e93cd67SAl Viro 
433e93cd67SAl Viro 	if (old_pwd.dentry)
443e93cd67SAl Viro 		path_put(&old_pwd);
453e93cd67SAl Viro }
463e93cd67SAl Viro 
473e93cd67SAl Viro void chroot_fs_refs(struct path *old_root, struct path *new_root)
483e93cd67SAl Viro {
493e93cd67SAl Viro 	struct task_struct *g, *p;
503e93cd67SAl Viro 	struct fs_struct *fs;
513e93cd67SAl Viro 	int count = 0;
523e93cd67SAl Viro 
533e93cd67SAl Viro 	read_lock(&tasklist_lock);
543e93cd67SAl Viro 	do_each_thread(g, p) {
553e93cd67SAl Viro 		task_lock(p);
563e93cd67SAl Viro 		fs = p->fs;
573e93cd67SAl Viro 		if (fs) {
582a4419b5SNick Piggin 			spin_lock(&fs->lock);
59*c28cc364SNick Piggin 			write_seqcount_begin(&fs->seq);
603e93cd67SAl Viro 			if (fs->root.dentry == old_root->dentry
613e93cd67SAl Viro 			    && fs->root.mnt == old_root->mnt) {
623e93cd67SAl Viro 				path_get(new_root);
633e93cd67SAl Viro 				fs->root = *new_root;
643e93cd67SAl Viro 				count++;
653e93cd67SAl Viro 			}
663e93cd67SAl Viro 			if (fs->pwd.dentry == old_root->dentry
673e93cd67SAl Viro 			    && fs->pwd.mnt == old_root->mnt) {
683e93cd67SAl Viro 				path_get(new_root);
693e93cd67SAl Viro 				fs->pwd = *new_root;
703e93cd67SAl Viro 				count++;
713e93cd67SAl Viro 			}
72*c28cc364SNick Piggin 			write_seqcount_end(&fs->seq);
732a4419b5SNick Piggin 			spin_unlock(&fs->lock);
743e93cd67SAl Viro 		}
753e93cd67SAl Viro 		task_unlock(p);
763e93cd67SAl Viro 	} while_each_thread(g, p);
773e93cd67SAl Viro 	read_unlock(&tasklist_lock);
783e93cd67SAl Viro 	while (count--)
793e93cd67SAl Viro 		path_put(old_root);
803e93cd67SAl Viro }
813e93cd67SAl Viro 
82498052bbSAl Viro void free_fs_struct(struct fs_struct *fs)
833e93cd67SAl Viro {
843e93cd67SAl Viro 	path_put(&fs->root);
853e93cd67SAl Viro 	path_put(&fs->pwd);
863e93cd67SAl Viro 	kmem_cache_free(fs_cachep, fs);
873e93cd67SAl Viro }
883e93cd67SAl Viro 
893e93cd67SAl Viro void exit_fs(struct task_struct *tsk)
903e93cd67SAl Viro {
913e93cd67SAl Viro 	struct fs_struct *fs = tsk->fs;
923e93cd67SAl Viro 
933e93cd67SAl Viro 	if (fs) {
94498052bbSAl Viro 		int kill;
953e93cd67SAl Viro 		task_lock(tsk);
962a4419b5SNick Piggin 		spin_lock(&fs->lock);
97*c28cc364SNick Piggin 		write_seqcount_begin(&fs->seq);
983e93cd67SAl Viro 		tsk->fs = NULL;
99498052bbSAl Viro 		kill = !--fs->users;
100*c28cc364SNick Piggin 		write_seqcount_end(&fs->seq);
1012a4419b5SNick Piggin 		spin_unlock(&fs->lock);
1023e93cd67SAl Viro 		task_unlock(tsk);
103498052bbSAl Viro 		if (kill)
104498052bbSAl Viro 			free_fs_struct(fs);
1053e93cd67SAl Viro 	}
1063e93cd67SAl Viro }
1073e93cd67SAl Viro 
1083e93cd67SAl Viro struct fs_struct *copy_fs_struct(struct fs_struct *old)
1093e93cd67SAl Viro {
1103e93cd67SAl Viro 	struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
1113e93cd67SAl Viro 	/* We don't need to lock fs - think why ;-) */
1123e93cd67SAl Viro 	if (fs) {
113498052bbSAl Viro 		fs->users = 1;
114498052bbSAl Viro 		fs->in_exec = 0;
1152a4419b5SNick Piggin 		spin_lock_init(&fs->lock);
116*c28cc364SNick Piggin 		seqcount_init(&fs->seq);
1173e93cd67SAl Viro 		fs->umask = old->umask;
118f7ad3c6bSMiklos Szeredi 		get_fs_root_and_pwd(old, &fs->root, &fs->pwd);
1193e93cd67SAl Viro 	}
1203e93cd67SAl Viro 	return fs;
1213e93cd67SAl Viro }
1223e93cd67SAl Viro 
1233e93cd67SAl Viro int unshare_fs_struct(void)
1243e93cd67SAl Viro {
125498052bbSAl Viro 	struct fs_struct *fs = current->fs;
126498052bbSAl Viro 	struct fs_struct *new_fs = copy_fs_struct(fs);
127498052bbSAl Viro 	int kill;
128498052bbSAl Viro 
129498052bbSAl Viro 	if (!new_fs)
1303e93cd67SAl Viro 		return -ENOMEM;
131498052bbSAl Viro 
132498052bbSAl Viro 	task_lock(current);
1332a4419b5SNick Piggin 	spin_lock(&fs->lock);
134498052bbSAl Viro 	kill = !--fs->users;
135498052bbSAl Viro 	current->fs = new_fs;
1362a4419b5SNick Piggin 	spin_unlock(&fs->lock);
137498052bbSAl Viro 	task_unlock(current);
138498052bbSAl Viro 
139498052bbSAl Viro 	if (kill)
140498052bbSAl Viro 		free_fs_struct(fs);
141498052bbSAl Viro 
1423e93cd67SAl Viro 	return 0;
1433e93cd67SAl Viro }
1443e93cd67SAl Viro EXPORT_SYMBOL_GPL(unshare_fs_struct);
1453e93cd67SAl Viro 
146ce3b0f8dSAl Viro int current_umask(void)
147ce3b0f8dSAl Viro {
148ce3b0f8dSAl Viro 	return current->fs->umask;
149ce3b0f8dSAl Viro }
150ce3b0f8dSAl Viro EXPORT_SYMBOL(current_umask);
151ce3b0f8dSAl Viro 
1523e93cd67SAl Viro /* to be mentioned only in INIT_TASK */
1533e93cd67SAl Viro struct fs_struct init_fs = {
154498052bbSAl Viro 	.users		= 1,
1552a4419b5SNick Piggin 	.lock		= __SPIN_LOCK_UNLOCKED(init_fs.lock),
156*c28cc364SNick Piggin 	.seq		= SEQCNT_ZERO,
1573e93cd67SAl Viro 	.umask		= 0022,
1583e93cd67SAl Viro };
1593e93cd67SAl Viro 
1603e93cd67SAl Viro void daemonize_fs_struct(void)
1613e93cd67SAl Viro {
162498052bbSAl Viro 	struct fs_struct *fs = current->fs;
1633e93cd67SAl Viro 
164498052bbSAl Viro 	if (fs) {
165498052bbSAl Viro 		int kill;
166498052bbSAl Viro 
167498052bbSAl Viro 		task_lock(current);
168498052bbSAl Viro 
1692a4419b5SNick Piggin 		spin_lock(&init_fs.lock);
170498052bbSAl Viro 		init_fs.users++;
1712a4419b5SNick Piggin 		spin_unlock(&init_fs.lock);
172498052bbSAl Viro 
1732a4419b5SNick Piggin 		spin_lock(&fs->lock);
174498052bbSAl Viro 		current->fs = &init_fs;
175498052bbSAl Viro 		kill = !--fs->users;
1762a4419b5SNick Piggin 		spin_unlock(&fs->lock);
177498052bbSAl Viro 
178498052bbSAl Viro 		task_unlock(current);
179498052bbSAl Viro 		if (kill)
180498052bbSAl Viro 			free_fs_struct(fs);
181498052bbSAl Viro 	}
1823e93cd67SAl Viro }
183