| From 25c22becae31d5d385f7b8695b4fbc13bab0b856 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 22 Jun 2021 18:38:01 -0700 |
| Subject: ACPI: bgrt: Fix CFI violation |
| |
| From: Nathan Chancellor <nathan@kernel.org> |
| |
| [ Upstream commit f37ccf8fce155d08ae2a4fb3db677911ced0c21a ] |
| |
| clang's Control Flow Integrity requires that every indirect call has a |
| valid target, which is based on the type of the function pointer. The |
| *_show() functions in this file are written as if they will be called |
| from dev_attr_show(); however, they will be called from |
| sysfs_kf_seq_show() because the files were created by |
| sysfs_create_group() and the sysfs ops are based on kobj_sysfs_ops |
| because of kobject_add_and_create(). Because the *_show() functions do |
| not match the type of the show() member in struct kobj_attribute, there |
| is a CFI violation. |
| |
| $ cat /sys/firmware/acpi/bgrt/{status,type,version,{x,y}offset}} |
| 1 |
| 0 |
| 1 |
| 522 |
| 307 |
| |
| $ dmesg | grep "CFI failure" |
| [ 267.761825] CFI failure (target: type_show.d5e1ad21498a5fd14edbc5c320906598.cfi_jt+0x0/0x8): |
| [ 267.762246] CFI failure (target: xoffset_show.d5e1ad21498a5fd14edbc5c320906598.cfi_jt+0x0/0x8): |
| [ 267.762584] CFI failure (target: status_show.d5e1ad21498a5fd14edbc5c320906598.cfi_jt+0x0/0x8): |
| [ 267.762973] CFI failure (target: yoffset_show.d5e1ad21498a5fd14edbc5c320906598.cfi_jt+0x0/0x8): |
| [ 267.763330] CFI failure (target: version_show.d5e1ad21498a5fd14edbc5c320906598.cfi_jt+0x0/0x8): |
| |
| Convert these functions to the type of the show() member in struct |
| kobj_attribute so that there is no more CFI violation. Because these |
| functions are all so similar, combine them into a macro. |
| |
| Fixes: d1ff4b1cdbab ("ACPI: Add support for exposing BGRT data") |
| Link: https://github.com/ClangBuiltLinux/linux/issues/1406 |
| Signed-off-by: Nathan Chancellor <nathan@kernel.org> |
| Reviewed-by: Kees Cook <keescook@chromium.org> |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/acpi/bgrt.c | 57 ++++++++++++++------------------------------- |
| 1 file changed, 18 insertions(+), 39 deletions(-) |
| |
| diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c |
| index 19bb7f870204..e0d14017706e 100644 |
| --- a/drivers/acpi/bgrt.c |
| +++ b/drivers/acpi/bgrt.c |
| @@ -15,40 +15,19 @@ |
| static void *bgrt_image; |
| static struct kobject *bgrt_kobj; |
| |
| -static ssize_t version_show(struct device *dev, |
| - struct device_attribute *attr, char *buf) |
| -{ |
| - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.version); |
| -} |
| -static DEVICE_ATTR_RO(version); |
| - |
| -static ssize_t status_show(struct device *dev, |
| - struct device_attribute *attr, char *buf) |
| -{ |
| - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.status); |
| -} |
| -static DEVICE_ATTR_RO(status); |
| - |
| -static ssize_t type_show(struct device *dev, |
| - struct device_attribute *attr, char *buf) |
| -{ |
| - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_type); |
| -} |
| -static DEVICE_ATTR_RO(type); |
| - |
| -static ssize_t xoffset_show(struct device *dev, |
| - struct device_attribute *attr, char *buf) |
| -{ |
| - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_x); |
| -} |
| -static DEVICE_ATTR_RO(xoffset); |
| - |
| -static ssize_t yoffset_show(struct device *dev, |
| - struct device_attribute *attr, char *buf) |
| -{ |
| - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_y); |
| -} |
| -static DEVICE_ATTR_RO(yoffset); |
| +#define BGRT_SHOW(_name, _member) \ |
| + static ssize_t _name##_show(struct kobject *kobj, \ |
| + struct kobj_attribute *attr, char *buf) \ |
| + { \ |
| + return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab._member); \ |
| + } \ |
| + struct kobj_attribute bgrt_attr_##_name = __ATTR_RO(_name) |
| + |
| +BGRT_SHOW(version, version); |
| +BGRT_SHOW(status, status); |
| +BGRT_SHOW(type, image_type); |
| +BGRT_SHOW(xoffset, image_offset_x); |
| +BGRT_SHOW(yoffset, image_offset_y); |
| |
| static ssize_t image_read(struct file *file, struct kobject *kobj, |
| struct bin_attribute *attr, char *buf, loff_t off, size_t count) |
| @@ -60,11 +39,11 @@ static ssize_t image_read(struct file *file, struct kobject *kobj, |
| static BIN_ATTR_RO(image, 0); /* size gets filled in later */ |
| |
| static struct attribute *bgrt_attributes[] = { |
| - &dev_attr_version.attr, |
| - &dev_attr_status.attr, |
| - &dev_attr_type.attr, |
| - &dev_attr_xoffset.attr, |
| - &dev_attr_yoffset.attr, |
| + &bgrt_attr_version.attr, |
| + &bgrt_attr_status.attr, |
| + &bgrt_attr_type.attr, |
| + &bgrt_attr_xoffset.attr, |
| + &bgrt_attr_yoffset.attr, |
| NULL, |
| }; |
| |
| -- |
| 2.30.2 |
| |