Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/selinux/netlink.c
49640 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Netlink event notifications for SELinux.
4
*
5
* Author: James Morris <[email protected]>
6
*
7
* Copyright (C) 2004 Red Hat, Inc., James Morris <[email protected]>
8
*/
9
#include <linux/init.h>
10
#include <linux/types.h>
11
#include <linux/slab.h>
12
#include <linux/stddef.h>
13
#include <linux/kernel.h>
14
#include <linux/export.h>
15
#include <linux/skbuff.h>
16
#include <linux/selinux_netlink.h>
17
#include <net/net_namespace.h>
18
#include <net/netlink.h>
19
20
#include "initcalls.h"
21
#include "security.h"
22
23
static struct sock *selnl __ro_after_init;
24
25
static int selnl_msglen(int msgtype)
26
{
27
int ret = 0;
28
29
switch (msgtype) {
30
case SELNL_MSG_SETENFORCE:
31
ret = sizeof(struct selnl_msg_setenforce);
32
break;
33
34
case SELNL_MSG_POLICYLOAD:
35
ret = sizeof(struct selnl_msg_policyload);
36
break;
37
38
default:
39
BUG();
40
}
41
return ret;
42
}
43
44
static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *data)
45
{
46
switch (msgtype) {
47
case SELNL_MSG_SETENFORCE: {
48
struct selnl_msg_setenforce *msg = nlmsg_data(nlh);
49
50
memset(msg, 0, len);
51
msg->val = *((int *)data);
52
break;
53
}
54
55
case SELNL_MSG_POLICYLOAD: {
56
struct selnl_msg_policyload *msg = nlmsg_data(nlh);
57
58
memset(msg, 0, len);
59
msg->seqno = *((u32 *)data);
60
break;
61
}
62
63
default:
64
BUG();
65
}
66
}
67
68
static void selnl_notify(int msgtype, void *data)
69
{
70
int len;
71
sk_buff_data_t tmp;
72
struct sk_buff *skb;
73
struct nlmsghdr *nlh;
74
75
len = selnl_msglen(msgtype);
76
77
skb = nlmsg_new(len, GFP_USER);
78
if (!skb)
79
goto oom;
80
81
tmp = skb->tail;
82
nlh = nlmsg_put(skb, 0, 0, msgtype, len, 0);
83
if (!nlh)
84
goto out_kfree_skb;
85
selnl_add_payload(nlh, len, msgtype, data);
86
nlh->nlmsg_len = skb->tail - tmp;
87
NETLINK_CB(skb).dst_group = SELNLGRP_AVC;
88
netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER);
89
out:
90
return;
91
92
out_kfree_skb:
93
kfree_skb(skb);
94
oom:
95
pr_err("SELinux: OOM in %s\n", __func__);
96
goto out;
97
}
98
99
void selnl_notify_setenforce(int val)
100
{
101
selnl_notify(SELNL_MSG_SETENFORCE, &val);
102
}
103
104
void selnl_notify_policyload(u32 seqno)
105
{
106
selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
107
}
108
109
int __init sel_netlink_init(void)
110
{
111
struct netlink_kernel_cfg cfg = {
112
.groups = SELNLGRP_MAX,
113
.flags = NL_CFG_F_NONROOT_RECV,
114
};
115
116
selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX, &cfg);
117
if (selnl == NULL)
118
panic("SELinux: Cannot create netlink socket.");
119
return 0;
120
}
121
122