2 * common LSM auditing functions
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>
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.
14 #include <linux/types.h>
15 #include <linux/stddef.h>
16 #include <linux/kernel.h>
18 #include <linux/init.h>
21 #include <net/af_unix.h>
22 #include <linux/audit.h>
23 #include <linux/ipv6.h>
27 #include <linux/tcp.h>
28 #include <linux/udp.h>
29 #include <linux/dccp.h>
30 #include <linux/sctp.h>
31 #include <linux/lsm_audit.h>
34 * ipv4_skb_to_auditdata : fill auditdata from skb
36 * @ad : the audit data to fill
37 * @proto : the layer 4 protocol
41 int ipv4_skb_to_auditdata(struct sk_buff
*skb
,
42 struct common_audit_data
*ad
, u8
*proto
)
51 ad
->u
.net
.v4info
.saddr
= ih
->saddr
;
52 ad
->u
.net
.v4info
.daddr
= ih
->daddr
;
55 *proto
= ih
->protocol
;
56 /* non initial fragment */
57 if (ntohs(ih
->frag_off
) & IP_OFFSET
)
60 switch (ih
->protocol
) {
62 struct tcphdr
*th
= tcp_hdr(skb
);
66 ad
->u
.net
.sport
= th
->source
;
67 ad
->u
.net
.dport
= th
->dest
;
71 struct udphdr
*uh
= udp_hdr(skb
);
75 ad
->u
.net
.sport
= uh
->source
;
76 ad
->u
.net
.dport
= uh
->dest
;
80 struct dccp_hdr
*dh
= dccp_hdr(skb
);
84 ad
->u
.net
.sport
= dh
->dccph_sport
;
85 ad
->u
.net
.dport
= dh
->dccph_dport
;
89 struct sctphdr
*sh
= sctp_hdr(skb
);
92 ad
->u
.net
.sport
= sh
->source
;
93 ad
->u
.net
.dport
= sh
->dest
;
101 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
103 * ipv6_skb_to_auditdata : fill auditdata from skb
105 * @ad : the audit data to fill
106 * @proto : the layer 4 protocol
108 * return 0 on success
110 int ipv6_skb_to_auditdata(struct sk_buff
*skb
,
111 struct common_audit_data
*ad
, u8
*proto
)
120 ipv6_addr_copy(&ad
->u
.net
.v6info
.saddr
, &ip6
->saddr
);
121 ipv6_addr_copy(&ad
->u
.net
.v6info
.daddr
, &ip6
->daddr
);
123 /* IPv6 can have several extension header before the Transport header
125 offset
= skb_network_offset(skb
);
126 offset
+= sizeof(*ip6
);
127 nexthdr
= ip6
->nexthdr
;
128 offset
= ipv6_skip_exthdr(skb
, offset
, &nexthdr
);
135 struct tcphdr _tcph
, *th
;
137 th
= skb_header_pointer(skb
, offset
, sizeof(_tcph
), &_tcph
);
141 ad
->u
.net
.sport
= th
->source
;
142 ad
->u
.net
.dport
= th
->dest
;
146 struct udphdr _udph
, *uh
;
148 uh
= skb_header_pointer(skb
, offset
, sizeof(_udph
), &_udph
);
152 ad
->u
.net
.sport
= uh
->source
;
153 ad
->u
.net
.dport
= uh
->dest
;
157 struct dccp_hdr _dccph
, *dh
;
159 dh
= skb_header_pointer(skb
, offset
, sizeof(_dccph
), &_dccph
);
163 ad
->u
.net
.sport
= dh
->dccph_sport
;
164 ad
->u
.net
.dport
= dh
->dccph_dport
;
168 struct sctphdr _sctph
, *sh
;
170 sh
= skb_header_pointer(skb
, offset
, sizeof(_sctph
), &_sctph
);
173 ad
->u
.net
.sport
= sh
->source
;
174 ad
->u
.net
.dport
= sh
->dest
;
185 static inline void print_ipv6_addr(struct audit_buffer
*ab
,
186 struct in6_addr
*addr
, __be16 port
,
187 char *name1
, char *name2
)
189 if (!ipv6_addr_any(addr
))
190 audit_log_format(ab
, " %s=%pI6", name1
, addr
);
192 audit_log_format(ab
, " %s=%d", name2
, ntohs(port
));
195 static inline void print_ipv4_addr(struct audit_buffer
*ab
, __be32 addr
,
196 __be16 port
, char *name1
, char *name2
)
199 audit_log_format(ab
, " %s=%pI4", name1
, &addr
);
201 audit_log_format(ab
, " %s=%d", name2
, ntohs(port
));
205 * dump_common_audit_data - helper to dump common audit data
206 * @a : common audit data
209 static void dump_common_audit_data(struct audit_buffer
*ab
,
210 struct common_audit_data
*a
)
212 struct inode
*inode
= NULL
;
213 struct task_struct
*tsk
= current
;
217 if (tsk
&& tsk
->pid
) {
218 audit_log_format(ab
, " pid=%d comm=", tsk
->pid
);
219 audit_log_untrustedstring(ab
, tsk
->comm
);
223 case LSM_AUDIT_NO_AUDIT
:
225 case LSM_AUDIT_DATA_IPC
:
226 audit_log_format(ab
, " key=%d ", a
->u
.ipc_id
);
228 case LSM_AUDIT_DATA_CAP
:
229 audit_log_format(ab
, " capability=%d ", a
->u
.cap
);
231 case LSM_AUDIT_DATA_FS
:
232 if (a
->u
.fs
.path
.dentry
) {
233 struct dentry
*dentry
= a
->u
.fs
.path
.dentry
;
234 if (a
->u
.fs
.path
.mnt
) {
235 audit_log_d_path(ab
, "path=", &a
->u
.fs
.path
);
237 audit_log_format(ab
, " name=");
238 audit_log_untrustedstring(ab
,
239 dentry
->d_name
.name
);
241 inode
= dentry
->d_inode
;
242 } else if (a
->u
.fs
.inode
) {
243 struct dentry
*dentry
;
244 inode
= a
->u
.fs
.inode
;
245 dentry
= d_find_alias(inode
);
247 audit_log_format(ab
, " name=");
248 audit_log_untrustedstring(ab
,
249 dentry
->d_name
.name
);
254 audit_log_format(ab
, " dev=%s ino=%lu",
258 case LSM_AUDIT_DATA_TASK
:
260 if (tsk
&& tsk
->pid
) {
261 audit_log_format(ab
, " pid=%d comm=", tsk
->pid
);
262 audit_log_untrustedstring(ab
, tsk
->comm
);
265 case LSM_AUDIT_DATA_NET
:
267 struct sock
*sk
= a
->u
.net
.sk
;
272 switch (sk
->sk_family
) {
274 struct inet_sock
*inet
= inet_sk(sk
);
276 print_ipv4_addr(ab
, inet
->rcv_saddr
,
279 print_ipv4_addr(ab
, inet
->daddr
,
285 struct inet_sock
*inet
= inet_sk(sk
);
286 struct ipv6_pinfo
*inet6
= inet6_sk(sk
);
288 print_ipv6_addr(ab
, &inet6
->rcv_saddr
,
291 print_ipv6_addr(ab
, &inet6
->daddr
,
303 audit_log_d_path(ab
, "path=", &path
);
308 len
= u
->addr
->len
-sizeof(short);
309 p
= &u
->addr
->name
->sun_path
[0];
310 audit_log_format(ab
, " path=");
312 audit_log_untrustedstring(ab
, p
);
314 audit_log_n_hex(ab
, p
, len
);
319 switch (a
->u
.net
.family
) {
321 print_ipv4_addr(ab
, a
->u
.net
.v4info
.saddr
,
324 print_ipv4_addr(ab
, a
->u
.net
.v4info
.daddr
,
329 print_ipv6_addr(ab
, &a
->u
.net
.v6info
.saddr
,
332 print_ipv6_addr(ab
, &a
->u
.net
.v6info
.daddr
,
337 if (a
->u
.net
.netif
> 0) {
338 struct net_device
*dev
;
340 /* NOTE: we always use init's namespace */
341 dev
= dev_get_by_index(&init_net
, a
->u
.net
.netif
);
343 audit_log_format(ab
, " netif=%s", dev
->name
);
349 case LSM_AUDIT_DATA_KEY
:
350 audit_log_format(ab
, " key_serial=%u", a
->u
.key_struct
.key
);
351 if (a
->u
.key_struct
.key_desc
) {
352 audit_log_format(ab
, " key_desc=");
353 audit_log_untrustedstring(ab
, a
->u
.key_struct
.key_desc
);
357 } /* switch (a->type) */
361 * common_lsm_audit - generic LSM auditing function
362 * @a: auxiliary audit data
364 * setup the audit buffer for common security information
365 * uses callback to print LSM specific information
367 void common_lsm_audit(struct common_audit_data
*a
)
369 struct audit_buffer
*ab
;
373 /* we use GFP_ATOMIC so we won't sleep */
374 ab
= audit_log_start(current
->audit_context
, GFP_ATOMIC
, AUDIT_AVC
);
379 if (a
->lsm_pre_audit
)
380 a
->lsm_pre_audit(ab
, a
);
382 dump_common_audit_data(ab
, a
);
384 if (a
->lsm_post_audit
)
385 a
->lsm_post_audit(ab
, a
);