]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
SUNRPC: fix some memleaks in gssx_dec_option_array
authorZhipeng Lu <alexious@zju.edu.cn>
Tue, 2 Jan 2024 05:38:13 +0000 (13:38 +0800)
committerSasha Levin <sashal@kernel.org>
Tue, 26 Mar 2024 22:21:51 +0000 (18:21 -0400)
[ Upstream commit 3cfcfc102a5e57b021b786a755a38935e357797d ]

The creds and oa->data need to be freed in the error-handling paths after
their allocation. So this patch add these deallocations in the
corresponding paths.

Fixes: 1d658336b05f ("SUNRPC: Add RPC based upcall mechanism for RPCGSS auth")
Signed-off-by: Zhipeng Lu <alexious@zju.edu.cn>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/sunrpc/auth_gss/gss_rpc_xdr.c

index 2ff7b7083ebab9dee3d4d1196be181cb39ba6c11..e265b8d38aa14db3f7c89e5a050e7d45b890e586 100644 (file)
@@ -250,8 +250,8 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,
 
        creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL);
        if (!creds) {
-               kfree(oa->data);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto free_oa;
        }
 
        oa->data[0].option.data = CREDS_VALUE;
@@ -265,29 +265,40 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,
 
                /* option buffer */
                p = xdr_inline_decode(xdr, 4);
-               if (unlikely(p == NULL))
-                       return -ENOSPC;
+               if (unlikely(p == NULL)) {
+                       err = -ENOSPC;
+                       goto free_creds;
+               }
 
                length = be32_to_cpup(p);
                p = xdr_inline_decode(xdr, length);
-               if (unlikely(p == NULL))
-                       return -ENOSPC;
+               if (unlikely(p == NULL)) {
+                       err = -ENOSPC;
+                       goto free_creds;
+               }
 
                if (length == sizeof(CREDS_VALUE) &&
                    memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) {
                        /* We have creds here. parse them */
                        err = gssx_dec_linux_creds(xdr, creds);
                        if (err)
-                               return err;
+                               goto free_creds;
                        oa->data[0].value.len = 1; /* presence */
                } else {
                        /* consume uninteresting buffer */
                        err = gssx_dec_buffer(xdr, &dummy);
                        if (err)
-                               return err;
+                               goto free_creds;
                }
        }
        return 0;
+
+free_creds:
+       kfree(creds);
+free_oa:
+       kfree(oa->data);
+       oa->data = NULL;
+       return err;
 }
 
 static int gssx_dec_status(struct xdr_stream *xdr,