File Index
Files and directories
Sign in
FILE

fs_struct.c

File preview with syntax highlighting.

linux-6.19.14/fs/fs_struct.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2#include <linux/export.h>
  3#include <linux/sched/signal.h>
  4#include <linux/sched/task.h>
  5#include <linux/fs.h>
  6#include <linux/path.h>
  7#include <linux/slab.h>
  8#include <linux/fs_struct.h>
  9#include <linux/init_task.h>
 10#include "internal.h"
 11
 12/*
 13 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
 14 * It can block.
 15 */
 16void set_fs_root(struct fs_struct *fs, const struct path *path)
 17{
 18	struct path old_root;
 19
 20	path_get(path);
 21	write_seqlock(&fs->seq);
 22	old_root = fs->root;
 23	fs->root = *path;
 24	write_sequnlock(&fs->seq);
 25	if (old_root.dentry)
 26		path_put(&old_root);
 27}
 28
 29/*
 30 * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
 31 * It can block.
 32 */
 33void set_fs_pwd(struct fs_struct *fs, const struct path *path)
 34{
 35	struct path old_pwd;
 36
 37	path_get(path);
 38	write_seqlock(&fs->seq);
 39	old_pwd = fs->pwd;
 40	fs->pwd = *path;
 41	write_sequnlock(&fs->seq);
 42
 43	if (old_pwd.dentry)
 44		path_put(&old_pwd);
 45}
 46
 47static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
 48{
 49	if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
 50		return 0;
 51	*p = *new;
 52	return 1;
 53}
 54
 55void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
 56{
 57	struct task_struct *g, *p;
 58	struct fs_struct *fs;
 59	int count = 0;
 60
 61	read_lock(&tasklist_lock);
 62	for_each_process_thread(g, p) {
 63		task_lock(p);
 64		fs = p->fs;
 65		if (fs) {
 66			int hits = 0;
 67			write_seqlock(&fs->seq);
 68			hits += replace_path(&fs->root, old_root, new_root);
 69			hits += replace_path(&fs->pwd, old_root, new_root);
 70			while (hits--) {
 71				count++;
 72				path_get(new_root);
 73			}
 74			write_sequnlock(&fs->seq);
 75		}
 76		task_unlock(p);
 77	}
 78	read_unlock(&tasklist_lock);
 79	while (count--)
 80		path_put(old_root);
 81}
 82
 83void free_fs_struct(struct fs_struct *fs)
 84{
 85	path_put(&fs->root);
 86	path_put(&fs->pwd);
 87	kmem_cache_free(fs_cachep, fs);
 88}
 89
 90void exit_fs(struct task_struct *tsk)
 91{
 92	struct fs_struct *fs = tsk->fs;
 93
 94	if (fs) {
 95		int kill;
 96		task_lock(tsk);
 97		read_seqlock_excl(&fs->seq);
 98		tsk->fs = NULL;
 99		kill = !--fs->users;
100		read_sequnlock_excl(&fs->seq);
101		task_unlock(tsk);
102		if (kill)
103			free_fs_struct(fs);
104	}
105}
106
107struct fs_struct *copy_fs_struct(struct fs_struct *old)
108{
109	struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL);
110	/* We don't need to lock fs - think why ;-) */
111	if (fs) {
112		fs->users = 1;
113		fs->in_exec = 0;
114		seqlock_init(&fs->seq);
115		fs->umask = old->umask;
116
117		read_seqlock_excl(&old->seq);
118		fs->root = old->root;
119		path_get(&fs->root);
120		fs->pwd = old->pwd;
121		path_get(&fs->pwd);
122		read_sequnlock_excl(&old->seq);
123	}
124	return fs;
125}
126
127int unshare_fs_struct(void)
128{
129	struct fs_struct *fs = current->fs;
130	struct fs_struct *new_fs = copy_fs_struct(fs);
131	int kill;
132
133	if (!new_fs)
134		return -ENOMEM;
135
136	task_lock(current);
137	read_seqlock_excl(&fs->seq);
138	kill = !--fs->users;
139	current->fs = new_fs;
140	read_sequnlock_excl(&fs->seq);
141	task_unlock(current);
142
143	if (kill)
144		free_fs_struct(fs);
145
146	return 0;
147}
148EXPORT_SYMBOL_GPL(unshare_fs_struct);
149
150/* to be mentioned only in INIT_TASK */
151struct fs_struct init_fs = {
152	.users		= 1,
153	.seq		= __SEQLOCK_UNLOCKED(init_fs.seq),
154	.umask		= 0022,
155};
~/ Read-only file preview.