mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Change userspace_init_fs from a declared-but-unused extern struct to a dynamically initialized pointer. Add init_userspace_fs() which is called early in kernel_init() (PID 1) to record PID 1's fs_struct as the canonical userspace filesystem state. Wire up __override_init_fs() and __revert_init_fs() to actually swap current->fs to/from userspace_init_fs. Previously these were no-ops that stored current->fs back to itself. Fix nullfs_userspace_init() to compare against userspace_init_fs instead of &init_fs. When PID 1 unshares its filesystem state, revert userspace_init_fs to init_fs's root (nullfs) so that stale filesystem state is not silently inherited by kworkers and usermodehelpers. At this stage PID 1's fs still points to rootfs (set by init_mount_tree), so userspace_init_fs points to rootfs and scoped_with_init_fs() is functionally equivalent to its previous no-op behavior. Link: https://patch.msgid.link/20260601-work-kthread-nullfs-v4-5-77ee053060e0@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
85 lines
2.0 KiB
C
85 lines
2.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_FS_STRUCT_H
|
|
#define _LINUX_FS_STRUCT_H
|
|
|
|
#include <linux/sched.h>
|
|
#include <linux/path.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/seqlock.h>
|
|
#include <linux/vfsdebug.h>
|
|
|
|
struct fs_struct {
|
|
int users;
|
|
seqlock_t seq;
|
|
int umask;
|
|
int in_exec;
|
|
struct path root, pwd;
|
|
} __randomize_layout;
|
|
|
|
extern struct kmem_cache *fs_cachep;
|
|
extern struct fs_struct *userspace_init_fs;
|
|
|
|
extern void exit_fs(struct task_struct *);
|
|
extern void set_fs_root(struct fs_struct *, const struct path *);
|
|
extern void set_fs_pwd(struct fs_struct *, const struct path *);
|
|
extern struct fs_struct *copy_fs_struct(struct fs_struct *);
|
|
extern void free_fs_struct(struct fs_struct *);
|
|
extern int unshare_fs_struct(void);
|
|
|
|
static inline void get_fs_root(struct fs_struct *fs, struct path *root)
|
|
{
|
|
read_seqlock_excl(&fs->seq);
|
|
*root = fs->root;
|
|
path_get(root);
|
|
read_sequnlock_excl(&fs->seq);
|
|
}
|
|
|
|
static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd)
|
|
{
|
|
read_seqlock_excl(&fs->seq);
|
|
*pwd = fs->pwd;
|
|
path_get(pwd);
|
|
read_sequnlock_excl(&fs->seq);
|
|
}
|
|
|
|
struct fs_struct *switch_fs_struct(struct fs_struct *new_fs);
|
|
|
|
extern bool current_chrooted(void);
|
|
|
|
static inline int current_umask(void)
|
|
{
|
|
return current->fs->umask;
|
|
}
|
|
|
|
/*
|
|
* Temporarily use userspace_init_fs for path resolution in kthreads.
|
|
* Callers should use scoped_with_init_fs() which automatically
|
|
* restores the original fs_struct at scope exit.
|
|
*/
|
|
static inline struct fs_struct *__override_init_fs(void)
|
|
{
|
|
struct fs_struct *old_fs;
|
|
|
|
old_fs = current->fs;
|
|
WRITE_ONCE(current->fs, userspace_init_fs);
|
|
return old_fs;
|
|
}
|
|
|
|
static inline void __revert_init_fs(struct fs_struct *old_fs)
|
|
{
|
|
VFS_WARN_ON_ONCE(current->fs != userspace_init_fs);
|
|
WRITE_ONCE(current->fs, old_fs);
|
|
}
|
|
|
|
DEFINE_CLASS(__override_init_fs,
|
|
struct fs_struct *,
|
|
__revert_init_fs(_T),
|
|
__override_init_fs(), void)
|
|
|
|
#define scoped_with_init_fs() \
|
|
scoped_class(__override_init_fs, __UNIQUE_ID(label))
|
|
|
|
void __init init_userspace_fs(void);
|
|
|
|
#endif /* _LINUX_FS_STRUCT_H */
|