auditsc.c 71.6 KB
Newer Older
1
/* auditsc.c -- System-call auditing support
Linus Torvalds's avatar
Linus Torvalds committed
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, 2006 IBM Corporation
Linus Torvalds's avatar
Linus Torvalds committed
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
 * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
 * 2006.
 *
35 36 37
 * The support of additional filter rules compares (>, <, >=, <=) was
 * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
 *
38 39
 * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
 * filesystem information.
40 41 42
 *
 * Subject and object context labeling support added by <danjones@us.ibm.com>
 * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
Linus Torvalds's avatar
Linus Torvalds committed
43 44 45 46
 */

#include <linux/init.h>
#include <asm/types.h>
Arun Sharma's avatar
Arun Sharma committed
47
#include <linux/atomic.h>
48 49
#include <linux/fs.h>
#include <linux/namei.h>
Linus Torvalds's avatar
Linus Torvalds committed
50
#include <linux/mm.h>
51
#include <linux/export.h>
52
#include <linux/slab.h>
53
#include <linux/mount.h>
54
#include <linux/socket.h>
55
#include <linux/mqueue.h>
Linus Torvalds's avatar
Linus Torvalds committed
56 57 58
#include <linux/audit.h>
#include <linux/personality.h>
#include <linux/time.h>
59
#include <linux/netlink.h>
60
#include <linux/compiler.h>
Linus Torvalds's avatar
Linus Torvalds committed
61
#include <asm/unistd.h>
62
#include <linux/security.h>
63
#include <linux/list.h>
64
#include <linux/tty.h>
Al Viro's avatar
Al Viro committed
65
#include <linux/binfmts.h>
66
#include <linux/highmem.h>
Al Viro's avatar
Al Viro committed
67
#include <linux/syscalls.h>
68
#include <linux/capability.h>
69
#include <linux/fs_struct.h>
70
#include <linux/compat.h>
Linus Torvalds's avatar
Linus Torvalds committed
71

72
#include "audit.h"
Linus Torvalds's avatar
Linus Torvalds committed
73

74 75 76 77 78
/* flags stating the success for a syscall */
#define AUDITSC_INVALID 0
#define AUDITSC_SUCCESS 1
#define AUDITSC_FAILURE 2

Linus Torvalds's avatar
Linus Torvalds committed
79
/* AUDIT_NAMES is the number of slots we reserve in the audit_context
80 81 82
 * for saving names from getname().  If we get more names we will allocate
 * a name dynamically and also add those to the list anchored by names_list. */
#define AUDIT_NAMES	5
Linus Torvalds's avatar
Linus Torvalds committed
83

84 85 86
/* Indicates that audit should log the full pathname. */
#define AUDIT_NAME_FULL -1

87 88 89
/* no execve audit message should be longer than this (userspace limits) */
#define MAX_EXECVE_AUDIT_LEN 7500

90 91 92
/* number of audit rules */
int audit_n_rules;

93 94 95
/* determines whether we collect data for signals sent */
int audit_signals;

96 97 98 99 100 101 102 103 104
struct audit_cap_data {
	kernel_cap_t		permitted;
	kernel_cap_t		inheritable;
	union {
		unsigned int	fE;		/* effective bit of a file capability */
		kernel_cap_t	effective;	/* effective set of a process */
	};
};

Linus Torvalds's avatar
Linus Torvalds committed
105 106 107 108 109 110
/* 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 {
111
	struct list_head list;		/* audit_context->names_list */
Linus Torvalds's avatar
Linus Torvalds committed
112 113 114 115
	const char	*name;
	unsigned long	ino;
	dev_t		dev;
	umode_t		mode;
116 117
	kuid_t		uid;
	kgid_t		gid;
Linus Torvalds's avatar
Linus Torvalds committed
118
	dev_t		rdev;
Steve Grubb's avatar
Steve Grubb committed
119
	u32		osid;
120 121
	struct audit_cap_data fcap;
	unsigned int	fcap_ver;
122 123 124 125 126 127 128 129
	int		name_len;	/* number of name's characters to log */
	bool		name_put;	/* call __putname() for this name */
	/*
	 * This was an allocated audit_names and not from the array of
	 * names allocated in the task audit context.  Thus this name
	 * should be freed on syscall exit
	 */
	bool		should_free;
Linus Torvalds's avatar
Linus Torvalds committed
130 131 132 133 134 135 136 137 138
};

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

#define AUDIT_AUX_IPCPERM	0

139 140 141
/* Number of target pids per aux struct. */
#define AUDIT_AUX_PIDS	16

Al Viro's avatar
Al Viro committed
142 143 144 145
struct audit_aux_data_execve {
	struct audit_aux_data	d;
	int argc;
	int envc;
Peter Zijlstra's avatar
Peter Zijlstra committed
146
	struct mm_struct *mm;
Al Viro's avatar
Al Viro committed
147 148
};

149 150 151
struct audit_aux_data_pids {
	struct audit_aux_data	d;
	pid_t			target_pid[AUDIT_AUX_PIDS];
152
	kuid_t			target_auid[AUDIT_AUX_PIDS];
153
	kuid_t			target_uid[AUDIT_AUX_PIDS];
154
	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
155
	u32			target_sid[AUDIT_AUX_PIDS];
156
	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
157 158 159
	int			pid_count;
};

160 161 162 163 164 165 166 167
struct audit_aux_data_bprm_fcaps {
	struct audit_aux_data	d;
	struct audit_cap_data	fcap;
	unsigned int		fcap_ver;
	struct audit_cap_data	old_pcap;
	struct audit_cap_data	new_pcap;
};

168 169 170 171 172 173
struct audit_aux_data_capset {
	struct audit_aux_data	d;
	pid_t			pid;
	struct audit_cap_data	cap;
};

