diff options
| author | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2026-09-04 10:43:19 +0200 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-09-04 07:58:36 -0700 |
| commit | 6668ed271eaefaa63e686bdfbedaeb7b8e492722 (patch) | |
| tree | 58e8288fead484f6755ad0815fc74c3742663761 /drivers/iommu/iommu-sysfs.c | |
| download | linux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.tar.gz linux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.zip | |
selftests/bpf: Reject graph kptr use after RCU unlockgrafted
Add a sleepable verifier test that loads a graph-node local kptr in an
explicit RCU read-side critical section, then passes its node to
bpf_rbtree_remove() after the section ends.
Before the verifier fix, the stale NON_OWN_REF flag makes the node look like
a live borrowed reference and the program is accepted. After the fix, the
pointer is demoted without NON_OWN_REF and the graph kfunc argument is
rejected.
Also exercise a graph kptr loaded while a spin lock provides implicit RCU
protection. The pointer must be invalidated when the lock is released, which
guards the required ordering between non-owning-reference invalidation and
RCU demotion.
Update the existing fault-protected load test state description. The
post-unlock pointer no longer carries NON_OWN_REF, but remains readable
because the load is rewritten to use BPF_PROBE_MEM.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904084325.52250-7-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'drivers/iommu/iommu-sysfs.c')
| -rw-r--r-- | drivers/iommu/iommu-sysfs.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c new file mode 100644 index 000000000..937d1c749 --- /dev/null +++ b/drivers/iommu/iommu-sysfs.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * IOMMU sysfs class support + * + * Copyright (C) 2014 Red Hat, Inc. All rights reserved. + * Author: Alex Williamson <alex.williamson@redhat.com> + */ + +#include <linux/device.h> +#include <linux/iommu.h> +#include <linux/init.h> +#include <linux/slab.h> + +/* + * We provide a common class "devices" group which initially has no attributes. + * As devices are added to the IOMMU, we'll add links to the group. + */ +static struct attribute *devices_attr[] = { + NULL, +}; + +static const struct attribute_group devices_attr_group = { + .name = "devices", + .attrs = devices_attr, +}; + +static const struct attribute_group *dev_groups[] = { + &devices_attr_group, + NULL, +}; + +static void release_device(struct device *dev) +{ + kfree(dev); +} + +static const struct class iommu_class = { + .name = "iommu", + .dev_release = release_device, + .dev_groups = dev_groups, +}; + +static int __init iommu_dev_init(void) +{ + return class_register(&iommu_class); +} +postcore_initcall(iommu_dev_init); + +/* + * Init the struct device for the IOMMU. IOMMU specific attributes can + * be provided as an attribute group, allowing a unique namespace per + * IOMMU type. + */ +int iommu_device_sysfs_add(struct iommu_device *iommu, + struct device *parent, + const struct attribute_group **groups, + const char *fmt, ...) +{ + va_list vargs; + int ret; + + iommu->dev = kzalloc_obj(*iommu->dev); + if (!iommu->dev) + return -ENOMEM; + + device_initialize(iommu->dev); + + iommu->dev->class = &iommu_class; + iommu->dev->parent = parent; + iommu->dev->groups = groups; + + va_start(vargs, fmt); + ret = kobject_set_name_vargs(&iommu->dev->kobj, fmt, vargs); + va_end(vargs); + if (ret) + goto error; + + ret = device_add(iommu->dev); + if (ret) + goto error; + + dev_set_drvdata(iommu->dev, iommu); + + return 0; + +error: + put_device(iommu->dev); + return ret; +} +EXPORT_SYMBOL_GPL(iommu_device_sysfs_add); + +void iommu_device_sysfs_remove(struct iommu_device *iommu) +{ + dev_set_drvdata(iommu->dev, NULL); + device_unregister(iommu->dev); + iommu->dev = NULL; +} +EXPORT_SYMBOL_GPL(iommu_device_sysfs_remove); + +/* + * IOMMU drivers can indicate a device is managed by a given IOMMU using + * this interface. A link to the device will be created in the "devices" + * directory of the IOMMU device in sysfs and an "iommu" link will be + * created under the linked device, pointing back at the IOMMU device. + */ +int iommu_device_link(struct iommu_device *iommu, struct device *link) +{ + int ret; + + ret = sysfs_add_link_to_group(&iommu->dev->kobj, "devices", + &link->kobj, dev_name(link)); + if (ret) + return ret; + + ret = sysfs_create_link_nowarn(&link->kobj, &iommu->dev->kobj, "iommu"); + if (ret) + sysfs_remove_link_from_group(&iommu->dev->kobj, "devices", + dev_name(link)); + + return ret; +} + +void iommu_device_unlink(struct iommu_device *iommu, struct device *link) +{ + sysfs_remove_link(&link->kobj, "iommu"); + sysfs_remove_link_from_group(&iommu->dev->kobj, "devices", dev_name(link)); +} |
