auditsc.c 35.1 KB
Newer Older
1
/* auditsc.c -- System-call auditing support
L
Linus Torvalds 已提交
2 3 4
 * Handles all system-call specific auditing features.
 *
 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
5
 * Copyright 2005 Hewlett-Packard Development Company, L.P.
6
 * Copyright (C) 2005 IBM Corporation
L
Linus Torvalds 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Written by Rickard E. (Rik) Faith <faith@redhat.com>
 *
 * Many of the ideas implemented here are from Stephen C. Tweedie,
 * especially the idea of avoiding a copy by using getname.
 *
 * The method for actual interception of syscall entry and exit (not in
 * this file -- see entry.S) is based on a GPL'd patch written by
 * okir@suse.de and Copyright 2003 SuSE Linux AG.
 *
32 33 34
 * The support of additional filter rules compares (>, <, >=, <=) was
 * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
 *
35 36
 * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
 * filesystem information.
37 38 39
 *
 * Subject and object context labeling support added by <danjones@us.ibm.com>
 * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
L
Linus Torvalds 已提交
40 41 42 43
 */

#include <linux/init.h>
#include <asm/types.h>
A
Alan Cox 已提交
44
#include <asm/atomic.h>
45 46 47
#include <asm/types.h>
#include <linux/fs.h>
#include <linux/namei.h>
L
Linus Torvalds 已提交
48 49
#include <linux/mm.h>
#include <linux/module.h>
50
#include <linux/mount.h>
51
#include <linux/socket.h>
L
Linus Torvalds 已提交
52 53 54
#include <linux/audit.h>
#include <linux/personality.h>
#include <linux/time.h>
55
#include <linux/netlink.h>
56
#include <linux/compiler.h>
L
Linus Torvalds 已提交
57
#include <asm/unistd.h>
58
#include <linux/security.h>
59
#include <linux/list.h>
60
#include <linux/tty.h>
61
#include <linux/selinux.h>
L
Linus Torvalds 已提交
62

63
#include "audit.h"
L
Linus Torvalds 已提交
64

65
extern struct list_head audit_filter_list[];
L
Linus Torvalds 已提交
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

/* No syscall auditing will take place unless audit_enabled != 0. */
extern int audit_enabled;

/* AUDIT_NAMES is the number of slots we reserve in the audit_context
 * for saving names from getname(). */
#define AUDIT_NAMES    20

/* AUDIT_NAMES_RESERVED is the number of slots we reserve in the
 * audit_context from being used for nameless inodes from
 * path_lookup. */
#define AUDIT_NAMES_RESERVED 7

/* When fs/namei.c:getname() is called, we store the pointer in name and
 * we don't let putname() free it (instead we free all of the saved
 * pointers at syscall exit time).
 *
 * Further, in fs/namei.c:path_lookup() we store the inode and device. */
struct audit_names {
	const char	*name;
	unsigned long	ino;
87
	unsigned long	pino;
L
Linus Torvalds 已提交
88 89 90 91 92
	dev_t		dev;
	umode_t		mode;
	uid_t		uid;
	gid_t		gid;
	dev_t		rdev;
S
Steve Grubb 已提交
93
	u32		osid;
L
Linus Torvalds 已提交
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
};

struct audit_aux_data {
	struct audit_aux_data	*next;
	int			type;
};

#define AUDIT_AUX_IPCPERM	0

struct audit_aux_data_ipcctl {
	struct audit_aux_data	d;
	struct ipc_perm		p;
	unsigned long		qbytes;
	uid_t			uid;
	gid_t			gid;
	mode_t			mode;
S
Steve Grubb 已提交
110
	u32			osid;
L
Linus Torvalds 已提交
111 112
};

113 114 115 116 117 118 119 120 121 122 123 124
struct audit_aux_data_socketcall {
	struct audit_aux_data	d;
	int			nargs;
	unsigned long		args[0];
};

struct audit_aux_data_sockaddr {
	struct audit_aux_data	d;
	int			len;
	char			a[0];
};

125 126 127 128 129
struct audit_aux_data_path {
	struct audit_aux_data	d;
	struct dentry		*dentry;
	struct vfsmount		*mnt;
};
L
Linus Torvalds 已提交
130 131 132 133 134 135 136 137 138 139 140

/* The per-task audit context. */
struct audit_context {
	int		    in_syscall;	/* 1 if task is in a syscall */
	enum audit_state    state;
	unsigned int	    serial;     /* serial number for record */
	struct timespec	    ctime;      /* time of syscall entry */
	uid_t		    loginuid;   /* login uid (identity) */
	int		    major;      /* syscall number */
	unsigned long	    argv[4];    /* syscall arguments */
	int		    return_valid; /* return code is valid */
141
	long		    return_code;/* syscall return code */
L
Linus Torvalds 已提交
142 143 144
	int		    auditable;  /* 1 if record should be written */
	int		    name_count;
	struct audit_names  names[AUDIT_NAMES];
145 146
	struct dentry *	    pwd;
	struct vfsmount *   pwdmnt;
L
Linus Torvalds 已提交
147 148 149 150 151 152 153 154
	struct audit_context *previous; /* For nested syscalls */
	struct audit_aux_data *aux;

				/* Save things to print about task_struct */
	pid_t		    pid;
	uid_t		    uid, euid, suid, fsuid;
	gid_t		    gid, egid, sgid, fsgid;
	unsigned long	    personality;
155
	int		    arch;
L
Linus Torvalds 已提交
156 157 158 159 160 161 162 163 164 165 166

#if AUDIT_DEBUG
	int		    put_count;
	int		    ino_count;
#endif
};


/* Compare a task_struct with an audit_rule.  Return 1 on match, 0
 * otherwise. */
