Question about possible use-after-free in nfs_direct_write_reschedule()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I've been reviewing some nfs/direct.c patches for possible backport to
one of our older enterprise kernels and I've found something that looks
wrong.

It isn't clear to me how to exercise the code so I haven't be able to
trigger a problem.  I'm hoping that someone could either explain when
this code runs, or confirm if the code is correct or not.

Commit 954998b60caa ("NFS: Fix error handling for O_DIRECT write scheduling")

adds an extra call to nfs_release_request() but I cannot find any place
that an extra reference is taken.

The code currently reads:

	while (!list_empty(&reqs)) {
		req = nfs_list_entry(reqs.next);
		nfs_list_remove_request(req);
		nfs_unlock_and_release_request(req);
		if (desc.pg_error == -EAGAIN) {
			nfs_mark_request_commit(req, NULL, &cinfo, 0);
		} else {
			spin_lock(&dreq->lock);
			nfs_direct_truncate_request(dreq, req);
			spin_unlock(&dreq->lock);
			nfs_release_request(req);
		}
	}

after the nfs_unlock_and_release_request() call I would expect that the
request could be freed, so that nfs_mark_request_commit() or the
nfs_release_request() could cause a problem.

Superficially it looks like the call should be simply
nfs_unlock_request().  This would follow the
list_remove;unlock;mark_commit pattern also found in
nfs_direct_write_reschedule_io().

Do we need:
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -581,7 +581,7 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
 	while (!list_empty(&reqs)) {
 		req = nfs_list_entry(reqs.next);
 		nfs_list_remove_request(req);
-		nfs_unlock_and_release_request(req);
+		nfs_unlock_request(req);
 		if (desc.pg_error == -EAGAIN) {
 			nfs_mark_request_commit(req, NULL, &cinfo, 0);
 		} else {

??

Thanks,
NeilBrown





[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux