• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2023 Huawei Device Co., Ltd.
4  */
5 
6 #include <linux/code_sign.h>
7 #include <linux/compat.h>
8 #include <linux/file.h>
9 #include <linux/miscdevice.h>
10 #include <linux/mm.h>
11 #include <linux/mman.h>
12 #include <linux/mm_types.h>
13 
14 #include "code_sign_ext.h"
15 #include "xpm_log.h"
16 #include "xpm_misc_device.h"
17 #include "xpm_report.h"
18 
19 #define XPM_SET_REGION _IOW('x', 0x01, struct xpm_config)
20 #define XPM_SET_OWNERID _IOW('x', 0x02, struct xpm_config)
21 
xpm_set_region(struct xpm_config * config)22 static int xpm_set_region(struct xpm_config *config)
23 {
24 	uint64_t addr;
25 	struct mm_struct *mm = current->mm;
26 
27 	if (!mm)
28 		return -EINVAL;
29 
30 	if ((mm->xpm_region.addr_start != 0) ||
31 		(mm->xpm_region.addr_end != 0)) {
32 		xpm_log_info("xpm region has been set");
33 		return 0;
34 	}
35 
36 	addr = get_unmapped_area(NULL, config->region_addr,
37 		config->region_length, 0, 0);
38 	if (IS_ERR_VALUE(addr) || (ULLONG_MAX - addr < config->region_length)) {
39 		xpm_log_error("xpm get unmmaped area failed");
40 		return -EINVAL;
41 	}
42 
43 	if (mmap_write_lock_killable(mm))
44 		return -EINTR;
45 
46 	mm->xpm_region.addr_start = addr;
47 	mm->xpm_region.addr_end = addr + config->region_length;
48 	mmap_write_unlock(mm);
49 
50 	return 0;
51 }
52 
xpm_set_ownerid(struct xpm_config * config)53 static int xpm_set_ownerid(struct xpm_config *config)
54 {
55 	struct mm_struct *mm = current->mm;
56 
57 	if (!mm)
58 		return -EINVAL;
59 
60 	if (config->id_type >= PROCESS_OWNERID_MAX) {
61 		xpm_log_error("input ownerid type is invalid");
62 		return -EINVAL;
63 	}
64 
65 #ifndef CONFIG_SECURITY_XPM_DEBUG
66 	if ((mm->pcs_info.id_type == PROCESS_OWNERID_APP) ||
67 		mm->pcs_info.id_type == PROCESS_OWNERID_DEBUG) {
68 		xpm_log_info("process ownerid has been set");
69 		return 0;
70 	}
71 #endif
72 
73 	if (config->ownerid[MAX_OWNERID_LEN - 1] != '\0') {
74 		xpm_log_error("input ownerid string is invalid");
75 		return -EINVAL;
76 	}
77 
78 	if (mmap_write_lock_killable(mm))
79 		return -EINTR;
80 
81 	code_sign_set_ownerid(&mm->pcs_info, config->id_type,
82 		config->ownerid, strlen(config->ownerid));
83 	mmap_write_unlock(mm);
84 
85 	return 0;
86 }
87 
xpm_ioctl(struct file * file,unsigned int cmd,unsigned long arg)88 static long xpm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
89 {
90 	int ret;
91 	struct xpm_config config = {0};
92 
93 	if (unlikely(copy_from_user(&config, u64_to_user_ptr((uint64_t)arg),
94 		sizeof(struct xpm_config))))
95 		return -EFAULT;
96 
97 	switch (cmd) {
98 	case XPM_SET_REGION:
99 		ret = xpm_set_region(&config);
100 		break;
101 	case XPM_SET_OWNERID:
102 		ret = xpm_set_ownerid(&config);
103 		break;
104 	default:
105 		xpm_log_error("xpm ioctl cmd error, cmd = %d", cmd);
106 		ret = -EINVAL;
107 		break;
108 	}
109 
110 	return ret;
111 }
112 
113 #ifdef CONFIG_COMPAT
xpm_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)114 static long xpm_compat_ioctl(struct file *file, unsigned int cmd,
115 	unsigned long arg)
116 {
117 	return 0;
118 }
119 #endif
120 
xpm_open(struct inode * inode,struct file * file)121 static int xpm_open(struct inode *inode, struct file *file)
122 {
123 	return 0;
124 }
125 
xpm_release(struct inode * inode,struct file * file)126 static int xpm_release(struct inode *inode, struct file *file)
127 {
128 	return 0;
129 }
130 
131 static const struct file_operations xpm_fops = {
132 	.owner          = THIS_MODULE,
133 	.open           = xpm_open,
134 	.release        = xpm_release,
135 	.unlocked_ioctl = xpm_ioctl,
136 #ifdef CONFIG_COMPAT
137 	.compat_ioctl   = xpm_compat_ioctl,
138 #endif
139 };
140 
141 static struct miscdevice xpm_misc = {
142 	.minor = MISC_DYNAMIC_MINOR,
143 	.name  = "xpm",
144 	.fops  = &xpm_fops,
145 };
146 
xpm_register_misc_device(void)147 int xpm_register_misc_device(void)
148 {
149 	return misc_register(&xpm_misc);
150 }
151 
xpm_deregister_misc_device(void)152 void xpm_deregister_misc_device(void)
153 {
154 	misc_deregister(&xpm_misc);
155 }
156