Al Viro's avatar
Al Viro committed
174 175 176 177 178
struct audit_tree_refs {
	struct audit_tree_refs *next;
	struct audit_chunk *c[31];
};

Linus Torvalds's avatar
Linus Torvalds committed
179 180
/* The per-task audit context. */
struct audit_context {
181
	int		    dummy;	/* must be the first element */
Linus Torvalds's avatar
Linus Torvalds committed
182
	int		    in_syscall;	/* 1 if task is in a syscall */
183
	enum audit_state    state, current_state;
Linus Torvalds's avatar
Linus Torvalds committed
184 185
	unsigned int	    serial;     /* serial number for record */
	int		    major;      /* syscall number */
186
	struct timespec	    ctime;      /* time of syscall entry */
Linus Torvalds's avatar
Linus Torvalds committed
187
	unsigned long	    argv[4];    /* syscall arguments */
188
	long		    return_code;/* syscall return code */
189
	u64		    prio;
190
	int		    return_valid; /* return code is valid */
191 192 193 194 195 196 197 198 199 200 201
	/*
	 * The names_list is the list of all audit_names collected during this
	 * syscall.  The first AUDIT_NAMES entries in the names_list will
	 * actually be from the preallocated_names array for performance
	 * reasons.  Except during allocation they should never be referenced
	 * through the preallocated_names array and should only be found/used
	 * by running the names_list.
	 */
	struct audit_names  preallocated_names[AUDIT_NAMES];
	int		    name_count; /* total records in names_list */
	struct list_head    names_list;	/* anchor for struct audit_names->list */
Amy Griffis's avatar
Amy Griffis committed
202
	char *		    filterkey;	/* key for rule that triggered record */
203
	struct path	    pwd;
Linus Torvalds's avatar
Linus Torvalds committed
204 205
	struct audit_context *previous; /* For nested syscalls */
	struct audit_aux_data *aux;
206
	struct audit_aux_data *aux_pids;
207 208
	struct sockaddr_storage *sockaddr;
	size_t sockaddr_len;
Linus Torvalds's avatar
Linus Torvalds committed
209
				/* Save things to print about task_struct */
Al Viro's avatar
Al Viro committed
210
	pid_t		    pid, ppid;
211 212
	kuid_t		    uid, euid, suid, fsuid;
	kgid_t		    gid, egid, sgid, fsgid;
Linus Torvalds's avatar
Linus Torvalds committed
213
	unsigned long	    personality;
214
	int		    arch;
Linus Torvalds's avatar
Linus Torvalds committed
215

Al Viro's avatar
Al Viro committed
216
	pid_t		    target_pid;
217
	kuid_t		    target_auid;
218
	kuid_t		    target_uid;
219
	unsigned int	    target_sessionid;
Al Viro's avatar
Al Viro committed
220
	u32		    target_sid;
221
	char		    target_comm[TASK_COMM_LEN];
Al Viro's avatar
Al Viro committed
222

Al Viro's avatar
Al Viro committed
223
	struct audit_tree_refs *trees, *first_trees;
224
	struct list_head killed_trees;
225
	int tree_count;
Al Viro's avatar
Al Viro committed
226

Al Viro's avatar
Al Viro committed
227 228 229 230 231 232
	int type;
	union {
		struct {
			int nargs;
			long args[6];
		} socketcall;
Al Viro's avatar
Al Viro committed
233
		struct {
234 235
			kuid_t			uid;
			kgid_t			gid;
Al Viro's avatar
Al Viro committed
236
			umode_t			mode;
Al Viro's avatar
Al Viro committed
237
			u32			osid;
Al Viro's avatar
Al Viro committed
238 239 240
			int			has_perm;
			uid_t			perm_uid;
			gid_t			perm_gid;
Al Viro's avatar
Al Viro committed
241
			umode_t			perm_mode;
Al Viro's avatar
Al Viro committed
242
			unsigned long		qbytes;
Al Viro's avatar
Al Viro committed
243
		} ipc;
Al Viro's avatar
Al Viro committed
244 245 246 247
		struct {
			mqd_t			mqdes;
			struct mq_attr 		mqstat;
		} mq_getsetattr;
Al Viro's avatar
Al Viro committed
248 249 250 251
		struct {
			mqd_t			mqdes;
			int			sigev_signo;
		} mq_notify;
Al Viro's avatar
Al Viro committed
252 253 254 255 256 257
		struct {
			mqd_t			mqdes;
			size_t			msg_len;
			unsigned int		msg_prio;
			struct timespec		abs_timeout;
		} mq_sendrecv;
Al Viro's avatar
Al Viro committed
258 259
		struct {
			int			oflag;
Al Viro's avatar
Al Viro committed
260
			umode_t			mode;
Al Viro's avatar
Al Viro committed
261 262
			struct mq_attr		attr;
		} mq_open;
Al Viro's avatar
Al Viro committed
263 264 265 266
		struct {
			pid_t			pid;
			struct audit_cap_data	cap;
		} capset;
Al Viro's avatar
Al Viro committed
267 268 269 270
		struct {
			int			fd;
			int			flags;
		} mmap;
Al Viro's avatar
Al Viro committed
271
	};
Al Viro's avatar
Al Viro committed
272
	int fds[2];
Al Viro's avatar
Al Viro committed
273

Linus Torvalds's avatar
Linus Torvalds committed
274 275 276 277 278 279
#if AUDIT_DEBUG
	int		    put_count;
	int		    ino_count;
#endif
};

Al Viro's avatar
Al Viro committed
280 281 282 283 284 285 286 287 288 289
static inline int open_arg(int flags, int mask)
{
	int n = ACC_MODE(flags);
	if (flags & (O_TRUNC | O_CREAT))
		n |= AUDIT_PERM_WRITE;
	return n & mask;
}

