linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] nfs: Fix potential posix_acl refcnt leak in nfs3_set_acl
@ 2020-04-20 13:51 Andreas Gruenbacher
  2020-04-20 14:13 ` Trond Myklebust
  0 siblings, 1 reply; 8+ messages in thread
From: Andreas Gruenbacher @ 2020-04-20 13:51 UTC (permalink / raw)
  To: Trond Myklebust
  Cc: Andreas Gruenbacher, okir, tanxin.ctf, xiyuyang19, akpm,
	linux-kernel, linux-nfs, anna.schumaker, kjlu, yuanxzhang

nfs3_set_acl keeps track of the acl it allocated locally to determine if an acl
needs to be released at the end.  This results in a memory leak when the
function allocates an acl as well as a default acl.  Fix by releasing acls
that differ from the acl originally passed into nfs3_set_acl.

Fixes: b7fa0554cf1b ("[PATCH] NFS: Add support for NFSv3 ACLs")
Reported-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/nfs/nfs3acl.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index c5c3fc6e6c60..26c94b32d6f4 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -253,37 +253,45 @@ int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
 
 int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
-	struct posix_acl *alloc = NULL, *dfacl = NULL;
+	struct posix_acl *orig = acl, *dfacl = NULL, *alloc;
 	int status;
 
 	if (S_ISDIR(inode->i_mode)) {
 		switch(type) {
 		case ACL_TYPE_ACCESS:
-			alloc = dfacl = get_acl(inode, ACL_TYPE_DEFAULT);
+			alloc = get_acl(inode, ACL_TYPE_DEFAULT);
 			if (IS_ERR(alloc))
 				goto fail;
+			dfacl = alloc;
 			break;
 
 		case ACL_TYPE_DEFAULT:
-			dfacl = acl;
-			alloc = acl = get_acl(inode, ACL_TYPE_ACCESS);
+			alloc = get_acl(inode, ACL_TYPE_ACCESS);
 			if (IS_ERR(alloc))
 				goto fail;
+			dfacl = acl;
+			acl = alloc;
 			break;
 		}
 	}
 
 	if (acl == NULL) {
-		alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+		alloc = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
 		if (IS_ERR(alloc))
 			goto fail;
+		acl = alloc;
 	}
 	status = __nfs3_proc_setacls(inode, acl, dfacl);
-	posix_acl_release(alloc);
+out:
+	if (acl != orig)
+		posix_acl_release(acl);
+	if (dfacl != orig)
+		posix_acl_release(dfacl);
 	return status;
 
 fail:
-	return PTR_ERR(alloc);
+	status = PTR_ERR(alloc);
+	goto out;
 }
 
 const struct xattr_handler *nfs3_xattr_handlers[] = {

base-commit: ae83d0b416db002fe95601e7f97f64b59514d936
-- 
2.25.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread
* [PATCH] nfs: Fix potential posix_acl refcnt leak in nfs3_set_acl
@ 2020-04-20  5:43 Xiyu Yang
  2020-04-20 12:14 ` Trond Myklebust
  0 siblings, 1 reply; 8+ messages in thread
From: Xiyu Yang @ 2020-04-20  5:43 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Olaf Kirch, Andrew Morton,
	Andreas Gruenbacher, linux-nfs, linux-kernel
  Cc: yuanxzhang, kjlu, Xiyu Yang, Xin Tan

nfs3_set_acl() invokes get_acl(), which returns a local reference of the
posix_acl object to "alloc" with increased refcount.

When nfs3_set_acl() returns or a new object is assigned to "alloc",  the
original local reference of  "alloc" becomes invalid, so the refcount
should be decreased to keep refcount balanced.

The reference counting issue happens in one path of nfs3_set_acl(). When
"acl" equals to NULL but "alloc" is not NULL, the function forgets to
decrease the refcnt increased by get_acl() and causes a refcnt leak.

Fix this issue by calling posix_acl_release() on this path when "alloc"
is not NULL.

Fixes: b7fa0554cf1b ("[PATCH] NFS: Add support for NFSv3 ACLs")
Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
---
 fs/nfs/nfs3acl.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index c5c3fc6e6c60..b5c41bcca8cf 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -274,6 +274,8 @@ int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 	}
 
 	if (acl == NULL) {
+		if (alloc)
+			posix_acl_release(alloc);
 		alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
 		if (IS_ERR(alloc))
 			goto fail;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-04-20 14:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-20 13:51 [PATCH] nfs: Fix potential posix_acl refcnt leak in nfs3_set_acl Andreas Gruenbacher
2020-04-20 14:13 ` Trond Myklebust
  -- strict thread matches above, loose matches on Subject: below --
2020-04-20  5:43 Xiyu Yang
2020-04-20 12:14 ` Trond Myklebust
2020-04-20 12:51   ` Andreas Gruenbacher
2020-04-20 12:59     ` Trond Myklebust
2020-04-20 13:04       ` Andreas Gruenbacher
2020-04-20 13:13         ` Trond Myklebust

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).