The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/security/lsm_audit.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * common LSM auditing functions
    3  *
    4  * Based on code written for SELinux by :
    5  *                      Stephen Smalley, <sds@epoch.ncsc.mil>
    6  *                      James Morris <jmorris@redhat.com>
    7  * Author : Etienne Basset, <etienne.basset@ensta.org>
    8  *
    9  * This program is free software; you can redistribute it and/or modify
   10  * it under the terms of the GNU General Public License version 2,
   11  * as published by the Free Software Foundation.
   12  */
   13 
   14 #include <linux/types.h>
   15 #include <linux/stddef.h>
   16 #include <linux/kernel.h>
   17 #include <linux/gfp.h>
   18 #include <linux/fs.h>
   19 #include <linux/init.h>
   20 #include <net/sock.h>
   21 #include <linux/un.h>
   22 #include <net/af_unix.h>
   23 #include <linux/audit.h>
   24 #include <linux/ipv6.h>
   25 #include <linux/ip.h>
   26 #include <net/ip.h>
   27 #include <net/ipv6.h>
   28 #include <linux/tcp.h>
   29 #include <linux/udp.h>
   30 #include <linux/dccp.h>
   31 #include <linux/sctp.h>
   32 #include <linux/lsm_audit.h>
   33 
   34 /**
   35  * ipv4_skb_to_auditdata : fill auditdata from skb
   36  * @skb : the skb
   37  * @ad : the audit data to fill
   38  * @proto : the layer 4 protocol
   39  *
   40  * return  0 on success
   41  */
   42 int ipv4_skb_to_auditdata(struct sk_buff *skb,
   43                 struct common_audit_data *ad, u8 *proto)
   44 {
   45         int ret = 0;
   46         struct iphdr *ih;
   47 
   48         ih = ip_hdr(skb);
   49         if (ih == NULL)
   50                 return -EINVAL;
   51 
   52         ad->u.net->v4info.saddr = ih->saddr;
   53         ad->u.net->v4info.daddr = ih->daddr;
   54 
   55         if (proto)
   56                 *proto = ih->protocol;
   57         /* non initial fragment */
   58         if (ntohs(ih->frag_off) & IP_OFFSET)
   59                 return 0;
   60 
   61         switch (ih->protocol) {
   62         case IPPROTO_TCP: {
   63                 struct tcphdr *th = tcp_hdr(skb);
   64                 if (th == NULL)
   65                         break;
   66 
   67                 ad->u.net->sport = th->source;
   68                 ad->u.net->dport = th->dest;
   69                 break;
   70         }
   71         case IPPROTO_UDP: {
   72                 struct udphdr *uh = udp_hdr(skb);
   73                 if (uh == NULL)
   74                         break;
   75 
   76                 ad->u.net->sport = uh->source;
   77                 ad->u.net->dport = uh->dest;
   78                 break;
   79         }
   80         case IPPROTO_DCCP: {
   81                 struct dccp_hdr *dh = dccp_hdr(skb);
   82                 if (dh == NULL)
   83                         break;
   84 
   85                 ad->u.net->sport = dh->dccph_sport;
   86                 ad->u.net->dport = dh->dccph_dport;
   87                 break;
   88         }
   89         case IPPROTO_SCTP: {
   90                 struct sctphdr *sh = sctp_hdr(skb);
   91                 if (sh == NULL)
   92                         break;
   93                 ad->u.net->sport = sh->source;
   94                 ad->u.net->dport = sh->dest;
   95                 break;
   96         }
   97         default:
   98                 ret = -EINVAL;
   99         }
  100         return ret;
  101 }
  102 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  103 /**
  104  * ipv6_skb_to_auditdata : fill auditdata from skb
  105  * @skb : the skb
  106  * @ad : the audit data to fill
  107  * @proto : the layer 4 protocol
  108  *
  109  * return  0 on success
  110  */
  111 int ipv6_skb_to_auditdata(struct sk_buff *skb,
  112                 struct common_audit_data *ad, u8 *proto)
  113 {
  114         int offset, ret = 0;
  115         struct ipv6hdr *ip6;
  116         u8 nexthdr;
  117         __be16 frag_off;
  118 
  119         ip6 = ipv6_hdr(skb);
  120         if (ip6 == NULL)
  121                 return -EINVAL;
  122         ad->u.net->v6info.saddr = ip6->saddr;
  123         ad->u.net->v6info.daddr = ip6->daddr;
  124         ret = 0;
  125         /* IPv6 can have several extension header before the Transport header
  126          * skip them */
  127         offset = skb_network_offset(skb);
  128         offset += sizeof(*ip6);
  129         nexthdr = ip6->nexthdr;
  130         offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
  131         if (offset < 0)
  132                 return 0;
  133         if (proto)
  134                 *proto = nexthdr;
  135         switch (nexthdr) {
  136         case IPPROTO_TCP: {
  137                 struct tcphdr _tcph, *th;
  138 
  139                 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
  140                 if (th == NULL)
  141                         break;
  142 
  143                 ad->u.net->sport = th->source;
  144                 ad->u.net->dport = th->dest;
  145                 break;
  146         }
  147         case IPPROTO_UDP: {
  148                 struct udphdr _udph, *uh;
  149 
  150                 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
  151                 if (uh == NULL)
  152                         break;
  153 
  154                 ad->u.net->sport = uh->source;
  155                 ad->u.net->dport = uh->dest;
  156                 break;
  157         }
  158         case IPPROTO_DCCP: {
  159                 struct dccp_hdr _dccph, *dh;
  160 
  161                 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
  162                 if (dh == NULL)
  163                         break;
  164 
  165                 ad->u.net->sport = dh->dccph_sport;
  166                 ad->u.net->dport = dh->dccph_dport;
  167                 break;
  168         }
  169         case IPPROTO_SCTP: {
  170                 struct sctphdr _sctph, *sh;
  171 
  172                 sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
  173                 if (sh == NULL)
  174                         break;
  175                 ad->u.net->sport = sh->source;
  176                 ad->u.net->dport = sh->dest;
  177                 break;
  178         }
  179         default:
  180                 ret = -EINVAL;
  181         }
  182         return ret;
  183 }
  184 #endif
  185 
  186 
  187 static inline void print_ipv6_addr(struct audit_buffer *ab,
  188                                    struct in6_addr *addr, __be16 port,
  189                                    char *name1, char *name2)
  190 {
  191         if (!ipv6_addr_any(addr))
  192                 audit_log_format(ab, " %s=%pI6c", name1, addr);
  193         if (port)
  194                 audit_log_format(ab, " %s=%d", name2, ntohs(port));
  195 }
  196 
  197 static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
  198                                    __be16 port, char *name1, char *name2)
  199 {
  200         if (addr)
  201                 audit_log_format(ab, " %s=%pI4", name1, &addr);
  202         if (port)
  203                 audit_log_format(ab, " %s=%d", name2, ntohs(port));
  204 }
  205 
  206 /**
  207  * dump_common_audit_data - helper to dump common audit data
  208  * @a : common audit data
  209  *
  210  */
  211 static void dump_common_audit_data(struct audit_buffer *ab,
  212                                    struct common_audit_data *a)
  213 {
  214         struct task_struct *tsk = current;
  215 
  216         /*
  217          * To keep stack sizes in check force programers to notice if they
  218          * start making this union too large!  See struct lsm_network_audit
  219          * as an example of how to deal with large data.
  220          */
  221         BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
  222 
  223         audit_log_format(ab, " pid=%d comm=", tsk->pid);
  224         audit_log_untrustedstring(ab, tsk->comm);
  225 
  226         switch (a->type) {
  227         case LSM_AUDIT_DATA_NONE:
  228                 return;
  229         case LSM_AUDIT_DATA_IPC:
  230                 audit_log_format(ab, " key=%d ", a->u.ipc_id);
  231                 break;
  232         case LSM_AUDIT_DATA_CAP:
  233                 audit_log_format(ab, " capability=%d ", a->u.cap);
  234                 break;
  235         case LSM_AUDIT_DATA_PATH: {
  236                 struct inode *inode;
  237 
  238                 audit_log_d_path(ab, " path=", &a->u.path);
  239 
  240                 inode = a->u.path.dentry->d_inode;
  241                 if (inode) {
  242                         audit_log_format(ab, " dev=");
  243                         audit_log_untrustedstring(ab, inode->i_sb->s_id);
  244                         audit_log_format(ab, " ino=%lu", inode->i_ino);
  245                 }
  246                 break;
  247         }
  248         case LSM_AUDIT_DATA_DENTRY: {
  249                 struct inode *inode;
  250 
  251                 audit_log_format(ab, " name=");
  252                 audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
  253 
  254                 inode = a->u.dentry->d_inode;
  255                 if (inode) {
  256                         audit_log_format(ab, " dev=");
  257                         audit_log_untrustedstring(ab, inode->i_sb->s_id);
  258                         audit_log_format(ab, " ino=%lu", inode->i_ino);
  259                 }
  260                 break;
  261         }
  262         case LSM_AUDIT_DATA_INODE: {
  263                 struct dentry *dentry;
  264                 struct inode *inode;
  265 
  266                 inode = a->u.inode;
  267                 dentry = d_find_alias(inode);
  268                 if (dentry) {
  269                         audit_log_format(ab, " name=");
  270                         audit_log_untrustedstring(ab,
  271                                          dentry->d_name.name);
  272                         dput(dentry);
  273                 }
  274                 audit_log_format(ab, " dev=");
  275                 audit_log_untrustedstring(ab, inode->i_sb->s_id);
  276                 audit_log_format(ab, " ino=%lu", inode->i_ino);
  277                 break;
  278         }
  279         case LSM_AUDIT_DATA_TASK:
  280                 tsk = a->u.tsk;
  281                 if (tsk && tsk->pid) {
  282                         audit_log_format(ab, " pid=%d comm=", tsk->pid);
  283                         audit_log_untrustedstring(ab, tsk->comm);
  284                 }
  285                 break;
  286         case LSM_AUDIT_DATA_NET:
  287                 if (a->u.net->sk) {
  288                         struct sock *sk = a->u.net->sk;
  289                         struct unix_sock *u;
  290                         int len = 0;
  291                         char *p = NULL;
  292 
  293                         switch (sk->sk_family) {
  294                         case AF_INET: {
  295                                 struct inet_sock *inet = inet_sk(sk);
  296 
  297                                 print_ipv4_addr(ab, inet->inet_rcv_saddr,
  298                                                 inet->inet_sport,
  299                                                 "laddr", "lport");
  300                                 print_ipv4_addr(ab, inet->inet_daddr,
  301                                                 inet->inet_dport,
  302                                                 "faddr", "fport");
  303                                 break;
  304                         }
  305                         case AF_INET6: {
  306                                 struct inet_sock *inet = inet_sk(sk);
  307                                 struct ipv6_pinfo *inet6 = inet6_sk(sk);
  308 
  309                                 print_ipv6_addr(ab, &inet6->rcv_saddr,
  310                                                 inet->inet_sport,
  311                                                 "laddr", "lport");
  312                                 print_ipv6_addr(ab, &inet6->daddr,
  313                                                 inet->inet_dport,
  314                                                 "faddr", "fport");
  315                                 break;
  316                         }
  317                         case AF_UNIX:
  318                                 u = unix_sk(sk);
  319                                 if (u->path.dentry) {
  320                                         audit_log_d_path(ab, " path=", &u->path);
  321                                         break;
  322                                 }
  323                                 if (!u->addr)
  324                                         break;
  325                                 len = u->addr->len-sizeof(short);
  326                                 p = &u->addr->name->sun_path[0];
  327                                 audit_log_format(ab, " path=");
  328                                 if (*p)
  329                                         audit_log_untrustedstring(ab, p);
  330                                 else
  331                                         audit_log_n_hex(ab, p, len);
  332                                 break;
  333                         }
  334                 }
  335 
  336                 switch (a->u.net->family) {
  337                 case AF_INET:
  338                         print_ipv4_addr(ab, a->u.net->v4info.saddr,
  339                                         a->u.net->sport,
  340                                         "saddr", "src");
  341                         print_ipv4_addr(ab, a->u.net->v4info.daddr,
  342                                         a->u.net->dport,
  343                                         "daddr", "dest");
  344                         break;
  345                 case AF_INET6:
  346                         print_ipv6_addr(ab, &a->u.net->v6info.saddr,
  347                                         a->u.net->sport,
  348                                         "saddr", "src");
  349                         print_ipv6_addr(ab, &a->u.net->v6info.daddr,
  350                                         a->u.net->dport,
  351                                         "daddr", "dest");
  352                         break;
  353                 }
  354                 if (a->u.net->netif > 0) {
  355                         struct net_device *dev;
  356 
  357                         /* NOTE: we always use init's namespace */
  358                         dev = dev_get_by_index(&init_net, a->u.net->netif);
  359                         if (dev) {
  360                                 audit_log_format(ab, " netif=%s", dev->name);
  361                                 dev_put(dev);
  362                         }
  363                 }
  364                 break;
  365 #ifdef CONFIG_KEYS
  366         case LSM_AUDIT_DATA_KEY:
  367                 audit_log_format(ab, " key_serial=%u", a->u.key_struct.key);
  368                 if (a->u.key_struct.key_desc) {
  369                         audit_log_format(ab, " key_desc=");
  370                         audit_log_untrustedstring(ab, a->u.key_struct.key_desc);
  371                 }
  372                 break;
  373 #endif
  374         case LSM_AUDIT_DATA_KMOD:
  375                 audit_log_format(ab, " kmod=");
  376                 audit_log_untrustedstring(ab, a->u.kmod_name);
  377                 break;
  378         } /* switch (a->type) */
  379 }
  380 
  381 /**
  382  * common_lsm_audit - generic LSM auditing function
  383  * @a:  auxiliary audit data
  384  * @pre_audit: lsm-specific pre-audit callback
  385  * @post_audit: lsm-specific post-audit callback
  386  *
  387  * setup the audit buffer for common security information
  388  * uses callback to print LSM specific information
  389  */
  390 void common_lsm_audit(struct common_audit_data *a,
  391         void (*pre_audit)(struct audit_buffer *, void *),
  392         void (*post_audit)(struct audit_buffer *, void *))
  393 {
  394         struct audit_buffer *ab;
  395 
  396         if (a == NULL)
  397                 return;
  398         /* we use GFP_ATOMIC so we won't sleep */
  399         ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC);
  400 
  401         if (ab == NULL)
  402                 return;
  403 
  404         if (pre_audit)
  405                 pre_audit(ab, a);
  406 
  407         dump_common_audit_data(ab, a);
  408 
  409         if (post_audit)
  410                 post_audit(ab, a);
  411 
  412         audit_log_end(ab);
  413 }

Cache object: b210527a0be4905ce03e4eb202e00cd3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.