diff -drupN a/security/fivm/fivm_dev.c b/security/fivm/fivm_dev.c --- a/security/fivm/fivm_dev.c 1970-01-01 03:00:00.000000000 +0300 +++ b/security/fivm/fivm_dev.c 2022-06-12 05:28:14.000000000 +0300 @@ -0,0 +1,175 @@ +/* + * linux/security/fivm/fivm_dev.c + * + * Copyright (C) 2014 Allwinner Ltd. + * + * Author: ryan.chen + * + * allwinner fivm controller device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fivm.h" + +#define CMD_FIVM_INIT _IO('M', 0) +#define CMD_FIVM_ENABLE _IO('M', 1) +#define CMD_FIVM_SET _IOR('M', 2, struct fivm_param) + +#ifdef CONFIG_COMPAT +#define CMD_FIVM_SET32 _IOR('M', 2, struct fivm_param_t32) +#endif + +static dev_t dev; +static struct cdev c_dev; +static struct class *cl; + +static int fivm_open(struct inode *i, struct file *f) +{ + return 0; +} +static int fivm_close(struct inode *i, struct file *f) +{ + return 0; +} + +extern int fivm_init(void); +static long fivm_ioctl ( + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + int rc = 0; + switch (cmd) { + case CMD_FIVM_ENABLE: + rc = fivm_enable(); + break; + case CMD_FIVM_SET: + rc = fivm_set((void *)arg); + break; + default: + rc = -EINVAL; + break; + } + return rc; +} +#ifdef CONFIG_COMPAT +static long fivm_compat_ioctl(struct file *file, + unsigned int cmd, + unsigned long arg + ) +{ + int rc = 0; + struct fivm_param_t32 param_t32; + struct fivm_param __user *param; + + switch (cmd) { + case CMD_FIVM_ENABLE: + rc = fivm_enable(); + break; + case CMD_FIVM_SET32: + if (copy_from_user(¶m_t32, + (const void __user *)arg, + sizeof(param_t32))) { + pr_err("wrong copy from user param\n"); + return -EFAULT; + } + + param = compat_alloc_user_space(sizeof(*param)); + if (!access_ok(VERIFY_READ, param, sizeof(*param))) { + pr_err("access read fail for param\n"); + return -EINVAL; + } + put_user(compat_ptr(param_t32.sig_head), + ¶m->sig_head); + put_user(param_t32.sig_head_size, + ¶m->sig_head_size); + put_user(compat_ptr(param_t32.sig_table), + ¶m->sig_table); + put_user(param_t32.sig_table_size, + ¶m->sig_table_size); + + rc = fivm_set((void *)param); + break; + default: + rc = -EINVAL; + break; + } + return rc; +} +#endif +static const struct file_operations fivm_fops = { + .owner = THIS_MODULE, + .open = fivm_open, + .release = fivm_close, + .unlocked_ioctl = fivm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = fivm_compat_ioctl, +#endif +}; + +static int __init fivm_dev_init(void) /* Constructor */ +{ + if (alloc_chrdev_region(&dev, 0, 1, "fivm_dev") < 0) { + pr_err("fivm chrdev create fail\n"); + return -1; + } + cl = class_create(THIS_MODULE, "fivm_drv"); + if (!cl) { + pr_err("fivm class create fail\n"); + unregister_chrdev_region(dev, 1); + return -1; + } + if (device_create(cl, NULL, dev, NULL, "fivm") == NULL) { + pr_err("fivm device create fail\n"); + class_destroy(cl); + unregister_chrdev_region(dev, 1); + return -1; + } + cdev_init(&c_dev, &fivm_fops); + if (cdev_add(&c_dev, dev, 1) == -1) { + pr_err("fivm cdev add fail\n"); + device_destroy(cl, dev); + class_destroy(cl); + unregister_chrdev_region(dev, 1); + return -1; + } + if (fivm_init() < 0) { + pr_err("fivm init fail\n"); + return -1; + } + + pr_info("FIVM device register ok \n"); + return 0; +} + +static void __exit fivm_dev_exit(void) /* Destructor */ +{ + cdev_del(&c_dev); + device_destroy(cl, dev); + class_destroy(cl); + unregister_chrdev_region(dev, 1); + fivm_cleanup(); +} + +module_init(fivm_dev_init); +module_exit(fivm_dev_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("ryan chen"); +MODULE_DESCRIPTION("Sunxi file integrity verify module for system"); +