static int audit_filter_rules(struct task_struct *tsk,
167
			      struct audit_krule *rule,
L
Linus Torvalds 已提交
168 169 170
			      struct audit_context *ctx,
			      enum audit_state *state)
{
S
Steve Grubb 已提交
171
	int i, j, need_sid = 1;
172 173
	u32 sid;

L
Linus Torvalds 已提交
174
	for (i = 0; i < rule->field_count; i++) {
175
		struct audit_field *f = &rule->fields[i];
L
Linus Torvalds 已提交
176 177
		int result = 0;

178
		switch (f->type) {
L
Linus Torvalds 已提交
179
		case AUDIT_PID:
180
			result = audit_comparator(tsk->pid, f->op, f->val);
L
Linus Torvalds 已提交
181 182
			break;
		case AUDIT_UID:
183
			result = audit_comparator(tsk->uid, f->op, f->val);
L
Linus Torvalds 已提交
184 185
			break;
		case AUDIT_EUID:
186
			result = audit_comparator(tsk->euid, f->op, f->val);
L
Linus Torvalds 已提交
187 188
			break;
		case AUDIT_SUID:
189
			result = audit_comparator(tsk->suid, f->op, f->val);
L
Linus Torvalds 已提交
190 191
			break;
		case AUDIT_FSUID:
192
			result = audit_comparator(tsk->fsuid, f->op, f->val);
L
Linus Torvalds 已提交
193 194
			break;
		case AUDIT_GID:
195
			result = audit_comparator(tsk->gid, f->op, f->val);
L
Linus Torvalds 已提交
196 197
			break;
		case AUDIT_EGID:
198
			result = audit_comparator(tsk->egid, f->op, f->val);
L
Linus Torvalds 已提交
199 200
			break;
		case AUDIT_SGID:
201
			result = audit_comparator(tsk->sgid, f->op, f->val);
L
Linus Torvalds 已提交
202 203
			break;
		case AUDIT_FSGID:
204
			result = audit_comparator(tsk->fsgid, f->op, f->val);
L
Linus Torvalds 已提交
205 206
			break;
		case AUDIT_PERS:
207
			result = audit_comparator(tsk->personality, f->op, f->val);
L
Linus Torvalds 已提交
208
			break;
209
		case AUDIT_ARCH:
210
 			if (ctx)
211
				result = audit_comparator(ctx->arch, f->op, f->val);
212
			break;
L
Linus Torvalds 已提交
213 214 215

		case AUDIT_EXIT:
			if (ctx && ctx->return_valid)
216
				result = audit_comparator(ctx->return_code, f->op, f->val);
L
Linus Torvalds 已提交
217 218
			break;
		case AUDIT_SUCCESS:
219
			if (ctx && ctx->return_valid) {
220 221
				if (f->val)
					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
222
				else
223
					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
224
			}
L
Linus Torvalds 已提交
225 226 227 228
			break;
		case AUDIT_DEVMAJOR:
			if (ctx) {
				for (j = 0; j < ctx->name_count; j++) {
229
					if (audit_comparator(MAJOR(ctx->names[j].dev),	f->op, f->val)) {
L
Linus Torvalds 已提交
230 231 232 233 234 235 236 237 238
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_DEVMINOR:
			if (ctx) {
				for (j = 0; j < ctx->name_count; j++) {
239
					if (audit_comparator(MINOR(ctx->names[j].dev), f->op, f->val)) {
L
Linus Torvalds 已提交
240 241 242 243 244 245 246 247 248
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_INODE:
			if (ctx) {
				for (j = 0; j < ctx->name_count; j++) {
249 250
					if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
					    audit_comparator(ctx->names[j].pino, f->op, f->val)) {
L
Linus Torvalds 已提交
251 252 253 254 255 256 257 258 259
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_LOGINUID:
			result = 0;
			if (ctx)
260
				result = audit_comparator(ctx->loginuid, f->op, f->val);
L
Linus Torvalds 已提交
261
			break;
262 263 264 265 266 267 268 269 270 271
		case AUDIT_SE_USER:
		case AUDIT_SE_ROLE:
		case AUDIT_SE_TYPE:
		case AUDIT_SE_SEN:
		case AUDIT_SE_CLR:
			/* NOTE: this may return negative values indicating
			   a temporary error.  We simply treat this as a
			   match for now to avoid losing information that
			   may be wanted.   An error message will also be
			   logged upon error */
S
Steve Grubb 已提交
272 273 274 275 276
			if (f->se_rule) {
				if (need_sid) {
					selinux_task_ctxid(tsk, &sid);
					need_sid = 0;
				}
277 278 279 280
				result = selinux_audit_rule_match(sid, f->type,
				                                  f->op,
				                                  f->se_rule,
				                                  ctx);
S
Steve Grubb 已提交
281
			}
282
			break;
L
Linus Torvalds 已提交
283 284 285 286 287
		case AUDIT_ARG0:
		case AUDIT_ARG1:
		case AUDIT_ARG2:
		case AUDIT_ARG3:
			if (ctx)
288
				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
L
Linus Torvalds 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
			break;
		}

		if (!result)
			return 0;
	}
	switch (rule->action) {
	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
	case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
	}
	return 1;
}

/* At process creation time, we can determine if system-call auditing is
 * completely disabled for this task.  Since we only have the task
 * structure at this point, we can only check uid and gid.
 */
static enum audit_state audit_filter_task(struct task_struct *tsk)
{
	struct audit_entry *e;
	enum audit_state   state;

	rcu_read_lock();
313
	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
L
Linus Torvalds 已提交
314 315 316 317 318 319 320 321 322 323 324
		if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
			rcu_read_unlock();
			return state;
		}
	}
	rcu_read_unlock();
	return AUDIT_BUILD_CONTEXT;
}

/* At syscall entry and exit time, this filter is called if the
 * audit_state is not low enough that auditing cannot take place, but is
S
Steve Grubb 已提交
325
 * also not high enough that we already know we have to write an audit
326
 * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
L
Linus Torvalds 已提交
327 328 329 330 331 332
 */
static enum audit_state audit_filter_syscall(struct task_struct *tsk,
					     struct audit_context *ctx,
					     struct list_head *list)
{
	struct audit_entry *e;
333
	enum audit_state state;
L
Linus Torvalds 已提交
334

335
	if (audit_pid && tsk->tgid == audit_pid)
336 337
		return AUDIT_DISABLED;

L
Linus Torvalds 已提交
338
	rcu_read_lock();
339
	if (!list_empty(list)) {
340 341 342 343 344 345 346 347 348
		int word = AUDIT_WORD(ctx->major);
		int bit  = AUDIT_BIT(ctx->major);

		list_for_each_entry_rcu(e, list, list) {
			if ((e->rule.mask[word] & bit) == bit
					&& audit_filter_rules(tsk, &e->rule, ctx, &state)) {
				rcu_read_unlock();
				return state;
			}
349 350 351
		}
	}
	rcu_read_unlock();
L
Linus Torvalds 已提交
352
	return AUDIT_BUILD_CONTEXT;
353 354
}

L
Linus Torvalds 已提交
355 356 357 358 359 360 361 362 363 364 365
static inline struct audit_context *audit_get_context(struct task_struct *tsk,
						      int return_valid,
						      int return_code)
{
	struct audit_context *context = tsk->audit_context;

	if (likely(!context))
		return NULL;
	context->return_valid = return_valid;
	context->return_code  = return_code;

366
	if (context->in_syscall && !context->auditable) {
L
Linus Torvalds 已提交
367
		enum audit_state state;
368
		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
L
Linus Torvalds 已提交
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
		if (state == AUDIT_RECORD_CONTEXT)
			context->auditable = 1;
	}

	context->pid = tsk->pid;
	context->uid = tsk->uid;
	context->gid = tsk->gid;
	context->euid = tsk->euid;
	context->suid = tsk->suid;
	context->fsuid = tsk->fsuid;
	context->egid = tsk->egid;
	context->sgid = tsk->sgid;
	context->fsgid = tsk->fsgid;
	context->personality = tsk->personality;
	tsk->audit_context = NULL;
	return context;
}

static inline void audit_free_names(struct audit_context *context)
{
	int i;

#if AUDIT_DEBUG == 2
	if (context->auditable
	    ||context->put_count + context->ino_count != context->name_count) {
394
		printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d"
L
Linus Torvalds 已提交
395 396
		       " name_count=%d put_count=%d"
		       " ino_count=%d [NOT freeing]\n",
397
		       __FILE__, __LINE__,
L
Linus Torvalds 已提交
398 399 400
		       context->serial, context->major, context->in_syscall,
		       context->name_count, context->put_count,
		       context->ino_count);
401
		for (i = 0; i < context->name_count; i++) {
L
Linus Torvalds 已提交
402 403
			printk(KERN_ERR "names[%d] = %p = %s\n", i,
			       context->names[i].name,
404
			       context->names[i].name ?: "(null)");
405
		}
L
Linus Torvalds 已提交
406 407 408 409 410 411 412 413 414
		dump_stack();
		return;
	}
#endif
#if AUDIT_DEBUG
	context->put_count  = 0;
	context->ino_count  = 0;
#endif

415
	for (i = 0; i < context->name_count; i++) {
L
Linus Torvalds 已提交
416 417
		if (context->names[i].name)
			__putname(context->names[i].name);
418
	}
L
Linus Torvalds 已提交
419
	context->name_count = 0;
420 421 422 423 424 425
	if (context->pwd)
		dput(context->pwd);
	if (context->pwdmnt)
		mntput(context->pwdmnt);
	context->pwd = NULL;
	context->pwdmnt = NULL;
L
Linus Torvalds 已提交
426 427 428 429 430 431 432
}

static inline void audit_free_aux(struct audit_context *context)
{
	struct audit_aux_data *aux;

	while ((aux = context->aux)) {
433 434 435 436 437
		if (aux->type == AUDIT_AVC_PATH) {
			struct audit_aux_data_path *axi = (void *)aux;
			dput(axi->dentry);
			mntput(axi->mnt);
		}
438

L
Linus Torvalds 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
		context->aux = aux->next;
		kfree(aux);
	}
}

static inline void audit_zero_context(struct audit_context *context,
				      enum audit_state state)
{
	uid_t loginuid = context->loginuid;

	memset(context, 0, sizeof(*context));
	context->state      = state;
	context->loginuid   = loginuid;
}

static inline struct audit_context *audit_alloc_context(enum audit_state state)
{
	struct audit_context *context;

	if (!(context = kmalloc(sizeof(*context), GFP_KERNEL)))
		return NULL;
	audit_zero_context(context, state);
	return context;
}

464 465 466 467 468
/**
 * audit_alloc - allocate an audit context block for a task
 * @tsk: task
 *
 * Filter on the task information and allocate a per-task audit context
L
Linus Torvalds 已提交
469 470
 * if necessary.  Doing so turns on system call auditing for the
 * specified task.  This is called from copy_process, so no lock is
471 472
 * needed.
 */
L
Linus Torvalds 已提交
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
int audit_alloc(struct task_struct *tsk)
{
	struct audit_context *context;
	enum audit_state     state;

	if (likely(!audit_enabled))
		return 0; /* Return if not auditing. */

	state = audit_filter_task(tsk);
	if (likely(state == AUDIT_DISABLED))
		return 0;

	if (!(context = audit_alloc_context(state))) {
		audit_log_lost("out of memory in audit_alloc");
		return -ENOMEM;
	}

				/* Preserve login uid */
	context->loginuid = -1;
	if (current->audit_context)
		context->loginuid = current->audit_context->loginuid;

	tsk->audit_context  = context;
	set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
	return 0;
}

static inline void audit_free_context(struct audit_context *context)
{
	struct audit_context *previous;
	int		     count = 0;

	do {
		previous = context->previous;
		if (previous || (count &&  count < 10)) {
			++count;
			printk(KERN_ERR "audit(:%d): major=%d name_count=%d:"
			       " freeing multiple contexts (%d)\n",
			       context->serial, context->major,
			       context->name_count, count);
		}
		audit_free_names(context);
		audit_free_aux(context);
		kfree(context);
		context  = previous;
	} while (context);
	if (count >= 10)
		printk(KERN_ERR "audit: freed %d contexts\n", count);
}

523
static void audit_log_task_context(struct audit_buffer *ab)
524 525 526 527 528 529 530 531 532 533 534
{
	char *ctx = NULL;
	ssize_t len = 0;

	len = security_getprocattr(current, "current", NULL, 0);
	if (len < 0) {
		if (len != -EINVAL)
			goto error_path;
		return;
	}

535
	ctx = kmalloc(len, GFP_KERNEL);
536
	if (!ctx)
537 538 539 540 541 542 543
		goto error_path;

	len = security_getprocattr(current, "current", ctx, len);
	if (len < 0 )
		goto error_path;

	audit_log_format(ab, " subj=%s", ctx);
544
	return;
545 546 547 548

error_path:
	if (ctx)
		kfree(ctx);
549
	audit_panic("error in audit_log_task_context");
550 551 552
	return;
}

553
static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
554
{
555 556
	char name[sizeof(tsk->comm)];
	struct mm_struct *mm = tsk->mm;
557 558
	struct vm_area_struct *vma;

559 560
	/* tsk == current */

561
	get_task_comm(name, tsk);
562 563
	audit_log_format(ab, " comm=");
	audit_log_untrustedstring(ab, name);
564

565 566 567 568 569 570 571 572 573 574 575 576
	if (mm) {
		down_read(&mm->mmap_sem);
		vma = mm->mmap;
		while (vma) {
			if ((vma->vm_flags & VM_EXECUTABLE) &&
			    vma->vm_file) {
				audit_log_d_path(ab, "exe=",
						 vma->vm_file->f_dentry,
						 vma->vm_file->f_vfsmnt);
				break;
			}
			vma = vma->vm_next;
577
		}
578
		up_read(&mm->mmap_sem);
579
	}
580
	audit_log_task_context(ab);
581 582
}

583
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
L
Linus Torvalds 已提交
584
{
S
Steve Grubb 已提交
585
	int i, call_panic = 0;
L
Linus Torvalds 已提交
586
	struct audit_buffer *ab;
587
	struct audit_aux_data *aux;
588
	const char *tty;
L
Linus Torvalds 已提交
589

590 591 592
	/* tsk == current */

	ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
L
Linus Torvalds 已提交
593 594
	if (!ab)
		return;		/* audit_panic has been called */
595 596
	audit_log_format(ab, "arch=%x syscall=%d",
			 context->arch, context->major);
L
Linus Torvalds 已提交
597 598 599
	if (context->personality != PER_LINUX)
		audit_log_format(ab, " per=%lx", context->personality);
	if (context->return_valid)
600 601 602
		audit_log_format(ab, " success=%s exit=%ld", 
				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
				 context->return_code);
603 604
	if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
		tty = tsk->signal->tty->name;
605 606
	else
		tty = "(none)";
L
Linus Torvalds 已提交
607 608
	audit_log_format(ab,
		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
609 610
		  " pid=%d auid=%u uid=%u gid=%u"
		  " euid=%u suid=%u fsuid=%u"
611
		  " egid=%u sgid=%u fsgid=%u tty=%s",
L
Linus Torvalds 已提交
612 613 614 615 616 617 618 619 620 621
		  context->argv[0],
		  context->argv[1],
		  context->argv[2],
		  context->argv[3],
		  context->name_count,
		  context->pid,
		  context->loginuid,
		  context->uid,
		  context->gid,
		  context->euid, context->suid, context->fsuid,
622
		  context->egid, context->sgid, context->fsgid, tty);
623
	audit_log_task_info(ab, tsk);
L
Linus Torvalds 已提交
624 625
	audit_log_end(ab);

626
	for (aux = context->aux; aux; aux = aux->next) {
627

628
		ab = audit_log_start(context, GFP_KERNEL, aux->type);
L
Linus Torvalds 已提交
629 630 631 632
		if (!ab)
			continue; /* audit_panic has been called */

		switch (aux->type) {
633
		case AUDIT_IPC: {
L
Linus Torvalds 已提交
634 635
			struct audit_aux_data_ipcctl *axi = (void *)aux;
			audit_log_format(ab, 
S
Steve Grubb 已提交
636 637 638 639 640 641 642
				 " qbytes=%lx iuid=%u igid=%u mode=%x",
				 axi->qbytes, axi->uid, axi->gid, axi->mode);
			if (axi->osid != 0) {
				char *ctx = NULL;
				u32 len;
				if (selinux_ctxid_to_string(
						axi->osid, &ctx, &len)) {
643
					audit_log_format(ab, " osid=%u",
S
Steve Grubb 已提交
644 645 646 647 648 649
							axi->osid);
					call_panic = 1;
				} else
					audit_log_format(ab, " obj=%s", ctx);
				kfree(ctx);
			}
650 651
			break; }

S
Steve Grubb 已提交
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
		case AUDIT_IPC_SET_PERM: {
			struct audit_aux_data_ipcctl *axi = (void *)aux;
			audit_log_format(ab,
				" new qbytes=%lx new iuid=%u new igid=%u new mode=%x",
				axi->qbytes, axi->uid, axi->gid, axi->mode);
			if (axi->osid != 0) {
				char *ctx = NULL;
				u32 len;
				if (selinux_ctxid_to_string(
						axi->osid, &ctx, &len)) {
					audit_log_format(ab, " osid=%u",
							axi->osid);
					call_panic = 1;
				} else
					audit_log_format(ab, " obj=%s", ctx);
				kfree(ctx);
			}
			break; }

671 672 673 674 675 676 677 678 679 680 681 682 683 684
		case AUDIT_SOCKETCALL: {
			int i;
			struct audit_aux_data_socketcall *axs = (void *)aux;
			audit_log_format(ab, "nargs=%d", axs->nargs);
			for (i=0; i<axs->nargs; i++)
				audit_log_format(ab, " a%d=%lx", i, axs->args[i]);
			break; }

		case AUDIT_SOCKADDR: {
			struct audit_aux_data_sockaddr *axs = (void *)aux;

			audit_log_format(ab, "saddr=");
			audit_log_hex(ab, axs->a, axs->len);
			break; }
685 686 687 688 689 690

		case AUDIT_AVC_PATH: {
			struct audit_aux_data_path *axi = (void *)aux;
			audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
			break; }

L
Linus Torvalds 已提交
691 692 693 694
		}
		audit_log_end(ab);
	}

695
	if (context->pwd && context->pwdmnt) {
696
		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
697 698 699 700 701
		if (ab) {
			audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
			audit_log_end(ab);
		}
	}
L
Linus Torvalds 已提交
702
	for (i = 0; i < context->name_count; i++) {
703 704 705
		unsigned long ino  = context->names[i].ino;
		unsigned long pino = context->names[i].pino;

706
		ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
L
Linus Torvalds 已提交
707 708
		if (!ab)
			continue; /* audit_panic has been called */
709

L
Linus Torvalds 已提交
710
		audit_log_format(ab, "item=%d", i);
711 712 713

		audit_log_format(ab, " name=");
		if (context->names[i].name)
714
			audit_log_untrustedstring(ab, context->names[i].name);
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
		else
			audit_log_format(ab, "(null)");

		if (pino != (unsigned long)-1)
			audit_log_format(ab, " parent=%lu",  pino);
		if (ino != (unsigned long)-1)
			audit_log_format(ab, " inode=%lu",  ino);
		if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1))
			audit_log_format(ab, " dev=%02x:%02x mode=%#o" 
					 " ouid=%u ogid=%u rdev=%02x:%02x", 
					 MAJOR(context->names[i].dev), 
					 MINOR(context->names[i].dev), 
					 context->names[i].mode, 
					 context->names[i].uid, 
					 context->names[i].gid, 
					 MAJOR(context->names[i].rdev), 
L
Linus Torvalds 已提交
731
					 MINOR(context->names[i].rdev));
S
Steve Grubb 已提交
732 733 734 735 736
		if (context->names[i].osid != 0) {
			char *ctx = NULL;
			u32 len;
			if (selinux_ctxid_to_string(
				context->names[i].osid, &ctx, &len)) {
737
				audit_log_format(ab, " osid=%u",
S
Steve Grubb 已提交
738
						context->names[i].osid);
S
Steve Grubb 已提交
739
				call_panic = 2;
S
Steve Grubb 已提交
740 741 742
			} else
				audit_log_format(ab, " obj=%s", ctx);
			kfree(ctx);
743 744
		}

L
Linus Torvalds 已提交
745 746
		audit_log_end(ab);
	}
S
Steve Grubb 已提交
747 748
	if (call_panic)
		audit_panic("error converting sid to string");
L
Linus Torvalds 已提交
749 750
}

751 752 753 754
/**
 * audit_free - free a per-task audit context
 * @tsk: task whose audit context block to free
 *
755
 * Called from copy_process and do_exit
756
 */
L
Linus Torvalds 已提交
757 758 759 760 761 762 763 764 765
void audit_free(struct task_struct *tsk)
{
	struct audit_context *context;

	context = audit_get_context(tsk, 0, 0);
	if (likely(!context))
		return;

	/* Check for system calls that do not go through the exit
766 767 768
	 * function (e.g., exit_group), then free context block. 
	 * We use GFP_ATOMIC here because we might be doing this 
	 * in the context of the idle thread */
769
	/* that can happen only if we are called from do_exit() */
770
	if (context->in_syscall && context->auditable)
771
		audit_log_exit(context, tsk);
L
Linus Torvalds 已提交
772 773 774 775

	audit_free_context(context);
}

776 777 778 779 780 781 782 783 784 785 786
/**
 * audit_syscall_entry - fill in an audit record at syscall entry
 * @tsk: task being audited
 * @arch: architecture type
 * @major: major syscall type (function)
 * @a1: additional syscall register 1
 * @a2: additional syscall register 2
 * @a3: additional syscall register 3
 * @a4: additional syscall register 4
 *
 * Fill in audit context at syscall entry.  This only happens if the
L
Linus Torvalds 已提交
787 788 789 790 791
 * audit context was created when the task was created and the state or
 * filters demand the audit context be built.  If the state from the
 * per-task filter or from the per-syscall filter is AUDIT_RECORD_CONTEXT,
 * then the record will be written at syscall exit time (otherwise, it
 * will only be written if another part of the kernel requests that it
792 793
 * be written).
 */
794
void audit_syscall_entry(int arch, int major,
L
Linus Torvalds 已提交
795 796 797
			 unsigned long a1, unsigned long a2,
			 unsigned long a3, unsigned long a4)
{
798
	struct task_struct *tsk = current;
L
Linus Torvalds 已提交
799 800 801 802 803
	struct audit_context *context = tsk->audit_context;
	enum audit_state     state;

	BUG_ON(!context);

804 805
	/*
	 * This happens only on certain architectures that make system
L
Linus Torvalds 已提交
806 807 808 809 810 811 812
	 * calls in kernel_thread via the entry.S interface, instead of
	 * with direct calls.  (If you are porting to a new
	 * architecture, hitting this condition can indicate that you
	 * got the _exit/_leave calls backward in entry.S.)
	 *
	 * i386     no
	 * x86_64   no
813
	 * ppc64    yes (see arch/powerpc/platforms/iseries/misc.S)
L
Linus Torvalds 已提交
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
	 *
	 * This also happens with vm86 emulation in a non-nested manner
	 * (entries without exits), so this case must be caught.
	 */
	if (context->in_syscall) {
		struct audit_context *newctx;

#if AUDIT_DEBUG
		printk(KERN_ERR
		       "audit(:%d) pid=%d in syscall=%d;"
		       " entering syscall=%d\n",
		       context->serial, tsk->pid, context->major, major);
#endif
		newctx = audit_alloc_context(context->state);
		if (newctx) {
			newctx->previous   = context;
			context		   = newctx;
			tsk->audit_context = newctx;
		} else	{
			/* If we can't alloc a new context, the best we
			 * can do is to leak memory (any pending putname
			 * will be lost).  The only other alternative is
			 * to abandon auditing. */
			audit_zero_context(context, context->state);
		}
	}
	BUG_ON(context->in_syscall || context->name_count);

	if (!audit_enabled)
		return;

845
	context->arch	    = arch;
L
Linus Torvalds 已提交
846 847 848 849 850 851 852 853
	context->major      = major;
	context->argv[0]    = a1;
	context->argv[1]    = a2;
	context->argv[2]    = a3;
	context->argv[3]    = a4;

	state = context->state;
	if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)
854
		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
L
Linus Torvalds 已提交
855 856 857
	if (likely(state == AUDIT_DISABLED))
		return;

858
	context->serial     = 0;
L
Linus Torvalds 已提交
859 860 861 862 863
	context->ctime      = CURRENT_TIME;
	context->in_syscall = 1;
	context->auditable  = !!(state == AUDIT_RECORD_CONTEXT);
}

864 865 866 867 868 869 870
/**
 * audit_syscall_exit - deallocate audit context after a system call
 * @tsk: task being audited
 * @valid: success/failure flag
 * @return_code: syscall return value
 *
 * Tear down after system call.  If the audit context has been marked as
L
Linus Torvalds 已提交
871 872 873
 * auditable (either because of the AUDIT_RECORD_CONTEXT state from
 * filtering, or because some other part of the kernel write an audit
 * message), then write out the syscall information.  In call cases,
874 875
 * free the names stored from getname().
 */
876
void audit_syscall_exit(int valid, long return_code)
L
Linus Torvalds 已提交
877
{
878
	struct task_struct *tsk = current;
L
Linus Torvalds 已提交
879 880
	struct audit_context *context;

881
	context = audit_get_context(tsk, valid, return_code);
L
Linus Torvalds 已提交
882 883

	if (likely(!context))
884
		return;
L
Linus Torvalds 已提交
885

886
	if (context->in_syscall && context->auditable)
887
		audit_log_exit(context, tsk);
L
Linus Torvalds 已提交
888 889 890

	context->in_syscall = 0;
	context->auditable  = 0;
891

L
Linus Torvalds 已提交
892 893 894 895 896 897 898 899 900 901 902 903
	if (context->previous) {
		struct audit_context *new_context = context->previous;
		context->previous  = NULL;
		audit_free_context(context);
		tsk->audit_context = new_context;
	} else {
		audit_free_names(context);
		audit_free_aux(context);
		tsk->audit_context = context;
	}
}

904 905 906 907 908 909 910
/**
 * audit_getname - add a name to the list
 * @name: name to add
 *
 * Add a name to the list of audit names for this context.
 * Called from fs/namei.c:getname().
 */
L
Linus Torvalds 已提交
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
void audit_getname(const char *name)
{
	struct audit_context *context = current->audit_context;

	if (!context || IS_ERR(name) || !name)
		return;

	if (!context->in_syscall) {
#if AUDIT_DEBUG == 2
		printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n",
		       __FILE__, __LINE__, context->serial, name);
		dump_stack();
#endif
		return;
	}
	BUG_ON(context->name_count >= AUDIT_NAMES);
	context->names[context->name_count].name = name;
	context->names[context->name_count].ino  = (unsigned long)-1;
	++context->name_count;
930 931 932 933 934 935 936
	if (!context->pwd) {
		read_lock(&current->fs->lock);
		context->pwd = dget(current->fs->pwd);
		context->pwdmnt = mntget(current->fs->pwdmnt);
		read_unlock(&current->fs->lock);
	}
		
L
Linus Torvalds 已提交
937 938
}

939 940 941 942 943 944 945
/* audit_putname - intercept a putname request
 * @name: name to intercept and delay for putname
 *
 * If we have stored the name from getname in the audit context,
 * then we delay the putname until syscall exit.
 * Called from include/linux/fs.h:putname().
 */
L
Linus Torvalds 已提交
946 947 948 949 950 951 952 953 954 955 956 957 958 959
void audit_putname(const char *name)
{
	struct audit_context *context = current->audit_context;

	BUG_ON(!context);
	if (!context->in_syscall) {
#if AUDIT_DEBUG == 2
		printk(KERN_ERR "%s:%d(:%d): __putname(%p)\n",
		       __FILE__, __LINE__, context->serial, name);
		if (context->name_count) {
			int i;
			for (i = 0; i < context->name_count; i++)
				printk(KERN_ERR "name[%d] = %p = %s\n", i,
				       context->names[i].name,
960
				       context->names[i].name ?: "(null)");
L
Linus Torvalds 已提交
961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
		}
#endif
		__putname(name);
	}
#if AUDIT_DEBUG
	else {
		++context->put_count;
		if (context->put_count > context->name_count) {
			printk(KERN_ERR "%s:%d(:%d): major=%d"
			       " in_syscall=%d putname(%p) name_count=%d"
			       " put_count=%d\n",
			       __FILE__, __LINE__,
			       context->serial, context->major,
			       context->in_syscall, name, context->name_count,
			       context->put_count);
			dump_stack();
		}
	}
#endif
}

S
Steve Grubb 已提交
982
static void audit_inode_context(int idx, const struct inode *inode)
983 984 985
{
	struct audit_context *context = current->audit_context;

S
Steve Grubb 已提交
986
	selinux_get_inode_sid(inode, &context->names[idx].osid);
987 988 989
}


990 991 992 993 994 995 996 997
/**
 * audit_inode - store the inode and device from a lookup
 * @name: name being audited
 * @inode: inode being audited
 * @flags: lookup flags (as used in path_lookup())
 *
 * Called from fs/namei.c:path_lookup().
 */
998
void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
L
Linus Torvalds 已提交
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
{
	int idx;
	struct audit_context *context = current->audit_context;

	if (!context->in_syscall)
		return;
	if (context->name_count
	    && context->names[context->name_count-1].name
	    && context->names[context->name_count-1].name == name)
		idx = context->name_count - 1;
	else if (context->name_count > 1
		 && context->names[context->name_count-2].name
		 && context->names[context->name_count-2].name == name)
		idx = context->name_count - 2;
	else {
		/* FIXME: how much do we care about inodes that have no
		 * associated name? */
		if (context->name_count >= AUDIT_NAMES - AUDIT_NAMES_RESERVED)
			return;
		idx = context->name_count++;
		context->names[idx].name = NULL;
#if AUDIT_DEBUG
		++context->ino_count;
#endif
	}
1024 1025 1026 1027 1028
	context->names[idx].dev	  = inode->i_sb->s_dev;
	context->names[idx].mode  = inode->i_mode;
	context->names[idx].uid   = inode->i_uid;
	context->names[idx].gid   = inode->i_gid;
	context->names[idx].rdev  = inode->i_rdev;
1029
	audit_inode_context(idx, inode);
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
	if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) && 
	    (strcmp(name, ".") != 0)) {
		context->names[idx].ino   = (unsigned long)-1;
		context->names[idx].pino  = inode->i_ino;
	} else {
		context->names[idx].ino   = inode->i_ino;
		context->names[idx].pino  = (unsigned long)-1;
	}
}

