Branch data Line data Source code
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 : 0 : 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 [ # # ]: 0 : if (ih == NULL)
50 : : return -EINVAL;
51 : :
52 : 0 : ad->u.net->v4info.saddr = ih->saddr;
53 : 0 : ad->u.net->v4info.daddr = ih->daddr;
54 : :
55 [ # # ]: 0 : if (proto)
56 : 0 : *proto = ih->protocol;
57 : : /* non initial fragment */
58 [ # # ][ # # ]: 0 : if (ntohs(ih->frag_off) & IP_OFFSET)
59 : : return 0;
60 : :
61 [ # # # # : 0 : switch (ih->protocol) {
# ]
62 : : case IPPROTO_TCP: {
63 : : struct tcphdr *th = tcp_hdr(skb);
64 [ # # ]: 0 : if (th == NULL)
65 : : break;
66 : :
67 : 0 : ad->u.net->sport = th->source;
68 : 0 : ad->u.net->dport = th->dest;
69 : 0 : break;
70 : : }
71 : : case IPPROTO_UDP: {
72 : : struct udphdr *uh = udp_hdr(skb);
73 [ # # ]: 0 : if (uh == NULL)
74 : : break;
75 : :
76 : 0 : ad->u.net->sport = uh->source;
77 : 0 : ad->u.net->dport = uh->dest;
78 : 0 : break;
79 : : }
80 : : case IPPROTO_DCCP: {
81 : : struct dccp_hdr *dh = dccp_hdr(skb);
82 [ # # ]: 0 : if (dh == NULL)
83 : : break;
84 : :
85 : 0 : ad->u.net->sport = dh->dccph_sport;
86 : 0 : ad->u.net->dport = dh->dccph_dport;
87 : 0 : break;
88 : : }
89 : : case IPPROTO_SCTP: {
90 : : struct sctphdr *sh = sctp_hdr(skb);
91 [ # # ]: 0 : if (sh == NULL)
92 : : break;
93 : 0 : ad->u.net->sport = sh->source;
94 : 0 : ad->u.net->dport = sh->dest;
95 : 0 : break;
96 : : }
97 : : default:
98 : : ret = -EINVAL;
99 : : }
100 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (ip6 == NULL)
121 : : return -EINVAL;
122 : 0 : ad->u.net->v6info.saddr = ip6->saddr;
123 : 0 : 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 : 0 : offset += sizeof(*ip6);
129 : 0 : nexthdr = ip6->nexthdr;
130 : 0 : offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
131 [ # # ]: 0 : if (offset < 0)
132 : : return 0;
133 [ # # ]: 0 : if (proto)
134 : 0 : *proto = nexthdr;
135 [ # # # # : 0 : switch (nexthdr) {
# ]
136 : : case IPPROTO_TCP: {
137 : : struct tcphdr _tcph, *th;
138 : :
139 : : th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
140 [ # # ]: 0 : if (th == NULL)
141 : : break;
142 : :
143 : 0 : ad->u.net->sport = th->source;
144 : 0 : ad->u.net->dport = th->dest;
145 : 0 : break;
146 : : }
147 : : case IPPROTO_UDP: {
148 : : struct udphdr _udph, *uh;
149 : :
150 : : uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
151 [ # # ]: 0 : if (uh == NULL)
152 : : break;
153 : :
154 : 0 : ad->u.net->sport = uh->source;
155 : 0 : ad->u.net->dport = uh->dest;
156 : 0 : break;
157 : : }
158 : : case IPPROTO_DCCP: {
159 : : struct dccp_hdr _dccph, *dh;
160 : :
161 : : dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
162 [ # # ]: 0 : if (dh == NULL)
163 : : break;
164 : :
165 : 0 : ad->u.net->sport = dh->dccph_sport;
166 : 0 : ad->u.net->dport = dh->dccph_dport;
167 : 0 : break;
168 : : }
169 : : case IPPROTO_SCTP: {
170 : : struct sctphdr _sctph, *sh;
171 : :
172 : : sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
173 [ # # ]: 0 : if (sh == NULL)
174 : : break;
175 : 0 : ad->u.net->sport = sh->source;
176 : 0 : ad->u.net->dport = sh->dest;
177 : 0 : break;
178 : : }
179 : : default:
180 : : ret = -EINVAL;
181 : : }
182 : 0 : 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 [ # # ][ # # ]: 0 : if (!ipv6_addr_any(addr))
[ # # ][ # # ]
192 : 0 : audit_log_format(ab, " %s=%pI6c", name1, addr);
193 [ # # ][ # # ]: 0 : if (port)
[ # # ][ # # ]
194 [ # # ][ # # ]: 0 : 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 [ # # ][ # # ]: 0 : if (addr)
[ # # ][ # # ]
201 : 0 : audit_log_format(ab, " %s=%pI4", name1, &addr);
202 [ # # ][ # # ]: 0 : if (port)
[ # # ][ # # ]
203 [ # # ][ # # ]: 0 : 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 : 0 : static void dump_common_audit_data(struct audit_buffer *ab,
212 : : struct common_audit_data *a)
213 : : {
214 : 0 : 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 : 0 : audit_log_format(ab, " pid=%d comm=", tsk->pid);
224 : 0 : audit_log_untrustedstring(ab, tsk->comm);
225 : :
226 [ # # # # : 0 : switch (a->type) {
# # # # #
# ]
227 : : case LSM_AUDIT_DATA_NONE:
228 : 0 : return;
229 : : case LSM_AUDIT_DATA_IPC:
230 : 0 : audit_log_format(ab, " key=%d ", a->u.ipc_id);
231 : 0 : break;
232 : : case LSM_AUDIT_DATA_CAP:
233 : 0 : audit_log_format(ab, " capability=%d ", a->u.cap);
234 : 0 : break;
235 : : case LSM_AUDIT_DATA_PATH: {
236 : : struct inode *inode;
237 : :
238 : 0 : audit_log_d_path(ab, " path=", &a->u.path);
239 : :
240 : 0 : inode = a->u.path.dentry->d_inode;
241 [ # # ]: 0 : if (inode) {
242 : 0 : audit_log_format(ab, " dev=");
243 : 0 : audit_log_untrustedstring(ab, inode->i_sb->s_id);
244 : 0 : 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 : 0 : audit_log_format(ab, " name=");
252 : 0 : audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
253 : :
254 : 0 : inode = a->u.dentry->d_inode;
255 [ # # ]: 0 : if (inode) {
256 : 0 : audit_log_format(ab, " dev=");
257 : 0 : audit_log_untrustedstring(ab, inode->i_sb->s_id);
258 : 0 : 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 : 0 : inode = a->u.inode;
267 : 0 : dentry = d_find_alias(inode);
268 [ # # ]: 0 : if (dentry) {
269 : 0 : audit_log_format(ab, " name=");
270 : 0 : audit_log_untrustedstring(ab,
271 : 0 : dentry->d_name.name);
272 : 0 : dput(dentry);
273 : : }
274 : 0 : audit_log_format(ab, " dev=");
275 : 0 : audit_log_untrustedstring(ab, inode->i_sb->s_id);
276 : 0 : audit_log_format(ab, " ino=%lu", inode->i_ino);
277 : 0 : break;
278 : : }
279 : : case LSM_AUDIT_DATA_TASK:
280 : 0 : tsk = a->u.tsk;
281 [ # # ][ # # ]: 0 : if (tsk && tsk->pid) {
282 : 0 : audit_log_format(ab, " pid=%d comm=", tsk->pid);
283 : 0 : audit_log_untrustedstring(ab, tsk->comm);
284 : : }
285 : : break;
286 : : case LSM_AUDIT_DATA_NET:
287 [ # # ]: 0 : 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 [ # # # # ]: 0 : switch (sk->sk_family) {
294 : : case AF_INET: {
295 : : struct inet_sock *inet = inet_sk(sk);
296 : :
297 : 0 : print_ipv4_addr(ab, inet->inet_rcv_saddr,
298 : : inet->inet_sport,
299 : : "laddr", "lport");
300 : 0 : print_ipv4_addr(ab, inet->inet_daddr,
301 : : inet->inet_dport,
302 : : "faddr", "fport");
303 : : break;
304 : : }
305 : : #if IS_ENABLED(CONFIG_IPV6)
306 : : case AF_INET6: {
307 : : struct inet_sock *inet = inet_sk(sk);
308 : :
309 : 0 : print_ipv6_addr(ab, &sk->sk_v6_rcv_saddr,
310 : : inet->inet_sport,
311 : : "laddr", "lport");
312 : 0 : print_ipv6_addr(ab, &sk->sk_v6_daddr,
313 : : inet->inet_dport,
314 : : "faddr", "fport");
315 : : break;
316 : : }
317 : : #endif
318 : : case AF_UNIX:
319 : : u = unix_sk(sk);
320 [ # # ]: 0 : if (u->path.dentry) {
321 : 0 : audit_log_d_path(ab, " path=", &u->path);
322 : 0 : break;
323 : : }
324 [ # # ]: 0 : if (!u->addr)
325 : : break;
326 : 0 : len = u->addr->len-sizeof(short);
327 : 0 : p = &u->addr->name->sun_path[0];
328 : 0 : audit_log_format(ab, " path=");
329 [ # # ]: 0 : if (*p)
330 : 0 : audit_log_untrustedstring(ab, p);
331 : : else
332 : 0 : audit_log_n_hex(ab, p, len);
333 : : break;
334 : : }
335 : : }
336 : :
337 [ # # # ]: 0 : switch (a->u.net->family) {
338 : : case AF_INET:
339 : 0 : print_ipv4_addr(ab, a->u.net->v4info.saddr,
340 : : a->u.net->sport,
341 : : "saddr", "src");
342 : 0 : print_ipv4_addr(ab, a->u.net->v4info.daddr,
343 : : a->u.net->dport,
344 : : "daddr", "dest");
345 : : break;
346 : : case AF_INET6:
347 : 0 : print_ipv6_addr(ab, &a->u.net->v6info.saddr,
348 : : a->u.net->sport,
349 : : "saddr", "src");
350 : 0 : print_ipv6_addr(ab, &a->u.net->v6info.daddr,
351 : : a->u.net->dport,
352 : : "daddr", "dest");
353 : : break;
354 : : }
355 [ # # ]: 0 : if (a->u.net->netif > 0) {
356 : : struct net_device *dev;
357 : :
358 : : /* NOTE: we always use init's namespace */
359 : 0 : dev = dev_get_by_index(&init_net, a->u.net->netif);
360 [ # # ]: 0 : if (dev) {
361 : 0 : audit_log_format(ab, " netif=%s", dev->name);
362 : : dev_put(dev);
363 : : }
364 : : }
365 : : break;
366 : : #ifdef CONFIG_KEYS
367 : : case LSM_AUDIT_DATA_KEY:
368 : 0 : audit_log_format(ab, " key_serial=%u", a->u.key_struct.key);
369 [ # # ]: 0 : if (a->u.key_struct.key_desc) {
370 : 0 : audit_log_format(ab, " key_desc=");
371 : 0 : audit_log_untrustedstring(ab, a->u.key_struct.key_desc);
372 : : }
373 : : break;
374 : : #endif
375 : : case LSM_AUDIT_DATA_KMOD:
376 : 0 : audit_log_format(ab, " kmod=");
377 : 0 : audit_log_untrustedstring(ab, a->u.kmod_name);
378 : 0 : break;
379 : : } /* switch (a->type) */
380 : : }
381 : :
382 : : /**
383 : : * common_lsm_audit - generic LSM auditing function
384 : : * @a: auxiliary audit data
385 : : * @pre_audit: lsm-specific pre-audit callback
386 : : * @post_audit: lsm-specific post-audit callback
387 : : *
388 : : * setup the audit buffer for common security information
389 : : * uses callback to print LSM specific information
390 : : */
391 : 0 : void common_lsm_audit(struct common_audit_data *a,
392 : : void (*pre_audit)(struct audit_buffer *, void *),
393 : : void (*post_audit)(struct audit_buffer *, void *))
394 : : {
395 : : struct audit_buffer *ab;
396 : :
397 [ # # ]: 0 : if (a == NULL)
398 : : return;
399 : : /* we use GFP_ATOMIC so we won't sleep */
400 : 0 : ab = audit_log_start(current->audit_context, GFP_ATOMIC | __GFP_NOWARN,
401 : : AUDIT_AVC);
402 : :
403 [ # # ]: 0 : if (ab == NULL)
404 : : return;
405 : :
406 [ # # ]: 0 : if (pre_audit)
407 : 0 : pre_audit(ab, a);
408 : :
409 : 0 : dump_common_audit_data(ab, a);
410 : :
411 [ # # ]: 0 : if (post_audit)
412 : 0 : post_audit(ab, a);
413 : :
414 : 0 : audit_log_end(ab);
415 : : }
|