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