Thank you for your contribution! Sashiko AI review found 3 potential issue(s) 
to consider:
- [High] cla_vma_fault() unconditionally assumes FAULT_FLAG_ALLOW_RETRY is set, 
triggering a WARN_ON and SIGBUS during normal per-VMA lock faults.
- [High] cla_vma_open() silently ignores errors from cla_ctx_map(), leading to 
a context refcount imbalance and a deterministic NULL pointer dereference.
- [Medium] Concurrent ioctl queries race with CPU hotplug device setup, leaking 
uninitialized or partially updated accelerator descriptors to userspace.
--

--- Patch [8]: [RFC PATCH v1 8/8] misc/arm-cla: Add userspace interface ---
commit 5559b4038bdef30d19e3f3c9904b6bfa29dc03ab
Author: Ryan Roberts <[email protected]>
Subject: misc/arm-cla: Add userspace interface

This commit adds a character device interface for the Arm CLA driver,
allowing userspace to enumerate hardware and map accelerator register frames.
It defines version 1 of the UAPI with a GET_PARAM ioctl for querying device
telemetry. Additionally, it implements shared read-write mmap support for
CLA register pages, utilizing a domain scheduler to resolve faults.

> diff --git a/drivers/misc/arm-cla/cla-user.c b/drivers/misc/arm-cla/cla-user.c
> new file mode 100644
> index 0000000000000..415328a653b7f
> --- /dev/null
> +++ b/drivers/misc/arm-cla/cla-user.c
[ ... ]
> @@ -0,0 +1,351 @@
[ ... ]
> +static long cla_ioctl_get_param(unsigned long arg)
> +{
[ ... ]
> +     case ARM_CLA_PARAM_DEV_ACCELS:
> +             param.value = cla_lut_pg[dev_id]->accelerators;
> +             break;
> +     case ARM_CLA_PARAM_ACCEL_IIDR:
> +             param.value = cla_lut_pg[dev_id]->accel_descs[accel_id].iidr;

[Severity: Medium]
Can concurrent ioctl queries race with CPU hotplug device setup here?

During CPU hotplug, cla_dev_setup() calls cla_dev_setup_accel() which
modifies accel_descs fields without holding dev->lock. 

Concurrently, userspace can invoke this ioctl and read these fields without
any locks or memory barriers.

Because there is no synchronization, could an out-of-order read see the
dev->accelerators bit set before the corresponding accel_descs fields are
visible, returning uninitialized or stale telemetry data to userspace?

> +             break;
> +     case ARM_CLA_PARAM_ACCEL_DEVARCH:
> +             param.value = cla_lut_pg[dev_id]->accel_descs[accel_id].devarch;
> +             break;
[ ... ]
> +static void cla_vma_open(struct vm_area_struct *vma)
> +{
> +     /*
> +      * A vma previously created with cla_file_mmap() has been duplicated
> +      * within the same mm (most likely due to mremap). While this could also
> +      * be called for duplication into a new mm (via fork), we set
> +      * VM_DONTCOPY on the original mmap, so this will never happen. So the
> +      * contexts covered by this new vma already exist.
> +      */
> +     struct cla_domain *domain;
> +
> +     cla_for_each_mapped_domain(vma, domain)
> +             cla_ctx_map(domain, vma->vm_mm, vma->vm_file);

[Severity: High]
Does this code need to check the return value of cla_ctx_map()?

If a VMA is duplicated (e.g., via mremap with MREMAP_MAYMOVE) and the
domain is in a broken state, cla_ctx_map() will return ERR_PTR(-EIO)
without incrementing the context refcount.

Because cla_vma_open() silently ignores this error, the refcount remains
unbalanced. When the old VMA is subsequently closed, cla_ctx_unmap() drops
the refcount to zero and frees the context.

When the new VMA is closed, cla_ctx_unmap() will fail to find the context:

drivers/misc/arm-cla/cla-ctx.c:cla_ctx_unmap() {
    ...
    ctx = cla_domain_lookup_ctx(domain, mm, file);
    WARN_ON(!ctx);

    if (!refcount_dec_and_test(&ctx->mapped)) {
    ...
}

Could this lead to an unconditional NULL pointer dereference of ctx?

> +}
> +
> +static void cla_vma_close(struct vm_area_struct *vma)
[ ... ]
> +static vm_fault_t cla_vma_fault(struct vm_fault *vmf)
> +{
> +     struct vm_area_struct *vma = vmf->vma;
> +     struct cla_domain *domain;
> +     struct cla_dev *dev;
> +     struct cla_ctx *ctx;
> +     unsigned long pg;
> +
> +     /*
> +      * Reassignment needs mmap_lock, so we cannot wait while holding it.
> +      * Luckily, this flag is only missing in some exotic cases which do not
> +      * apply for this VM_IO | VM_PFNMAP vma. i.e. GUP without
> +      * FOLL_UNLOCKABLE or FOLL_NOWAIT or fixup_user_fault(unlocked=NULL),
> +      * used by futex fault-in path.
> +      */
> +     if (WARN_ON(!(vmf->flags & FAULT_FLAG_ALLOW_RETRY)))
> +             return VM_FAULT_SIGBUS;

[Severity: High]
Is it safe to unconditionally assume FAULT_FLAG_ALLOW_RETRY is set here?

Under the per-VMA lock fault path (which is the default for modern kernels),
FAULT_FLAG_VMA_LOCK is set but FAULT_FLAG_ALLOW_RETRY is explicitly absent.

Consequently, any normal page fault handled under the VMA lock will hit this
branch, returning VM_FAULT_SIGBUS and breaking normal memory access.

Additionally, because this is user-controllable, could the WARN_ON allow an
unprivileged local attacker to spam the kernel log or crash the system if
panic_on_warn is enabled?

> +
> +     pg = vma->vm_pgoff + ((vmf->address - vma->vm_start) >> PAGE_SHIFT);
> +     dev = cla_lut_pg[pg];

-- 
Sashiko AI review ยท 
https://sashiko.dev/#/patchset/[email protected]?part=8

Reply via email to