Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * custom_method.c - debugfs interface for customizing ACPI control method
  4 */
  5
  6#include <linux/init.h>
  7#include <linux/module.h>
  8#include <linux/kernel.h>
  9#include <linux/uaccess.h>
 10#include <linux/debugfs.h>
 11#include <linux/acpi.h>
 12#include <linux/security.h>
 13
 14#include "internal.h"
 15
 16#define _COMPONENT		ACPI_SYSTEM_COMPONENT
 17ACPI_MODULE_NAME("custom_method");
 18MODULE_LICENSE("GPL");
 19
 20static struct dentry *cm_dentry;
 21
 22/* /sys/kernel/debug/acpi/custom_method */
 23
 24static ssize_t cm_write(struct file *file, const char __user * user_buf,
 25			size_t count, loff_t *ppos)
 26{
 27	static char *buf;
 28	static u32 max_size;
 29	static u32 uncopied_bytes;
 30
 31	struct acpi_table_header table;
 32	acpi_status status;
 33	int ret;
 34
 35	ret = security_locked_down(LOCKDOWN_ACPI_TABLES);
 36	if (ret)
 37		return ret;
 38
 39	if (!(*ppos)) {
 40		/* parse the table header to get the table length */
 41		if (count <= sizeof(struct acpi_table_header))
 42			return -EINVAL;
 43		if (copy_from_user(&table, user_buf,
 44				   sizeof(struct acpi_table_header)))
 45			return -EFAULT;
 46		uncopied_bytes = max_size = table.length;
 
 
 47		buf = kzalloc(max_size, GFP_KERNEL);
 48		if (!buf)
 49			return -ENOMEM;
 50	}
 51
 52	if (buf == NULL)
 53		return -EINVAL;
 54
 55	if ((*ppos > max_size) ||
 56	    (*ppos + count > max_size) ||
 57	    (*ppos + count < count) ||
 58	    (count > uncopied_bytes)) {
 59		kfree(buf);
 
 60		return -EINVAL;
 61	}
 62
 63	if (copy_from_user(buf + (*ppos), user_buf, count)) {
 64		kfree(buf);
 65		buf = NULL;
 66		return -EFAULT;
 67	}
 68
 69	uncopied_bytes -= count;
 70	*ppos += count;
 71
 72	if (!uncopied_bytes) {
 73		status = acpi_install_method(buf);
 74		kfree(buf);
 75		buf = NULL;
 76		if (ACPI_FAILURE(status))
 77			return -EINVAL;
 78		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
 79	}
 80
 81	kfree(buf);
 82	return count;
 83}
 84
 85static const struct file_operations cm_fops = {
 86	.write = cm_write,
 87	.llseek = default_llseek,
 88};
 89
 90static int __init acpi_custom_method_init(void)
 91{
 92	cm_dentry = debugfs_create_file("custom_method", S_IWUSR,
 93					acpi_debugfs_dir, NULL, &cm_fops);
 94	return 0;
 95}
 96
 97static void __exit acpi_custom_method_exit(void)
 98{
 99	debugfs_remove(cm_dentry);
100}
101
102module_init(acpi_custom_method_init);
103module_exit(acpi_custom_method_exit);
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * custom_method.c - debugfs interface for customizing ACPI control method
  4 */
  5
  6#include <linux/init.h>
  7#include <linux/module.h>
  8#include <linux/kernel.h>
  9#include <linux/uaccess.h>
 10#include <linux/debugfs.h>
 11#include <linux/acpi.h>
 12#include <linux/security.h>
 13
 14#include "internal.h"
 15
 
 
 16MODULE_LICENSE("GPL");
 17
 18static struct dentry *cm_dentry;
 19
 20/* /sys/kernel/debug/acpi/custom_method */
 21
 22static ssize_t cm_write(struct file *file, const char __user *user_buf,
 23			size_t count, loff_t *ppos)
 24{
 25	static char *buf;
 26	static u32 max_size;
 27	static u32 uncopied_bytes;
 28
 29	struct acpi_table_header table;
 30	acpi_status status;
 31	int ret;
 32
 33	ret = security_locked_down(LOCKDOWN_ACPI_TABLES);
 34	if (ret)
 35		return ret;
 36
 37	if (!(*ppos)) {
 38		/* parse the table header to get the table length */
 39		if (count <= sizeof(struct acpi_table_header))
 40			return -EINVAL;
 41		if (copy_from_user(&table, user_buf,
 42				   sizeof(struct acpi_table_header)))
 43			return -EFAULT;
 44		uncopied_bytes = max_size = table.length;
 45		/* make sure the buf is not allocated */
 46		kfree(buf);
 47		buf = kzalloc(max_size, GFP_KERNEL);
 48		if (!buf)
 49			return -ENOMEM;
 50	}
 51
 52	if (buf == NULL)
 53		return -EINVAL;
 54
 55	if ((*ppos > max_size) ||
 56	    (*ppos + count > max_size) ||
 57	    (*ppos + count < count) ||
 58	    (count > uncopied_bytes)) {
 59		kfree(buf);
 60		buf = NULL;
 61		return -EINVAL;
 62	}
 63
 64	if (copy_from_user(buf + (*ppos), user_buf, count)) {
 65		kfree(buf);
 66		buf = NULL;
 67		return -EFAULT;
 68	}
 69
 70	uncopied_bytes -= count;
 71	*ppos += count;
 72
 73	if (!uncopied_bytes) {
 74		status = acpi_install_method(buf);
 75		kfree(buf);
 76		buf = NULL;
 77		if (ACPI_FAILURE(status))
 78			return -EINVAL;
 79		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
 80	}
 81
 
 82	return count;
 83}
 84
 85static const struct file_operations cm_fops = {
 86	.write = cm_write,
 87	.llseek = default_llseek,
 88};
 89
 90static int __init acpi_custom_method_init(void)
 91{
 92	cm_dentry = debugfs_create_file("custom_method", S_IWUSR,
 93					acpi_debugfs_dir, NULL, &cm_fops);
 94	return 0;
 95}
 96
 97static void __exit acpi_custom_method_exit(void)
 98{
 99	debugfs_remove(cm_dentry);
100}
101
102module_init(acpi_custom_method_init);
103module_exit(acpi_custom_method_exit);