1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*4882a593Smuzhiyun /* Filesystem superblock creation and reconfiguration context. 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. 5*4882a593Smuzhiyun * Written by David Howells (dhowells@redhat.com) 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun #ifndef _LINUX_FS_CONTEXT_H 9*4882a593Smuzhiyun #define _LINUX_FS_CONTEXT_H 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #include <linux/kernel.h> 12*4882a593Smuzhiyun #include <linux/refcount.h> 13*4882a593Smuzhiyun #include <linux/errno.h> 14*4882a593Smuzhiyun #include <linux/security.h> 15*4882a593Smuzhiyun #include <linux/mutex.h> 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun struct cred; 18*4882a593Smuzhiyun struct dentry; 19*4882a593Smuzhiyun struct file_operations; 20*4882a593Smuzhiyun struct file_system_type; 21*4882a593Smuzhiyun struct mnt_namespace; 22*4882a593Smuzhiyun struct net; 23*4882a593Smuzhiyun struct pid_namespace; 24*4882a593Smuzhiyun struct super_block; 25*4882a593Smuzhiyun struct user_namespace; 26*4882a593Smuzhiyun struct vfsmount; 27*4882a593Smuzhiyun struct path; 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun enum fs_context_purpose { 30*4882a593Smuzhiyun FS_CONTEXT_FOR_MOUNT, /* New superblock for explicit mount */ 31*4882a593Smuzhiyun FS_CONTEXT_FOR_SUBMOUNT, /* New superblock for automatic submount */ 32*4882a593Smuzhiyun FS_CONTEXT_FOR_RECONFIGURE, /* Superblock reconfiguration (remount) */ 33*4882a593Smuzhiyun }; 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun /* 36*4882a593Smuzhiyun * Userspace usage phase for fsopen/fspick. 37*4882a593Smuzhiyun */ 38*4882a593Smuzhiyun enum fs_context_phase { 39*4882a593Smuzhiyun FS_CONTEXT_CREATE_PARAMS, /* Loading params for sb creation */ 40*4882a593Smuzhiyun FS_CONTEXT_CREATING, /* A superblock is being created */ 41*4882a593Smuzhiyun FS_CONTEXT_AWAITING_MOUNT, /* Superblock created, awaiting fsmount() */ 42*4882a593Smuzhiyun FS_CONTEXT_AWAITING_RECONF, /* Awaiting initialisation for reconfiguration */ 43*4882a593Smuzhiyun FS_CONTEXT_RECONF_PARAMS, /* Loading params for reconfiguration */ 44*4882a593Smuzhiyun FS_CONTEXT_RECONFIGURING, /* Reconfiguring the superblock */ 45*4882a593Smuzhiyun FS_CONTEXT_FAILED, /* Failed to correctly transition a context */ 46*4882a593Smuzhiyun }; 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun /* 49*4882a593Smuzhiyun * Type of parameter value. 50*4882a593Smuzhiyun */ 51*4882a593Smuzhiyun enum fs_value_type { 52*4882a593Smuzhiyun fs_value_is_undefined, 53*4882a593Smuzhiyun fs_value_is_flag, /* Value not given a value */ 54*4882a593Smuzhiyun fs_value_is_string, /* Value is a string */ 55*4882a593Smuzhiyun fs_value_is_blob, /* Value is a binary blob */ 56*4882a593Smuzhiyun fs_value_is_filename, /* Value is a filename* + dirfd */ 57*4882a593Smuzhiyun fs_value_is_file, /* Value is a file* */ 58*4882a593Smuzhiyun }; 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun /* 61*4882a593Smuzhiyun * Configuration parameter. 62*4882a593Smuzhiyun */ 63*4882a593Smuzhiyun struct fs_parameter { 64*4882a593Smuzhiyun const char *key; /* Parameter name */ 65*4882a593Smuzhiyun enum fs_value_type type:8; /* The type of value here */ 66*4882a593Smuzhiyun union { 67*4882a593Smuzhiyun char *string; 68*4882a593Smuzhiyun void *blob; 69*4882a593Smuzhiyun struct filename *name; 70*4882a593Smuzhiyun struct file *file; 71*4882a593Smuzhiyun }; 72*4882a593Smuzhiyun size_t size; 73*4882a593Smuzhiyun int dirfd; 74*4882a593Smuzhiyun }; 75*4882a593Smuzhiyun 76*4882a593Smuzhiyun struct p_log { 77*4882a593Smuzhiyun const char *prefix; 78*4882a593Smuzhiyun struct fc_log *log; 79*4882a593Smuzhiyun }; 80*4882a593Smuzhiyun 81*4882a593Smuzhiyun /* 82*4882a593Smuzhiyun * Filesystem context for holding the parameters used in the creation or 83*4882a593Smuzhiyun * reconfiguration of a superblock. 84*4882a593Smuzhiyun * 85*4882a593Smuzhiyun * Superblock creation fills in ->root whereas reconfiguration begins with this 86*4882a593Smuzhiyun * already set. 87*4882a593Smuzhiyun * 88*4882a593Smuzhiyun * See Documentation/filesystems/mount_api.rst 89*4882a593Smuzhiyun */ 90*4882a593Smuzhiyun struct fs_context { 91*4882a593Smuzhiyun const struct fs_context_operations *ops; 92*4882a593Smuzhiyun struct mutex uapi_mutex; /* Userspace access mutex */ 93*4882a593Smuzhiyun struct file_system_type *fs_type; 94*4882a593Smuzhiyun void *fs_private; /* The filesystem's context */ 95*4882a593Smuzhiyun void *sget_key; 96*4882a593Smuzhiyun struct dentry *root; /* The root and superblock */ 97*4882a593Smuzhiyun struct user_namespace *user_ns; /* The user namespace for this mount */ 98*4882a593Smuzhiyun struct net *net_ns; /* The network namespace for this mount */ 99*4882a593Smuzhiyun const struct cred *cred; /* The mounter's credentials */ 100*4882a593Smuzhiyun struct p_log log; /* Logging buffer */ 101*4882a593Smuzhiyun const char *source; /* The source name (eg. dev path) */ 102*4882a593Smuzhiyun void *security; /* Linux S&M options */ 103*4882a593Smuzhiyun void *s_fs_info; /* Proposed s_fs_info */ 104*4882a593Smuzhiyun unsigned int sb_flags; /* Proposed superblock flags (SB_*) */ 105*4882a593Smuzhiyun unsigned int sb_flags_mask; /* Superblock flags that were changed */ 106*4882a593Smuzhiyun unsigned int s_iflags; /* OR'd with sb->s_iflags */ 107*4882a593Smuzhiyun unsigned int lsm_flags; /* Information flags from the fs to the LSM */ 108*4882a593Smuzhiyun enum fs_context_purpose purpose:8; 109*4882a593Smuzhiyun enum fs_context_phase phase:8; /* The phase the context is in */ 110*4882a593Smuzhiyun bool need_free:1; /* Need to call ops->free() */ 111*4882a593Smuzhiyun bool global:1; /* Goes into &init_user_ns */ 112*4882a593Smuzhiyun bool oldapi:1; /* Coming from mount(2) */ 113*4882a593Smuzhiyun }; 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun struct fs_context_operations { 116*4882a593Smuzhiyun void (*free)(struct fs_context *fc); 117*4882a593Smuzhiyun int (*dup)(struct fs_context *fc, struct fs_context *src_fc); 118*4882a593Smuzhiyun int (*parse_param)(struct fs_context *fc, struct fs_parameter *param); 119*4882a593Smuzhiyun int (*parse_monolithic)(struct fs_context *fc, void *data); 120*4882a593Smuzhiyun int (*get_tree)(struct fs_context *fc); 121*4882a593Smuzhiyun int (*reconfigure)(struct fs_context *fc); 122*4882a593Smuzhiyun }; 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun /* 125*4882a593Smuzhiyun * fs_context manipulation functions. 126*4882a593Smuzhiyun */ 127*4882a593Smuzhiyun extern struct fs_context *fs_context_for_mount(struct file_system_type *fs_type, 128*4882a593Smuzhiyun unsigned int sb_flags); 129*4882a593Smuzhiyun extern struct fs_context *fs_context_for_reconfigure(struct dentry *dentry, 130*4882a593Smuzhiyun unsigned int sb_flags, 131*4882a593Smuzhiyun unsigned int sb_flags_mask); 132*4882a593Smuzhiyun extern struct fs_context *fs_context_for_submount(struct file_system_type *fs_type, 133*4882a593Smuzhiyun struct dentry *reference); 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun extern struct fs_context *vfs_dup_fs_context(struct fs_context *fc); 136*4882a593Smuzhiyun extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param); 137*4882a593Smuzhiyun extern int vfs_parse_fs_string(struct fs_context *fc, const char *key, 138*4882a593Smuzhiyun const char *value, size_t v_size); 139*4882a593Smuzhiyun extern int generic_parse_monolithic(struct fs_context *fc, void *data); 140*4882a593Smuzhiyun extern int vfs_get_tree(struct fs_context *fc); 141*4882a593Smuzhiyun extern void put_fs_context(struct fs_context *fc); 142*4882a593Smuzhiyun extern void fc_drop_locked(struct fs_context *fc); 143*4882a593Smuzhiyun int reconfigure_single(struct super_block *s, 144*4882a593Smuzhiyun int flags, void *data); 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun /* 147*4882a593Smuzhiyun * sget() wrappers to be called from the ->get_tree() op. 148*4882a593Smuzhiyun */ 149*4882a593Smuzhiyun enum vfs_get_super_keying { 150*4882a593Smuzhiyun vfs_get_single_super, /* Only one such superblock may exist */ 151*4882a593Smuzhiyun vfs_get_single_reconf_super, /* As above, but reconfigure if it exists */ 152*4882a593Smuzhiyun vfs_get_keyed_super, /* Superblocks with different s_fs_info keys may exist */ 153*4882a593Smuzhiyun vfs_get_independent_super, /* Multiple independent superblocks may exist */ 154*4882a593Smuzhiyun }; 155*4882a593Smuzhiyun extern int vfs_get_super(struct fs_context *fc, 156*4882a593Smuzhiyun enum vfs_get_super_keying keying, 157*4882a593Smuzhiyun int (*fill_super)(struct super_block *sb, 158*4882a593Smuzhiyun struct fs_context *fc)); 159*4882a593Smuzhiyun 160*4882a593Smuzhiyun extern int get_tree_nodev(struct fs_context *fc, 161*4882a593Smuzhiyun int (*fill_super)(struct super_block *sb, 162*4882a593Smuzhiyun struct fs_context *fc)); 163*4882a593Smuzhiyun extern int get_tree_single(struct fs_context *fc, 164*4882a593Smuzhiyun int (*fill_super)(struct super_block *sb, 165*4882a593Smuzhiyun struct fs_context *fc)); 166*4882a593Smuzhiyun extern int get_tree_single_reconf(struct fs_context *fc, 167*4882a593Smuzhiyun int (*fill_super)(struct super_block *sb, 168*4882a593Smuzhiyun struct fs_context *fc)); 169*4882a593Smuzhiyun extern int get_tree_keyed(struct fs_context *fc, 170*4882a593Smuzhiyun int (*fill_super)(struct super_block *sb, 171*4882a593Smuzhiyun struct fs_context *fc), 172*4882a593Smuzhiyun void *key); 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun extern int get_tree_bdev(struct fs_context *fc, 175*4882a593Smuzhiyun int (*fill_super)(struct super_block *sb, 176*4882a593Smuzhiyun struct fs_context *fc)); 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun extern const struct file_operations fscontext_fops; 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun /* 181*4882a593Smuzhiyun * Mount error, warning and informational message logging. This structure is 182*4882a593Smuzhiyun * shareable between a mount and a subordinate mount. 183*4882a593Smuzhiyun */ 184*4882a593Smuzhiyun struct fc_log { 185*4882a593Smuzhiyun refcount_t usage; 186*4882a593Smuzhiyun u8 head; /* Insertion index in buffer[] */ 187*4882a593Smuzhiyun u8 tail; /* Removal index in buffer[] */ 188*4882a593Smuzhiyun u8 need_free; /* Mask of kfree'able items in buffer[] */ 189*4882a593Smuzhiyun struct module *owner; /* Owner module for strings that don't then need freeing */ 190*4882a593Smuzhiyun char *buffer[8]; 191*4882a593Smuzhiyun }; 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun extern __attribute__((format(printf, 4, 5))) 194*4882a593Smuzhiyun void logfc(struct fc_log *log, const char *prefix, char level, const char *fmt, ...); 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun #define __logfc(fc, l, fmt, ...) logfc((fc)->log.log, NULL, \ 197*4882a593Smuzhiyun l, fmt, ## __VA_ARGS__) 198*4882a593Smuzhiyun #define __plog(p, l, fmt, ...) logfc((p)->log, (p)->prefix, \ 199*4882a593Smuzhiyun l, fmt, ## __VA_ARGS__) 200*4882a593Smuzhiyun /** 201*4882a593Smuzhiyun * infof - Store supplementary informational message 202*4882a593Smuzhiyun * @fc: The context in which to log the informational message 203*4882a593Smuzhiyun * @fmt: The format string 204*4882a593Smuzhiyun * 205*4882a593Smuzhiyun * Store the supplementary informational message for the process if the process 206*4882a593Smuzhiyun * has enabled the facility. 207*4882a593Smuzhiyun */ 208*4882a593Smuzhiyun #define infof(fc, fmt, ...) __logfc(fc, 'i', fmt, ## __VA_ARGS__) 209*4882a593Smuzhiyun #define info_plog(p, fmt, ...) __plog(p, 'i', fmt, ## __VA_ARGS__) 210*4882a593Smuzhiyun #define infofc(p, fmt, ...) __plog((&(fc)->log), 'i', fmt, ## __VA_ARGS__) 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun /** 213*4882a593Smuzhiyun * warnf - Store supplementary warning message 214*4882a593Smuzhiyun * @fc: The context in which to log the error message 215*4882a593Smuzhiyun * @fmt: The format string 216*4882a593Smuzhiyun * 217*4882a593Smuzhiyun * Store the supplementary warning message for the process if the process has 218*4882a593Smuzhiyun * enabled the facility. 219*4882a593Smuzhiyun */ 220*4882a593Smuzhiyun #define warnf(fc, fmt, ...) __logfc(fc, 'w', fmt, ## __VA_ARGS__) 221*4882a593Smuzhiyun #define warn_plog(p, fmt, ...) __plog(p, 'w', fmt, ## __VA_ARGS__) 222*4882a593Smuzhiyun #define warnfc(fc, fmt, ...) __plog((&(fc)->log), 'w', fmt, ## __VA_ARGS__) 223*4882a593Smuzhiyun 224*4882a593Smuzhiyun /** 225*4882a593Smuzhiyun * errorf - Store supplementary error message 226*4882a593Smuzhiyun * @fc: The context in which to log the error message 227*4882a593Smuzhiyun * @fmt: The format string 228*4882a593Smuzhiyun * 229*4882a593Smuzhiyun * Store the supplementary error message for the process if the process has 230*4882a593Smuzhiyun * enabled the facility. 231*4882a593Smuzhiyun */ 232*4882a593Smuzhiyun #define errorf(fc, fmt, ...) __logfc(fc, 'e', fmt, ## __VA_ARGS__) 233*4882a593Smuzhiyun #define error_plog(p, fmt, ...) __plog(p, 'e', fmt, ## __VA_ARGS__) 234*4882a593Smuzhiyun #define errorfc(fc, fmt, ...) __plog((&(fc)->log), 'e', fmt, ## __VA_ARGS__) 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun /** 237*4882a593Smuzhiyun * invalf - Store supplementary invalid argument error message 238*4882a593Smuzhiyun * @fc: The context in which to log the error message 239*4882a593Smuzhiyun * @fmt: The format string 240*4882a593Smuzhiyun * 241*4882a593Smuzhiyun * Store the supplementary error message for the process if the process has 242*4882a593Smuzhiyun * enabled the facility and return -EINVAL. 243*4882a593Smuzhiyun */ 244*4882a593Smuzhiyun #define invalf(fc, fmt, ...) (errorf(fc, fmt, ## __VA_ARGS__), -EINVAL) 245*4882a593Smuzhiyun #define inval_plog(p, fmt, ...) (error_plog(p, fmt, ## __VA_ARGS__), -EINVAL) 246*4882a593Smuzhiyun #define invalfc(fc, fmt, ...) (errorfc(fc, fmt, ## __VA_ARGS__), -EINVAL) 247*4882a593Smuzhiyun 248*4882a593Smuzhiyun #endif /* _LINUX_FS_CONTEXT_H */ 249