/**
 * audit_inode_child - collect inode info for created/removed objects
 * @dname: inode's dentry name
 * @inode: inode being audited
 * @pino: inode number of dentry parent
 *
 * For syscalls that create or remove filesystem objects, audit_inode
 * can only collect information for the filesystem object's parent.
 * This call updates the audit context with the child's information.
 * Syscalls that create a new filesystem object must be hooked after
 * the object is created.  Syscalls that remove a filesystem object
 * must be hooked prior, in order to capture the target inode during
 * unsuccessful attempts.
 */
void __audit_inode_child(const char *dname, const struct inode *inode,
			 unsigned long pino)
{
	int idx;
	struct audit_context *context = current->audit_context;

	if (!context->in_syscall)
		return;

	/* determine matching parent */
	if (dname)
		for (idx = 0; idx < context->name_count; idx++)
			if (context->names[idx].pino == pino) {
				const char *n;
				const char *name = context->names[idx].name;
				int dlen = strlen(dname);
				int nlen = name ? strlen(name) : 0;

				if (nlen < dlen)
					continue;
				
				/* disregard trailing slashes */
				n = name + nlen - 1;
				while ((*n == '/') && (n > name))
					n--;

				/* find last path component */
				n = n - dlen + 1;
				if (n < name)
					continue;
				else if (n > name) {
					if (*--n != '/')
						continue;
					else
						n++;
				}

				if (strncmp(n, dname, dlen) == 0)
					goto update_context;
			}

	/* catch-all in case match not found */
	idx = context->name_count++;
	context->names[idx].name  = NULL;
	context->names[idx].pino  = pino;
#if AUDIT_DEBUG
	context->ino_count++;
#endif

update_context:
	if (inode) {
		context->names[idx].ino   = inode->i_ino;
		context->names[idx].dev	  = inode->i_sb->s_dev;
		context->names[idx].mode  = inode->i_mode;
		context->names[idx].uid   = inode->i_uid;
		context->names[idx].gid   = inode->i_gid;
		context->names[idx].rdev  = inode->i_rdev;
1111
		audit_inode_context(idx, inode);
1112
	}
L
Linus Torvalds 已提交
1113 1114
}

