Commit 12bf0b63 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client bugfixes from Trond Myklebust:
 "Highlights include:

  Stable fixes:
   - nfs: fix NULL deference in nfs4_get_valid_delegation

  Bugfixes:
   - Fix corruption of the return value in cachefiles_read_or_alloc_pages()
   - Fix several fscache cookie issues
   - Fix a fscache queuing race that can trigger a BUG_ON
   - NFS: Fix two use-after-free regressions due to the RPC_TASK_CRED_NOREF flag
   - SUNRPC: Fix a use-after-free regression in rpc_free_client_work()
   - SUNRPC: Fix a race when tearing down the rpc client debugfs directory
   - SUNRPC: Signalled ASYNC tasks need to exit
   - NFSv3: fix rpc receive buffer size for MOUNT call"

* tag 'nfs-for-5.7-5' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  NFSv3: fix rpc receive buffer size for MOUNT call
  SUNRPC: 'Directory with parent 'rpc_clnt' already present!'
  NFS/pnfs: Don't use RPC_TASK_CRED_NOREF with pnfs
  NFS: Don't use RPC_TASK_CRED_NOREF with delegreturn
  SUNRPC: Signalled ASYNC tasks need to exit
  nfs: fix NULL deference in nfs4_get_valid_delegation
  SUNRPC: fix use-after-free in rpc_free_client_work()
  cachefiles: Fix race between read_waiter and read_copier involving op->to_do
  NFSv4: Fix fscache cookie aux_data to ensure change_attr is included
  NFS: Fix fscache super_cookie allocation
  NFS: Fix fscache super_cookie index_key from changing after umount
  cachefiles: Fix corruption of the return value in cachefiles_read_or_alloc_pages()
parents f85c1598 8eed292b
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -60,9 +60,9 @@ static int cachefiles_read_waiter(wait_queue_entry_t *wait, unsigned mode,
	object = container_of(op->op.object, struct cachefiles_object, fscache);
	spin_lock(&object->work_lock);
	list_add_tail(&monitor->op_link, &op->to_do);
	fscache_enqueue_retrieval(op);
	spin_unlock(&object->work_lock);

	fscache_enqueue_retrieval(op);
	fscache_put_retrieval(op);
	return 0;
}
@@ -398,7 +398,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
	struct inode *inode;
	sector_t block;
	unsigned shift;
	int ret;
	int ret, ret2;

	object = container_of(op->op.object,
			      struct cachefiles_object, fscache);
@@ -430,8 +430,8 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
	block = page->index;
	block <<= shift;

	ret = bmap(inode, &block);
	ASSERT(ret < 0);
	ret2 = bmap(inode, &block);
	ASSERT(ret2 == 0);

	_debug("%llx -> %llx",
	       (unsigned long long) (page->index << shift),
@@ -739,8 +739,8 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
		block = page->index;
		block <<= shift;

		ret = bmap(inode, &block);
		ASSERT(!ret);
		ret2 = bmap(inode, &block);
		ASSERT(ret2 == 0);

		_debug("%llx -> %llx",
		       (unsigned long long) (page->index << shift),
+18 −21
Original line number Diff line number Diff line
@@ -118,8 +118,6 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int

	nfss->fscache_key = NULL;
	nfss->fscache = NULL;
	if (!(nfss->options & NFS_OPTION_FSCACHE))
		return;
	if (!uniq) {
		uniq = "";
		ulen = 1;
@@ -188,7 +186,8 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
	/* create a cache index for looking up filehandles */
	nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
					       &nfs_fscache_super_index_def,
					       key, sizeof(*key) + ulen,
					       &key->key,
					       sizeof(key->key) + ulen,
					       NULL, 0,
					       nfss, 0, true);
	dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
@@ -226,6 +225,19 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
	}
}

static void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata,
				  struct nfs_inode *nfsi)
{
	memset(auxdata, 0, sizeof(*auxdata));
	auxdata->mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
	auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
	auxdata->ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
	auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;

	if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
		auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
}

/*
 * Initialise the per-inode cache cookie pointer for an NFS inode.
 */
@@ -239,14 +251,7 @@ void nfs_fscache_init_inode(struct inode *inode)
	if (!(nfss->fscache && S_ISREG(inode->i_mode)))
		return;

	memset(&auxdata, 0, sizeof(auxdata));
	auxdata.mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
	auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
	auxdata.ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
	auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;

	if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
		auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
	nfs_fscache_update_auxdata(&auxdata, nfsi);

	nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
					       &nfs_fscache_inode_object_def,
@@ -266,11 +271,7 @@ void nfs_fscache_clear_inode(struct inode *inode)

	dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);

	memset(&auxdata, 0, sizeof(auxdata));
	auxdata.mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
	auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
	auxdata.ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
	auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
	nfs_fscache_update_auxdata(&auxdata, nfsi);
	fscache_relinquish_cookie(cookie, &auxdata, false);
	nfsi->fscache = NULL;
}
@@ -310,11 +311,7 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp)
	if (!fscache_cookie_valid(cookie))
		return;

	memset(&auxdata, 0, sizeof(auxdata));
	auxdata.mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
	auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
	auxdata.ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
	auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
	nfs_fscache_update_auxdata(&auxdata, nfsi);

	if (inode_is_open_for_write(inode)) {
		dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
+2 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#define encode_dirpath_sz	(1 + XDR_QUADLEN(MNTPATHLEN))
#define MNT_status_sz		(1)
#define MNT_fhandle_sz		XDR_QUADLEN(NFS2_FHSIZE)
#define MNT_fhandlev3_sz	XDR_QUADLEN(NFS3_FHSIZE)
#define MNT_authflav3_sz	(1 + NFS_MAX_SECFLAVORS)

/*
@@ -37,7 +38,7 @@
 */
#define MNT_enc_dirpath_sz	encode_dirpath_sz
#define MNT_dec_mountres_sz	(MNT_status_sz + MNT_fhandle_sz)
#define MNT_dec_mountres3_sz	(MNT_status_sz + MNT_fhandle_sz + \
#define MNT_dec_mountres3_sz	(MNT_status_sz + MNT_fhandlev3_sz + \
				 MNT_authflav3_sz)

/*
+1 −1
Original line number Diff line number Diff line
@@ -6347,7 +6347,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
		.rpc_client = server->client,
		.rpc_message = &msg,
		.callback_ops = &nfs4_delegreturn_ops,
		.flags = RPC_TASK_ASYNC | RPC_TASK_CRED_NOREF | RPC_TASK_TIMEOUT,
		.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
	};
	int status = 0;

+1 −1
Original line number Diff line number Diff line
@@ -734,9 +734,9 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
		state = new;
		state->owner = owner;
		atomic_inc(&owner->so_count);
		list_add_rcu(&state->inode_states, &nfsi->open_states);
		ihold(inode);
		state->inode = inode;
		list_add_rcu(&state->inode_states, &nfsi->open_states);
		spin_unlock(&inode->i_lock);
		/* Note: The reclaim code dictates that we add stateless
		 * and read-only stateids to the end of the list */
Loading