static int audit_match_perm(struct audit_context *ctx, int mask)
{
290
	unsigned n;
291 292
	if (unlikely(!ctx))
		return 0;
293
	n = ctx->major;
294

Al Viro's avatar
Al Viro committed
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
	switch (audit_classify_syscall(ctx->arch, n)) {
	case 0:	/* native */
		if ((mask & AUDIT_PERM_WRITE) &&
		     audit_match_class(AUDIT_CLASS_WRITE, n))
			return 1;
		if ((mask & AUDIT_PERM_READ) &&
		     audit_match_class(AUDIT_CLASS_READ, n))
			return 1;
		if ((mask & AUDIT_PERM_ATTR) &&
		     audit_match_class(AUDIT_CLASS_CHATTR, n))
			return 1;
		return 0;
	case 1: /* 32bit on biarch */
		if ((mask & AUDIT_PERM_WRITE) &&
		     audit_match_class(AUDIT_CLASS_WRITE_32, n))
			return 1;
		if ((mask & AUDIT_PERM_READ) &&
		     audit_match_class(AUDIT_CLASS_READ_32, n))
			return 1;
		if ((mask & AUDIT_PERM_ATTR) &&
		     audit_match_class(AUDIT_CLASS_CHATTR_32, n))
			return 1;
		return 0;
	case 2: /* open */
		return mask & ACC_MODE(ctx->argv[1]);
	case 3: /* openat */
		return mask & ACC_MODE(ctx->argv[2]);
	case 4: /* socketcall */
		return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
	case 5: /* execve */
		return mask & AUDIT_PERM_EXEC;
	default:
		return 0;
	}
}

331
static int audit_match_filetype(struct audit_context *ctx, int val)
332
{
333
	struct audit_names *n;
334
	umode_t mode = (umode_t)val;
335 336 337 338

	if (unlikely(!ctx))
		return 0;

339 340 341
	list_for_each_entry(n, &ctx->names_list, list) {
		if ((n->ino != -1) &&
		    ((n->mode & S_IFMT) == mode))
342 343
			return 1;
	}
344

345
	return 0;
346 347
}

Al Viro's avatar
Al Viro committed
348 349 350 351 352 353 354 355 356 357 358
/*
 * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
 * ->first_trees points to its beginning, ->trees - to the current end of data.
 * ->tree_count is the number of free entries in array pointed to by ->trees.
 * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL,
 * "empty" becomes (p, p, 31) afterwards.  We don't shrink the list (and seriously,
 * it's going to remain 1-element for almost any setup) until we free context itself.
 * References in it _are_ dropped - at the same time we free/drop aux stuff.
 */

#ifdef CONFIG_AUDIT_TREE
359 360 361 362 363 364 365 366
static void audit_set_auditable(struct audit_context *ctx)
{
	if (!ctx->prio) {
		ctx->prio = 1;
		ctx->current_state = AUDIT_RECORD_CONTEXT;
	}
}

Al Viro's avatar
Al Viro committed
367 368 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 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 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 464 465 466
static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
{
	struct audit_tree_refs *p = ctx->trees;
	int left = ctx->tree_count;
	if (likely(left)) {
		p->c[--left] = chunk;
		ctx->tree_count = left;
		return 1;
	}
	if (!p)
		return 0;
	p = p->next;
	if (p) {
		p->c[30] = chunk;
		ctx->trees = p;
		ctx->tree_count = 30;
		return 1;
	}
	return 0;
}

static int grow_tree_refs(struct audit_context *ctx)
{
	struct audit_tree_refs *p = ctx->trees;
	ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
	if (!ctx->trees) {
		ctx->trees = p;
		return 0;
	}
	if (p)
		p->next = ctx->trees;
	else
		ctx->first_trees = ctx->trees;
	ctx->tree_count = 31;
	return 1;
}
#endif

static void unroll_tree_refs(struct audit_context *ctx,
		      struct audit_tree_refs *p, int count)
{
#ifdef CONFIG_AUDIT_TREE
	struct audit_tree_refs *q;
	int n;
	if (!p) {
		/* we started with empty chain */
		p = ctx->first_trees;
		count = 31;
		/* if the very first allocation has failed, nothing to do */
		if (!p)
			return;
	}
	n = count;
	for (q = p; q != ctx->trees; q = q->next, n = 31) {
		while (n--) {
			audit_put_chunk(q->c[n]);
			q->c[n] = NULL;
		}
	}
	while (n-- > ctx->tree_count) {
		audit_put_chunk(q->c[n]);
		q->c[n] = NULL;
	}
	ctx->trees = p;
	ctx->tree_count = count;
#endif
}

static void free_tree_refs(struct audit_context *ctx)
{
	struct audit_tree_refs *p, *q;
	for (p = ctx->first_trees; p; p = q) {
		q = p->next;
		kfree(p);
	}
}

static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
{
#ifdef CONFIG_AUDIT_TREE
	struct audit_tree_refs *p;
	int n;
	if (!tree)
		return 0;
	/* full ones */
	for (p = ctx->first_trees; p != ctx->trees; p = p->next) {
		for (n = 0; n < 31; n++)
			if (audit_tree_match(p->c[n], tree))
				return 1;
	}
	/* partial */
	if (p) {
		for (n = ctx->tree_count; n < 31; n++)
			if (audit_tree_match(p->c[n], tree))
				return 1;
	}
#endif
	return 0;
}

467 468 469 470
static int audit_compare_uid(kuid_t uid,
			     struct audit_names *name,
			     struct audit_field *f,
			     struct audit_context *ctx)
