Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7a128f0 authored by Trond Myklebust's avatar Trond Myklebust Committed by Greg Kroah-Hartman
Browse files

NFSv4: nfs4_copy_delegation_stateid() must fail if the delegation is invalid



commit aa05c87f23efe417adc7ff9b4193b7201ec0dd79 upstream.

We must not allow the use of delegations that have been revoked or are
being returned.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Fixes: 869f9dfa ("NFSv4: Fix races between nfs_remove_bad_delegation()...")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Tested-by: default avatarOleg Drokin <green@linuxhacker.ru>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 79e7e444
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -41,6 +41,17 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
	set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
}

static bool
nfs4_is_valid_delegation(const struct nfs_delegation *delegation,
		fmode_t flags)
{
	if (delegation != NULL && (delegation->type & flags) == flags &&
	    !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
	    !test_bit(NFS_DELEGATION_RETURNING, &delegation->flags))
		return true;
	return false;
}

static int
nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
{
@@ -50,9 +61,7 @@ nfs4_do_check_delegation(struct inode *inode, fmode_t flags, bool mark)
	flags &= FMODE_READ|FMODE_WRITE;
	rcu_read_lock();
	delegation = rcu_dereference(NFS_I(inode)->delegation);
	if (delegation != NULL && (delegation->type & flags) == flags &&
	    !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) &&
	    !test_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) {
	if (nfs4_is_valid_delegation(delegation, flags)) {
		if (mark)
			nfs_mark_delegation_referenced(delegation);
		ret = 1;
@@ -893,7 +902,7 @@ bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode,
	flags &= FMODE_READ|FMODE_WRITE;
	rcu_read_lock();
	delegation = rcu_dereference(nfsi->delegation);
	ret = (delegation != NULL && (delegation->type & flags) == flags);
	ret = nfs4_is_valid_delegation(delegation, flags);
	if (ret) {
		nfs4_stateid_copy(dst, &delegation->stateid);
		nfs_mark_delegation_referenced(delegation);