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

custom_method.c (2170B)


      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);