-
Notifications
You must be signed in to change notification settings - Fork 3
/
module-init.c
92 lines (67 loc) · 1.98 KB
/
module-init.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/security.h>
#include "udis86.h"
#define debug(fmt...) \
pr_info("[" KBUILD_MODNAME "] " fmt)
/* fake security operations */
static struct security_operations sop;
/* pointer to the system's LSM-model */
static struct security_operations * realsop;
/* pointer to the module's fake LSM-model */
static struct security_operations * fakesop = &sop;
/* pointer to 'security_ops' pointer */
static struct security_operations ** psop = NULL;
static void * get_lsm_entry(void)
{
/* this one is exported */
return (void *)&security_sb_copy_data;
}
static struct security_operations ** get_lsm_sop(void)
{
ud_t ud;
void * entry = get_lsm_entry(), * result = NULL;
ud_initialize(&ud, BITS_PER_LONG, UD_VENDOR_ANY, entry, 128);
while (ud_disassemble(&ud) && ud.mnemonic != UD_Iret) {
if (ud.mnemonic == UD_Imov && \
ud.operand[0].type == UD_OP_REG && ud.operand[1].type == UD_OP_MEM)
{
#ifdef CONFIG_X86_64
result = entry + ud_insn_off(&ud) + ud_insn_len(&ud);
#endif
result = result + ud.operand[1].lval.sdword;
break;
}
}
return result;
}
static int fake_inode_permission(struct inode * inode, int mask)
{
debug("%s inode:%pK mask:%08x\n", __func__, inode, mask);
return realsop->inode_permission(inode, mask);
}
int init_module(void)
{
psop = get_lsm_sop();
if (!psop) {
debug("can't find LSM security_ops pointer\n");
return -EINVAL;
}
realsop = *psop;
memcpy(fakesop, realsop, sizeof(struct security_operations));
snprintf(fakesop->name, SECURITY_NAME_MAX, "fakesop");
debug("found LSM security_ops @ %pK (%s)\n", psop, (*psop)->name);
fakesop->inode_permission = &fake_inode_permission;
*psop = fakesop;
debug("initialized\n");
return 0;
}
void cleanup_module(void)
{
*psop = realsop;
debug("deinitialized\n");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ilya V. Matveychikov <[email protected]>");
MODULE_DESCRIPTION("Linux kernel LSM replacement example");