netlink.c revision c544c028e45feceeb48b629456d0eb43adc8eaaf
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#include <net/net_namespace.h>
21
22static struct sock *selnl;
23
24static int selnl_msglen(int msgtype)
25{
26	int ret = 0;
27
28	switch (msgtype) {
29	case SELNL_MSG_SETENFORCE:
30		ret = sizeof(struct selnl_msg_setenforce);
31		break;
32
33	case SELNL_MSG_POLICYLOAD:
34		ret = sizeof(struct selnl_msg_policyload);
35		break;
36
37	default:
38		BUG();
39	}
40	return ret;
41}
42
43static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *data)
44{
45	switch (msgtype) {
46	case SELNL_MSG_SETENFORCE: {
47		struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
48
49		memset(msg, 0, len);
50		msg->val = *((int *)data);
51		break;
52	}
53
54	case SELNL_MSG_POLICYLOAD: {
55		struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
56
57		memset(msg, 0, len);
58		msg->seqno = *((u32 *)data);
59		break;
60	}
61
62	default:
63		BUG();
64	}
65}
66
67static void selnl_notify(int msgtype, void *data)
68{
69	int len;
70	sk_buff_data_t tmp;
71	struct sk_buff *skb;
72	struct nlmsghdr *nlh;
73
74	len = selnl_msglen(msgtype);
75
76	skb = alloc_skb(NLMSG_SPACE(len), GFP_USER);
77	if (!skb)
78		goto oom;
79
80	tmp = skb->tail;
81	nlh = NLMSG_PUT(skb, 0, 0, msgtype, len);
82	selnl_add_payload(nlh, len, msgtype, data);
83	nlh->nlmsg_len = skb->tail - tmp;
84	NETLINK_CB(skb).dst_group = SELNLGRP_AVC;
85	netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER);
86out:
87	return;
88
89nlmsg_failure:
90	kfree_skb(skb);
91oom:
92	printk(KERN_ERR "SELinux:  OOM in %s\n", __func__);
93	goto out;
94}
95
96void selnl_notify_setenforce(int val)
97{
98	selnl_notify(SELNL_MSG_SETENFORCE, &val);
99}
100
101void selnl_notify_policyload(u32 seqno)
102{
103	selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
104}
105
106static int __init selnl_init(void)
107{
108	selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX,
109				      SELNLGRP_MAX, NULL, NULL, THIS_MODULE);
110	if (selnl == NULL)
111		panic("SELinux:  Cannot create netlink socket.");
112	netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
113	return 0;
114}
115
116__initcall(selnl_init);
117