From: Lizhi Hou <lizhi.hou@amd.com>
To: Mario Limonciello <mario.limonciello@amd.com>,
<ogabbay@kernel.org>, <quic_jhugo@quicinc.com>,
<dri-devel@lists.freedesktop.org>,
<maciej.falkowski@linux.intel.com>
Cc: <linux-kernel@vger.kernel.org>, <max.zhen@amd.com>,
<sonal.santan@amd.com>
Subject: Re: [PATCH V2] accel/amdxdna: Adjust size for copy_to_user()
Date: Fri, 3 Apr 2026 08:50:20 -0700 [thread overview]
Message-ID: <474ea416-ddde-88ed-1751-9960dcaef5a2@amd.com> (raw)
In-Reply-To: <ec41932c-79b9-4301-a66f-e1a50ede017c@amd.com>
On 4/2/26 14:06, Mario Limonciello wrote:
> On 4/2/26 12:41 PM, Lizhi Hou wrote:
>> The amount of data returned to user space should be limited by the
>> buffer
>> size provided by the application. If the buffer is smaller than the data
>> size, return only the portion that fits instead of failing.
>>
>> Fixes: 850d71f6bf4c ("accel/amdxdna: Add query functions")
>> Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
>> ---
>> drivers/accel/amdxdna/aie2_error.c | 5 ++-
>> drivers/accel/amdxdna/aie2_message.c | 20 ++++++----
>> drivers/accel/amdxdna/aie2_pci.c | 59 ++++++++++++++++------------
>> 3 files changed, 50 insertions(+), 34 deletions(-)
>>
>> diff --git a/drivers/accel/amdxdna/aie2_error.c
>> b/drivers/accel/amdxdna/aie2_error.c
>> index 9d20e956c020..70007b4363cd 100644
>> --- a/drivers/accel/amdxdna/aie2_error.c
>> +++ b/drivers/accel/amdxdna/aie2_error.c
>> @@ -406,8 +406,11 @@ int aie2_get_array_async_error(struct
>> amdxdna_dev_hdl *ndev, struct amdxdna_drm_
>> drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
>> + if (!args->num_element)
>> + return -EINVAL;
>> +
>> args->num_element = 1;
>
> I don't really follow. Why check if args->num_element is 0 and then
> set it to 1? Does the check actually make sense? Just set it to one
> and ignore what's there before.
args->num_element is used as both user input and output argument.
As a input argument, it means the max number of element user expected.
Expecting 0 element doe not make sense, thus -EINVAL is returned.
As a output argument, driver fills actual number of element being
returned. One element is returned for getting async error case.
>
> If it's for protecting args like a NULL args->buffer, wouldn't it make
> more sense to check for that?
>
>> - args->element_size = sizeof(ndev->last_async_err);
>> + args->element_size = min(args->element_size,
>> sizeof(ndev->last_async_err));
>
> As this comes from userspace, couldn't it end up being clamped if
> userspace sends a smaller buffer? Is that intended?
Yes, it is possible user sends smaller buffer. In this case, driver
fills partial of its data. This is intended.
>
>> if (copy_to_user(u64_to_user_ptr(args->buffer),
>> &ndev->last_async_err, args->element_size))
>> return -EFAULT;
>> diff --git a/drivers/accel/amdxdna/aie2_message.c
>> b/drivers/accel/amdxdna/aie2_message.c
>> index e5e7da7a8f40..e52dc7ea9fc7 100644
>> --- a/drivers/accel/amdxdna/aie2_message.c
>> +++ b/drivers/accel/amdxdna/aie2_message.c
>> @@ -369,12 +369,13 @@ int aie2_query_status(struct amdxdna_dev_hdl
>> *ndev, char __user *buf,
>> {
>> DECLARE_AIE_MSG(aie_column_info, MSG_OP_QUERY_COL_STATUS);
>> struct amdxdna_dev *xdna = ndev->aie.xdna;
>> - u32 buf_sz = size, aie_bitmap = 0;
>> + u32 buf_sz, aie_bitmap = 0;
>> struct amdxdna_client *client;
>> dma_addr_t dma_addr;
>> u8 *buff_addr;
>> int ret;
>> + buf_sz = ndev->metadata.cols * ndev->metadata.size;
>
> Don't you want to respect /check the size of the caller immediately?
> It seems odd to hardcode it here at allocation time.
ndev->metadata.cols * ndev->metadata.size is from firmware but not user
space. So it does not need to check.
Thanks,
Lizhi
>
>> buff_addr = aie2_alloc_msg_buffer(ndev, &buf_sz, &dma_addr);
>> if (IS_ERR(buff_addr))
>> return PTR_ERR(buff_addr);
>> @@ -398,13 +399,14 @@ int aie2_query_status(struct amdxdna_dev_hdl
>> *ndev, char __user *buf,
>> XDNA_DBG(xdna, "Query NPU status completed");
>> - if (size < resp.size) {
>> + if (buf_sz < resp.size) {
>> ret = -EINVAL;
>> - XDNA_ERR(xdna, "Bad buffer size. Available: %u. Needs: %u",
>> size, resp.size);
>> + XDNA_ERR(xdna, "Bad buffer size. Available: %u. Needs: %u",
>> buf_sz, resp.size);
>> goto fail;
>> }
>> - if (copy_to_user(buf, buff_addr, resp.size)) {
>> + size = min(size, resp.size);
>> + if (copy_to_user(buf, buff_addr, size)) {
>> ret = -EFAULT;
>> XDNA_ERR(xdna, "Failed to copy NPU status to user space");
>> goto fail;
>> @@ -424,13 +426,14 @@ int aie2_query_telemetry(struct amdxdna_dev_hdl
>> *ndev,
>> DECLARE_AIE_MSG(get_telemetry, MSG_OP_GET_TELEMETRY);
>> struct amdxdna_dev *xdna = ndev->aie.xdna;
>> dma_addr_t dma_addr;
>> - u32 buf_sz = size;
>> + u32 buf_sz;
>> u8 *addr;
>> int ret;
>> if (header->type >= MAX_TELEMETRY_TYPE)
>> return -EINVAL;
>> + buf_sz = min(size, SZ_4M);
>> addr = aie2_alloc_msg_buffer(ndev, &buf_sz, &dma_addr);
>> if (IS_ERR(addr))
>> return PTR_ERR(addr);
>> @@ -446,13 +449,14 @@ int aie2_query_telemetry(struct amdxdna_dev_hdl
>> *ndev,
>> goto free_buf;
>> }
>> - if (size < resp.size) {
>> + if (buf_sz < resp.size) {
>> ret = -EINVAL;
>> - XDNA_ERR(xdna, "Bad buffer size. Available: %u. Needs: %u",
>> size, resp.size);
>> + XDNA_ERR(xdna, "Bad buffer size. Available: %u. Needs: %u",
>> buf_sz, resp.size);
>> goto free_buf;
>> }
>> - if (copy_to_user(buf, addr, resp.size)) {
>> + size = min(size, resp.size);
>> + if (copy_to_user(buf, addr, size)) {
>> ret = -EFAULT;
>> XDNA_ERR(xdna, "Failed to copy telemetry to user space");
>> goto free_buf;
>> diff --git a/drivers/accel/amdxdna/aie2_pci.c
>> b/drivers/accel/amdxdna/aie2_pci.c
>> index 164e188ba501..041cbc8cd7e5 100644
>> --- a/drivers/accel/amdxdna/aie2_pci.c
>> +++ b/drivers/accel/amdxdna/aie2_pci.c
>> @@ -620,23 +620,19 @@ static void aie2_fini(struct amdxdna_dev *xdna)
>> static int aie2_get_aie_status(struct amdxdna_client *client,
>> struct amdxdna_drm_get_info *args)
>> {
>> - struct amdxdna_drm_query_aie_status status;
>> + struct amdxdna_drm_query_aie_status status = {};
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_dev_hdl *ndev;
>> + u32 buf_sz;
>> int ret;
>> ndev = xdna->dev_handle;
>> - if (copy_from_user(&status, u64_to_user_ptr(args->buffer),
>> sizeof(status))) {
>> + buf_sz = min(args->buffer_size, sizeof(status));
>> + if (copy_from_user(&status, u64_to_user_ptr(args->buffer),
>> buf_sz)) {
>> XDNA_ERR(xdna, "Failed to copy AIE request into kernel");
>> return -EFAULT;
>> }
>> - if (ndev->metadata.cols * ndev->metadata.size <
>> status.buffer_size) {
>> - XDNA_ERR(xdna, "Invalid buffer size. Given Size: %u. Need
>> Size: %u.",
>> - status.buffer_size, ndev->metadata.cols *
>> ndev->metadata.size);
>> - return -EINVAL;
>> - }
>> -
>> ret = aie2_query_status(ndev, u64_to_user_ptr(status.buffer),
>> status.buffer_size, &status.cols_filled);
>> if (ret) {
>> @@ -644,7 +640,7 @@ static int aie2_get_aie_status(struct
>> amdxdna_client *client,
>> return ret;
>> }
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), &status,
>> sizeof(status))) {
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), &status, buf_sz)) {
>> XDNA_ERR(xdna, "Failed to copy AIE request info to user
>> space");
>> return -EFAULT;
>> }
>> @@ -659,6 +655,7 @@ static int aie2_get_aie_metadata(struct
>> amdxdna_client *client,
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_dev_hdl *ndev;
>> int ret = 0;
>> + u32 buf_sz;
>> ndev = xdna->dev_handle;
>> meta = kzalloc_obj(*meta);
>> @@ -690,7 +687,8 @@ static int aie2_get_aie_metadata(struct
>> amdxdna_client *client,
>> meta->shim.lock_count = ndev->metadata.shim.lock_count;
>> meta->shim.event_reg_count = ndev->metadata.shim.event_reg_count;
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), meta,
>> sizeof(*meta)))
>> + buf_sz = min(args->buffer_size, sizeof(*meta));
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), meta, buf_sz))
>> ret = -EFAULT;
>> kfree(meta);
>> @@ -703,12 +701,14 @@ static int aie2_get_aie_version(struct
>> amdxdna_client *client,
>> struct amdxdna_drm_query_aie_version version;
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_dev_hdl *ndev;
>> + u32 buf_sz;
>> ndev = xdna->dev_handle;
>> version.major = ndev->version.major;
>> version.minor = ndev->version.minor;
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), &version,
>> sizeof(version)))
>> + buf_sz = min(args->buffer_size, sizeof(version));
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), &version, buf_sz))
>> return -EFAULT;
>> return 0;
>> @@ -719,13 +719,15 @@ static int aie2_get_firmware_version(struct
>> amdxdna_client *client,
>> {
>> struct amdxdna_drm_query_firmware_version version;
>> struct amdxdna_dev *xdna = client->xdna;
>> + u32 buf_sz;
>> version.major = xdna->fw_ver.major;
>> version.minor = xdna->fw_ver.minor;
>> version.patch = xdna->fw_ver.sub;
>> version.build = xdna->fw_ver.build;
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), &version,
>> sizeof(version)))
>> + buf_sz = min(args->buffer_size, sizeof(version));
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), &version, buf_sz))
>> return -EFAULT;
>> return 0;
>> @@ -737,11 +739,13 @@ static int aie2_get_power_mode(struct
>> amdxdna_client *client,
>> struct amdxdna_drm_get_power_mode mode = {};
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_dev_hdl *ndev;
>> + u32 buf_sz;
>> ndev = xdna->dev_handle;
>> mode.power_mode = ndev->pw_mode;
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), &mode,
>> sizeof(mode)))
>> + buf_sz = min(args->buffer_size, sizeof(mode));
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), &mode, buf_sz))
>> return -EFAULT;
>> return 0;
>> @@ -754,6 +758,7 @@ static int aie2_get_clock_metadata(struct
>> amdxdna_client *client,
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_dev_hdl *ndev;
>> int ret = 0;
>> + u32 buf_sz;
>> ndev = xdna->dev_handle;
>> clock = kzalloc_obj(*clock);
>> @@ -766,7 +771,8 @@ static int aie2_get_clock_metadata(struct
>> amdxdna_client *client,
>> snprintf(clock->h_clock.name, sizeof(clock->h_clock.name), "H
>> Clock");
>> clock->h_clock.freq_mhz = ndev->hclk_freq;
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), clock,
>> sizeof(*clock)))
>> + buf_sz = min(args->buffer_size, sizeof(*clock));
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), clock, buf_sz))
>> ret = -EFAULT;
>> kfree(clock);
>> @@ -792,12 +798,14 @@ static int aie2_get_sensors(struct
>> amdxdna_client *client,
>> scnprintf(sensor.label, sizeof(sensor.label), "Total Power");
>> scnprintf(sensor.units, sizeof(sensor.units), "mW");
>> + if (args->buffer_size < sizeof(sensor))
>> + goto out;
>> +
>> if (copy_to_user(u64_to_user_ptr(args->buffer), &sensor,
>> sizeof(sensor)))
>> return -EFAULT;
>> + args->buffer_size -= sizeof(sensor);
>> sensors_count++;
>> - if (args->buffer_size <= sensors_count * sizeof(sensor))
>> - goto out;
>> for (i = 0; i < min_t(u32, ndev->total_col, 8); i++) {
>> memset(&sensor, 0, sizeof(sensor));
>> @@ -807,13 +815,15 @@ static int aie2_get_sensors(struct
>> amdxdna_client *client,
>> scnprintf(sensor.label, sizeof(sensor.label), "Column %d
>> Utilization", i);
>> scnprintf(sensor.units, sizeof(sensor.units), "%%");
>> + if (args->buffer_size < sizeof(sensor))
>> + goto out;
>> +
>> if (copy_to_user(u64_to_user_ptr(args->buffer) +
>> sensors_count * sizeof(sensor),
>> &sensor, sizeof(sensor)))
>> return -EFAULT;
>> + args->buffer_size -= sizeof(sensor);
>> sensors_count++;
>> - if (args->buffer_size <= sensors_count * sizeof(sensor))
>> - goto out;
>> }
>> out:
>> @@ -909,6 +919,7 @@ static int aie2_query_resource_info(struct
>> amdxdna_client *client,
>> const struct amdxdna_dev_priv *priv;
>> struct amdxdna_dev_hdl *ndev;
>> struct amdxdna_dev *xdna;
>> + u32 buf_sz;
>> xdna = client->xdna;
>> ndev = xdna->dev_handle;
>> @@ -920,7 +931,8 @@ static int aie2_query_resource_info(struct
>> amdxdna_client *client,
>> res_info.npu_tops_curr = ndev->curr_tops;
>> res_info.npu_task_curr = ndev->hwctx_num;
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), &res_info,
>> sizeof(res_info)))
>> + buf_sz = min(args->buffer_size, sizeof(res_info));
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), &res_info, buf_sz))
>> return -EFAULT;
>> return 0;
>> @@ -956,12 +968,7 @@ static int aie2_get_telemetry(struct
>> amdxdna_client *client,
>> XDNA_ERR(xdna, "Invalid buffer size");
>> return -EINVAL;
>> }
>> -
>> telemetry_data_sz = args->buffer_size - header_sz;
>> - if (telemetry_data_sz > SZ_4M) {
>> - XDNA_ERR(xdna, "Buffer size is too big, %d",
>> telemetry_data_sz);
>> - return -EINVAL;
>> - }
>> header = kzalloc(header_sz, GFP_KERNEL);
>> if (!header)
>> @@ -1002,6 +1009,7 @@ static int aie2_get_preempt_state(struct
>> amdxdna_client *client,
>> struct amdxdna_drm_attribute_state state = {};
>> struct amdxdna_dev *xdna = client->xdna;
>> struct amdxdna_dev_hdl *ndev;
>> + u32 buf_sz;
>> ndev = xdna->dev_handle;
>> if (args->param == DRM_AMDXDNA_GET_FORCE_PREEMPT_STATE)
>> @@ -1009,7 +1017,8 @@ static int aie2_get_preempt_state(struct
>> amdxdna_client *client,
>> else if (args->param ==
>> DRM_AMDXDNA_GET_FRAME_BOUNDARY_PREEMPT_STATE)
>> state.state = ndev->frame_boundary_preempt;
>> - if (copy_to_user(u64_to_user_ptr(args->buffer), &state,
>> sizeof(state)))
>> + buf_sz = min(args->buffer_size, sizeof(state));
>> + if (copy_to_user(u64_to_user_ptr(args->buffer), &state, buf_sz))
>> return -EFAULT;
>> return 0;
>
next prev parent reply other threads:[~2026-04-03 15:50 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 17:41 Lizhi Hou
2026-04-02 21:06 ` Mario Limonciello
2026-04-03 15:50 ` Lizhi Hou [this message]
2026-04-03 15:56 ` Mario Limonciello
2026-04-03 18:00 ` Lizhi Hou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=474ea416-ddde-88ed-1751-9960dcaef5a2@amd.com \
--to=lizhi.hou@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maciej.falkowski@linux.intel.com \
--cc=mario.limonciello@amd.com \
--cc=max.zhen@amd.com \
--cc=ogabbay@kernel.org \
--cc=quic_jhugo@quicinc.com \
--cc=sonal.santan@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®