// SPDX-License-Identifier: GPL-2.0 /* * NFS server file handle treatment. * * Copyright (C) 1995, 1996 Olaf Kirch <[email protected]> * Portions Copyright (C) 1999 G. Allen Morris III <[email protected]> * Extensive rewrite by Neil Brown <[email protected]> Southern-Spring 1999 * ... and again Southern-Winter 2001 to support export_operations */ #include <linux/exportfs.h> #include <linux/sunrpc/svcauth_gss.h> #include "nfsd.h" #include "vfs.h" #include "auth.h" #include "trace.h" #define NFSDDBG_FACILITY … /* * our acceptability function. * if NOSUBTREECHECK, accept anything * if not, require that we can walk up to exp->ex_dentry * doing some checks on the 'x' bits */ static int nfsd_acceptable(void *expv, struct dentry *dentry) { … } /* Type check. The correct error return for type mismatches does not seem to be * generally agreed upon. SunOS seems to use EISDIR if file isn't S_IFREG; a * comment in the NFSv3 spec says this is incorrect (implementation notes for * the write call). */ static inline __be32 nfsd_mode_check(struct svc_rqst *rqstp, struct dentry *dentry, umode_t requested) { … } static bool nfsd_originating_port_ok(struct svc_rqst *rqstp, int flags) { … } static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp, struct svc_export *exp) { … } static inline __be32 check_pseudo_root(struct svc_rqst *rqstp, struct dentry *dentry, struct svc_export *exp) { … } /* * Use the given filehandle to look up the corresponding export and * dentry. On success, the results are used to set fh_export and * fh_dentry. */ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) { … } /** * fh_verify - filehandle lookup and access checking * @rqstp: pointer to current rpc request * @fhp: filehandle to be verified * @type: expected type of object pointed to by filehandle * @access: type of access needed to object * * Look up a dentry from the on-the-wire filehandle, check the client's * access to the export, and set the current task's credentials. * * Regardless of success or failure of fh_verify(), fh_put() should be * called on @fhp when the caller is finished with the filehandle. * * fh_verify() may be called multiple times on a given filehandle, for * example, when processing an NFSv4 compound. The first call will look * up a dentry using the on-the-wire filehandle. Subsequent calls will * skip the lookup and just perform the other checks and possibly change * the current task's credentials. * * @type specifies the type of object expected using one of the S_IF* * constants defined in include/linux/stat.h. The caller may use zero * to indicate that it doesn't care, or a negative integer to indicate * that it expects something not of the given type. * * @access is formed from the NFSD_MAY_* constants defined in * fs/nfsd/vfs.h. */ __be32 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access) { … } /* * Compose a file handle for an NFS reply. * * Note that when first composed, the dentry may not yet have * an inode. In this case a call to fh_update should be made * before the fh goes out on the wire ... */ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry) { … } static bool is_root_export(struct svc_export *exp) { … } static struct super_block *exp_sb(struct svc_export *exp) { … } static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp) { … } static void set_version_and_fsid_type(struct svc_fh *fhp, struct svc_export *exp, struct svc_fh *ref_fh) { … } __be32 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { … } /* * Update file handle information after changing a dentry. * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create */ __be32 fh_update(struct svc_fh *fhp) { … } /** * fh_fill_pre_attrs - Fill in pre-op attributes * @fhp: file handle to be updated * */ __be32 __must_check fh_fill_pre_attrs(struct svc_fh *fhp) { … } /** * fh_fill_post_attrs - Fill in post-op attributes * @fhp: file handle to be updated * */ __be32 fh_fill_post_attrs(struct svc_fh *fhp) { … } /** * fh_fill_both_attrs - Fill pre-op and post-op attributes * @fhp: file handle to be updated * * This is used when the directory wasn't changed, but wcc attributes * are needed anyway. */ __be32 __must_check fh_fill_both_attrs(struct svc_fh *fhp) { … } /* * Release a file handle. */ void fh_put(struct svc_fh *fhp) { … } /* * Shorthand for dprintk()'s */ char * SVCFH_fmt(struct svc_fh *fhp) { … } enum fsid_source fsid_source(const struct svc_fh *fhp) { … } /* * We could use i_version alone as the change attribute. However, i_version * can go backwards on a regular file after an unclean shutdown. On its own * that doesn't necessarily cause a problem, but if i_version goes backwards * and then is incremented again it could reuse a value that was previously * used before boot, and a client who queried the two values might incorrectly * assume nothing changed. * * By using both ctime and the i_version counter we guarantee that as long as * time doesn't go backwards we never reuse an old value. If the filesystem * advertises STATX_ATTR_CHANGE_MONOTONIC, then this mitigation is not * needed. * * We only need to do this for regular files as well. For directories, we * assume that the new change attr is always logged to stable storage in some * fashion before the results can be seen. */ u64 nfsd4_change_attribute(const struct kstat *stat, const struct inode *inode) { … }