xref: /linux/kernel/auditsc.c (revision 84a73014d86fd660822a20c032625e3afe99ca58)
185c8721fS /* auditsc.c -- System-call auditing support
21da177e4SLinus Torvalds  * Handles all system-call specific auditing features.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
573241cccSAmy Griffis  * Copyright 2005 Hewlett-Packard Development Company, L.P.
620ca73bcSGeorge C. Wilson  * Copyright (C) 2005, 2006 IBM Corporation
71da177e4SLinus Torvalds  * All Rights Reserved.
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
101da177e4SLinus Torvalds  * it under the terms of the GNU General Public License as published by
111da177e4SLinus Torvalds  * the Free Software Foundation; either version 2 of the License, or
121da177e4SLinus Torvalds  * (at your option) any later version.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * This program is distributed in the hope that it will be useful,
151da177e4SLinus Torvalds  * but WITHOUT ANY WARRANTY; without even the implied warranty of
161da177e4SLinus Torvalds  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
171da177e4SLinus Torvalds  * GNU General Public License for more details.
181da177e4SLinus Torvalds  *
191da177e4SLinus Torvalds  * You should have received a copy of the GNU General Public License
201da177e4SLinus Torvalds  * along with this program; if not, write to the Free Software
211da177e4SLinus Torvalds  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
221da177e4SLinus Torvalds  *
231da177e4SLinus Torvalds  * Written by Rickard E. (Rik) Faith <faith@redhat.com>
241da177e4SLinus Torvalds  *
251da177e4SLinus Torvalds  * Many of the ideas implemented here are from Stephen C. Tweedie,
261da177e4SLinus Torvalds  * especially the idea of avoiding a copy by using getname.
271da177e4SLinus Torvalds  *
281da177e4SLinus Torvalds  * The method for actual interception of syscall entry and exit (not in
291da177e4SLinus Torvalds  * this file -- see entry.S) is based on a GPL'd patch written by
301da177e4SLinus Torvalds  * okir@suse.de and Copyright 2003 SuSE Linux AG.
311da177e4SLinus Torvalds  *
3220ca73bcSGeorge C. Wilson  * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
3320ca73bcSGeorge C. Wilson  * 2006.
3420ca73bcSGeorge C. Wilson  *
35b63862f4SDustin Kirkland  * The support of additional filter rules compares (>, <, >=, <=) was
36b63862f4SDustin Kirkland  * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
37b63862f4SDustin Kirkland  *
3873241cccSAmy Griffis  * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
3973241cccSAmy Griffis  * filesystem information.
408c8570fbSDustin Kirkland  *
418c8570fbSDustin Kirkland  * Subject and object context labeling support added by <danjones@us.ibm.com>
428c8570fbSDustin Kirkland  * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
431da177e4SLinus Torvalds  */
441da177e4SLinus Torvalds 
45f952d10fSRichard Guy Briggs #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
46f952d10fSRichard Guy Briggs 
471da177e4SLinus Torvalds #include <linux/init.h>
481da177e4SLinus Torvalds #include <asm/types.h>
4960063497SArun Sharma #include <linux/atomic.h>
5073241cccSAmy Griffis #include <linux/fs.h>
5173241cccSAmy Griffis #include <linux/namei.h>
521da177e4SLinus Torvalds #include <linux/mm.h>
539984de1aSPaul Gortmaker #include <linux/export.h>
545a0e3ad6STejun Heo #include <linux/slab.h>
5501116105SStephen Smalley #include <linux/mount.h>
563ec3b2fbSDavid Woodhouse #include <linux/socket.h>
5720ca73bcSGeorge C. Wilson #include <linux/mqueue.h>
581da177e4SLinus Torvalds #include <linux/audit.h>
591da177e4SLinus Torvalds #include <linux/personality.h>
601da177e4SLinus Torvalds #include <linux/time.h>
615bb289b5SDavid Woodhouse #include <linux/netlink.h>
62f5561964SDavid Woodhouse #include <linux/compiler.h>
631da177e4SLinus Torvalds #include <asm/unistd.h>
648c8570fbSDustin Kirkland #include <linux/security.h>
65fe7752baSDavid Woodhouse #include <linux/list.h>
66a6c043a8SSteve Grubb #include <linux/tty.h>
67473ae30bSAl Viro #include <linux/binfmts.h>
68a1f8e7f7SAl Viro #include <linux/highmem.h>
69f46038ffSAl Viro #include <linux/syscalls.h>
7084db564aSRichard Guy Briggs #include <asm/syscall.h>
71851f7ff5SEric Paris #include <linux/capability.h>
725ad4e53bSAl Viro #include <linux/fs_struct.h>
733dc1c1b2SKees Cook #include <linux/compat.h>
743f1c8250SWilliam Roberts #include <linux/ctype.h>
75fcf22d82SPaul Moore #include <linux/string.h>
76fcf22d82SPaul Moore #include <uapi/linux/limits.h>
771da177e4SLinus Torvalds 
78fe7752baSDavid Woodhouse #include "audit.h"
79fe7752baSDavid Woodhouse 
80d7e7528bSEric Paris /* flags stating the success for a syscall */
81d7e7528bSEric Paris #define AUDITSC_INVALID 0
82d7e7528bSEric Paris #define AUDITSC_SUCCESS 1
83d7e7528bSEric Paris #define AUDITSC_FAILURE 2
84d7e7528bSEric Paris 
85de6bbd1dSEric Paris /* no execve audit message should be longer than this (userspace limits) */
86de6bbd1dSEric Paris #define MAX_EXECVE_AUDIT_LEN 7500
87de6bbd1dSEric Paris 
883f1c8250SWilliam Roberts /* max length to print of cmdline/proctitle value during audit */
893f1c8250SWilliam Roberts #define MAX_PROCTITLE_AUDIT_LEN 128
903f1c8250SWilliam Roberts 
91471a5c7cSAl Viro /* number of audit rules */
92471a5c7cSAl Viro int audit_n_rules;
93471a5c7cSAl Viro 
94e54dc243SAmy Griffis /* determines whether we collect data for signals sent */
95e54dc243SAmy Griffis int audit_signals;
96e54dc243SAmy Griffis 
971da177e4SLinus Torvalds struct audit_aux_data {
981da177e4SLinus Torvalds 	struct audit_aux_data	*next;
991da177e4SLinus Torvalds 	int			type;
1001da177e4SLinus Torvalds };
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds #define AUDIT_AUX_IPCPERM	0
1031da177e4SLinus Torvalds 
104e54dc243SAmy Griffis /* Number of target pids per aux struct. */
105e54dc243SAmy Griffis #define AUDIT_AUX_PIDS	16
106e54dc243SAmy Griffis 
107e54dc243SAmy Griffis struct audit_aux_data_pids {
108e54dc243SAmy Griffis 	struct audit_aux_data	d;
109e54dc243SAmy Griffis 	pid_t			target_pid[AUDIT_AUX_PIDS];
110e1760bd5SEric W. Biederman 	kuid_t			target_auid[AUDIT_AUX_PIDS];
111cca080d9SEric W. Biederman 	kuid_t			target_uid[AUDIT_AUX_PIDS];
1124746ec5bSEric Paris 	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
113e54dc243SAmy Griffis 	u32			target_sid[AUDIT_AUX_PIDS];
114c2a7780eSEric Paris 	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
115e54dc243SAmy Griffis 	int			pid_count;
116e54dc243SAmy Griffis };
117e54dc243SAmy Griffis 
1183fc689e9SEric Paris struct audit_aux_data_bprm_fcaps {
1193fc689e9SEric Paris 	struct audit_aux_data	d;
1203fc689e9SEric Paris 	struct audit_cap_data	fcap;
1213fc689e9SEric Paris 	unsigned int		fcap_ver;
1223fc689e9SEric Paris 	struct audit_cap_data	old_pcap;
1233fc689e9SEric Paris 	struct audit_cap_data	new_pcap;
1243fc689e9SEric Paris };
1253fc689e9SEric Paris 
12674c3cbe3SAl Viro struct audit_tree_refs {
12774c3cbe3SAl Viro 	struct audit_tree_refs *next;
12874c3cbe3SAl Viro 	struct audit_chunk *c[31];
12974c3cbe3SAl Viro };
13074c3cbe3SAl Viro 
13155669bfaSAl Viro static int audit_match_perm(struct audit_context *ctx, int mask)
13255669bfaSAl Viro {
133c4bacefbSCordelia 	unsigned n;
1341a61c88dSzhangxiliang 	if (unlikely(!ctx))
1351a61c88dSzhangxiliang 		return 0;
136c4bacefbSCordelia 	n = ctx->major;
137dbda4c0bSAlan Cox 
13855669bfaSAl Viro 	switch (audit_classify_syscall(ctx->arch, n)) {
13955669bfaSAl Viro 	case 0:	/* native */
14055669bfaSAl Viro 		if ((mask & AUDIT_PERM_WRITE) &&
14155669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_WRITE, n))
14255669bfaSAl Viro 			return 1;
14355669bfaSAl Viro 		if ((mask & AUDIT_PERM_READ) &&
14455669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_READ, n))
14555669bfaSAl Viro 			return 1;
14655669bfaSAl Viro 		if ((mask & AUDIT_PERM_ATTR) &&
14755669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_CHATTR, n))
14855669bfaSAl Viro 			return 1;
14955669bfaSAl Viro 		return 0;
15055669bfaSAl Viro 	case 1: /* 32bit on biarch */
15155669bfaSAl Viro 		if ((mask & AUDIT_PERM_WRITE) &&
15255669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_WRITE_32, n))
15355669bfaSAl Viro 			return 1;
15455669bfaSAl Viro 		if ((mask & AUDIT_PERM_READ) &&
15555669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_READ_32, n))
15655669bfaSAl Viro 			return 1;
15755669bfaSAl Viro 		if ((mask & AUDIT_PERM_ATTR) &&
15855669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_CHATTR_32, n))
15955669bfaSAl Viro 			return 1;
16055669bfaSAl Viro 		return 0;
16155669bfaSAl Viro 	case 2: /* open */
16255669bfaSAl Viro 		return mask & ACC_MODE(ctx->argv[1]);
16355669bfaSAl Viro 	case 3: /* openat */
16455669bfaSAl Viro 		return mask & ACC_MODE(ctx->argv[2]);
16555669bfaSAl Viro 	case 4: /* socketcall */
16655669bfaSAl Viro 		return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
16755669bfaSAl Viro 	case 5: /* execve */
16855669bfaSAl Viro 		return mask & AUDIT_PERM_EXEC;
16955669bfaSAl Viro 	default:
17055669bfaSAl Viro 		return 0;
17155669bfaSAl Viro 	}
17255669bfaSAl Viro }
17355669bfaSAl Viro 
1745ef30ee5SEric Paris static int audit_match_filetype(struct audit_context *ctx, int val)
1758b67dca9SAl Viro {
1765195d8e2SEric Paris 	struct audit_names *n;
1775ef30ee5SEric Paris 	umode_t mode = (umode_t)val;
1781a61c88dSzhangxiliang 
1791a61c88dSzhangxiliang 	if (unlikely(!ctx))
1801a61c88dSzhangxiliang 		return 0;
1811a61c88dSzhangxiliang 
1825195d8e2SEric Paris 	list_for_each_entry(n, &ctx->names_list, list) {
18384cb777eSRichard Guy Briggs 		if ((n->ino != AUDIT_INO_UNSET) &&
1845195d8e2SEric Paris 		    ((n->mode & S_IFMT) == mode))
1858b67dca9SAl Viro 			return 1;
1868b67dca9SAl Viro 	}
1875195d8e2SEric Paris 
1885ef30ee5SEric Paris 	return 0;
1895ef30ee5SEric Paris }
1908b67dca9SAl Viro 
19174c3cbe3SAl Viro /*
19274c3cbe3SAl Viro  * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
19374c3cbe3SAl Viro  * ->first_trees points to its beginning, ->trees - to the current end of data.
19474c3cbe3SAl Viro  * ->tree_count is the number of free entries in array pointed to by ->trees.
19574c3cbe3SAl Viro  * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL,
19674c3cbe3SAl Viro  * "empty" becomes (p, p, 31) afterwards.  We don't shrink the list (and seriously,
19774c3cbe3SAl Viro  * it's going to remain 1-element for almost any setup) until we free context itself.
19874c3cbe3SAl Viro  * References in it _are_ dropped - at the same time we free/drop aux stuff.
19974c3cbe3SAl Viro  */
20074c3cbe3SAl Viro 
20174c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE
202679173b7SEric Paris static void audit_set_auditable(struct audit_context *ctx)
203679173b7SEric Paris {
204679173b7SEric Paris 	if (!ctx->prio) {
205679173b7SEric Paris 		ctx->prio = 1;
206679173b7SEric Paris 		ctx->current_state = AUDIT_RECORD_CONTEXT;
207679173b7SEric Paris 	}
208679173b7SEric Paris }
209679173b7SEric Paris 
21074c3cbe3SAl Viro static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
21174c3cbe3SAl Viro {
21274c3cbe3SAl Viro 	struct audit_tree_refs *p = ctx->trees;
21374c3cbe3SAl Viro 	int left = ctx->tree_count;
21474c3cbe3SAl Viro 	if (likely(left)) {
21574c3cbe3SAl Viro 		p->c[--left] = chunk;
21674c3cbe3SAl Viro 		ctx->tree_count = left;
21774c3cbe3SAl Viro 		return 1;
21874c3cbe3SAl Viro 	}
21974c3cbe3SAl Viro 	if (!p)
22074c3cbe3SAl Viro 		return 0;
22174c3cbe3SAl Viro 	p = p->next;
22274c3cbe3SAl Viro 	if (p) {
22374c3cbe3SAl Viro 		p->c[30] = chunk;
22474c3cbe3SAl Viro 		ctx->trees = p;
22574c3cbe3SAl Viro 		ctx->tree_count = 30;
22674c3cbe3SAl Viro 		return 1;
22774c3cbe3SAl Viro 	}
22874c3cbe3SAl Viro 	return 0;
22974c3cbe3SAl Viro }
23074c3cbe3SAl Viro 
23174c3cbe3SAl Viro static int grow_tree_refs(struct audit_context *ctx)
23274c3cbe3SAl Viro {
23374c3cbe3SAl Viro 	struct audit_tree_refs *p = ctx->trees;
23474c3cbe3SAl Viro 	ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
23574c3cbe3SAl Viro 	if (!ctx->trees) {
23674c3cbe3SAl Viro 		ctx->trees = p;
23774c3cbe3SAl Viro 		return 0;
23874c3cbe3SAl Viro 	}
23974c3cbe3SAl Viro 	if (p)
24074c3cbe3SAl Viro 		p->next = ctx->trees;
24174c3cbe3SAl Viro 	else
24274c3cbe3SAl Viro 		ctx->first_trees = ctx->trees;
24374c3cbe3SAl Viro 	ctx->tree_count = 31;
24474c3cbe3SAl Viro 	return 1;
24574c3cbe3SAl Viro }
24674c3cbe3SAl Viro #endif
24774c3cbe3SAl Viro 
24874c3cbe3SAl Viro static void unroll_tree_refs(struct audit_context *ctx,
24974c3cbe3SAl Viro 		      struct audit_tree_refs *p, int count)
25074c3cbe3SAl Viro {
25174c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE
25274c3cbe3SAl Viro 	struct audit_tree_refs *q;
25374c3cbe3SAl Viro 	int n;
25474c3cbe3SAl Viro 	if (!p) {
25574c3cbe3SAl Viro 		/* we started with empty chain */
25674c3cbe3SAl Viro 		p = ctx->first_trees;
25774c3cbe3SAl Viro 		count = 31;
25874c3cbe3SAl Viro 		/* if the very first allocation has failed, nothing to do */
25974c3cbe3SAl Viro 		if (!p)
26074c3cbe3SAl Viro 			return;
26174c3cbe3SAl Viro 	}
26274c3cbe3SAl Viro 	n = count;
26374c3cbe3SAl Viro 	for (q = p; q != ctx->trees; q = q->next, n = 31) {
26474c3cbe3SAl Viro 		while (n--) {
26574c3cbe3SAl Viro 			audit_put_chunk(q->c[n]);
26674c3cbe3SAl Viro 			q->c[n] = NULL;
26774c3cbe3SAl Viro 		}
26874c3cbe3SAl Viro 	}
26974c3cbe3SAl Viro 	while (n-- > ctx->tree_count) {
27074c3cbe3SAl Viro 		audit_put_chunk(q->c[n]);
27174c3cbe3SAl Viro 		q->c[n] = NULL;
27274c3cbe3SAl Viro 	}
27374c3cbe3SAl Viro 	ctx->trees = p;
27474c3cbe3SAl Viro 	ctx->tree_count = count;
27574c3cbe3SAl Viro #endif
27674c3cbe3SAl Viro }
27774c3cbe3SAl Viro 
27874c3cbe3SAl Viro static void free_tree_refs(struct audit_context *ctx)
27974c3cbe3SAl Viro {
28074c3cbe3SAl Viro 	struct audit_tree_refs *p, *q;
28174c3cbe3SAl Viro 	for (p = ctx->first_trees; p; p = q) {
28274c3cbe3SAl Viro 		q = p->next;
28374c3cbe3SAl Viro 		kfree(p);
28474c3cbe3SAl Viro 	}
28574c3cbe3SAl Viro }
28674c3cbe3SAl Viro 
28774c3cbe3SAl Viro static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
28874c3cbe3SAl Viro {
28974c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE
29074c3cbe3SAl Viro 	struct audit_tree_refs *p;
29174c3cbe3SAl Viro 	int n;
29274c3cbe3SAl Viro 	if (!tree)
29374c3cbe3SAl Viro 		return 0;
29474c3cbe3SAl Viro 	/* full ones */
29574c3cbe3SAl Viro 	for (p = ctx->first_trees; p != ctx->trees; p = p->next) {
29674c3cbe3SAl Viro 		for (n = 0; n < 31; n++)
29774c3cbe3SAl Viro 			if (audit_tree_match(p->c[n], tree))
29874c3cbe3SAl Viro 				return 1;
29974c3cbe3SAl Viro 	}
30074c3cbe3SAl Viro 	/* partial */
30174c3cbe3SAl Viro 	if (p) {
30274c3cbe3SAl Viro 		for (n = ctx->tree_count; n < 31; n++)
30374c3cbe3SAl Viro 			if (audit_tree_match(p->c[n], tree))
30474c3cbe3SAl Viro 				return 1;
30574c3cbe3SAl Viro 	}
30674c3cbe3SAl Viro #endif
30774c3cbe3SAl Viro 	return 0;
30874c3cbe3SAl Viro }
30974c3cbe3SAl Viro 
310ca57ec0fSEric W. Biederman static int audit_compare_uid(kuid_t uid,
311b34b0393SEric Paris 			     struct audit_names *name,
312b34b0393SEric Paris 			     struct audit_field *f,
313b34b0393SEric Paris 			     struct audit_context *ctx)
314b34b0393SEric Paris {
315b34b0393SEric Paris 	struct audit_names *n;
316b34b0393SEric Paris 	int rc;
317b34b0393SEric Paris 
318b34b0393SEric Paris 	if (name) {
319ca57ec0fSEric W. Biederman 		rc = audit_uid_comparator(uid, f->op, name->uid);
320b34b0393SEric Paris 		if (rc)
321b34b0393SEric Paris 			return rc;
322b34b0393SEric Paris 	}
323b34b0393SEric Paris 
324b34b0393SEric Paris 	if (ctx) {
325b34b0393SEric Paris 		list_for_each_entry(n, &ctx->names_list, list) {
326ca57ec0fSEric W. Biederman 			rc = audit_uid_comparator(uid, f->op, n->uid);
327ca57ec0fSEric W. Biederman 			if (rc)
328ca57ec0fSEric W. Biederman 				return rc;
329ca57ec0fSEric W. Biederman 		}
330ca57ec0fSEric W. Biederman 	}
331ca57ec0fSEric W. Biederman 	return 0;
332ca57ec0fSEric W. Biederman }
333b34b0393SEric Paris 
334ca57ec0fSEric W. Biederman static int audit_compare_gid(kgid_t gid,
335ca57ec0fSEric W. Biederman 			     struct audit_names *name,
336ca57ec0fSEric W. Biederman 			     struct audit_field *f,
337ca57ec0fSEric W. Biederman 			     struct audit_context *ctx)
338ca57ec0fSEric W. Biederman {
339ca57ec0fSEric W. Biederman 	struct audit_names *n;
340ca57ec0fSEric W. Biederman 	int rc;
341b34b0393SEric Paris 
342ca57ec0fSEric W. Biederman 	if (name) {
343ca57ec0fSEric W. Biederman 		rc = audit_gid_comparator(gid, f->op, name->gid);
344ca57ec0fSEric W. Biederman 		if (rc)
345ca57ec0fSEric W. Biederman 			return rc;
346ca57ec0fSEric W. Biederman 	}
347ca57ec0fSEric W. Biederman 
348ca57ec0fSEric W. Biederman 	if (ctx) {
349ca57ec0fSEric W. Biederman 		list_for_each_entry(n, &ctx->names_list, list) {
350ca57ec0fSEric W. Biederman 			rc = audit_gid_comparator(gid, f->op, n->gid);
351b34b0393SEric Paris 			if (rc)
352b34b0393SEric Paris 				return rc;
353b34b0393SEric Paris 		}
354b34b0393SEric Paris 	}
355b34b0393SEric Paris 	return 0;
356b34b0393SEric Paris }
357b34b0393SEric Paris 
35802d86a56SEric Paris static int audit_field_compare(struct task_struct *tsk,
35902d86a56SEric Paris 			       const struct cred *cred,
36002d86a56SEric Paris 			       struct audit_field *f,
36102d86a56SEric Paris 			       struct audit_context *ctx,
36202d86a56SEric Paris 			       struct audit_names *name)
36302d86a56SEric Paris {
36402d86a56SEric Paris 	switch (f->val) {
3654a6633edSPeter Moody 	/* process to file object comparisons */
36602d86a56SEric Paris 	case AUDIT_COMPARE_UID_TO_OBJ_UID:
367ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->uid, name, f, ctx);
368c9fe685fSEric Paris 	case AUDIT_COMPARE_GID_TO_OBJ_GID:
369ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->gid, name, f, ctx);
3704a6633edSPeter Moody 	case AUDIT_COMPARE_EUID_TO_OBJ_UID:
371ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->euid, name, f, ctx);
3724a6633edSPeter Moody 	case AUDIT_COMPARE_EGID_TO_OBJ_GID:
373ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->egid, name, f, ctx);
3744a6633edSPeter Moody 	case AUDIT_COMPARE_AUID_TO_OBJ_UID:
375ca57ec0fSEric W. Biederman 		return audit_compare_uid(tsk->loginuid, name, f, ctx);
3764a6633edSPeter Moody 	case AUDIT_COMPARE_SUID_TO_OBJ_UID:
377ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->suid, name, f, ctx);
3784a6633edSPeter Moody 	case AUDIT_COMPARE_SGID_TO_OBJ_GID:
379ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->sgid, name, f, ctx);
3804a6633edSPeter Moody 	case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
381ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->fsuid, name, f, ctx);
3824a6633edSPeter Moody 	case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
383ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->fsgid, name, f, ctx);
38410d68360SPeter Moody 	/* uid comparisons */
38510d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_AUID:
386ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->uid, f->op, tsk->loginuid);
38710d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_EUID:
388ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->uid, f->op, cred->euid);
38910d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_SUID:
390ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->uid, f->op, cred->suid);
39110d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_FSUID:
392ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->uid, f->op, cred->fsuid);
39310d68360SPeter Moody 	/* auid comparisons */
39410d68360SPeter Moody 	case AUDIT_COMPARE_AUID_TO_EUID:
395ca57ec0fSEric W. Biederman 		return audit_uid_comparator(tsk->loginuid, f->op, cred->euid);
39610d68360SPeter Moody 	case AUDIT_COMPARE_AUID_TO_SUID:
397ca57ec0fSEric W. Biederman 		return audit_uid_comparator(tsk->loginuid, f->op, cred->suid);
39810d68360SPeter Moody 	case AUDIT_COMPARE_AUID_TO_FSUID:
399ca57ec0fSEric W. Biederman 		return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid);
40010d68360SPeter Moody 	/* euid comparisons */
40110d68360SPeter Moody 	case AUDIT_COMPARE_EUID_TO_SUID:
402ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->euid, f->op, cred->suid);
40310d68360SPeter Moody 	case AUDIT_COMPARE_EUID_TO_FSUID:
404ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->euid, f->op, cred->fsuid);
40510d68360SPeter Moody 	/* suid comparisons */
40610d68360SPeter Moody 	case AUDIT_COMPARE_SUID_TO_FSUID:
407ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->suid, f->op, cred->fsuid);
40810d68360SPeter Moody 	/* gid comparisons */
40910d68360SPeter Moody 	case AUDIT_COMPARE_GID_TO_EGID:
410ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->gid, f->op, cred->egid);
41110d68360SPeter Moody 	case AUDIT_COMPARE_GID_TO_SGID:
412ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->gid, f->op, cred->sgid);
41310d68360SPeter Moody 	case AUDIT_COMPARE_GID_TO_FSGID:
414ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->gid, f->op, cred->fsgid);
41510d68360SPeter Moody 	/* egid comparisons */
41610d68360SPeter Moody 	case AUDIT_COMPARE_EGID_TO_SGID:
417ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->egid, f->op, cred->sgid);
41810d68360SPeter Moody 	case AUDIT_COMPARE_EGID_TO_FSGID:
419ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->egid, f->op, cred->fsgid);
42010d68360SPeter Moody 	/* sgid comparison */
42110d68360SPeter Moody 	case AUDIT_COMPARE_SGID_TO_FSGID:
422ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->sgid, f->op, cred->fsgid);
42302d86a56SEric Paris 	default:
42402d86a56SEric Paris 		WARN(1, "Missing AUDIT_COMPARE define.  Report as a bug\n");
42502d86a56SEric Paris 		return 0;
42602d86a56SEric Paris 	}
42702d86a56SEric Paris 	return 0;
42802d86a56SEric Paris }
42902d86a56SEric Paris 
430f368c07dSAmy Griffis /* Determine if any context name data matches a rule's watch data */
4311da177e4SLinus Torvalds /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
432f5629883STony Jones  * otherwise.
433f5629883STony Jones  *
434f5629883STony Jones  * If task_creation is true, this is an explicit indication that we are
435f5629883STony Jones  * filtering a task rule at task creation time.  This and tsk == current are
436f5629883STony Jones  * the only situations where tsk->cred may be accessed without an rcu read lock.
437f5629883STony Jones  */
4381da177e4SLinus Torvalds static int audit_filter_rules(struct task_struct *tsk,
43993315ed6SAmy Griffis 			      struct audit_krule *rule,
4401da177e4SLinus Torvalds 			      struct audit_context *ctx,
441f368c07dSAmy Griffis 			      struct audit_names *name,
442f5629883STony Jones 			      enum audit_state *state,
443f5629883STony Jones 			      bool task_creation)
4441da177e4SLinus Torvalds {
445f5629883STony Jones 	const struct cred *cred;
4465195d8e2SEric Paris 	int i, need_sid = 1;
4473dc7e315SDarrel Goeddel 	u32 sid;
4483dc7e315SDarrel Goeddel 
449f5629883STony Jones 	cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);
450f5629883STony Jones 
4511da177e4SLinus Torvalds 	for (i = 0; i < rule->field_count; i++) {
45293315ed6SAmy Griffis 		struct audit_field *f = &rule->fields[i];
4535195d8e2SEric Paris 		struct audit_names *n;
4541da177e4SLinus Torvalds 		int result = 0;
455f1dc4867SRichard Guy Briggs 		pid_t pid;
4561da177e4SLinus Torvalds 
45793315ed6SAmy Griffis 		switch (f->type) {
4581da177e4SLinus Torvalds 		case AUDIT_PID:
459f1dc4867SRichard Guy Briggs 			pid = task_pid_nr(tsk);
460f1dc4867SRichard Guy Briggs 			result = audit_comparator(pid, f->op, f->val);
4611da177e4SLinus Torvalds 			break;
4623c66251eSAl Viro 		case AUDIT_PPID:
463419c58f1SAlexander Viro 			if (ctx) {
464419c58f1SAlexander Viro 				if (!ctx->ppid)
465c92cdeb4SRichard Guy Briggs 					ctx->ppid = task_ppid_nr(tsk);
4663c66251eSAl Viro 				result = audit_comparator(ctx->ppid, f->op, f->val);
467419c58f1SAlexander Viro 			}
4683c66251eSAl Viro 			break;
46934d99af5SRichard Guy Briggs 		case AUDIT_EXE:
47034d99af5SRichard Guy Briggs 			result = audit_exe_compare(tsk, rule->exe);
47134d99af5SRichard Guy Briggs 			break;
4721da177e4SLinus Torvalds 		case AUDIT_UID:
473ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->uid, f->op, f->uid);
4741da177e4SLinus Torvalds 			break;
4751da177e4SLinus Torvalds 		case AUDIT_EUID:
476ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->euid, f->op, f->uid);
4771da177e4SLinus Torvalds 			break;
4781da177e4SLinus Torvalds 		case AUDIT_SUID:
479ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->suid, f->op, f->uid);
4801da177e4SLinus Torvalds 			break;
4811da177e4SLinus Torvalds 		case AUDIT_FSUID:
482ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->fsuid, f->op, f->uid);
4831da177e4SLinus Torvalds 			break;
4841da177e4SLinus Torvalds 		case AUDIT_GID:
485ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->gid, f->op, f->gid);
48637eebe39SMatvejchikov Ilya 			if (f->op == Audit_equal) {
48737eebe39SMatvejchikov Ilya 				if (!result)
48837eebe39SMatvejchikov Ilya 					result = in_group_p(f->gid);
48937eebe39SMatvejchikov Ilya 			} else if (f->op == Audit_not_equal) {
49037eebe39SMatvejchikov Ilya 				if (result)
49137eebe39SMatvejchikov Ilya 					result = !in_group_p(f->gid);
49237eebe39SMatvejchikov Ilya 			}
4931da177e4SLinus Torvalds 			break;
4941da177e4SLinus Torvalds 		case AUDIT_EGID:
495ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->egid, f->op, f->gid);
49637eebe39SMatvejchikov Ilya 			if (f->op == Audit_equal) {
49737eebe39SMatvejchikov Ilya 				if (!result)
49837eebe39SMatvejchikov Ilya 					result = in_egroup_p(f->gid);
49937eebe39SMatvejchikov Ilya 			} else if (f->op == Audit_not_equal) {
50037eebe39SMatvejchikov Ilya 				if (result)
50137eebe39SMatvejchikov Ilya 					result = !in_egroup_p(f->gid);
50237eebe39SMatvejchikov Ilya 			}
5031da177e4SLinus Torvalds 			break;
5041da177e4SLinus Torvalds 		case AUDIT_SGID:
505ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->sgid, f->op, f->gid);
5061da177e4SLinus Torvalds 			break;
5071da177e4SLinus Torvalds 		case AUDIT_FSGID:
508ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->fsgid, f->op, f->gid);
5091da177e4SLinus Torvalds 			break;
5101da177e4SLinus Torvalds 		case AUDIT_PERS:
51193315ed6SAmy Griffis 			result = audit_comparator(tsk->personality, f->op, f->val);
5121da177e4SLinus Torvalds 			break;
5132fd6f58bS 		case AUDIT_ARCH:
5142fd6f58bS 			if (ctx)
51593315ed6SAmy Griffis 				result = audit_comparator(ctx->arch, f->op, f->val);
5162fd6f58bS 			break;
5171da177e4SLinus Torvalds 
5181da177e4SLinus Torvalds 		case AUDIT_EXIT:
5191da177e4SLinus Torvalds 			if (ctx && ctx->return_valid)
52093315ed6SAmy Griffis 				result = audit_comparator(ctx->return_code, f->op, f->val);
5211da177e4SLinus Torvalds 			break;
5221da177e4SLinus Torvalds 		case AUDIT_SUCCESS:
523b01f2cc1SDavid Woodhouse 			if (ctx && ctx->return_valid) {
52493315ed6SAmy Griffis 				if (f->val)
52593315ed6SAmy Griffis 					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
526b01f2cc1SDavid Woodhouse 				else
52793315ed6SAmy Griffis 					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
528b01f2cc1SDavid Woodhouse 			}
5291da177e4SLinus Torvalds 			break;
5301da177e4SLinus Torvalds 		case AUDIT_DEVMAJOR:
53116c174bdSEric Paris 			if (name) {
53216c174bdSEric Paris 				if (audit_comparator(MAJOR(name->dev), f->op, f->val) ||
53316c174bdSEric Paris 				    audit_comparator(MAJOR(name->rdev), f->op, f->val))
53416c174bdSEric Paris 					++result;
53516c174bdSEric Paris 			} else if (ctx) {
5365195d8e2SEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
53716c174bdSEric Paris 					if (audit_comparator(MAJOR(n->dev), f->op, f->val) ||
53816c174bdSEric Paris 					    audit_comparator(MAJOR(n->rdev), f->op, f->val)) {
5391da177e4SLinus Torvalds 						++result;
5401da177e4SLinus Torvalds 						break;
5411da177e4SLinus Torvalds 					}
5421da177e4SLinus Torvalds 				}
5431da177e4SLinus Torvalds 			}
5441da177e4SLinus Torvalds 			break;
5451da177e4SLinus Torvalds 		case AUDIT_DEVMINOR:
54616c174bdSEric Paris 			if (name) {
54716c174bdSEric Paris 				if (audit_comparator(MINOR(name->dev), f->op, f->val) ||
54816c174bdSEric Paris 				    audit_comparator(MINOR(name->rdev), f->op, f->val))
54916c174bdSEric Paris 					++result;
55016c174bdSEric Paris 			} else if (ctx) {
5515195d8e2SEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
55216c174bdSEric Paris 					if (audit_comparator(MINOR(n->dev), f->op, f->val) ||
55316c174bdSEric Paris 					    audit_comparator(MINOR(n->rdev), f->op, f->val)) {
5541da177e4SLinus Torvalds 						++result;
5551da177e4SLinus Torvalds 						break;
5561da177e4SLinus Torvalds 					}
5571da177e4SLinus Torvalds 				}
5581da177e4SLinus Torvalds 			}
5591da177e4SLinus Torvalds 			break;
5601da177e4SLinus Torvalds 		case AUDIT_INODE:
561f368c07dSAmy Griffis 			if (name)
562db510fc5SRichard Guy Briggs 				result = audit_comparator(name->ino, f->op, f->val);
563f368c07dSAmy Griffis 			else if (ctx) {
5645195d8e2SEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
5655195d8e2SEric Paris 					if (audit_comparator(n->ino, f->op, f->val)) {
5661da177e4SLinus Torvalds 						++result;
5671da177e4SLinus Torvalds 						break;
5681da177e4SLinus Torvalds 					}
5691da177e4SLinus Torvalds 				}
5701da177e4SLinus Torvalds 			}
5711da177e4SLinus Torvalds 			break;
572efaffd6eSEric Paris 		case AUDIT_OBJ_UID:
573efaffd6eSEric Paris 			if (name) {
574ca57ec0fSEric W. Biederman 				result = audit_uid_comparator(name->uid, f->op, f->uid);
575efaffd6eSEric Paris 			} else if (ctx) {
576efaffd6eSEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
577ca57ec0fSEric W. Biederman 					if (audit_uid_comparator(n->uid, f->op, f->uid)) {
578efaffd6eSEric Paris 						++result;
579efaffd6eSEric Paris 						break;
580efaffd6eSEric Paris 					}
581efaffd6eSEric Paris 				}
582efaffd6eSEric Paris 			}
583efaffd6eSEric Paris 			break;
58454d3218bSEric Paris 		case AUDIT_OBJ_GID:
58554d3218bSEric Paris 			if (name) {
586ca57ec0fSEric W. Biederman 				result = audit_gid_comparator(name->gid, f->op, f->gid);
58754d3218bSEric Paris 			} else if (ctx) {
58854d3218bSEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
589ca57ec0fSEric W. Biederman 					if (audit_gid_comparator(n->gid, f->op, f->gid)) {
59054d3218bSEric Paris 						++result;
59154d3218bSEric Paris 						break;
59254d3218bSEric Paris 					}
59354d3218bSEric Paris 				}
59454d3218bSEric Paris 			}
59554d3218bSEric Paris 			break;
596f368c07dSAmy Griffis 		case AUDIT_WATCH:
597ae7b8f41SEric Paris 			if (name)
598ae7b8f41SEric Paris 				result = audit_watch_compare(rule->watch, name->ino, name->dev);
599f368c07dSAmy Griffis 			break;
60074c3cbe3SAl Viro 		case AUDIT_DIR:
60174c3cbe3SAl Viro 			if (ctx)
60274c3cbe3SAl Viro 				result = match_tree_refs(ctx, rule->tree);
60374c3cbe3SAl Viro 			break;
6041da177e4SLinus Torvalds 		case AUDIT_LOGINUID:
605ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(tsk->loginuid, f->op, f->uid);
6061da177e4SLinus Torvalds 			break;
607780a7654SEric W. Biederman 		case AUDIT_LOGINUID_SET:
608780a7654SEric W. Biederman 			result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
609780a7654SEric W. Biederman 			break;
6103a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_USER:
6113a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_ROLE:
6123a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_TYPE:
6133a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_SEN:
6143a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_CLR:
6153dc7e315SDarrel Goeddel 			/* NOTE: this may return negative values indicating
6163dc7e315SDarrel Goeddel 			   a temporary error.  We simply treat this as a
6173dc7e315SDarrel Goeddel 			   match for now to avoid losing information that
6183dc7e315SDarrel Goeddel 			   may be wanted.   An error message will also be
6193dc7e315SDarrel Goeddel 			   logged upon error */
62004305e4aSAhmed S. Darwish 			if (f->lsm_rule) {
6212ad312d2SSteve Grubb 				if (need_sid) {
6222a862b32SAhmed S. Darwish 					security_task_getsecid(tsk, &sid);
6232ad312d2SSteve Grubb 					need_sid = 0;
6242ad312d2SSteve Grubb 				}
625d7a96f3aSAhmed S. Darwish 				result = security_audit_rule_match(sid, f->type,
6263dc7e315SDarrel Goeddel 				                                  f->op,
62704305e4aSAhmed S. Darwish 				                                  f->lsm_rule,
6283dc7e315SDarrel Goeddel 				                                  ctx);
6292ad312d2SSteve Grubb 			}
6303dc7e315SDarrel Goeddel 			break;
6316e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_USER:
6326e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_ROLE:
6336e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_TYPE:
6346e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_LEV_LOW:
6356e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_LEV_HIGH:
6366e5a2d1dSDarrel Goeddel 			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
6376e5a2d1dSDarrel Goeddel 			   also applies here */
63804305e4aSAhmed S. Darwish 			if (f->lsm_rule) {
6396e5a2d1dSDarrel Goeddel 				/* Find files that match */
6406e5a2d1dSDarrel Goeddel 				if (name) {
641d7a96f3aSAhmed S. Darwish 					result = security_audit_rule_match(
6426e5a2d1dSDarrel Goeddel 					           name->osid, f->type, f->op,
64304305e4aSAhmed S. Darwish 					           f->lsm_rule, ctx);
6446e5a2d1dSDarrel Goeddel 				} else if (ctx) {
6455195d8e2SEric Paris 					list_for_each_entry(n, &ctx->names_list, list) {
6465195d8e2SEric Paris 						if (security_audit_rule_match(n->osid, f->type,
6475195d8e2SEric Paris 									      f->op, f->lsm_rule,
6485195d8e2SEric Paris 									      ctx)) {
6496e5a2d1dSDarrel Goeddel 							++result;
6506e5a2d1dSDarrel Goeddel 							break;
6516e5a2d1dSDarrel Goeddel 						}
6526e5a2d1dSDarrel Goeddel 					}
6536e5a2d1dSDarrel Goeddel 				}
6546e5a2d1dSDarrel Goeddel 				/* Find ipc objects that match */
655a33e6751SAl Viro 				if (!ctx || ctx->type != AUDIT_IPC)
6566e5a2d1dSDarrel Goeddel 					break;
657a33e6751SAl Viro 				if (security_audit_rule_match(ctx->ipc.osid,
658a33e6751SAl Viro 							      f->type, f->op,
659a33e6751SAl Viro 							      f->lsm_rule, ctx))
660a33e6751SAl Viro 					++result;
6616e5a2d1dSDarrel Goeddel 			}
6626e5a2d1dSDarrel Goeddel 			break;
6631da177e4SLinus Torvalds 		case AUDIT_ARG0:
6641da177e4SLinus Torvalds 		case AUDIT_ARG1:
6651da177e4SLinus Torvalds 		case AUDIT_ARG2:
6661da177e4SLinus Torvalds 		case AUDIT_ARG3:
6671da177e4SLinus Torvalds 			if (ctx)
66893315ed6SAmy Griffis 				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
6691da177e4SLinus Torvalds 			break;
6705adc8a6aSAmy Griffis 		case AUDIT_FILTERKEY:
6715adc8a6aSAmy Griffis 			/* ignore this field for filtering */
6725adc8a6aSAmy Griffis 			result = 1;
6735adc8a6aSAmy Griffis 			break;
67455669bfaSAl Viro 		case AUDIT_PERM:
67555669bfaSAl Viro 			result = audit_match_perm(ctx, f->val);
67655669bfaSAl Viro 			break;
6778b67dca9SAl Viro 		case AUDIT_FILETYPE:
6788b67dca9SAl Viro 			result = audit_match_filetype(ctx, f->val);
6798b67dca9SAl Viro 			break;
68002d86a56SEric Paris 		case AUDIT_FIELD_COMPARE:
68102d86a56SEric Paris 			result = audit_field_compare(tsk, cred, f, ctx, name);
68202d86a56SEric Paris 			break;
6831da177e4SLinus Torvalds 		}
684f5629883STony Jones 		if (!result)
6851da177e4SLinus Torvalds 			return 0;
6861da177e4SLinus Torvalds 	}
6870590b933SAl Viro 
6880590b933SAl Viro 	if (ctx) {
6890590b933SAl Viro 		if (rule->prio <= ctx->prio)
6900590b933SAl Viro 			return 0;
6910590b933SAl Viro 		if (rule->filterkey) {
6920590b933SAl Viro 			kfree(ctx->filterkey);
6935adc8a6aSAmy Griffis 			ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
6940590b933SAl Viro 		}
6950590b933SAl Viro 		ctx->prio = rule->prio;
6960590b933SAl Viro 	}
6971da177e4SLinus Torvalds 	switch (rule->action) {
6981da177e4SLinus Torvalds 	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
6991da177e4SLinus Torvalds 	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
7001da177e4SLinus Torvalds 	}
7011da177e4SLinus Torvalds 	return 1;
7021da177e4SLinus Torvalds }
7031da177e4SLinus Torvalds 
7041da177e4SLinus Torvalds /* At process creation time, we can determine if system-call auditing is
7051da177e4SLinus Torvalds  * completely disabled for this task.  Since we only have the task
7061da177e4SLinus Torvalds  * structure at this point, we can only check uid and gid.
7071da177e4SLinus Torvalds  */
708e048e02cSAl Viro static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
7091da177e4SLinus Torvalds {
7101da177e4SLinus Torvalds 	struct audit_entry *e;
7111da177e4SLinus Torvalds 	enum audit_state   state;
7121da177e4SLinus Torvalds 
7131da177e4SLinus Torvalds 	rcu_read_lock();
7140f45aa18SDavid Woodhouse 	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
715f5629883STony Jones 		if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
716f5629883STony Jones 				       &state, true)) {
717e048e02cSAl Viro 			if (state == AUDIT_RECORD_CONTEXT)
718e048e02cSAl Viro 				*key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
7191da177e4SLinus Torvalds 			rcu_read_unlock();
7201da177e4SLinus Torvalds 			return state;
7211da177e4SLinus Torvalds 		}
7221da177e4SLinus Torvalds 	}
7231da177e4SLinus Torvalds 	rcu_read_unlock();
7241da177e4SLinus Torvalds 	return AUDIT_BUILD_CONTEXT;
7251da177e4SLinus Torvalds }
7261da177e4SLinus Torvalds 
727a3c54931SAndy Lutomirski static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
728a3c54931SAndy Lutomirski {
729a3c54931SAndy Lutomirski 	int word, bit;
730a3c54931SAndy Lutomirski 
731a3c54931SAndy Lutomirski 	if (val > 0xffffffff)
732a3c54931SAndy Lutomirski 		return false;
733a3c54931SAndy Lutomirski 
734a3c54931SAndy Lutomirski 	word = AUDIT_WORD(val);
735a3c54931SAndy Lutomirski 	if (word >= AUDIT_BITMASK_SIZE)
736a3c54931SAndy Lutomirski 		return false;
737a3c54931SAndy Lutomirski 
738a3c54931SAndy Lutomirski 	bit = AUDIT_BIT(val);
739a3c54931SAndy Lutomirski 
740a3c54931SAndy Lutomirski 	return rule->mask[word] & bit;
741a3c54931SAndy Lutomirski }
742a3c54931SAndy Lutomirski 
7431da177e4SLinus Torvalds /* At syscall entry and exit time, this filter is called if the
7441da177e4SLinus Torvalds  * audit_state is not low enough that auditing cannot take place, but is
74523f32d18SSteve Grubb  * also not high enough that we already know we have to write an audit
7461da177e4SLinus Torvalds  * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
7471da177e4SLinus Torvalds  */
7481da177e4SLinus Torvalds static enum audit_state audit_filter_syscall(struct task_struct *tsk,
7491da177e4SLinus Torvalds 					     struct audit_context *ctx,
7501da177e4SLinus Torvalds 					     struct list_head *list)
7511da177e4SLinus Torvalds {
7521da177e4SLinus Torvalds 	struct audit_entry *e;
7531da177e4SLinus Torvalds 	enum audit_state state;
7541da177e4SLinus Torvalds 
755351bb722SDavid Woodhouse 	if (audit_pid && tsk->tgid == audit_pid)
756f7056d64SDavid Woodhouse 		return AUDIT_DISABLED;
757f7056d64SDavid Woodhouse 
7581da177e4SLinus Torvalds 	rcu_read_lock();
759c3896495SDavid Woodhouse 	if (!list_empty(list)) {
7601da177e4SLinus Torvalds 		list_for_each_entry_rcu(e, list, list) {
761a3c54931SAndy Lutomirski 			if (audit_in_mask(&e->rule, ctx->major) &&
762f368c07dSAmy Griffis 			    audit_filter_rules(tsk, &e->rule, ctx, NULL,
763f5629883STony Jones 					       &state, false)) {
7641da177e4SLinus Torvalds 				rcu_read_unlock();
7650590b933SAl Viro 				ctx->current_state = state;
7661da177e4SLinus Torvalds 				return state;
7671da177e4SLinus Torvalds 			}
7681da177e4SLinus Torvalds 		}
769c3896495SDavid Woodhouse 	}
7701da177e4SLinus Torvalds 	rcu_read_unlock();
7711da177e4SLinus Torvalds 	return AUDIT_BUILD_CONTEXT;
7721da177e4SLinus Torvalds }
7731da177e4SLinus Torvalds 
7745195d8e2SEric Paris /*
7755195d8e2SEric Paris  * Given an audit_name check the inode hash table to see if they match.
7765195d8e2SEric Paris  * Called holding the rcu read lock to protect the use of audit_inode_hash
7775195d8e2SEric Paris  */
7785195d8e2SEric Paris static int audit_filter_inode_name(struct task_struct *tsk,
7795195d8e2SEric Paris 				   struct audit_names *n,
7805195d8e2SEric Paris 				   struct audit_context *ctx) {
7815195d8e2SEric Paris 	int h = audit_hash_ino((u32)n->ino);
7825195d8e2SEric Paris 	struct list_head *list = &audit_inode_hash[h];
7835195d8e2SEric Paris 	struct audit_entry *e;
7845195d8e2SEric Paris 	enum audit_state state;
7855195d8e2SEric Paris 
7865195d8e2SEric Paris 	if (list_empty(list))
7875195d8e2SEric Paris 		return 0;
7885195d8e2SEric Paris 
7895195d8e2SEric Paris 	list_for_each_entry_rcu(e, list, list) {
790a3c54931SAndy Lutomirski 		if (audit_in_mask(&e->rule, ctx->major) &&
7915195d8e2SEric Paris 		    audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
7925195d8e2SEric Paris 			ctx->current_state = state;
7935195d8e2SEric Paris 			return 1;
7945195d8e2SEric Paris 		}
7955195d8e2SEric Paris 	}
7965195d8e2SEric Paris 
7975195d8e2SEric Paris 	return 0;
7985195d8e2SEric Paris }
7995195d8e2SEric Paris 
8005195d8e2SEric Paris /* At syscall exit time, this filter is called if any audit_names have been
801f368c07dSAmy Griffis  * collected during syscall processing.  We only check rules in sublists at hash
8025195d8e2SEric Paris  * buckets applicable to the inode numbers in audit_names.
803f368c07dSAmy Griffis  * Regarding audit_state, same rules apply as for audit_filter_syscall().
804f368c07dSAmy Griffis  */
8050590b933SAl Viro void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
806f368c07dSAmy Griffis {
8075195d8e2SEric Paris 	struct audit_names *n;
808f368c07dSAmy Griffis 
809f368c07dSAmy Griffis 	if (audit_pid && tsk->tgid == audit_pid)
8100590b933SAl Viro 		return;
811f368c07dSAmy Griffis 
812f368c07dSAmy Griffis 	rcu_read_lock();
813f368c07dSAmy Griffis 
8145195d8e2SEric Paris 	list_for_each_entry(n, &ctx->names_list, list) {
8155195d8e2SEric Paris 		if (audit_filter_inode_name(tsk, n, ctx))
8165195d8e2SEric Paris 			break;
817f368c07dSAmy Griffis 	}
818f368c07dSAmy Griffis 	rcu_read_unlock();
819f368c07dSAmy Griffis }
820f368c07dSAmy Griffis 
8214a3eb726SRichard Guy Briggs /* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */
8224a3eb726SRichard Guy Briggs static inline struct audit_context *audit_take_context(struct task_struct *tsk,
8231da177e4SLinus Torvalds 						      int return_valid,
8246d208da8SPaul Moore 						      long return_code)
8251da177e4SLinus Torvalds {
8261da177e4SLinus Torvalds 	struct audit_context *context = tsk->audit_context;
8271da177e4SLinus Torvalds 
82856179a6eSEric Paris 	if (!context)
8291da177e4SLinus Torvalds 		return NULL;
8301da177e4SLinus Torvalds 	context->return_valid = return_valid;
831f701b75eSEric Paris 
832f701b75eSEric Paris 	/*
833f701b75eSEric Paris 	 * we need to fix up the return code in the audit logs if the actual
834f701b75eSEric Paris 	 * return codes are later going to be fixed up by the arch specific
835f701b75eSEric Paris 	 * signal handlers
836f701b75eSEric Paris 	 *
837f701b75eSEric Paris 	 * This is actually a test for:
838f701b75eSEric Paris 	 * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
839f701b75eSEric Paris 	 * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
840f701b75eSEric Paris 	 *
841f701b75eSEric Paris 	 * but is faster than a bunch of ||
842f701b75eSEric Paris 	 */
843f701b75eSEric Paris 	if (unlikely(return_code <= -ERESTARTSYS) &&
844f701b75eSEric Paris 	    (return_code >= -ERESTART_RESTARTBLOCK) &&
845f701b75eSEric Paris 	    (return_code != -ENOIOCTLCMD))
846f701b75eSEric Paris 		context->return_code = -EINTR;
847f701b75eSEric Paris 	else
8481da177e4SLinus Torvalds 		context->return_code  = return_code;
8491da177e4SLinus Torvalds 
8500590b933SAl Viro 	if (context->in_syscall && !context->dummy) {
8510590b933SAl Viro 		audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
8520590b933SAl Viro 		audit_filter_inodes(tsk, context);
8531da177e4SLinus Torvalds 	}
8541da177e4SLinus Torvalds 
8551da177e4SLinus Torvalds 	tsk->audit_context = NULL;
8561da177e4SLinus Torvalds 	return context;
8571da177e4SLinus Torvalds }
8581da177e4SLinus Torvalds 
8593f1c8250SWilliam Roberts static inline void audit_proctitle_free(struct audit_context *context)
8603f1c8250SWilliam Roberts {
8613f1c8250SWilliam Roberts 	kfree(context->proctitle.value);
8623f1c8250SWilliam Roberts 	context->proctitle.value = NULL;
8633f1c8250SWilliam Roberts 	context->proctitle.len = 0;
8643f1c8250SWilliam Roberts }
8653f1c8250SWilliam Roberts 
8661da177e4SLinus Torvalds static inline void audit_free_names(struct audit_context *context)
8671da177e4SLinus Torvalds {
8685195d8e2SEric Paris 	struct audit_names *n, *next;
8691da177e4SLinus Torvalds 
8705195d8e2SEric Paris 	list_for_each_entry_safe(n, next, &context->names_list, list) {
8715195d8e2SEric Paris 		list_del(&n->list);
87255422d0bSPaul Moore 		if (n->name)
87355422d0bSPaul Moore 			putname(n->name);
8745195d8e2SEric Paris 		if (n->should_free)
8755195d8e2SEric Paris 			kfree(n);
8768c8570fbSDustin Kirkland 	}
8771da177e4SLinus Torvalds 	context->name_count = 0;
87844707fdfSJan Blunck 	path_put(&context->pwd);
87944707fdfSJan Blunck 	context->pwd.dentry = NULL;
88044707fdfSJan Blunck 	context->pwd.mnt = NULL;
8811da177e4SLinus Torvalds }
8821da177e4SLinus Torvalds 
8831da177e4SLinus Torvalds static inline void audit_free_aux(struct audit_context *context)
8841da177e4SLinus Torvalds {
8851da177e4SLinus Torvalds 	struct audit_aux_data *aux;
8861da177e4SLinus Torvalds 
8871da177e4SLinus Torvalds 	while ((aux = context->aux)) {
8881da177e4SLinus Torvalds 		context->aux = aux->next;
8891da177e4SLinus Torvalds 		kfree(aux);
8901da177e4SLinus Torvalds 	}
891e54dc243SAmy Griffis 	while ((aux = context->aux_pids)) {
892e54dc243SAmy Griffis 		context->aux_pids = aux->next;
893e54dc243SAmy Griffis 		kfree(aux);
894e54dc243SAmy Griffis 	}
8951da177e4SLinus Torvalds }
8961da177e4SLinus Torvalds 
8971da177e4SLinus Torvalds static inline struct audit_context *audit_alloc_context(enum audit_state state)
8981da177e4SLinus Torvalds {
8991da177e4SLinus Torvalds 	struct audit_context *context;
9001da177e4SLinus Torvalds 
90117c6ee70SRakib Mullick 	context = kzalloc(sizeof(*context), GFP_KERNEL);
90217c6ee70SRakib Mullick 	if (!context)
9031da177e4SLinus Torvalds 		return NULL;
904e2c5adc8SAndrew Morton 	context->state = state;
905e2c5adc8SAndrew Morton 	context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
906916d7576SAl Viro 	INIT_LIST_HEAD(&context->killed_trees);
9075195d8e2SEric Paris 	INIT_LIST_HEAD(&context->names_list);
9081da177e4SLinus Torvalds 	return context;
9091da177e4SLinus Torvalds }
9101da177e4SLinus Torvalds 
911b0dd25a8SRandy Dunlap /**
912b0dd25a8SRandy Dunlap  * audit_alloc - allocate an audit context block for a task
913b0dd25a8SRandy Dunlap  * @tsk: task
914b0dd25a8SRandy Dunlap  *
915b0dd25a8SRandy Dunlap  * Filter on the task information and allocate a per-task audit context
9161da177e4SLinus Torvalds  * if necessary.  Doing so turns on system call auditing for the
9171da177e4SLinus Torvalds  * specified task.  This is called from copy_process, so no lock is
918b0dd25a8SRandy Dunlap  * needed.
919b0dd25a8SRandy Dunlap  */
9201da177e4SLinus Torvalds int audit_alloc(struct task_struct *tsk)
9211da177e4SLinus Torvalds {
9221da177e4SLinus Torvalds 	struct audit_context *context;
9231da177e4SLinus Torvalds 	enum audit_state     state;
924e048e02cSAl Viro 	char *key = NULL;
9251da177e4SLinus Torvalds 
926b593d384SEric Paris 	if (likely(!audit_ever_enabled))
9271da177e4SLinus Torvalds 		return 0; /* Return if not auditing. */
9281da177e4SLinus Torvalds 
929e048e02cSAl Viro 	state = audit_filter_task(tsk, &key);
930d48d8051SOleg Nesterov 	if (state == AUDIT_DISABLED) {
931d48d8051SOleg Nesterov 		clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
9321da177e4SLinus Torvalds 		return 0;
933d48d8051SOleg Nesterov 	}
9341da177e4SLinus Torvalds 
9351da177e4SLinus Torvalds 	if (!(context = audit_alloc_context(state))) {
936e048e02cSAl Viro 		kfree(key);
9371da177e4SLinus Torvalds 		audit_log_lost("out of memory in audit_alloc");
9381da177e4SLinus Torvalds 		return -ENOMEM;
9391da177e4SLinus Torvalds 	}
940e048e02cSAl Viro 	context->filterkey = key;
9411da177e4SLinus Torvalds 
9421da177e4SLinus Torvalds 	tsk->audit_context  = context;
9431da177e4SLinus Torvalds 	set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
9441da177e4SLinus Torvalds 	return 0;
9451da177e4SLinus Torvalds }
9461da177e4SLinus Torvalds 
9471da177e4SLinus Torvalds static inline void audit_free_context(struct audit_context *context)
9481da177e4SLinus Torvalds {
9491da177e4SLinus Torvalds 	audit_free_names(context);
95074c3cbe3SAl Viro 	unroll_tree_refs(context, NULL, 0);
95174c3cbe3SAl Viro 	free_tree_refs(context);
9521da177e4SLinus Torvalds 	audit_free_aux(context);
9535adc8a6aSAmy Griffis 	kfree(context->filterkey);
9544f6b434fSAl Viro 	kfree(context->sockaddr);
9553f1c8250SWilliam Roberts 	audit_proctitle_free(context);
9561da177e4SLinus Torvalds 	kfree(context);
9571da177e4SLinus Torvalds }
9581da177e4SLinus Torvalds 
959e54dc243SAmy Griffis static int audit_log_pid_context(struct audit_context *context, pid_t pid,
960cca080d9SEric W. Biederman 				 kuid_t auid, kuid_t uid, unsigned int sessionid,
9614746ec5bSEric Paris 				 u32 sid, char *comm)
962e54dc243SAmy Griffis {
963e54dc243SAmy Griffis 	struct audit_buffer *ab;
9642a862b32SAhmed S. Darwish 	char *ctx = NULL;
965e54dc243SAmy Griffis 	u32 len;
966e54dc243SAmy Griffis 	int rc = 0;
967e54dc243SAmy Griffis 
968e54dc243SAmy Griffis 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
969e54dc243SAmy Griffis 	if (!ab)
9706246ccabSEric Paris 		return rc;
971e54dc243SAmy Griffis 
972e1760bd5SEric W. Biederman 	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
973e1760bd5SEric W. Biederman 			 from_kuid(&init_user_ns, auid),
974cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, uid), sessionid);
975ad395abeSEric Paris 	if (sid) {
9762a862b32SAhmed S. Darwish 		if (security_secid_to_secctx(sid, &ctx, &len)) {
977c2a7780eSEric Paris 			audit_log_format(ab, " obj=(none)");
978e54dc243SAmy Griffis 			rc = 1;
9792a862b32SAhmed S. Darwish 		} else {
9802a862b32SAhmed S. Darwish 			audit_log_format(ab, " obj=%s", ctx);
9812a862b32SAhmed S. Darwish 			security_release_secctx(ctx, len);
9822a862b32SAhmed S. Darwish 		}
983ad395abeSEric Paris 	}
984c2a7780eSEric Paris 	audit_log_format(ab, " ocomm=");
985c2a7780eSEric Paris 	audit_log_untrustedstring(ab, comm);
986e54dc243SAmy Griffis 	audit_log_end(ab);
987e54dc243SAmy Griffis 
988e54dc243SAmy Griffis 	return rc;
989e54dc243SAmy Griffis }
990e54dc243SAmy Griffis 
991de6bbd1dSEric Paris /*
992de6bbd1dSEric Paris  * to_send and len_sent accounting are very loose estimates.  We aren't
993de6bbd1dSEric Paris  * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being
99425985edcSLucas De Marchi  * within about 500 bytes (next page boundary)
995de6bbd1dSEric Paris  *
996de6bbd1dSEric Paris  * why snprintf?  an int is up to 12 digits long.  if we just assumed when
997de6bbd1dSEric Paris  * logging that a[%d]= was going to be 16 characters long we would be wasting
998de6bbd1dSEric Paris  * space in every audit message.  In one 7500 byte message we can log up to
999de6bbd1dSEric Paris  * about 1000 min size arguments.  That comes down to about 50% waste of space
1000de6bbd1dSEric Paris  * if we didn't do the snprintf to find out how long arg_num_len was.
1001de6bbd1dSEric Paris  */
1002de6bbd1dSEric Paris static int audit_log_single_execve_arg(struct audit_context *context,
1003de6bbd1dSEric Paris 					struct audit_buffer **ab,
1004de6bbd1dSEric Paris 					int arg_num,
1005de6bbd1dSEric Paris 					size_t *len_sent,
1006de6bbd1dSEric Paris 					const char __user *p,
1007de6bbd1dSEric Paris 					char *buf)
1008bdf4c48aSPeter Zijlstra {
1009de6bbd1dSEric Paris 	char arg_num_len_buf[12];
1010de6bbd1dSEric Paris 	const char __user *tmp_p = p;
1011b87ce6e4SEric Paris 	/* how many digits are in arg_num? 5 is the length of ' a=""' */
1012b87ce6e4SEric Paris 	size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5;
1013de6bbd1dSEric Paris 	size_t len, len_left, to_send;
1014de6bbd1dSEric Paris 	size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;
1015de6bbd1dSEric Paris 	unsigned int i, has_cntl = 0, too_long = 0;
1016de6bbd1dSEric Paris 	int ret;
1017bdf4c48aSPeter Zijlstra 
1018de6bbd1dSEric Paris 	/* strnlen_user includes the null we don't want to send */
1019de6bbd1dSEric Paris 	len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1;
1020bdf4c48aSPeter Zijlstra 
1021bdf4c48aSPeter Zijlstra 	/*
1022bdf4c48aSPeter Zijlstra 	 * We just created this mm, if we can't find the strings
1023bdf4c48aSPeter Zijlstra 	 * we just copied into it something is _very_ wrong. Similar
1024bdf4c48aSPeter Zijlstra 	 * for strings that are too long, we should not have created
1025bdf4c48aSPeter Zijlstra 	 * any.
1026bdf4c48aSPeter Zijlstra 	 */
102745820c29SLinus Torvalds 	if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) {
1028bdf4c48aSPeter Zijlstra 		send_sig(SIGKILL, current, 0);
1029b0abcfc1SEric Paris 		return -1;
1030bdf4c48aSPeter Zijlstra 	}
1031bdf4c48aSPeter Zijlstra 
1032de6bbd1dSEric Paris 	/* walk the whole argument looking for non-ascii chars */
1033de6bbd1dSEric Paris 	do {
1034de6bbd1dSEric Paris 		if (len_left > MAX_EXECVE_AUDIT_LEN)
1035de6bbd1dSEric Paris 			to_send = MAX_EXECVE_AUDIT_LEN;
1036de6bbd1dSEric Paris 		else
1037de6bbd1dSEric Paris 			to_send = len_left;
1038de6bbd1dSEric Paris 		ret = copy_from_user(buf, tmp_p, to_send);
1039bdf4c48aSPeter Zijlstra 		/*
1040bdf4c48aSPeter Zijlstra 		 * There is no reason for this copy to be short. We just
1041bdf4c48aSPeter Zijlstra 		 * copied them here, and the mm hasn't been exposed to user-
1042bdf4c48aSPeter Zijlstra 		 * space yet.
1043bdf4c48aSPeter Zijlstra 		 */
1044040b3a2dSPeter Zijlstra 		if (ret) {
1045bdf4c48aSPeter Zijlstra 			WARN_ON(1);
1046bdf4c48aSPeter Zijlstra 			send_sig(SIGKILL, current, 0);
1047b0abcfc1SEric Paris 			return -1;
1048bdf4c48aSPeter Zijlstra 		}
1049de6bbd1dSEric Paris 		buf[to_send] = '\0';
1050de6bbd1dSEric Paris 		has_cntl = audit_string_contains_control(buf, to_send);
1051de6bbd1dSEric Paris 		if (has_cntl) {
1052de6bbd1dSEric Paris 			/*
1053de6bbd1dSEric Paris 			 * hex messages get logged as 2 bytes, so we can only
1054de6bbd1dSEric Paris 			 * send half as much in each message
1055de6bbd1dSEric Paris 			 */
1056de6bbd1dSEric Paris 			max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2;
1057de6bbd1dSEric Paris 			break;
1058bdf4c48aSPeter Zijlstra 		}
1059de6bbd1dSEric Paris 		len_left -= to_send;
1060de6bbd1dSEric Paris 		tmp_p += to_send;
1061de6bbd1dSEric Paris 	} while (len_left > 0);
1062de6bbd1dSEric Paris 
1063de6bbd1dSEric Paris 	len_left = len;
1064de6bbd1dSEric Paris 
1065de6bbd1dSEric Paris 	if (len > max_execve_audit_len)
1066de6bbd1dSEric Paris 		too_long = 1;
1067de6bbd1dSEric Paris 
1068de6bbd1dSEric Paris 	/* rewalk the argument actually logging the message */
1069de6bbd1dSEric Paris 	for (i = 0; len_left > 0; i++) {
1070de6bbd1dSEric Paris 		int room_left;
1071de6bbd1dSEric Paris 
1072de6bbd1dSEric Paris 		if (len_left > max_execve_audit_len)
1073de6bbd1dSEric Paris 			to_send = max_execve_audit_len;
1074de6bbd1dSEric Paris 		else
1075de6bbd1dSEric Paris 			to_send = len_left;
1076de6bbd1dSEric Paris 
1077de6bbd1dSEric Paris 		/* do we have space left to send this argument in this ab? */
1078de6bbd1dSEric Paris 		room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent;
1079de6bbd1dSEric Paris 		if (has_cntl)
1080de6bbd1dSEric Paris 			room_left -= (to_send * 2);
1081de6bbd1dSEric Paris 		else
1082de6bbd1dSEric Paris 			room_left -= to_send;
1083de6bbd1dSEric Paris 		if (room_left < 0) {
1084de6bbd1dSEric Paris 			*len_sent = 0;
1085de6bbd1dSEric Paris 			audit_log_end(*ab);
1086de6bbd1dSEric Paris 			*ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);
1087de6bbd1dSEric Paris 			if (!*ab)
1088de6bbd1dSEric Paris 				return 0;
1089de6bbd1dSEric Paris 		}
1090de6bbd1dSEric Paris 
1091de6bbd1dSEric Paris 		/*
1092de6bbd1dSEric Paris 		 * first record needs to say how long the original string was
1093de6bbd1dSEric Paris 		 * so we can be sure nothing was lost.
1094de6bbd1dSEric Paris 		 */
1095de6bbd1dSEric Paris 		if ((i == 0) && (too_long))
1096422b03cfSPaul Moore 			audit_log_format(*ab, " a%d_len=%zu", arg_num,
1097de6bbd1dSEric Paris 					 has_cntl ? 2*len : len);
1098de6bbd1dSEric Paris 
1099de6bbd1dSEric Paris 		/*
1100de6bbd1dSEric Paris 		 * normally arguments are small enough to fit and we already
1101de6bbd1dSEric Paris 		 * filled buf above when we checked for control characters
1102de6bbd1dSEric Paris 		 * so don't bother with another copy_from_user
1103de6bbd1dSEric Paris 		 */
1104de6bbd1dSEric Paris 		if (len >= max_execve_audit_len)
1105de6bbd1dSEric Paris 			ret = copy_from_user(buf, p, to_send);
1106de6bbd1dSEric Paris 		else
1107de6bbd1dSEric Paris 			ret = 0;
1108de6bbd1dSEric Paris 		if (ret) {
1109de6bbd1dSEric Paris 			WARN_ON(1);
1110de6bbd1dSEric Paris 			send_sig(SIGKILL, current, 0);
1111b0abcfc1SEric Paris 			return -1;
1112de6bbd1dSEric Paris 		}
1113de6bbd1dSEric Paris 		buf[to_send] = '\0';
1114de6bbd1dSEric Paris 
1115de6bbd1dSEric Paris 		/* actually log it */
1116de6bbd1dSEric Paris 		audit_log_format(*ab, " a%d", arg_num);
1117de6bbd1dSEric Paris 		if (too_long)
1118de6bbd1dSEric Paris 			audit_log_format(*ab, "[%d]", i);
1119de6bbd1dSEric Paris 		audit_log_format(*ab, "=");
1120de6bbd1dSEric Paris 		if (has_cntl)
1121b556f8adSEric Paris 			audit_log_n_hex(*ab, buf, to_send);
1122de6bbd1dSEric Paris 		else
11239d960985SEric Paris 			audit_log_string(*ab, buf);
1124de6bbd1dSEric Paris 
1125de6bbd1dSEric Paris 		p += to_send;
1126de6bbd1dSEric Paris 		len_left -= to_send;
1127de6bbd1dSEric Paris 		*len_sent += arg_num_len;
1128de6bbd1dSEric Paris 		if (has_cntl)
1129de6bbd1dSEric Paris 			*len_sent += to_send * 2;
1130de6bbd1dSEric Paris 		else
1131de6bbd1dSEric Paris 			*len_sent += to_send;
1132de6bbd1dSEric Paris 	}
1133de6bbd1dSEric Paris 	/* include the null we didn't log */
1134de6bbd1dSEric Paris 	return len + 1;
1135de6bbd1dSEric Paris }
1136de6bbd1dSEric Paris 
1137de6bbd1dSEric Paris static void audit_log_execve_info(struct audit_context *context,
1138d9cfea91SRichard Guy Briggs 				  struct audit_buffer **ab)
1139de6bbd1dSEric Paris {
11405afb8a3fSXi Wang 	int i, len;
11415afb8a3fSXi Wang 	size_t len_sent = 0;
1142de6bbd1dSEric Paris 	const char __user *p;
1143de6bbd1dSEric Paris 	char *buf;
1144de6bbd1dSEric Paris 
1145d9cfea91SRichard Guy Briggs 	p = (const char __user *)current->mm->arg_start;
1146de6bbd1dSEric Paris 
1147d9cfea91SRichard Guy Briggs 	audit_log_format(*ab, "argc=%d", context->execve.argc);
1148de6bbd1dSEric Paris 
1149de6bbd1dSEric Paris 	/*
1150de6bbd1dSEric Paris 	 * we need some kernel buffer to hold the userspace args.  Just
1151de6bbd1dSEric Paris 	 * allocate one big one rather than allocating one of the right size
1152de6bbd1dSEric Paris 	 * for every single argument inside audit_log_single_execve_arg()
1153de6bbd1dSEric Paris 	 * should be <8k allocation so should be pretty safe.
1154de6bbd1dSEric Paris 	 */
1155de6bbd1dSEric Paris 	buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
1156de6bbd1dSEric Paris 	if (!buf) {
1157b7550787SJoe Perches 		audit_panic("out of memory for argv string");
1158de6bbd1dSEric Paris 		return;
1159de6bbd1dSEric Paris 	}
1160de6bbd1dSEric Paris 
1161d9cfea91SRichard Guy Briggs 	for (i = 0; i < context->execve.argc; i++) {
1162de6bbd1dSEric Paris 		len = audit_log_single_execve_arg(context, ab, i,
1163de6bbd1dSEric Paris 						  &len_sent, p, buf);
1164de6bbd1dSEric Paris 		if (len <= 0)
1165de6bbd1dSEric Paris 			break;
1166de6bbd1dSEric Paris 		p += len;
1167de6bbd1dSEric Paris 	}
1168de6bbd1dSEric Paris 	kfree(buf);
1169bdf4c48aSPeter Zijlstra }
1170bdf4c48aSPeter Zijlstra 
1171a33e6751SAl Viro static void show_special(struct audit_context *context, int *call_panic)
1172f3298dc4SAl Viro {
1173f3298dc4SAl Viro 	struct audit_buffer *ab;
1174f3298dc4SAl Viro 	int i;
1175f3298dc4SAl Viro 
1176f3298dc4SAl Viro 	ab = audit_log_start(context, GFP_KERNEL, context->type);
1177f3298dc4SAl Viro 	if (!ab)
1178f3298dc4SAl Viro 		return;
1179f3298dc4SAl Viro 
1180f3298dc4SAl Viro 	switch (context->type) {
1181f3298dc4SAl Viro 	case AUDIT_SOCKETCALL: {
1182f3298dc4SAl Viro 		int nargs = context->socketcall.nargs;
1183f3298dc4SAl Viro 		audit_log_format(ab, "nargs=%d", nargs);
1184f3298dc4SAl Viro 		for (i = 0; i < nargs; i++)
1185f3298dc4SAl Viro 			audit_log_format(ab, " a%d=%lx", i,
1186f3298dc4SAl Viro 				context->socketcall.args[i]);
1187f3298dc4SAl Viro 		break; }
1188a33e6751SAl Viro 	case AUDIT_IPC: {
1189a33e6751SAl Viro 		u32 osid = context->ipc.osid;
1190a33e6751SAl Viro 
11912570ebbdSAl Viro 		audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho",
1192cca080d9SEric W. Biederman 				 from_kuid(&init_user_ns, context->ipc.uid),
1193cca080d9SEric W. Biederman 				 from_kgid(&init_user_ns, context->ipc.gid),
1194cca080d9SEric W. Biederman 				 context->ipc.mode);
1195a33e6751SAl Viro 		if (osid) {
1196a33e6751SAl Viro 			char *ctx = NULL;
1197a33e6751SAl Viro 			u32 len;
1198a33e6751SAl Viro 			if (security_secid_to_secctx(osid, &ctx, &len)) {
1199a33e6751SAl Viro 				audit_log_format(ab, " osid=%u", osid);
1200a33e6751SAl Viro 				*call_panic = 1;
1201a33e6751SAl Viro 			} else {
1202a33e6751SAl Viro 				audit_log_format(ab, " obj=%s", ctx);
1203a33e6751SAl Viro 				security_release_secctx(ctx, len);
1204a33e6751SAl Viro 			}
1205a33e6751SAl Viro 		}
1206e816f370SAl Viro 		if (context->ipc.has_perm) {
1207e816f370SAl Viro 			audit_log_end(ab);
1208e816f370SAl Viro 			ab = audit_log_start(context, GFP_KERNEL,
1209e816f370SAl Viro 					     AUDIT_IPC_SET_PERM);
12100644ec0cSKees Cook 			if (unlikely(!ab))
12110644ec0cSKees Cook 				return;
1212e816f370SAl Viro 			audit_log_format(ab,
12132570ebbdSAl Viro 				"qbytes=%lx ouid=%u ogid=%u mode=%#ho",
1214e816f370SAl Viro 				context->ipc.qbytes,
1215e816f370SAl Viro 				context->ipc.perm_uid,
1216e816f370SAl Viro 				context->ipc.perm_gid,
1217e816f370SAl Viro 				context->ipc.perm_mode);
1218e816f370SAl Viro 		}
1219a33e6751SAl Viro 		break; }
1220564f6993SAl Viro 	case AUDIT_MQ_OPEN: {
1221564f6993SAl Viro 		audit_log_format(ab,
1222df0a4283SAl Viro 			"oflag=0x%x mode=%#ho mq_flags=0x%lx mq_maxmsg=%ld "
1223564f6993SAl Viro 			"mq_msgsize=%ld mq_curmsgs=%ld",
1224564f6993SAl Viro 			context->mq_open.oflag, context->mq_open.mode,
1225564f6993SAl Viro 			context->mq_open.attr.mq_flags,
1226564f6993SAl Viro 			context->mq_open.attr.mq_maxmsg,
1227564f6993SAl Viro 			context->mq_open.attr.mq_msgsize,
1228564f6993SAl Viro 			context->mq_open.attr.mq_curmsgs);
1229564f6993SAl Viro 		break; }
1230c32c8af4SAl Viro 	case AUDIT_MQ_SENDRECV: {
1231c32c8af4SAl Viro 		audit_log_format(ab,
1232c32c8af4SAl Viro 			"mqdes=%d msg_len=%zd msg_prio=%u "
1233c32c8af4SAl Viro 			"abs_timeout_sec=%ld abs_timeout_nsec=%ld",
1234c32c8af4SAl Viro 			context->mq_sendrecv.mqdes,
1235c32c8af4SAl Viro 			context->mq_sendrecv.msg_len,
1236c32c8af4SAl Viro 			context->mq_sendrecv.msg_prio,
1237c32c8af4SAl Viro 			context->mq_sendrecv.abs_timeout.tv_sec,
1238c32c8af4SAl Viro 			context->mq_sendrecv.abs_timeout.tv_nsec);
1239c32c8af4SAl Viro 		break; }
124020114f71SAl Viro 	case AUDIT_MQ_NOTIFY: {
124120114f71SAl Viro 		audit_log_format(ab, "mqdes=%d sigev_signo=%d",
124220114f71SAl Viro 				context->mq_notify.mqdes,
124320114f71SAl Viro 				context->mq_notify.sigev_signo);
124420114f71SAl Viro 		break; }
12457392906eSAl Viro 	case AUDIT_MQ_GETSETATTR: {
12467392906eSAl Viro 		struct mq_attr *attr = &context->mq_getsetattr.mqstat;
12477392906eSAl Viro 		audit_log_format(ab,
12487392906eSAl Viro 			"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
12497392906eSAl Viro 			"mq_curmsgs=%ld ",
12507392906eSAl Viro 			context->mq_getsetattr.mqdes,
12517392906eSAl Viro 			attr->mq_flags, attr->mq_maxmsg,
12527392906eSAl Viro 			attr->mq_msgsize, attr->mq_curmsgs);
12537392906eSAl Viro 		break; }
125457f71a0aSAl Viro 	case AUDIT_CAPSET: {
125557f71a0aSAl Viro 		audit_log_format(ab, "pid=%d", context->capset.pid);
125657f71a0aSAl Viro 		audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
125757f71a0aSAl Viro 		audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
125857f71a0aSAl Viro 		audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
125957f71a0aSAl Viro 		break; }
1260120a795dSAl Viro 	case AUDIT_MMAP: {
1261120a795dSAl Viro 		audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
1262120a795dSAl Viro 				 context->mmap.flags);
1263120a795dSAl Viro 		break; }
1264d9cfea91SRichard Guy Briggs 	case AUDIT_EXECVE: {
1265d9cfea91SRichard Guy Briggs 		audit_log_execve_info(context, &ab);
1266d9cfea91SRichard Guy Briggs 		break; }
1267f3298dc4SAl Viro 	}
1268f3298dc4SAl Viro 	audit_log_end(ab);
1269f3298dc4SAl Viro }
1270f3298dc4SAl Viro 
12713f1c8250SWilliam Roberts static inline int audit_proctitle_rtrim(char *proctitle, int len)
12723f1c8250SWilliam Roberts {
12733f1c8250SWilliam Roberts 	char *end = proctitle + len - 1;
12743f1c8250SWilliam Roberts 	while (end > proctitle && !isprint(*end))
12753f1c8250SWilliam Roberts 		end--;
12763f1c8250SWilliam Roberts 
12773f1c8250SWilliam Roberts 	/* catch the case where proctitle is only 1 non-print character */
12783f1c8250SWilliam Roberts 	len = end - proctitle + 1;
12793f1c8250SWilliam Roberts 	len -= isprint(proctitle[len-1]) == 0;
12803f1c8250SWilliam Roberts 	return len;
12813f1c8250SWilliam Roberts }
12823f1c8250SWilliam Roberts 
12833f1c8250SWilliam Roberts static void audit_log_proctitle(struct task_struct *tsk,
12843f1c8250SWilliam Roberts 			 struct audit_context *context)
12853f1c8250SWilliam Roberts {
12863f1c8250SWilliam Roberts 	int res;
12873f1c8250SWilliam Roberts 	char *buf;
12883f1c8250SWilliam Roberts 	char *msg = "(null)";
12893f1c8250SWilliam Roberts 	int len = strlen(msg);
12903f1c8250SWilliam Roberts 	struct audit_buffer *ab;
12913f1c8250SWilliam Roberts 
12923f1c8250SWilliam Roberts 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
12933f1c8250SWilliam Roberts 	if (!ab)
12943f1c8250SWilliam Roberts 		return;	/* audit_panic or being filtered */
12953f1c8250SWilliam Roberts 
12963f1c8250SWilliam Roberts 	audit_log_format(ab, "proctitle=");
12973f1c8250SWilliam Roberts 
12983f1c8250SWilliam Roberts 	/* Not  cached */
12993f1c8250SWilliam Roberts 	if (!context->proctitle.value) {
13003f1c8250SWilliam Roberts 		buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL);
13013f1c8250SWilliam Roberts 		if (!buf)
13023f1c8250SWilliam Roberts 			goto out;
13033f1c8250SWilliam Roberts 		/* Historically called this from procfs naming */
13043f1c8250SWilliam Roberts 		res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN);
13053f1c8250SWilliam Roberts 		if (res == 0) {
13063f1c8250SWilliam Roberts 			kfree(buf);
13073f1c8250SWilliam Roberts 			goto out;
13083f1c8250SWilliam Roberts 		}
13093f1c8250SWilliam Roberts 		res = audit_proctitle_rtrim(buf, res);
13103f1c8250SWilliam Roberts 		if (res == 0) {
13113f1c8250SWilliam Roberts 			kfree(buf);
13123f1c8250SWilliam Roberts 			goto out;
13133f1c8250SWilliam Roberts 		}
13143f1c8250SWilliam Roberts 		context->proctitle.value = buf;
13153f1c8250SWilliam Roberts 		context->proctitle.len = res;
13163f1c8250SWilliam Roberts 	}
13173f1c8250SWilliam Roberts 	msg = context->proctitle.value;
13183f1c8250SWilliam Roberts 	len = context->proctitle.len;
13193f1c8250SWilliam Roberts out:
13203f1c8250SWilliam Roberts 	audit_log_n_untrustedstring(ab, msg, len);
13213f1c8250SWilliam Roberts 	audit_log_end(ab);
13223f1c8250SWilliam Roberts }
13233f1c8250SWilliam Roberts 
1324e495149bSAl Viro static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
13251da177e4SLinus Torvalds {
13269c7aa6aaSSteve Grubb 	int i, call_panic = 0;
13271da177e4SLinus Torvalds 	struct audit_buffer *ab;
13287551ced3SDavid Woodhouse 	struct audit_aux_data *aux;
13295195d8e2SEric Paris 	struct audit_names *n;
13301da177e4SLinus Torvalds 
1331e495149bSAl Viro 	/* tsk == current */
13323f2792ffSAl Viro 	context->personality = tsk->personality;
1333e495149bSAl Viro 
1334e495149bSAl Viro 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
13351da177e4SLinus Torvalds 	if (!ab)
13361da177e4SLinus Torvalds 		return;		/* audit_panic has been called */
1337bccf6ae0SDavid Woodhouse 	audit_log_format(ab, "arch=%x syscall=%d",
1338bccf6ae0SDavid Woodhouse 			 context->arch, context->major);
13391da177e4SLinus Torvalds 	if (context->personality != PER_LINUX)
13401da177e4SLinus Torvalds 		audit_log_format(ab, " per=%lx", context->personality);
13411da177e4SLinus Torvalds 	if (context->return_valid)
13422fd6f58bS 		audit_log_format(ab, " success=%s exit=%ld",
13432fd6f58bS 				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
13442fd6f58bS 				 context->return_code);
1345eb84a20eSAlan Cox 
13461da177e4SLinus Torvalds 	audit_log_format(ab,
1347e23eb920SPeter Moody 			 " a0=%lx a1=%lx a2=%lx a3=%lx items=%d",
13481da177e4SLinus Torvalds 			 context->argv[0],
13491da177e4SLinus Torvalds 			 context->argv[1],
13501da177e4SLinus Torvalds 			 context->argv[2],
13511da177e4SLinus Torvalds 			 context->argv[3],
1352e23eb920SPeter Moody 			 context->name_count);
1353eb84a20eSAlan Cox 
1354e495149bSAl Viro 	audit_log_task_info(ab, tsk);
13559d960985SEric Paris 	audit_log_key(ab, context->filterkey);
13561da177e4SLinus Torvalds 	audit_log_end(ab);
13571da177e4SLinus Torvalds 
13587551ced3SDavid Woodhouse 	for (aux = context->aux; aux; aux = aux->next) {
1359c0404993SSteve Grubb 
1360e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, aux->type);
13611da177e4SLinus Torvalds 		if (!ab)
13621da177e4SLinus Torvalds 			continue; /* audit_panic has been called */
13631da177e4SLinus Torvalds 
13641da177e4SLinus Torvalds 		switch (aux->type) {
136520ca73bcSGeorge C. Wilson 
13663fc689e9SEric Paris 		case AUDIT_BPRM_FCAPS: {
13673fc689e9SEric Paris 			struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
13683fc689e9SEric Paris 			audit_log_format(ab, "fver=%x", axs->fcap_ver);
13693fc689e9SEric Paris 			audit_log_cap(ab, "fp", &axs->fcap.permitted);
13703fc689e9SEric Paris 			audit_log_cap(ab, "fi", &axs->fcap.inheritable);
13713fc689e9SEric Paris 			audit_log_format(ab, " fe=%d", axs->fcap.fE);
13723fc689e9SEric Paris 			audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
13733fc689e9SEric Paris 			audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
13743fc689e9SEric Paris 			audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
13753fc689e9SEric Paris 			audit_log_cap(ab, "new_pp", &axs->new_pcap.permitted);
13763fc689e9SEric Paris 			audit_log_cap(ab, "new_pi", &axs->new_pcap.inheritable);
13773fc689e9SEric Paris 			audit_log_cap(ab, "new_pe", &axs->new_pcap.effective);
13783fc689e9SEric Paris 			break; }
13793fc689e9SEric Paris 
13801da177e4SLinus Torvalds 		}
13811da177e4SLinus Torvalds 		audit_log_end(ab);
13821da177e4SLinus Torvalds 	}
13831da177e4SLinus Torvalds 
1384f3298dc4SAl Viro 	if (context->type)
1385a33e6751SAl Viro 		show_special(context, &call_panic);
1386f3298dc4SAl Viro 
1387157cf649SAl Viro 	if (context->fds[0] >= 0) {
1388157cf649SAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR);
1389157cf649SAl Viro 		if (ab) {
1390157cf649SAl Viro 			audit_log_format(ab, "fd0=%d fd1=%d",
1391157cf649SAl Viro 					context->fds[0], context->fds[1]);
1392157cf649SAl Viro 			audit_log_end(ab);
1393157cf649SAl Viro 		}
1394157cf649SAl Viro 	}
1395157cf649SAl Viro 
13964f6b434fSAl Viro 	if (context->sockaddr_len) {
13974f6b434fSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR);
13984f6b434fSAl Viro 		if (ab) {
13994f6b434fSAl Viro 			audit_log_format(ab, "saddr=");
14004f6b434fSAl Viro 			audit_log_n_hex(ab, (void *)context->sockaddr,
14014f6b434fSAl Viro 					context->sockaddr_len);
14024f6b434fSAl Viro 			audit_log_end(ab);
14034f6b434fSAl Viro 		}
14044f6b434fSAl Viro 	}
14054f6b434fSAl Viro 
1406e54dc243SAmy Griffis 	for (aux = context->aux_pids; aux; aux = aux->next) {
1407e54dc243SAmy Griffis 		struct audit_aux_data_pids *axs = (void *)aux;
1408e54dc243SAmy Griffis 
1409e54dc243SAmy Griffis 		for (i = 0; i < axs->pid_count; i++)
1410e54dc243SAmy Griffis 			if (audit_log_pid_context(context, axs->target_pid[i],
1411c2a7780eSEric Paris 						  axs->target_auid[i],
1412c2a7780eSEric Paris 						  axs->target_uid[i],
14134746ec5bSEric Paris 						  axs->target_sessionid[i],
1414c2a7780eSEric Paris 						  axs->target_sid[i],
1415c2a7780eSEric Paris 						  axs->target_comm[i]))
1416e54dc243SAmy Griffis 				call_panic = 1;
1417a5cb013dSAl Viro 	}
1418e54dc243SAmy Griffis 
1419e54dc243SAmy Griffis 	if (context->target_pid &&
1420e54dc243SAmy Griffis 	    audit_log_pid_context(context, context->target_pid,
1421c2a7780eSEric Paris 				  context->target_auid, context->target_uid,
14224746ec5bSEric Paris 				  context->target_sessionid,
1423c2a7780eSEric Paris 				  context->target_sid, context->target_comm))
1424e54dc243SAmy Griffis 			call_panic = 1;
1425a5cb013dSAl Viro 
142644707fdfSJan Blunck 	if (context->pwd.dentry && context->pwd.mnt) {
1427e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
14288f37d47cSDavid Woodhouse 		if (ab) {
142944707fdfSJan Blunck 			audit_log_d_path(ab, " cwd=", &context->pwd);
14308f37d47cSDavid Woodhouse 			audit_log_end(ab);
14318f37d47cSDavid Woodhouse 		}
14328f37d47cSDavid Woodhouse 	}
143373241cccSAmy Griffis 
14345195d8e2SEric Paris 	i = 0;
143579f6530cSJeff Layton 	list_for_each_entry(n, &context->names_list, list) {
143679f6530cSJeff Layton 		if (n->hidden)
143779f6530cSJeff Layton 			continue;
1438b24a30a7SEric Paris 		audit_log_name(context, n, NULL, i++, &call_panic);
143979f6530cSJeff Layton 	}
1440c0641f28SEric Paris 
14413f1c8250SWilliam Roberts 	audit_log_proctitle(tsk, context);
14423f1c8250SWilliam Roberts 
1443c0641f28SEric Paris 	/* Send end of event record to help user space know we are finished */
1444c0641f28SEric Paris 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
1445c0641f28SEric Paris 	if (ab)
1446c0641f28SEric Paris 		audit_log_end(ab);
14471b50eed9SSteve Grubb 	if (call_panic)
14481b50eed9SSteve Grubb 		audit_panic("error converting sid to string");
14491da177e4SLinus Torvalds }
14501da177e4SLinus Torvalds 
1451b0dd25a8SRandy Dunlap /**
1452b0dd25a8SRandy Dunlap  * audit_free - free a per-task audit context
1453b0dd25a8SRandy Dunlap  * @tsk: task whose audit context block to free
1454b0dd25a8SRandy Dunlap  *
1455fa84cb93SAl Viro  * Called from copy_process and do_exit
1456b0dd25a8SRandy Dunlap  */
1457a4ff8dbaSEric Paris void __audit_free(struct task_struct *tsk)
14581da177e4SLinus Torvalds {
14591da177e4SLinus Torvalds 	struct audit_context *context;
14601da177e4SLinus Torvalds 
14614a3eb726SRichard Guy Briggs 	context = audit_take_context(tsk, 0, 0);
146256179a6eSEric Paris 	if (!context)
14631da177e4SLinus Torvalds 		return;
14641da177e4SLinus Torvalds 
14651da177e4SLinus Torvalds 	/* Check for system calls that do not go through the exit
1466f5561964SDavid Woodhouse 	 * function (e.g., exit_group), then free context block.
1467f5561964SDavid Woodhouse 	 * We use GFP_ATOMIC here because we might be doing this
1468f5561964SDavid Woodhouse 	 * in the context of the idle thread */
1469e495149bSAl Viro 	/* that can happen only if we are called from do_exit() */
14700590b933SAl Viro 	if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
1471e495149bSAl Viro 		audit_log_exit(context, tsk);
1472916d7576SAl Viro 	if (!list_empty(&context->killed_trees))
1473916d7576SAl Viro 		audit_kill_trees(&context->killed_trees);
14741da177e4SLinus Torvalds 
14751da177e4SLinus Torvalds 	audit_free_context(context);
14761da177e4SLinus Torvalds }
14771da177e4SLinus Torvalds 
1478b0dd25a8SRandy Dunlap /**
1479b0dd25a8SRandy Dunlap  * audit_syscall_entry - fill in an audit record at syscall entry
1480b0dd25a8SRandy Dunlap  * @major: major syscall type (function)
1481b0dd25a8SRandy Dunlap  * @a1: additional syscall register 1
1482b0dd25a8SRandy Dunlap  * @a2: additional syscall register 2
1483b0dd25a8SRandy Dunlap  * @a3: additional syscall register 3
1484b0dd25a8SRandy Dunlap  * @a4: additional syscall register 4
1485b0dd25a8SRandy Dunlap  *
1486b0dd25a8SRandy Dunlap  * Fill in audit context at syscall entry.  This only happens if the
14871da177e4SLinus Torvalds  * audit context was created when the task was created and the state or
14881da177e4SLinus Torvalds  * filters demand the audit context be built.  If the state from the
14891da177e4SLinus Torvalds  * per-task filter or from the per-syscall filter is AUDIT_RECORD_CONTEXT,
14901da177e4SLinus Torvalds  * then the record will be written at syscall exit time (otherwise, it
14911da177e4SLinus Torvalds  * will only be written if another part of the kernel requests that it
1492b0dd25a8SRandy Dunlap  * be written).
1493b0dd25a8SRandy Dunlap  */
1494b4f0d375SRichard Guy Briggs void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
14951da177e4SLinus Torvalds 			   unsigned long a3, unsigned long a4)
14961da177e4SLinus Torvalds {
14975411be59SAl Viro 	struct task_struct *tsk = current;
14981da177e4SLinus Torvalds 	struct audit_context *context = tsk->audit_context;
14991da177e4SLinus Torvalds 	enum audit_state     state;
15001da177e4SLinus Torvalds 
150156179a6eSEric Paris 	if (!context)
150286a1c34aSRoland McGrath 		return;
15031da177e4SLinus Torvalds 
15041da177e4SLinus Torvalds 	BUG_ON(context->in_syscall || context->name_count);
15051da177e4SLinus Torvalds 
15061da177e4SLinus Torvalds 	if (!audit_enabled)
15071da177e4SLinus Torvalds 		return;
15081da177e4SLinus Torvalds 
15094a99854cSRichard Guy Briggs 	context->arch	    = syscall_get_arch();
15101da177e4SLinus Torvalds 	context->major      = major;
15111da177e4SLinus Torvalds 	context->argv[0]    = a1;
15121da177e4SLinus Torvalds 	context->argv[1]    = a2;
15131da177e4SLinus Torvalds 	context->argv[2]    = a3;
15141da177e4SLinus Torvalds 	context->argv[3]    = a4;
15151da177e4SLinus Torvalds 
15161da177e4SLinus Torvalds 	state = context->state;
1517d51374adSAl Viro 	context->dummy = !audit_n_rules;
15180590b933SAl Viro 	if (!context->dummy && state == AUDIT_BUILD_CONTEXT) {
15190590b933SAl Viro 		context->prio = 0;
15200f45aa18SDavid Woodhouse 		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
15210590b933SAl Viro 	}
152256179a6eSEric Paris 	if (state == AUDIT_DISABLED)
15231da177e4SLinus Torvalds 		return;
15241da177e4SLinus Torvalds 
1525ce625a80SDavid Woodhouse 	context->serial     = 0;
15261da177e4SLinus Torvalds 	context->ctime      = CURRENT_TIME;
15271da177e4SLinus Torvalds 	context->in_syscall = 1;
15280590b933SAl Viro 	context->current_state  = state;
1529419c58f1SAlexander Viro 	context->ppid       = 0;
15301da177e4SLinus Torvalds }
15311da177e4SLinus Torvalds 
1532b0dd25a8SRandy Dunlap /**
1533b0dd25a8SRandy Dunlap  * audit_syscall_exit - deallocate audit context after a system call
153442ae610cSRandy Dunlap  * @success: success value of the syscall
153542ae610cSRandy Dunlap  * @return_code: return value of the syscall
1536b0dd25a8SRandy Dunlap  *
1537b0dd25a8SRandy Dunlap  * Tear down after system call.  If the audit context has been marked as
15381da177e4SLinus Torvalds  * auditable (either because of the AUDIT_RECORD_CONTEXT state from
153942ae610cSRandy Dunlap  * filtering, or because some other part of the kernel wrote an audit
15401da177e4SLinus Torvalds  * message), then write out the syscall information.  In call cases,
1541b0dd25a8SRandy Dunlap  * free the names stored from getname().
1542b0dd25a8SRandy Dunlap  */
1543d7e7528bSEric Paris void __audit_syscall_exit(int success, long return_code)
15441da177e4SLinus Torvalds {
15455411be59SAl Viro 	struct task_struct *tsk = current;
15461da177e4SLinus Torvalds 	struct audit_context *context;
15471da177e4SLinus Torvalds 
1548d7e7528bSEric Paris 	if (success)
1549d7e7528bSEric Paris 		success = AUDITSC_SUCCESS;
1550d7e7528bSEric Paris 	else
1551d7e7528bSEric Paris 		success = AUDITSC_FAILURE;
15521da177e4SLinus Torvalds 
15534a3eb726SRichard Guy Briggs 	context = audit_take_context(tsk, success, return_code);
155456179a6eSEric Paris 	if (!context)
155597e94c45SAl Viro 		return;
15561da177e4SLinus Torvalds 
15570590b933SAl Viro 	if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT)
1558e495149bSAl Viro 		audit_log_exit(context, tsk);
15591da177e4SLinus Torvalds 
15601da177e4SLinus Torvalds 	context->in_syscall = 0;
15610590b933SAl Viro 	context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
15622fd6f58bS 
1563916d7576SAl Viro 	if (!list_empty(&context->killed_trees))
1564916d7576SAl Viro 		audit_kill_trees(&context->killed_trees);
1565916d7576SAl Viro 
15661da177e4SLinus Torvalds 	audit_free_names(context);
156774c3cbe3SAl Viro 	unroll_tree_refs(context, NULL, 0);
15681da177e4SLinus Torvalds 	audit_free_aux(context);
1569e54dc243SAmy Griffis 	context->aux = NULL;
1570e54dc243SAmy Griffis 	context->aux_pids = NULL;
1571a5cb013dSAl Viro 	context->target_pid = 0;
1572e54dc243SAmy Griffis 	context->target_sid = 0;
15734f6b434fSAl Viro 	context->sockaddr_len = 0;
1574f3298dc4SAl Viro 	context->type = 0;
1575157cf649SAl Viro 	context->fds[0] = -1;
1576e048e02cSAl Viro 	if (context->state != AUDIT_RECORD_CONTEXT) {
15775adc8a6aSAmy Griffis 		kfree(context->filterkey);
15785adc8a6aSAmy Griffis 		context->filterkey = NULL;
1579e048e02cSAl Viro 	}
15801da177e4SLinus Torvalds 	tsk->audit_context = context;
15811da177e4SLinus Torvalds }
15821da177e4SLinus Torvalds 
158374c3cbe3SAl Viro static inline void handle_one(const struct inode *inode)
158474c3cbe3SAl Viro {
158574c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE
158674c3cbe3SAl Viro 	struct audit_context *context;
158774c3cbe3SAl Viro 	struct audit_tree_refs *p;
158874c3cbe3SAl Viro 	struct audit_chunk *chunk;
158974c3cbe3SAl Viro 	int count;
1590e61ce867SEric Paris 	if (likely(hlist_empty(&inode->i_fsnotify_marks)))
159174c3cbe3SAl Viro 		return;
159274c3cbe3SAl Viro 	context = current->audit_context;
159374c3cbe3SAl Viro 	p = context->trees;
159474c3cbe3SAl Viro 	count = context->tree_count;
159574c3cbe3SAl Viro 	rcu_read_lock();
159674c3cbe3SAl Viro 	chunk = audit_tree_lookup(inode);
159774c3cbe3SAl Viro 	rcu_read_unlock();
159874c3cbe3SAl Viro 	if (!chunk)
159974c3cbe3SAl Viro 		return;
160074c3cbe3SAl Viro 	if (likely(put_tree_ref(context, chunk)))
160174c3cbe3SAl Viro 		return;
160274c3cbe3SAl Viro 	if (unlikely(!grow_tree_refs(context))) {
1603f952d10fSRichard Guy Briggs 		pr_warn("out of memory, audit has lost a tree reference\n");
160474c3cbe3SAl Viro 		audit_set_auditable(context);
160574c3cbe3SAl Viro 		audit_put_chunk(chunk);
160674c3cbe3SAl Viro 		unroll_tree_refs(context, p, count);
160774c3cbe3SAl Viro 		return;
160874c3cbe3SAl Viro 	}
160974c3cbe3SAl Viro 	put_tree_ref(context, chunk);
161074c3cbe3SAl Viro #endif
161174c3cbe3SAl Viro }
161274c3cbe3SAl Viro 
161374c3cbe3SAl Viro static void handle_path(const struct dentry *dentry)
161474c3cbe3SAl Viro {
161574c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE
161674c3cbe3SAl Viro 	struct audit_context *context;
161774c3cbe3SAl Viro 	struct audit_tree_refs *p;
161874c3cbe3SAl Viro 	const struct dentry *d, *parent;
161974c3cbe3SAl Viro 	struct audit_chunk *drop;
162074c3cbe3SAl Viro 	unsigned long seq;
162174c3cbe3SAl Viro 	int count;
162274c3cbe3SAl Viro 
162374c3cbe3SAl Viro 	context = current->audit_context;
162474c3cbe3SAl Viro 	p = context->trees;
162574c3cbe3SAl Viro 	count = context->tree_count;
162674c3cbe3SAl Viro retry:
162774c3cbe3SAl Viro 	drop = NULL;
162874c3cbe3SAl Viro 	d = dentry;
162974c3cbe3SAl Viro 	rcu_read_lock();
163074c3cbe3SAl Viro 	seq = read_seqbegin(&rename_lock);
163174c3cbe3SAl Viro 	for(;;) {
16323b362157SDavid Howells 		struct inode *inode = d_backing_inode(d);
1633e61ce867SEric Paris 		if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_marks))) {
163474c3cbe3SAl Viro 			struct audit_chunk *chunk;
163574c3cbe3SAl Viro 			chunk = audit_tree_lookup(inode);
163674c3cbe3SAl Viro 			if (chunk) {
163774c3cbe3SAl Viro 				if (unlikely(!put_tree_ref(context, chunk))) {
163874c3cbe3SAl Viro 					drop = chunk;
163974c3cbe3SAl Viro 					break;
164074c3cbe3SAl Viro 				}
164174c3cbe3SAl Viro 			}
164274c3cbe3SAl Viro 		}
164374c3cbe3SAl Viro 		parent = d->d_parent;
164474c3cbe3SAl Viro 		if (parent == d)
164574c3cbe3SAl Viro 			break;
164674c3cbe3SAl Viro 		d = parent;
164774c3cbe3SAl Viro 	}
164874c3cbe3SAl Viro 	if (unlikely(read_seqretry(&rename_lock, seq) || drop)) {  /* in this order */
164974c3cbe3SAl Viro 		rcu_read_unlock();
165074c3cbe3SAl Viro 		if (!drop) {
165174c3cbe3SAl Viro 			/* just a race with rename */
165274c3cbe3SAl Viro 			unroll_tree_refs(context, p, count);
165374c3cbe3SAl Viro 			goto retry;
165474c3cbe3SAl Viro 		}
165574c3cbe3SAl Viro 		audit_put_chunk(drop);
165674c3cbe3SAl Viro 		if (grow_tree_refs(context)) {
165774c3cbe3SAl Viro 			/* OK, got more space */
165874c3cbe3SAl Viro 			unroll_tree_refs(context, p, count);
165974c3cbe3SAl Viro 			goto retry;
166074c3cbe3SAl Viro 		}
166174c3cbe3SAl Viro 		/* too bad */
1662f952d10fSRichard Guy Briggs 		pr_warn("out of memory, audit has lost a tree reference\n");
166374c3cbe3SAl Viro 		unroll_tree_refs(context, p, count);
166474c3cbe3SAl Viro 		audit_set_auditable(context);
166574c3cbe3SAl Viro 		return;
166674c3cbe3SAl Viro 	}
166774c3cbe3SAl Viro 	rcu_read_unlock();
166874c3cbe3SAl Viro #endif
166974c3cbe3SAl Viro }
167074c3cbe3SAl Viro 
167178e2e802SJeff Layton static struct audit_names *audit_alloc_name(struct audit_context *context,
167278e2e802SJeff Layton 						unsigned char type)
16735195d8e2SEric Paris {
16745195d8e2SEric Paris 	struct audit_names *aname;
16755195d8e2SEric Paris 
16765195d8e2SEric Paris 	if (context->name_count < AUDIT_NAMES) {
16775195d8e2SEric Paris 		aname = &context->preallocated_names[context->name_count];
16785195d8e2SEric Paris 		memset(aname, 0, sizeof(*aname));
16795195d8e2SEric Paris 	} else {
16805195d8e2SEric Paris 		aname = kzalloc(sizeof(*aname), GFP_NOFS);
16815195d8e2SEric Paris 		if (!aname)
16825195d8e2SEric Paris 			return NULL;
16835195d8e2SEric Paris 		aname->should_free = true;
16845195d8e2SEric Paris 	}
16855195d8e2SEric Paris 
168684cb777eSRichard Guy Briggs 	aname->ino = AUDIT_INO_UNSET;
168778e2e802SJeff Layton 	aname->type = type;
16885195d8e2SEric Paris 	list_add_tail(&aname->list, &context->names_list);
16895195d8e2SEric Paris 
16905195d8e2SEric Paris 	context->name_count++;
16915195d8e2SEric Paris 	return aname;
16925195d8e2SEric Paris }
16935195d8e2SEric Paris 
1694b0dd25a8SRandy Dunlap /**
16957ac86265SJeff Layton  * audit_reusename - fill out filename with info from existing entry
16967ac86265SJeff Layton  * @uptr: userland ptr to pathname
16977ac86265SJeff Layton  *
16987ac86265SJeff Layton  * Search the audit_names list for the current audit context. If there is an
16997ac86265SJeff Layton  * existing entry with a matching "uptr" then return the filename
17007ac86265SJeff Layton  * associated with that audit_name. If not, return NULL.
17017ac86265SJeff Layton  */
17027ac86265SJeff Layton struct filename *
17037ac86265SJeff Layton __audit_reusename(const __user char *uptr)
17047ac86265SJeff Layton {
17057ac86265SJeff Layton 	struct audit_context *context = current->audit_context;
17067ac86265SJeff Layton 	struct audit_names *n;
17077ac86265SJeff Layton 
17087ac86265SJeff Layton 	list_for_each_entry(n, &context->names_list, list) {
17097ac86265SJeff Layton 		if (!n->name)
17107ac86265SJeff Layton 			continue;
171155422d0bSPaul Moore 		if (n->name->uptr == uptr) {
171255422d0bSPaul Moore 			n->name->refcnt++;
17137ac86265SJeff Layton 			return n->name;
17147ac86265SJeff Layton 		}
171555422d0bSPaul Moore 	}
17167ac86265SJeff Layton 	return NULL;
17177ac86265SJeff Layton }
17187ac86265SJeff Layton 
17197ac86265SJeff Layton /**
1720b0dd25a8SRandy Dunlap  * audit_getname - add a name to the list
1721b0dd25a8SRandy Dunlap  * @name: name to add
1722b0dd25a8SRandy Dunlap  *
1723b0dd25a8SRandy Dunlap  * Add a name to the list of audit names for this context.
1724b0dd25a8SRandy Dunlap  * Called from fs/namei.c:getname().
1725b0dd25a8SRandy Dunlap  */
172691a27b2aSJeff Layton void __audit_getname(struct filename *name)
17271da177e4SLinus Torvalds {
17281da177e4SLinus Torvalds 	struct audit_context *context = current->audit_context;
17295195d8e2SEric Paris 	struct audit_names *n;
17301da177e4SLinus Torvalds 
173155422d0bSPaul Moore 	if (!context->in_syscall)
17321da177e4SLinus Torvalds 		return;
173391a27b2aSJeff Layton 
173478e2e802SJeff Layton 	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
17355195d8e2SEric Paris 	if (!n)
17365195d8e2SEric Paris 		return;
17375195d8e2SEric Paris 
17385195d8e2SEric Paris 	n->name = name;
17395195d8e2SEric Paris 	n->name_len = AUDIT_NAME_FULL;
1740adb5c247SJeff Layton 	name->aname = n;
174155422d0bSPaul Moore 	name->refcnt++;
17425195d8e2SEric Paris 
1743f7ad3c6bSMiklos Szeredi 	if (!context->pwd.dentry)
1744f7ad3c6bSMiklos Szeredi 		get_fs_pwd(current->fs, &context->pwd);
17451da177e4SLinus Torvalds }
17461da177e4SLinus Torvalds 
1747b0dd25a8SRandy Dunlap /**
1748bfcec708SJeff Layton  * __audit_inode - store the inode and device from a lookup
1749b0dd25a8SRandy Dunlap  * @name: name being audited
1750481968f4SRandy Dunlap  * @dentry: dentry being audited
175179f6530cSJeff Layton  * @flags: attributes for this particular entry
1752b0dd25a8SRandy Dunlap  */
1753adb5c247SJeff Layton void __audit_inode(struct filename *name, const struct dentry *dentry,
175479f6530cSJeff Layton 		   unsigned int flags)
17551da177e4SLinus Torvalds {
17561da177e4SLinus Torvalds 	struct audit_context *context = current->audit_context;
17573b362157SDavid Howells 	const struct inode *inode = d_backing_inode(dentry);
17585195d8e2SEric Paris 	struct audit_names *n;
175979f6530cSJeff Layton 	bool parent = flags & AUDIT_INODE_PARENT;
17601da177e4SLinus Torvalds 
17611da177e4SLinus Torvalds 	if (!context->in_syscall)
17621da177e4SLinus Torvalds 		return;
17635195d8e2SEric Paris 
17649cec9d68SJeff Layton 	if (!name)
17659cec9d68SJeff Layton 		goto out_alloc;
17669cec9d68SJeff Layton 
1767adb5c247SJeff Layton 	/*
1768adb5c247SJeff Layton 	 * If we have a pointer to an audit_names entry already, then we can
1769adb5c247SJeff Layton 	 * just use it directly if the type is correct.
1770adb5c247SJeff Layton 	 */
1771adb5c247SJeff Layton 	n = name->aname;
1772adb5c247SJeff Layton 	if (n) {
1773adb5c247SJeff Layton 		if (parent) {
1774adb5c247SJeff Layton 			if (n->type == AUDIT_TYPE_PARENT ||
1775adb5c247SJeff Layton 			    n->type == AUDIT_TYPE_UNKNOWN)
1776adb5c247SJeff Layton 				goto out;
1777adb5c247SJeff Layton 		} else {
1778adb5c247SJeff Layton 			if (n->type != AUDIT_TYPE_PARENT)
1779adb5c247SJeff Layton 				goto out;
1780adb5c247SJeff Layton 		}
1781adb5c247SJeff Layton 	}
1782adb5c247SJeff Layton 
17835195d8e2SEric Paris 	list_for_each_entry_reverse(n, &context->names_list, list) {
178457c59f58SPaul Moore 		if (n->ino) {
178557c59f58SPaul Moore 			/* valid inode number, use that for the comparison */
178657c59f58SPaul Moore 			if (n->ino != inode->i_ino ||
178757c59f58SPaul Moore 			    n->dev != inode->i_sb->s_dev)
178857c59f58SPaul Moore 				continue;
178957c59f58SPaul Moore 		} else if (n->name) {
179057c59f58SPaul Moore 			/* inode number has not been set, check the name */
179157c59f58SPaul Moore 			if (strcmp(n->name->name, name->name))
179257c59f58SPaul Moore 				continue;
179357c59f58SPaul Moore 		} else
179457c59f58SPaul Moore 			/* no inode and no name (?!) ... this is odd ... */
1795bfcec708SJeff Layton 			continue;
1796bfcec708SJeff Layton 
1797bfcec708SJeff Layton 		/* match the correct record type */
1798bfcec708SJeff Layton 		if (parent) {
1799bfcec708SJeff Layton 			if (n->type == AUDIT_TYPE_PARENT ||
1800bfcec708SJeff Layton 			    n->type == AUDIT_TYPE_UNKNOWN)
18015195d8e2SEric Paris 				goto out;
1802bfcec708SJeff Layton 		} else {
1803bfcec708SJeff Layton 			if (n->type != AUDIT_TYPE_PARENT)
1804bfcec708SJeff Layton 				goto out;
1805bfcec708SJeff Layton 		}
18061da177e4SLinus Torvalds 	}
18075195d8e2SEric Paris 
18089cec9d68SJeff Layton out_alloc:
18094a928436SPaul Moore 	/* unable to find an entry with both a matching name and type */
18104a928436SPaul Moore 	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
18115195d8e2SEric Paris 	if (!n)
18125195d8e2SEric Paris 		return;
1813fcf22d82SPaul Moore 	if (name) {
1814fd3522fdSPaul Moore 		n->name = name;
181555422d0bSPaul Moore 		name->refcnt++;
1816fcf22d82SPaul Moore 	}
18174a928436SPaul Moore 
18185195d8e2SEric Paris out:
1819bfcec708SJeff Layton 	if (parent) {
182091a27b2aSJeff Layton 		n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
1821bfcec708SJeff Layton 		n->type = AUDIT_TYPE_PARENT;
182279f6530cSJeff Layton 		if (flags & AUDIT_INODE_HIDDEN)
182379f6530cSJeff Layton 			n->hidden = true;
1824bfcec708SJeff Layton 	} else {
1825bfcec708SJeff Layton 		n->name_len = AUDIT_NAME_FULL;
1826bfcec708SJeff Layton 		n->type = AUDIT_TYPE_NORMAL;
1827bfcec708SJeff Layton 	}
182874c3cbe3SAl Viro 	handle_path(dentry);
18295195d8e2SEric Paris 	audit_copy_inode(n, dentry, inode);
183073241cccSAmy Griffis }
183173241cccSAmy Griffis 
18329f45f5bfSAl Viro void __audit_file(const struct file *file)
18339f45f5bfSAl Viro {
18349f45f5bfSAl Viro 	__audit_inode(NULL, file->f_path.dentry, 0);
18359f45f5bfSAl Viro }
18369f45f5bfSAl Viro 
183773241cccSAmy Griffis /**
1838c43a25abSJeff Layton  * __audit_inode_child - collect inode info for created/removed objects
183973d3ec5aSAmy Griffis  * @parent: inode of dentry parent
1840c43a25abSJeff Layton  * @dentry: dentry being audited
18414fa6b5ecSJeff Layton  * @type:   AUDIT_TYPE_* value that we're looking for
184273241cccSAmy Griffis  *
184373241cccSAmy Griffis  * For syscalls that create or remove filesystem objects, audit_inode
184473241cccSAmy Griffis  * can only collect information for the filesystem object's parent.
184573241cccSAmy Griffis  * This call updates the audit context with the child's information.
184673241cccSAmy Griffis  * Syscalls that create a new filesystem object must be hooked after
184773241cccSAmy Griffis  * the object is created.  Syscalls that remove a filesystem object
184873241cccSAmy Griffis  * must be hooked prior, in order to capture the target inode during
184973241cccSAmy Griffis  * unsuccessful attempts.
185073241cccSAmy Griffis  */
1851c43a25abSJeff Layton void __audit_inode_child(const struct inode *parent,
18524fa6b5ecSJeff Layton 			 const struct dentry *dentry,
18534fa6b5ecSJeff Layton 			 const unsigned char type)
185473241cccSAmy Griffis {
185573241cccSAmy Griffis 	struct audit_context *context = current->audit_context;
18563b362157SDavid Howells 	const struct inode *inode = d_backing_inode(dentry);
1857cccc6bbaSAl Viro 	const char *dname = dentry->d_name.name;
18584fa6b5ecSJeff Layton 	struct audit_names *n, *found_parent = NULL, *found_child = NULL;
185973241cccSAmy Griffis 
186073241cccSAmy Griffis 	if (!context->in_syscall)
186173241cccSAmy Griffis 		return;
186273241cccSAmy Griffis 
186374c3cbe3SAl Viro 	if (inode)
186474c3cbe3SAl Viro 		handle_one(inode);
186573241cccSAmy Griffis 
18664fa6b5ecSJeff Layton 	/* look for a parent entry first */
18675195d8e2SEric Paris 	list_for_each_entry(n, &context->names_list, list) {
186857c59f58SPaul Moore 		if (!n->name ||
186957c59f58SPaul Moore 		    (n->type != AUDIT_TYPE_PARENT &&
187057c59f58SPaul Moore 		     n->type != AUDIT_TYPE_UNKNOWN))
187173241cccSAmy Griffis 			continue;
187273241cccSAmy Griffis 
187357c59f58SPaul Moore 		if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev &&
187457c59f58SPaul Moore 		    !audit_compare_dname_path(dname,
187557c59f58SPaul Moore 					      n->name->name, n->name_len)) {
187657c59f58SPaul Moore 			if (n->type == AUDIT_TYPE_UNKNOWN)
187757c59f58SPaul Moore 				n->type = AUDIT_TYPE_PARENT;
18784fa6b5ecSJeff Layton 			found_parent = n;
18794fa6b5ecSJeff Layton 			break;
18809c937dccSAmy Griffis 		}
188173241cccSAmy Griffis 	}
188273241cccSAmy Griffis 
18834fa6b5ecSJeff Layton 	/* is there a matching child entry? */
18845195d8e2SEric Paris 	list_for_each_entry(n, &context->names_list, list) {
18854fa6b5ecSJeff Layton 		/* can only match entries that have a name */
188657c59f58SPaul Moore 		if (!n->name ||
188757c59f58SPaul Moore 		    (n->type != type && n->type != AUDIT_TYPE_UNKNOWN))
18884fa6b5ecSJeff Layton 			continue;
18894fa6b5ecSJeff Layton 
189091a27b2aSJeff Layton 		if (!strcmp(dname, n->name->name) ||
189191a27b2aSJeff Layton 		    !audit_compare_dname_path(dname, n->name->name,
18924fa6b5ecSJeff Layton 						found_parent ?
18934fa6b5ecSJeff Layton 						found_parent->name_len :
1894e3d6b07bSJeff Layton 						AUDIT_NAME_FULL)) {
189557c59f58SPaul Moore 			if (n->type == AUDIT_TYPE_UNKNOWN)
189657c59f58SPaul Moore 				n->type = type;
18974fa6b5ecSJeff Layton 			found_child = n;
18984fa6b5ecSJeff Layton 			break;
1899ac9910ceSSteve Grubb 		}
19005712e88fSAmy Griffis 	}
19015712e88fSAmy Griffis 
19025712e88fSAmy Griffis 	if (!found_parent) {
19034fa6b5ecSJeff Layton 		/* create a new, "anonymous" parent record */
19044fa6b5ecSJeff Layton 		n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
19055195d8e2SEric Paris 		if (!n)
19065712e88fSAmy Griffis 			return;
19075195d8e2SEric Paris 		audit_copy_inode(n, NULL, parent);
190873d3ec5aSAmy Griffis 	}
19095712e88fSAmy Griffis 
19105712e88fSAmy Griffis 	if (!found_child) {
19114fa6b5ecSJeff Layton 		found_child = audit_alloc_name(context, type);
19124fa6b5ecSJeff Layton 		if (!found_child)
19135712e88fSAmy Griffis 			return;
19145712e88fSAmy Griffis 
19155712e88fSAmy Griffis 		/* Re-use the name belonging to the slot for a matching parent
19165712e88fSAmy Griffis 		 * directory. All names for this context are relinquished in
19175712e88fSAmy Griffis 		 * audit_free_names() */
19185712e88fSAmy Griffis 		if (found_parent) {
19194fa6b5ecSJeff Layton 			found_child->name = found_parent->name;
19204fa6b5ecSJeff Layton 			found_child->name_len = AUDIT_NAME_FULL;
192155422d0bSPaul Moore 			found_child->name->refcnt++;
19225712e88fSAmy Griffis 		}
19234fa6b5ecSJeff Layton 	}
192457c59f58SPaul Moore 
19255712e88fSAmy Griffis 	if (inode)
19264fa6b5ecSJeff Layton 		audit_copy_inode(found_child, dentry, inode);
19274fa6b5ecSJeff Layton 	else
192884cb777eSRichard Guy Briggs 		found_child->ino = AUDIT_INO_UNSET;
19293e2efce0SAmy Griffis }
193050e437d5STrond Myklebust EXPORT_SYMBOL_GPL(__audit_inode_child);
19313e2efce0SAmy Griffis 
19323e2efce0SAmy Griffis /**
1933b0dd25a8SRandy Dunlap  * auditsc_get_stamp - get local copies of audit_context values
1934b0dd25a8SRandy Dunlap  * @ctx: audit_context for the task
1935b0dd25a8SRandy Dunlap  * @t: timespec to store time recorded in the audit_context
1936b0dd25a8SRandy Dunlap  * @serial: serial value that is recorded in the audit_context
1937b0dd25a8SRandy Dunlap  *
1938b0dd25a8SRandy Dunlap  * Also sets the context as auditable.
1939b0dd25a8SRandy Dunlap  */
194048887e63SAl Viro int auditsc_get_stamp(struct audit_context *ctx,
1941d812ddbbSSteve Grubb 		       struct timespec *t, unsigned int *serial)
19421da177e4SLinus Torvalds {
194348887e63SAl Viro 	if (!ctx->in_syscall)
194448887e63SAl Viro 		return 0;
1945ce625a80SDavid Woodhouse 	if (!ctx->serial)
1946ce625a80SDavid Woodhouse 		ctx->serial = audit_serial();
19471da177e4SLinus Torvalds 	t->tv_sec  = ctx->ctime.tv_sec;
19481da177e4SLinus Torvalds 	t->tv_nsec = ctx->ctime.tv_nsec;
19491da177e4SLinus Torvalds 	*serial    = ctx->serial;
19500590b933SAl Viro 	if (!ctx->prio) {
19510590b933SAl Viro 		ctx->prio = 1;
19520590b933SAl Viro 		ctx->current_state = AUDIT_RECORD_CONTEXT;
19530590b933SAl Viro 	}
195448887e63SAl Viro 	return 1;
19551da177e4SLinus Torvalds }
19561da177e4SLinus Torvalds 
19574746ec5bSEric Paris /* global counter which is incremented every time something logs in */
19584746ec5bSEric Paris static atomic_t session_id = ATOMIC_INIT(0);
19594746ec5bSEric Paris 
1960da0a6104SEric Paris static int audit_set_loginuid_perm(kuid_t loginuid)
1961da0a6104SEric Paris {
1962da0a6104SEric Paris 	/* if we are unset, we don't need privs */
1963da0a6104SEric Paris 	if (!audit_loginuid_set(current))
1964da0a6104SEric Paris 		return 0;
196521b85c31SEric Paris 	/* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/
196621b85c31SEric Paris 	if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE))
196721b85c31SEric Paris 		return -EPERM;
196883fa6bbeSEric Paris 	/* it is set, you need permission */
196983fa6bbeSEric Paris 	if (!capable(CAP_AUDIT_CONTROL))
1970da0a6104SEric Paris 		return -EPERM;
1971d040e5afSEric Paris 	/* reject if this is not an unset and we don't allow that */
1972d040e5afSEric Paris 	if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) && uid_valid(loginuid))
1973d040e5afSEric Paris 		return -EPERM;
197483fa6bbeSEric Paris 	return 0;
1975da0a6104SEric Paris }
1976da0a6104SEric Paris 
1977da0a6104SEric Paris static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid,
1978da0a6104SEric Paris 				   unsigned int oldsessionid, unsigned int sessionid,
1979da0a6104SEric Paris 				   int rc)
1980da0a6104SEric Paris {
1981da0a6104SEric Paris 	struct audit_buffer *ab;
19825ee9a75cSRichard Guy Briggs 	uid_t uid, oldloginuid, loginuid;
1983da0a6104SEric Paris 
1984c2412d91SGao feng 	if (!audit_enabled)
1985c2412d91SGao feng 		return;
1986c2412d91SGao feng 
1987da0a6104SEric Paris 	uid = from_kuid(&init_user_ns, task_uid(current));
19885ee9a75cSRichard Guy Briggs 	oldloginuid = from_kuid(&init_user_ns, koldloginuid);
19895ee9a75cSRichard Guy Briggs 	loginuid = from_kuid(&init_user_ns, kloginuid),
1990da0a6104SEric Paris 
1991da0a6104SEric Paris 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
1992da0a6104SEric Paris 	if (!ab)
1993da0a6104SEric Paris 		return;
1994ddfad8afSEric Paris 	audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid);
1995ddfad8afSEric Paris 	audit_log_task_context(ab);
1996ddfad8afSEric Paris 	audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d",
1997ddfad8afSEric Paris 			 oldloginuid, loginuid, oldsessionid, sessionid, !rc);
1998da0a6104SEric Paris 	audit_log_end(ab);
1999da0a6104SEric Paris }
2000da0a6104SEric Paris 
2001b0dd25a8SRandy Dunlap /**
20020a300be6SEric Paris  * audit_set_loginuid - set current task's audit_context loginuid
2003b0dd25a8SRandy Dunlap  * @loginuid: loginuid value
2004b0dd25a8SRandy Dunlap  *
2005b0dd25a8SRandy Dunlap  * Returns 0.
2006b0dd25a8SRandy Dunlap  *
2007b0dd25a8SRandy Dunlap  * Called (set) from fs/proc/base.c::proc_loginuid_write().
2008b0dd25a8SRandy Dunlap  */
2009e1760bd5SEric W. Biederman int audit_set_loginuid(kuid_t loginuid)
20101da177e4SLinus Torvalds {
20110a300be6SEric Paris 	struct task_struct *task = current;
20129175c9d2SEric Paris 	unsigned int oldsessionid, sessionid = (unsigned int)-1;
20139175c9d2SEric Paris 	kuid_t oldloginuid;
2014da0a6104SEric Paris 	int rc;
201541757106SSteve Grubb 
2016da0a6104SEric Paris 	oldloginuid = audit_get_loginuid(current);
2017da0a6104SEric Paris 	oldsessionid = audit_get_sessionid(current);
2018da0a6104SEric Paris 
2019da0a6104SEric Paris 	rc = audit_set_loginuid_perm(loginuid);
2020da0a6104SEric Paris 	if (rc)
2021da0a6104SEric Paris 		goto out;
2022633b4545SEric Paris 
202381407c84SEric Paris 	/* are we setting or clearing? */
202481407c84SEric Paris 	if (uid_valid(loginuid))
20254440e854SEric Paris 		sessionid = (unsigned int)atomic_inc_return(&session_id);
2026c0404993SSteve Grubb 
20274746ec5bSEric Paris 	task->sessionid = sessionid;
2028bfef93a5SAl Viro 	task->loginuid = loginuid;
2029da0a6104SEric Paris out:
2030da0a6104SEric Paris 	audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc);
2031da0a6104SEric Paris 	return rc;
20321da177e4SLinus Torvalds }
20331da177e4SLinus Torvalds 
2034b0dd25a8SRandy Dunlap /**
203520ca73bcSGeorge C. Wilson  * __audit_mq_open - record audit data for a POSIX MQ open
203620ca73bcSGeorge C. Wilson  * @oflag: open flag
203720ca73bcSGeorge C. Wilson  * @mode: mode bits
20386b962559SRandy Dunlap  * @attr: queue attributes
203920ca73bcSGeorge C. Wilson  *
204020ca73bcSGeorge C. Wilson  */
2041df0a4283SAl Viro void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
204220ca73bcSGeorge C. Wilson {
204320ca73bcSGeorge C. Wilson 	struct audit_context *context = current->audit_context;
204420ca73bcSGeorge C. Wilson 
2045564f6993SAl Viro 	if (attr)
2046564f6993SAl Viro 		memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr));
2047564f6993SAl Viro 	else
2048564f6993SAl Viro 		memset(&context->mq_open.attr, 0, sizeof(struct mq_attr));
204920ca73bcSGeorge C. Wilson 
2050564f6993SAl Viro 	context->mq_open.oflag = oflag;
2051564f6993SAl Viro 	context->mq_open.mode = mode;
205220ca73bcSGeorge C. Wilson 
2053564f6993SAl Viro 	context->type = AUDIT_MQ_OPEN;
205420ca73bcSGeorge C. Wilson }
205520ca73bcSGeorge C. Wilson 
205620ca73bcSGeorge C. Wilson /**
2057c32c8af4SAl Viro  * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive
205820ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
205920ca73bcSGeorge C. Wilson  * @msg_len: Message length
206020ca73bcSGeorge C. Wilson  * @msg_prio: Message priority
2061c32c8af4SAl Viro  * @abs_timeout: Message timeout in absolute time
206220ca73bcSGeorge C. Wilson  *
206320ca73bcSGeorge C. Wilson  */
2064c32c8af4SAl Viro void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
2065c32c8af4SAl Viro 			const struct timespec *abs_timeout)
206620ca73bcSGeorge C. Wilson {
206720ca73bcSGeorge C. Wilson 	struct audit_context *context = current->audit_context;
2068c32c8af4SAl Viro 	struct timespec *p = &context->mq_sendrecv.abs_timeout;
206920ca73bcSGeorge C. Wilson 
2070c32c8af4SAl Viro 	if (abs_timeout)
2071c32c8af4SAl Viro 		memcpy(p, abs_timeout, sizeof(struct timespec));
2072c32c8af4SAl Viro 	else
2073c32c8af4SAl Viro 		memset(p, 0, sizeof(struct timespec));
207420ca73bcSGeorge C. Wilson 
2075c32c8af4SAl Viro 	context->mq_sendrecv.mqdes = mqdes;
2076c32c8af4SAl Viro 	context->mq_sendrecv.msg_len = msg_len;
2077c32c8af4SAl Viro 	context->mq_sendrecv.msg_prio = msg_prio;
207820ca73bcSGeorge C. Wilson 
2079c32c8af4SAl Viro 	context->type = AUDIT_MQ_SENDRECV;
208020ca73bcSGeorge C. Wilson }
208120ca73bcSGeorge C. Wilson 
208220ca73bcSGeorge C. Wilson /**
208320ca73bcSGeorge C. Wilson  * __audit_mq_notify - record audit data for a POSIX MQ notify
208420ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
20856b962559SRandy Dunlap  * @notification: Notification event
208620ca73bcSGeorge C. Wilson  *
208720ca73bcSGeorge C. Wilson  */
208820ca73bcSGeorge C. Wilson 
208920114f71SAl Viro void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
209020ca73bcSGeorge C. Wilson {
209120ca73bcSGeorge C. Wilson 	struct audit_context *context = current->audit_context;
209220ca73bcSGeorge C. Wilson 
209320114f71SAl Viro 	if (notification)
209420114f71SAl Viro 		context->mq_notify.sigev_signo = notification->sigev_signo;
209520114f71SAl Viro 	else
209620114f71SAl Viro 		context->mq_notify.sigev_signo = 0;
209720ca73bcSGeorge C. Wilson 
209820114f71SAl Viro 	context->mq_notify.mqdes = mqdes;
209920114f71SAl Viro 	context->type = AUDIT_MQ_NOTIFY;
210020ca73bcSGeorge C. Wilson }
210120ca73bcSGeorge C. Wilson 
210220ca73bcSGeorge C. Wilson /**
210320ca73bcSGeorge C. Wilson  * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
210420ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
210520ca73bcSGeorge C. Wilson  * @mqstat: MQ flags
210620ca73bcSGeorge C. Wilson  *
210720ca73bcSGeorge C. Wilson  */
21087392906eSAl Viro void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
210920ca73bcSGeorge C. Wilson {
211020ca73bcSGeorge C. Wilson 	struct audit_context *context = current->audit_context;
21117392906eSAl Viro 	context->mq_getsetattr.mqdes = mqdes;
21127392906eSAl Viro 	context->mq_getsetattr.mqstat = *mqstat;
21137392906eSAl Viro 	context->type = AUDIT_MQ_GETSETATTR;
211420ca73bcSGeorge C. Wilson }
211520ca73bcSGeorge C. Wilson 
211620ca73bcSGeorge C. Wilson /**
2117073115d6SSteve Grubb  * audit_ipc_obj - record audit data for ipc object
2118073115d6SSteve Grubb  * @ipcp: ipc permissions
2119073115d6SSteve Grubb  *
2120073115d6SSteve Grubb  */
2121a33e6751SAl Viro void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
2122073115d6SSteve Grubb {
2123073115d6SSteve Grubb 	struct audit_context *context = current->audit_context;
2124a33e6751SAl Viro 	context->ipc.uid = ipcp->uid;
2125a33e6751SAl Viro 	context->ipc.gid = ipcp->gid;
2126a33e6751SAl Viro 	context->ipc.mode = ipcp->mode;
2127e816f370SAl Viro 	context->ipc.has_perm = 0;
2128a33e6751SAl Viro 	security_ipc_getsecid(ipcp, &context->ipc.osid);
2129a33e6751SAl Viro 	context->type = AUDIT_IPC;
2130073115d6SSteve Grubb }
2131073115d6SSteve Grubb 
2132073115d6SSteve Grubb /**
2133073115d6SSteve Grubb  * audit_ipc_set_perm - record audit data for new ipc permissions
2134b0dd25a8SRandy Dunlap  * @qbytes: msgq bytes
2135b0dd25a8SRandy Dunlap  * @uid: msgq user id
2136b0dd25a8SRandy Dunlap  * @gid: msgq group id
2137b0dd25a8SRandy Dunlap  * @mode: msgq mode (permissions)
2138b0dd25a8SRandy Dunlap  *
2139e816f370SAl Viro  * Called only after audit_ipc_obj().
2140b0dd25a8SRandy Dunlap  */
21412570ebbdSAl Viro void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode)
21421da177e4SLinus Torvalds {
21431da177e4SLinus Torvalds 	struct audit_context *context = current->audit_context;
21441da177e4SLinus Torvalds 
2145e816f370SAl Viro 	context->ipc.qbytes = qbytes;
2146e816f370SAl Viro 	context->ipc.perm_uid = uid;
2147e816f370SAl Viro 	context->ipc.perm_gid = gid;
2148e816f370SAl Viro 	context->ipc.perm_mode = mode;
2149e816f370SAl Viro 	context->ipc.has_perm = 1;
21501da177e4SLinus Torvalds }
2151c2f0c7c3SSteve Grubb 
2152d9cfea91SRichard Guy Briggs void __audit_bprm(struct linux_binprm *bprm)
2153473ae30bSAl Viro {
2154473ae30bSAl Viro 	struct audit_context *context = current->audit_context;
2155473ae30bSAl Viro 
2156d9cfea91SRichard Guy Briggs 	context->type = AUDIT_EXECVE;
2157d9cfea91SRichard Guy Briggs 	context->execve.argc = bprm->argc;
2158473ae30bSAl Viro }
2159473ae30bSAl Viro 
2160473ae30bSAl Viro 
2161b0dd25a8SRandy Dunlap /**
2162b0dd25a8SRandy Dunlap  * audit_socketcall - record audit data for sys_socketcall
21632950fa9dSChen Gang  * @nargs: number of args, which should not be more than AUDITSC_ARGS.
2164b0dd25a8SRandy Dunlap  * @args: args array
2165b0dd25a8SRandy Dunlap  *
2166b0dd25a8SRandy Dunlap  */
21672950fa9dSChen Gang int __audit_socketcall(int nargs, unsigned long *args)
21683ec3b2fbSDavid Woodhouse {
21693ec3b2fbSDavid Woodhouse 	struct audit_context *context = current->audit_context;
21703ec3b2fbSDavid Woodhouse 
21712950fa9dSChen Gang 	if (nargs <= 0 || nargs > AUDITSC_ARGS || !args)
21722950fa9dSChen Gang 		return -EINVAL;
2173f3298dc4SAl Viro 	context->type = AUDIT_SOCKETCALL;
2174f3298dc4SAl Viro 	context->socketcall.nargs = nargs;
2175f3298dc4SAl Viro 	memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
21762950fa9dSChen Gang 	return 0;
21773ec3b2fbSDavid Woodhouse }
21783ec3b2fbSDavid Woodhouse 
2179b0dd25a8SRandy Dunlap /**
2180db349509SAl Viro  * __audit_fd_pair - record audit data for pipe and socketpair
2181db349509SAl Viro  * @fd1: the first file descriptor
2182db349509SAl Viro  * @fd2: the second file descriptor
2183db349509SAl Viro  *
2184db349509SAl Viro  */
2185157cf649SAl Viro void __audit_fd_pair(int fd1, int fd2)
2186db349509SAl Viro {
2187db349509SAl Viro 	struct audit_context *context = current->audit_context;
2188157cf649SAl Viro 	context->fds[0] = fd1;
2189157cf649SAl Viro 	context->fds[1] = fd2;
2190db349509SAl Viro }
2191db349509SAl Viro 
2192db349509SAl Viro /**
2193b0dd25a8SRandy Dunlap  * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
2194b0dd25a8SRandy Dunlap  * @len: data length in user space
2195b0dd25a8SRandy Dunlap  * @a: data address in kernel space
2196b0dd25a8SRandy Dunlap  *
2197b0dd25a8SRandy Dunlap  * Returns 0 for success or NULL context or < 0 on error.
2198b0dd25a8SRandy Dunlap  */
219907c49417SEric Paris int __audit_sockaddr(int len, void *a)
22003ec3b2fbSDavid Woodhouse {
22013ec3b2fbSDavid Woodhouse 	struct audit_context *context = current->audit_context;
22023ec3b2fbSDavid Woodhouse 
22034f6b434fSAl Viro 	if (!context->sockaddr) {
22044f6b434fSAl Viro 		void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
22054f6b434fSAl Viro 		if (!p)
22063ec3b2fbSDavid Woodhouse 			return -ENOMEM;
22074f6b434fSAl Viro 		context->sockaddr = p;
22084f6b434fSAl Viro 	}
22093ec3b2fbSDavid Woodhouse 
22104f6b434fSAl Viro 	context->sockaddr_len = len;
22114f6b434fSAl Viro 	memcpy(context->sockaddr, a, len);
22123ec3b2fbSDavid Woodhouse 	return 0;
22133ec3b2fbSDavid Woodhouse }
22143ec3b2fbSDavid Woodhouse 
2215a5cb013dSAl Viro void __audit_ptrace(struct task_struct *t)
2216a5cb013dSAl Viro {
2217a5cb013dSAl Viro 	struct audit_context *context = current->audit_context;
2218a5cb013dSAl Viro 
2219f1dc4867SRichard Guy Briggs 	context->target_pid = task_pid_nr(t);
2220c2a7780eSEric Paris 	context->target_auid = audit_get_loginuid(t);
2221c69e8d9cSDavid Howells 	context->target_uid = task_uid(t);
22224746ec5bSEric Paris 	context->target_sessionid = audit_get_sessionid(t);
22232a862b32SAhmed S. Darwish 	security_task_getsecid(t, &context->target_sid);
2224c2a7780eSEric Paris 	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
2225a5cb013dSAl Viro }
2226a5cb013dSAl Viro 
2227b0dd25a8SRandy Dunlap /**
2228b0dd25a8SRandy Dunlap  * audit_signal_info - record signal info for shutting down audit subsystem
2229b0dd25a8SRandy Dunlap  * @sig: signal value
2230b0dd25a8SRandy Dunlap  * @t: task being signaled
2231b0dd25a8SRandy Dunlap  *
2232b0dd25a8SRandy Dunlap  * If the audit subsystem is being terminated, record the task (pid)
2233b0dd25a8SRandy Dunlap  * and uid that is doing that.
2234b0dd25a8SRandy Dunlap  */
2235e54dc243SAmy Griffis int __audit_signal_info(int sig, struct task_struct *t)
2236c2f0c7c3SSteve Grubb {
2237e54dc243SAmy Griffis 	struct audit_aux_data_pids *axp;
2238e54dc243SAmy Griffis 	struct task_struct *tsk = current;
2239e54dc243SAmy Griffis 	struct audit_context *ctx = tsk->audit_context;
2240cca080d9SEric W. Biederman 	kuid_t uid = current_uid(), t_uid = task_uid(t);
2241c2f0c7c3SSteve Grubb 
2242175fc484SAl Viro 	if (audit_pid && t->tgid == audit_pid) {
2243ee1d3156SEric Paris 		if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
2244f1dc4867SRichard Guy Briggs 			audit_sig_pid = task_pid_nr(tsk);
2245e1760bd5SEric W. Biederman 			if (uid_valid(tsk->loginuid))
2246bfef93a5SAl Viro 				audit_sig_uid = tsk->loginuid;
2247c2f0c7c3SSteve Grubb 			else
2248c69e8d9cSDavid Howells 				audit_sig_uid = uid;
22492a862b32SAhmed S. Darwish 			security_task_getsecid(tsk, &audit_sig_sid);
2250c2f0c7c3SSteve Grubb 		}
2251175fc484SAl Viro 		if (!audit_signals || audit_dummy_context())
2252e54dc243SAmy Griffis 			return 0;
2253175fc484SAl Viro 	}
2254e54dc243SAmy Griffis 
2255e54dc243SAmy Griffis 	/* optimize the common case by putting first signal recipient directly
2256e54dc243SAmy Griffis 	 * in audit_context */
2257e54dc243SAmy Griffis 	if (!ctx->target_pid) {
2258f1dc4867SRichard Guy Briggs 		ctx->target_pid = task_tgid_nr(t);
2259c2a7780eSEric Paris 		ctx->target_auid = audit_get_loginuid(t);
2260c69e8d9cSDavid Howells 		ctx->target_uid = t_uid;
22614746ec5bSEric Paris 		ctx->target_sessionid = audit_get_sessionid(t);
22622a862b32SAhmed S. Darwish 		security_task_getsecid(t, &ctx->target_sid);
2263c2a7780eSEric Paris 		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
2264e54dc243SAmy Griffis 		return 0;
2265e54dc243SAmy Griffis 	}
2266e54dc243SAmy Griffis 
2267e54dc243SAmy Griffis 	axp = (void *)ctx->aux_pids;
2268e54dc243SAmy Griffis 	if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
2269e54dc243SAmy Griffis 		axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
2270e54dc243SAmy Griffis 		if (!axp)
2271e54dc243SAmy Griffis 			return -ENOMEM;
2272e54dc243SAmy Griffis 
2273e54dc243SAmy Griffis 		axp->d.type = AUDIT_OBJ_PID;
2274e54dc243SAmy Griffis 		axp->d.next = ctx->aux_pids;
2275e54dc243SAmy Griffis 		ctx->aux_pids = (void *)axp;
2276e54dc243SAmy Griffis 	}
227788ae704cSAdrian Bunk 	BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
2278e54dc243SAmy Griffis 
2279f1dc4867SRichard Guy Briggs 	axp->target_pid[axp->pid_count] = task_tgid_nr(t);
2280c2a7780eSEric Paris 	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
2281c69e8d9cSDavid Howells 	axp->target_uid[axp->pid_count] = t_uid;
22824746ec5bSEric Paris 	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
22832a862b32SAhmed S. Darwish 	security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
2284c2a7780eSEric Paris 	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
2285e54dc243SAmy Griffis 	axp->pid_count++;
2286e54dc243SAmy Griffis 
2287e54dc243SAmy Griffis 	return 0;
2288c2f0c7c3SSteve Grubb }
22890a4ff8c2SSteve Grubb 
22900a4ff8c2SSteve Grubb /**
22913fc689e9SEric Paris  * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps
2292d84f4f99SDavid Howells  * @bprm: pointer to the bprm being processed
2293d84f4f99SDavid Howells  * @new: the proposed new credentials
2294d84f4f99SDavid Howells  * @old: the old credentials
22953fc689e9SEric Paris  *
22963fc689e9SEric Paris  * Simply check if the proc already has the caps given by the file and if not
22973fc689e9SEric Paris  * store the priv escalation info for later auditing at the end of the syscall
22983fc689e9SEric Paris  *
22993fc689e9SEric Paris  * -Eric
23003fc689e9SEric Paris  */
2301d84f4f99SDavid Howells int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
2302d84f4f99SDavid Howells 			   const struct cred *new, const struct cred *old)
23033fc689e9SEric Paris {
23043fc689e9SEric Paris 	struct audit_aux_data_bprm_fcaps *ax;
23053fc689e9SEric Paris 	struct audit_context *context = current->audit_context;
23063fc689e9SEric Paris 	struct cpu_vfs_cap_data vcaps;
23073fc689e9SEric Paris 
23083fc689e9SEric Paris 	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
23093fc689e9SEric Paris 	if (!ax)
2310d84f4f99SDavid Howells 		return -ENOMEM;
23113fc689e9SEric Paris 
23123fc689e9SEric Paris 	ax->d.type = AUDIT_BPRM_FCAPS;
23133fc689e9SEric Paris 	ax->d.next = context->aux;
23143fc689e9SEric Paris 	context->aux = (void *)ax;
23153fc689e9SEric Paris 
2316f4a4a8b1SAl Viro 	get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps);
23173fc689e9SEric Paris 
23183fc689e9SEric Paris 	ax->fcap.permitted = vcaps.permitted;
23193fc689e9SEric Paris 	ax->fcap.inheritable = vcaps.inheritable;
23203fc689e9SEric Paris 	ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
23213fc689e9SEric Paris 	ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
23223fc689e9SEric Paris 
2323d84f4f99SDavid Howells 	ax->old_pcap.permitted   = old->cap_permitted;
2324d84f4f99SDavid Howells 	ax->old_pcap.inheritable = old->cap_inheritable;
2325d84f4f99SDavid Howells 	ax->old_pcap.effective   = old->cap_effective;
23263fc689e9SEric Paris 
2327d84f4f99SDavid Howells 	ax->new_pcap.permitted   = new->cap_permitted;
2328d84f4f99SDavid Howells 	ax->new_pcap.inheritable = new->cap_inheritable;
2329d84f4f99SDavid Howells 	ax->new_pcap.effective   = new->cap_effective;
2330d84f4f99SDavid Howells 	return 0;
23313fc689e9SEric Paris }
23323fc689e9SEric Paris 
23333fc689e9SEric Paris /**
2334e68b75a0SEric Paris  * __audit_log_capset - store information about the arguments to the capset syscall
2335d84f4f99SDavid Howells  * @new: the new credentials
2336d84f4f99SDavid Howells  * @old: the old (current) credentials
2337e68b75a0SEric Paris  *
2338da3dae54SMasanari Iida  * Record the arguments userspace sent to sys_capset for later printing by the
2339e68b75a0SEric Paris  * audit system if applicable
2340e68b75a0SEric Paris  */
2341ca24a23eSEric W. Biederman void __audit_log_capset(const struct cred *new, const struct cred *old)
2342e68b75a0SEric Paris {
2343e68b75a0SEric Paris 	struct audit_context *context = current->audit_context;
2344ca24a23eSEric W. Biederman 	context->capset.pid = task_pid_nr(current);
234557f71a0aSAl Viro 	context->capset.cap.effective   = new->cap_effective;
234657f71a0aSAl Viro 	context->capset.cap.inheritable = new->cap_effective;
234757f71a0aSAl Viro 	context->capset.cap.permitted   = new->cap_permitted;
234857f71a0aSAl Viro 	context->type = AUDIT_CAPSET;
2349e68b75a0SEric Paris }
2350e68b75a0SEric Paris 
2351120a795dSAl Viro void __audit_mmap_fd(int fd, int flags)
2352120a795dSAl Viro {
2353120a795dSAl Viro 	struct audit_context *context = current->audit_context;
2354120a795dSAl Viro 	context->mmap.fd = fd;
2355120a795dSAl Viro 	context->mmap.flags = flags;
2356120a795dSAl Viro 	context->type = AUDIT_MMAP;
2357120a795dSAl Viro }
2358120a795dSAl Viro 
23597b9205bdSKees Cook static void audit_log_task(struct audit_buffer *ab)
236085e7bac3SEric Paris {
2361cca080d9SEric W. Biederman 	kuid_t auid, uid;
2362cca080d9SEric W. Biederman 	kgid_t gid;
236385e7bac3SEric Paris 	unsigned int sessionid;
23649eab339bSRichard Guy Briggs 	char comm[sizeof(current->comm)];
236585e7bac3SEric Paris 
236685e7bac3SEric Paris 	auid = audit_get_loginuid(current);
236785e7bac3SEric Paris 	sessionid = audit_get_sessionid(current);
236885e7bac3SEric Paris 	current_uid_gid(&uid, &gid);
236985e7bac3SEric Paris 
237085e7bac3SEric Paris 	audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
2371cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, auid),
2372cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, uid),
2373cca080d9SEric W. Biederman 			 from_kgid(&init_user_ns, gid),
2374cca080d9SEric W. Biederman 			 sessionid);
237585e7bac3SEric Paris 	audit_log_task_context(ab);
2376f1dc4867SRichard Guy Briggs 	audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
23779eab339bSRichard Guy Briggs 	audit_log_untrustedstring(ab, get_task_comm(comm, current));
23784766b199SDavidlohr Bueso 	audit_log_d_path_exe(ab, current->mm);
23797b9205bdSKees Cook }
23807b9205bdSKees Cook 
2381e68b75a0SEric Paris /**
23820a4ff8c2SSteve Grubb  * audit_core_dumps - record information about processes that end abnormally
23836d9525b5SHenrik Kretzschmar  * @signr: signal value
23840a4ff8c2SSteve Grubb  *
23850a4ff8c2SSteve Grubb  * If a process ends with a core dump, something fishy is going on and we
23860a4ff8c2SSteve Grubb  * should record the event for investigation.
23870a4ff8c2SSteve Grubb  */
23880a4ff8c2SSteve Grubb void audit_core_dumps(long signr)
23890a4ff8c2SSteve Grubb {
23900a4ff8c2SSteve Grubb 	struct audit_buffer *ab;
23910a4ff8c2SSteve Grubb 
23920a4ff8c2SSteve Grubb 	if (!audit_enabled)
23930a4ff8c2SSteve Grubb 		return;
23940a4ff8c2SSteve Grubb 
23950a4ff8c2SSteve Grubb 	if (signr == SIGQUIT)	/* don't care for those */
23960a4ff8c2SSteve Grubb 		return;
23970a4ff8c2SSteve Grubb 
23980a4ff8c2SSteve Grubb 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
23990644ec0cSKees Cook 	if (unlikely(!ab))
24000644ec0cSKees Cook 		return;
240161c0ee87SPaul Davies C 	audit_log_task(ab);
240261c0ee87SPaul Davies C 	audit_log_format(ab, " sig=%ld", signr);
240385e7bac3SEric Paris 	audit_log_end(ab);
240485e7bac3SEric Paris }
24050a4ff8c2SSteve Grubb 
24063dc1c1b2SKees Cook void __audit_seccomp(unsigned long syscall, long signr, int code)
240785e7bac3SEric Paris {
240885e7bac3SEric Paris 	struct audit_buffer *ab;
240985e7bac3SEric Paris 
24107b9205bdSKees Cook 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP);
24117b9205bdSKees Cook 	if (unlikely(!ab))
24127b9205bdSKees Cook 		return;
24137b9205bdSKees Cook 	audit_log_task(ab);
241484db564aSRichard Guy Briggs 	audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
241584db564aSRichard Guy Briggs 			 signr, syscall_get_arch(), syscall, is_compat_task(),
241684db564aSRichard Guy Briggs 			 KSTK_EIP(current), code);
24170a4ff8c2SSteve Grubb 	audit_log_end(ab);
24180a4ff8c2SSteve Grubb }
2419916d7576SAl Viro 
2420916d7576SAl Viro struct list_head *audit_killed_trees(void)
2421916d7576SAl Viro {
2422916d7576SAl Viro 	struct audit_context *ctx = current->audit_context;
2423916d7576SAl Viro 	if (likely(!ctx || !ctx->in_syscall))
2424916d7576SAl Viro 		return NULL;
2425916d7576SAl Viro 	return &ctx->killed_trees;
2426916d7576SAl Viro }
2427