Commit 914c6194 authored by Lv Zheng's avatar Lv Zheng Committed by Rafael J. Wysocki

ACPI / sysfs: Update sysfs signature handling code

This patch cleans up sysfs table signature handling code:

 1. Convert the signature handling code to use the ACPICA APIs to
    benefit from the future improvements of the APIs.

 2. Add 'filename' attribute in order to handle both BE/LE name tags.

 3. Add instance check in order to avoid the possible buffer overflow
    related to the table file name.
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
[ rjw: Changelog ]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 307ecb0a
...@@ -314,10 +314,14 @@ static struct kobject *tables_kobj; ...@@ -314,10 +314,14 @@ static struct kobject *tables_kobj;
static struct kobject *dynamic_tables_kobj; static struct kobject *dynamic_tables_kobj;
static struct kobject *hotplug_kobj; static struct kobject *hotplug_kobj;
#define ACPI_MAX_TABLE_INSTANCES 999
#define ACPI_INST_SIZE 4 /* including trailing 0 */
struct acpi_table_attr { struct acpi_table_attr {
struct bin_attribute attr; struct bin_attribute attr;
char name[8]; char name[ACPI_NAME_SIZE];
int instance; int instance;
char filename[ACPI_NAME_SIZE+ACPI_INST_SIZE];
struct list_head node; struct list_head node;
}; };
...@@ -329,14 +333,9 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, ...@@ -329,14 +333,9 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
container_of(bin_attr, struct acpi_table_attr, attr); container_of(bin_attr, struct acpi_table_attr, attr);
struct acpi_table_header *table_header = NULL; struct acpi_table_header *table_header = NULL;
acpi_status status; acpi_status status;
char name[ACPI_NAME_SIZE];
if (strncmp(table_attr->name, "NULL", 4)) status = acpi_get_table(table_attr->name, table_attr->instance,
memcpy(name, table_attr->name, ACPI_NAME_SIZE); &table_header);
else
memcpy(name, "\0\0\0\0", 4);
status = acpi_get_table(name, table_attr->instance, &table_header);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENODEV; return -ENODEV;
...@@ -344,38 +343,45 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, ...@@ -344,38 +343,45 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
table_header, table_header->length); table_header, table_header->length);
} }
static void acpi_table_attr_init(struct acpi_table_attr *table_attr, static int acpi_table_attr_init(struct kobject *tables_obj,
struct acpi_table_header *table_header) struct acpi_table_attr *table_attr,
struct acpi_table_header *table_header)
{ {
struct acpi_table_header *header = NULL; struct acpi_table_header *header = NULL;
struct acpi_table_attr *attr = NULL; struct acpi_table_attr *attr = NULL;
char instance_str[ACPI_INST_SIZE];
sysfs_attr_init(&table_attr->attr.attr); sysfs_attr_init(&table_attr->attr.attr);
if (table_header->signature[0] != '\0') ACPI_MOVE_NAME(table_attr->name, table_header->signature);
memcpy(table_attr->name, table_header->signature,
ACPI_NAME_SIZE);
else
memcpy(table_attr->name, "NULL", 4);
list_for_each_entry(attr, &acpi_table_attr_list, node) { list_for_each_entry(attr, &acpi_table_attr_list, node) {
if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) if (ACPI_COMPARE_NAME(table_attr->name, attr->name))
if (table_attr->instance < attr->instance) if (table_attr->instance < attr->instance)
table_attr->instance = attr->instance; table_attr->instance = attr->instance;
} }
table_attr->instance++; table_attr->instance++;
if (table_attr->instance > ACPI_MAX_TABLE_INSTANCES) {
pr_warn("%4.4s: too many table instances\n",
table_attr->name);
return -ERANGE;
}
ACPI_MOVE_NAME(table_attr->filename, table_header->signature);
table_attr->filename[ACPI_NAME_SIZE] = '\0';
if (table_attr->instance > 1 || (table_attr->instance == 1 && if (table_attr->instance > 1 || (table_attr->instance == 1 &&
!acpi_get_table !acpi_get_table
(table_header->signature, 2, &header))) (table_header->signature, 2, &header))) {
sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", snprintf(instance_str, sizeof(instance_str), "%u",
table_attr->instance); table_attr->instance);
strcat(table_attr->filename, instance_str);
}
table_attr->attr.size = table_header->length; table_attr->attr.size = table_header->length;
table_attr->attr.read = acpi_table_show; table_attr->attr.read = acpi_table_show;
table_attr->attr.attr.name = table_attr->name; table_attr->attr.attr.name = table_attr->filename;
table_attr->attr.attr.mode = 0400; table_attr->attr.attr.mode = 0400;
return; return sysfs_create_bin_file(tables_obj, &table_attr->attr);
} }
acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context) acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)
...@@ -389,13 +395,12 @@ acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context) ...@@ -389,13 +395,12 @@ acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)
if (!table_attr) if (!table_attr)
return AE_NO_MEMORY; return AE_NO_MEMORY;
acpi_table_attr_init(table_attr, table); if (acpi_table_attr_init(dynamic_tables_kobj,
if (sysfs_create_bin_file(dynamic_tables_kobj, table_attr, table)) {
&table_attr->attr)) {
kfree(table_attr); kfree(table_attr);
return AE_ERROR; return AE_ERROR;
} else }
list_add_tail(&table_attr->node, &acpi_table_attr_list); list_add_tail(&table_attr->node, &acpi_table_attr_list);
break; break;
case ACPI_TABLE_EVENT_LOAD: case ACPI_TABLE_EVENT_LOAD:
case ACPI_TABLE_EVENT_UNLOAD: case ACPI_TABLE_EVENT_UNLOAD:
...@@ -437,13 +442,12 @@ static int acpi_tables_sysfs_init(void) ...@@ -437,13 +442,12 @@ static int acpi_tables_sysfs_init(void)
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
continue; continue;
table_attr = NULL;
table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL); table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);
if (!table_attr) if (!table_attr)
return -ENOMEM; return -ENOMEM;
acpi_table_attr_init(table_attr, table_header); ret = acpi_table_attr_init(tables_kobj,
ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr); table_attr, table_header);
if (ret) { if (ret) {
kfree(table_attr); kfree(table_attr);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment