Commit 421ca22e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client fixes from Anna Schumaker:
 "Stable Fix:

   - Don't change task->tk_status after the call to rpc_exit_task

  Other Bugfixes:

   - Convert kmap_atomic() to kmap_local_folio()

   - Fix a potential double free with READ_PLUS"

* tag 'nfs-for-6.4-2' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFSv4.2: Fix a potential double free with READ_PLUS
  SUNRPC: Don't change task->tk_status after the call to rpc_exit_task
  NFS: Convert kmap_atomic() to kmap_local_folio()
parents 44c026a7 43439d85
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -317,7 +317,7 @@ static int nfs_readdir_folio_array_append(struct folio *folio,

	name = nfs_readdir_copy_name(entry->name, entry->len);

	array = kmap_atomic(folio_page(folio, 0));
	array = kmap_local_folio(folio, 0);
	if (!name)
		goto out;
	ret = nfs_readdir_array_can_expand(array);
@@ -340,7 +340,7 @@ static int nfs_readdir_folio_array_append(struct folio *folio,
		nfs_readdir_array_set_eof(array);
out:
	*cookie = array->last_cookie;
	kunmap_atomic(array);
	kunmap_local(array);
	return ret;
}

+10 −2
Original line number Diff line number Diff line
@@ -5437,10 +5437,18 @@ static bool nfs4_read_plus_not_supported(struct rpc_task *task,
	return false;
}

static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
static inline void nfs4_read_plus_scratch_free(struct nfs_pgio_header *hdr)
{
	if (hdr->res.scratch)
	if (hdr->res.scratch) {
		kfree(hdr->res.scratch);
		hdr->res.scratch = NULL;
	}
}

static int nfs4_read_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
{
	nfs4_read_plus_scratch_free(hdr);

	if (!nfs4_sequence_done(task, &hdr->res.seq_res))
		return -EAGAIN;
	if (nfs4_read_stateid_changed(task, &hdr->args))
+2 −3
Original line number Diff line number Diff line
@@ -927,10 +927,9 @@ static void __rpc_execute(struct rpc_task *task)
		 */
		do_action = task->tk_action;
		/* Tasks with an RPC error status should exit */
		if (do_action != rpc_exit_task &&
		if (do_action && do_action != rpc_exit_task &&
		    (status = READ_ONCE(task->tk_rpc_status)) != 0) {
			task->tk_status = status;
			if (do_action != NULL)
			do_action = rpc_exit_task;
		}
		/* Callbacks override all actions */