cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

passobj-attributes.c (5248B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Functions corresponding to password object type attributes under BIOS Password Object GUID for
      4 * use with dell-wmi-sysman
      5 *
      6 *  Copyright (c) 2020 Dell Inc.
      7 */
      8
      9#include "dell-wmi-sysman.h"
     10
     11enum po_properties {IS_PASS_SET = 1, MIN_PASS_LEN, MAX_PASS_LEN};
     12
     13get_instance_id(po);
     14
     15static ssize_t is_enabled_show(struct kobject *kobj, struct kobj_attribute *attr,
     16					  char *buf)
     17{
     18	int instance_id = get_po_instance_id(kobj);
     19	union acpi_object *obj;
     20	ssize_t ret;
     21
     22	if (instance_id < 0)
     23		return instance_id;
     24
     25	/* need to use specific instance_id and guid combination to get right data */
     26	obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_PASSOBJ_ATTRIBUTE_GUID);
     27	if (!obj)
     28		return -EIO;
     29	if (obj->package.elements[IS_PASS_SET].type != ACPI_TYPE_INTEGER) {
     30		kfree(obj);
     31		return -EINVAL;
     32	}
     33	ret = snprintf(buf, PAGE_SIZE, "%lld\n", obj->package.elements[IS_PASS_SET].integer.value);
     34	kfree(obj);
     35	return ret;
     36}
     37
     38static struct kobj_attribute po_is_pass_set = __ATTR_RO(is_enabled);
     39
     40static ssize_t current_password_store(struct kobject *kobj,
     41				      struct kobj_attribute *attr,
     42				      const char *buf, size_t count)
     43{
     44	char *target = NULL;
     45	int length;
     46
     47	length = strlen(buf);
     48	if (buf[length-1] == '\n')
     49		length--;
     50
     51	/* firmware does verifiation of min/max password length,
     52	 * hence only check for not exceeding MAX_BUFF here.
     53	 */
     54	if (length >= MAX_BUFF)
     55		return -EINVAL;
     56
     57	if (strcmp(kobj->name, "Admin") == 0)
     58		target = wmi_priv.current_admin_password;
     59	else if (strcmp(kobj->name, "System") == 0)
     60		target = wmi_priv.current_system_password;
     61	if (!target)
     62		return -EIO;
     63	memcpy(target, buf, length);
     64	target[length] = '\0';
     65
     66	return count;
     67}
     68
     69static struct kobj_attribute po_current_password = __ATTR_WO(current_password);
     70
     71static ssize_t new_password_store(struct kobject *kobj,
     72				  struct kobj_attribute *attr,
     73				  const char *buf, size_t count)
     74{
     75	char *p, *buf_cp;
     76	int ret;
     77
     78	buf_cp = kstrdup(buf, GFP_KERNEL);
     79	if (!buf_cp)
     80		return -ENOMEM;
     81	p = memchr(buf_cp, '\n', count);
     82
     83	if (p != NULL)
     84		*p = '\0';
     85	if (strlen(buf_cp) > MAX_BUFF) {
     86		ret = -EINVAL;
     87		goto out;
     88	}
     89
     90	ret = set_new_password(kobj->name, buf_cp);
     91
     92out:
     93	kfree(buf_cp);
     94	return ret ? ret : count;
     95}
     96
     97static struct kobj_attribute po_new_password = __ATTR_WO(new_password);
     98
     99attribute_n_property_show(min_password_length, po);
    100static struct kobj_attribute po_min_pass_length = __ATTR_RO(min_password_length);
    101
    102attribute_n_property_show(max_password_length, po);
    103static struct kobj_attribute po_max_pass_length = __ATTR_RO(max_password_length);
    104
    105static ssize_t mechanism_show(struct kobject *kobj, struct kobj_attribute *attr,
    106			 char *buf)
    107{
    108	return sprintf(buf, "password\n");
    109}
    110
    111static struct kobj_attribute po_mechanism = __ATTR_RO(mechanism);
    112
    113static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr,
    114			 char *buf)
    115{
    116	if (strcmp(kobj->name, "Admin") == 0)
    117		return sprintf(buf, "bios-admin\n");
    118	else if (strcmp(kobj->name, "System") == 0)
    119		return sprintf(buf, "power-on\n");
    120	return -EIO;
    121}
    122
    123static struct kobj_attribute po_role = __ATTR_RO(role);
    124
    125static struct attribute *po_attrs[] = {
    126	&po_is_pass_set.attr,
    127	&po_min_pass_length.attr,
    128	&po_max_pass_length.attr,
    129	&po_current_password.attr,
    130	&po_new_password.attr,
    131	&po_role.attr,
    132	&po_mechanism.attr,
    133	NULL,
    134};
    135
    136static const struct attribute_group po_attr_group = {
    137	.attrs = po_attrs,
    138};
    139
    140int alloc_po_data(void)
    141{
    142	int ret = 0;
    143
    144	wmi_priv.po_instances_count = get_instance_count(DELL_WMI_BIOS_PASSOBJ_ATTRIBUTE_GUID);
    145	wmi_priv.po_data = kcalloc(wmi_priv.po_instances_count, sizeof(struct po_data), GFP_KERNEL);
    146	if (!wmi_priv.po_data) {
    147		wmi_priv.po_instances_count = 0;
    148		ret = -ENOMEM;
    149	}
    150	return ret;
    151}
    152
    153/**
    154 * populate_po_data() - Populate all properties of an instance under password object attribute
    155 * @po_obj: ACPI object with password object data
    156 * @instance_id: The instance to enumerate
    157 * @attr_name_kobj: The parent kernel object
    158 */
    159int populate_po_data(union acpi_object *po_obj, int instance_id, struct kobject *attr_name_kobj)
    160{
    161	wmi_priv.po_data[instance_id].attr_name_kobj = attr_name_kobj;
    162	if (check_property_type(po, ATTR_NAME, ACPI_TYPE_STRING))
    163		return -EINVAL;
    164	strlcpy_attr(wmi_priv.po_data[instance_id].attribute_name,
    165		     po_obj[ATTR_NAME].string.pointer);
    166	if (check_property_type(po, MIN_PASS_LEN, ACPI_TYPE_INTEGER))
    167		return -EINVAL;
    168	wmi_priv.po_data[instance_id].min_password_length =
    169		(uintptr_t)po_obj[MIN_PASS_LEN].string.pointer;
    170	if (check_property_type(po, MAX_PASS_LEN, ACPI_TYPE_INTEGER))
    171		return -EINVAL;
    172	wmi_priv.po_data[instance_id].max_password_length =
    173		(uintptr_t) po_obj[MAX_PASS_LEN].string.pointer;
    174
    175	return sysfs_create_group(attr_name_kobj, &po_attr_group);
    176}
    177
    178/**
    179 * exit_po_attributes() - Clear all attribute data
    180 *
    181 * Clears all data allocated for this group of attributes
    182 */
    183void exit_po_attributes(void)
    184{
    185	int instance_id;
    186
    187	for (instance_id = 0; instance_id < wmi_priv.po_instances_count; instance_id++) {
    188		if (wmi_priv.po_data[instance_id].attr_name_kobj)
    189			sysfs_remove_group(wmi_priv.po_data[instance_id].attr_name_kobj,
    190								&po_attr_group);
    191	}
    192	wmi_priv.po_instances_count = 0;
    193
    194	kfree(wmi_priv.po_data);
    195	wmi_priv.po_data = NULL;
    196}