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: Lv Zheng <lv.zheng@intel.com> [ rjw: Changelog ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
307ecb0aa3
commit
914c619409
|
@ -314,10 +314,14 @@ static struct kobject *tables_kobj;
|
|||
static struct kobject *dynamic_tables_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 bin_attribute attr;
|
||||
char name[8];
|
||||
char name[ACPI_NAME_SIZE];
|
||||
int instance;
|
||||
char filename[ACPI_NAME_SIZE+ACPI_INST_SIZE];
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
struct acpi_table_header *table_header = NULL;
|
||||
acpi_status status;
|
||||
char name[ACPI_NAME_SIZE];
|
||||
|
||||
if (strncmp(table_attr->name, "NULL", 4))
|
||||
memcpy(name, table_attr->name, ACPI_NAME_SIZE);
|
||||
else
|
||||
memcpy(name, "\0\0\0\0", 4);
|
||||
|
||||
status = acpi_get_table(name, table_attr->instance, &table_header);
|
||||
status = acpi_get_table(table_attr->name, table_attr->instance,
|
||||
&table_header);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -344,38 +343,45 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
|
|||
table_header, table_header->length);
|
||||
}
|
||||
|
||||
static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
|
||||
struct acpi_table_header *table_header)
|
||||
static int acpi_table_attr_init(struct kobject *tables_obj,
|
||||
struct acpi_table_attr *table_attr,
|
||||
struct acpi_table_header *table_header)
|
||||
{
|
||||
struct acpi_table_header *header = NULL;
|
||||
struct acpi_table_attr *attr = NULL;
|
||||
char instance_str[ACPI_INST_SIZE];
|
||||
|
||||
sysfs_attr_init(&table_attr->attr.attr);
|
||||
if (table_header->signature[0] != '\0')
|
||||
memcpy(table_attr->name, table_header->signature,
|
||||
ACPI_NAME_SIZE);
|
||||
else
|
||||
memcpy(table_attr->name, "NULL", 4);
|
||||
ACPI_MOVE_NAME(table_attr->name, table_header->signature);
|
||||
|
||||
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)
|
||||
table_attr->instance = 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 &&
|
||||
!acpi_get_table
|
||||
(table_header->signature, 2, &header)))
|
||||
sprintf(table_attr->name + ACPI_NAME_SIZE, "%d",
|
||||
table_attr->instance);
|
||||
(table_header->signature, 2, &header))) {
|
||||
snprintf(instance_str, sizeof(instance_str), "%u",
|
||||
table_attr->instance);
|
||||
strcat(table_attr->filename, instance_str);
|
||||
}
|
||||
|
||||
table_attr->attr.size = table_header->length;
|
||||
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;
|
||||
|
||||
return;
|
||||
return sysfs_create_bin_file(tables_obj, &table_attr->attr);
|
||||
}
|
||||
|
||||
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)
|
||||
return AE_NO_MEMORY;
|
||||
|
||||
acpi_table_attr_init(table_attr, table);
|
||||
if (sysfs_create_bin_file(dynamic_tables_kobj,
|
||||
&table_attr->attr)) {
|
||||
if (acpi_table_attr_init(dynamic_tables_kobj,
|
||||
table_attr, table)) {
|
||||
kfree(table_attr);
|
||||
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;
|
||||
case ACPI_TABLE_EVENT_LOAD:
|
||||
case ACPI_TABLE_EVENT_UNLOAD:
|
||||
|
@ -437,13 +442,12 @@ static int acpi_tables_sysfs_init(void)
|
|||
if (ACPI_FAILURE(status))
|
||||
continue;
|
||||
|
||||
table_attr = NULL;
|
||||
table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);
|
||||
if (!table_attr)
|
||||
return -ENOMEM;
|
||||
|
||||
acpi_table_attr_init(table_attr, table_header);
|
||||
ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr);
|
||||
ret = acpi_table_attr_init(tables_kobj,
|
||||
table_attr, table_header);
|
||||
if (ret) {
|
||||
kfree(table_attr);
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue