diff mbox series

NFSv4: fix out path in __nfs4_get_acl_uncached

Message ID 20230725115933.23784-1-pchelkin@ispras.ru (mailing list archive)
State New, archived
Headers show
Series NFSv4: fix out path in __nfs4_get_acl_uncached | expand

Commit Message

Fedor Pchelkin July 25, 2023, 11:59 a.m. UTC
Another highly rare error case when a page allocating loop (inside
__nfs4_get_acl_uncached, this time) is not properly unwound on error.
Since pages array is allocated being uninitialized, need to free only
lower array indices. NULL checks were useful before commit 62a1573fcf84
("NFSv4 fix acl retrieval over krb5i/krb5p mounts") when the array had
been initialized to zero on stack.

Found by Linux Verification Center (linuxtesting.org).

Fixes: 62a1573fcf84 ("NFSv4 fix acl retrieval over krb5i/krb5p mounts")
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
---
 fs/nfs/nfs4proc.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Comments

Benjamin Coddington July 26, 2023, 3:09 p.m. UTC | #1
On 25 Jul 2023, at 7:59, Fedor Pchelkin wrote:

> Another highly rare error case when a page allocating loop (inside
> __nfs4_get_acl_uncached, this time) is not properly unwound on error.
> Since pages array is allocated being uninitialized, need to free only
> lower array indices. NULL checks were useful before commit 62a1573fcf84
> ("NFSv4 fix acl retrieval over krb5i/krb5p mounts") when the array had
> been initialized to zero on stack.
>
> Found by Linux Verification Center (linuxtesting.org).
>
> Fixes: 62a1573fcf84 ("NFSv4 fix acl retrieval over krb5i/krb5p mounts")
> Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>

Nice one.

Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
diff mbox series

Patch

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e1a886b58354..08e8381a5e46 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6004,9 +6004,8 @@  static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
 out_ok:
 	ret = res.acl_len;
 out_free:
-	for (i = 0; i < npages; i++)
-		if (pages[i])
-			__free_page(pages[i]);
+	while (--i >= 0)
+		__free_page(pages[i]);
 	if (res.acl_scratch)
 		__free_page(res.acl_scratch);
 	kfree(pages);