471 472 473
{
	struct audit_names *n;
	int rc;
474
 
475
	if (name) {
476
		rc = audit_uid_comparator(uid, f->op, name->uid);
477 478 479
		if (rc)
			return rc;
	}
480
 
481 482
	if (ctx) {
		list_for_each_entry(n, &ctx->names_list, list) {
483 484 485 486 487 488 489
			rc = audit_uid_comparator(uid, f->op, n->uid);
			if (rc)
				return rc;
		}
	}
	return 0;
}
490

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
static int audit_compare_gid(kgid_t gid,
			     struct audit_names *name,
			     struct audit_field *f,
			     struct audit_context *ctx)
{
	struct audit_names *n;
	int rc;
 
	if (name) {
		rc = audit_gid_comparator(gid, f->op, name->gid);
		if (rc)
			return rc;
	}
 
	if (ctx) {
		list_for_each_entry(n, &ctx->names_list, list) {
			rc = audit_gid_comparator(gid, f->op, n->gid);
508 509 510 511 512 513 514
			if (rc)
				return rc;
		}
	}
	return 0;
}

515 516 517 518 519 520 521
static int audit_field_compare(struct task_struct *tsk,
			       const struct cred *cred,
			       struct audit_field *f,
			       struct audit_context *ctx,
			       struct audit_names *name)
{
	switch (f->val) {
522
	/* process to file object comparisons */
523
	case AUDIT_COMPARE_UID_TO_OBJ_UID:
524
		return audit_compare_uid(cred->uid, name, f, ctx);
525
	case AUDIT_COMPARE_GID_TO_OBJ_GID:
526
		return audit_compare_gid(cred->gid, name, f, ctx);
527
	case AUDIT_COMPARE_EUID_TO_OBJ_UID:
528
		return audit_compare_uid(cred->euid, name, f, ctx);
529
	case AUDIT_COMPARE_EGID_TO_OBJ_GID:
530
		return audit_compare_gid(cred->egid, name, f, ctx);
531
	case AUDIT_COMPARE_AUID_TO_OBJ_UID:
532
		return audit_compare_uid(tsk->loginuid, name, f, ctx);
533
	case AUDIT_COMPARE_SUID_TO_OBJ_UID:
534
		return audit_compare_uid(cred->suid, name, f, ctx);
535
	case AUDIT_COMPARE_SGID_TO_OBJ_GID:
536
		return audit_compare_gid(cred->sgid, name, f, ctx);
537
	case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
538
		return audit_compare_uid(cred->fsuid, name, f, ctx);
539
	case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
540
		return audit_compare_gid(cred->fsgid, name, f, ctx);
541 542
	/* uid comparisons */
	case AUDIT_COMPARE_UID_TO_AUID:
543
		return audit_uid_comparator(cred->uid, f->op, tsk->loginuid);
544
	case AUDIT_COMPARE_UID_TO_EUID:
545
		return audit_uid_comparator(cred->uid, f->op, cred->euid);
546
	case AUDIT_COMPARE_UID_TO_SUID:
547
		return audit_uid_comparator(cred->uid, f->op, cred->suid);
548
	case AUDIT_COMPARE_UID_TO_FSUID:
549
		return audit_uid_comparator(cred->uid, f->op, cred->fsuid);
550 551
	/* auid comparisons */
	case AUDIT_COMPARE_AUID_TO_EUID:
552
		return audit_uid_comparator(tsk->loginuid, f->op, cred->euid);
553
	case AUDIT_COMPARE_AUID_TO_SUID:
554
		return audit_uid_comparator(tsk->loginuid, f->op, cred->suid);
555
	case AUDIT_COMPARE_AUID_TO_FSUID:
556
		return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid);
557 558
	/* euid comparisons */
	case AUDIT_COMPARE_EUID_TO_SUID:
559
		return audit_uid_comparator(cred->euid, f->op, cred->suid);
560
	case AUDIT_COMPARE_EUID_TO_FSUID:
561
		return audit_uid_comparator(cred->euid, f->op, cred->fsuid);
562 563
	/* suid comparisons */
	case AUDIT_COMPARE_SUID_TO_FSUID:
564
		return audit_uid_comparator(cred->suid, f->op, cred->fsuid);
565 566
	/* gid comparisons */
	case AUDIT_COMPARE_GID_TO_EGID:
567
		return audit_gid_comparator(cred->gid, f->op, cred->egid);
568
	case AUDIT_COMPARE_GID_TO_SGID:
569
		return audit_gid_comparator(cred->gid, f->op, cred->sgid);
570
	case AUDIT_COMPARE_GID_TO_FSGID:
571
		return audit_gid_comparator(cred->gid, f->op, cred->fsgid);
572 573
	/* egid comparisons */
	case AUDIT_COMPARE_EGID_TO_SGID:
574
		return audit_gid_comparator(cred->egid, f->op, cred->sgid);
575
	case AUDIT_COMPARE_EGID_TO_FSGID:
576
		return audit_gid_comparator(cred->egid, f->op, cred->fsgid);
577 578
	/* sgid comparison */
	case AUDIT_COMPARE_SGID_TO_FSGID:
579
		return audit_gid_comparator(cred->sgid, f->op, cred->fsgid);
580 581 582 583 584 585 586
	default:
		WARN(1, "Missing AUDIT_COMPARE define.  Report as a bug\n");
		return 0;
	}
	return 0;
}

587
/* Determine if any context name data matches a rule's watch data */
Linus Torvalds's avatar
Linus Torvalds committed
588
/* Compare a task_struct with an audit_rule.  Return 1 on match, 0
589 590 591 592 593 594
 * otherwise.
 *
 * If task_creation is true, this is an explicit indication that we are
 * filtering a task rule at task creation time.  This and tsk == current are
 * the only situations where tsk->cred may be accessed without an rcu read lock.
 */
