fs/nfsd/nfsfh.c

Source file repositories/reference/linux-study-clean/fs/nfsd/nfsfh.c

File Facts

System
Linux kernel
Corpus path
fs/nfsd/nfsfh.c
Extension
.c
Size
25968 bytes
Lines
963
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (err < 0) {
			dput(parent);
			break;
		}
		dput(tdentry);
		tdentry = parent;
	}
	if (tdentry != exp->ex_path.dentry)
		dprintk("nfsd_acceptable failed at %p %pd\n", tdentry, tdentry);
	rv = (tdentry == exp->ex_path.dentry);
	dput(tdentry);
	return rv;
}

/* 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 dentry *dentry, umode_t requested)
{
	umode_t mode = d_inode(dentry)->i_mode & S_IFMT;

	if (requested == 0) /* the caller doesn't care */
		return nfs_ok;
	if (mode == requested) {
		if (mode == S_IFDIR && !d_can_lookup(dentry)) {
			WARN_ON_ONCE(1);
			return nfserr_notdir;
		}
		return nfs_ok;
	}
	if (mode == S_IFLNK) {
		if (requested == S_IFDIR)
			return nfserr_symlink_not_dir;
		return nfserr_symlink;
	}
	if (requested == S_IFDIR)
		return nfserr_notdir;
	if (mode == S_IFDIR)
		return nfserr_isdir;
	return nfserr_wrong_type;
}

static bool nfsd_originating_port_ok(struct svc_rqst *rqstp,
				     struct svc_cred *cred,
				     struct svc_export *exp)
{
	if (nfsexp_flags(cred, exp) & NFSEXP_INSECURE_PORT)
		return true;
	/* We don't require gss requests to use low ports: */
	if (cred->cr_flavor >= RPC_AUTH_GSS)
		return true;
	return test_bit(RQ_SECURE, &rqstp->rq_flags);
}

static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
					  struct svc_cred *cred,
					  struct svc_export *exp)
{
	/* Check if the request originated from a secure port. */
	if (rqstp && !nfsd_originating_port_ok(rqstp, cred, exp)) {
		if (IS_ENABLED(CONFIG_SUNRPC_DEBUG)) {
			char buf[RPC_MAX_ADDRBUFLEN];

			dprintk("nfsd: request from insecure port %s!\n",
			        svc_print_addr(rqstp, buf, sizeof(buf)));
		}
		return nfserr_perm;
	}

	/* Set user creds for this exportpoint */
	return nfserrno(nfsd_setuser(cred, exp));
}

static inline __be32 check_pseudo_root(struct dentry *dentry,
				       struct svc_export *exp)
{
	if (!(exp->ex_flags & NFSEXP_V4ROOT))
		return nfs_ok;
	/*
	 * We're exposing only the directories and symlinks that have to be
	 * traversed on the way to real exports:
	 */
	if (unlikely(!d_is_dir(dentry) &&
		     !d_is_symlink(dentry)))
		return nfserr_stale;
	/*
	 * A pseudoroot export gives permission to access only one

Annotation

Implementation Notes