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>
17 #include <linux/gfp.h>
19 #include <linux/init.h>
22 #include <net/af_unix.h>
23 #include <linux/audit.h>
24 #include <linux/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>
35 * ipv4_skb_to_auditdata : fill auditdata from skb
37 * @ad : the audit data to fill
38 * @proto : the layer 4 protocol
42 int ipv4_skb_to_auditdata(struct sk_buff
*skb
,
43 struct common_audit_data
*ad
, u8
*proto
)
52 ad
->u
.net
->v4info
.saddr
= ih
->saddr
;
53 ad
->u
.net
->v4info
.daddr
= ih
->daddr
;
56 *proto
= ih
->protocol
;
57 /* non initial fragment */
58 if (ntohs(ih
->frag_off
) & IP_OFFSET
)
61 switch (ih
->protocol
) {
63 struct tcphdr
*th
= tcp_hdr(skb
);
67 ad
->u
.net
->sport
= th
->source
;
68 ad
->u
.net
->dport
= th
->dest
;
72 struct udphdr
*uh
= udp_hdr(skb
);
76 ad
->u
.net
->sport
= uh
->source
;
77 ad
->u
.net
->dport
= uh
->dest
;
81 struct dccp_hdr
*dh
= dccp_hdr(skb
);
85 ad
->u
.net
->sport
= dh
->dccph_sport
;
86 ad
->u
.net
->dport
= dh
->dccph_dport
;
90 struct sctphdr
*sh
= sctp_hdr(skb
);
93 ad
->u
.net
->sport
= sh
->source
;
94 ad
->u
.net
->dport
= sh
->dest
;
102 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
104 * ipv6_skb_to_auditdata : fill auditdata from skb
106 * @ad : the audit data to fill
107 * @proto : the layer 4 protocol
109 * return 0 on success
111 int ipv6_skb_to_auditdata(struct sk_buff
*skb
,
112 struct common_audit_data
*ad
, u8
*proto
)
122 ad
->u
.net
->v6info
.saddr
= ip6
->saddr
;
123 ad
->u
.net
->v6info
.daddr
= ip6
->daddr
;
125 /* IPv6 can have several extension header before the Transport header
127 offset
= skb_network_offset(skb
);
128 offset
+= sizeof(*ip6
);
129 nexthdr
= ip6
->nexthdr
;
130 offset
= ipv6_skip_exthdr(skb
, offset
, &nexthdr
, &frag_off
);
137 struct tcphdr _tcph
, *th
;
139 th
= skb_header_pointer(skb
, offset
, sizeof(_tcph
), &_tcph
);
143 ad
->u
.net
->sport
= th
->source
;
144 ad
->u
.net
->dport
= th
->dest
;
148 struct udphdr _udph
, *uh
;
150 uh
= skb_header_pointer(skb
, offset
, sizeof(_udph
), &_udph
);
154 ad
->u
.net
->sport
= uh
->source
;
155 ad
->u
.net
->dport
= uh
->dest
;
159 struct dccp_hdr _dccph
, *dh
;
161 dh
= skb_header_pointer(skb
, offset
, sizeof(_dccph
), &_dccph
);
165 ad
->u
.net
->sport
= dh
->dccph_sport
;
166 ad
->u
.net
->dport
= dh
->dccph_dport
;
170 struct sctphdr _sctph
, *sh
;
172 sh
= skb_header_pointer(skb
, offset
, sizeof(_sctph
), &_sctph
);
175 ad
->u
.net
->sport
= sh
->source
;
176 ad
->u
.net
->dport
= sh
->dest
;
187 static inline void print_ipv6_addr(struct audit_buffer
*ab
,
188 struct in6_addr
*addr
, __be16 port
,
189 char *name1
, char *name2
)
191 if (!ipv6_addr_any(addr
))
192 audit_log_format(ab
, " %s=%pI6c", name1
, addr
);
194 audit_log_format(ab
, " %s=%d", name2
, ntohs(port
));
197 static inline void print_ipv4_addr(struct audit_buffer
*ab
, __be32 addr
,
198 __be16 port
, char *name1
, char *name2
)
201 audit_log_format(ab
, " %s=%pI4", name1
, &addr
);
203 audit_log_format(ab
, " %s=%d", name2
, ntohs(port
));
207 * dump_common_audit_data - helper to dump common audit data
208 * @a : common audit data
211 static void dump_common_audit_data(struct audit_buffer
*ab
,
212 struct common_audit_data
*a
)
214 char comm
[sizeof(current
->comm
)];
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.
221 BUILD_BUG_ON(sizeof(a
->u
) > sizeof(void *)*2);
223 audit_log_format(ab
, " pid=%d comm=", task_pid_nr(current
));
224 audit_log_untrustedstring(ab
, memcpy(comm
, current
->comm
, sizeof(comm
)));
227 case LSM_AUDIT_DATA_NONE
:
229 case LSM_AUDIT_DATA_IPC
:
230 audit_log_format(ab
, " key=%d ", a
->u
.ipc_id
);
232 case LSM_AUDIT_DATA_CAP
:
233 audit_log_format(ab
, " capability=%d ", a
->u
.cap
);
235 case LSM_AUDIT_DATA_PATH
: {
238 audit_log_d_path(ab
, " path=", &a
->u
.path
);
240 inode
= d_backing_inode(a
->u
.path
.dentry
);
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
);
248 case LSM_AUDIT_DATA_IOCTL_OP
: {
251 audit_log_d_path(ab
, " path=", &a
->u
.op
->path
);
253 inode
= a
->u
.op
->path
.dentry
->d_inode
;
255 audit_log_format(ab
, " dev=");
256 audit_log_untrustedstring(ab
, inode
->i_sb
->s_id
);
257 audit_log_format(ab
, " ino=%lu", inode
->i_ino
);
260 audit_log_format(ab
, " ioctlcmd=%hx", a
->u
.op
->cmd
);
263 case LSM_AUDIT_DATA_DENTRY
: {
266 audit_log_format(ab
, " name=");
267 audit_log_untrustedstring(ab
, a
->u
.dentry
->d_name
.name
);
269 inode
= d_backing_inode(a
->u
.dentry
);
271 audit_log_format(ab
, " dev=");
272 audit_log_untrustedstring(ab
, inode
->i_sb
->s_id
);
273 audit_log_format(ab
, " ino=%lu", inode
->i_ino
);
277 case LSM_AUDIT_DATA_INODE
: {
278 struct dentry
*dentry
;
282 dentry
= d_find_alias(inode
);
284 audit_log_format(ab
, " name=");
285 audit_log_untrustedstring(ab
,
286 dentry
->d_name
.name
);
289 audit_log_format(ab
, " dev=");
290 audit_log_untrustedstring(ab
, inode
->i_sb
->s_id
);
291 audit_log_format(ab
, " ino=%lu", inode
->i_ino
);
294 case LSM_AUDIT_DATA_TASK
: {
295 struct task_struct
*tsk
= a
->u
.tsk
;
297 pid_t pid
= task_pid_nr(tsk
);
299 char comm
[sizeof(tsk
->comm
)];
300 audit_log_format(ab
, " opid=%d ocomm=", pid
);
301 audit_log_untrustedstring(ab
,
302 memcpy(comm
, tsk
->comm
, sizeof(comm
)));
307 case LSM_AUDIT_DATA_NET
:
309 struct sock
*sk
= a
->u
.net
->sk
;
314 switch (sk
->sk_family
) {
316 struct inet_sock
*inet
= inet_sk(sk
);
318 print_ipv4_addr(ab
, inet
->inet_rcv_saddr
,
321 print_ipv4_addr(ab
, inet
->inet_daddr
,
326 #if IS_ENABLED(CONFIG_IPV6)
328 struct inet_sock
*inet
= inet_sk(sk
);
330 print_ipv6_addr(ab
, &sk
->sk_v6_rcv_saddr
,
333 print_ipv6_addr(ab
, &sk
->sk_v6_daddr
,
341 if (u
->path
.dentry
) {
342 audit_log_d_path(ab
, " path=", &u
->path
);
347 len
= u
->addr
->len
-sizeof(short);
348 p
= &u
->addr
->name
->sun_path
[0];
349 audit_log_format(ab
, " path=");
351 audit_log_untrustedstring(ab
, p
);
353 audit_log_n_hex(ab
, p
, len
);
358 switch (a
->u
.net
->family
) {
360 print_ipv4_addr(ab
, a
->u
.net
->v4info
.saddr
,
363 print_ipv4_addr(ab
, a
->u
.net
->v4info
.daddr
,
368 print_ipv6_addr(ab
, &a
->u
.net
->v6info
.saddr
,
371 print_ipv6_addr(ab
, &a
->u
.net
->v6info
.daddr
,
376 if (a
->u
.net
->netif
> 0) {
377 struct net_device
*dev
;
379 /* NOTE: we always use init's namespace */
380 dev
= dev_get_by_index(&init_net
, a
->u
.net
->netif
);
382 audit_log_format(ab
, " netif=%s", dev
->name
);
388 case LSM_AUDIT_DATA_KEY
:
389 audit_log_format(ab
, " key_serial=%u", a
->u
.key_struct
.key
);
390 if (a
->u
.key_struct
.key_desc
) {
391 audit_log_format(ab
, " key_desc=");
392 audit_log_untrustedstring(ab
, a
->u
.key_struct
.key_desc
);
396 case LSM_AUDIT_DATA_KMOD
:
397 audit_log_format(ab
, " kmod=");
398 audit_log_untrustedstring(ab
, a
->u
.kmod_name
);
400 } /* switch (a->type) */
404 * common_lsm_audit - generic LSM auditing function
405 * @a: auxiliary audit data
406 * @pre_audit: lsm-specific pre-audit callback
407 * @post_audit: lsm-specific post-audit callback
409 * setup the audit buffer for common security information
410 * uses callback to print LSM specific information
412 void common_lsm_audit(struct common_audit_data
*a
,
413 void (*pre_audit
)(struct audit_buffer
*, void *),
414 void (*post_audit
)(struct audit_buffer
*, void *))
416 struct audit_buffer
*ab
;
420 /* we use GFP_ATOMIC so we won't sleep */
421 ab
= audit_log_start(current
->audit_context
, GFP_ATOMIC
| __GFP_NOWARN
,
430 dump_common_audit_data(ab
, a
);