Skip to content

Commit 7a28d65

Browse files
Mike Snitzergregkh
authored andcommitted
nfs/localio: fix regression due to out-of-order __put_cred
commit 3af870a upstream. Commit f2060bd ("nfs/localio: add refcounting for each iocb IO associated with NFS pgio header") inadvertantly reintroduced the same potential for __put_cred() triggering BUG_ON(cred == current->cred) that commit 992203a ("nfs/localio: restore creds before releasing pageio data") fixed. Fix this by saving and restoring the cred around each {read,write}_iter call within the respective for loop of nfs_local_call_{read,write} using scoped_with_creds(). NOTE: this fix started by first reverting the following commits: 94afb62 ("nfs: use credential guards in nfs_local_call_read()") bff3c84 ("nfs: use credential guards in nfs_local_call_write()") 1d18101 ("Merge tag 'kernel-6.19-rc1.cred' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs") followed by narrowly fixing the cred lifetime issue by using scoped_with_creds(). In doing so, this commit's changes appear more extensive than they really are (as evidenced by comparing to v6.18's fs/nfs/localio.c). Reported-by: Zorro Lang <[email protected]> Signed-off-by: Mike Snitzer <[email protected]> Acked-by: Trond Myklebust <[email protected]> Reviewed-by: Christian Brauner <[email protected]> Link: https://lore.kernel.org/linux-next/[email protected]/ Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Trond Myklebust <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 98a2689 commit 7a28d65

1 file changed

Lines changed: 6 additions & 6 deletions

File tree

fs/nfs/localio.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -623,8 +623,6 @@ static void nfs_local_call_read(struct work_struct *work)
623623
ssize_t status;
624624
int n_iters;
625625

626-
save_cred = override_creds(filp->f_cred);
627-
628626
n_iters = atomic_read(&iocb->n_iters);
629627
for (int i = 0; i < n_iters ; i++) {
630628
if (iocb->iter_is_dio_aligned[i]) {
@@ -637,7 +635,10 @@ static void nfs_local_call_read(struct work_struct *work)
637635
} else
638636
iocb->kiocb.ki_flags &= ~IOCB_DIRECT;
639637

638+
save_cred = override_creds(filp->f_cred);
640639
status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]);
640+
revert_creds(save_cred);
641+
641642
if (status != -EIOCBQUEUED) {
642643
if (unlikely(status >= 0 && status < iocb->iters[i].count))
643644
force_done = true; /* Partial read */
@@ -647,8 +648,6 @@ static void nfs_local_call_read(struct work_struct *work)
647648
}
648649
}
649650
}
650-
651-
revert_creds(save_cred);
652651
}
653652

654653
static int
@@ -830,7 +829,6 @@ static void nfs_local_call_write(struct work_struct *work)
830829
int n_iters;
831830

832831
current->flags |= PF_LOCAL_THROTTLE | PF_MEMALLOC_NOIO;
833-
save_cred = override_creds(filp->f_cred);
834832

835833
file_start_write(filp);
836834
n_iters = atomic_read(&iocb->n_iters);
@@ -845,7 +843,10 @@ static void nfs_local_call_write(struct work_struct *work)
845843
} else
846844
iocb->kiocb.ki_flags &= ~IOCB_DIRECT;
847845

846+
save_cred = override_creds(filp->f_cred);
848847
status = filp->f_op->write_iter(&iocb->kiocb, &iocb->iters[i]);
848+
revert_creds(save_cred);
849+
849850
if (status != -EIOCBQUEUED) {
850851
if (unlikely(status >= 0 && status < iocb->iters[i].count))
851852
force_done = true; /* Partial write */
@@ -857,7 +858,6 @@ static void nfs_local_call_write(struct work_struct *work)
857858
}
858859
file_end_write(filp);
859860

860-
revert_creds(save_cred);
861861
current->flags = old_flags;
862862
}
863863

0 commit comments

Comments
 (0)