/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_FS_STRUCT_H #define _LINUX_FS_STRUCT_H #include #include #include #include #include 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 */