diff options
Diffstat (limited to 'security/selinux/netlink.c')
-rw-r--r-- | security/selinux/netlink.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c new file mode 100644 index 000000000000..18d08acafa78 --- /dev/null +++ b/security/selinux/netlink.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * Netlink event notifications for SELinux. | ||
3 | * | ||
4 | * Author: James Morris <jmorris@redhat.com> | ||
5 | * | ||
6 | * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2, | ||
10 | * as published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/stddef.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/netlink.h> | ||
19 | #include <linux/selinux_netlink.h> | ||
20 | |||
21 | static struct sock *selnl; | ||
22 | |||
23 | static int selnl_msglen(int msgtype) | ||
24 | { | ||
25 | int ret = 0; | ||
26 | |||
27 | switch (msgtype) { | ||
28 | case SELNL_MSG_SETENFORCE: | ||
29 | ret = sizeof(struct selnl_msg_setenforce); | ||
30 | break; | ||
31 | |||
32 | case SELNL_MSG_POLICYLOAD: | ||
33 | ret = sizeof(struct selnl_msg_policyload); | ||
34 | break; | ||
35 | |||
36 | default: | ||
37 | BUG(); | ||
38 | } | ||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *data) | ||
43 | { | ||
44 | switch (msgtype) { | ||
45 | case SELNL_MSG_SETENFORCE: { | ||
46 | struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh); | ||
47 | |||
48 | memset(msg, 0, len); | ||
49 | msg->val = *((int *)data); | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | case SELNL_MSG_POLICYLOAD: { | ||
54 | struct selnl_msg_policyload *msg = NLMSG_DATA(nlh); | ||
55 | |||
56 | memset(msg, 0, len); | ||
57 | msg->seqno = *((u32 *)data); | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | default: | ||
62 | BUG(); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | static void selnl_notify(int msgtype, void *data) | ||
67 | { | ||
68 | int len; | ||
69 | unsigned char *tmp; | ||
70 | struct sk_buff *skb; | ||
71 | struct nlmsghdr *nlh; | ||
72 | |||
73 | len = selnl_msglen(msgtype); | ||
74 | |||
75 | skb = alloc_skb(NLMSG_SPACE(len), GFP_USER); | ||
76 | if (!skb) | ||
77 | goto oom; | ||
78 | |||
79 | tmp = skb->tail; | ||
80 | nlh = NLMSG_PUT(skb, 0, 0, msgtype, len); | ||
81 | selnl_add_payload(nlh, len, msgtype, data); | ||
82 | nlh->nlmsg_len = skb->tail - tmp; | ||
83 | netlink_broadcast(selnl, skb, 0, SELNL_GRP_AVC, GFP_USER); | ||
84 | out: | ||
85 | return; | ||
86 | |||
87 | nlmsg_failure: | ||
88 | kfree_skb(skb); | ||
89 | oom: | ||
90 | printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__); | ||
91 | goto out; | ||
92 | } | ||
93 | |||
94 | void selnl_notify_setenforce(int val) | ||
95 | { | ||
96 | selnl_notify(SELNL_MSG_SETENFORCE, &val); | ||
97 | } | ||
98 | |||
99 | void selnl_notify_policyload(u32 seqno) | ||
100 | { | ||
101 | selnl_notify(SELNL_MSG_POLICYLOAD, &seqno); | ||
102 | } | ||
103 | |||
104 | static int __init selnl_init(void) | ||
105 | { | ||
106 | selnl = netlink_kernel_create(NETLINK_SELINUX, NULL); | ||
107 | if (selnl == NULL) | ||
108 | panic("SELinux: Cannot create netlink socket."); | ||
109 | netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | __initcall(selnl_init); | ||