brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · 86ec962 Raw
153 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Functions corresponding to SET password methods under BIOS attributes interface GUID4 *5 *  Copyright (c) 2020 Dell Inc.6 */7 8#include <linux/wmi.h>9#include "dell-wmi-sysman.h"10 11static int call_password_interface(struct wmi_device *wdev, char *in_args, size_t size)12{13	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};14	struct acpi_buffer input;15	union acpi_object *obj;16	acpi_status status;17	int ret = -EIO;18 19	input.length =  (acpi_size) size;20	input.pointer = in_args;21	status = wmidev_evaluate_method(wdev, 0, 1, &input, &output);22	if (ACPI_FAILURE(status))23		return -EIO;24	obj = (union acpi_object *)output.pointer;25	if (obj->type == ACPI_TYPE_INTEGER)26		ret = obj->integer.value;27 28	kfree(output.pointer);29	/* let userland know it may need to check is_password_set again */30	kobject_uevent(&wmi_priv.class_dev->kobj, KOBJ_CHANGE);31	return map_wmi_error(ret);32}33 34/**35 * set_new_password() - Sets a system admin password36 * @password_type: The type of password to set37 * @new: The new password38 *39 * Sets the password using plaintext interface40 */41int set_new_password(const char *password_type, const char *new)42{43	size_t password_type_size, current_password_size, new_size;44	size_t security_area_size, buffer_size;45	char *buffer = NULL, *start;46	char *current_password;47	int ret;48 49	mutex_lock(&wmi_priv.mutex);50	if (!wmi_priv.password_attr_wdev) {51		ret = -ENODEV;52		goto out;53	}54	if (strcmp(password_type, "Admin") == 0) {55		current_password = wmi_priv.current_admin_password;56	} else if (strcmp(password_type, "System") == 0) {57		current_password = wmi_priv.current_system_password;58	} else {59		ret = -EINVAL;60		dev_err(&wmi_priv.password_attr_wdev->dev, "unknown password type %s\n",61			password_type);62		goto out;63	}64 65	/* build/calculate buffer */66	security_area_size = calculate_security_buffer(wmi_priv.current_admin_password);67	password_type_size = calculate_string_buffer(password_type);68	current_password_size = calculate_string_buffer(current_password);69	new_size = calculate_string_buffer(new);70	buffer_size = security_area_size + password_type_size + current_password_size + new_size;71	buffer = kzalloc(buffer_size, GFP_KERNEL);72	if (!buffer) {73		ret = -ENOMEM;74		goto out;75	}76 77	/* build security area */78	populate_security_buffer(buffer, wmi_priv.current_admin_password);79 80	/* build variables to set */81	start = buffer + security_area_size;82	ret = populate_string_buffer(start, password_type_size, password_type);83	if (ret < 0)84		goto out;85 86	start += ret;87	ret = populate_string_buffer(start, current_password_size, current_password);88	if (ret < 0)89		goto out;90 91	start += ret;92	ret = populate_string_buffer(start, new_size, new);93	if (ret < 0)94		goto out;95 96	print_hex_dump_bytes("set new password data: ", DUMP_PREFIX_NONE, buffer, buffer_size);97	ret = call_password_interface(wmi_priv.password_attr_wdev, buffer, buffer_size);98	/* on success copy the new password to current password */99	if (!ret)100		strscpy(current_password, new, MAX_BUFF);101	/* explain to user the detailed failure reason */102	else if (ret == -EOPNOTSUPP)103		dev_err(&wmi_priv.password_attr_wdev->dev, "admin password must be configured\n");104	else if (ret == -EACCES)105		dev_err(&wmi_priv.password_attr_wdev->dev, "invalid password\n");106 107out:108	kfree(buffer);109	mutex_unlock(&wmi_priv.mutex);110 111	return ret;112}113 114static int bios_attr_pass_interface_probe(struct wmi_device *wdev, const void *context)115{116	mutex_lock(&wmi_priv.mutex);117	wmi_priv.password_attr_wdev = wdev;118	mutex_unlock(&wmi_priv.mutex);119	return 0;120}121 122static void bios_attr_pass_interface_remove(struct wmi_device *wdev)123{124	mutex_lock(&wmi_priv.mutex);125	wmi_priv.password_attr_wdev = NULL;126	mutex_unlock(&wmi_priv.mutex);127}128 129static const struct wmi_device_id bios_attr_pass_interface_id_table[] = {130	{ .guid_string = DELL_WMI_BIOS_PASSWORD_INTERFACE_GUID },131	{ },132};133static struct wmi_driver bios_attr_pass_interface_driver = {134	.driver = {135		.name = DRIVER_NAME"-password"136	},137	.probe = bios_attr_pass_interface_probe,138	.remove = bios_attr_pass_interface_remove,139	.id_table = bios_attr_pass_interface_id_table,140};141 142int init_bios_attr_pass_interface(void)143{144	return wmi_driver_register(&bios_attr_pass_interface_driver);145}146 147void exit_bios_attr_pass_interface(void)148{149	wmi_driver_unregister(&bios_attr_pass_interface_driver);150}151 152MODULE_DEVICE_TABLE(wmi, bios_attr_pass_interface_id_table);153