1115 1116 1117 1118 1119 1120 1121 1122
/**
 * auditsc_get_stamp - get local copies of audit_context values
 * @ctx: audit_context for the task
 * @t: timespec to store time recorded in the audit_context
 * @serial: serial value that is recorded in the audit_context
 *
 * Also sets the context as auditable.
 */
1123 1124
void auditsc_get_stamp(struct audit_context *ctx,
		       struct timespec *t, unsigned int *serial)
L
Linus Torvalds 已提交
1125
{
1126 1127
	if (!ctx->serial)
		ctx->serial = audit_serial();
1128 1129 1130 1131
	t->tv_sec  = ctx->ctime.tv_sec;
	t->tv_nsec = ctx->ctime.tv_nsec;
	*serial    = ctx->serial;
	ctx->auditable = 1;
L
Linus Torvalds 已提交
1132 1133
}

1134 1135 1136 1137 1138 1139 1140 1141 1142
/**
 * audit_set_loginuid - set a task's audit_context loginuid
 * @task: task whose audit context is being modified
 * @loginuid: loginuid value
 *
 * Returns 0.
 *
 * Called (set) from fs/proc/base.c::proc_loginuid_write().
 */
S
Steve Grubb 已提交
1143
int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
L
Linus Torvalds 已提交
1144
{
S
Steve Grubb 已提交
1145
	if (task->audit_context) {
1146 1147
		struct audit_buffer *ab;

1148
		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
1149 1150
		if (ab) {
			audit_log_format(ab, "login pid=%d uid=%u "
1151
				"old auid=%u new auid=%u",
1152 1153 1154 1155
				task->pid, task->uid, 
				task->audit_context->loginuid, loginuid);
			audit_log_end(ab);
		}
S
Steve Grubb 已提交
1156
		task->audit_context->loginuid = loginuid;
L
Linus Torvalds 已提交
1157 1158 1159 1160
	}
	return 0;
}

