1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2023 Huawei Device Co., Ltd.
4 */
5 #include <linux/mman.h>
6 #include <linux/mm_types.h>
7 #include <linux/sched.h>
8 #include <linux/mm.h>
9
10 #include "jit_memory.h"
11 #include "jit_space_list.h"
12 #include "avc.h"
13 #include "objsec.h"
14 #include <linux/version.h>
15
16 DEFINE_SPINLOCK(list_lock);
17
jit_avc_has_perm(u16 tclass,u32 requested,struct task_struct * task)18 static bool jit_avc_has_perm(u16 tclass, u32 requested, struct task_struct *task)
19 {
20 // Bypass 'init'
21 if (task_pid_nr(current) == 1) {
22 return false;
23 }
24
25 struct av_decision avd;
26 u32 secid;
27 security_cred_getsecid(task->cred, &secid);
28
29 #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0))
30 return (avc_has_perm_noaudit(&selinux_state, secid, secid, tclass, requested,
31 AVC_STRICT, &avd) == 0);
32 #else
33 return (avc_has_perm_noaudit(secid, secid, tclass, requested,
34 AVC_STRICT, &avd) == 0);
35 #endif
36 }
37
find_jit_memory(struct task_struct * task,unsigned long start,unsigned long size,int * err)38 void find_jit_memory(struct task_struct *task, unsigned long start, unsigned long size, int *err)
39 {
40 if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task))
41 return;
42
43 struct list_head *head = (find_process_jit_space(&root_tree, task->pid).head);
44 if (head != NULL) {
45 spin_lock(&list_lock);
46 find_jit_space(head, start, size, err);
47 spin_unlock(&list_lock);
48 }
49
50 }
51
check_jit_memory(struct task_struct * task,unsigned long cookie,unsigned long prot,unsigned long flag,unsigned long size,unsigned long * err)52 void check_jit_memory(struct task_struct *task, unsigned long cookie, unsigned long prot,
53 unsigned long flag, unsigned long size, unsigned long *err)
54 {
55 if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task) || !(flag & MAP_ANONYMOUS))
56 return;
57 unsigned long start = *err;
58
59 // check for apply EXEC mem has been removed here
60 if (!(flag & MAP_JIT))
61 return;
62
63 struct list_head *head = update_process_jit_space(&root_tree, task->pid, cookie, err);
64 if (IS_ERR_VALUE(*err)) {
65 vm_munmap(start, size);
66 return;
67 }
68 if (head != NULL) {
69 spin_lock(&list_lock);
70 update_jit_space(head, start, size);
71 spin_unlock(&list_lock);
72 }
73 }
74
delete_jit_memory(struct task_struct * task,unsigned long start,unsigned long size,int * err)75 void delete_jit_memory(struct task_struct *task, unsigned long start, unsigned long size, int *err)
76 {
77 if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task))
78 return;
79
80 struct list_head *head = (find_process_jit_space(&root_tree, task->pid).head);
81 if (head != NULL) {
82 spin_lock(&list_lock);
83 delete_jit_space(head, start, size, err);
84 spin_unlock(&list_lock);
85 }
86 }
87
exit_jit_memory(struct task_struct * task)88 void exit_jit_memory(struct task_struct *task)
89 {
90 if (!jit_avc_has_perm(SECCLASS_JIT_MEMORY, JIT_MEMORY__EXEC_MEM_CTRL, task))
91 return;
92
93 struct jit_process *process = delete_process_jit_space(&root_tree, task->pid);
94 if (process != NULL) {
95 spin_lock(&list_lock);
96 exit_jit_space(&(process->head));
97 spin_unlock(&list_lock);
98 kfree(process);
99 }
100 }