Commit 3cb5b917 authored by Zhipeng Lu's avatar Zhipeng Lu Committed by Dong Chenchen
Browse files

SUNRPC: fix some memleaks in gssx_dec_option_array

mainline inclusion
from mainline-v6.9-rc1
commit 3cfcfc102a5e57b021b786a755a38935e357797d
category: bugfix
bugzilla: 189901, https://gitee.com/src-openeuler/kernel/issues/I9L9J1
CVE: CVE-2024-27388

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=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: 1d658336 ("SUNRPC: Add RPC based upcall mechanism for RPCGSS auth")
Signed-off-by: default avatarZhipeng Lu <alexious@zju.edu.cn>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarDong Chenchen <dongchenchen2@huawei.com>
parent 7d91c9c7
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
@@ -263,8 +263,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;
@@ -278,29 +278,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,