1161 1162 1163 1164 1165 1166
/**
 * audit_get_loginuid - get the loginuid for an audit_context
 * @ctx: the audit_context
 *
 * Returns the context's loginuid or -1 if @ctx is NULL.
 */
L
Linus Torvalds 已提交
1167 1168 1169 1170 1171
uid_t audit_get_loginuid(struct audit_context *ctx)
{
	return ctx ? ctx->loginuid : -1;
}

1172
/**
S
Steve Grubb 已提交
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
 * audit_ipc_obj - record audit data for ipc object
 * @ipcp: ipc permissions
 *
 * Returns 0 for success or NULL context or < 0 on error.
 */
int audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
	struct audit_aux_data_ipcctl *ax;
	struct audit_context *context = current->audit_context;

	if (likely(!context))
		return 0;

	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
	if (!ax)
		return -ENOMEM;

	ax->uid = ipcp->uid;
	ax->gid = ipcp->gid;
	ax->mode = ipcp->mode;
	selinux_get_ipc_sid(ipcp, &ax->osid);

	ax->d.type = AUDIT_IPC;
	ax->d.next = context->aux;
	context->aux = (void *)ax;
	return 0;
}

/**
 * audit_ipc_set_perm - record audit data for new ipc permissions
1203 1204 1205 1206 1207 1208 1209
 * @qbytes: msgq bytes
 * @uid: msgq user id
 * @gid: msgq group id
 * @mode: msgq mode (permissions)
 *
 * Returns 0 for success or NULL context or < 0 on error.
 */
