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