Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+33 −29
Original line number Diff line number Diff line
@@ -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,
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_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,12 +395,11 @@ 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);
		break;
	case ACPI_TABLE_EVENT_LOAD:
@@ -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;