When booting with CONFIG_CFI_CLANG, there are numerous violations when accessing the files under /sys/devices/pci0000:00/0000:00:02.0/drm/card0/gt/gt0: $ cd /sys/devices/pci0000:00/0000:00:02.0/drm/card0/gt/gt0 $ grep . * id:0 punit_req_freq_mhz:350 rc6_enable:1 rc6_residency_ms:214934 rps_act_freq_mhz:1300 rps_boost_freq_mhz:1300 rps_cur_freq_mhz:350 rps_max_freq_mhz:1300 rps_min_freq_mhz:350 rps_RP0_freq_mhz:1300 rps_RP1_freq_mhz:350 rps_RPn_freq_mhz:350 throttle_reason_pl1:0 throttle_reason_pl2:0 throttle_reason_pl4:0 throttle_reason_prochot:0 throttle_reason_ratl:0 throttle_reason_status:0 throttle_reason_thermal:0 throttle_reason_vr_tdc:0 throttle_reason_vr_thermalert:0 $ sudo dmesg &| grep "CFI failure at" [ 214.595903] CFI failure at kobj_attr_show+0x19/0x30 (target: id_show+0x0/0x70 [i915]; expected type: 0xc527b809) [ 214.596064] CFI failure at kobj_attr_show+0x19/0x30 (target: punit_req_freq_mhz_show+0x0/0x40 [i915]; expected type: 0xc527b809) [ 214.596407] CFI failure at kobj_attr_show+0x19/0x30 (target: rc6_enable_show+0x0/0x40 [i915]; expected type: 0xc527b809) [ 214.596528] CFI failure at kobj_attr_show+0x19/0x30 (target: rc6_residency_ms_show+0x0/0x270 [i915]; expected type: 0xc527b809) [ 214.596682] CFI failure at kobj_attr_show+0x19/0x30 (target: act_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.596792] CFI failure at kobj_attr_show+0x19/0x30 (target: boost_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.596893] CFI failure at kobj_attr_show+0x19/0x30 (target: cur_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.596996] CFI failure at kobj_attr_show+0x19/0x30 (target: max_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.597099] CFI failure at kobj_attr_show+0x19/0x30 (target: min_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.597198] CFI failure at kobj_attr_show+0x19/0x30 (target: RP0_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.597301] CFI failure at kobj_attr_show+0x19/0x30 (target: RP1_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.597405] CFI failure at kobj_attr_show+0x19/0x30 (target: RPn_freq_mhz_show+0x0/0xe0 [i915]; expected type: 0xc527b809) [ 214.597538] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.597701] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.597836] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.597952] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.598071] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.598177] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.598307] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.598439] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) [ 214.598542] CFI failure at kobj_attr_show+0x19/0x30 (target: throttle_reason_bool_show+0x0/0x50 [i915]; expected type: 0xc527b809) With kCFI, indirect calls are validated against their expected type versus actual type and failures occur when the two types do not match. The ultimate issue is that these sysfs functions are expecting to be called via dev_attr_show() but they may also be called via kobj_attr_show(), as certain files are created under two different kobjects that have two different sysfs_ops in intel_gt_sysfs_register(), hence the warnings above. When accessing the gt_ files under /sys/devices/pci0000:00/0000:00:02.0/drm/card0, which are using the same sysfs functions, there are no violations, meaning the functions are being called with the proper type. To make everything work properly, adjust certain functions to match the type of the ->show() and ->store() members in 'struct kobj_attribute'. Add a macro to generate functions for that can be called via both dev_attr_{show,store}() or kobj_attr_{show,store}() so that they can be called through both kobject locations without violating kCFI and adjust the attribute groups to account for this. Link: https://github.com/ClangBuiltLinux/linux/issues/1716 Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com> Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Nathan Chancellor <nathan@kernel.org> Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20221013205909.1282545-1-nathan@kernel.org
116 lines
2.7 KiB
C
116 lines
2.7 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright © 2022 Intel Corporation
|
|
*/
|
|
|
|
#include <drm/drm_device.h>
|
|
#include <linux/device.h>
|
|
#include <linux/kobject.h>
|
|
#include <linux/printk.h>
|
|
#include <linux/sysfs.h>
|
|
|
|
#include "i915_drv.h"
|
|
#include "i915_sysfs.h"
|
|
#include "intel_gt.h"
|
|
#include "intel_gt_sysfs.h"
|
|
#include "intel_gt_sysfs_pm.h"
|
|
#include "intel_gt_types.h"
|
|
#include "intel_rc6.h"
|
|
|
|
bool is_object_gt(struct kobject *kobj)
|
|
{
|
|
return !strncmp(kobj->name, "gt", 2);
|
|
}
|
|
|
|
struct intel_gt *intel_gt_sysfs_get_drvdata(struct kobject *kobj,
|
|
const char *name)
|
|
{
|
|
/*
|
|
* We are interested at knowing from where the interface
|
|
* has been called, whether it's called from gt/ or from
|
|
* the parent directory.
|
|
* From the interface position it depends also the value of
|
|
* the private data.
|
|
* If the interface is called from gt/ then private data is
|
|
* of the "struct intel_gt *" type, otherwise it's * a
|
|
* "struct drm_i915_private *" type.
|
|
*/
|
|
if (!is_object_gt(kobj)) {
|
|
struct device *dev = kobj_to_dev(kobj);
|
|
struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
|
|
|
|
return to_gt(i915);
|
|
}
|
|
|
|
return kobj_to_gt(kobj);
|
|
}
|
|
|
|
static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
|
|
{
|
|
return >->i915->drm.primary->kdev->kobj;
|
|
}
|
|
|
|
static ssize_t id_show(struct kobject *kobj,
|
|
struct kobj_attribute *attr,
|
|
char *buf)
|
|
{
|
|
struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
|
|
|
|
return sysfs_emit(buf, "%u\n", gt->info.id);
|
|
}
|
|
static struct kobj_attribute attr_id = __ATTR_RO(id);
|
|
|
|
static struct attribute *id_attrs[] = {
|
|
&attr_id.attr,
|
|
NULL,
|
|
};
|
|
ATTRIBUTE_GROUPS(id);
|
|
|
|
/* A kobject needs a release() method even if it does nothing */
|
|
static void kobj_gt_release(struct kobject *kobj)
|
|
{
|
|
}
|
|
|
|
static struct kobj_type kobj_gt_type = {
|
|
.release = kobj_gt_release,
|
|
.sysfs_ops = &kobj_sysfs_ops,
|
|
.default_groups = id_groups,
|
|
};
|
|
|
|
void intel_gt_sysfs_register(struct intel_gt *gt)
|
|
{
|
|
/*
|
|
* We need to make things right with the
|
|
* ABI compatibility. The files were originally
|
|
* generated under the parent directory.
|
|
*
|
|
* We generate the files only for gt 0
|
|
* to avoid duplicates.
|
|
*/
|
|
if (gt_is_root(gt))
|
|
intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
|
|
|
|
/* init and xfer ownership to sysfs tree */
|
|
if (kobject_init_and_add(>->sysfs_gt, &kobj_gt_type,
|
|
gt->i915->sysfs_gt, "gt%d", gt->info.id))
|
|
goto exit_fail;
|
|
|
|
gt->sysfs_defaults = kobject_create_and_add(".defaults", >->sysfs_gt);
|
|
if (!gt->sysfs_defaults)
|
|
goto exit_fail;
|
|
|
|
intel_gt_sysfs_pm_init(gt, >->sysfs_gt);
|
|
|
|
return;
|
|
|
|
exit_fail:
|
|
kobject_put(>->sysfs_gt);
|
|
drm_warn(>->i915->drm,
|
|
"failed to initialize gt%d sysfs root\n", gt->info.id);
|
|
}
|
|
|
|
void intel_gt_sysfs_unregister(struct intel_gt *gt)
|
|
{
|
|
kobject_put(gt->sysfs_defaults);
|
|
kobject_put(>->sysfs_gt);
|
|
}
|