S
Steve Grubb 已提交
1210
int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
L
Linus Torvalds 已提交
1211 1212 1213 1214 1215 1216 1217
{
	struct audit_aux_data_ipcctl *ax;
	struct audit_context *context = current->audit_context;

	if (likely(!context))
		return 0;

1218
	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
L
Linus Torvalds 已提交
1219 1220 1221 1222 1223 1224 1225
	if (!ax)
		return -ENOMEM;

	ax->qbytes = qbytes;
	ax->uid = uid;
	ax->gid = gid;
	ax->mode = mode;
S
Steve Grubb 已提交
1226
	selinux_get_ipc_sid(ipcp, &ax->osid);
L
Linus Torvalds 已提交
1227

S
Steve Grubb 已提交
1228
	ax->d.type = AUDIT_IPC_SET_PERM;
L
Linus Torvalds 已提交
1229 1230 1231 1232
	ax->d.next = context->aux;
	context->aux = (void *)ax;
	return 0;
}
1233

1234 1235 1236 1237 1238 1239 1240
/**
 * audit_socketcall - record audit data for sys_socketcall
 * @nargs: number of args
 * @args: args array
 *
 * Returns 0 for success or NULL context or < 0 on error.
 */
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
int audit_socketcall(int nargs, unsigned long *args)
{
	struct audit_aux_data_socketcall *ax;
	struct audit_context *context = current->audit_context;

	if (likely(!context))
		return 0;

	ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL);
	if (!ax)
		return -ENOMEM;

	ax->nargs = nargs;
	memcpy(ax->args, args, nargs * sizeof(unsigned long));

	ax->d.type = AUDIT_SOCKETCALL;
	ax->d.next = context->aux;
	context->aux = (void *)ax;
	return 0;
}

