Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Netlink event notifications for SELinux.
0004  *
0005  * Author: James Morris <jmorris@redhat.com>
0006  *
0007  * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
0008  */
0009 #include <linux/init.h>
0010 #include <linux/types.h>
0011 #include <linux/slab.h>
0012 #include <linux/stddef.h>
0013 #include <linux/kernel.h>
0014 #include <linux/export.h>
0015 #include <linux/skbuff.h>
0016 #include <linux/selinux_netlink.h>
0017 #include <net/net_namespace.h>
0018 #include <net/netlink.h>
0019 
0020 #include "security.h"
0021 
0022 static struct sock *selnl __ro_after_init;
0023 
0024 static int selnl_msglen(int msgtype)
0025 {
0026     int ret = 0;
0027 
0028     switch (msgtype) {
0029     case SELNL_MSG_SETENFORCE:
0030         ret = sizeof(struct selnl_msg_setenforce);
0031         break;
0032 
0033     case SELNL_MSG_POLICYLOAD:
0034         ret = sizeof(struct selnl_msg_policyload);
0035         break;
0036 
0037     default:
0038         BUG();
0039     }
0040     return ret;
0041 }
0042 
0043 static void selnl_add_payload(struct nlmsghdr *nlh, int len, int msgtype, void *data)
0044 {
0045     switch (msgtype) {
0046     case SELNL_MSG_SETENFORCE: {
0047         struct selnl_msg_setenforce *msg = nlmsg_data(nlh);
0048 
0049         memset(msg, 0, len);
0050         msg->val = *((int *)data);
0051         break;
0052     }
0053 
0054     case SELNL_MSG_POLICYLOAD: {
0055         struct selnl_msg_policyload *msg = nlmsg_data(nlh);
0056 
0057         memset(msg, 0, len);
0058         msg->seqno = *((u32 *)data);
0059         break;
0060     }
0061 
0062     default:
0063         BUG();
0064     }
0065 }
0066 
0067 static void selnl_notify(int msgtype, void *data)
0068 {
0069     int len;
0070     sk_buff_data_t tmp;
0071     struct sk_buff *skb;
0072     struct nlmsghdr *nlh;
0073 
0074     len = selnl_msglen(msgtype);
0075 
0076     skb = nlmsg_new(len, GFP_USER);
0077     if (!skb)
0078         goto oom;
0079 
0080     tmp = skb->tail;
0081     nlh = nlmsg_put(skb, 0, 0, msgtype, len, 0);
0082     if (!nlh)
0083         goto out_kfree_skb;
0084     selnl_add_payload(nlh, len, msgtype, data);
0085     nlh->nlmsg_len = skb->tail - tmp;
0086     NETLINK_CB(skb).dst_group = SELNLGRP_AVC;
0087     netlink_broadcast(selnl, skb, 0, SELNLGRP_AVC, GFP_USER);
0088 out:
0089     return;
0090 
0091 out_kfree_skb:
0092     kfree_skb(skb);
0093 oom:
0094     pr_err("SELinux:  OOM in %s\n", __func__);
0095     goto out;
0096 }
0097 
0098 void selnl_notify_setenforce(int val)
0099 {
0100     selnl_notify(SELNL_MSG_SETENFORCE, &val);
0101 }
0102 
0103 void selnl_notify_policyload(u32 seqno)
0104 {
0105     selnl_notify(SELNL_MSG_POLICYLOAD, &seqno);
0106 }
0107 
0108 static int __init selnl_init(void)
0109 {
0110     struct netlink_kernel_cfg cfg = {
0111         .groups = SELNLGRP_MAX,
0112         .flags  = NL_CFG_F_NONROOT_RECV,
0113     };
0114 
0115     selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX, &cfg);
0116     if (selnl == NULL)
0117         panic("SELinux:  Cannot create netlink socket.");
0118     return 0;
0119 }
0120 
0121 __initcall(selnl_init);