SUNRPC: fix some memleaks in gssx_dec_option_array

[ 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: 1d658336b0 ("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>
This commit is contained in:
Zhipeng Lu
2024-01-02 13:38:13 +08:00
committed by Sasha Levin
parent a4e7ff1a74
commit bb336cd8d5

View File

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