1262 1263 1264 1265 1266 1267 1268
/**
 * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
 * @len: data length in user space
 * @a: data address in kernel space
 *
 * Returns 0 for success or NULL context or < 0 on error.
 */
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
int audit_sockaddr(int len, void *a)
{
	struct audit_aux_data_sockaddr *ax;
	struct audit_context *context = current->audit_context;

	if (likely(!context))
		return 0;

	ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL);
	if (!ax)
		return -ENOMEM;

	ax->len = len;
	memcpy(ax->a, a, len);

	ax->d.type = AUDIT_SOCKADDR;
	ax->d.next = context->aux;
	context->aux = (void *)ax;
	return 0;
}

1290 1291 1292 1293 1294 1295 1296 1297 1298
/**
 * audit_avc_path - record the granting or denial of permissions
 * @dentry: dentry to record
 * @mnt: mnt to record
 *
 * Returns 0 for success or NULL context or < 0 on error.
 *
 * Called from security/selinux/avc.c::avc_audit()
 */
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
{
	struct audit_aux_data_path *ax;
	struct audit_context *context = current->audit_context;

	if (likely(!context))
		return 0;

	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
	if (!ax)
		return -ENOMEM;

	ax->dentry = dget(dentry);
	ax->mnt = mntget(mnt);

	ax->d.type = AUDIT_AVC_PATH;
	ax->d.next = context->aux;
	context->aux = (void *)ax;
	return 0;
}

1320 1321 1322 1323 1324 1325 1326 1327
/**
 * audit_signal_info - record signal info for shutting down audit subsystem
 * @sig: signal value
 * @t: task being signaled
 *
 * If the audit subsystem is being terminated, record the task (pid)
 * and uid that is doing that.
 */
1328 1329 1330 1331 1332
void audit_signal_info(int sig, struct task_struct *t)
{
	extern pid_t audit_sig_pid;
	extern uid_t audit_sig_uid;

1333
	if (unlikely(audit_pid && t->tgid == audit_pid)) {
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
		if (sig == SIGTERM || sig == SIGHUP) {
			struct audit_context *ctx = current->audit_context;
			audit_sig_pid = current->pid;
			if (ctx)
				audit_sig_uid = ctx->loginuid;
			else
				audit_sig_uid = current->uid;
		}
	}
}