xref: /linux/fs/fs_struct.c (revision 2a4419b5b2a77f3f4537c14f7ad7df95770655dd)
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 
16*2a4419b5SNick Piggin 	spin_lock(&fs->lock);
173e93cd67SAl Viro 	old_root = fs->root;
183e93cd67SAl Viro 	fs->root = *path;
193e93cd67SAl Viro 	path_get(path);
20*2a4419b5SNick Piggin 	spin_unlock(&fs->lock);
213e93cd67SAl Viro 	if (old_root.dentry)
223e93cd67SAl Viro 		path_put(&old_root);
233e93cd67SAl Viro }
243e93cd67SAl Viro 
253e93cd67SAl Viro /*
263e93cd67SAl Viro  * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
273e93cd67SAl Viro  * It can block.
283e93cd67SAl Viro  */
293e93cd67SAl Viro void set_fs_pwd(struct fs_struct *fs, struct path *path)
303e93cd67SAl Viro {
313e93cd67SAl Viro 	struct path old_pwd;
323e93cd67SAl Viro 
33*2a4419b5SNick Piggin 	spin_lock(&fs->lock);
343e93cd67SAl Viro 	old_pwd = fs->pwd;
353e93cd67SAl Viro 	fs->pwd = *path;
363e93cd67SAl Viro 	path_get(path);
37*2a4419b5SNick Piggin 	spin_unlock(&fs->lock);
383e93cd67SAl Viro 
393e93cd67SAl Viro 	if (old_pwd.dentry)
403e93cd67SAl Viro 		path_put(&old_pwd);
413e93cd67SAl Viro }
423e93cd67SAl Viro 
433e93cd67SAl Viro void chroot_fs_refs(struct path *old_root, struct path *new_root)
443e93cd67SAl Viro {
453e93cd67SAl Viro 	struct task_struct *g, *p;
463e93cd67SAl Viro 	struct fs_struct *fs;
473e93cd67SAl Viro 	int count = 0;
483e93cd67SAl Viro 
493e93cd67SAl Viro 	read_lock(&tasklist_lock);
503e93cd67SAl Viro 	do_each_thread(g, p) {
513e93cd67SAl Viro 		task_lock(p);
523e93cd67SAl Viro 		fs = p->fs;
533e93cd67SAl Viro 		if (fs) {
54*2a4419b5SNick Piggin 			spin_lock(&fs->lock);
553e93cd67SAl Viro 			if (fs->root.dentry == old_root->dentry
563e93cd67SAl Viro 			    && fs->root.mnt == old_root->mnt) {
573e93cd67SAl Viro 				path_get(new_root);
583e93cd67SAl Viro 				fs->root = *new_root;
593e93cd67SAl Viro 				count++;
603e93cd67SAl Viro 			}
613e93cd67SAl Viro 			if (fs->pwd.dentry == old_root->dentry
623e93cd67SAl Viro 			    && fs->pwd.mnt == old_root->mnt) {
633e93cd67SAl Viro 				path_get(new_root);
643e93cd67SAl Viro 				fs->pwd = *new_root;
653e93cd67SAl Viro 				count++;
663e93cd67SAl Viro 			}
67*2a4419b5SNick Piggin 			spin_unlock(&fs->lock);
683e93cd67SAl Viro 		}
693e93cd67SAl Viro 		task_unlock(p);
703e93cd67SAl Viro 	} while_each_thread(g, p);
713e93cd67SAl Viro 	read_unlock(&tasklist_lock);
723e93cd67SAl Viro 	while (count--)
733e93cd67SAl Viro 		path_put(old_root);
743e93cd67SAl Viro }
753e93cd67SAl Viro 
76498052bbSAl Viro void free_fs_struct(struct fs_struct *fs)
773e93cd67SAl Viro {
783e93cd67SAl Viro 	path_put(&fs->root);
793e93cd67SAl Viro 	path_put(&fs->pwd);
803e93cd67SAl Viro 	kmem_cache_free(fs_cachep, fs);
813e93cd67SAl Viro }
823e93cd67SAl Viro 
833e93cd67SAl Viro void exit_fs(struct task_struct *tsk)
843e93cd67SAl Viro {
853e93cd67SAl Viro 	struct fs_struct *fs = tsk->fs;
863e93cd67SAl Viro 
873e93cd67SAl Viro 	if (fs) {
88498052bbSAl Viro 		int kill;
893e93cd67SAl Viro 		task_lock(tsk);
90*2a4419b5SNick Piggin 		spin_lock(&fs->lock);
913e93cd67SAl Viro 		tsk->fs = NULL;
92498052bbSAl Viro 		kill = !--fs->users;
93*2a4419b5SNick Piggin 		spin_unlock(&fs->lock);
943e93cd67SAl Viro 		task_unlock(tsk);
95498052bbSAl Viro 		if (kill)
96498052bbSAl Viro 			free_fs_struct(fs);
973e93cd67SAl Viro 	}
983e93cd67SAl Viro }
993e93cd67SAl Viro 
1003e93cd67SAl Viro struct fs_struct *copy_fs_struct(struct fs_struct *old)
1013e93cd67SAl Viro {
1023e93cd67SAl Viro 	struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
1033e93cd67SAl Viro 	/* We don't need to lock fs - think why ;-) */
1043e93cd67SAl Viro 	if (fs) {
105498052bbSAl Viro 		fs->users = 1;
106498052bbSAl Viro 		fs->in_exec = 0;
107*2a4419b5SNick Piggin 		spin_lock_init(&fs->lock);
1083e93cd67SAl Viro 		fs->umask = old->umask;
109f7ad3c6bSMiklos Szeredi 		get_fs_root_and_pwd(old, &fs->root, &fs->pwd);
1103e93cd67SAl Viro 	}
1113e93cd67SAl Viro 	return fs;
1123e93cd67SAl Viro }
1133e93cd67SAl Viro 
1143e93cd67SAl Viro int unshare_fs_struct(void)
1153e93cd67SAl Viro {
116498052bbSAl Viro 	struct fs_struct *fs = current->fs;
117498052bbSAl Viro 	struct fs_struct *new_fs = copy_fs_struct(fs);
118498052bbSAl Viro 	int kill;
119498052bbSAl Viro 
120498052bbSAl Viro 	if (!new_fs)
1213e93cd67SAl Viro 		return -ENOMEM;
122498052bbSAl Viro 
123498052bbSAl Viro 	task_lock(current);
124*2a4419b5SNick Piggin 	spin_lock(&fs->lock);
125498052bbSAl Viro 	kill = !--fs->users;
126498052bbSAl Viro 	current->fs = new_fs;
127*2a4419b5SNick Piggin 	spin_unlock(&fs->lock);
128498052bbSAl Viro 	task_unlock(current);
129498052bbSAl Viro 
130498052bbSAl Viro 	if (kill)
131498052bbSAl Viro 		free_fs_struct(fs);
132498052bbSAl Viro 
1333e93cd67SAl Viro 	return 0;
1343e93cd67SAl Viro }
1353e93cd67SAl Viro EXPORT_SYMBOL_GPL(unshare_fs_struct);
1363e93cd67SAl Viro 
137ce3b0f8dSAl Viro int current_umask(void)
138ce3b0f8dSAl Viro {
139ce3b0f8dSAl Viro 	return current->fs->umask;
140ce3b0f8dSAl Viro }
141ce3b0f8dSAl Viro EXPORT_SYMBOL(current_umask);
142ce3b0f8dSAl Viro 
1433e93cd67SAl Viro /* to be mentioned only in INIT_TASK */
1443e93cd67SAl Viro struct fs_struct init_fs = {
145498052bbSAl Viro 	.users		= 1,
146*2a4419b5SNick Piggin 	.lock		= __SPIN_LOCK_UNLOCKED(init_fs.lock),
1473e93cd67SAl Viro 	.umask		= 0022,
1483e93cd67SAl Viro };
1493e93cd67SAl Viro 
1503e93cd67SAl Viro void daemonize_fs_struct(void)
1513e93cd67SAl Viro {
152498052bbSAl Viro 	struct fs_struct *fs = current->fs;
1533e93cd67SAl Viro 
154498052bbSAl Viro 	if (fs) {
155498052bbSAl Viro 		int kill;
156498052bbSAl Viro 
157498052bbSAl Viro 		task_lock(current);
158498052bbSAl Viro 
159*2a4419b5SNick Piggin 		spin_lock(&init_fs.lock);
160498052bbSAl Viro 		init_fs.users++;
161*2a4419b5SNick Piggin 		spin_unlock(&init_fs.lock);
162498052bbSAl Viro 
163*2a4419b5SNick Piggin 		spin_lock(&fs->lock);
164498052bbSAl Viro 		current->fs = &init_fs;
165498052bbSAl Viro 		kill = !--fs->users;
166*2a4419b5SNick Piggin 		spin_unlock(&fs->lock);
167498052bbSAl Viro 
168498052bbSAl Viro 		task_unlock(current);
169498052bbSAl Viro 		if (kill)
170498052bbSAl Viro 			free_fs_struct(fs);
171498052bbSAl Viro 	}
1723e93cd67SAl Viro }
173