Commit 860448cf authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-4.1' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:
 "A quiet cycle this time; this is basically entirely bugfixes.

  The few that aren't cc'd to stable are cleanup or seemed unlikely to
  affect anyone much"

* 'for-4.1' of git://linux-nfs.org/~bfields/linux:
  uapi: Remove kernel internal declaration
  nfsd: fix nsfd startup race triggering BUG_ON
  nfsd: eliminate NFSD_DEBUG
  nfsd4: fix READ permission checking
  nfsd4: disallow SEEK with special stateids
  nfsd4: disallow ALLOCATE with special stateids
  nfsd: add NFSEXP_PNFS to the exflags array
  nfsd: Remove duplicate macro define for max sec label length
  nfsd: allow setting acls with unenforceable DENYs
  nfsd: NFSD_FAULT_INJECTION depends on DEBUG_FS
  nfsd: remove unused status arg to nfsd4_cleanup_open_state
  nfsd: remove bogus setting of status in nfsd4_process_open2
  NFSD: Use correct reply size calculating function
  NFSD: Using path_equal() for checking two paths
parents ba0e4ae8 bff17523
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@
static struct hlist_head	nlm_files[FILE_NRHASH];
static DEFINE_MUTEX(nlm_file_mutex);

#ifdef NFSD_DEBUG
#ifdef CONFIG_SUNRPC_DEBUG
static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
{
	u32 *fhp = (u32*)f->data;
+1 −1
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ config NFSD_V4_SECURITY_LABEL

config NFSD_FAULT_INJECTION
	bool "NFS server manual fault injection"
	depends on NFSD_V4 && DEBUG_KERNEL
	depends on NFSD_V4 && DEBUG_KERNEL && DEBUG_FS
	help
	  This option enables support for manually injecting faults
	  into the NFS server.  This is intended to be used for
+2 −2
Original line number Diff line number Diff line
@@ -691,8 +691,7 @@ static int svc_export_match(struct cache_head *a, struct cache_head *b)
	struct svc_export *orig = container_of(a, struct svc_export, h);
	struct svc_export *new = container_of(b, struct svc_export, h);
	return orig->ex_client == new->ex_client &&
		orig->ex_path.dentry == new->ex_path.dentry &&
		orig->ex_path.mnt == new->ex_path.mnt;
		path_equal(&orig->ex_path, &new->ex_path);
}

static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
@@ -1159,6 +1158,7 @@ static struct flags {
	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
	{ NFSEXP_V4ROOT, {"v4root", ""}},
	{ NFSEXP_PNFS, {"pnfs", ""}},
	{ 0, {"", ""}}
};

+1 −49
Original line number Diff line number Diff line
@@ -499,43 +499,13 @@ static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_s
	state->mask.allow |= astate->allow;
}

/*
 * Certain bits (SYNCHRONIZE, DELETE, WRITE_OWNER, READ/WRITE_NAMED_ATTRS,
 * READ_ATTRIBUTES, READ_ACL) are currently unenforceable and don't translate
 * to traditional read/write/execute permissions.
 *
 * It's problematic to reject acls that use certain mode bits, because it
 * places the burden on users to learn the rules about which bits one
 * particular server sets, without giving the user a lot of help--we return an
 * error that could mean any number of different things.  To make matters
 * worse, the problematic bits might be introduced by some application that's
 * automatically mapping from some other acl model.
 *
 * So wherever possible we accept anything, possibly erring on the side of
 * denying more permissions than necessary.
 *
 * However we do reject *explicit* DENY's of a few bits representing
 * permissions we could never deny:
 */

static inline int check_deny(u32 mask, int isowner)
{
	if (mask & (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL))
		return -EINVAL;
	if (!isowner)
		return 0;
	if (mask & (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL))
		return -EINVAL;
	return 0;
}

static struct posix_acl *
posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
{
	struct posix_acl_entry *pace;
	struct posix_acl *pacl;
	int nace;
	int i, error = 0;
	int i;

	/*
	 * ACLs with no ACEs are treated differently in the inheritable
@@ -560,17 +530,11 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)

	pace = pacl->a_entries;
	pace->e_tag = ACL_USER_OBJ;
	error = check_deny(state->owner.deny, 1);
	if (error)
		goto out_err;
	low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);

	for (i=0; i < state->users->n; i++) {
		pace++;
		pace->e_tag = ACL_USER;
		error = check_deny(state->users->aces[i].perms.deny, 0);
		if (error)
			goto out_err;
		low_mode_from_nfs4(state->users->aces[i].perms.allow,
					&pace->e_perm, flags);
		pace->e_uid = state->users->aces[i].uid;
@@ -579,18 +543,12 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)

	pace++;
	pace->e_tag = ACL_GROUP_OBJ;
	error = check_deny(state->group.deny, 0);
	if (error)
		goto out_err;
	low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
	add_to_mask(state, &state->group);

	for (i=0; i < state->groups->n; i++) {
		pace++;
		pace->e_tag = ACL_GROUP;
		error = check_deny(state->groups->aces[i].perms.deny, 0);
		if (error)
			goto out_err;
		low_mode_from_nfs4(state->groups->aces[i].perms.allow,
					&pace->e_perm, flags);
		pace->e_gid = state->groups->aces[i].gid;
@@ -605,15 +563,9 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)

	pace++;
	pace->e_tag = ACL_OTHER;
	error = check_deny(state->other.deny, 0);
	if (error)
		goto out_err;
	low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);

	return pacl;
out_err:
	posix_acl_release(pacl);
	return ERR_PTR(error);
}

static inline void allow_bits(struct posix_ace_state *astate, u32 mask)
+8 −4
Original line number Diff line number Diff line
@@ -470,7 +470,7 @@ out:
		fh_put(resfh);
		kfree(resfh);
	}
	nfsd4_cleanup_open_state(cstate, open, status);
	nfsd4_cleanup_open_state(cstate, open);
	nfsd4_bump_seqid(cstate, status);
	return status;
}
@@ -1030,6 +1030,8 @@ nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
		return status;
	}
	if (!file)
		return nfserr_bad_stateid;

	status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file,
				     fallocate->falloc_offset,
@@ -1069,6 +1071,8 @@ nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
		dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n");
		return status;
	}
	if (!file)
		return nfserr_bad_stateid;

	switch (seek->seek_whence) {
	case NFS4_CONTENT_DATA:
@@ -1815,7 +1819,7 @@ static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp,
		bmap0 &= ~FATTR4_WORD0_FILEHANDLE;
	}
	if (bmap2 & FATTR4_WORD2_SECURITY_LABEL) {
		ret += NFSD4_MAX_SEC_LABEL_LEN + 12;
		ret += NFS4_MAXLABELLEN + 12;
		bmap2 &= ~FATTR4_WORD2_SECURITY_LABEL;
	}
	/*
@@ -2282,13 +2286,13 @@ static struct nfsd4_operation nfsd4_ops[] = {
		.op_func = (nfsd4op_func)nfsd4_allocate,
		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
		.op_name = "OP_ALLOCATE",
		.op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
	},
	[OP_DEALLOCATE] = {
		.op_func = (nfsd4op_func)nfsd4_deallocate,
		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
		.op_name = "OP_DEALLOCATE",
		.op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
	},
	[OP_SEEK] = {
		.op_func = (nfsd4op_func)nfsd4_seek,
Loading