Linus Torvalds's avatar
Linus Torvalds committed
595
static int audit_filter_rules(struct task_struct *tsk,
596
			      struct audit_krule *rule,
Linus Torvalds's avatar
Linus Torvalds committed
597
			      struct audit_context *ctx,
598
			      struct audit_names *name,
599 600
			      enum audit_state *state,
			      bool task_creation)
Linus Torvalds's avatar
Linus Torvalds committed
601
{
602
	const struct cred *cred;
603
	int i, need_sid = 1;
604 605
	u32 sid;

606 607
	cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);

Linus Torvalds's avatar
Linus Torvalds committed
608
	for (i = 0; i < rule->field_count; i++) {
609
		struct audit_field *f = &rule->fields[i];
610
		struct audit_names *n;
Linus Torvalds's avatar
Linus Torvalds committed
611 612
		int result = 0;

613
		switch (f->type) {
Linus Torvalds's avatar
Linus Torvalds committed
614
		case AUDIT_PID:
615
			result = audit_comparator(tsk->pid, f->op, f->val);
Linus Torvalds's avatar
Linus Torvalds committed
616
			break;
Al Viro's avatar
Al Viro committed
617
		case AUDIT_PPID:
Alexander Viro's avatar
Alexander Viro committed
618 619 620
			if (ctx) {
				if (!ctx->ppid)
					ctx->ppid = sys_getppid();
Al Viro's avatar
Al Viro committed
621
				result = audit_comparator(ctx->ppid, f->op, f->val);
Alexander Viro's avatar
Alexander Viro committed
622
			}
Al Viro's avatar
Al Viro committed
623
			break;
Linus Torvalds's avatar
Linus Torvalds committed
624
		case AUDIT_UID:
625
			result = audit_uid_comparator(cred->uid, f->op, f->uid);
Linus Torvalds's avatar
Linus Torvalds committed
626 627
			break;
		case AUDIT_EUID:
628
			result = audit_uid_comparator(cred->euid, f->op, f->uid);
Linus Torvalds's avatar
Linus Torvalds committed
629 630
			break;
		case AUDIT_SUID:
631
			result = audit_uid_comparator(cred->suid, f->op, f->uid);
Linus Torvalds's avatar
Linus Torvalds committed
632 633
			break;
		case AUDIT_FSUID:
634
			result = audit_uid_comparator(cred->fsuid, f->op, f->uid);
Linus Torvalds's avatar
Linus Torvalds committed
635 636
			break;
		case AUDIT_GID:
637
			result = audit_gid_comparator(cred->gid, f->op, f->gid);
Linus Torvalds's avatar
Linus Torvalds committed
638 639
			break;
		case AUDIT_EGID:
640
			result = audit_gid_comparator(cred->egid, f->op, f->gid);
Linus Torvalds's avatar
Linus Torvalds committed
641 642
			break;
		case AUDIT_SGID:
643
			result = audit_gid_comparator(cred->sgid, f->op, f->gid);
Linus Torvalds's avatar
Linus Torvalds committed
644 645
			break;
		case AUDIT_FSGID:
646
			result = audit_gid_comparator(cred->fsgid, f->op, f->gid);
Linus Torvalds's avatar
Linus Torvalds committed
647 648
			break;
		case AUDIT_PERS:
649
			result = audit_comparator(tsk->personality, f->op, f->val);
Linus Torvalds's avatar
Linus Torvalds committed
650
			break;
651
		case AUDIT_ARCH:
652
			if (ctx)
653
				result = audit_comparator(ctx->arch, f->op, f->val);
654
			break;
Linus Torvalds's avatar
Linus Torvalds committed
655 656 657

		case AUDIT_EXIT:
			if (ctx && ctx->return_valid)
658
				result = audit_comparator(ctx->return_code, f->op, f->val);
Linus Torvalds's avatar
Linus Torvalds committed
659 660
			break;
		case AUDIT_SUCCESS:
661
			if (ctx && ctx->return_valid) {
662 663
				if (f->val)
					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
664
				else
665
					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
666
			}
Linus Torvalds's avatar
Linus Torvalds committed
667 668
			break;
		case AUDIT_DEVMAJOR:
669 670 671 672 673
			if (name) {
				if (audit_comparator(MAJOR(name->dev), f->op, f->val) ||
				    audit_comparator(MAJOR(name->rdev), f->op, f->val))
					++result;
			} else if (ctx) {
674
				list_for_each_entry(n, &ctx->names_list, list) {
675 676
					if (audit_comparator(MAJOR(n->dev), f->op, f->val) ||
					    audit_comparator(MAJOR(n->rdev), f->op, f->val)) {
Linus Torvalds's avatar
Linus Torvalds committed
677 678 679 680 681 682 683
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_DEVMINOR:
684 685 686 687 688
			if (name) {
				if (audit_comparator(MINOR(name->dev), f->op, f->val) ||
				    audit_comparator(MINOR(name->rdev), f->op, f->val))
					++result;
			} else if (ctx) {
689
				list_for_each_entry(n, &ctx->names_list, list) {
690 691
					if (audit_comparator(MINOR(n->dev), f->op, f->val) ||
					    audit_comparator(MINOR(n->rdev), f->op, f->val)) {
Linus Torvalds's avatar
Linus Torvalds committed
692 693 694 695 696 697 698
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_INODE:
699
			if (name)
700
				result = (name->ino == f->val);
701
			else if (ctx) {
702 703
				list_for_each_entry(n, &ctx->names_list, list) {
					if (audit_comparator(n->ino, f->op, f->val)) {
Linus Torvalds's avatar
Linus Torvalds committed
704 705 706 707 708 709
						++result;
						break;
					}
				}
			}
			break;
710 711
		case AUDIT_OBJ_UID:
			if (name) {
712
				result = audit_uid_comparator(name->uid, f->op, f->uid);
713 714
			} else if (ctx) {
				list_for_each_entry(n, &ctx->names_list, list) {
715
					if (audit_uid_comparator(n->uid, f->op, f->uid)) {
716 717 718 719 720 721
						++result;
						break;
					}
				}
			}
			break;
722 723
		case AUDIT_OBJ_GID:
			if (name) {
724
				result = audit_gid_comparator(name->gid, f->op, f->gid);
725 726
			} else if (ctx) {
				list_for_each_entry(n, &ctx->names_list, list) {
727
					if (audit_gid_comparator(n->gid, f->op, f->gid)) {
728 729 730 731 732 733
						++result;
						break;
					}
				}
			}
			break;
734
		case AUDIT_WATCH:
735 736
			if (name)
				result = audit_watch_compare(rule->watch, name->ino, name->dev);
737
			break;
Al Viro's avatar
Al Viro committed
738 739 740 741
		case AUDIT_DIR:
			if (ctx)
				result = match_tree_refs(ctx, rule->tree);
			break;
Linus Torvalds's avatar
Linus Torvalds committed
742 743 744
		case AUDIT_LOGINUID:
			result = 0;
			if (ctx)
745
				result = audit_uid_comparator(tsk->loginuid, f->op, f->uid);
Linus Torvalds's avatar
Linus Torvalds committed
746
			break;
747 748 749 750 751
		case AUDIT_SUBJ_USER:
		case AUDIT_SUBJ_ROLE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
752 753 754 755 756
			/* 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 */
757
			if (f->lsm_rule) {
758
				if (need_sid) {
759
					security_task_getsecid(tsk, &sid);
760 761
					need_sid = 0;
				}
762
				result = security_audit_rule_match(sid, f->type,
763
				                                  f->op,
764
				                                  f->lsm_rule,
765
				                                  ctx);
766
			}
767
			break;
768 769 770 771 772 773 774
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
			   also applies here */
775
			if (f->lsm_rule) {
776 777
				/* Find files that match */
				if (name) {
778
					result = security_audit_rule_match(
779
					           name->osid, f->type, f->op,
780
					           f->lsm_rule, ctx);
781
				} else if (ctx) {
782 783 784 785
					list_for_each_entry(n, &ctx->names_list, list) {
						if (security_audit_rule_match(n->osid, f->type,
									      f->op, f->lsm_rule,
									      ctx)) {
786 787 788 789 790 791
							++result;
							break;
						}
					}
				}
				/* Find ipc objects that match */
Al Viro's avatar
Al Viro committed
792 793 794 795 796 797
				if (!ctx || ctx->type != AUDIT_IPC)
					break;
				if (security_audit_rule_match(ctx->ipc.osid,
							      f->type, f->op,
							      f->lsm_rule, ctx))
					++result;
798 799
			}
			break;
Linus Torvalds's avatar
Linus Torvalds committed
800 801 802 803 804
		case AUDIT_ARG0:
		case AUDIT_ARG1:
		case AUDIT_ARG2:
		case AUDIT_ARG3:
			if (ctx)
805
				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
Linus Torvalds's avatar
Linus Torvalds committed
806
			break;
Amy Griffis's avatar
Amy Griffis committed
807 808 809 810
		case AUDIT_FILTERKEY:
			/* ignore this field for filtering */
			result = 1;
			break;
Al Viro's avatar
Al Viro committed
811 812 813
		case AUDIT_PERM:
			result = audit_match_perm(ctx, f->val);
			break;
814 815 816
		case AUDIT_FILETYPE:
			result = audit_match_filetype(ctx, f->val);
			break;
817 818 819
		case AUDIT_FIELD_COMPARE:
			result = audit_field_compare(tsk, cred, f, ctx, name);
			break;
Linus Torvalds's avatar
Linus Torvalds committed
820
		}
821
		if (!result)
Linus Torvalds's avatar
Linus Torvalds committed
822 823
			return 0;
	}
824 825 826 827 828 829 830 831 832 833

	if (ctx) {
		if (rule->prio <= ctx->prio)
			return 0;
		if (rule->filterkey) {
			kfree(ctx->filterkey);
			ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
		}
		ctx->prio = rule->prio;
	}
Linus Torvalds's avatar
Linus Torvalds committed
834 835 836 837 838 839 840 841 842 843 844
	switch (rule->action) {
	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    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.
 */
845
static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
Linus Torvalds's avatar
Linus Torvalds committed
846 847 848 849 850
{
	struct audit_entry *e;
	enum audit_state   state;

	rcu_read_lock();
851
	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
852 853
		if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
				       &state, true)) {
854 855
			if (state == AUDIT_RECORD_CONTEXT)
				*key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
Linus Torvalds's avatar
Linus Torvalds committed
856 857 858 859 860 861 862 863 864 865
			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
866
 * also not high enough that we already know we have to write an audit
867
 * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
Linus Torvalds's avatar
Linus Torvalds committed
868 869 870 871 872 873
 */
static enum audit_state audit_filter_syscall(struct task_struct *tsk,
					     struct audit_context *ctx,
					     struct list_head *list)
{
	struct audit_entry *e;
874
	enum audit_state state;
Linus Torvalds's avatar
Linus Torvalds committed
875

876
	if (audit_pid && tsk->tgid == audit_pid)
877 878
		return AUDIT_DISABLED;

Linus Torvalds's avatar
Linus Torvalds committed
879
	rcu_read_lock();
880
	if (!list_empty(list)) {
881 882 883 884
		int word = AUDIT_WORD(ctx->major);
		int bit  = AUDIT_BIT(ctx->major);

		list_for_each_entry_rcu(e, list, list) {
885 886
			if ((e->rule.mask[word] & bit) == bit &&
			    audit_filter_rules(tsk, &e->rule, ctx, NULL,
887
					       &state, false)) {
888
				rcu_read_unlock();
889
				ctx->current_state = state;
890 891 892 893 894 895 896 897
				return state;
			}
		}
	}
	rcu_read_unlock();
	return AUDIT_BUILD_CONTEXT;
}

898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
/*
 * Given an audit_name check the inode hash table to see if they match.
 * Called holding the rcu read lock to protect the use of audit_inode_hash
 */
static int audit_filter_inode_name(struct task_struct *tsk,
				   struct audit_names *n,
				   struct audit_context *ctx) {
	int word, bit;
	int h = audit_hash_ino((u32)n->ino);
	struct list_head *list = &audit_inode_hash[h];
	struct audit_entry *e;
	enum audit_state state;

	word = AUDIT_WORD(ctx->major);
	bit  = AUDIT_BIT(ctx->major);

	if (list_empty(list))
		return 0;

	list_for_each_entry_rcu(e, list, list) {
		if ((e->rule.mask[word] & bit) == bit &&
		    audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
			ctx->current_state = state;
			return 1;
		}
	}

	return 0;
}

/* At syscall exit time, this filter is called if any audit_names have been
929
 * collected during syscall processing.  We only check rules in sublists at hash
930
 * buckets applicable to the inode numbers in audit_names.
931 932
 * Regarding audit_state, same rules apply as for audit_filter_syscall().
 */
933
void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
934
{
935
	struct audit_names *n;
936 937

	if (audit_pid && tsk->tgid == audit_pid)
938
		return;
939 940 941

	rcu_read_lock();

942 943 944
	list_for_each_entry(n, &ctx->names_list, list) {
		if (audit_filter_inode_name(tsk, n, ctx))
			break;
945 946 947 948
	}
	rcu_read_unlock();
}

Linus Torvalds's avatar
Linus Torvalds committed
949 950
static inline struct audit_context *audit_get_context(struct task_struct *tsk,
						      int return_valid,
951
						      long return_code)
Linus Torvalds's avatar
Linus Torvalds committed
952 953 954
{
	struct audit_context *context = tsk->audit_context;

955
	if (!context)
Linus Torvalds's avatar
Linus Torvalds committed
956 957
		return NULL;
	context->return_valid = return_valid;
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975

	/*
	 * we need to fix up the return code in the audit logs if the actual
	 * return codes are later going to be fixed up by the arch specific
	 * signal handlers
	 *
	 * This is actually a test for:
	 * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
	 * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
	 *
	 * but is faster than a bunch of ||
	 */
	if (unlikely(return_code <= -ERESTARTSYS) &&
	    (return_code >= -ERESTART_RESTARTBLOCK) &&
	    (return_code != -ENOIOCTLCMD))
		context->return_code = -EINTR;
	else
		context->return_code  = return_code;
Linus Torvalds's avatar
Linus Torvalds committed
976

977 978 979
	if (context->in_syscall && !context->dummy) {
		audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
		audit_filter_inodes(tsk, context);
Linus Torvalds's avatar
Linus Torvalds committed
980 981 982 983 984 985 986 987
	}

	tsk->audit_context = NULL;
	return context;
}

static inline void audit_free_names(struct audit_context *context)
{
988
	struct audit_names *n, *next;
Linus Torvalds's avatar
Linus Torvalds committed
989 990

#if AUDIT_DEBUG == 2
991
	if (context->put_count + context->ino_count != context->name_count) {
992
		printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d"
Linus Torvalds's avatar
Linus Torvalds committed
993 994
		       " name_count=%d put_count=%d"
		       " ino_count=%d [NOT freeing]\n",
995
		       __FILE__, __LINE__,
Linus Torvalds's avatar
Linus Torvalds committed
996 997 998
		       context->serial, context->major, context->in_syscall,
		       context->name_count, context->put_count,
		       context->ino_count);
999
		list_for_each_entry(n, &context->names_list, list) {
Linus Torvalds's avatar
Linus Torvalds committed
1000
			printk(KERN_ERR "names[%d] = %p = %s\n", i,
1001
			       n->name, n->name ?: "(null)");
1002
		}
Linus Torvalds's avatar
Linus Torvalds committed
1003 1004 1005 1006 1007 1008 1009 1010 1011
		dump_stack();
		return;
	}
#endif
#if AUDIT_DEBUG
	context->put_count  = 0;
	context->ino_count  = 0;
#endif

1012 1013 1014 1015 1016 1017
	list_for_each_entry_safe(n, next, &context->names_list, list) {
		list_del(&n->list);
		if (n->name && n->name_put)
			__putname(n->name);
		if (n->should_free)
			kfree(n);
1018
	}
Linus Torvalds's avatar
Linus Torvalds committed
1019
	context->name_count = 0;
1020 1021 1022
	path_put(&context->pwd);
	context->pwd.dentry = NULL;
	context->pwd.mnt = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
}

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

	while ((aux = context->aux)) {
		context->aux = aux->next;
		kfree(aux);
	}
1033 1034 1035 1036
	while ((aux = context->aux_pids)) {
		context->aux_pids = aux->next;
		kfree(aux);
	}
Linus Torvalds's avatar
Linus Torvalds committed
1037 1038 1039 1040 1041 1042 1043
}

static inline void audit_zero_context(struct audit_context *context,
				      enum audit_state state)
{
	memset(context, 0, sizeof(*context));
	context->state      = state;
1044
	context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
Linus Torvalds's avatar
Linus Torvalds committed
1045 1046 1047 1048 1049 1050 1051 1052 1053
}

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);
1054
	INIT_LIST_HEAD(&context->killed_trees);
1055
	INIT_LIST_HEAD(&context->names_list);
Linus Torvalds's avatar
Linus Torvalds committed
1056 1057 1058
	return context;
}

1059 1060 1061 1062 1063
/**
 * audit_alloc - allocate an audit context block for a task
 * @tsk: task
 *
 * Filter on the task information and allocate a per-task audit context
Linus Torvalds's avatar
Linus Torvalds committed
1064 1065
 * if necessary.  Doing so turns on system call auditing for the
 * specified task.  This is called from copy_process, so no lock is
1066 1067
 * needed.
 */
Linus Torvalds's avatar
Linus Torvalds committed
1068 1069 1070 1071
int audit_alloc(struct task_struct *tsk)
{
	struct audit_context *context;
	enum audit_state     state;
1072
	char *key = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
1073

1074
	if (likely(!audit_ever_enabled))
Linus Torvalds's avatar
Linus Torvalds committed
1075 1076
		return 0; /* Return if not auditing. */

1077
	state = audit_filter_task(tsk, &key);
1078
	if (state == AUDIT_DISABLED)
Linus Torvalds's avatar
Linus Torvalds committed
1079 1080 1081
		return 0;

	if (!(context = audit_alloc_context(state))) {
1082
		kfree(key);
Linus Torvalds's avatar
Linus Torvalds committed
1083 1084 1085
		audit_log_lost("out of memory in audit_alloc");
		return -ENOMEM;
	}
1086
	context->filterkey = key;
Linus Torvalds's avatar
Linus Torvalds committed
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107

	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);
Al Viro's avatar
Al Viro committed
1108 1109
		unroll_tree_refs(context, NULL, 0);
		free_tree_refs(context);
Linus Torvalds's avatar
Linus Torvalds committed
1110
		audit_free_aux(context);
Amy Griffis's avatar
Amy Griffis committed
1111
		kfree(context->filterkey);
1112
		kfree(context->sockaddr);
Linus Torvalds's avatar
Linus Torvalds committed
1113 1114 1115 1116 1117 1118 1119
		kfree(context);
		context  = previous;
	} while (context);
	if (count >= 10)
		printk(KERN_ERR "audit: freed %d contexts\n", count);
}

Joy Latten's avatar
Joy Latten committed
1120
void audit_log_task_context(struct audit_buffer *ab)
1121 1122
{
	char *ctx = NULL;
1123 1124 1125 1126
	unsigned len;
	int error;
	u32 sid;

1127
	security_task_getsecid(current, &sid);
1128 1129
	if (!sid)
		return;
1130

1131
	error = security_secid_to_secctx(sid, &ctx, &len);
1132 1133
	if (error) {
		if (error != -EINVAL)
1134 1135 1136 1137 1138
			goto error_path;
		return;
	}

	audit_log_format(ab, " subj=%s", ctx);
1139
	security_release_secctx(ctx, len);
1140
	return;
1141 1142

error_path:
1143
	audit_panic("error in audit_log_task_context");
1144 1145 1146
	return;
}

Joy Latten's avatar
Joy Latten committed
1147 1148
EXPORT_SYMBOL(audit_log_task_context);

1149
void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
1150
{
1151
	const struct cred *cred;
1152 1153
	char name[sizeof(tsk->comm)];
	struct mm_struct *mm = tsk->mm;
1154 1155 1156 1157
	char *tty;

	if (!ab)
		return;
1158

1159
	/* tsk == current */
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
	cred = current_cred();

	spin_lock_irq(&tsk->sighand->siglock);
	if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
		tty = tsk->signal->tty->name;
	else
		tty = "(none)";
	spin_unlock_irq(&tsk->sighand->siglock);


	audit_log_format(ab,
			 " ppid=%ld pid=%d auid=%u uid=%u gid=%u"
			 " euid=%u suid=%u fsuid=%u"
			 " egid=%u sgid=%u fsgid=%u ses=%u tty=%s",
			 sys_getppid(),
			 tsk->pid,
1176 1177 1178 1179 1180 1181 1182 1183 1184
			 from_kuid(&init_user_ns, tsk->loginuid),
			 from_kuid(&init_user_ns, cred->uid),
			 from_kgid(&init_user_ns, cred->gid),
			 from_kuid(&init_user_ns, cred->euid),
			 from_kuid(&init_user_ns, cred->suid),
			 from_kuid(&init_user_ns, cred->fsuid),
			 from_kgid(&init_user_ns, cred->egid),
			 from_kgid(&init_user_ns, cred->sgid),
			 from_kgid(&init_user_ns, cred->fsgid),
1185
			 tsk->sessionid, tty);
1186

1187
	get_task_comm(name, tsk);
1188 1189
	audit_log_format(ab, " comm=");
	audit_log_untrustedstring(ab, name);
1190

1191 1192
	if (mm) {
		down_read(&mm->mmap_sem);
1193 1194
		if (mm->exe_file)
			audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
1195
		up_read(&mm->mmap_sem);
1196
	}
1197
	audit_log_task_context(ab);
1198 1199
}

1200 1201
EXPORT_SYMBOL(audit_log_task_info);

1202
static int audit_log_pid_context(struct audit_context *context, pid_t pid,
1203
				 kuid_t auid, kuid_t uid, unsigned int sessionid,
1204
				 u32 sid, char *comm)
1205 1206
{
	struct audit_buffer *ab;
1207
	char *ctx = NULL;
1208 1209 1210 1211 1212
	u32 len;
	int rc = 0;

	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
	if (!ab)
1213
		return rc;
1214

1215 1216
	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
			 from_kuid(&init_user_ns, auid),
1217
			 from_kuid(&init_user_ns, uid), sessionid);