xref: /openbmc/linux/kernel/auditsc.c (revision ea1cc20cd4ce55dd920a87a317c43da03ccea192)
1d680c6b4SCai Huoqing // SPDX-License-Identifier: GPL-2.0-or-later
285c8721fS /* auditsc.c -- System-call auditing support
31da177e4SLinus Torvalds  * Handles all system-call specific auditing features.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
673241cccSAmy Griffis  * Copyright 2005 Hewlett-Packard Development Company, L.P.
720ca73bcSGeorge C. Wilson  * Copyright (C) 2005, 2006 IBM Corporation
81da177e4SLinus Torvalds  * All Rights Reserved.
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * Written by Rickard E. (Rik) Faith <faith@redhat.com>
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  * Many of the ideas implemented here are from Stephen C. Tweedie,
131da177e4SLinus Torvalds  * especially the idea of avoiding a copy by using getname.
141da177e4SLinus Torvalds  *
151da177e4SLinus Torvalds  * The method for actual interception of syscall entry and exit (not in
161da177e4SLinus Torvalds  * this file -- see entry.S) is based on a GPL'd patch written by
171da177e4SLinus Torvalds  * okir@suse.de and Copyright 2003 SuSE Linux AG.
181da177e4SLinus Torvalds  *
1920ca73bcSGeorge C. Wilson  * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
2020ca73bcSGeorge C. Wilson  * 2006.
2120ca73bcSGeorge C. Wilson  *
22b63862f4SDustin Kirkland  * The support of additional filter rules compares (>, <, >=, <=) was
23b63862f4SDustin Kirkland  * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
24b63862f4SDustin Kirkland  *
2573241cccSAmy Griffis  * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
2673241cccSAmy Griffis  * filesystem information.
278c8570fbSDustin Kirkland  *
288c8570fbSDustin Kirkland  * Subject and object context labeling support added by <danjones@us.ibm.com>
298c8570fbSDustin Kirkland  * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
301da177e4SLinus Torvalds  */
311da177e4SLinus Torvalds 
32f952d10fSRichard Guy Briggs #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33f952d10fSRichard Guy Briggs 
341da177e4SLinus Torvalds #include <linux/init.h>
351da177e4SLinus Torvalds #include <asm/types.h>
3660063497SArun Sharma #include <linux/atomic.h>
3773241cccSAmy Griffis #include <linux/fs.h>
3873241cccSAmy Griffis #include <linux/namei.h>
391da177e4SLinus Torvalds #include <linux/mm.h>
409984de1aSPaul Gortmaker #include <linux/export.h>
415a0e3ad6STejun Heo #include <linux/slab.h>
4201116105SStephen Smalley #include <linux/mount.h>
433ec3b2fbSDavid Woodhouse #include <linux/socket.h>
4420ca73bcSGeorge C. Wilson #include <linux/mqueue.h>
451da177e4SLinus Torvalds #include <linux/audit.h>
461da177e4SLinus Torvalds #include <linux/personality.h>
471da177e4SLinus Torvalds #include <linux/time.h>
485bb289b5SDavid Woodhouse #include <linux/netlink.h>
49f5561964SDavid Woodhouse #include <linux/compiler.h>
501da177e4SLinus Torvalds #include <asm/unistd.h>
518c8570fbSDustin Kirkland #include <linux/security.h>
52fe7752baSDavid Woodhouse #include <linux/list.h>
53473ae30bSAl Viro #include <linux/binfmts.h>
54a1f8e7f7SAl Viro #include <linux/highmem.h>
55f46038ffSAl Viro #include <linux/syscalls.h>
5684db564aSRichard Guy Briggs #include <asm/syscall.h>
57851f7ff5SEric Paris #include <linux/capability.h>
585ad4e53bSAl Viro #include <linux/fs_struct.h>
593dc1c1b2SKees Cook #include <linux/compat.h>
603f1c8250SWilliam Roberts #include <linux/ctype.h>
61fcf22d82SPaul Moore #include <linux/string.h>
6243761473SPaul Moore #include <linux/uaccess.h>
639dd813c1SJan Kara #include <linux/fsnotify_backend.h>
64fcf22d82SPaul Moore #include <uapi/linux/limits.h>
658e6cf365SRichard Guy Briggs #include <uapi/linux/netfilter/nf_tables.h>
66571e5c0eSRichard Guy Briggs #include <uapi/linux/openat2.h> // struct open_how
67032bffd4SRichard Guy Briggs #include <uapi/linux/fanotify.h>
681da177e4SLinus Torvalds 
69fe7752baSDavid Woodhouse #include "audit.h"
70fe7752baSDavid Woodhouse 
71d7e7528bSEric Paris /* flags stating the success for a syscall */
72d7e7528bSEric Paris #define AUDITSC_INVALID 0
73d7e7528bSEric Paris #define AUDITSC_SUCCESS 1
74d7e7528bSEric Paris #define AUDITSC_FAILURE 2
75d7e7528bSEric Paris 
7643761473SPaul Moore /* no execve audit message should be longer than this (userspace limits),
7743761473SPaul Moore  * see the note near the top of audit_log_execve_info() about this value */
78de6bbd1dSEric Paris #define MAX_EXECVE_AUDIT_LEN 7500
79de6bbd1dSEric Paris 
803f1c8250SWilliam Roberts /* max length to print of cmdline/proctitle value during audit */
813f1c8250SWilliam Roberts #define MAX_PROCTITLE_AUDIT_LEN 128
823f1c8250SWilliam Roberts 
83471a5c7cSAl Viro /* number of audit rules */
84471a5c7cSAl Viro int audit_n_rules;
85471a5c7cSAl Viro 
86e54dc243SAmy Griffis /* determines whether we collect data for signals sent */
87e54dc243SAmy Griffis int audit_signals;
88e54dc243SAmy Griffis 
891da177e4SLinus Torvalds struct audit_aux_data {
901da177e4SLinus Torvalds 	struct audit_aux_data	*next;
911da177e4SLinus Torvalds 	int			type;
921da177e4SLinus Torvalds };
931da177e4SLinus Torvalds 
94e54dc243SAmy Griffis /* Number of target pids per aux struct. */
95e54dc243SAmy Griffis #define AUDIT_AUX_PIDS	16
96e54dc243SAmy Griffis 
97e54dc243SAmy Griffis struct audit_aux_data_pids {
98e54dc243SAmy Griffis 	struct audit_aux_data	d;
99e54dc243SAmy Griffis 	pid_t			target_pid[AUDIT_AUX_PIDS];
100e1760bd5SEric W. Biederman 	kuid_t			target_auid[AUDIT_AUX_PIDS];
101cca080d9SEric W. Biederman 	kuid_t			target_uid[AUDIT_AUX_PIDS];
1024746ec5bSEric Paris 	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
103e54dc243SAmy Griffis 	u32			target_sid[AUDIT_AUX_PIDS];
104c2a7780eSEric Paris 	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
105e54dc243SAmy Griffis 	int			pid_count;
106e54dc243SAmy Griffis };
107e54dc243SAmy Griffis 
1083fc689e9SEric Paris struct audit_aux_data_bprm_fcaps {
1093fc689e9SEric Paris 	struct audit_aux_data	d;
1103fc689e9SEric Paris 	struct audit_cap_data	fcap;
1113fc689e9SEric Paris 	unsigned int		fcap_ver;
1123fc689e9SEric Paris 	struct audit_cap_data	old_pcap;
1133fc689e9SEric Paris 	struct audit_cap_data	new_pcap;
1143fc689e9SEric Paris };
1153fc689e9SEric Paris 
11674c3cbe3SAl Viro struct audit_tree_refs {
11774c3cbe3SAl Viro 	struct audit_tree_refs *next;
11874c3cbe3SAl Viro 	struct audit_chunk *c[31];
11974c3cbe3SAl Viro };
12074c3cbe3SAl Viro 
121c4dad0aaSRichard Guy Briggs struct audit_nfcfgop_tab {
122c4dad0aaSRichard Guy Briggs 	enum audit_nfcfgop	op;
123c4dad0aaSRichard Guy Briggs 	const char		*s;
124c4dad0aaSRichard Guy Briggs };
125c4dad0aaSRichard Guy Briggs 
126db9ff6ecSZheng Bin static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
1278e6cf365SRichard Guy Briggs 	{ AUDIT_XT_OP_REGISTER,			"xt_register"		   },
1288e6cf365SRichard Guy Briggs 	{ AUDIT_XT_OP_REPLACE,			"xt_replace"		   },
1298e6cf365SRichard Guy Briggs 	{ AUDIT_XT_OP_UNREGISTER,		"xt_unregister"		   },
1308e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_TABLE_REGISTER,		"nft_register_table"	   },
1318e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_TABLE_UNREGISTER,	"nft_unregister_table"	   },
1328e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_CHAIN_REGISTER,		"nft_register_chain"	   },
1338e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_CHAIN_UNREGISTER,	"nft_unregister_chain"	   },
1348e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_RULE_REGISTER,		"nft_register_rule"	   },
1358e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_RULE_UNREGISTER,		"nft_unregister_rule"	   },
1368e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_SET_REGISTER,		"nft_register_set"	   },
1378e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_SET_UNREGISTER,		"nft_unregister_set"	   },
1388e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_SETELEM_REGISTER,	"nft_register_setelem"	   },
1398e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_SETELEM_UNREGISTER,	"nft_unregister_setelem"   },
1408e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_GEN_REGISTER,		"nft_register_gen"	   },
1418e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_OBJ_REGISTER,		"nft_register_obj"	   },
1428e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_OBJ_UNREGISTER,		"nft_unregister_obj"	   },
1438e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_OBJ_RESET,		"nft_reset_obj"		   },
1448e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_FLOWTABLE_REGISTER,	"nft_register_flowtable"   },
1458e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,	"nft_unregister_flowtable" },
1467e9be112SPhil Sutter 	{ AUDIT_NFT_OP_SETELEM_RESET,		"nft_reset_setelem"        },
147ea078ae9SPhil Sutter 	{ AUDIT_NFT_OP_RULE_RESET,		"nft_reset_rule"           },
1488e6cf365SRichard Guy Briggs 	{ AUDIT_NFT_OP_INVALID,			"nft_invalid"		   },
149c4dad0aaSRichard Guy Briggs };
150c4dad0aaSRichard Guy Briggs 
audit_match_perm(struct audit_context * ctx,int mask)15155669bfaSAl Viro static int audit_match_perm(struct audit_context *ctx, int mask)
15255669bfaSAl Viro {
153c4bacefbSCordelia 	unsigned n;
154254c8b96SRoni Nevalainen 
1551a61c88dSzhangxiliang 	if (unlikely(!ctx))
1561a61c88dSzhangxiliang 		return 0;
157c4bacefbSCordelia 	n = ctx->major;
158dbda4c0bSAlan Cox 
15955669bfaSAl Viro 	switch (audit_classify_syscall(ctx->arch, n)) {
16042f355efSRichard Guy Briggs 	case AUDITSC_NATIVE:
16155669bfaSAl Viro 		if ((mask & AUDIT_PERM_WRITE) &&
16255669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_WRITE, n))
16355669bfaSAl Viro 			return 1;
16455669bfaSAl Viro 		if ((mask & AUDIT_PERM_READ) &&
16555669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_READ, n))
16655669bfaSAl Viro 			return 1;
16755669bfaSAl Viro 		if ((mask & AUDIT_PERM_ATTR) &&
16855669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_CHATTR, n))
16955669bfaSAl Viro 			return 1;
17055669bfaSAl Viro 		return 0;
17142f355efSRichard Guy Briggs 	case AUDITSC_COMPAT: /* 32bit on biarch */
17255669bfaSAl Viro 		if ((mask & AUDIT_PERM_WRITE) &&
17355669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_WRITE_32, n))
17455669bfaSAl Viro 			return 1;
17555669bfaSAl Viro 		if ((mask & AUDIT_PERM_READ) &&
17655669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_READ_32, n))
17755669bfaSAl Viro 			return 1;
17855669bfaSAl Viro 		if ((mask & AUDIT_PERM_ATTR) &&
17955669bfaSAl Viro 		     audit_match_class(AUDIT_CLASS_CHATTR_32, n))
18055669bfaSAl Viro 			return 1;
18155669bfaSAl Viro 		return 0;
18242f355efSRichard Guy Briggs 	case AUDITSC_OPEN:
18355669bfaSAl Viro 		return mask & ACC_MODE(ctx->argv[1]);
18442f355efSRichard Guy Briggs 	case AUDITSC_OPENAT:
18555669bfaSAl Viro 		return mask & ACC_MODE(ctx->argv[2]);
18642f355efSRichard Guy Briggs 	case AUDITSC_SOCKETCALL:
18755669bfaSAl Viro 		return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
18842f355efSRichard Guy Briggs 	case AUDITSC_EXECVE:
18955669bfaSAl Viro 		return mask & AUDIT_PERM_EXEC;
1901c30e3afSRichard Guy Briggs 	case AUDITSC_OPENAT2:
1917a82f89dSPaul Moore 		return mask & ACC_MODE((u32)ctx->openat2.flags);
19255669bfaSAl Viro 	default:
19355669bfaSAl Viro 		return 0;
19455669bfaSAl Viro 	}
19555669bfaSAl Viro }
19655669bfaSAl Viro 
audit_match_filetype(struct audit_context * ctx,int val)1975ef30ee5SEric Paris static int audit_match_filetype(struct audit_context *ctx, int val)
1988b67dca9SAl Viro {
1995195d8e2SEric Paris 	struct audit_names *n;
2005ef30ee5SEric Paris 	umode_t mode = (umode_t)val;
2011a61c88dSzhangxiliang 
2021a61c88dSzhangxiliang 	if (unlikely(!ctx))
2031a61c88dSzhangxiliang 		return 0;
2041a61c88dSzhangxiliang 
2055195d8e2SEric Paris 	list_for_each_entry(n, &ctx->names_list, list) {
20684cb777eSRichard Guy Briggs 		if ((n->ino != AUDIT_INO_UNSET) &&
2075195d8e2SEric Paris 		    ((n->mode & S_IFMT) == mode))
2088b67dca9SAl Viro 			return 1;
2098b67dca9SAl Viro 	}
2105195d8e2SEric Paris 
2115ef30ee5SEric Paris 	return 0;
2125ef30ee5SEric Paris }
2138b67dca9SAl Viro 
21474c3cbe3SAl Viro /*
21574c3cbe3SAl Viro  * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
21674c3cbe3SAl Viro  * ->first_trees points to its beginning, ->trees - to the current end of data.
21774c3cbe3SAl Viro  * ->tree_count is the number of free entries in array pointed to by ->trees.
21874c3cbe3SAl Viro  * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL,
21974c3cbe3SAl Viro  * "empty" becomes (p, p, 31) afterwards.  We don't shrink the list (and seriously,
22074c3cbe3SAl Viro  * it's going to remain 1-element for almost any setup) until we free context itself.
22174c3cbe3SAl Viro  * References in it _are_ dropped - at the same time we free/drop aux stuff.
22274c3cbe3SAl Viro  */
22374c3cbe3SAl Viro 
audit_set_auditable(struct audit_context * ctx)224679173b7SEric Paris static void audit_set_auditable(struct audit_context *ctx)
225679173b7SEric Paris {
226679173b7SEric Paris 	if (!ctx->prio) {
227679173b7SEric Paris 		ctx->prio = 1;
228619ed58aSSergey Nazarov 		ctx->current_state = AUDIT_STATE_RECORD;
229679173b7SEric Paris 	}
230679173b7SEric Paris }
231679173b7SEric Paris 
put_tree_ref(struct audit_context * ctx,struct audit_chunk * chunk)23274c3cbe3SAl Viro static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
23374c3cbe3SAl Viro {
23474c3cbe3SAl Viro 	struct audit_tree_refs *p = ctx->trees;
23574c3cbe3SAl Viro 	int left = ctx->tree_count;
236254c8b96SRoni Nevalainen 
23774c3cbe3SAl Viro 	if (likely(left)) {
23874c3cbe3SAl Viro 		p->c[--left] = chunk;
23974c3cbe3SAl Viro 		ctx->tree_count = left;
24074c3cbe3SAl Viro 		return 1;
24174c3cbe3SAl Viro 	}
24274c3cbe3SAl Viro 	if (!p)
24374c3cbe3SAl Viro 		return 0;
24474c3cbe3SAl Viro 	p = p->next;
24574c3cbe3SAl Viro 	if (p) {
24674c3cbe3SAl Viro 		p->c[30] = chunk;
24774c3cbe3SAl Viro 		ctx->trees = p;
24874c3cbe3SAl Viro 		ctx->tree_count = 30;
24974c3cbe3SAl Viro 		return 1;
25074c3cbe3SAl Viro 	}
25174c3cbe3SAl Viro 	return 0;
25274c3cbe3SAl Viro }
25374c3cbe3SAl Viro 
grow_tree_refs(struct audit_context * ctx)25474c3cbe3SAl Viro static int grow_tree_refs(struct audit_context *ctx)
25574c3cbe3SAl Viro {
25674c3cbe3SAl Viro 	struct audit_tree_refs *p = ctx->trees;
257254c8b96SRoni Nevalainen 
25874c3cbe3SAl Viro 	ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
25974c3cbe3SAl Viro 	if (!ctx->trees) {
26074c3cbe3SAl Viro 		ctx->trees = p;
26174c3cbe3SAl Viro 		return 0;
26274c3cbe3SAl Viro 	}
26374c3cbe3SAl Viro 	if (p)
26474c3cbe3SAl Viro 		p->next = ctx->trees;
26574c3cbe3SAl Viro 	else
26674c3cbe3SAl Viro 		ctx->first_trees = ctx->trees;
26774c3cbe3SAl Viro 	ctx->tree_count = 31;
26874c3cbe3SAl Viro 	return 1;
26974c3cbe3SAl Viro }
27074c3cbe3SAl Viro 
unroll_tree_refs(struct audit_context * ctx,struct audit_tree_refs * p,int count)27174c3cbe3SAl Viro static void unroll_tree_refs(struct audit_context *ctx,
27274c3cbe3SAl Viro 		      struct audit_tree_refs *p, int count)
27374c3cbe3SAl Viro {
27474c3cbe3SAl Viro 	struct audit_tree_refs *q;
27574c3cbe3SAl Viro 	int n;
276254c8b96SRoni Nevalainen 
27774c3cbe3SAl Viro 	if (!p) {
27874c3cbe3SAl Viro 		/* we started with empty chain */
27974c3cbe3SAl Viro 		p = ctx->first_trees;
28074c3cbe3SAl Viro 		count = 31;
28174c3cbe3SAl Viro 		/* if the very first allocation has failed, nothing to do */
28274c3cbe3SAl Viro 		if (!p)
28374c3cbe3SAl Viro 			return;
28474c3cbe3SAl Viro 	}
28574c3cbe3SAl Viro 	n = count;
28674c3cbe3SAl Viro 	for (q = p; q != ctx->trees; q = q->next, n = 31) {
28774c3cbe3SAl Viro 		while (n--) {
28874c3cbe3SAl Viro 			audit_put_chunk(q->c[n]);
28974c3cbe3SAl Viro 			q->c[n] = NULL;
29074c3cbe3SAl Viro 		}
29174c3cbe3SAl Viro 	}
29274c3cbe3SAl Viro 	while (n-- > ctx->tree_count) {
29374c3cbe3SAl Viro 		audit_put_chunk(q->c[n]);
29474c3cbe3SAl Viro 		q->c[n] = NULL;
29574c3cbe3SAl Viro 	}
29674c3cbe3SAl Viro 	ctx->trees = p;
29774c3cbe3SAl Viro 	ctx->tree_count = count;
29874c3cbe3SAl Viro }
29974c3cbe3SAl Viro 
free_tree_refs(struct audit_context * ctx)30074c3cbe3SAl Viro static void free_tree_refs(struct audit_context *ctx)
30174c3cbe3SAl Viro {
30274c3cbe3SAl Viro 	struct audit_tree_refs *p, *q;
303254c8b96SRoni Nevalainen 
30474c3cbe3SAl Viro 	for (p = ctx->first_trees; p; p = q) {
30574c3cbe3SAl Viro 		q = p->next;
30674c3cbe3SAl Viro 		kfree(p);
30774c3cbe3SAl Viro 	}
30874c3cbe3SAl Viro }
30974c3cbe3SAl Viro 
match_tree_refs(struct audit_context * ctx,struct audit_tree * tree)31074c3cbe3SAl Viro static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
31174c3cbe3SAl Viro {
31274c3cbe3SAl Viro 	struct audit_tree_refs *p;
31374c3cbe3SAl Viro 	int n;
314254c8b96SRoni Nevalainen 
31574c3cbe3SAl Viro 	if (!tree)
31674c3cbe3SAl Viro 		return 0;
31774c3cbe3SAl Viro 	/* full ones */
31874c3cbe3SAl Viro 	for (p = ctx->first_trees; p != ctx->trees; p = p->next) {
31974c3cbe3SAl Viro 		for (n = 0; n < 31; n++)
32074c3cbe3SAl Viro 			if (audit_tree_match(p->c[n], tree))
32174c3cbe3SAl Viro 				return 1;
32274c3cbe3SAl Viro 	}
32374c3cbe3SAl Viro 	/* partial */
32474c3cbe3SAl Viro 	if (p) {
32574c3cbe3SAl Viro 		for (n = ctx->tree_count; n < 31; n++)
32674c3cbe3SAl Viro 			if (audit_tree_match(p->c[n], tree))
32774c3cbe3SAl Viro 				return 1;
32874c3cbe3SAl Viro 	}
32974c3cbe3SAl Viro 	return 0;
33074c3cbe3SAl Viro }
33174c3cbe3SAl Viro 
audit_compare_uid(kuid_t uid,struct audit_names * name,struct audit_field * f,struct audit_context * ctx)332ca57ec0fSEric W. Biederman static int audit_compare_uid(kuid_t uid,
333b34b0393SEric Paris 			     struct audit_names *name,
334b34b0393SEric Paris 			     struct audit_field *f,
335b34b0393SEric Paris 			     struct audit_context *ctx)
336b34b0393SEric Paris {
337b34b0393SEric Paris 	struct audit_names *n;
338b34b0393SEric Paris 	int rc;
339b34b0393SEric Paris 
340b34b0393SEric Paris 	if (name) {
341ca57ec0fSEric W. Biederman 		rc = audit_uid_comparator(uid, f->op, name->uid);
342b34b0393SEric Paris 		if (rc)
343b34b0393SEric Paris 			return rc;
344b34b0393SEric Paris 	}
345b34b0393SEric Paris 
346b34b0393SEric Paris 	if (ctx) {
347b34b0393SEric Paris 		list_for_each_entry(n, &ctx->names_list, list) {
348ca57ec0fSEric W. Biederman 			rc = audit_uid_comparator(uid, f->op, n->uid);
349ca57ec0fSEric W. Biederman 			if (rc)
350ca57ec0fSEric W. Biederman 				return rc;
351ca57ec0fSEric W. Biederman 		}
352ca57ec0fSEric W. Biederman 	}
353ca57ec0fSEric W. Biederman 	return 0;
354ca57ec0fSEric W. Biederman }
355b34b0393SEric Paris 
audit_compare_gid(kgid_t gid,struct audit_names * name,struct audit_field * f,struct audit_context * ctx)356ca57ec0fSEric W. Biederman static int audit_compare_gid(kgid_t gid,
357ca57ec0fSEric W. Biederman 			     struct audit_names *name,
358ca57ec0fSEric W. Biederman 			     struct audit_field *f,
359ca57ec0fSEric W. Biederman 			     struct audit_context *ctx)
360ca57ec0fSEric W. Biederman {
361ca57ec0fSEric W. Biederman 	struct audit_names *n;
362ca57ec0fSEric W. Biederman 	int rc;
363b34b0393SEric Paris 
364ca57ec0fSEric W. Biederman 	if (name) {
365ca57ec0fSEric W. Biederman 		rc = audit_gid_comparator(gid, f->op, name->gid);
366ca57ec0fSEric W. Biederman 		if (rc)
367ca57ec0fSEric W. Biederman 			return rc;
368ca57ec0fSEric W. Biederman 	}
369ca57ec0fSEric W. Biederman 
370ca57ec0fSEric W. Biederman 	if (ctx) {
371ca57ec0fSEric W. Biederman 		list_for_each_entry(n, &ctx->names_list, list) {
372ca57ec0fSEric W. Biederman 			rc = audit_gid_comparator(gid, f->op, n->gid);
373b34b0393SEric Paris 			if (rc)
374b34b0393SEric Paris 				return rc;
375b34b0393SEric Paris 		}
376b34b0393SEric Paris 	}
377b34b0393SEric Paris 	return 0;
378b34b0393SEric Paris }
379b34b0393SEric Paris 
audit_field_compare(struct task_struct * tsk,const struct cred * cred,struct audit_field * f,struct audit_context * ctx,struct audit_names * name)38002d86a56SEric Paris static int audit_field_compare(struct task_struct *tsk,
38102d86a56SEric Paris 			       const struct cred *cred,
38202d86a56SEric Paris 			       struct audit_field *f,
38302d86a56SEric Paris 			       struct audit_context *ctx,
38402d86a56SEric Paris 			       struct audit_names *name)
38502d86a56SEric Paris {
38602d86a56SEric Paris 	switch (f->val) {
3874a6633edSPeter Moody 	/* process to file object comparisons */
38802d86a56SEric Paris 	case AUDIT_COMPARE_UID_TO_OBJ_UID:
389ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->uid, name, f, ctx);
390c9fe685fSEric Paris 	case AUDIT_COMPARE_GID_TO_OBJ_GID:
391ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->gid, name, f, ctx);
3924a6633edSPeter Moody 	case AUDIT_COMPARE_EUID_TO_OBJ_UID:
393ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->euid, name, f, ctx);
3944a6633edSPeter Moody 	case AUDIT_COMPARE_EGID_TO_OBJ_GID:
395ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->egid, name, f, ctx);
3964a6633edSPeter Moody 	case AUDIT_COMPARE_AUID_TO_OBJ_UID:
39738f80590SRichard Guy Briggs 		return audit_compare_uid(audit_get_loginuid(tsk), name, f, ctx);
3984a6633edSPeter Moody 	case AUDIT_COMPARE_SUID_TO_OBJ_UID:
399ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->suid, name, f, ctx);
4004a6633edSPeter Moody 	case AUDIT_COMPARE_SGID_TO_OBJ_GID:
401ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->sgid, name, f, ctx);
4024a6633edSPeter Moody 	case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
403ca57ec0fSEric W. Biederman 		return audit_compare_uid(cred->fsuid, name, f, ctx);
4044a6633edSPeter Moody 	case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
405ca57ec0fSEric W. Biederman 		return audit_compare_gid(cred->fsgid, name, f, ctx);
40610d68360SPeter Moody 	/* uid comparisons */
40710d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_AUID:
40838f80590SRichard Guy Briggs 		return audit_uid_comparator(cred->uid, f->op,
40938f80590SRichard Guy Briggs 					    audit_get_loginuid(tsk));
41010d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_EUID:
411ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->uid, f->op, cred->euid);
41210d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_SUID:
413ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->uid, f->op, cred->suid);
41410d68360SPeter Moody 	case AUDIT_COMPARE_UID_TO_FSUID:
415ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->uid, f->op, cred->fsuid);
41610d68360SPeter Moody 	/* auid comparisons */
41710d68360SPeter Moody 	case AUDIT_COMPARE_AUID_TO_EUID:
41838f80590SRichard Guy Briggs 		return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
41938f80590SRichard Guy Briggs 					    cred->euid);
42010d68360SPeter Moody 	case AUDIT_COMPARE_AUID_TO_SUID:
42138f80590SRichard Guy Briggs 		return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
42238f80590SRichard Guy Briggs 					    cred->suid);
42310d68360SPeter Moody 	case AUDIT_COMPARE_AUID_TO_FSUID:
42438f80590SRichard Guy Briggs 		return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
42538f80590SRichard Guy Briggs 					    cred->fsuid);
42610d68360SPeter Moody 	/* euid comparisons */
42710d68360SPeter Moody 	case AUDIT_COMPARE_EUID_TO_SUID:
428ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->euid, f->op, cred->suid);
42910d68360SPeter Moody 	case AUDIT_COMPARE_EUID_TO_FSUID:
430ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->euid, f->op, cred->fsuid);
43110d68360SPeter Moody 	/* suid comparisons */
43210d68360SPeter Moody 	case AUDIT_COMPARE_SUID_TO_FSUID:
433ca57ec0fSEric W. Biederman 		return audit_uid_comparator(cred->suid, f->op, cred->fsuid);
43410d68360SPeter Moody 	/* gid comparisons */
43510d68360SPeter Moody 	case AUDIT_COMPARE_GID_TO_EGID:
436ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->gid, f->op, cred->egid);
43710d68360SPeter Moody 	case AUDIT_COMPARE_GID_TO_SGID:
438ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->gid, f->op, cred->sgid);
43910d68360SPeter Moody 	case AUDIT_COMPARE_GID_TO_FSGID:
440ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->gid, f->op, cred->fsgid);
44110d68360SPeter Moody 	/* egid comparisons */
44210d68360SPeter Moody 	case AUDIT_COMPARE_EGID_TO_SGID:
443ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->egid, f->op, cred->sgid);
44410d68360SPeter Moody 	case AUDIT_COMPARE_EGID_TO_FSGID:
445ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->egid, f->op, cred->fsgid);
44610d68360SPeter Moody 	/* sgid comparison */
44710d68360SPeter Moody 	case AUDIT_COMPARE_SGID_TO_FSGID:
448ca57ec0fSEric W. Biederman 		return audit_gid_comparator(cred->sgid, f->op, cred->fsgid);
44902d86a56SEric Paris 	default:
45002d86a56SEric Paris 		WARN(1, "Missing AUDIT_COMPARE define.  Report as a bug\n");
45102d86a56SEric Paris 		return 0;
45202d86a56SEric Paris 	}
45302d86a56SEric Paris 	return 0;
45402d86a56SEric Paris }
45502d86a56SEric Paris 
456f368c07dSAmy Griffis /* Determine if any context name data matches a rule's watch data */
4571da177e4SLinus Torvalds /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
458f5629883STony Jones  * otherwise.
459f5629883STony Jones  *
460f5629883STony Jones  * If task_creation is true, this is an explicit indication that we are
461f5629883STony Jones  * filtering a task rule at task creation time.  This and tsk == current are
462f5629883STony Jones  * the only situations where tsk->cred may be accessed without an rcu read lock.
463f5629883STony Jones  */
audit_filter_rules(struct task_struct * tsk,struct audit_krule * rule,struct audit_context * ctx,struct audit_names * name,enum audit_state * state,bool task_creation)4641da177e4SLinus Torvalds static int audit_filter_rules(struct task_struct *tsk,
46593315ed6SAmy Griffis 			      struct audit_krule *rule,
4661da177e4SLinus Torvalds 			      struct audit_context *ctx,
467f368c07dSAmy Griffis 			      struct audit_names *name,
468f5629883STony Jones 			      enum audit_state *state,
469f5629883STony Jones 			      bool task_creation)
4701da177e4SLinus Torvalds {
471f5629883STony Jones 	const struct cred *cred;
4725195d8e2SEric Paris 	int i, need_sid = 1;
4733dc7e315SDarrel Goeddel 	u32 sid;
4748fae4770SRichard Guy Briggs 	unsigned int sessionid;
4753dc7e315SDarrel Goeddel 
476d9516f34SGaosheng Cui 	if (ctx && rule->prio <= ctx->prio)
477d9516f34SGaosheng Cui 		return 0;
478d9516f34SGaosheng Cui 
479f5629883STony Jones 	cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);
480f5629883STony Jones 
4811da177e4SLinus Torvalds 	for (i = 0; i < rule->field_count; i++) {
48293315ed6SAmy Griffis 		struct audit_field *f = &rule->fields[i];
4835195d8e2SEric Paris 		struct audit_names *n;
4841da177e4SLinus Torvalds 		int result = 0;
485f1dc4867SRichard Guy Briggs 		pid_t pid;
4861da177e4SLinus Torvalds 
48793315ed6SAmy Griffis 		switch (f->type) {
4881da177e4SLinus Torvalds 		case AUDIT_PID:
489fa2bea2fSPaul Moore 			pid = task_tgid_nr(tsk);
490f1dc4867SRichard Guy Briggs 			result = audit_comparator(pid, f->op, f->val);
4911da177e4SLinus Torvalds 			break;
4923c66251eSAl Viro 		case AUDIT_PPID:
493419c58f1SAlexander Viro 			if (ctx) {
494419c58f1SAlexander Viro 				if (!ctx->ppid)
495c92cdeb4SRichard Guy Briggs 					ctx->ppid = task_ppid_nr(tsk);
4963c66251eSAl Viro 				result = audit_comparator(ctx->ppid, f->op, f->val);
497419c58f1SAlexander Viro 			}
4983c66251eSAl Viro 			break;
49934d99af5SRichard Guy Briggs 		case AUDIT_EXE:
50034d99af5SRichard Guy Briggs 			result = audit_exe_compare(tsk, rule->exe);
50123bcc480SOndrej Mosnáček 			if (f->op == Audit_not_equal)
50223bcc480SOndrej Mosnáček 				result = !result;
50334d99af5SRichard Guy Briggs 			break;
5041da177e4SLinus Torvalds 		case AUDIT_UID:
505ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->uid, f->op, f->uid);
5061da177e4SLinus Torvalds 			break;
5071da177e4SLinus Torvalds 		case AUDIT_EUID:
508ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->euid, f->op, f->uid);
5091da177e4SLinus Torvalds 			break;
5101da177e4SLinus Torvalds 		case AUDIT_SUID:
511ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->suid, f->op, f->uid);
5121da177e4SLinus Torvalds 			break;
5131da177e4SLinus Torvalds 		case AUDIT_FSUID:
514ca57ec0fSEric W. Biederman 			result = audit_uid_comparator(cred->fsuid, f->op, f->uid);
5151da177e4SLinus Torvalds 			break;
5161da177e4SLinus Torvalds 		case AUDIT_GID:
517ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->gid, f->op, f->gid);
51837eebe39SMatvejchikov Ilya 			if (f->op == Audit_equal) {
51937eebe39SMatvejchikov Ilya 				if (!result)
520af85d177SOndrej Mosnáček 					result = groups_search(cred->group_info, f->gid);
52137eebe39SMatvejchikov Ilya 			} else if (f->op == Audit_not_equal) {
52237eebe39SMatvejchikov Ilya 				if (result)
523af85d177SOndrej Mosnáček 					result = !groups_search(cred->group_info, f->gid);
52437eebe39SMatvejchikov Ilya 			}
5251da177e4SLinus Torvalds 			break;
5261da177e4SLinus Torvalds 		case AUDIT_EGID:
527ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->egid, f->op, f->gid);
52837eebe39SMatvejchikov Ilya 			if (f->op == Audit_equal) {
52937eebe39SMatvejchikov Ilya 				if (!result)
530af85d177SOndrej Mosnáček 					result = groups_search(cred->group_info, f->gid);
53137eebe39SMatvejchikov Ilya 			} else if (f->op == Audit_not_equal) {
53237eebe39SMatvejchikov Ilya 				if (result)
533af85d177SOndrej Mosnáček 					result = !groups_search(cred->group_info, f->gid);
53437eebe39SMatvejchikov Ilya 			}
5351da177e4SLinus Torvalds 			break;
5361da177e4SLinus Torvalds 		case AUDIT_SGID:
537ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->sgid, f->op, f->gid);
5381da177e4SLinus Torvalds 			break;
5391da177e4SLinus Torvalds 		case AUDIT_FSGID:
540ca57ec0fSEric W. Biederman 			result = audit_gid_comparator(cred->fsgid, f->op, f->gid);
5411da177e4SLinus Torvalds 			break;
5428fae4770SRichard Guy Briggs 		case AUDIT_SESSIONID:
5435b713886SOndrej Mosnáček 			sessionid = audit_get_sessionid(tsk);
5448fae4770SRichard Guy Briggs 			result = audit_comparator(sessionid, f->op, f->val);
5458fae4770SRichard Guy Briggs 			break;
5461da177e4SLinus Torvalds 		case AUDIT_PERS:
54793315ed6SAmy Griffis 			result = audit_comparator(tsk->personality, f->op, f->val);
5481da177e4SLinus Torvalds 			break;
5492fd6f58bS 		case AUDIT_ARCH:
5502fd6f58bS 			if (ctx)
55193315ed6SAmy Griffis 				result = audit_comparator(ctx->arch, f->op, f->val);
5522fd6f58bS 			break;
5531da177e4SLinus Torvalds 
5541da177e4SLinus Torvalds 		case AUDIT_EXIT:
555ba59eae7SAlex Shi 			if (ctx && ctx->return_valid != AUDITSC_INVALID)
55693315ed6SAmy Griffis 				result = audit_comparator(ctx->return_code, f->op, f->val);
5571da177e4SLinus Torvalds 			break;
5581da177e4SLinus Torvalds 		case AUDIT_SUCCESS:
559ba59eae7SAlex Shi 			if (ctx && ctx->return_valid != AUDITSC_INVALID) {
56093315ed6SAmy Griffis 				if (f->val)
56193315ed6SAmy Griffis 					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
562b01f2cc1SDavid Woodhouse 				else
56393315ed6SAmy Griffis 					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
564b01f2cc1SDavid Woodhouse 			}
5651da177e4SLinus Torvalds 			break;
5661da177e4SLinus Torvalds 		case AUDIT_DEVMAJOR:
56716c174bdSEric Paris 			if (name) {
56816c174bdSEric Paris 				if (audit_comparator(MAJOR(name->dev), f->op, f->val) ||
56916c174bdSEric Paris 				    audit_comparator(MAJOR(name->rdev), f->op, f->val))
57016c174bdSEric Paris 					++result;
57116c174bdSEric Paris 			} else if (ctx) {
5725195d8e2SEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
57316c174bdSEric Paris 					if (audit_comparator(MAJOR(n->dev), f->op, f->val) ||
57416c174bdSEric Paris 					    audit_comparator(MAJOR(n->rdev), f->op, f->val)) {
5751da177e4SLinus Torvalds 						++result;
5761da177e4SLinus Torvalds 						break;
5771da177e4SLinus Torvalds 					}
5781da177e4SLinus Torvalds 				}
5791da177e4SLinus Torvalds 			}
5801da177e4SLinus Torvalds 			break;
5811da177e4SLinus Torvalds 		case AUDIT_DEVMINOR:
58216c174bdSEric Paris 			if (name) {
58316c174bdSEric Paris 				if (audit_comparator(MINOR(name->dev), f->op, f->val) ||
58416c174bdSEric Paris 				    audit_comparator(MINOR(name->rdev), f->op, f->val))
58516c174bdSEric Paris 					++result;
58616c174bdSEric Paris 			} else if (ctx) {
5875195d8e2SEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
58816c174bdSEric Paris 					if (audit_comparator(MINOR(n->dev), f->op, f->val) ||
58916c174bdSEric Paris 					    audit_comparator(MINOR(n->rdev), f->op, f->val)) {
5901da177e4SLinus Torvalds 						++result;
5911da177e4SLinus Torvalds 						break;
5921da177e4SLinus Torvalds 					}
5931da177e4SLinus Torvalds 				}
5941da177e4SLinus Torvalds 			}
5951da177e4SLinus Torvalds 			break;
5961da177e4SLinus Torvalds 		case AUDIT_INODE:
597f368c07dSAmy Griffis 			if (name)
598db510fc5SRichard Guy Briggs 				result = audit_comparator(name->ino, f->op, f->val);
599f368c07dSAmy Griffis 			else if (ctx) {
6005195d8e2SEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
6015195d8e2SEric Paris 					if (audit_comparator(n->ino, f->op, f->val)) {
6021da177e4SLinus Torvalds 						++result;
6031da177e4SLinus Torvalds 						break;
6041da177e4SLinus Torvalds 					}
6051da177e4SLinus Torvalds 				}
6061da177e4SLinus Torvalds 			}
6071da177e4SLinus Torvalds 			break;
608efaffd6eSEric Paris 		case AUDIT_OBJ_UID:
609efaffd6eSEric Paris 			if (name) {
610ca57ec0fSEric W. Biederman 				result = audit_uid_comparator(name->uid, f->op, f->uid);
611efaffd6eSEric Paris 			} else if (ctx) {
612efaffd6eSEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
613ca57ec0fSEric W. Biederman 					if (audit_uid_comparator(n->uid, f->op, f->uid)) {
614efaffd6eSEric Paris 						++result;
615efaffd6eSEric Paris 						break;
616efaffd6eSEric Paris 					}
617efaffd6eSEric Paris 				}
618efaffd6eSEric Paris 			}
619efaffd6eSEric Paris 			break;
62054d3218bSEric Paris 		case AUDIT_OBJ_GID:
62154d3218bSEric Paris 			if (name) {
622ca57ec0fSEric W. Biederman 				result = audit_gid_comparator(name->gid, f->op, f->gid);
62354d3218bSEric Paris 			} else if (ctx) {
62454d3218bSEric Paris 				list_for_each_entry(n, &ctx->names_list, list) {
625ca57ec0fSEric W. Biederman 					if (audit_gid_comparator(n->gid, f->op, f->gid)) {
62654d3218bSEric Paris 						++result;
62754d3218bSEric Paris 						break;
62854d3218bSEric Paris 					}
62954d3218bSEric Paris 				}
63054d3218bSEric Paris 			}
63154d3218bSEric Paris 			break;
632f368c07dSAmy Griffis 		case AUDIT_WATCH:
6330223fad3SRichard Guy Briggs 			if (name) {
6340223fad3SRichard Guy Briggs 				result = audit_watch_compare(rule->watch,
6350223fad3SRichard Guy Briggs 							     name->ino,
6360223fad3SRichard Guy Briggs 							     name->dev);
6370223fad3SRichard Guy Briggs 				if (f->op == Audit_not_equal)
6380223fad3SRichard Guy Briggs 					result = !result;
6390223fad3SRichard Guy Briggs 			}
640f368c07dSAmy Griffis 			break;
64174c3cbe3SAl Viro 		case AUDIT_DIR:
6420223fad3SRichard Guy Briggs 			if (ctx) {
64374c3cbe3SAl Viro 				result = match_tree_refs(ctx, rule->tree);
6440223fad3SRichard Guy Briggs 				if (f->op == Audit_not_equal)
6450223fad3SRichard Guy Briggs 					result = !result;
6460223fad3SRichard Guy Briggs 			}
64774c3cbe3SAl Viro 			break;
6481da177e4SLinus Torvalds 		case AUDIT_LOGINUID:
64938f80590SRichard Guy Briggs 			result = audit_uid_comparator(audit_get_loginuid(tsk),
65038f80590SRichard Guy Briggs 						      f->op, f->uid);
6511da177e4SLinus Torvalds 			break;
652780a7654SEric W. Biederman 		case AUDIT_LOGINUID_SET:
653780a7654SEric W. Biederman 			result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
654780a7654SEric W. Biederman 			break;
655bf361231SRichard Guy Briggs 		case AUDIT_SADDR_FAM:
6566e3ee990SGaosheng Cui 			if (ctx && ctx->sockaddr)
657bf361231SRichard Guy Briggs 				result = audit_comparator(ctx->sockaddr->ss_family,
658bf361231SRichard Guy Briggs 							  f->op, f->val);
659bf361231SRichard Guy Briggs 			break;
6603a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_USER:
6613a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_ROLE:
6623a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_TYPE:
6633a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_SEN:
6643a6b9f85SDarrel Goeddel 		case AUDIT_SUBJ_CLR:
6653dc7e315SDarrel Goeddel 			/* NOTE: this may return negative values indicating
6663dc7e315SDarrel Goeddel 			   a temporary error.  We simply treat this as a
6673dc7e315SDarrel Goeddel 			   match for now to avoid losing information that
6683dc7e315SDarrel Goeddel 			   may be wanted.   An error message will also be
6693dc7e315SDarrel Goeddel 			   logged upon error */
67004305e4aSAhmed S. Darwish 			if (f->lsm_rule) {
6712ad312d2SSteve Grubb 				if (need_sid) {
6726326948fSPaul Moore 					/* @tsk should always be equal to
6736326948fSPaul Moore 					 * @current with the exception of
6746326948fSPaul Moore 					 * fork()/copy_process() in which case
6756326948fSPaul Moore 					 * the new @tsk creds are still a dup
6766326948fSPaul Moore 					 * of @current's creds so we can still
6776326948fSPaul Moore 					 * use security_current_getsecid_subj()
6786326948fSPaul Moore 					 * here even though it always refs
6796326948fSPaul Moore 					 * @current's creds
6806326948fSPaul Moore 					 */
6816326948fSPaul Moore 					security_current_getsecid_subj(&sid);
6822ad312d2SSteve Grubb 					need_sid = 0;
6832ad312d2SSteve Grubb 				}
684d7a96f3aSAhmed S. Darwish 				result = security_audit_rule_match(sid, f->type,
6853dc7e315SDarrel Goeddel 								   f->op,
68690462a5bSRichard Guy Briggs 								   f->lsm_rule);
6872ad312d2SSteve Grubb 			}
6883dc7e315SDarrel Goeddel 			break;
6896e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_USER:
6906e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_ROLE:
6916e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_TYPE:
6926e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_LEV_LOW:
6936e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_LEV_HIGH:
6946e5a2d1dSDarrel Goeddel 			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
6956e5a2d1dSDarrel Goeddel 			   also applies here */
69604305e4aSAhmed S. Darwish 			if (f->lsm_rule) {
6976e5a2d1dSDarrel Goeddel 				/* Find files that match */
6986e5a2d1dSDarrel Goeddel 				if (name) {
699d7a96f3aSAhmed S. Darwish 					result = security_audit_rule_match(
70090462a5bSRichard Guy Briggs 								name->osid,
70190462a5bSRichard Guy Briggs 								f->type,
70290462a5bSRichard Guy Briggs 								f->op,
70390462a5bSRichard Guy Briggs 								f->lsm_rule);
7046e5a2d1dSDarrel Goeddel 				} else if (ctx) {
7055195d8e2SEric Paris 					list_for_each_entry(n, &ctx->names_list, list) {
70690462a5bSRichard Guy Briggs 						if (security_audit_rule_match(
70790462a5bSRichard Guy Briggs 								n->osid,
70890462a5bSRichard Guy Briggs 								f->type,
70990462a5bSRichard Guy Briggs 								f->op,
71090462a5bSRichard Guy Briggs 								f->lsm_rule)) {
7116e5a2d1dSDarrel Goeddel 							++result;
7126e5a2d1dSDarrel Goeddel 							break;
7136e5a2d1dSDarrel Goeddel 						}
7146e5a2d1dSDarrel Goeddel 					}
7156e5a2d1dSDarrel Goeddel 				}
7166e5a2d1dSDarrel Goeddel 				/* Find ipc objects that match */
717a33e6751SAl Viro 				if (!ctx || ctx->type != AUDIT_IPC)
7186e5a2d1dSDarrel Goeddel 					break;
719a33e6751SAl Viro 				if (security_audit_rule_match(ctx->ipc.osid,
720a33e6751SAl Viro 							      f->type, f->op,
72190462a5bSRichard Guy Briggs 							      f->lsm_rule))
722a33e6751SAl Viro 					++result;
7236e5a2d1dSDarrel Goeddel 			}
7246e5a2d1dSDarrel Goeddel 			break;
7251da177e4SLinus Torvalds 		case AUDIT_ARG0:
7261da177e4SLinus Torvalds 		case AUDIT_ARG1:
7271da177e4SLinus Torvalds 		case AUDIT_ARG2:
7281da177e4SLinus Torvalds 		case AUDIT_ARG3:
7291da177e4SLinus Torvalds 			if (ctx)
73093315ed6SAmy Griffis 				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
7311da177e4SLinus Torvalds 			break;
7325adc8a6aSAmy Griffis 		case AUDIT_FILTERKEY:
7335adc8a6aSAmy Griffis 			/* ignore this field for filtering */
7345adc8a6aSAmy Griffis 			result = 1;
7355adc8a6aSAmy Griffis 			break;
73655669bfaSAl Viro 		case AUDIT_PERM:
73755669bfaSAl Viro 			result = audit_match_perm(ctx, f->val);
7380223fad3SRichard Guy Briggs 			if (f->op == Audit_not_equal)
7390223fad3SRichard Guy Briggs 				result = !result;
74055669bfaSAl Viro 			break;
7418b67dca9SAl Viro 		case AUDIT_FILETYPE:
7428b67dca9SAl Viro 			result = audit_match_filetype(ctx, f->val);
7430223fad3SRichard Guy Briggs 			if (f->op == Audit_not_equal)
7440223fad3SRichard Guy Briggs 				result = !result;
7458b67dca9SAl Viro 			break;
74602d86a56SEric Paris 		case AUDIT_FIELD_COMPARE:
74702d86a56SEric Paris 			result = audit_field_compare(tsk, cred, f, ctx, name);
74802d86a56SEric Paris 			break;
7491da177e4SLinus Torvalds 		}
750f5629883STony Jones 		if (!result)
7511da177e4SLinus Torvalds 			return 0;
7521da177e4SLinus Torvalds 	}
7530590b933SAl Viro 
7540590b933SAl Viro 	if (ctx) {
7550590b933SAl Viro 		if (rule->filterkey) {
7560590b933SAl Viro 			kfree(ctx->filterkey);
7575adc8a6aSAmy Griffis 			ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
7580590b933SAl Viro 		}
7590590b933SAl Viro 		ctx->prio = rule->prio;
7600590b933SAl Viro 	}
7611da177e4SLinus Torvalds 	switch (rule->action) {
76266b12abcSPaul Moore 	case AUDIT_NEVER:
763619ed58aSSergey Nazarov 		*state = AUDIT_STATE_DISABLED;
76466b12abcSPaul Moore 		break;
76566b12abcSPaul Moore 	case AUDIT_ALWAYS:
766619ed58aSSergey Nazarov 		*state = AUDIT_STATE_RECORD;
76766b12abcSPaul Moore 		break;
7681da177e4SLinus Torvalds 	}
7691da177e4SLinus Torvalds 	return 1;
7701da177e4SLinus Torvalds }
7711da177e4SLinus Torvalds 
7721da177e4SLinus Torvalds /* At process creation time, we can determine if system-call auditing is
7731da177e4SLinus Torvalds  * completely disabled for this task.  Since we only have the task
7741da177e4SLinus Torvalds  * structure at this point, we can only check uid and gid.
7751da177e4SLinus Torvalds  */
audit_filter_task(struct task_struct * tsk,char ** key)776e048e02cSAl Viro static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
7771da177e4SLinus Torvalds {
7781da177e4SLinus Torvalds 	struct audit_entry *e;
7791da177e4SLinus Torvalds 	enum audit_state   state;
7801da177e4SLinus Torvalds 
7811da177e4SLinus Torvalds 	rcu_read_lock();
7820f45aa18SDavid Woodhouse 	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
783f5629883STony Jones 		if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
784f5629883STony Jones 				       &state, true)) {
785619ed58aSSergey Nazarov 			if (state == AUDIT_STATE_RECORD)
786e048e02cSAl Viro 				*key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
7871da177e4SLinus Torvalds 			rcu_read_unlock();
7881da177e4SLinus Torvalds 			return state;
7891da177e4SLinus Torvalds 		}
7901da177e4SLinus Torvalds 	}
7911da177e4SLinus Torvalds 	rcu_read_unlock();
792619ed58aSSergey Nazarov 	return AUDIT_STATE_BUILD;
7931da177e4SLinus Torvalds }
7941da177e4SLinus Torvalds 
audit_in_mask(const struct audit_krule * rule,unsigned long val)795a3c54931SAndy Lutomirski static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
796a3c54931SAndy Lutomirski {
797a3c54931SAndy Lutomirski 	int word, bit;
798a3c54931SAndy Lutomirski 
799a3c54931SAndy Lutomirski 	if (val > 0xffffffff)
800a3c54931SAndy Lutomirski 		return false;
801a3c54931SAndy Lutomirski 
802a3c54931SAndy Lutomirski 	word = AUDIT_WORD(val);
803a3c54931SAndy Lutomirski 	if (word >= AUDIT_BITMASK_SIZE)
804a3c54931SAndy Lutomirski 		return false;
805a3c54931SAndy Lutomirski 
806a3c54931SAndy Lutomirski 	bit = AUDIT_BIT(val);
807a3c54931SAndy Lutomirski 
808a3c54931SAndy Lutomirski 	return rule->mask[word] & bit;
809a3c54931SAndy Lutomirski }
810a3c54931SAndy Lutomirski 
81167daf270SPaul Moore /**
81250979953SAnkur Arora  * __audit_filter_op - common filter helper for operations (syscall/uring/etc)
81350979953SAnkur Arora  * @tsk: associated task
81450979953SAnkur Arora  * @ctx: audit context
81550979953SAnkur Arora  * @list: audit filter list
81650979953SAnkur Arora  * @name: audit_name (can be NULL)
81750979953SAnkur Arora  * @op: current syscall/uring_op
81850979953SAnkur Arora  *
81950979953SAnkur Arora  * Run the udit filters specified in @list against @tsk using @ctx,
82050979953SAnkur Arora  * @name, and @op, as necessary; the caller is responsible for ensuring
82150979953SAnkur Arora  * that the call is made while the RCU read lock is held. The @name
82250979953SAnkur Arora  * parameter can be NULL, but all others must be specified.
82350979953SAnkur Arora  * Returns 1/true if the filter finds a match, 0/false if none are found.
82450979953SAnkur Arora  */
__audit_filter_op(struct task_struct * tsk,struct audit_context * ctx,struct list_head * list,struct audit_names * name,unsigned long op)82550979953SAnkur Arora static int __audit_filter_op(struct task_struct *tsk,
82650979953SAnkur Arora 			   struct audit_context *ctx,
82750979953SAnkur Arora 			   struct list_head *list,
82850979953SAnkur Arora 			   struct audit_names *name,
82950979953SAnkur Arora 			   unsigned long op)
83050979953SAnkur Arora {
83150979953SAnkur Arora 	struct audit_entry *e;
83250979953SAnkur Arora 	enum audit_state state;
83350979953SAnkur Arora 
83450979953SAnkur Arora 	list_for_each_entry_rcu(e, list, list) {
83550979953SAnkur Arora 		if (audit_in_mask(&e->rule, op) &&
83650979953SAnkur Arora 		    audit_filter_rules(tsk, &e->rule, ctx, name,
83750979953SAnkur Arora 				       &state, false)) {
83850979953SAnkur Arora 			ctx->current_state = state;
83950979953SAnkur Arora 			return 1;
84050979953SAnkur Arora 		}
84150979953SAnkur Arora 	}
84250979953SAnkur Arora 	return 0;
84350979953SAnkur Arora }
84450979953SAnkur Arora 
84550979953SAnkur Arora /**
84667daf270SPaul Moore  * audit_filter_uring - apply filters to an io_uring operation
84767daf270SPaul Moore  * @tsk: associated task
84867daf270SPaul Moore  * @ctx: audit context
84967daf270SPaul Moore  */
audit_filter_uring(struct task_struct * tsk,struct audit_context * ctx)85067daf270SPaul Moore static void audit_filter_uring(struct task_struct *tsk,
85167daf270SPaul Moore 			       struct audit_context *ctx)
85267daf270SPaul Moore {
85367daf270SPaul Moore 	if (auditd_test_task(tsk))
85467daf270SPaul Moore 		return;
85567daf270SPaul Moore 
85667daf270SPaul Moore 	rcu_read_lock();
85750979953SAnkur Arora 	__audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_URING_EXIT],
85850979953SAnkur Arora 			NULL, ctx->uring_op);
85967daf270SPaul Moore 	rcu_read_unlock();
86067daf270SPaul Moore }
86167daf270SPaul Moore 
862127c8c5fSYang Yang /* At syscall exit time, this filter is called if the audit_state is
863127c8c5fSYang Yang  * not low enough that auditing cannot take place, but is also not
864127c8c5fSYang Yang  * high enough that we already know we have to write an audit record
865619ed58aSSergey Nazarov  * (i.e., the state is AUDIT_STATE_BUILD).
8661da177e4SLinus Torvalds  */
audit_filter_syscall(struct task_struct * tsk,struct audit_context * ctx)867127c8c5fSYang Yang static void audit_filter_syscall(struct task_struct *tsk,
8685504a69aSRichard Guy Briggs 				 struct audit_context *ctx)
8691da177e4SLinus Torvalds {
8705b52330bSPaul Moore 	if (auditd_test_task(tsk))
871127c8c5fSYang Yang 		return;
872f7056d64SDavid Woodhouse 
8731da177e4SLinus Torvalds 	rcu_read_lock();
87450979953SAnkur Arora 	__audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_EXIT],
87550979953SAnkur Arora 			NULL, ctx->major);
8761da177e4SLinus Torvalds 	rcu_read_unlock();
8771da177e4SLinus Torvalds }
8781da177e4SLinus Torvalds 
8795195d8e2SEric Paris /*
8805195d8e2SEric Paris  * Given an audit_name check the inode hash table to see if they match.
8815195d8e2SEric Paris  * Called holding the rcu read lock to protect the use of audit_inode_hash
8825195d8e2SEric Paris  */
audit_filter_inode_name(struct task_struct * tsk,struct audit_names * n,struct audit_context * ctx)8835195d8e2SEric Paris static int audit_filter_inode_name(struct task_struct *tsk,
8845195d8e2SEric Paris 				   struct audit_names *n,
88522cde101SAtul Kumar Pant 				   struct audit_context *ctx)
88622cde101SAtul Kumar Pant {
8875195d8e2SEric Paris 	int h = audit_hash_ino((u32)n->ino);
8885195d8e2SEric Paris 	struct list_head *list = &audit_inode_hash[h];
8895195d8e2SEric Paris 
89050979953SAnkur Arora 	return __audit_filter_op(tsk, ctx, list, n, ctx->major);
8915195d8e2SEric Paris }
8925195d8e2SEric Paris 
8935195d8e2SEric Paris /* At syscall exit time, this filter is called if any audit_names have been
894f368c07dSAmy Griffis  * collected during syscall processing.  We only check rules in sublists at hash
8955195d8e2SEric Paris  * buckets applicable to the inode numbers in audit_names.
896f368c07dSAmy Griffis  * Regarding audit_state, same rules apply as for audit_filter_syscall().
897f368c07dSAmy Griffis  */
audit_filter_inodes(struct task_struct * tsk,struct audit_context * ctx)8980590b933SAl Viro void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
899f368c07dSAmy Griffis {
9005195d8e2SEric Paris 	struct audit_names *n;
901f368c07dSAmy Griffis 
9025b52330bSPaul Moore 	if (auditd_test_task(tsk))
9030590b933SAl Viro 		return;
904f368c07dSAmy Griffis 
905f368c07dSAmy Griffis 	rcu_read_lock();
906f368c07dSAmy Griffis 
9075195d8e2SEric Paris 	list_for_each_entry(n, &ctx->names_list, list) {
9085195d8e2SEric Paris 		if (audit_filter_inode_name(tsk, n, ctx))
9095195d8e2SEric Paris 			break;
910f368c07dSAmy Griffis 	}
911f368c07dSAmy Griffis 	rcu_read_unlock();
912f368c07dSAmy Griffis }
913f368c07dSAmy Griffis 
audit_proctitle_free(struct audit_context * context)9143f1c8250SWilliam Roberts static inline void audit_proctitle_free(struct audit_context *context)
9153f1c8250SWilliam Roberts {
9163f1c8250SWilliam Roberts 	kfree(context->proctitle.value);
9173f1c8250SWilliam Roberts 	context->proctitle.value = NULL;
9183f1c8250SWilliam Roberts 	context->proctitle.len = 0;
9193f1c8250SWilliam Roberts }
9203f1c8250SWilliam Roberts 
audit_free_module(struct audit_context * context)92195e0b46fSLi RongQing static inline void audit_free_module(struct audit_context *context)
92295e0b46fSLi RongQing {
92395e0b46fSLi RongQing 	if (context->type == AUDIT_KERN_MODULE) {
92495e0b46fSLi RongQing 		kfree(context->module.name);
92595e0b46fSLi RongQing 		context->module.name = NULL;
92695e0b46fSLi RongQing 	}
92795e0b46fSLi RongQing }
audit_free_names(struct audit_context * context)9281da177e4SLinus Torvalds static inline void audit_free_names(struct audit_context *context)
9291da177e4SLinus Torvalds {
9305195d8e2SEric Paris 	struct audit_names *n, *next;
9311da177e4SLinus Torvalds 
9325195d8e2SEric Paris 	list_for_each_entry_safe(n, next, &context->names_list, list) {
9335195d8e2SEric Paris 		list_del(&n->list);
93455422d0bSPaul Moore 		if (n->name)
93555422d0bSPaul Moore 			putname(n->name);
9365195d8e2SEric Paris 		if (n->should_free)
9375195d8e2SEric Paris 			kfree(n);
9388c8570fbSDustin Kirkland 	}
9391da177e4SLinus Torvalds 	context->name_count = 0;
94044707fdfSJan Blunck 	path_put(&context->pwd);
94144707fdfSJan Blunck 	context->pwd.dentry = NULL;
94244707fdfSJan Blunck 	context->pwd.mnt = NULL;
9431da177e4SLinus Torvalds }
9441da177e4SLinus Torvalds 
audit_free_aux(struct audit_context * context)9451da177e4SLinus Torvalds static inline void audit_free_aux(struct audit_context *context)
9461da177e4SLinus Torvalds {
9471da177e4SLinus Torvalds 	struct audit_aux_data *aux;
9481da177e4SLinus Torvalds 
9491da177e4SLinus Torvalds 	while ((aux = context->aux)) {
9501da177e4SLinus Torvalds 		context->aux = aux->next;
9511da177e4SLinus Torvalds 		kfree(aux);
9521da177e4SLinus Torvalds 	}
95312c5e81dSPaul Moore 	context->aux = NULL;
954e54dc243SAmy Griffis 	while ((aux = context->aux_pids)) {
955e54dc243SAmy Griffis 		context->aux_pids = aux->next;
956e54dc243SAmy Griffis 		kfree(aux);
957e54dc243SAmy Griffis 	}
95812c5e81dSPaul Moore 	context->aux_pids = NULL;
95912c5e81dSPaul Moore }
96012c5e81dSPaul Moore 
96112c5e81dSPaul Moore /**
96212c5e81dSPaul Moore  * audit_reset_context - reset a audit_context structure
96312c5e81dSPaul Moore  * @ctx: the audit_context to reset
96412c5e81dSPaul Moore  *
96512c5e81dSPaul Moore  * All fields in the audit_context will be reset to an initial state, all
96612c5e81dSPaul Moore  * references held by fields will be dropped, and private memory will be
96712c5e81dSPaul Moore  * released.  When this function returns the audit_context will be suitable
96812c5e81dSPaul Moore  * for reuse, so long as the passed context is not NULL or a dummy context.
96912c5e81dSPaul Moore  */
audit_reset_context(struct audit_context * ctx)97012c5e81dSPaul Moore static void audit_reset_context(struct audit_context *ctx)
97112c5e81dSPaul Moore {
97212c5e81dSPaul Moore 	if (!ctx)
97312c5e81dSPaul Moore 		return;
97412c5e81dSPaul Moore 
975e84d9f52SRichard Guy Briggs 	/* if ctx is non-null, reset the "ctx->context" regardless */
97612c5e81dSPaul Moore 	ctx->context = AUDIT_CTX_UNUSED;
97712c5e81dSPaul Moore 	if (ctx->dummy)
97812c5e81dSPaul Moore 		return;
97912c5e81dSPaul Moore 
98012c5e81dSPaul Moore 	/*
98112c5e81dSPaul Moore 	 * NOTE: It shouldn't matter in what order we release the fields, so
98212c5e81dSPaul Moore 	 *       release them in the order in which they appear in the struct;
98312c5e81dSPaul Moore 	 *       this gives us some hope of quickly making sure we are
98412c5e81dSPaul Moore 	 *       resetting the audit_context properly.
98512c5e81dSPaul Moore 	 *
98612c5e81dSPaul Moore 	 *       Other things worth mentioning:
98712c5e81dSPaul Moore 	 *       - we don't reset "dummy"
98812c5e81dSPaul Moore 	 *       - we don't reset "state", we do reset "current_state"
98912c5e81dSPaul Moore 	 *       - we preserve "filterkey" if "state" is AUDIT_STATE_RECORD
99012c5e81dSPaul Moore 	 *       - much of this is likely overkill, but play it safe for now
99112c5e81dSPaul Moore 	 *       - we really need to work on improving the audit_context struct
99212c5e81dSPaul Moore 	 */
99312c5e81dSPaul Moore 
99412c5e81dSPaul Moore 	ctx->current_state = ctx->state;
99512c5e81dSPaul Moore 	ctx->serial = 0;
99612c5e81dSPaul Moore 	ctx->major = 0;
9975bd2182dSPaul Moore 	ctx->uring_op = 0;
99812c5e81dSPaul Moore 	ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
99912c5e81dSPaul Moore 	memset(ctx->argv, 0, sizeof(ctx->argv));
100012c5e81dSPaul Moore 	ctx->return_code = 0;
100112c5e81dSPaul Moore 	ctx->prio = (ctx->state == AUDIT_STATE_RECORD ? ~0ULL : 0);
100212c5e81dSPaul Moore 	ctx->return_valid = AUDITSC_INVALID;
100312c5e81dSPaul Moore 	audit_free_names(ctx);
100412c5e81dSPaul Moore 	if (ctx->state != AUDIT_STATE_RECORD) {
100512c5e81dSPaul Moore 		kfree(ctx->filterkey);
100612c5e81dSPaul Moore 		ctx->filterkey = NULL;
100712c5e81dSPaul Moore 	}
100812c5e81dSPaul Moore 	audit_free_aux(ctx);
100912c5e81dSPaul Moore 	kfree(ctx->sockaddr);
101012c5e81dSPaul Moore 	ctx->sockaddr = NULL;
101112c5e81dSPaul Moore 	ctx->sockaddr_len = 0;
1012e84d9f52SRichard Guy Briggs 	ctx->ppid = 0;
101312c5e81dSPaul Moore 	ctx->uid = ctx->euid = ctx->suid = ctx->fsuid = KUIDT_INIT(0);
101412c5e81dSPaul Moore 	ctx->gid = ctx->egid = ctx->sgid = ctx->fsgid = KGIDT_INIT(0);
101512c5e81dSPaul Moore 	ctx->personality = 0;
101612c5e81dSPaul Moore 	ctx->arch = 0;
101712c5e81dSPaul Moore 	ctx->target_pid = 0;
101812c5e81dSPaul Moore 	ctx->target_auid = ctx->target_uid = KUIDT_INIT(0);
101912c5e81dSPaul Moore 	ctx->target_sessionid = 0;
102012c5e81dSPaul Moore 	ctx->target_sid = 0;
102112c5e81dSPaul Moore 	ctx->target_comm[0] = '\0';
102212c5e81dSPaul Moore 	unroll_tree_refs(ctx, NULL, 0);
102312c5e81dSPaul Moore 	WARN_ON(!list_empty(&ctx->killed_trees));
102412c5e81dSPaul Moore 	audit_free_module(ctx);
102512c5e81dSPaul Moore 	ctx->fds[0] = -1;
1026ef79c396SChristian Göttsche 	ctx->type = 0; /* reset last for audit_free_*() */
10271da177e4SLinus Torvalds }
10281da177e4SLinus Torvalds 
audit_alloc_context(enum audit_state state)10291da177e4SLinus Torvalds static inline struct audit_context *audit_alloc_context(enum audit_state state)
10301da177e4SLinus Torvalds {
10311da177e4SLinus Torvalds 	struct audit_context *context;
10321da177e4SLinus Torvalds 
103317c6ee70SRakib Mullick 	context = kzalloc(sizeof(*context), GFP_KERNEL);
103417c6ee70SRakib Mullick 	if (!context)
10351da177e4SLinus Torvalds 		return NULL;
103612c5e81dSPaul Moore 	context->context = AUDIT_CTX_UNUSED;
1037e2c5adc8SAndrew Morton 	context->state = state;
1038619ed58aSSergey Nazarov 	context->prio = state == AUDIT_STATE_RECORD ? ~0ULL : 0;
1039916d7576SAl Viro 	INIT_LIST_HEAD(&context->killed_trees);
10405195d8e2SEric Paris 	INIT_LIST_HEAD(&context->names_list);
10416d915476SRichard Guy Briggs 	context->fds[0] = -1;
1042ba59eae7SAlex Shi 	context->return_valid = AUDITSC_INVALID;
10431da177e4SLinus Torvalds 	return context;
10441da177e4SLinus Torvalds }
10451da177e4SLinus Torvalds 
1046b0dd25a8SRandy Dunlap /**
1047b0dd25a8SRandy Dunlap  * audit_alloc - allocate an audit context block for a task
1048b0dd25a8SRandy Dunlap  * @tsk: task
1049b0dd25a8SRandy Dunlap  *
1050b0dd25a8SRandy Dunlap  * Filter on the task information and allocate a per-task audit context
10511da177e4SLinus Torvalds  * if necessary.  Doing so turns on system call auditing for the
10521da177e4SLinus Torvalds  * specified task.  This is called from copy_process, so no lock is
1053b0dd25a8SRandy Dunlap  * needed.
1054b0dd25a8SRandy Dunlap  */
audit_alloc(struct task_struct * tsk)10551da177e4SLinus Torvalds int audit_alloc(struct task_struct *tsk)
10561da177e4SLinus Torvalds {
10571da177e4SLinus Torvalds 	struct audit_context *context;
10581da177e4SLinus Torvalds 	enum audit_state     state;
1059e048e02cSAl Viro 	char *key = NULL;
10601da177e4SLinus Torvalds 
1061b593d384SEric Paris 	if (likely(!audit_ever_enabled))
106212c5e81dSPaul Moore 		return 0;
10631da177e4SLinus Torvalds 
1064e048e02cSAl Viro 	state = audit_filter_task(tsk, &key);
1065619ed58aSSergey Nazarov 	if (state == AUDIT_STATE_DISABLED) {
1066785dc4ebSGabriel Krisman Bertazi 		clear_task_syscall_work(tsk, SYSCALL_AUDIT);
10671da177e4SLinus Torvalds 		return 0;
1068d48d8051SOleg Nesterov 	}
10691da177e4SLinus Torvalds 
107022cde101SAtul Kumar Pant 	context = audit_alloc_context(state);
107122cde101SAtul Kumar Pant 	if (!context) {
1072e048e02cSAl Viro 		kfree(key);
10731da177e4SLinus Torvalds 		audit_log_lost("out of memory in audit_alloc");
10741da177e4SLinus Torvalds 		return -ENOMEM;
10751da177e4SLinus Torvalds 	}
1076e048e02cSAl Viro 	context->filterkey = key;
10771da177e4SLinus Torvalds 
1078c0b0ae8aSRichard Guy Briggs 	audit_set_context(tsk, context);
1079785dc4ebSGabriel Krisman Bertazi 	set_task_syscall_work(tsk, SYSCALL_AUDIT);
10801da177e4SLinus Torvalds 	return 0;
10811da177e4SLinus Torvalds }
10821da177e4SLinus Torvalds 
audit_free_context(struct audit_context * context)10831da177e4SLinus Torvalds static inline void audit_free_context(struct audit_context *context)
10841da177e4SLinus Torvalds {
108512c5e81dSPaul Moore 	/* resetting is extra work, but it is likely just noise */
108612c5e81dSPaul Moore 	audit_reset_context(context);
1087c3f3ea8aSRichard Guy Briggs 	audit_proctitle_free(context);
108874c3cbe3SAl Viro 	free_tree_refs(context);
10895adc8a6aSAmy Griffis 	kfree(context->filterkey);
10901da177e4SLinus Torvalds 	kfree(context);
10911da177e4SLinus Torvalds }
10921da177e4SLinus Torvalds 
audit_log_pid_context(struct audit_context * context,pid_t pid,kuid_t auid,kuid_t uid,unsigned int sessionid,u32 sid,char * comm)1093e54dc243SAmy Griffis static int audit_log_pid_context(struct audit_context *context, pid_t pid,
1094cca080d9SEric W. Biederman 				 kuid_t auid, kuid_t uid, unsigned int sessionid,
10954746ec5bSEric Paris 				 u32 sid, char *comm)
1096e54dc243SAmy Griffis {
1097e54dc243SAmy Griffis 	struct audit_buffer *ab;
10982a862b32SAhmed S. Darwish 	char *ctx = NULL;
1099e54dc243SAmy Griffis 	u32 len;
1100e54dc243SAmy Griffis 	int rc = 0;
1101e54dc243SAmy Griffis 
1102e54dc243SAmy Griffis 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
1103e54dc243SAmy Griffis 	if (!ab)
11046246ccabSEric Paris 		return rc;
1105e54dc243SAmy Griffis 
1106e1760bd5SEric W. Biederman 	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
1107e1760bd5SEric W. Biederman 			 from_kuid(&init_user_ns, auid),
1108cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, uid), sessionid);
1109ad395abeSEric Paris 	if (sid) {
11102a862b32SAhmed S. Darwish 		if (security_secid_to_secctx(sid, &ctx, &len)) {
1111c2a7780eSEric Paris 			audit_log_format(ab, " obj=(none)");
1112e54dc243SAmy Griffis 			rc = 1;
11132a862b32SAhmed S. Darwish 		} else {
11142a862b32SAhmed S. Darwish 			audit_log_format(ab, " obj=%s", ctx);
11152a862b32SAhmed S. Darwish 			security_release_secctx(ctx, len);
11162a862b32SAhmed S. Darwish 		}
1117ad395abeSEric Paris 	}
1118c2a7780eSEric Paris 	audit_log_format(ab, " ocomm=");
1119c2a7780eSEric Paris 	audit_log_untrustedstring(ab, comm);
1120e54dc243SAmy Griffis 	audit_log_end(ab);
1121e54dc243SAmy Griffis 
1122e54dc243SAmy Griffis 	return rc;
1123e54dc243SAmy Griffis }
1124e54dc243SAmy Griffis 
audit_log_execve_info(struct audit_context * context,struct audit_buffer ** ab)1125de6bbd1dSEric Paris static void audit_log_execve_info(struct audit_context *context,
1126d9cfea91SRichard Guy Briggs 				  struct audit_buffer **ab)
1127de6bbd1dSEric Paris {
112843761473SPaul Moore 	long len_max;
112943761473SPaul Moore 	long len_rem;
113043761473SPaul Moore 	long len_full;
113143761473SPaul Moore 	long len_buf;
11328443075eSRichard Guy Briggs 	long len_abuf = 0;
113343761473SPaul Moore 	long len_tmp;
113443761473SPaul Moore 	bool require_data;
113543761473SPaul Moore 	bool encode;
113643761473SPaul Moore 	unsigned int iter;
113743761473SPaul Moore 	unsigned int arg;
113843761473SPaul Moore 	char *buf_head;
1139de6bbd1dSEric Paris 	char *buf;
114043761473SPaul Moore 	const char __user *p = (const char __user *)current->mm->arg_start;
1141de6bbd1dSEric Paris 
114243761473SPaul Moore 	/* NOTE: this buffer needs to be large enough to hold all the non-arg
114343761473SPaul Moore 	 *       data we put in the audit record for this argument (see the
114443761473SPaul Moore 	 *       code below) ... at this point in time 96 is plenty */
114543761473SPaul Moore 	char abuf[96];
1146de6bbd1dSEric Paris 
114743761473SPaul Moore 	/* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the
114843761473SPaul Moore 	 *       current value of 7500 is not as important as the fact that it
114943761473SPaul Moore 	 *       is less than 8k, a setting of 7500 gives us plenty of wiggle
115043761473SPaul Moore 	 *       room if we go over a little bit in the logging below */
115143761473SPaul Moore 	WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500);
115243761473SPaul Moore 	len_max = MAX_EXECVE_AUDIT_LEN;
1153de6bbd1dSEric Paris 
115443761473SPaul Moore 	/* scratch buffer to hold the userspace args */
115543761473SPaul Moore 	buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
115643761473SPaul Moore 	if (!buf_head) {
1157b7550787SJoe Perches 		audit_panic("out of memory for argv string");
1158de6bbd1dSEric Paris 		return;
1159de6bbd1dSEric Paris 	}
116043761473SPaul Moore 	buf = buf_head;
1161de6bbd1dSEric Paris 
116243761473SPaul Moore 	audit_log_format(*ab, "argc=%d", context->execve.argc);
116343761473SPaul Moore 
116443761473SPaul Moore 	len_rem = len_max;
116543761473SPaul Moore 	len_buf = 0;
116643761473SPaul Moore 	len_full = 0;
116743761473SPaul Moore 	require_data = true;
116843761473SPaul Moore 	encode = false;
116943761473SPaul Moore 	iter = 0;
117043761473SPaul Moore 	arg = 0;
117143761473SPaul Moore 	do {
117243761473SPaul Moore 		/* NOTE: we don't ever want to trust this value for anything
117343761473SPaul Moore 		 *       serious, but the audit record format insists we
117443761473SPaul Moore 		 *       provide an argument length for really long arguments,
117543761473SPaul Moore 		 *       e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but
117643761473SPaul Moore 		 *       to use strncpy_from_user() to obtain this value for
117743761473SPaul Moore 		 *       recording in the log, although we don't use it
117843761473SPaul Moore 		 *       anywhere here to avoid a double-fetch problem */
117943761473SPaul Moore 		if (len_full == 0)
118043761473SPaul Moore 			len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1;
118143761473SPaul Moore 
118243761473SPaul Moore 		/* read more data from userspace */
118343761473SPaul Moore 		if (require_data) {
118443761473SPaul Moore 			/* can we make more room in the buffer? */
118543761473SPaul Moore 			if (buf != buf_head) {
118643761473SPaul Moore 				memmove(buf_head, buf, len_buf);
118743761473SPaul Moore 				buf = buf_head;
1188de6bbd1dSEric Paris 			}
118943761473SPaul Moore 
119043761473SPaul Moore 			/* fetch as much as we can of the argument */
119143761473SPaul Moore 			len_tmp = strncpy_from_user(&buf_head[len_buf], p,
119243761473SPaul Moore 						    len_max - len_buf);
119343761473SPaul Moore 			if (len_tmp == -EFAULT) {
119443761473SPaul Moore 				/* unable to copy from userspace */
119543761473SPaul Moore 				send_sig(SIGKILL, current, 0);
119643761473SPaul Moore 				goto out;
119743761473SPaul Moore 			} else if (len_tmp == (len_max - len_buf)) {
119843761473SPaul Moore 				/* buffer is not large enough */
119943761473SPaul Moore 				require_data = true;
120043761473SPaul Moore 				/* NOTE: if we are going to span multiple
120143761473SPaul Moore 				 *       buffers force the encoding so we stand
120243761473SPaul Moore 				 *       a chance at a sane len_full value and
120343761473SPaul Moore 				 *       consistent record encoding */
120443761473SPaul Moore 				encode = true;
120543761473SPaul Moore 				len_full = len_full * 2;
120643761473SPaul Moore 				p += len_tmp;
120743761473SPaul Moore 			} else {
120843761473SPaul Moore 				require_data = false;
120943761473SPaul Moore 				if (!encode)
121043761473SPaul Moore 					encode = audit_string_contains_control(
121143761473SPaul Moore 								buf, len_tmp);
121243761473SPaul Moore 				/* try to use a trusted value for len_full */
121343761473SPaul Moore 				if (len_full < len_max)
121443761473SPaul Moore 					len_full = (encode ?
121543761473SPaul Moore 						    len_tmp * 2 : len_tmp);
121643761473SPaul Moore 				p += len_tmp + 1;
121743761473SPaul Moore 			}
121843761473SPaul Moore 			len_buf += len_tmp;
121943761473SPaul Moore 			buf_head[len_buf] = '\0';
122043761473SPaul Moore 
122143761473SPaul Moore 			/* length of the buffer in the audit record? */
122243761473SPaul Moore 			len_abuf = (encode ? len_buf * 2 : len_buf + 2);
122343761473SPaul Moore 		}
122443761473SPaul Moore 
122543761473SPaul Moore 		/* write as much as we can to the audit log */
1226ea956d8bSRichard Guy Briggs 		if (len_buf >= 0) {
122743761473SPaul Moore 			/* NOTE: some magic numbers here - basically if we
122843761473SPaul Moore 			 *       can't fit a reasonable amount of data into the
122943761473SPaul Moore 			 *       existing audit buffer, flush it and start with
123043761473SPaul Moore 			 *       a new buffer */
123143761473SPaul Moore 			if ((sizeof(abuf) + 8) > len_rem) {
123243761473SPaul Moore 				len_rem = len_max;
123343761473SPaul Moore 				audit_log_end(*ab);
123443761473SPaul Moore 				*ab = audit_log_start(context,
123543761473SPaul Moore 						      GFP_KERNEL, AUDIT_EXECVE);
123643761473SPaul Moore 				if (!*ab)
123743761473SPaul Moore 					goto out;
123843761473SPaul Moore 			}
123943761473SPaul Moore 
124043761473SPaul Moore 			/* create the non-arg portion of the arg record */
124143761473SPaul Moore 			len_tmp = 0;
124243761473SPaul Moore 			if (require_data || (iter > 0) ||
124343761473SPaul Moore 			    ((len_abuf + sizeof(abuf)) > len_rem)) {
124443761473SPaul Moore 				if (iter == 0) {
124543761473SPaul Moore 					len_tmp += snprintf(&abuf[len_tmp],
124643761473SPaul Moore 							sizeof(abuf) - len_tmp,
124743761473SPaul Moore 							" a%d_len=%lu",
124843761473SPaul Moore 							arg, len_full);
124943761473SPaul Moore 				}
125043761473SPaul Moore 				len_tmp += snprintf(&abuf[len_tmp],
125143761473SPaul Moore 						    sizeof(abuf) - len_tmp,
125243761473SPaul Moore 						    " a%d[%d]=", arg, iter++);
125343761473SPaul Moore 			} else
125443761473SPaul Moore 				len_tmp += snprintf(&abuf[len_tmp],
125543761473SPaul Moore 						    sizeof(abuf) - len_tmp,
125643761473SPaul Moore 						    " a%d=", arg);
125743761473SPaul Moore 			WARN_ON(len_tmp >= sizeof(abuf));
125843761473SPaul Moore 			abuf[sizeof(abuf) - 1] = '\0';
125943761473SPaul Moore 
126043761473SPaul Moore 			/* log the arg in the audit record */
126143761473SPaul Moore 			audit_log_format(*ab, "%s", abuf);
126243761473SPaul Moore 			len_rem -= len_tmp;
126343761473SPaul Moore 			len_tmp = len_buf;
126443761473SPaul Moore 			if (encode) {
126543761473SPaul Moore 				if (len_abuf > len_rem)
126643761473SPaul Moore 					len_tmp = len_rem / 2; /* encoding */
126743761473SPaul Moore 				audit_log_n_hex(*ab, buf, len_tmp);
126843761473SPaul Moore 				len_rem -= len_tmp * 2;
126943761473SPaul Moore 				len_abuf -= len_tmp * 2;
127043761473SPaul Moore 			} else {
127143761473SPaul Moore 				if (len_abuf > len_rem)
127243761473SPaul Moore 					len_tmp = len_rem - 2; /* quotes */
127343761473SPaul Moore 				audit_log_n_string(*ab, buf, len_tmp);
127443761473SPaul Moore 				len_rem -= len_tmp + 2;
127543761473SPaul Moore 				/* don't subtract the "2" because we still need
127643761473SPaul Moore 				 * to add quotes to the remaining string */
127743761473SPaul Moore 				len_abuf -= len_tmp;
127843761473SPaul Moore 			}
127943761473SPaul Moore 			len_buf -= len_tmp;
128043761473SPaul Moore 			buf += len_tmp;
128143761473SPaul Moore 		}
128243761473SPaul Moore 
128343761473SPaul Moore 		/* ready to move to the next argument? */
128443761473SPaul Moore 		if ((len_buf == 0) && !require_data) {
128543761473SPaul Moore 			arg++;
128643761473SPaul Moore 			iter = 0;
128743761473SPaul Moore 			len_full = 0;
128843761473SPaul Moore 			require_data = true;
128943761473SPaul Moore 			encode = false;
129043761473SPaul Moore 		}
129143761473SPaul Moore 	} while (arg < context->execve.argc);
129243761473SPaul Moore 
129343761473SPaul Moore 	/* NOTE: the caller handles the final audit_log_end() call */
129443761473SPaul Moore 
129543761473SPaul Moore out:
129643761473SPaul Moore 	kfree(buf_head);
1297bdf4c48aSPeter Zijlstra }
1298bdf4c48aSPeter Zijlstra 
audit_log_cap(struct audit_buffer * ab,char * prefix,kernel_cap_t * cap)12992efa48feSYueHaibing static void audit_log_cap(struct audit_buffer *ab, char *prefix,
13002efa48feSYueHaibing 			  kernel_cap_t *cap)
13015f3d544fSRichard Guy Briggs {
13025f3d544fSRichard Guy Briggs 	if (cap_isclear(*cap)) {
13035f3d544fSRichard Guy Briggs 		audit_log_format(ab, " %s=0", prefix);
13045f3d544fSRichard Guy Briggs 		return;
13055f3d544fSRichard Guy Briggs 	}
1306f122a08bSLinus Torvalds 	audit_log_format(ab, " %s=%016llx", prefix, cap->val);
13075f3d544fSRichard Guy Briggs }
13085f3d544fSRichard Guy Briggs 
audit_log_fcaps(struct audit_buffer * ab,struct audit_names * name)13095f3d544fSRichard Guy Briggs static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
13105f3d544fSRichard Guy Briggs {
13115f3d544fSRichard Guy Briggs 	if (name->fcap_ver == -1) {
13125f3d544fSRichard Guy Briggs 		audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?");
13135f3d544fSRichard Guy Briggs 		return;
13145f3d544fSRichard Guy Briggs 	}
13155f3d544fSRichard Guy Briggs 	audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
13165f3d544fSRichard Guy Briggs 	audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
13175f3d544fSRichard Guy Briggs 	audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d",
13185f3d544fSRichard Guy Briggs 			 name->fcap.fE, name->fcap_ver,
13195f3d544fSRichard Guy Briggs 			 from_kuid(&init_user_ns, name->fcap.rootid));
13205f3d544fSRichard Guy Briggs }
13215f3d544fSRichard Guy Briggs 
audit_log_time(struct audit_context * context,struct audit_buffer ** ab)1322272ceeaeSRichard Guy Briggs static void audit_log_time(struct audit_context *context, struct audit_buffer **ab)
1323272ceeaeSRichard Guy Briggs {
1324272ceeaeSRichard Guy Briggs 	const struct audit_ntp_data *ntp = &context->time.ntp_data;
1325272ceeaeSRichard Guy Briggs 	const struct timespec64 *tk = &context->time.tk_injoffset;
1326272ceeaeSRichard Guy Briggs 	static const char * const ntp_name[] = {
1327272ceeaeSRichard Guy Briggs 		"offset",
1328272ceeaeSRichard Guy Briggs 		"freq",
1329272ceeaeSRichard Guy Briggs 		"status",
1330272ceeaeSRichard Guy Briggs 		"tai",
1331272ceeaeSRichard Guy Briggs 		"tick",
1332272ceeaeSRichard Guy Briggs 		"adjust",
1333272ceeaeSRichard Guy Briggs 	};
1334272ceeaeSRichard Guy Briggs 	int type;
1335272ceeaeSRichard Guy Briggs 
1336272ceeaeSRichard Guy Briggs 	if (context->type == AUDIT_TIME_ADJNTPVAL) {
1337272ceeaeSRichard Guy Briggs 		for (type = 0; type < AUDIT_NTP_NVALS; type++) {
1338272ceeaeSRichard Guy Briggs 			if (ntp->vals[type].newval != ntp->vals[type].oldval) {
1339272ceeaeSRichard Guy Briggs 				if (!*ab) {
1340272ceeaeSRichard Guy Briggs 					*ab = audit_log_start(context,
1341272ceeaeSRichard Guy Briggs 							GFP_KERNEL,
1342272ceeaeSRichard Guy Briggs 							AUDIT_TIME_ADJNTPVAL);
1343272ceeaeSRichard Guy Briggs 					if (!*ab)
1344272ceeaeSRichard Guy Briggs 						return;
1345272ceeaeSRichard Guy Briggs 				}
1346272ceeaeSRichard Guy Briggs 				audit_log_format(*ab, "op=%s old=%lli new=%lli",
1347272ceeaeSRichard Guy Briggs 						 ntp_name[type],
1348272ceeaeSRichard Guy Briggs 						 ntp->vals[type].oldval,
1349272ceeaeSRichard Guy Briggs 						 ntp->vals[type].newval);
1350272ceeaeSRichard Guy Briggs 				audit_log_end(*ab);
1351272ceeaeSRichard Guy Briggs 				*ab = NULL;
1352272ceeaeSRichard Guy Briggs 			}
1353272ceeaeSRichard Guy Briggs 		}
1354272ceeaeSRichard Guy Briggs 	}
1355272ceeaeSRichard Guy Briggs 	if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
1356272ceeaeSRichard Guy Briggs 		if (!*ab) {
1357272ceeaeSRichard Guy Briggs 			*ab = audit_log_start(context, GFP_KERNEL,
1358272ceeaeSRichard Guy Briggs 					      AUDIT_TIME_INJOFFSET);
1359272ceeaeSRichard Guy Briggs 			if (!*ab)
1360272ceeaeSRichard Guy Briggs 				return;
1361272ceeaeSRichard Guy Briggs 		}
1362272ceeaeSRichard Guy Briggs 		audit_log_format(*ab, "sec=%lli nsec=%li",
1363272ceeaeSRichard Guy Briggs 				 (long long)tk->tv_sec, tk->tv_nsec);
1364272ceeaeSRichard Guy Briggs 		audit_log_end(*ab);
1365272ceeaeSRichard Guy Briggs 		*ab = NULL;
1366272ceeaeSRichard Guy Briggs 	}
1367272ceeaeSRichard Guy Briggs }
1368272ceeaeSRichard Guy Briggs 
show_special(struct audit_context * context,int * call_panic)1369a33e6751SAl Viro static void show_special(struct audit_context *context, int *call_panic)
1370f3298dc4SAl Viro {
1371f3298dc4SAl Viro 	struct audit_buffer *ab;
1372f3298dc4SAl Viro 	int i;
1373f3298dc4SAl Viro 
1374f3298dc4SAl Viro 	ab = audit_log_start(context, GFP_KERNEL, context->type);
1375f3298dc4SAl Viro 	if (!ab)
1376f3298dc4SAl Viro 		return;
1377f3298dc4SAl Viro 
1378f3298dc4SAl Viro 	switch (context->type) {
1379f3298dc4SAl Viro 	case AUDIT_SOCKETCALL: {
1380f3298dc4SAl Viro 		int nargs = context->socketcall.nargs;
1381254c8b96SRoni Nevalainen 
1382f3298dc4SAl Viro 		audit_log_format(ab, "nargs=%d", nargs);
1383f3298dc4SAl Viro 		for (i = 0; i < nargs; i++)
1384f3298dc4SAl Viro 			audit_log_format(ab, " a%d=%lx", i,
1385f3298dc4SAl Viro 				context->socketcall.args[i]);
1386f3298dc4SAl Viro 		break; }
1387a33e6751SAl Viro 	case AUDIT_IPC: {
1388a33e6751SAl Viro 		u32 osid = context->ipc.osid;
1389a33e6751SAl Viro 
13902570ebbdSAl Viro 		audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho",
1391cca080d9SEric W. Biederman 				 from_kuid(&init_user_ns, context->ipc.uid),
1392cca080d9SEric W. Biederman 				 from_kgid(&init_user_ns, context->ipc.gid),
1393cca080d9SEric W. Biederman 				 context->ipc.mode);
1394a33e6751SAl Viro 		if (osid) {
1395a33e6751SAl Viro 			char *ctx = NULL;
1396a33e6751SAl Viro 			u32 len;
1397254c8b96SRoni Nevalainen 
1398a33e6751SAl Viro 			if (security_secid_to_secctx(osid, &ctx, &len)) {
1399a33e6751SAl Viro 				audit_log_format(ab, " osid=%u", osid);
1400a33e6751SAl Viro 				*call_panic = 1;
1401a33e6751SAl Viro 			} else {
1402a33e6751SAl Viro 				audit_log_format(ab, " obj=%s", ctx);
1403a33e6751SAl Viro 				security_release_secctx(ctx, len);
1404a33e6751SAl Viro 			}
1405a33e6751SAl Viro 		}
1406e816f370SAl Viro 		if (context->ipc.has_perm) {
1407e816f370SAl Viro 			audit_log_end(ab);
1408e816f370SAl Viro 			ab = audit_log_start(context, GFP_KERNEL,
1409e816f370SAl Viro 					     AUDIT_IPC_SET_PERM);
14100644ec0cSKees Cook 			if (unlikely(!ab))
14110644ec0cSKees Cook 				return;
1412e816f370SAl Viro 			audit_log_format(ab,
14132570ebbdSAl Viro 				"qbytes=%lx ouid=%u ogid=%u mode=%#ho",
1414e816f370SAl Viro 				context->ipc.qbytes,
1415e816f370SAl Viro 				context->ipc.perm_uid,
1416e816f370SAl Viro 				context->ipc.perm_gid,
1417e816f370SAl Viro 				context->ipc.perm_mode);
1418e816f370SAl Viro 		}
1419a33e6751SAl Viro 		break; }
1420fe8e52b9SPaul Moore 	case AUDIT_MQ_OPEN:
1421564f6993SAl Viro 		audit_log_format(ab,
1422df0a4283SAl Viro 			"oflag=0x%x mode=%#ho mq_flags=0x%lx mq_maxmsg=%ld "
1423564f6993SAl Viro 			"mq_msgsize=%ld mq_curmsgs=%ld",
1424564f6993SAl Viro 			context->mq_open.oflag, context->mq_open.mode,
1425564f6993SAl Viro 			context->mq_open.attr.mq_flags,
1426564f6993SAl Viro 			context->mq_open.attr.mq_maxmsg,
1427564f6993SAl Viro 			context->mq_open.attr.mq_msgsize,
1428564f6993SAl Viro 			context->mq_open.attr.mq_curmsgs);
1429fe8e52b9SPaul Moore 		break;
1430fe8e52b9SPaul Moore 	case AUDIT_MQ_SENDRECV:
1431c32c8af4SAl Viro 		audit_log_format(ab,
1432c32c8af4SAl Viro 			"mqdes=%d msg_len=%zd msg_prio=%u "
1433b9047726SDeepa Dinamani 			"abs_timeout_sec=%lld abs_timeout_nsec=%ld",
1434c32c8af4SAl Viro 			context->mq_sendrecv.mqdes,
1435c32c8af4SAl Viro 			context->mq_sendrecv.msg_len,
1436c32c8af4SAl Viro 			context->mq_sendrecv.msg_prio,
1437b9047726SDeepa Dinamani 			(long long) context->mq_sendrecv.abs_timeout.tv_sec,
1438c32c8af4SAl Viro 			context->mq_sendrecv.abs_timeout.tv_nsec);
1439fe8e52b9SPaul Moore 		break;
1440fe8e52b9SPaul Moore 	case AUDIT_MQ_NOTIFY:
144120114f71SAl Viro 		audit_log_format(ab, "mqdes=%d sigev_signo=%d",
144220114f71SAl Viro 				context->mq_notify.mqdes,
144320114f71SAl Viro 				context->mq_notify.sigev_signo);
1444fe8e52b9SPaul Moore 		break;
14457392906eSAl Viro 	case AUDIT_MQ_GETSETATTR: {
14467392906eSAl Viro 		struct mq_attr *attr = &context->mq_getsetattr.mqstat;
1447254c8b96SRoni Nevalainen 
14487392906eSAl Viro 		audit_log_format(ab,
14497392906eSAl Viro 			"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
14507392906eSAl Viro 			"mq_curmsgs=%ld ",
14517392906eSAl Viro 			context->mq_getsetattr.mqdes,
14527392906eSAl Viro 			attr->mq_flags, attr->mq_maxmsg,
14537392906eSAl Viro 			attr->mq_msgsize, attr->mq_curmsgs);
14547392906eSAl Viro 		break; }
1455fe8e52b9SPaul Moore 	case AUDIT_CAPSET:
145657f71a0aSAl Viro 		audit_log_format(ab, "pid=%d", context->capset.pid);
145757f71a0aSAl Viro 		audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
145857f71a0aSAl Viro 		audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
145957f71a0aSAl Viro 		audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
14607786f6b6SRichard Guy Briggs 		audit_log_cap(ab, "cap_pa", &context->capset.cap.ambient);
1461fe8e52b9SPaul Moore 		break;
1462fe8e52b9SPaul Moore 	case AUDIT_MMAP:
1463120a795dSAl Viro 		audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
1464120a795dSAl Viro 				 context->mmap.flags);
1465fe8e52b9SPaul Moore 		break;
1466571e5c0eSRichard Guy Briggs 	case AUDIT_OPENAT2:
1467571e5c0eSRichard Guy Briggs 		audit_log_format(ab, "oflag=0%llo mode=0%llo resolve=0x%llx",
1468571e5c0eSRichard Guy Briggs 				 context->openat2.flags,
1469571e5c0eSRichard Guy Briggs 				 context->openat2.mode,
1470571e5c0eSRichard Guy Briggs 				 context->openat2.resolve);
1471571e5c0eSRichard Guy Briggs 		break;
1472fe8e52b9SPaul Moore 	case AUDIT_EXECVE:
1473d9cfea91SRichard Guy Briggs 		audit_log_execve_info(context, &ab);
1474fe8e52b9SPaul Moore 		break;
1475ca86cad7SRichard Guy Briggs 	case AUDIT_KERN_MODULE:
1476ca86cad7SRichard Guy Briggs 		audit_log_format(ab, "name=");
1477b305f7edSYi Wang 		if (context->module.name) {
1478ca86cad7SRichard Guy Briggs 			audit_log_untrustedstring(ab, context->module.name);
1479b305f7edSYi Wang 		} else
1480b305f7edSYi Wang 			audit_log_format(ab, "(null)");
1481b305f7edSYi Wang 
1482ca86cad7SRichard Guy Briggs 		break;
1483272ceeaeSRichard Guy Briggs 	case AUDIT_TIME_ADJNTPVAL:
1484272ceeaeSRichard Guy Briggs 	case AUDIT_TIME_INJOFFSET:
1485272ceeaeSRichard Guy Briggs 		/* this call deviates from the rest, eating the buffer */
1486272ceeaeSRichard Guy Briggs 		audit_log_time(context, &ab);
1487272ceeaeSRichard Guy Briggs 		break;
1488f3298dc4SAl Viro 	}
1489f3298dc4SAl Viro 	audit_log_end(ab);
1490f3298dc4SAl Viro }
1491f3298dc4SAl Viro 
audit_proctitle_rtrim(char * proctitle,int len)14923f1c8250SWilliam Roberts static inline int audit_proctitle_rtrim(char *proctitle, int len)
14933f1c8250SWilliam Roberts {
14943f1c8250SWilliam Roberts 	char *end = proctitle + len - 1;
1495254c8b96SRoni Nevalainen 
14963f1c8250SWilliam Roberts 	while (end > proctitle && !isprint(*end))
14973f1c8250SWilliam Roberts 		end--;
14983f1c8250SWilliam Roberts 
14993f1c8250SWilliam Roberts 	/* catch the case where proctitle is only 1 non-print character */
15003f1c8250SWilliam Roberts 	len = end - proctitle + 1;
15013f1c8250SWilliam Roberts 	len -= isprint(proctitle[len-1]) == 0;
15023f1c8250SWilliam Roberts 	return len;
15033f1c8250SWilliam Roberts }
15043f1c8250SWilliam Roberts 
15055f3d544fSRichard Guy Briggs /*
15065f3d544fSRichard Guy Briggs  * audit_log_name - produce AUDIT_PATH record from struct audit_names
15075f3d544fSRichard Guy Briggs  * @context: audit_context for the task
15085f3d544fSRichard Guy Briggs  * @n: audit_names structure with reportable details
15095f3d544fSRichard Guy Briggs  * @path: optional path to report instead of audit_names->name
15105f3d544fSRichard Guy Briggs  * @record_num: record number to report when handling a list of names
15115f3d544fSRichard Guy Briggs  * @call_panic: optional pointer to int that will be updated if secid fails
15125f3d544fSRichard Guy Briggs  */
audit_log_name(struct audit_context * context,struct audit_names * n,const struct path * path,int record_num,int * call_panic)15135f3d544fSRichard Guy Briggs static void audit_log_name(struct audit_context *context, struct audit_names *n,
15145f3d544fSRichard Guy Briggs 		    const struct path *path, int record_num, int *call_panic)
15155f3d544fSRichard Guy Briggs {
15165f3d544fSRichard Guy Briggs 	struct audit_buffer *ab;
15175f3d544fSRichard Guy Briggs 
15185f3d544fSRichard Guy Briggs 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
15195f3d544fSRichard Guy Briggs 	if (!ab)
15205f3d544fSRichard Guy Briggs 		return;
15215f3d544fSRichard Guy Briggs 
15225f3d544fSRichard Guy Briggs 	audit_log_format(ab, "item=%d", record_num);
15235f3d544fSRichard Guy Briggs 
15245f3d544fSRichard Guy Briggs 	if (path)
15255f3d544fSRichard Guy Briggs 		audit_log_d_path(ab, " name=", path);
15265f3d544fSRichard Guy Briggs 	else if (n->name) {
15275f3d544fSRichard Guy Briggs 		switch (n->name_len) {
15285f3d544fSRichard Guy Briggs 		case AUDIT_NAME_FULL:
15295f3d544fSRichard Guy Briggs 			/* log the full path */
15305f3d544fSRichard Guy Briggs 			audit_log_format(ab, " name=");
15315f3d544fSRichard Guy Briggs 			audit_log_untrustedstring(ab, n->name->name);
15325f3d544fSRichard Guy Briggs 			break;
15335f3d544fSRichard Guy Briggs 		case 0:
15345f3d544fSRichard Guy Briggs 			/* name was specified as a relative path and the
15355f3d544fSRichard Guy Briggs 			 * directory component is the cwd
15365f3d544fSRichard Guy Briggs 			 */
15376d915476SRichard Guy Briggs 			if (context->pwd.dentry && context->pwd.mnt)
15385f3d544fSRichard Guy Briggs 				audit_log_d_path(ab, " name=", &context->pwd);
15396d915476SRichard Guy Briggs 			else
15406d915476SRichard Guy Briggs 				audit_log_format(ab, " name=(null)");
15415f3d544fSRichard Guy Briggs 			break;
15425f3d544fSRichard Guy Briggs 		default:
15435f3d544fSRichard Guy Briggs 			/* log the name's directory component */
15445f3d544fSRichard Guy Briggs 			audit_log_format(ab, " name=");
15455f3d544fSRichard Guy Briggs 			audit_log_n_untrustedstring(ab, n->name->name,
15465f3d544fSRichard Guy Briggs 						    n->name_len);
15475f3d544fSRichard Guy Briggs 		}
15485f3d544fSRichard Guy Briggs 	} else
15495f3d544fSRichard Guy Briggs 		audit_log_format(ab, " name=(null)");
15505f3d544fSRichard Guy Briggs 
15515f3d544fSRichard Guy Briggs 	if (n->ino != AUDIT_INO_UNSET)
15525f3d544fSRichard Guy Briggs 		audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x",
15535f3d544fSRichard Guy Briggs 				 n->ino,
15545f3d544fSRichard Guy Briggs 				 MAJOR(n->dev),
15555f3d544fSRichard Guy Briggs 				 MINOR(n->dev),
15565f3d544fSRichard Guy Briggs 				 n->mode,
15575f3d544fSRichard Guy Briggs 				 from_kuid(&init_user_ns, n->uid),
15585f3d544fSRichard Guy Briggs 				 from_kgid(&init_user_ns, n->gid),
15595f3d544fSRichard Guy Briggs 				 MAJOR(n->rdev),
15605f3d544fSRichard Guy Briggs 				 MINOR(n->rdev));
15615f3d544fSRichard Guy Briggs 	if (n->osid != 0) {
15625f3d544fSRichard Guy Briggs 		char *ctx = NULL;
15635f3d544fSRichard Guy Briggs 		u32 len;
15645f3d544fSRichard Guy Briggs 
15655f3d544fSRichard Guy Briggs 		if (security_secid_to_secctx(
15665f3d544fSRichard Guy Briggs 			n->osid, &ctx, &len)) {
15675f3d544fSRichard Guy Briggs 			audit_log_format(ab, " osid=%u", n->osid);
15685f3d544fSRichard Guy Briggs 			if (call_panic)
15695f3d544fSRichard Guy Briggs 				*call_panic = 2;
15705f3d544fSRichard Guy Briggs 		} else {
15715f3d544fSRichard Guy Briggs 			audit_log_format(ab, " obj=%s", ctx);
15725f3d544fSRichard Guy Briggs 			security_release_secctx(ctx, len);
15735f3d544fSRichard Guy Briggs 		}
15745f3d544fSRichard Guy Briggs 	}
15755f3d544fSRichard Guy Briggs 
15765f3d544fSRichard Guy Briggs 	/* log the audit_names record type */
15775f3d544fSRichard Guy Briggs 	switch (n->type) {
15785f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_NORMAL:
15795f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=NORMAL");
15805f3d544fSRichard Guy Briggs 		break;
15815f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_PARENT:
15825f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=PARENT");
15835f3d544fSRichard Guy Briggs 		break;
15845f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_CHILD_DELETE:
15855f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=DELETE");
15865f3d544fSRichard Guy Briggs 		break;
15875f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_CHILD_CREATE:
15885f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=CREATE");
15895f3d544fSRichard Guy Briggs 		break;
15905f3d544fSRichard Guy Briggs 	default:
15915f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=UNKNOWN");
15925f3d544fSRichard Guy Briggs 		break;
15935f3d544fSRichard Guy Briggs 	}
15945f3d544fSRichard Guy Briggs 
15955f3d544fSRichard Guy Briggs 	audit_log_fcaps(ab, n);
15965f3d544fSRichard Guy Briggs 	audit_log_end(ab);
15975f3d544fSRichard Guy Briggs }
15985f3d544fSRichard Guy Briggs 
audit_log_proctitle(void)15992a1fe215SPaul Moore static void audit_log_proctitle(void)
16003f1c8250SWilliam Roberts {
16013f1c8250SWilliam Roberts 	int res;
16023f1c8250SWilliam Roberts 	char *buf;
16033f1c8250SWilliam Roberts 	char *msg = "(null)";
16043f1c8250SWilliam Roberts 	int len = strlen(msg);
16052a1fe215SPaul Moore 	struct audit_context *context = audit_context();
16063f1c8250SWilliam Roberts 	struct audit_buffer *ab;
16073f1c8250SWilliam Roberts 
16083f1c8250SWilliam Roberts 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
16093f1c8250SWilliam Roberts 	if (!ab)
16103f1c8250SWilliam Roberts 		return;	/* audit_panic or being filtered */
16113f1c8250SWilliam Roberts 
16123f1c8250SWilliam Roberts 	audit_log_format(ab, "proctitle=");
16133f1c8250SWilliam Roberts 
16143f1c8250SWilliam Roberts 	/* Not  cached */
16153f1c8250SWilliam Roberts 	if (!context->proctitle.value) {
16163f1c8250SWilliam Roberts 		buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL);
16173f1c8250SWilliam Roberts 		if (!buf)
16183f1c8250SWilliam Roberts 			goto out;
16193f1c8250SWilliam Roberts 		/* Historically called this from procfs naming */
16202a1fe215SPaul Moore 		res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN);
16213f1c8250SWilliam Roberts 		if (res == 0) {
16223f1c8250SWilliam Roberts 			kfree(buf);
16233f1c8250SWilliam Roberts 			goto out;
16243f1c8250SWilliam Roberts 		}
16253f1c8250SWilliam Roberts 		res = audit_proctitle_rtrim(buf, res);
16263f1c8250SWilliam Roberts 		if (res == 0) {
16273f1c8250SWilliam Roberts 			kfree(buf);
16283f1c8250SWilliam Roberts 			goto out;
16293f1c8250SWilliam Roberts 		}
16303f1c8250SWilliam Roberts 		context->proctitle.value = buf;
16313f1c8250SWilliam Roberts 		context->proctitle.len = res;
16323f1c8250SWilliam Roberts 	}
16333f1c8250SWilliam Roberts 	msg = context->proctitle.value;
16343f1c8250SWilliam Roberts 	len = context->proctitle.len;
16353f1c8250SWilliam Roberts out:
16363f1c8250SWilliam Roberts 	audit_log_n_untrustedstring(ab, msg, len);
16373f1c8250SWilliam Roberts 	audit_log_end(ab);
16383f1c8250SWilliam Roberts }
16393f1c8250SWilliam Roberts 
16405bd2182dSPaul Moore /**
16415bd2182dSPaul Moore  * audit_log_uring - generate a AUDIT_URINGOP record
16425bd2182dSPaul Moore  * @ctx: the audit context
16435bd2182dSPaul Moore  */
audit_log_uring(struct audit_context * ctx)16445bd2182dSPaul Moore static void audit_log_uring(struct audit_context *ctx)
16455bd2182dSPaul Moore {
16465bd2182dSPaul Moore 	struct audit_buffer *ab;
16475bd2182dSPaul Moore 	const struct cred *cred;
16485bd2182dSPaul Moore 
16495bd2182dSPaul Moore 	ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_URINGOP);
16505bd2182dSPaul Moore 	if (!ab)
16515bd2182dSPaul Moore 		return;
16525bd2182dSPaul Moore 	cred = current_cred();
16535bd2182dSPaul Moore 	audit_log_format(ab, "uring_op=%d", ctx->uring_op);
16545bd2182dSPaul Moore 	if (ctx->return_valid != AUDITSC_INVALID)
16555bd2182dSPaul Moore 		audit_log_format(ab, " success=%s exit=%ld",
16565bd2182dSPaul Moore 				 (ctx->return_valid == AUDITSC_SUCCESS ?
16575bd2182dSPaul Moore 				  "yes" : "no"),
16585bd2182dSPaul Moore 				 ctx->return_code);
16595bd2182dSPaul Moore 	audit_log_format(ab,
16605bd2182dSPaul Moore 			 " items=%d"
16615bd2182dSPaul Moore 			 " ppid=%d pid=%d uid=%u gid=%u euid=%u suid=%u"
16625bd2182dSPaul Moore 			 " fsuid=%u egid=%u sgid=%u fsgid=%u",
16635bd2182dSPaul Moore 			 ctx->name_count,
16645bd2182dSPaul Moore 			 task_ppid_nr(current), task_tgid_nr(current),
16655bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->uid),
16665bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->gid),
16675bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->euid),
16685bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->suid),
16695bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->fsuid),
16705bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->egid),
16715bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->sgid),
16725bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->fsgid));
16735bd2182dSPaul Moore 	audit_log_task_context(ab);
16745bd2182dSPaul Moore 	audit_log_key(ab, ctx->filterkey);
16755bd2182dSPaul Moore 	audit_log_end(ab);
16765bd2182dSPaul Moore }
16775bd2182dSPaul Moore 
audit_log_exit(void)16782a1fe215SPaul Moore static void audit_log_exit(void)
16791da177e4SLinus Torvalds {
16809c7aa6aaSSteve Grubb 	int i, call_panic = 0;
16812a1fe215SPaul Moore 	struct audit_context *context = audit_context();
16821da177e4SLinus Torvalds 	struct audit_buffer *ab;
16837551ced3SDavid Woodhouse 	struct audit_aux_data *aux;
16845195d8e2SEric Paris 	struct audit_names *n;
16851da177e4SLinus Torvalds 
16862a1fe215SPaul Moore 	context->personality = current->personality;
1687e495149bSAl Viro 
168812c5e81dSPaul Moore 	switch (context->context) {
168912c5e81dSPaul Moore 	case AUDIT_CTX_SYSCALL:
1690e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
16911da177e4SLinus Torvalds 		if (!ab)
169212c5e81dSPaul Moore 			return;
1693bccf6ae0SDavid Woodhouse 		audit_log_format(ab, "arch=%x syscall=%d",
1694bccf6ae0SDavid Woodhouse 				 context->arch, context->major);
16951da177e4SLinus Torvalds 		if (context->personality != PER_LINUX)
16961da177e4SLinus Torvalds 			audit_log_format(ab, " per=%lx", context->personality);
1697ba59eae7SAlex Shi 		if (context->return_valid != AUDITSC_INVALID)
16982fd6f58bS 			audit_log_format(ab, " success=%s exit=%ld",
169912c5e81dSPaul Moore 					 (context->return_valid == AUDITSC_SUCCESS ?
170012c5e81dSPaul Moore 					  "yes" : "no"),
17012fd6f58bS 					 context->return_code);
17021da177e4SLinus Torvalds 		audit_log_format(ab,
1703e23eb920SPeter Moody 				 " a0=%lx a1=%lx a2=%lx a3=%lx items=%d",
17041da177e4SLinus Torvalds 				 context->argv[0],
17051da177e4SLinus Torvalds 				 context->argv[1],
17061da177e4SLinus Torvalds 				 context->argv[2],
17071da177e4SLinus Torvalds 				 context->argv[3],
1708e23eb920SPeter Moody 				 context->name_count);
17092a1fe215SPaul Moore 		audit_log_task_info(ab);
17109d960985SEric Paris 		audit_log_key(ab, context->filterkey);
17111da177e4SLinus Torvalds 		audit_log_end(ab);
171212c5e81dSPaul Moore 		break;
17135bd2182dSPaul Moore 	case AUDIT_CTX_URING:
17145bd2182dSPaul Moore 		audit_log_uring(context);
17155bd2182dSPaul Moore 		break;
171612c5e81dSPaul Moore 	default:
171712c5e81dSPaul Moore 		BUG();
171812c5e81dSPaul Moore 		break;
171912c5e81dSPaul Moore 	}
17201da177e4SLinus Torvalds 
17217551ced3SDavid Woodhouse 	for (aux = context->aux; aux; aux = aux->next) {
1722c0404993SSteve Grubb 
1723e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, aux->type);
17241da177e4SLinus Torvalds 		if (!ab)
17251da177e4SLinus Torvalds 			continue; /* audit_panic has been called */
17261da177e4SLinus Torvalds 
17271da177e4SLinus Torvalds 		switch (aux->type) {
172820ca73bcSGeorge C. Wilson 
17293fc689e9SEric Paris 		case AUDIT_BPRM_FCAPS: {
17303fc689e9SEric Paris 			struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
1731254c8b96SRoni Nevalainen 
17323fc689e9SEric Paris 			audit_log_format(ab, "fver=%x", axs->fcap_ver);
17333fc689e9SEric Paris 			audit_log_cap(ab, "fp", &axs->fcap.permitted);
17343fc689e9SEric Paris 			audit_log_cap(ab, "fi", &axs->fcap.inheritable);
17353fc689e9SEric Paris 			audit_log_format(ab, " fe=%d", axs->fcap.fE);
17363fc689e9SEric Paris 			audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
17373fc689e9SEric Paris 			audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
17383fc689e9SEric Paris 			audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
17397786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "old_pa", &axs->old_pcap.ambient);
17407786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pp", &axs->new_pcap.permitted);
17417786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pi", &axs->new_pcap.inheritable);
17427786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pe", &axs->new_pcap.effective);
17437786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pa", &axs->new_pcap.ambient);
17442fec30e2SRichard Guy Briggs 			audit_log_format(ab, " frootid=%d",
17452fec30e2SRichard Guy Briggs 					 from_kuid(&init_user_ns,
17462fec30e2SRichard Guy Briggs 						   axs->fcap.rootid));
17473fc689e9SEric Paris 			break; }
17483fc689e9SEric Paris 
17491da177e4SLinus Torvalds 		}
17501da177e4SLinus Torvalds 		audit_log_end(ab);
17511da177e4SLinus Torvalds 	}
17521da177e4SLinus Torvalds 
1753f3298dc4SAl Viro 	if (context->type)
1754a33e6751SAl Viro 		show_special(context, &call_panic);
1755f3298dc4SAl Viro 
1756157cf649SAl Viro 	if (context->fds[0] >= 0) {
1757157cf649SAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR);
1758157cf649SAl Viro 		if (ab) {
1759157cf649SAl Viro 			audit_log_format(ab, "fd0=%d fd1=%d",
1760157cf649SAl Viro 					context->fds[0], context->fds[1]);
1761157cf649SAl Viro 			audit_log_end(ab);
1762157cf649SAl Viro 		}
1763157cf649SAl Viro 	}
1764157cf649SAl Viro 
17654f6b434fSAl Viro 	if (context->sockaddr_len) {
17664f6b434fSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR);
17674f6b434fSAl Viro 		if (ab) {
17684f6b434fSAl Viro 			audit_log_format(ab, "saddr=");
17694f6b434fSAl Viro 			audit_log_n_hex(ab, (void *)context->sockaddr,
17704f6b434fSAl Viro 					context->sockaddr_len);
17714f6b434fSAl Viro 			audit_log_end(ab);
17724f6b434fSAl Viro 		}
17734f6b434fSAl Viro 	}
17744f6b434fSAl Viro 
1775e54dc243SAmy Griffis 	for (aux = context->aux_pids; aux; aux = aux->next) {
1776e54dc243SAmy Griffis 		struct audit_aux_data_pids *axs = (void *)aux;
1777e54dc243SAmy Griffis 
1778e54dc243SAmy Griffis 		for (i = 0; i < axs->pid_count; i++)
1779e54dc243SAmy Griffis 			if (audit_log_pid_context(context, axs->target_pid[i],
1780c2a7780eSEric Paris 						  axs->target_auid[i],
1781c2a7780eSEric Paris 						  axs->target_uid[i],
17824746ec5bSEric Paris 						  axs->target_sessionid[i],
1783c2a7780eSEric Paris 						  axs->target_sid[i],
1784c2a7780eSEric Paris 						  axs->target_comm[i]))
1785e54dc243SAmy Griffis 				call_panic = 1;
1786a5cb013dSAl Viro 	}
1787e54dc243SAmy Griffis 
1788e54dc243SAmy Griffis 	if (context->target_pid &&
1789e54dc243SAmy Griffis 	    audit_log_pid_context(context, context->target_pid,
1790c2a7780eSEric Paris 				  context->target_auid, context->target_uid,
17914746ec5bSEric Paris 				  context->target_sessionid,
1792c2a7780eSEric Paris 				  context->target_sid, context->target_comm))
1793e54dc243SAmy Griffis 			call_panic = 1;
1794a5cb013dSAl Viro 
179544707fdfSJan Blunck 	if (context->pwd.dentry && context->pwd.mnt) {
1796e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
17978f37d47cSDavid Woodhouse 		if (ab) {
179844707fdfSJan Blunck 			audit_log_d_path(ab, "cwd=", &context->pwd);
17998f37d47cSDavid Woodhouse 			audit_log_end(ab);
18008f37d47cSDavid Woodhouse 		}
18018f37d47cSDavid Woodhouse 	}
180273241cccSAmy Griffis 
18035195d8e2SEric Paris 	i = 0;
180479f6530cSJeff Layton 	list_for_each_entry(n, &context->names_list, list) {
180579f6530cSJeff Layton 		if (n->hidden)
180679f6530cSJeff Layton 			continue;
1807b24a30a7SEric Paris 		audit_log_name(context, n, NULL, i++, &call_panic);
180879f6530cSJeff Layton 	}
1809c0641f28SEric Paris 
181012c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_SYSCALL)
18112a1fe215SPaul Moore 		audit_log_proctitle();
18123f1c8250SWilliam Roberts 
1813c0641f28SEric Paris 	/* Send end of event record to help user space know we are finished */
1814c0641f28SEric Paris 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
1815c0641f28SEric Paris 	if (ab)
1816c0641f28SEric Paris 		audit_log_end(ab);
18171b50eed9SSteve Grubb 	if (call_panic)
181812c5e81dSPaul Moore 		audit_panic("error in audit_log_exit()");
18191da177e4SLinus Torvalds }
18201da177e4SLinus Torvalds 
1821b0dd25a8SRandy Dunlap /**
1822196a5085SGeliang Tang  * __audit_free - free a per-task audit context
1823b0dd25a8SRandy Dunlap  * @tsk: task whose audit context block to free
1824b0dd25a8SRandy Dunlap  *
182567daf270SPaul Moore  * Called from copy_process, do_exit, and the io_uring code
1826b0dd25a8SRandy Dunlap  */
__audit_free(struct task_struct * tsk)1827a4ff8dbaSEric Paris void __audit_free(struct task_struct *tsk)
18281da177e4SLinus Torvalds {
18292a1fe215SPaul Moore 	struct audit_context *context = tsk->audit_context;
18301da177e4SLinus Torvalds 
183156179a6eSEric Paris 	if (!context)
18321da177e4SLinus Torvalds 		return;
18331da177e4SLinus Torvalds 
183412c5e81dSPaul Moore 	/* this may generate CONFIG_CHANGE records */
18359e36a5d4SRichard Guy Briggs 	if (!list_empty(&context->killed_trees))
18369e36a5d4SRichard Guy Briggs 		audit_kill_trees(context);
18379e36a5d4SRichard Guy Briggs 
18382a1fe215SPaul Moore 	/* We are called either by do_exit() or the fork() error handling code;
18392a1fe215SPaul Moore 	 * in the former case tsk == current and in the latter tsk is a
18400351dc57SJilin Yuan 	 * random task_struct that doesn't have any meaningful data we
18412a1fe215SPaul Moore 	 * need to log via audit_log_exit().
18422a1fe215SPaul Moore 	 */
184367daf270SPaul Moore 	if (tsk == current && !context->dummy) {
1844ba59eae7SAlex Shi 		context->return_valid = AUDITSC_INVALID;
18452a1fe215SPaul Moore 		context->return_code = 0;
184667daf270SPaul Moore 		if (context->context == AUDIT_CTX_SYSCALL) {
18475504a69aSRichard Guy Briggs 			audit_filter_syscall(tsk, context);
18482a1fe215SPaul Moore 			audit_filter_inodes(tsk, context);
1849619ed58aSSergey Nazarov 			if (context->current_state == AUDIT_STATE_RECORD)
18502a1fe215SPaul Moore 				audit_log_exit();
185167daf270SPaul Moore 		} else if (context->context == AUDIT_CTX_URING) {
185267daf270SPaul Moore 			/* TODO: verify this case is real and valid */
185367daf270SPaul Moore 			audit_filter_uring(tsk, context);
185467daf270SPaul Moore 			audit_filter_inodes(tsk, context);
185567daf270SPaul Moore 			if (context->current_state == AUDIT_STATE_RECORD)
185667daf270SPaul Moore 				audit_log_uring(context);
185767daf270SPaul Moore 		}
18582a1fe215SPaul Moore 	}
18592a1fe215SPaul Moore 
18602a1fe215SPaul Moore 	audit_set_context(tsk, NULL);
18611da177e4SLinus Torvalds 	audit_free_context(context);
18621da177e4SLinus Torvalds }
18631da177e4SLinus Torvalds 
1864b0dd25a8SRandy Dunlap /**
186512c5e81dSPaul Moore  * audit_return_fixup - fixup the return codes in the audit_context
186612c5e81dSPaul Moore  * @ctx: the audit_context
186712c5e81dSPaul Moore  * @success: true/false value to indicate if the operation succeeded or not
186812c5e81dSPaul Moore  * @code: operation return code
186912c5e81dSPaul Moore  *
187012c5e81dSPaul Moore  * We need to fixup the return code in the audit logs if the actual return
187112c5e81dSPaul Moore  * codes are later going to be fixed by the arch specific signal handlers.
187212c5e81dSPaul Moore  */
audit_return_fixup(struct audit_context * ctx,int success,long code)187312c5e81dSPaul Moore static void audit_return_fixup(struct audit_context *ctx,
187412c5e81dSPaul Moore 			       int success, long code)
187512c5e81dSPaul Moore {
187612c5e81dSPaul Moore 	/*
187712c5e81dSPaul Moore 	 * This is actually a test for:
187812c5e81dSPaul Moore 	 * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
187912c5e81dSPaul Moore 	 * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
188012c5e81dSPaul Moore 	 *
188112c5e81dSPaul Moore 	 * but is faster than a bunch of ||
188212c5e81dSPaul Moore 	 */
188312c5e81dSPaul Moore 	if (unlikely(code <= -ERESTARTSYS) &&
188412c5e81dSPaul Moore 	    (code >= -ERESTART_RESTARTBLOCK) &&
188512c5e81dSPaul Moore 	    (code != -ENOIOCTLCMD))
188612c5e81dSPaul Moore 		ctx->return_code = -EINTR;
188712c5e81dSPaul Moore 	else
188812c5e81dSPaul Moore 		ctx->return_code  = code;
188912c5e81dSPaul Moore 	ctx->return_valid = (success ? AUDITSC_SUCCESS : AUDITSC_FAILURE);
189012c5e81dSPaul Moore }
189112c5e81dSPaul Moore 
189212c5e81dSPaul Moore /**
18935bd2182dSPaul Moore  * __audit_uring_entry - prepare the kernel task's audit context for io_uring
18945bd2182dSPaul Moore  * @op: the io_uring opcode
18955bd2182dSPaul Moore  *
18965bd2182dSPaul Moore  * This is similar to audit_syscall_entry() but is intended for use by io_uring
18975bd2182dSPaul Moore  * operations.  This function should only ever be called from
18985bd2182dSPaul Moore  * audit_uring_entry() as we rely on the audit context checking present in that
18995bd2182dSPaul Moore  * function.
19005bd2182dSPaul Moore  */
__audit_uring_entry(u8 op)19015bd2182dSPaul Moore void __audit_uring_entry(u8 op)
19025bd2182dSPaul Moore {
19035bd2182dSPaul Moore 	struct audit_context *ctx = audit_context();
19045bd2182dSPaul Moore 
19055bd2182dSPaul Moore 	if (ctx->state == AUDIT_STATE_DISABLED)
19065bd2182dSPaul Moore 		return;
19075bd2182dSPaul Moore 
19085bd2182dSPaul Moore 	/*
19095bd2182dSPaul Moore 	 * NOTE: It's possible that we can be called from the process' context
19105bd2182dSPaul Moore 	 *       before it returns to userspace, and before audit_syscall_exit()
19115bd2182dSPaul Moore 	 *       is called.  In this case there is not much to do, just record
19125bd2182dSPaul Moore 	 *       the io_uring details and return.
19135bd2182dSPaul Moore 	 */
19145bd2182dSPaul Moore 	ctx->uring_op = op;
19155bd2182dSPaul Moore 	if (ctx->context == AUDIT_CTX_SYSCALL)
19165bd2182dSPaul Moore 		return;
19175bd2182dSPaul Moore 
19185bd2182dSPaul Moore 	ctx->dummy = !audit_n_rules;
19195bd2182dSPaul Moore 	if (!ctx->dummy && ctx->state == AUDIT_STATE_BUILD)
19205bd2182dSPaul Moore 		ctx->prio = 0;
19215bd2182dSPaul Moore 
19225bd2182dSPaul Moore 	ctx->context = AUDIT_CTX_URING;
19235bd2182dSPaul Moore 	ctx->current_state = ctx->state;
19245bd2182dSPaul Moore 	ktime_get_coarse_real_ts64(&ctx->ctime);
19255bd2182dSPaul Moore }
19265bd2182dSPaul Moore 
19275bd2182dSPaul Moore /**
19285bd2182dSPaul Moore  * __audit_uring_exit - wrap up the kernel task's audit context after io_uring
19295bd2182dSPaul Moore  * @success: true/false value to indicate if the operation succeeded or not
19305bd2182dSPaul Moore  * @code: operation return code
19315bd2182dSPaul Moore  *
19325bd2182dSPaul Moore  * This is similar to audit_syscall_exit() but is intended for use by io_uring
19335bd2182dSPaul Moore  * operations.  This function should only ever be called from
19345bd2182dSPaul Moore  * audit_uring_exit() as we rely on the audit context checking present in that
19355bd2182dSPaul Moore  * function.
19365bd2182dSPaul Moore  */
__audit_uring_exit(int success,long code)19375bd2182dSPaul Moore void __audit_uring_exit(int success, long code)
19385bd2182dSPaul Moore {
19395bd2182dSPaul Moore 	struct audit_context *ctx = audit_context();
19405bd2182dSPaul Moore 
194169e9cd66SJulian Orth 	if (ctx->dummy) {
194269e9cd66SJulian Orth 		if (ctx->context != AUDIT_CTX_URING)
194369e9cd66SJulian Orth 			return;
194469e9cd66SJulian Orth 		goto out;
194569e9cd66SJulian Orth 	}
194669e9cd66SJulian Orth 
1947d4fefa48SRichard Guy Briggs 	audit_return_fixup(ctx, success, code);
19485bd2182dSPaul Moore 	if (ctx->context == AUDIT_CTX_SYSCALL) {
19495bd2182dSPaul Moore 		/*
19505bd2182dSPaul Moore 		 * NOTE: See the note in __audit_uring_entry() about the case
19515bd2182dSPaul Moore 		 *       where we may be called from process context before we
19525bd2182dSPaul Moore 		 *       return to userspace via audit_syscall_exit().  In this
19535bd2182dSPaul Moore 		 *       case we simply emit a URINGOP record and bail, the
19545bd2182dSPaul Moore 		 *       normal syscall exit handling will take care of
19555bd2182dSPaul Moore 		 *       everything else.
19565bd2182dSPaul Moore 		 *       It is also worth mentioning that when we are called,
19575bd2182dSPaul Moore 		 *       the current process creds may differ from the creds
19585bd2182dSPaul Moore 		 *       used during the normal syscall processing; keep that
19595bd2182dSPaul Moore 		 *       in mind if/when we move the record generation code.
19605bd2182dSPaul Moore 		 */
19615bd2182dSPaul Moore 
19625bd2182dSPaul Moore 		/*
19635bd2182dSPaul Moore 		 * We need to filter on the syscall info here to decide if we
19645bd2182dSPaul Moore 		 * should emit a URINGOP record.  I know it seems odd but this
19655bd2182dSPaul Moore 		 * solves the problem where users have a filter to block *all*
19665bd2182dSPaul Moore 		 * syscall records in the "exit" filter; we want to preserve
19675bd2182dSPaul Moore 		 * the behavior here.
19685bd2182dSPaul Moore 		 */
19695bd2182dSPaul Moore 		audit_filter_syscall(current, ctx);
197067daf270SPaul Moore 		if (ctx->current_state != AUDIT_STATE_RECORD)
197167daf270SPaul Moore 			audit_filter_uring(current, ctx);
19725bd2182dSPaul Moore 		audit_filter_inodes(current, ctx);
19735bd2182dSPaul Moore 		if (ctx->current_state != AUDIT_STATE_RECORD)
19745bd2182dSPaul Moore 			return;
19755bd2182dSPaul Moore 
19765bd2182dSPaul Moore 		audit_log_uring(ctx);
19775bd2182dSPaul Moore 		return;
19785bd2182dSPaul Moore 	}
19795bd2182dSPaul Moore 
19805bd2182dSPaul Moore 	/* this may generate CONFIG_CHANGE records */
19815bd2182dSPaul Moore 	if (!list_empty(&ctx->killed_trees))
19825bd2182dSPaul Moore 		audit_kill_trees(ctx);
19835bd2182dSPaul Moore 
198467daf270SPaul Moore 	/* run through both filters to ensure we set the filterkey properly */
198567daf270SPaul Moore 	audit_filter_uring(current, ctx);
19865bd2182dSPaul Moore 	audit_filter_inodes(current, ctx);
19875bd2182dSPaul Moore 	if (ctx->current_state != AUDIT_STATE_RECORD)
19885bd2182dSPaul Moore 		goto out;
19895bd2182dSPaul Moore 	audit_log_exit();
19905bd2182dSPaul Moore 
19915bd2182dSPaul Moore out:
19925bd2182dSPaul Moore 	audit_reset_context(ctx);
19935bd2182dSPaul Moore }
19945bd2182dSPaul Moore 
19955bd2182dSPaul Moore /**
1996196a5085SGeliang Tang  * __audit_syscall_entry - fill in an audit record at syscall entry
1997b0dd25a8SRandy Dunlap  * @major: major syscall type (function)
1998b0dd25a8SRandy Dunlap  * @a1: additional syscall register 1
1999b0dd25a8SRandy Dunlap  * @a2: additional syscall register 2
2000b0dd25a8SRandy Dunlap  * @a3: additional syscall register 3
2001b0dd25a8SRandy Dunlap  * @a4: additional syscall register 4
2002b0dd25a8SRandy Dunlap  *
2003b0dd25a8SRandy Dunlap  * Fill in audit context at syscall entry.  This only happens if the
20041da177e4SLinus Torvalds  * audit context was created when the task was created and the state or
20051da177e4SLinus Torvalds  * filters demand the audit context be built.  If the state from the
2006619ed58aSSergey Nazarov  * per-task filter or from the per-syscall filter is AUDIT_STATE_RECORD,
20071da177e4SLinus Torvalds  * then the record will be written at syscall exit time (otherwise, it
20081da177e4SLinus Torvalds  * will only be written if another part of the kernel requests that it
2009b0dd25a8SRandy Dunlap  * be written).
2010b0dd25a8SRandy Dunlap  */
__audit_syscall_entry(int major,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4)2011b4f0d375SRichard Guy Briggs void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
20121da177e4SLinus Torvalds 			   unsigned long a3, unsigned long a4)
20131da177e4SLinus Torvalds {
2014cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
20151da177e4SLinus Torvalds 	enum audit_state     state;
20161da177e4SLinus Torvalds 
201794d14e3eSRichard Guy Briggs 	if (!audit_enabled || !context)
201886a1c34aSRoland McGrath 		return;
20191da177e4SLinus Torvalds 
202012c5e81dSPaul Moore 	WARN_ON(context->context != AUDIT_CTX_UNUSED);
202112c5e81dSPaul Moore 	WARN_ON(context->name_count);
202212c5e81dSPaul Moore 	if (context->context != AUDIT_CTX_UNUSED || context->name_count) {
202312c5e81dSPaul Moore 		audit_panic("unrecoverable error in audit_syscall_entry()");
202412c5e81dSPaul Moore 		return;
202512c5e81dSPaul Moore 	}
20261da177e4SLinus Torvalds 
20275260ecc2SRichard Guy Briggs 	state = context->state;
2028619ed58aSSergey Nazarov 	if (state == AUDIT_STATE_DISABLED)
20295260ecc2SRichard Guy Briggs 		return;
20305260ecc2SRichard Guy Briggs 
20315260ecc2SRichard Guy Briggs 	context->dummy = !audit_n_rules;
2032619ed58aSSergey Nazarov 	if (!context->dummy && state == AUDIT_STATE_BUILD) {
20335260ecc2SRichard Guy Briggs 		context->prio = 0;
2034cdfb6b34SRichard Guy Briggs 		if (auditd_test_task(current))
20355260ecc2SRichard Guy Briggs 			return;
20365260ecc2SRichard Guy Briggs 	}
20375260ecc2SRichard Guy Briggs 
203816add411SDmitry V. Levin 	context->arch	    = syscall_get_arch(current);
20391da177e4SLinus Torvalds 	context->major      = major;
20401da177e4SLinus Torvalds 	context->argv[0]    = a1;
20411da177e4SLinus Torvalds 	context->argv[1]    = a2;
20421da177e4SLinus Torvalds 	context->argv[2]    = a3;
20431da177e4SLinus Torvalds 	context->argv[3]    = a4;
204412c5e81dSPaul Moore 	context->context = AUDIT_CTX_SYSCALL;
20450590b933SAl Viro 	context->current_state  = state;
2046290e44b7SPaul Moore 	ktime_get_coarse_real_ts64(&context->ctime);
20471da177e4SLinus Torvalds }
20481da177e4SLinus Torvalds 
2049b0dd25a8SRandy Dunlap /**
2050196a5085SGeliang Tang  * __audit_syscall_exit - deallocate audit context after a system call
205142ae610cSRandy Dunlap  * @success: success value of the syscall
205242ae610cSRandy Dunlap  * @return_code: return value of the syscall
2053b0dd25a8SRandy Dunlap  *
2054b0dd25a8SRandy Dunlap  * Tear down after system call.  If the audit context has been marked as
2055619ed58aSSergey Nazarov  * auditable (either because of the AUDIT_STATE_RECORD state from
205642ae610cSRandy Dunlap  * filtering, or because some other part of the kernel wrote an audit
20571da177e4SLinus Torvalds  * message), then write out the syscall information.  In call cases,
2058b0dd25a8SRandy Dunlap  * free the names stored from getname().
2059b0dd25a8SRandy Dunlap  */
__audit_syscall_exit(int success,long return_code)2060d7e7528bSEric Paris void __audit_syscall_exit(int success, long return_code)
20611da177e4SLinus Torvalds {
206212c5e81dSPaul Moore 	struct audit_context *context = audit_context();
20631da177e4SLinus Torvalds 
206412c5e81dSPaul Moore 	if (!context || context->dummy ||
206512c5e81dSPaul Moore 	    context->context != AUDIT_CTX_SYSCALL)
206612c5e81dSPaul Moore 		goto out;
20671da177e4SLinus Torvalds 
206812c5e81dSPaul Moore 	/* this may generate CONFIG_CHANGE records */
20699e36a5d4SRichard Guy Briggs 	if (!list_empty(&context->killed_trees))
20709e36a5d4SRichard Guy Briggs 		audit_kill_trees(context);
20719e36a5d4SRichard Guy Briggs 
2072d4fefa48SRichard Guy Briggs 	audit_return_fixup(context, success, return_code);
207312c5e81dSPaul Moore 	/* run through both filters to ensure we set the filterkey properly */
20745504a69aSRichard Guy Briggs 	audit_filter_syscall(current, context);
20752a1fe215SPaul Moore 	audit_filter_inodes(current, context);
20763ed66951SRichard Guy Briggs 	if (context->current_state != AUDIT_STATE_RECORD)
207712c5e81dSPaul Moore 		goto out;
207812c5e81dSPaul Moore 
20792a1fe215SPaul Moore 	audit_log_exit();
20801da177e4SLinus Torvalds 
208112c5e81dSPaul Moore out:
208212c5e81dSPaul Moore 	audit_reset_context(context);
20831da177e4SLinus Torvalds }
20841da177e4SLinus Torvalds 
handle_one(const struct inode * inode)208574c3cbe3SAl Viro static inline void handle_one(const struct inode *inode)
208674c3cbe3SAl Viro {
208774c3cbe3SAl Viro 	struct audit_context *context;
208874c3cbe3SAl Viro 	struct audit_tree_refs *p;
208974c3cbe3SAl Viro 	struct audit_chunk *chunk;
209074c3cbe3SAl Viro 	int count;
2091254c8b96SRoni Nevalainen 
209208991e83SJan Kara 	if (likely(!inode->i_fsnotify_marks))
209374c3cbe3SAl Viro 		return;
2094cdfb6b34SRichard Guy Briggs 	context = audit_context();
209574c3cbe3SAl Viro 	p = context->trees;
209674c3cbe3SAl Viro 	count = context->tree_count;
209774c3cbe3SAl Viro 	rcu_read_lock();
209874c3cbe3SAl Viro 	chunk = audit_tree_lookup(inode);
209974c3cbe3SAl Viro 	rcu_read_unlock();
210074c3cbe3SAl Viro 	if (!chunk)
210174c3cbe3SAl Viro 		return;
210274c3cbe3SAl Viro 	if (likely(put_tree_ref(context, chunk)))
210374c3cbe3SAl Viro 		return;
210474c3cbe3SAl Viro 	if (unlikely(!grow_tree_refs(context))) {
2105f952d10fSRichard Guy Briggs 		pr_warn("out of memory, audit has lost a tree reference\n");
210674c3cbe3SAl Viro 		audit_set_auditable(context);
210774c3cbe3SAl Viro 		audit_put_chunk(chunk);
210874c3cbe3SAl Viro 		unroll_tree_refs(context, p, count);
210974c3cbe3SAl Viro 		return;
211074c3cbe3SAl Viro 	}
211174c3cbe3SAl Viro 	put_tree_ref(context, chunk);
211274c3cbe3SAl Viro }
211374c3cbe3SAl Viro 
handle_path(const struct dentry * dentry)211474c3cbe3SAl Viro static void handle_path(const struct dentry *dentry)
211574c3cbe3SAl Viro {
211674c3cbe3SAl Viro 	struct audit_context *context;
211774c3cbe3SAl Viro 	struct audit_tree_refs *p;
211874c3cbe3SAl Viro 	const struct dentry *d, *parent;
211974c3cbe3SAl Viro 	struct audit_chunk *drop;
212074c3cbe3SAl Viro 	unsigned long seq;
212174c3cbe3SAl Viro 	int count;
212274c3cbe3SAl Viro 
2123cdfb6b34SRichard Guy Briggs 	context = audit_context();
212474c3cbe3SAl Viro 	p = context->trees;
212574c3cbe3SAl Viro 	count = context->tree_count;
212674c3cbe3SAl Viro retry:
212774c3cbe3SAl Viro 	drop = NULL;
212874c3cbe3SAl Viro 	d = dentry;
212974c3cbe3SAl Viro 	rcu_read_lock();
213074c3cbe3SAl Viro 	seq = read_seqbegin(&rename_lock);
213174c3cbe3SAl Viro 	for (;;) {
21323b362157SDavid Howells 		struct inode *inode = d_backing_inode(d);
2133254c8b96SRoni Nevalainen 
213408991e83SJan Kara 		if (inode && unlikely(inode->i_fsnotify_marks)) {
213574c3cbe3SAl Viro 			struct audit_chunk *chunk;
2136254c8b96SRoni Nevalainen 
213774c3cbe3SAl Viro 			chunk = audit_tree_lookup(inode);
213874c3cbe3SAl Viro 			if (chunk) {
213974c3cbe3SAl Viro 				if (unlikely(!put_tree_ref(context, chunk))) {
214074c3cbe3SAl Viro 					drop = chunk;
214174c3cbe3SAl Viro 					break;
214274c3cbe3SAl Viro 				}
214374c3cbe3SAl Viro 			}
214474c3cbe3SAl Viro 		}
214574c3cbe3SAl Viro 		parent = d->d_parent;
214674c3cbe3SAl Viro 		if (parent == d)
214774c3cbe3SAl Viro 			break;
214874c3cbe3SAl Viro 		d = parent;
214974c3cbe3SAl Viro 	}
215074c3cbe3SAl Viro 	if (unlikely(read_seqretry(&rename_lock, seq) || drop)) {  /* in this order */
215174c3cbe3SAl Viro 		rcu_read_unlock();
215274c3cbe3SAl Viro 		if (!drop) {
215374c3cbe3SAl Viro 			/* just a race with rename */
215474c3cbe3SAl Viro 			unroll_tree_refs(context, p, count);
215574c3cbe3SAl Viro 			goto retry;
215674c3cbe3SAl Viro 		}
215774c3cbe3SAl Viro 		audit_put_chunk(drop);
215874c3cbe3SAl Viro 		if (grow_tree_refs(context)) {
215974c3cbe3SAl Viro 			/* OK, got more space */
216074c3cbe3SAl Viro 			unroll_tree_refs(context, p, count);
216174c3cbe3SAl Viro 			goto retry;
216274c3cbe3SAl Viro 		}
216374c3cbe3SAl Viro 		/* too bad */
2164f952d10fSRichard Guy Briggs 		pr_warn("out of memory, audit has lost a tree reference\n");
216574c3cbe3SAl Viro 		unroll_tree_refs(context, p, count);
216674c3cbe3SAl Viro 		audit_set_auditable(context);
216774c3cbe3SAl Viro 		return;
216874c3cbe3SAl Viro 	}
216974c3cbe3SAl Viro 	rcu_read_unlock();
217074c3cbe3SAl Viro }
217174c3cbe3SAl Viro 
audit_alloc_name(struct audit_context * context,unsigned char type)217278e2e802SJeff Layton static struct audit_names *audit_alloc_name(struct audit_context *context,
217378e2e802SJeff Layton 						unsigned char type)
21745195d8e2SEric Paris {
21755195d8e2SEric Paris 	struct audit_names *aname;
21765195d8e2SEric Paris 
21775195d8e2SEric Paris 	if (context->name_count < AUDIT_NAMES) {
21785195d8e2SEric Paris 		aname = &context->preallocated_names[context->name_count];
21795195d8e2SEric Paris 		memset(aname, 0, sizeof(*aname));
21805195d8e2SEric Paris 	} else {
21815195d8e2SEric Paris 		aname = kzalloc(sizeof(*aname), GFP_NOFS);
21825195d8e2SEric Paris 		if (!aname)
21835195d8e2SEric Paris 			return NULL;
21845195d8e2SEric Paris 		aname->should_free = true;
21855195d8e2SEric Paris 	}
21865195d8e2SEric Paris 
218784cb777eSRichard Guy Briggs 	aname->ino = AUDIT_INO_UNSET;
218878e2e802SJeff Layton 	aname->type = type;
21895195d8e2SEric Paris 	list_add_tail(&aname->list, &context->names_list);
21905195d8e2SEric Paris 
21915195d8e2SEric Paris 	context->name_count++;
21926d915476SRichard Guy Briggs 	if (!context->pwd.dentry)
21936d915476SRichard Guy Briggs 		get_fs_pwd(current->fs, &context->pwd);
21945195d8e2SEric Paris 	return aname;
21955195d8e2SEric Paris }
21965195d8e2SEric Paris 
2197b0dd25a8SRandy Dunlap /**
2198196a5085SGeliang Tang  * __audit_reusename - fill out filename with info from existing entry
21997ac86265SJeff Layton  * @uptr: userland ptr to pathname
22007ac86265SJeff Layton  *
22017ac86265SJeff Layton  * Search the audit_names list for the current audit context. If there is an
22027ac86265SJeff Layton  * existing entry with a matching "uptr" then return the filename
22037ac86265SJeff Layton  * associated with that audit_name. If not, return NULL.
22047ac86265SJeff Layton  */
22057ac86265SJeff Layton struct filename *
__audit_reusename(const __user char * uptr)22067ac86265SJeff Layton __audit_reusename(const __user char *uptr)
22077ac86265SJeff Layton {
2208cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
22097ac86265SJeff Layton 	struct audit_names *n;
22107ac86265SJeff Layton 
22117ac86265SJeff Layton 	list_for_each_entry(n, &context->names_list, list) {
22127ac86265SJeff Layton 		if (!n->name)
22137ac86265SJeff Layton 			continue;
221455422d0bSPaul Moore 		if (n->name->uptr == uptr) {
2215*03adc61eSDan Clash 			atomic_inc(&n->name->refcnt);
22167ac86265SJeff Layton 			return n->name;
22177ac86265SJeff Layton 		}
221855422d0bSPaul Moore 	}
22197ac86265SJeff Layton 	return NULL;
22207ac86265SJeff Layton }
22217ac86265SJeff Layton 
22227ac86265SJeff Layton /**
2223196a5085SGeliang Tang  * __audit_getname - add a name to the list
2224b0dd25a8SRandy Dunlap  * @name: name to add
2225b0dd25a8SRandy Dunlap  *
2226b0dd25a8SRandy Dunlap  * Add a name to the list of audit names for this context.
2227b0dd25a8SRandy Dunlap  * Called from fs/namei.c:getname().
2228b0dd25a8SRandy Dunlap  */
__audit_getname(struct filename * name)222991a27b2aSJeff Layton void __audit_getname(struct filename *name)
22301da177e4SLinus Torvalds {
2231cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
22325195d8e2SEric Paris 	struct audit_names *n;
22331da177e4SLinus Torvalds 
223412c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_UNUSED)
22351da177e4SLinus Torvalds 		return;
223691a27b2aSJeff Layton 
223778e2e802SJeff Layton 	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
22385195d8e2SEric Paris 	if (!n)
22395195d8e2SEric Paris 		return;
22405195d8e2SEric Paris 
22415195d8e2SEric Paris 	n->name = name;
22425195d8e2SEric Paris 	n->name_len = AUDIT_NAME_FULL;
2243adb5c247SJeff Layton 	name->aname = n;
2244*03adc61eSDan Clash 	atomic_inc(&name->refcnt);
22451da177e4SLinus Torvalds }
22461da177e4SLinus Torvalds 
audit_copy_fcaps(struct audit_names * name,const struct dentry * dentry)22475f3d544fSRichard Guy Briggs static inline int audit_copy_fcaps(struct audit_names *name,
22485f3d544fSRichard Guy Briggs 				   const struct dentry *dentry)
22495f3d544fSRichard Guy Briggs {
22505f3d544fSRichard Guy Briggs 	struct cpu_vfs_cap_data caps;
22515f3d544fSRichard Guy Briggs 	int rc;
22525f3d544fSRichard Guy Briggs 
22535f3d544fSRichard Guy Briggs 	if (!dentry)
22545f3d544fSRichard Guy Briggs 		return 0;
22555f3d544fSRichard Guy Briggs 
225639f60c1cSChristian Brauner 	rc = get_vfs_caps_from_disk(&nop_mnt_idmap, dentry, &caps);
22575f3d544fSRichard Guy Briggs 	if (rc)
22585f3d544fSRichard Guy Briggs 		return rc;
22595f3d544fSRichard Guy Briggs 
22605f3d544fSRichard Guy Briggs 	name->fcap.permitted = caps.permitted;
22615f3d544fSRichard Guy Briggs 	name->fcap.inheritable = caps.inheritable;
22625f3d544fSRichard Guy Briggs 	name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
22635f3d544fSRichard Guy Briggs 	name->fcap.rootid = caps.rootid;
22645f3d544fSRichard Guy Briggs 	name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
22655f3d544fSRichard Guy Briggs 				VFS_CAP_REVISION_SHIFT;
22665f3d544fSRichard Guy Briggs 
22675f3d544fSRichard Guy Briggs 	return 0;
22685f3d544fSRichard Guy Briggs }
22695f3d544fSRichard Guy Briggs 
22705f3d544fSRichard Guy Briggs /* Copy inode data into an audit_names. */
audit_copy_inode(struct audit_names * name,const struct dentry * dentry,struct inode * inode,unsigned int flags)22712efa48feSYueHaibing static void audit_copy_inode(struct audit_names *name,
22722efa48feSYueHaibing 			     const struct dentry *dentry,
22735f3d544fSRichard Guy Briggs 			     struct inode *inode, unsigned int flags)
22745f3d544fSRichard Guy Briggs {
22755f3d544fSRichard Guy Briggs 	name->ino   = inode->i_ino;
22765f3d544fSRichard Guy Briggs 	name->dev   = inode->i_sb->s_dev;
22775f3d544fSRichard Guy Briggs 	name->mode  = inode->i_mode;
22785f3d544fSRichard Guy Briggs 	name->uid   = inode->i_uid;
22795f3d544fSRichard Guy Briggs 	name->gid   = inode->i_gid;
22805f3d544fSRichard Guy Briggs 	name->rdev  = inode->i_rdev;
22815f3d544fSRichard Guy Briggs 	security_inode_getsecid(inode, &name->osid);
22825f3d544fSRichard Guy Briggs 	if (flags & AUDIT_INODE_NOEVAL) {
22835f3d544fSRichard Guy Briggs 		name->fcap_ver = -1;
22845f3d544fSRichard Guy Briggs 		return;
22855f3d544fSRichard Guy Briggs 	}
22865f3d544fSRichard Guy Briggs 	audit_copy_fcaps(name, dentry);
22875f3d544fSRichard Guy Briggs }
22885f3d544fSRichard Guy Briggs 
2289b0dd25a8SRandy Dunlap /**
2290bfcec708SJeff Layton  * __audit_inode - store the inode and device from a lookup
2291b0dd25a8SRandy Dunlap  * @name: name being audited
2292481968f4SRandy Dunlap  * @dentry: dentry being audited
229379f6530cSJeff Layton  * @flags: attributes for this particular entry
2294b0dd25a8SRandy Dunlap  */
__audit_inode(struct filename * name,const struct dentry * dentry,unsigned int flags)2295adb5c247SJeff Layton void __audit_inode(struct filename *name, const struct dentry *dentry,
229679f6530cSJeff Layton 		   unsigned int flags)
22971da177e4SLinus Torvalds {
2298cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2299d6335d77SAndreas Gruenbacher 	struct inode *inode = d_backing_inode(dentry);
23005195d8e2SEric Paris 	struct audit_names *n;
230179f6530cSJeff Layton 	bool parent = flags & AUDIT_INODE_PARENT;
2302a252f56aSRichard Guy Briggs 	struct audit_entry *e;
2303a252f56aSRichard Guy Briggs 	struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
2304a252f56aSRichard Guy Briggs 	int i;
23051da177e4SLinus Torvalds 
230612c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_UNUSED)
23071da177e4SLinus Torvalds 		return;
23085195d8e2SEric Paris 
2309a252f56aSRichard Guy Briggs 	rcu_read_lock();
2310a252f56aSRichard Guy Briggs 	list_for_each_entry_rcu(e, list, list) {
2311a252f56aSRichard Guy Briggs 		for (i = 0; i < e->rule.field_count; i++) {
2312a252f56aSRichard Guy Briggs 			struct audit_field *f = &e->rule.fields[i];
2313a252f56aSRichard Guy Briggs 
2314a252f56aSRichard Guy Briggs 			if (f->type == AUDIT_FSTYPE
2315a252f56aSRichard Guy Briggs 			    && audit_comparator(inode->i_sb->s_magic,
2316a252f56aSRichard Guy Briggs 						f->op, f->val)
2317a252f56aSRichard Guy Briggs 			    && e->rule.action == AUDIT_NEVER) {
2318a252f56aSRichard Guy Briggs 				rcu_read_unlock();
2319a252f56aSRichard Guy Briggs 				return;
2320a252f56aSRichard Guy Briggs 			}
2321a252f56aSRichard Guy Briggs 		}
2322a252f56aSRichard Guy Briggs 	}
2323a252f56aSRichard Guy Briggs 	rcu_read_unlock();
2324a252f56aSRichard Guy Briggs 
23259cec9d68SJeff Layton 	if (!name)
23269cec9d68SJeff Layton 		goto out_alloc;
23279cec9d68SJeff Layton 
2328adb5c247SJeff Layton 	/*
2329adb5c247SJeff Layton 	 * If we have a pointer to an audit_names entry already, then we can
2330adb5c247SJeff Layton 	 * just use it directly if the type is correct.
2331adb5c247SJeff Layton 	 */
2332adb5c247SJeff Layton 	n = name->aname;
2333adb5c247SJeff Layton 	if (n) {
2334adb5c247SJeff Layton 		if (parent) {
2335adb5c247SJeff Layton 			if (n->type == AUDIT_TYPE_PARENT ||
2336adb5c247SJeff Layton 			    n->type == AUDIT_TYPE_UNKNOWN)
2337adb5c247SJeff Layton 				goto out;
2338adb5c247SJeff Layton 		} else {
2339adb5c247SJeff Layton 			if (n->type != AUDIT_TYPE_PARENT)
2340adb5c247SJeff Layton 				goto out;
2341adb5c247SJeff Layton 		}
2342adb5c247SJeff Layton 	}
2343adb5c247SJeff Layton 
23445195d8e2SEric Paris 	list_for_each_entry_reverse(n, &context->names_list, list) {
234557c59f58SPaul Moore 		if (n->ino) {
234657c59f58SPaul Moore 			/* valid inode number, use that for the comparison */
234757c59f58SPaul Moore 			if (n->ino != inode->i_ino ||
234857c59f58SPaul Moore 			    n->dev != inode->i_sb->s_dev)
234957c59f58SPaul Moore 				continue;
235057c59f58SPaul Moore 		} else if (n->name) {
235157c59f58SPaul Moore 			/* inode number has not been set, check the name */
235257c59f58SPaul Moore 			if (strcmp(n->name->name, name->name))
235357c59f58SPaul Moore 				continue;
235457c59f58SPaul Moore 		} else
235557c59f58SPaul Moore 			/* no inode and no name (?!) ... this is odd ... */
2356bfcec708SJeff Layton 			continue;
2357bfcec708SJeff Layton 
2358bfcec708SJeff Layton 		/* match the correct record type */
2359bfcec708SJeff Layton 		if (parent) {
2360bfcec708SJeff Layton 			if (n->type == AUDIT_TYPE_PARENT ||
2361bfcec708SJeff Layton 			    n->type == AUDIT_TYPE_UNKNOWN)
23625195d8e2SEric Paris 				goto out;
2363bfcec708SJeff Layton 		} else {
2364bfcec708SJeff Layton 			if (n->type != AUDIT_TYPE_PARENT)
2365bfcec708SJeff Layton 				goto out;
2366bfcec708SJeff Layton 		}
23671da177e4SLinus Torvalds 	}
23685195d8e2SEric Paris 
23699cec9d68SJeff Layton out_alloc:
23704a928436SPaul Moore 	/* unable to find an entry with both a matching name and type */
23714a928436SPaul Moore 	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
23725195d8e2SEric Paris 	if (!n)
23735195d8e2SEric Paris 		return;
2374fcf22d82SPaul Moore 	if (name) {
2375fd3522fdSPaul Moore 		n->name = name;
2376*03adc61eSDan Clash 		atomic_inc(&name->refcnt);
2377fcf22d82SPaul Moore 	}
23784a928436SPaul Moore 
23795195d8e2SEric Paris out:
2380bfcec708SJeff Layton 	if (parent) {
238191a27b2aSJeff Layton 		n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
2382bfcec708SJeff Layton 		n->type = AUDIT_TYPE_PARENT;
238379f6530cSJeff Layton 		if (flags & AUDIT_INODE_HIDDEN)
238479f6530cSJeff Layton 			n->hidden = true;
2385bfcec708SJeff Layton 	} else {
2386bfcec708SJeff Layton 		n->name_len = AUDIT_NAME_FULL;
2387bfcec708SJeff Layton 		n->type = AUDIT_TYPE_NORMAL;
2388bfcec708SJeff Layton 	}
238974c3cbe3SAl Viro 	handle_path(dentry);
239057d46577SRichard Guy Briggs 	audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL);
239173241cccSAmy Griffis }
239273241cccSAmy Griffis 
__audit_file(const struct file * file)23939f45f5bfSAl Viro void __audit_file(const struct file *file)
23949f45f5bfSAl Viro {
23959f45f5bfSAl Viro 	__audit_inode(NULL, file->f_path.dentry, 0);
23969f45f5bfSAl Viro }
23979f45f5bfSAl Viro 
239873241cccSAmy Griffis /**
2399c43a25abSJeff Layton  * __audit_inode_child - collect inode info for created/removed objects
240073d3ec5aSAmy Griffis  * @parent: inode of dentry parent
2401c43a25abSJeff Layton  * @dentry: dentry being audited
24024fa6b5ecSJeff Layton  * @type:   AUDIT_TYPE_* value that we're looking for
240373241cccSAmy Griffis  *
240473241cccSAmy Griffis  * For syscalls that create or remove filesystem objects, audit_inode
240573241cccSAmy Griffis  * can only collect information for the filesystem object's parent.
240673241cccSAmy Griffis  * This call updates the audit context with the child's information.
240773241cccSAmy Griffis  * Syscalls that create a new filesystem object must be hooked after
240873241cccSAmy Griffis  * the object is created.  Syscalls that remove a filesystem object
240973241cccSAmy Griffis  * must be hooked prior, in order to capture the target inode during
241073241cccSAmy Griffis  * unsuccessful attempts.
241173241cccSAmy Griffis  */
__audit_inode_child(struct inode * parent,const struct dentry * dentry,const unsigned char type)2412d6335d77SAndreas Gruenbacher void __audit_inode_child(struct inode *parent,
24134fa6b5ecSJeff Layton 			 const struct dentry *dentry,
24144fa6b5ecSJeff Layton 			 const unsigned char type)
241573241cccSAmy Griffis {
2416cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2417d6335d77SAndreas Gruenbacher 	struct inode *inode = d_backing_inode(dentry);
2418795d673aSAl Viro 	const struct qstr *dname = &dentry->d_name;
24194fa6b5ecSJeff Layton 	struct audit_names *n, *found_parent = NULL, *found_child = NULL;
242042d5e376SRichard Guy Briggs 	struct audit_entry *e;
242142d5e376SRichard Guy Briggs 	struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
242242d5e376SRichard Guy Briggs 	int i;
242373241cccSAmy Griffis 
242412c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_UNUSED)
242573241cccSAmy Griffis 		return;
242673241cccSAmy Griffis 
242742d5e376SRichard Guy Briggs 	rcu_read_lock();
242842d5e376SRichard Guy Briggs 	list_for_each_entry_rcu(e, list, list) {
242942d5e376SRichard Guy Briggs 		for (i = 0; i < e->rule.field_count; i++) {
243042d5e376SRichard Guy Briggs 			struct audit_field *f = &e->rule.fields[i];
243142d5e376SRichard Guy Briggs 
2432a252f56aSRichard Guy Briggs 			if (f->type == AUDIT_FSTYPE
2433a252f56aSRichard Guy Briggs 			    && audit_comparator(parent->i_sb->s_magic,
2434a252f56aSRichard Guy Briggs 						f->op, f->val)
2435a252f56aSRichard Guy Briggs 			    && e->rule.action == AUDIT_NEVER) {
243642d5e376SRichard Guy Briggs 				rcu_read_unlock();
243742d5e376SRichard Guy Briggs 				return;
243842d5e376SRichard Guy Briggs 			}
243942d5e376SRichard Guy Briggs 		}
244042d5e376SRichard Guy Briggs 	}
244142d5e376SRichard Guy Briggs 	rcu_read_unlock();
244242d5e376SRichard Guy Briggs 
244374c3cbe3SAl Viro 	if (inode)
244474c3cbe3SAl Viro 		handle_one(inode);
244573241cccSAmy Griffis 
24464fa6b5ecSJeff Layton 	/* look for a parent entry first */
24475195d8e2SEric Paris 	list_for_each_entry(n, &context->names_list, list) {
244857c59f58SPaul Moore 		if (!n->name ||
244957c59f58SPaul Moore 		    (n->type != AUDIT_TYPE_PARENT &&
245057c59f58SPaul Moore 		     n->type != AUDIT_TYPE_UNKNOWN))
245173241cccSAmy Griffis 			continue;
245273241cccSAmy Griffis 
245357c59f58SPaul Moore 		if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev &&
245457c59f58SPaul Moore 		    !audit_compare_dname_path(dname,
245557c59f58SPaul Moore 					      n->name->name, n->name_len)) {
245657c59f58SPaul Moore 			if (n->type == AUDIT_TYPE_UNKNOWN)
245757c59f58SPaul Moore 				n->type = AUDIT_TYPE_PARENT;
24584fa6b5ecSJeff Layton 			found_parent = n;
24594fa6b5ecSJeff Layton 			break;
24609c937dccSAmy Griffis 		}
246173241cccSAmy Griffis 	}
246273241cccSAmy Griffis 
2463b59bc6e3SGaosheng Cui 	cond_resched();
2464b59bc6e3SGaosheng Cui 
24654fa6b5ecSJeff Layton 	/* is there a matching child entry? */
24665195d8e2SEric Paris 	list_for_each_entry(n, &context->names_list, list) {
24674fa6b5ecSJeff Layton 		/* can only match entries that have a name */
246857c59f58SPaul Moore 		if (!n->name ||
246957c59f58SPaul Moore 		    (n->type != type && n->type != AUDIT_TYPE_UNKNOWN))
24704fa6b5ecSJeff Layton 			continue;
24714fa6b5ecSJeff Layton 
2472795d673aSAl Viro 		if (!strcmp(dname->name, n->name->name) ||
247391a27b2aSJeff Layton 		    !audit_compare_dname_path(dname, n->name->name,
24744fa6b5ecSJeff Layton 						found_parent ?
24754fa6b5ecSJeff Layton 						found_parent->name_len :
2476e3d6b07bSJeff Layton 						AUDIT_NAME_FULL)) {
247757c59f58SPaul Moore 			if (n->type == AUDIT_TYPE_UNKNOWN)
247857c59f58SPaul Moore 				n->type = type;
24794fa6b5ecSJeff Layton 			found_child = n;
24804fa6b5ecSJeff Layton 			break;
2481ac9910ceSSteve Grubb 		}
24825712e88fSAmy Griffis 	}
24835712e88fSAmy Griffis 
24845712e88fSAmy Griffis 	if (!found_parent) {
24854fa6b5ecSJeff Layton 		/* create a new, "anonymous" parent record */
24864fa6b5ecSJeff Layton 		n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
24875195d8e2SEric Paris 		if (!n)
24885712e88fSAmy Griffis 			return;
248957d46577SRichard Guy Briggs 		audit_copy_inode(n, NULL, parent, 0);
249073d3ec5aSAmy Griffis 	}
24915712e88fSAmy Griffis 
24925712e88fSAmy Griffis 	if (!found_child) {
24934fa6b5ecSJeff Layton 		found_child = audit_alloc_name(context, type);
24944fa6b5ecSJeff Layton 		if (!found_child)
24955712e88fSAmy Griffis 			return;
24965712e88fSAmy Griffis 
24975712e88fSAmy Griffis 		/* Re-use the name belonging to the slot for a matching parent
24985712e88fSAmy Griffis 		 * directory. All names for this context are relinquished in
24995712e88fSAmy Griffis 		 * audit_free_names() */
25005712e88fSAmy Griffis 		if (found_parent) {
25014fa6b5ecSJeff Layton 			found_child->name = found_parent->name;
25024fa6b5ecSJeff Layton 			found_child->name_len = AUDIT_NAME_FULL;
2503*03adc61eSDan Clash 			atomic_inc(&found_child->name->refcnt);
25045712e88fSAmy Griffis 		}
25054fa6b5ecSJeff Layton 	}
250657c59f58SPaul Moore 
25075712e88fSAmy Griffis 	if (inode)
250857d46577SRichard Guy Briggs 		audit_copy_inode(found_child, dentry, inode, 0);
25094fa6b5ecSJeff Layton 	else
251084cb777eSRichard Guy Briggs 		found_child->ino = AUDIT_INO_UNSET;
25113e2efce0SAmy Griffis }
251250e437d5STrond Myklebust EXPORT_SYMBOL_GPL(__audit_inode_child);
25133e2efce0SAmy Griffis 
25143e2efce0SAmy Griffis /**
2515b0dd25a8SRandy Dunlap  * auditsc_get_stamp - get local copies of audit_context values
2516b0dd25a8SRandy Dunlap  * @ctx: audit_context for the task
25172115bb25SDeepa Dinamani  * @t: timespec64 to store time recorded in the audit_context
2518b0dd25a8SRandy Dunlap  * @serial: serial value that is recorded in the audit_context
2519b0dd25a8SRandy Dunlap  *
2520b0dd25a8SRandy Dunlap  * Also sets the context as auditable.
2521b0dd25a8SRandy Dunlap  */
auditsc_get_stamp(struct audit_context * ctx,struct timespec64 * t,unsigned int * serial)252248887e63SAl Viro int auditsc_get_stamp(struct audit_context *ctx,
25232115bb25SDeepa Dinamani 		       struct timespec64 *t, unsigned int *serial)
25241da177e4SLinus Torvalds {
252512c5e81dSPaul Moore 	if (ctx->context == AUDIT_CTX_UNUSED)
252648887e63SAl Viro 		return 0;
2527ce625a80SDavid Woodhouse 	if (!ctx->serial)
2528ce625a80SDavid Woodhouse 		ctx->serial = audit_serial();
25291da177e4SLinus Torvalds 	t->tv_sec  = ctx->ctime.tv_sec;
25301da177e4SLinus Torvalds 	t->tv_nsec = ctx->ctime.tv_nsec;
25311da177e4SLinus Torvalds 	*serial    = ctx->serial;
25320590b933SAl Viro 	if (!ctx->prio) {
25330590b933SAl Viro 		ctx->prio = 1;
2534619ed58aSSergey Nazarov 		ctx->current_state = AUDIT_STATE_RECORD;
25350590b933SAl Viro 	}
253648887e63SAl Viro 	return 1;
25371da177e4SLinus Torvalds }
25381da177e4SLinus Torvalds 
2539b0dd25a8SRandy Dunlap /**
254020ca73bcSGeorge C. Wilson  * __audit_mq_open - record audit data for a POSIX MQ open
254120ca73bcSGeorge C. Wilson  * @oflag: open flag
254220ca73bcSGeorge C. Wilson  * @mode: mode bits
25436b962559SRandy Dunlap  * @attr: queue attributes
254420ca73bcSGeorge C. Wilson  *
254520ca73bcSGeorge C. Wilson  */
__audit_mq_open(int oflag,umode_t mode,struct mq_attr * attr)2546df0a4283SAl Viro void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
254720ca73bcSGeorge C. Wilson {
2548cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
254920ca73bcSGeorge C. Wilson 
2550564f6993SAl Viro 	if (attr)
2551564f6993SAl Viro 		memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr));
2552564f6993SAl Viro 	else
2553564f6993SAl Viro 		memset(&context->mq_open.attr, 0, sizeof(struct mq_attr));
255420ca73bcSGeorge C. Wilson 
2555564f6993SAl Viro 	context->mq_open.oflag = oflag;
2556564f6993SAl Viro 	context->mq_open.mode = mode;
255720ca73bcSGeorge C. Wilson 
2558564f6993SAl Viro 	context->type = AUDIT_MQ_OPEN;
255920ca73bcSGeorge C. Wilson }
256020ca73bcSGeorge C. Wilson 
256120ca73bcSGeorge C. Wilson /**
2562c32c8af4SAl Viro  * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive
256320ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
256420ca73bcSGeorge C. Wilson  * @msg_len: Message length
256520ca73bcSGeorge C. Wilson  * @msg_prio: Message priority
2566c32c8af4SAl Viro  * @abs_timeout: Message timeout in absolute time
256720ca73bcSGeorge C. Wilson  *
256820ca73bcSGeorge C. Wilson  */
__audit_mq_sendrecv(mqd_t mqdes,size_t msg_len,unsigned int msg_prio,const struct timespec64 * abs_timeout)2569c32c8af4SAl Viro void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
2570b9047726SDeepa Dinamani 			const struct timespec64 *abs_timeout)
257120ca73bcSGeorge C. Wilson {
2572cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2573b9047726SDeepa Dinamani 	struct timespec64 *p = &context->mq_sendrecv.abs_timeout;
257420ca73bcSGeorge C. Wilson 
2575c32c8af4SAl Viro 	if (abs_timeout)
2576b9047726SDeepa Dinamani 		memcpy(p, abs_timeout, sizeof(*p));
2577c32c8af4SAl Viro 	else
2578b9047726SDeepa Dinamani 		memset(p, 0, sizeof(*p));
257920ca73bcSGeorge C. Wilson 
2580c32c8af4SAl Viro 	context->mq_sendrecv.mqdes = mqdes;
2581c32c8af4SAl Viro 	context->mq_sendrecv.msg_len = msg_len;
2582c32c8af4SAl Viro 	context->mq_sendrecv.msg_prio = msg_prio;
258320ca73bcSGeorge C. Wilson 
2584c32c8af4SAl Viro 	context->type = AUDIT_MQ_SENDRECV;
258520ca73bcSGeorge C. Wilson }
258620ca73bcSGeorge C. Wilson 
258720ca73bcSGeorge C. Wilson /**
258820ca73bcSGeorge C. Wilson  * __audit_mq_notify - record audit data for a POSIX MQ notify
258920ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
25906b962559SRandy Dunlap  * @notification: Notification event
259120ca73bcSGeorge C. Wilson  *
259220ca73bcSGeorge C. Wilson  */
259320ca73bcSGeorge C. Wilson 
__audit_mq_notify(mqd_t mqdes,const struct sigevent * notification)259420114f71SAl Viro void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
259520ca73bcSGeorge C. Wilson {
2596cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
259720ca73bcSGeorge C. Wilson 
259820114f71SAl Viro 	if (notification)
259920114f71SAl Viro 		context->mq_notify.sigev_signo = notification->sigev_signo;
260020114f71SAl Viro 	else
260120114f71SAl Viro 		context->mq_notify.sigev_signo = 0;
260220ca73bcSGeorge C. Wilson 
260320114f71SAl Viro 	context->mq_notify.mqdes = mqdes;
260420114f71SAl Viro 	context->type = AUDIT_MQ_NOTIFY;
260520ca73bcSGeorge C. Wilson }
260620ca73bcSGeorge C. Wilson 
260720ca73bcSGeorge C. Wilson /**
260820ca73bcSGeorge C. Wilson  * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
260920ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
261020ca73bcSGeorge C. Wilson  * @mqstat: MQ flags
261120ca73bcSGeorge C. Wilson  *
261220ca73bcSGeorge C. Wilson  */
__audit_mq_getsetattr(mqd_t mqdes,struct mq_attr * mqstat)26137392906eSAl Viro void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
261420ca73bcSGeorge C. Wilson {
2615cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2616254c8b96SRoni Nevalainen 
26177392906eSAl Viro 	context->mq_getsetattr.mqdes = mqdes;
26187392906eSAl Viro 	context->mq_getsetattr.mqstat = *mqstat;
26197392906eSAl Viro 	context->type = AUDIT_MQ_GETSETATTR;
262020ca73bcSGeorge C. Wilson }
262120ca73bcSGeorge C. Wilson 
262220ca73bcSGeorge C. Wilson /**
2623196a5085SGeliang Tang  * __audit_ipc_obj - record audit data for ipc object
2624073115d6SSteve Grubb  * @ipcp: ipc permissions
2625073115d6SSteve Grubb  *
2626073115d6SSteve Grubb  */
__audit_ipc_obj(struct kern_ipc_perm * ipcp)2627a33e6751SAl Viro void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
2628073115d6SSteve Grubb {
2629cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2630254c8b96SRoni Nevalainen 
2631a33e6751SAl Viro 	context->ipc.uid = ipcp->uid;
2632a33e6751SAl Viro 	context->ipc.gid = ipcp->gid;
2633a33e6751SAl Viro 	context->ipc.mode = ipcp->mode;
2634e816f370SAl Viro 	context->ipc.has_perm = 0;
2635a33e6751SAl Viro 	security_ipc_getsecid(ipcp, &context->ipc.osid);
2636a33e6751SAl Viro 	context->type = AUDIT_IPC;
2637073115d6SSteve Grubb }
2638073115d6SSteve Grubb 
2639073115d6SSteve Grubb /**
2640196a5085SGeliang Tang  * __audit_ipc_set_perm - record audit data for new ipc permissions
2641b0dd25a8SRandy Dunlap  * @qbytes: msgq bytes
2642b0dd25a8SRandy Dunlap  * @uid: msgq user id
2643b0dd25a8SRandy Dunlap  * @gid: msgq group id
2644b0dd25a8SRandy Dunlap  * @mode: msgq mode (permissions)
2645b0dd25a8SRandy Dunlap  *
2646e816f370SAl Viro  * Called only after audit_ipc_obj().
2647b0dd25a8SRandy Dunlap  */
__audit_ipc_set_perm(unsigned long qbytes,uid_t uid,gid_t gid,umode_t mode)26482570ebbdSAl Viro void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode)
26491da177e4SLinus Torvalds {
2650cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
26511da177e4SLinus Torvalds 
2652e816f370SAl Viro 	context->ipc.qbytes = qbytes;
2653e816f370SAl Viro 	context->ipc.perm_uid = uid;
2654e816f370SAl Viro 	context->ipc.perm_gid = gid;
2655e816f370SAl Viro 	context->ipc.perm_mode = mode;
2656e816f370SAl Viro 	context->ipc.has_perm = 1;
26571da177e4SLinus Torvalds }
2658c2f0c7c3SSteve Grubb 
__audit_bprm(struct linux_binprm * bprm)2659d9cfea91SRichard Guy Briggs void __audit_bprm(struct linux_binprm *bprm)
2660473ae30bSAl Viro {
2661cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2662473ae30bSAl Viro 
2663d9cfea91SRichard Guy Briggs 	context->type = AUDIT_EXECVE;
2664d9cfea91SRichard Guy Briggs 	context->execve.argc = bprm->argc;
2665473ae30bSAl Viro }
2666473ae30bSAl Viro 
2667473ae30bSAl Viro 
2668b0dd25a8SRandy Dunlap /**
2669196a5085SGeliang Tang  * __audit_socketcall - record audit data for sys_socketcall
26702950fa9dSChen Gang  * @nargs: number of args, which should not be more than AUDITSC_ARGS.
2671b0dd25a8SRandy Dunlap  * @args: args array
2672b0dd25a8SRandy Dunlap  *
2673b0dd25a8SRandy Dunlap  */
__audit_socketcall(int nargs,unsigned long * args)26742950fa9dSChen Gang int __audit_socketcall(int nargs, unsigned long *args)
26753ec3b2fbSDavid Woodhouse {
2676cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
26773ec3b2fbSDavid Woodhouse 
26782950fa9dSChen Gang 	if (nargs <= 0 || nargs > AUDITSC_ARGS || !args)
26792950fa9dSChen Gang 		return -EINVAL;
2680f3298dc4SAl Viro 	context->type = AUDIT_SOCKETCALL;
2681f3298dc4SAl Viro 	context->socketcall.nargs = nargs;
2682f3298dc4SAl Viro 	memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
26832950fa9dSChen Gang 	return 0;
26843ec3b2fbSDavid Woodhouse }
26853ec3b2fbSDavid Woodhouse 
2686b0dd25a8SRandy Dunlap /**
2687db349509SAl Viro  * __audit_fd_pair - record audit data for pipe and socketpair
2688db349509SAl Viro  * @fd1: the first file descriptor
2689db349509SAl Viro  * @fd2: the second file descriptor
2690db349509SAl Viro  *
2691db349509SAl Viro  */
__audit_fd_pair(int fd1,int fd2)2692157cf649SAl Viro void __audit_fd_pair(int fd1, int fd2)
2693db349509SAl Viro {
2694cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2695254c8b96SRoni Nevalainen 
2696157cf649SAl Viro 	context->fds[0] = fd1;
2697157cf649SAl Viro 	context->fds[1] = fd2;
2698db349509SAl Viro }
2699db349509SAl Viro 
2700db349509SAl Viro /**
2701196a5085SGeliang Tang  * __audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
2702b0dd25a8SRandy Dunlap  * @len: data length in user space
2703b0dd25a8SRandy Dunlap  * @a: data address in kernel space
2704b0dd25a8SRandy Dunlap  *
2705b0dd25a8SRandy Dunlap  * Returns 0 for success or NULL context or < 0 on error.
2706b0dd25a8SRandy Dunlap  */
__audit_sockaddr(int len,void * a)270707c49417SEric Paris int __audit_sockaddr(int len, void *a)
27083ec3b2fbSDavid Woodhouse {
2709cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
27103ec3b2fbSDavid Woodhouse 
27114f6b434fSAl Viro 	if (!context->sockaddr) {
27124f6b434fSAl Viro 		void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
2713254c8b96SRoni Nevalainen 
27144f6b434fSAl Viro 		if (!p)
27153ec3b2fbSDavid Woodhouse 			return -ENOMEM;
27164f6b434fSAl Viro 		context->sockaddr = p;
27174f6b434fSAl Viro 	}
27183ec3b2fbSDavid Woodhouse 
27194f6b434fSAl Viro 	context->sockaddr_len = len;
27204f6b434fSAl Viro 	memcpy(context->sockaddr, a, len);
27213ec3b2fbSDavid Woodhouse 	return 0;
27223ec3b2fbSDavid Woodhouse }
27233ec3b2fbSDavid Woodhouse 
__audit_ptrace(struct task_struct * t)2724a5cb013dSAl Viro void __audit_ptrace(struct task_struct *t)
2725a5cb013dSAl Viro {
2726cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2727a5cb013dSAl Viro 
2728fa2bea2fSPaul Moore 	context->target_pid = task_tgid_nr(t);
2729c2a7780eSEric Paris 	context->target_auid = audit_get_loginuid(t);
2730c69e8d9cSDavid Howells 	context->target_uid = task_uid(t);
27314746ec5bSEric Paris 	context->target_sessionid = audit_get_sessionid(t);
27324ebd7651SPaul Moore 	security_task_getsecid_obj(t, &context->target_sid);
2733c2a7780eSEric Paris 	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
2734a5cb013dSAl Viro }
2735a5cb013dSAl Viro 
2736b0dd25a8SRandy Dunlap /**
2737b48345aaSRichard Guy Briggs  * audit_signal_info_syscall - record signal info for syscalls
2738b0dd25a8SRandy Dunlap  * @t: task being signaled
2739b0dd25a8SRandy Dunlap  *
2740b0dd25a8SRandy Dunlap  * If the audit subsystem is being terminated, record the task (pid)
2741b0dd25a8SRandy Dunlap  * and uid that is doing that.
2742b0dd25a8SRandy Dunlap  */
audit_signal_info_syscall(struct task_struct * t)2743b48345aaSRichard Guy Briggs int audit_signal_info_syscall(struct task_struct *t)
2744c2f0c7c3SSteve Grubb {
2745e54dc243SAmy Griffis 	struct audit_aux_data_pids *axp;
2746cdfb6b34SRichard Guy Briggs 	struct audit_context *ctx = audit_context();
2747b48345aaSRichard Guy Briggs 	kuid_t t_uid = task_uid(t);
2748ab6434a1SPaul Moore 
2749175fc484SAl Viro 	if (!audit_signals || audit_dummy_context())
2750e54dc243SAmy Griffis 		return 0;
2751e54dc243SAmy Griffis 
2752e54dc243SAmy Griffis 	/* optimize the common case by putting first signal recipient directly
2753e54dc243SAmy Griffis 	 * in audit_context */
2754e54dc243SAmy Griffis 	if (!ctx->target_pid) {
2755f1dc4867SRichard Guy Briggs 		ctx->target_pid = task_tgid_nr(t);
2756c2a7780eSEric Paris 		ctx->target_auid = audit_get_loginuid(t);
2757c69e8d9cSDavid Howells 		ctx->target_uid = t_uid;
27584746ec5bSEric Paris 		ctx->target_sessionid = audit_get_sessionid(t);
27594ebd7651SPaul Moore 		security_task_getsecid_obj(t, &ctx->target_sid);
2760c2a7780eSEric Paris 		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
2761e54dc243SAmy Griffis 		return 0;
2762e54dc243SAmy Griffis 	}
2763e54dc243SAmy Griffis 
2764e54dc243SAmy Griffis 	axp = (void *)ctx->aux_pids;
2765e54dc243SAmy Griffis 	if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
2766e54dc243SAmy Griffis 		axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
2767e54dc243SAmy Griffis 		if (!axp)
2768e54dc243SAmy Griffis 			return -ENOMEM;
2769e54dc243SAmy Griffis 
2770e54dc243SAmy Griffis 		axp->d.type = AUDIT_OBJ_PID;
2771e54dc243SAmy Griffis 		axp->d.next = ctx->aux_pids;
2772e54dc243SAmy Griffis 		ctx->aux_pids = (void *)axp;
2773e54dc243SAmy Griffis 	}
277488ae704cSAdrian Bunk 	BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
2775e54dc243SAmy Griffis 
2776f1dc4867SRichard Guy Briggs 	axp->target_pid[axp->pid_count] = task_tgid_nr(t);
2777c2a7780eSEric Paris 	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
2778c69e8d9cSDavid Howells 	axp->target_uid[axp->pid_count] = t_uid;
27794746ec5bSEric Paris 	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
27804ebd7651SPaul Moore 	security_task_getsecid_obj(t, &axp->target_sid[axp->pid_count]);
2781c2a7780eSEric Paris 	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
2782e54dc243SAmy Griffis 	axp->pid_count++;
2783e54dc243SAmy Griffis 
2784e54dc243SAmy Griffis 	return 0;
2785c2f0c7c3SSteve Grubb }
27860a4ff8c2SSteve Grubb 
27870a4ff8c2SSteve Grubb /**
27883fc689e9SEric Paris  * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps
2789d84f4f99SDavid Howells  * @bprm: pointer to the bprm being processed
2790d84f4f99SDavid Howells  * @new: the proposed new credentials
2791d84f4f99SDavid Howells  * @old: the old credentials
27923fc689e9SEric Paris  *
27933fc689e9SEric Paris  * Simply check if the proc already has the caps given by the file and if not
27943fc689e9SEric Paris  * store the priv escalation info for later auditing at the end of the syscall
27953fc689e9SEric Paris  *
27963fc689e9SEric Paris  * -Eric
27973fc689e9SEric Paris  */
__audit_log_bprm_fcaps(struct linux_binprm * bprm,const struct cred * new,const struct cred * old)2798d84f4f99SDavid Howells int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
2799d84f4f99SDavid Howells 			   const struct cred *new, const struct cred *old)
28003fc689e9SEric Paris {
28013fc689e9SEric Paris 	struct audit_aux_data_bprm_fcaps *ax;
2802cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
28033fc689e9SEric Paris 	struct cpu_vfs_cap_data vcaps;
28043fc689e9SEric Paris 
28053fc689e9SEric Paris 	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
28063fc689e9SEric Paris 	if (!ax)
2807d84f4f99SDavid Howells 		return -ENOMEM;
28083fc689e9SEric Paris 
28093fc689e9SEric Paris 	ax->d.type = AUDIT_BPRM_FCAPS;
28103fc689e9SEric Paris 	ax->d.next = context->aux;
28113fc689e9SEric Paris 	context->aux = (void *)ax;
28123fc689e9SEric Paris 
281339f60c1cSChristian Brauner 	get_vfs_caps_from_disk(&nop_mnt_idmap,
281471bc356fSChristian Brauner 			       bprm->file->f_path.dentry, &vcaps);
28153fc689e9SEric Paris 
28163fc689e9SEric Paris 	ax->fcap.permitted = vcaps.permitted;
28173fc689e9SEric Paris 	ax->fcap.inheritable = vcaps.inheritable;
28183fc689e9SEric Paris 	ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
28192fec30e2SRichard Guy Briggs 	ax->fcap.rootid = vcaps.rootid;
28203fc689e9SEric Paris 	ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
28213fc689e9SEric Paris 
2822d84f4f99SDavid Howells 	ax->old_pcap.permitted   = old->cap_permitted;
2823d84f4f99SDavid Howells 	ax->old_pcap.inheritable = old->cap_inheritable;
2824d84f4f99SDavid Howells 	ax->old_pcap.effective   = old->cap_effective;
28257786f6b6SRichard Guy Briggs 	ax->old_pcap.ambient     = old->cap_ambient;
28263fc689e9SEric Paris 
2827d84f4f99SDavid Howells 	ax->new_pcap.permitted   = new->cap_permitted;
2828d84f4f99SDavid Howells 	ax->new_pcap.inheritable = new->cap_inheritable;
2829d84f4f99SDavid Howells 	ax->new_pcap.effective   = new->cap_effective;
28307786f6b6SRichard Guy Briggs 	ax->new_pcap.ambient     = new->cap_ambient;
2831d84f4f99SDavid Howells 	return 0;
28323fc689e9SEric Paris }
28333fc689e9SEric Paris 
28343fc689e9SEric Paris /**
2835e68b75a0SEric Paris  * __audit_log_capset - store information about the arguments to the capset syscall
2836d84f4f99SDavid Howells  * @new: the new credentials
2837d84f4f99SDavid Howells  * @old: the old (current) credentials
2838e68b75a0SEric Paris  *
2839da3dae54SMasanari Iida  * Record the arguments userspace sent to sys_capset for later printing by the
2840e68b75a0SEric Paris  * audit system if applicable
2841e68b75a0SEric Paris  */
__audit_log_capset(const struct cred * new,const struct cred * old)2842ca24a23eSEric W. Biederman void __audit_log_capset(const struct cred *new, const struct cred *old)
2843e68b75a0SEric Paris {
2844cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2845254c8b96SRoni Nevalainen 
2846fa2bea2fSPaul Moore 	context->capset.pid = task_tgid_nr(current);
284757f71a0aSAl Viro 	context->capset.cap.effective   = new->cap_effective;
284857f71a0aSAl Viro 	context->capset.cap.inheritable = new->cap_effective;
284957f71a0aSAl Viro 	context->capset.cap.permitted   = new->cap_permitted;
28507786f6b6SRichard Guy Briggs 	context->capset.cap.ambient     = new->cap_ambient;
285157f71a0aSAl Viro 	context->type = AUDIT_CAPSET;
2852e68b75a0SEric Paris }
2853e68b75a0SEric Paris 
__audit_mmap_fd(int fd,int flags)2854120a795dSAl Viro void __audit_mmap_fd(int fd, int flags)
2855120a795dSAl Viro {
2856cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2857254c8b96SRoni Nevalainen 
2858120a795dSAl Viro 	context->mmap.fd = fd;
2859120a795dSAl Viro 	context->mmap.flags = flags;
2860120a795dSAl Viro 	context->type = AUDIT_MMAP;
2861120a795dSAl Viro }
2862120a795dSAl Viro 
__audit_openat2_how(struct open_how * how)2863571e5c0eSRichard Guy Briggs void __audit_openat2_how(struct open_how *how)
2864571e5c0eSRichard Guy Briggs {
2865571e5c0eSRichard Guy Briggs 	struct audit_context *context = audit_context();
2866571e5c0eSRichard Guy Briggs 
2867571e5c0eSRichard Guy Briggs 	context->openat2.flags = how->flags;
2868571e5c0eSRichard Guy Briggs 	context->openat2.mode = how->mode;
2869571e5c0eSRichard Guy Briggs 	context->openat2.resolve = how->resolve;
2870571e5c0eSRichard Guy Briggs 	context->type = AUDIT_OPENAT2;
2871571e5c0eSRichard Guy Briggs }
2872571e5c0eSRichard Guy Briggs 
__audit_log_kern_module(char * name)2873ca86cad7SRichard Guy Briggs void __audit_log_kern_module(char *name)
2874ca86cad7SRichard Guy Briggs {
2875cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2876ca86cad7SRichard Guy Briggs 
2877b305f7edSYi Wang 	context->module.name = kstrdup(name, GFP_KERNEL);
2878b305f7edSYi Wang 	if (!context->module.name)
2879b305f7edSYi Wang 		audit_log_lost("out of memory in __audit_log_kern_module");
2880ca86cad7SRichard Guy Briggs 	context->type = AUDIT_KERN_MODULE;
2881ca86cad7SRichard Guy Briggs }
2882ca86cad7SRichard Guy Briggs 
__audit_fanotify(u32 response,struct fanotify_response_info_audit_rule * friar)2883032bffd4SRichard Guy Briggs void __audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
2884de8cd83eSSteve Grubb {
2885032bffd4SRichard Guy Briggs 	/* {subj,obj}_trust values are {0,1,2}: no,yes,unknown */
2886032bffd4SRichard Guy Briggs 	switch (friar->hdr.type) {
2887032bffd4SRichard Guy Briggs 	case FAN_RESPONSE_INFO_NONE:
2888032bffd4SRichard Guy Briggs 		audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2889032bffd4SRichard Guy Briggs 			  "resp=%u fan_type=%u fan_info=0 subj_trust=2 obj_trust=2",
2890032bffd4SRichard Guy Briggs 			  response, FAN_RESPONSE_INFO_NONE);
2891032bffd4SRichard Guy Briggs 		break;
2892032bffd4SRichard Guy Briggs 	case FAN_RESPONSE_INFO_AUDIT_RULE:
2893032bffd4SRichard Guy Briggs 		audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2894032bffd4SRichard Guy Briggs 			  "resp=%u fan_type=%u fan_info=%X subj_trust=%u obj_trust=%u",
2895032bffd4SRichard Guy Briggs 			  response, friar->hdr.type, friar->rule_number,
2896032bffd4SRichard Guy Briggs 			  friar->subj_trust, friar->obj_trust);
2897032bffd4SRichard Guy Briggs 	}
2898de8cd83eSSteve Grubb }
2899de8cd83eSSteve Grubb 
__audit_tk_injoffset(struct timespec64 offset)29002d87a067SOndrej Mosnacek void __audit_tk_injoffset(struct timespec64 offset)
29012d87a067SOndrej Mosnacek {
2902272ceeaeSRichard Guy Briggs 	struct audit_context *context = audit_context();
29032d87a067SOndrej Mosnacek 
2904272ceeaeSRichard Guy Briggs 	/* only set type if not already set by NTP */
2905272ceeaeSRichard Guy Briggs 	if (!context->type)
2906272ceeaeSRichard Guy Briggs 		context->type = AUDIT_TIME_INJOFFSET;
2907272ceeaeSRichard Guy Briggs 	memcpy(&context->time.tk_injoffset, &offset, sizeof(offset));
29087e8eda73SOndrej Mosnacek }
29097e8eda73SOndrej Mosnacek 
__audit_ntp_log(const struct audit_ntp_data * ad)29107e8eda73SOndrej Mosnacek void __audit_ntp_log(const struct audit_ntp_data *ad)
29117e8eda73SOndrej Mosnacek {
2912272ceeaeSRichard Guy Briggs 	struct audit_context *context = audit_context();
2913272ceeaeSRichard Guy Briggs 	int type;
2914272ceeaeSRichard Guy Briggs 
2915272ceeaeSRichard Guy Briggs 	for (type = 0; type < AUDIT_NTP_NVALS; type++)
2916272ceeaeSRichard Guy Briggs 		if (ad->vals[type].newval != ad->vals[type].oldval) {
2917272ceeaeSRichard Guy Briggs 			/* unconditionally set type, overwriting TK */
2918272ceeaeSRichard Guy Briggs 			context->type = AUDIT_TIME_ADJNTPVAL;
2919272ceeaeSRichard Guy Briggs 			memcpy(&context->time.ntp_data, ad, sizeof(*ad));
2920272ceeaeSRichard Guy Briggs 			break;
2921272ceeaeSRichard Guy Briggs 		}
29227e8eda73SOndrej Mosnacek }
29237e8eda73SOndrej Mosnacek 
__audit_log_nfcfg(const char * name,u8 af,unsigned int nentries,enum audit_nfcfgop op,gfp_t gfp)2924c4dad0aaSRichard Guy Briggs void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
292514224039SRichard Guy Briggs 		       enum audit_nfcfgop op, gfp_t gfp)
2926c4dad0aaSRichard Guy Briggs {
2927c4dad0aaSRichard Guy Briggs 	struct audit_buffer *ab;
29289d44a121SRichard Guy Briggs 	char comm[sizeof(current->comm)];
2929c4dad0aaSRichard Guy Briggs 
293014224039SRichard Guy Briggs 	ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG);
2931c4dad0aaSRichard Guy Briggs 	if (!ab)
2932c4dad0aaSRichard Guy Briggs 		return;
2933c4dad0aaSRichard Guy Briggs 	audit_log_format(ab, "table=%s family=%u entries=%u op=%s",
2934c4dad0aaSRichard Guy Briggs 			 name, af, nentries, audit_nfcfgs[op].s);
29359d44a121SRichard Guy Briggs 
29369d44a121SRichard Guy Briggs 	audit_log_format(ab, " pid=%u", task_pid_nr(current));
29379d44a121SRichard Guy Briggs 	audit_log_task_context(ab); /* subj= */
29389d44a121SRichard Guy Briggs 	audit_log_format(ab, " comm=");
29399d44a121SRichard Guy Briggs 	audit_log_untrustedstring(ab, get_task_comm(comm, current));
2940c4dad0aaSRichard Guy Briggs 	audit_log_end(ab);
2941c4dad0aaSRichard Guy Briggs }
2942c4dad0aaSRichard Guy Briggs EXPORT_SYMBOL_GPL(__audit_log_nfcfg);
2943c4dad0aaSRichard Guy Briggs 
audit_log_task(struct audit_buffer * ab)29447b9205bdSKees Cook static void audit_log_task(struct audit_buffer *ab)
294585e7bac3SEric Paris {
2946cca080d9SEric W. Biederman 	kuid_t auid, uid;
2947cca080d9SEric W. Biederman 	kgid_t gid;
294885e7bac3SEric Paris 	unsigned int sessionid;
29499eab339bSRichard Guy Briggs 	char comm[sizeof(current->comm)];
295085e7bac3SEric Paris 
295185e7bac3SEric Paris 	auid = audit_get_loginuid(current);
295285e7bac3SEric Paris 	sessionid = audit_get_sessionid(current);
295385e7bac3SEric Paris 	current_uid_gid(&uid, &gid);
295485e7bac3SEric Paris 
295585e7bac3SEric Paris 	audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
2956cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, auid),
2957cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, uid),
2958cca080d9SEric W. Biederman 			 from_kgid(&init_user_ns, gid),
2959cca080d9SEric W. Biederman 			 sessionid);
296085e7bac3SEric Paris 	audit_log_task_context(ab);
2961fa2bea2fSPaul Moore 	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
29629eab339bSRichard Guy Briggs 	audit_log_untrustedstring(ab, get_task_comm(comm, current));
29634766b199SDavidlohr Bueso 	audit_log_d_path_exe(ab, current->mm);
29647b9205bdSKees Cook }
29657b9205bdSKees Cook 
2966e68b75a0SEric Paris /**
29670a4ff8c2SSteve Grubb  * audit_core_dumps - record information about processes that end abnormally
29686d9525b5SHenrik Kretzschmar  * @signr: signal value
29690a4ff8c2SSteve Grubb  *
29700a4ff8c2SSteve Grubb  * If a process ends with a core dump, something fishy is going on and we
29710a4ff8c2SSteve Grubb  * should record the event for investigation.
29720a4ff8c2SSteve Grubb  */
audit_core_dumps(long signr)29730a4ff8c2SSteve Grubb void audit_core_dumps(long signr)
29740a4ff8c2SSteve Grubb {
29750a4ff8c2SSteve Grubb 	struct audit_buffer *ab;
29760a4ff8c2SSteve Grubb 
29770a4ff8c2SSteve Grubb 	if (!audit_enabled)
29780a4ff8c2SSteve Grubb 		return;
29790a4ff8c2SSteve Grubb 
29800a4ff8c2SSteve Grubb 	if (signr == SIGQUIT)	/* don't care for those */
29810a4ff8c2SSteve Grubb 		return;
29820a4ff8c2SSteve Grubb 
2983d87de4a8SRichard Guy Briggs 	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_ABEND);
29840644ec0cSKees Cook 	if (unlikely(!ab))
29850644ec0cSKees Cook 		return;
298661c0ee87SPaul Davies C 	audit_log_task(ab);
298789670affSSteve Grubb 	audit_log_format(ab, " sig=%ld res=1", signr);
298885e7bac3SEric Paris 	audit_log_end(ab);
298985e7bac3SEric Paris }
29900a4ff8c2SSteve Grubb 
2991326bee02STyler Hicks /**
2992326bee02STyler Hicks  * audit_seccomp - record information about a seccomp action
2993326bee02STyler Hicks  * @syscall: syscall number
2994326bee02STyler Hicks  * @signr: signal value
2995326bee02STyler Hicks  * @code: the seccomp action
2996326bee02STyler Hicks  *
2997326bee02STyler Hicks  * Record the information associated with a seccomp action. Event filtering for
2998326bee02STyler Hicks  * seccomp actions that are not to be logged is done in seccomp_log().
2999326bee02STyler Hicks  * Therefore, this function forces auditing independent of the audit_enabled
3000326bee02STyler Hicks  * and dummy context state because seccomp actions should be logged even when
3001326bee02STyler Hicks  * audit is not in use.
3002326bee02STyler Hicks  */
audit_seccomp(unsigned long syscall,long signr,int code)3003326bee02STyler Hicks void audit_seccomp(unsigned long syscall, long signr, int code)
300485e7bac3SEric Paris {
300585e7bac3SEric Paris 	struct audit_buffer *ab;
300685e7bac3SEric Paris 
30079b8753ffSRichard Guy Briggs 	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_SECCOMP);
30087b9205bdSKees Cook 	if (unlikely(!ab))
30097b9205bdSKees Cook 		return;
30107b9205bdSKees Cook 	audit_log_task(ab);
301184db564aSRichard Guy Briggs 	audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
301216add411SDmitry V. Levin 			 signr, syscall_get_arch(current), syscall,
3013efbc0fbfSAndy Lutomirski 			 in_compat_syscall(), KSTK_EIP(current), code);
30140a4ff8c2SSteve Grubb 	audit_log_end(ab);
30150a4ff8c2SSteve Grubb }
3016916d7576SAl Viro 
audit_seccomp_actions_logged(const char * names,const char * old_names,int res)3017ea6eca77STyler Hicks void audit_seccomp_actions_logged(const char *names, const char *old_names,
3018ea6eca77STyler Hicks 				  int res)
3019ea6eca77STyler Hicks {
3020ea6eca77STyler Hicks 	struct audit_buffer *ab;
3021ea6eca77STyler Hicks 
3022ea6eca77STyler Hicks 	if (!audit_enabled)
3023ea6eca77STyler Hicks 		return;
3024ea6eca77STyler Hicks 
30258982a1fbSRichard Guy Briggs 	ab = audit_log_start(audit_context(), GFP_KERNEL,
3026ea6eca77STyler Hicks 			     AUDIT_CONFIG_CHANGE);
3027ea6eca77STyler Hicks 	if (unlikely(!ab))
3028ea6eca77STyler Hicks 		return;
3029ea6eca77STyler Hicks 
3030d0a3f18aSPaul Moore 	audit_log_format(ab,
3031d0a3f18aSPaul Moore 			 "op=seccomp-logging actions=%s old-actions=%s res=%d",
3032d0a3f18aSPaul Moore 			 names, old_names, res);
3033ea6eca77STyler Hicks 	audit_log_end(ab);
3034ea6eca77STyler Hicks }
3035ea6eca77STyler Hicks 
audit_killed_trees(void)3036916d7576SAl Viro struct list_head *audit_killed_trees(void)
3037916d7576SAl Viro {
3038cdfb6b34SRichard Guy Briggs 	struct audit_context *ctx = audit_context();
303912c5e81dSPaul Moore 	if (likely(!ctx || ctx->context == AUDIT_CTX_UNUSED))
3040916d7576SAl Viro 		return NULL;
3041916d7576SAl Viro 	return &ctx->killed_trees;
3042916d7576SAl Viro }
3043