Print this page
NEX-13644 File access audit logging
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/c2/audit_start.c
+++ new/usr/src/uts/common/c2/audit_start.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
23 24 */
24 25
25 26 /*
26 27 * This file contains the envelope code for system call auditing.
27 28 */
28 29
29 30 #include <sys/param.h>
30 31 #include <sys/types.h>
31 32 #include <sys/time.h>
32 33 #include <sys/kmem.h>
33 34 #include <sys/proc.h>
34 35 #include <sys/vnode.h>
35 36 #include <sys/file.h>
36 37 #include <sys/user.h>
37 38 #include <sys/stropts.h>
38 39 #include <sys/systm.h>
39 40 #include <sys/pathname.h>
40 41 #include <sys/debug.h>
41 42 #include <sys/cred.h>
42 43 #include <sys/zone.h>
43 44 #include <c2/audit.h>
44 45 #include <c2/audit_kernel.h>
45 46 #include <c2/audit_kevents.h>
46 47 #include <c2/audit_record.h>
47 48 #include "audit_door_infc.h"
48 49
49 50 extern uint_t num_syscall; /* size of audit_s2e table */
50 51 extern kmutex_t pidlock; /* proc table lock */
51 52
52 53 /*
53 54 * Obsolete and ignored - Historically, the 'set c2audit:audit_load=1' entry
54 55 * in /etc/system enabled auditing. The No Reboot Audit project does not
55 56 * use this entry. However, to prevent the system from printing warning
56 57 * messages, the audit_load entry is being left in /etc/system. It will be
57 58 * removed when there is a small chance that the entry is used on currently
58 59 * running systems.
59 60 */
60 61 int audit_load = 0;
61 62
62 63 kmutex_t module_lock; /* audit_module_state lock */
63 64
64 65 /*
65 66 * Das Boot. Initialize first process. Also generate an audit record indicating
66 67 * that the system has been booted.
67 68 */
68 69 void
69 70 audit_init_module()
70 71 {
71 72 token_t *rp = NULL;
72 73 label_t jb;
73 74 t_audit_data_t *tad = U2A(u);
74 75
75 76 /*
76 77 * Solaris Auditing module is being loaded -> change the state. The lock
77 78 * is here to prevent memory leaks caused by multiple initializations.
78 79 */
79 80 mutex_enter(&module_lock);
80 81 if (audit_active != C2AUDIT_UNLOADED) {
81 82 mutex_exit(&module_lock);
82 83 return;
83 84 }
84 85 audit_active = C2AUDIT_LOADED;
85 86 mutex_exit(&module_lock);
86 87
87 88 /* initialize memory allocators */
88 89 au_mem_init();
89 90
90 91 /*
91 92 * setup environment for asynchronous auditing. We can't use
92 93 * audit_async_start() here since it assumes the audit system
93 94 * has been started via auditd(1m). auditd sets the variable,
94 95 * auk_auditstate, to indicate audit record generation should
95 96 * commence. Here we want to always generate an audit record.
96 97 */
97 98 if (setjmp(&jb)) {
98 99 /* process audit policy (AUDIT_AHLT) for asynchronous events */
99 100 audit_async_drop((caddr_t *)(&rp), 0);
100 101 return;
101 102 }
102 103
103 104 ASSERT(tad->tad_errjmp == NULL);
104 105 tad->tad_errjmp = (void *)&jb;
105 106 tad->tad_ctrl |= TAD_ERRJMP;
106 107
107 108 /* generate a system-booted audit record */
108 109 au_write((caddr_t *)&rp, au_to_text("booting kernel"));
109 110 audit_async_finish((caddr_t *)&rp, AUE_SYSTEMBOOT, NULL,
110 111 &(p0.p_user.u_start));
111 112 }
112 113
113 114
114 115 /*
115 116 * Enter system call. Do any necessary setup here. allocate resouces, etc.
116 117 */
117 118
118 119 #include <sys/syscall.h>
119 120
120 121
121 122 /*ARGSUSED*/
122 123 int
123 124 audit_start(
124 125 unsigned type,
125 126 unsigned scid,
126 127 uint32_t audit_state,
127 128 int error,
128 129 klwp_t *lwp)
129 130 {
130 131 struct t_audit_data *tad;
131 132 au_kcontext_t *kctx;
132 133
133 134 tad = U2A(u);
134 135 ASSERT(tad != NULL);
135 136
136 137 /* Remember the audit state in the cache */
137 138 tad->tad_audit = audit_state;
138 139
139 140 if (error) {
140 141 tad->tad_ctrl = 0;
141 142 tad->tad_flag = 0;
142 143 return (0);
143 144 }
144 145
145 146 audit_update_context(curproc, NULL);
146 147
147 148 /*
148 149 * if this is an indirect system call then don't do anything.
149 150 * audit_start will be called again from indir() in trap.c
150 151 */
151 152 if (scid == 0) {
152 153 tad->tad_ctrl = 0;
153 154 tad->tad_flag = 0;
154 155 return (0);
155 156 }
156 157 if (scid >= num_syscall)
157 158 scid = 0;
158 159
159 160 /*
160 161 * we can no longer depend on a valid lwp_ap, so we need to
161 162 * copy the syscall args as future audit stuff may need them.
162 163 */
163 164 (void) save_syscall_args();
164 165
165 166 /*
166 167 * We need to gather paths for certain system calls even if they are
167 168 * not audited so that we can audit the various f* calls and be
168 169 * sure to have a CWD and CAR. Thus we thus set tad_ctrl over the
169 170 * system call regardless if the call is audited or not.
170 171 * We allow the event specific initial processing routines (au_init)
171 172 * to adjust the tad_ctrl as necessary.
172 173 */
173 174 tad->tad_ctrl = audit_s2e[scid].au_ctrl;
174 175 tad->tad_scid = scid;
175 176
176 177 /* get basic event for system call */
177 178 tad->tad_event = audit_s2e[scid].au_event;
178 179 if (audit_s2e[scid].au_init != (au_event_t)AUE_NULL) {
179 180 /* get specific event */
180 181 tad->tad_event = (*audit_s2e[scid].au_init)(tad->tad_event);
181 182 }
182 183
183 184 kctx = GET_KCTX_PZ;
184 185
185 186 /* now do preselection. Audit or not to Audit, that is the question */
186 187 if ((tad->tad_flag = auditme(kctx, tad,
187 188 kctx->auk_ets[tad->tad_event])) == 0) {
188 189 /*
189 190 * we assume that audit_finish will always be called.
190 191 */
191 192 return (0);
192 193 }
193 194
194 195 /*
195 196 * if auditing not enabled, then don't generate an audit record
196 197 * and don't count it.
197 198 */
198 199 if (audit_state & ~(AUC_AUDITING | AUC_INIT_AUDIT)) {
199 200 /*
200 201 * we assume that audit_finish will always be called.
201 202 */
202 203 tad->tad_flag = 0;
203 204 return (0);
204 205 }
205 206
206 207 /*
207 208 * audit daemon has informed us that there is no longer any
208 209 * space left to hold audit records. We decide here if records
209 210 * should be dropped (but counted).
210 211 */
211 212 if (audit_state == AUC_NOSPACE) {
212 213 if ((kctx->auk_policy & AUDIT_CNT) ||
213 214 (kctx->auk_policy & AUDIT_SCNT)) {
214 215 /* assume that audit_finish will always be called. */
215 216 tad->tad_flag = 0;
216 217
217 218 /* just count # of dropped audit records */
218 219 AS_INC(as_dropped, 1, kctx);
219 220
220 221 return (0);
221 222 }
222 223 }
223 224
224 225 tad->tad_evmod = 0;
225 226
226 227 if (audit_s2e[scid].au_start != NULL) {
227 228 /* do start of system call processing */
228 229 (*audit_s2e[scid].au_start)(tad);
229 230 }
230 231
231 232 return (0);
232 233 }
233 234
234 235 /*
235 236 * system call has completed. Now determine if we genearate an audit record
236 237 * or not.
237 238 */
238 239 /*ARGSUSED*/
239 240 void
240 241 audit_finish(
241 242 unsigned type,
242 243 unsigned scid,
243 244 int error,
244 245 rval_t *rval)
245 246 {
246 247 struct t_audit_data *tad;
247 248 int flag;
248 249 au_defer_info_t *attr;
249 250 au_kcontext_t *kctx = GET_KCTX_PZ;
250 251
251 252 tad = U2A(u);
252 253
253 254 /*
254 255 * Process all deferred events first.
255 256 */
256 257 attr = tad->tad_defer_head;
257 258 while (attr != NULL) {
258 259 au_defer_info_t *tmp_attr = attr;
259 260
260 261 au_close_time(kctx, (token_t *)attr->audi_ad, attr->audi_flag,
261 262 attr->audi_e_type, attr->audi_e_mod, &(attr->audi_atime));
262 263
263 264 attr = attr->audi_next;
264 265 kmem_free(tmp_attr, sizeof (au_defer_info_t));
265 266 }
266 267 tad->tad_defer_head = tad->tad_defer_tail = NULL;
267 268
268 269 if (tad->tad_flag == 0 && !(tad->tad_ctrl & TAD_SAVPATH)) {
269 270 /*
270 271 * clear the ctrl flag so that we don't have spurious
271 272 * collection of audit information.
272 273 */
273 274 tad->tad_scid = 0;
274 275 tad->tad_event = 0;
275 276 tad->tad_evmod = 0;
276 277 tad->tad_ctrl = 0;
277 278 tad->tad_audit = AUC_UNSET;
278 279 ASSERT(tad->tad_aupath == NULL);
279 280 return;
280 281 }
281 282
282 283 scid = tad->tad_scid;
283 284
284 285 /*
285 286 * Perform any extra processing and determine if we are
286 287 * really going to generate any audit record.
287 288 */
288 289 if (audit_s2e[scid].au_finish != NULL) {
289 290 /* do any post system call processing */
290 291 (*audit_s2e[scid].au_finish)(tad, error, rval);
291 292 }
292 293 if (tad->tad_flag) {
293 294 tad->tad_flag = 0;
294 295
295 296 if (flag = audit_success(kctx, tad, error, NULL)) {
296 297 unsigned int sy_flags;
297 298 cred_t *cr = CRED();
298 299 const auditinfo_addr_t *ainfo = crgetauinfo(cr);
299 300
300 301 ASSERT(ainfo != NULL);
301 302
302 303 /* Add subject information */
303 304 AUDIT_SETSUBJ(&(u_ad), cr, ainfo, kctx);
304 305
305 306 if (tad->tad_evmod & PAD_SPRIVUSE) {
306 307 au_write(&(u_ad),
307 308 au_to_privset("", &tad->tad_sprivs,
308 309 AUT_UPRIV, 1));
309 310 }
310 311
311 312 if (tad->tad_evmod & PAD_FPRIVUSE) {
312 313 au_write(&(u_ad),
313 314 au_to_privset("", &tad->tad_fprivs,
314 315 AUT_UPRIV, 0));
315 316 }
316 317
317 318 /* Add a return token */
318 319 #ifdef _SYSCALL32_IMPL
319 320 if (lwp_getdatamodel(ttolwp(curthread)) ==
320 321 DATAMODEL_NATIVE) {
321 322 sy_flags = sysent[scid].sy_flags & SE_RVAL_MASK;
322 323 } else {
323 324 sy_flags =
324 325 sysent32[scid].sy_flags & SE_RVAL_MASK;
325 326 }
326 327 #else /* _SYSCALL64_IMPL */
327 328 sy_flags = sysent[scid].sy_flags & SE_RVAL_MASK;
328 329 #endif /* _SYSCALL32_IMPL */
329 330
330 331 if (sy_flags == SE_32RVAL1) {
331 332 if (type == 0) {
332 333 au_write(&(u_ad),
333 334 au_to_return32(error, 0));
334 335 } else {
335 336 au_write(&(u_ad), au_to_return32(error,
336 337 rval->r_val1));
337 338 }
338 339 }
339 340 if (sy_flags == (SE_32RVAL2|SE_32RVAL1)) {
340 341 if (type == 0) {
341 342 au_write(&(u_ad),
342 343 au_to_return32(error, 0));
343 344 } else {
344 345 au_write(&(u_ad),
345 346 au_to_return32(error,
346 347 rval->r_val1));
347 348 #ifdef NOTYET /* for possible future support */
348 349 au_write(&(u_ad), au_to_return32(error,
349 350 rval->r_val2));
350 351 #endif
351 352 }
352 353 }
353 354 if (sy_flags == SE_64RVAL) {
354 355 if (type == 0) {
355 356 au_write(&(u_ad),
356 357 au_to_return64(error, 0));
357 358 } else {
358 359 au_write(&(u_ad), au_to_return64(error,
359 360 rval->r_vals));
360 361 }
361 362 }
362 363
363 364 AS_INC(as_generated, 1, kctx);
364 365 AS_INC(as_kernel, 1, kctx);
365 366 }
366 367
367 368 /* Close up everything */
368 369 au_close(kctx, &(u_ad), flag, tad->tad_event, tad->tad_evmod,
369 370 NULL);
370 371 }
371 372
372 373 ASSERT(u_ad == NULL);
373 374
374 375 /* free up any space remaining with the path's */
375 376 if (tad->tad_aupath != NULL) {
376 377 au_pathrele(tad->tad_aupath);
377 378 tad->tad_aupath = NULL;
378 379 }
379 380
380 381 /* free up any space remaining with openat path's */
381 382 if (tad->tad_atpath) {
382 383 au_pathrele(tad->tad_atpath);
383 384 tad->tad_atpath = NULL;
384 385 }
385 386
386 387 /*
387 388 * clear the ctrl flag so that we don't have spurious collection of
388 389 * audit information.
389 390 */
390 391 tad->tad_scid = 0;
391 392 tad->tad_event = 0;
392 393 tad->tad_evmod = 0;
393 394 tad->tad_ctrl = 0;
394 395 tad->tad_audit = AUC_UNSET;
395 396 }
396 397
397 398 int
398 399 audit_success(au_kcontext_t *kctx, struct t_audit_data *tad, int error,
399 400 cred_t *cr)
400 401 {
401 402 au_state_t ess;
402 403 au_state_t esf;
403 404 au_mask_t amask;
404 405 const auditinfo_addr_t *ainfo;
405 406
406 407 ess = esf = kctx->auk_ets[tad->tad_event];
407 408
408 409 if (error)
409 410 tad->tad_evmod |= PAD_FAILURE;
410 411
411 412 /* see if we really want to generate an audit record */
412 413 if (tad->tad_ctrl & TAD_NOAUDIT)
413 414 return (0);
414 415
415 416 /*
416 417 * Used passed cred if available, otherwise use cred from kernel thread
417 418 */
418 419 if (cr == NULL)
419 420 cr = CRED();
420 421 ainfo = crgetauinfo(cr);
421 422 if (ainfo == NULL)
422 423 return (0);
423 424 amask = ainfo->ai_mask;
424 425
425 426 if (error == 0)
426 427 return ((ess & amask.as_success) ? AU_OK : 0);
427 428 else
428 429 return ((esf & amask.as_failure) ? AU_OK : 0);
429 430 }
430 431
431 432 /*
432 433 * determine if we've preselected this event (system call).
433 434 */
434 435 int
435 436 auditme(au_kcontext_t *kctx, struct t_audit_data *tad, au_state_t estate)
436 437 {
437 438 int flag = 0;
438 439 au_mask_t amask;
439 440 const auditinfo_addr_t *ainfo;
440 441
441 442 ainfo = crgetauinfo(CRED());
442 443 if (ainfo == NULL)
443 444 return (0);
444 445 amask = ainfo->ai_mask;
445 446
446 447 /* preselected system call */
447 448
448 449 if (amask.as_success & estate || amask.as_failure & estate) {
449 450 flag = 1;
450 451 } else if ((tad->tad_scid == SYS_putmsg) ||
451 452 (tad->tad_scid == SYS_getmsg)) {
452 453 estate = kctx->auk_ets[AUE_SOCKCONNECT] |
453 454 kctx->auk_ets[AUE_SOCKACCEPT] |
454 455 kctx->auk_ets[AUE_SOCKSEND] |
455 456 kctx->auk_ets[AUE_SOCKRECEIVE];
|
↓ open down ↓ |
423 lines elided |
↑ open up ↑ |
456 457 if (amask.as_success & estate || amask.as_failure & estate)
457 458 flag = 1;
458 459 } else if (tad->tad_scid == SYS_execve &&
459 460 getpflags(PRIV_PFEXEC, CRED()) != 0) {
460 461 estate = kctx->auk_ets[AUE_PFEXEC];
461 462 if (amask.as_success & estate || amask.as_failure & estate)
462 463 flag = 1;
463 464 }
464 465
465 466 return (flag);
467 +}
468 +
469 +/*
470 + * determine if we've preselected this event (non-syscall).
471 + */
472 +
473 +int
474 +auditev(au_event_t event, cred_t *cr)
475 +{
476 + au_mask_t amask;
477 + const auditinfo_addr_t *ainfo;
478 + au_state_t estate;
479 + au_kcontext_t *kctx = GET_KCTX_PZ;
480 +
481 + ASSERT3U(event, <=, MAX_KEVENTS);
482 +
483 + estate = kctx->auk_ets[event];
484 + ainfo = crgetauinfo(cr);
485 + if (ainfo == NULL)
486 + return (0);
487 + amask = ainfo->ai_mask;
488 +
489 + if ((amask.as_success & estate) != 0 ||
490 + (amask.as_failure & estate) != 0)
491 + return (AU_OK);
492 +
493 + return (0);
466 494 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX