xref: /linux-6.15/kernel/auditsc.c (revision 61185101)
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 <[email protected]>
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  * [email protected] and Copyright 2003 SuSE Linux AG.
181da177e4SLinus Torvalds  *
1920ca73bcSGeorge C. Wilson  * POSIX message queue support added by George Wilson <[email protected]>,
2020ca73bcSGeorge C. Wilson  * 2006.
2120ca73bcSGeorge C. Wilson  *
22b63862f4SDustin Kirkland  * The support of additional filter rules compares (>, <, >=, <=) was
23b63862f4SDustin Kirkland  * added by Dustin Kirkland <[email protected]>, 2005.
24b63862f4SDustin Kirkland  *
2573241cccSAmy Griffis  * Modified by Amy Griffis <[email protected]> to collect additional
2673241cccSAmy Griffis  * filesystem information.
278c8570fbSDustin Kirkland  *
288c8570fbSDustin Kirkland  * Subject and object context labeling support added by <[email protected]>
298c8570fbSDustin Kirkland  * and <[email protected]> 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];
10313d826e5SCasey Schaufler 	struct lsm_prop		target_ref[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;
473870b7fdcSCasey Schaufler 	struct lsm_prop prop = { };
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
67737f670aaSCasey Schaufler 					 * use
67837f670aaSCasey Schaufler 					 * security_current_getlsmprop_subj()
6796326948fSPaul Moore 					 * here even though it always refs
6806326948fSPaul Moore 					 * @current's creds
6816326948fSPaul Moore 					 */
68237f670aaSCasey Schaufler 					security_current_getlsmprop_subj(&prop);
6832ad312d2SSteve Grubb 					need_sid = 0;
6842ad312d2SSteve Grubb 				}
685870b7fdcSCasey Schaufler 				result = security_audit_rule_match(&prop,
686870b7fdcSCasey Schaufler 								   f->type,
6873dc7e315SDarrel Goeddel 								   f->op,
68890462a5bSRichard Guy Briggs 								   f->lsm_rule);
6892ad312d2SSteve Grubb 			}
6903dc7e315SDarrel Goeddel 			break;
6916e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_USER:
6926e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_ROLE:
6936e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_TYPE:
6946e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_LEV_LOW:
6956e5a2d1dSDarrel Goeddel 		case AUDIT_OBJ_LEV_HIGH:
6966e5a2d1dSDarrel Goeddel 			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
6976e5a2d1dSDarrel Goeddel 			   also applies here */
69804305e4aSAhmed S. Darwish 			if (f->lsm_rule) {
6996e5a2d1dSDarrel Goeddel 				/* Find files that match */
7006e5a2d1dSDarrel Goeddel 				if (name) {
701d7a96f3aSAhmed S. Darwish 					result = security_audit_rule_match(
702e0a8dcbdSCasey Schaufler 								&name->oprop,
70390462a5bSRichard Guy Briggs 								f->type,
70490462a5bSRichard Guy Briggs 								f->op,
70590462a5bSRichard Guy Briggs 								f->lsm_rule);
7066e5a2d1dSDarrel Goeddel 				} else if (ctx) {
7075195d8e2SEric Paris 					list_for_each_entry(n, &ctx->names_list, list) {
70890462a5bSRichard Guy Briggs 						if (security_audit_rule_match(
709e0a8dcbdSCasey Schaufler 								&n->oprop,
71090462a5bSRichard Guy Briggs 								f->type,
71190462a5bSRichard Guy Briggs 								f->op,
71290462a5bSRichard Guy Briggs 								f->lsm_rule)) {
7136e5a2d1dSDarrel Goeddel 							++result;
7146e5a2d1dSDarrel Goeddel 							break;
7156e5a2d1dSDarrel Goeddel 						}
7166e5a2d1dSDarrel Goeddel 					}
7176e5a2d1dSDarrel Goeddel 				}
7186e5a2d1dSDarrel Goeddel 				/* Find ipc objects that match */
719a33e6751SAl Viro 				if (!ctx || ctx->type != AUDIT_IPC)
7206e5a2d1dSDarrel Goeddel 					break;
7217183abccSCasey Schaufler 				if (security_audit_rule_match(&ctx->ipc.oprop,
722a33e6751SAl Viro 							      f->type, f->op,
72390462a5bSRichard Guy Briggs 							      f->lsm_rule))
724a33e6751SAl Viro 					++result;
7256e5a2d1dSDarrel Goeddel 			}
7266e5a2d1dSDarrel Goeddel 			break;
7271da177e4SLinus Torvalds 		case AUDIT_ARG0:
7281da177e4SLinus Torvalds 		case AUDIT_ARG1:
7291da177e4SLinus Torvalds 		case AUDIT_ARG2:
7301da177e4SLinus Torvalds 		case AUDIT_ARG3:
7311da177e4SLinus Torvalds 			if (ctx)
73293315ed6SAmy Griffis 				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
7331da177e4SLinus Torvalds 			break;
7345adc8a6aSAmy Griffis 		case AUDIT_FILTERKEY:
7355adc8a6aSAmy Griffis 			/* ignore this field for filtering */
7365adc8a6aSAmy Griffis 			result = 1;
7375adc8a6aSAmy Griffis 			break;
73855669bfaSAl Viro 		case AUDIT_PERM:
73955669bfaSAl Viro 			result = audit_match_perm(ctx, f->val);
7400223fad3SRichard Guy Briggs 			if (f->op == Audit_not_equal)
7410223fad3SRichard Guy Briggs 				result = !result;
74255669bfaSAl Viro 			break;
7438b67dca9SAl Viro 		case AUDIT_FILETYPE:
7448b67dca9SAl Viro 			result = audit_match_filetype(ctx, f->val);
7450223fad3SRichard Guy Briggs 			if (f->op == Audit_not_equal)
7460223fad3SRichard Guy Briggs 				result = !result;
7478b67dca9SAl Viro 			break;
74802d86a56SEric Paris 		case AUDIT_FIELD_COMPARE:
74902d86a56SEric Paris 			result = audit_field_compare(tsk, cred, f, ctx, name);
75002d86a56SEric Paris 			break;
7511da177e4SLinus Torvalds 		}
752f5629883STony Jones 		if (!result)
7531da177e4SLinus Torvalds 			return 0;
7541da177e4SLinus Torvalds 	}
7550590b933SAl Viro 
7560590b933SAl Viro 	if (ctx) {
7570590b933SAl Viro 		if (rule->filterkey) {
7580590b933SAl Viro 			kfree(ctx->filterkey);
7595adc8a6aSAmy Griffis 			ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
7600590b933SAl Viro 		}
7610590b933SAl Viro 		ctx->prio = rule->prio;
7620590b933SAl Viro 	}
7631da177e4SLinus Torvalds 	switch (rule->action) {
76466b12abcSPaul Moore 	case AUDIT_NEVER:
765619ed58aSSergey Nazarov 		*state = AUDIT_STATE_DISABLED;
76666b12abcSPaul Moore 		break;
76766b12abcSPaul Moore 	case AUDIT_ALWAYS:
768619ed58aSSergey Nazarov 		*state = AUDIT_STATE_RECORD;
76966b12abcSPaul Moore 		break;
7701da177e4SLinus Torvalds 	}
7711da177e4SLinus Torvalds 	return 1;
7721da177e4SLinus Torvalds }
7731da177e4SLinus Torvalds 
7741da177e4SLinus Torvalds /* At process creation time, we can determine if system-call auditing is
7751da177e4SLinus Torvalds  * completely disabled for this task.  Since we only have the task
7761da177e4SLinus Torvalds  * structure at this point, we can only check uid and gid.
7771da177e4SLinus Torvalds  */
audit_filter_task(struct task_struct * tsk,char ** key)778e048e02cSAl Viro static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
7791da177e4SLinus Torvalds {
7801da177e4SLinus Torvalds 	struct audit_entry *e;
7811da177e4SLinus Torvalds 	enum audit_state   state;
7821da177e4SLinus Torvalds 
7831da177e4SLinus Torvalds 	rcu_read_lock();
7840f45aa18SDavid Woodhouse 	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
785f5629883STony Jones 		if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
786f5629883STony Jones 				       &state, true)) {
787619ed58aSSergey Nazarov 			if (state == AUDIT_STATE_RECORD)
788e048e02cSAl Viro 				*key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
7891da177e4SLinus Torvalds 			rcu_read_unlock();
7901da177e4SLinus Torvalds 			return state;
7911da177e4SLinus Torvalds 		}
7921da177e4SLinus Torvalds 	}
7931da177e4SLinus Torvalds 	rcu_read_unlock();
794619ed58aSSergey Nazarov 	return AUDIT_STATE_BUILD;
7951da177e4SLinus Torvalds }
7961da177e4SLinus Torvalds 
audit_in_mask(const struct audit_krule * rule,unsigned long val)797a3c54931SAndy Lutomirski static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
798a3c54931SAndy Lutomirski {
799a3c54931SAndy Lutomirski 	int word, bit;
800a3c54931SAndy Lutomirski 
801a3c54931SAndy Lutomirski 	if (val > 0xffffffff)
802a3c54931SAndy Lutomirski 		return false;
803a3c54931SAndy Lutomirski 
804a3c54931SAndy Lutomirski 	word = AUDIT_WORD(val);
805a3c54931SAndy Lutomirski 	if (word >= AUDIT_BITMASK_SIZE)
806a3c54931SAndy Lutomirski 		return false;
807a3c54931SAndy Lutomirski 
808a3c54931SAndy Lutomirski 	bit = AUDIT_BIT(val);
809a3c54931SAndy Lutomirski 
810a3c54931SAndy Lutomirski 	return rule->mask[word] & bit;
811a3c54931SAndy Lutomirski }
812a3c54931SAndy Lutomirski 
81367daf270SPaul Moore /**
81450979953SAnkur Arora  * __audit_filter_op - common filter helper for operations (syscall/uring/etc)
81550979953SAnkur Arora  * @tsk: associated task
81650979953SAnkur Arora  * @ctx: audit context
81750979953SAnkur Arora  * @list: audit filter list
81850979953SAnkur Arora  * @name: audit_name (can be NULL)
81950979953SAnkur Arora  * @op: current syscall/uring_op
82050979953SAnkur Arora  *
82150979953SAnkur Arora  * Run the udit filters specified in @list against @tsk using @ctx,
82250979953SAnkur Arora  * @name, and @op, as necessary; the caller is responsible for ensuring
82350979953SAnkur Arora  * that the call is made while the RCU read lock is held. The @name
82450979953SAnkur Arora  * parameter can be NULL, but all others must be specified.
82550979953SAnkur Arora  * Returns 1/true if the filter finds a match, 0/false if none are found.
82650979953SAnkur Arora  */
__audit_filter_op(struct task_struct * tsk,struct audit_context * ctx,struct list_head * list,struct audit_names * name,unsigned long op)82750979953SAnkur Arora static int __audit_filter_op(struct task_struct *tsk,
82850979953SAnkur Arora 			   struct audit_context *ctx,
82950979953SAnkur Arora 			   struct list_head *list,
83050979953SAnkur Arora 			   struct audit_names *name,
83150979953SAnkur Arora 			   unsigned long op)
83250979953SAnkur Arora {
83350979953SAnkur Arora 	struct audit_entry *e;
83450979953SAnkur Arora 	enum audit_state state;
83550979953SAnkur Arora 
83650979953SAnkur Arora 	list_for_each_entry_rcu(e, list, list) {
83750979953SAnkur Arora 		if (audit_in_mask(&e->rule, op) &&
83850979953SAnkur Arora 		    audit_filter_rules(tsk, &e->rule, ctx, name,
83950979953SAnkur Arora 				       &state, false)) {
84050979953SAnkur Arora 			ctx->current_state = state;
84150979953SAnkur Arora 			return 1;
84250979953SAnkur Arora 		}
84350979953SAnkur Arora 	}
84450979953SAnkur Arora 	return 0;
84550979953SAnkur Arora }
84650979953SAnkur Arora 
84750979953SAnkur Arora /**
84867daf270SPaul Moore  * audit_filter_uring - apply filters to an io_uring operation
84967daf270SPaul Moore  * @tsk: associated task
85067daf270SPaul Moore  * @ctx: audit context
85167daf270SPaul Moore  */
audit_filter_uring(struct task_struct * tsk,struct audit_context * ctx)85267daf270SPaul Moore static void audit_filter_uring(struct task_struct *tsk,
85367daf270SPaul Moore 			       struct audit_context *ctx)
85467daf270SPaul Moore {
85567daf270SPaul Moore 	if (auditd_test_task(tsk))
85667daf270SPaul Moore 		return;
85767daf270SPaul Moore 
85867daf270SPaul Moore 	rcu_read_lock();
85950979953SAnkur Arora 	__audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_URING_EXIT],
86050979953SAnkur Arora 			NULL, ctx->uring_op);
86167daf270SPaul Moore 	rcu_read_unlock();
86267daf270SPaul Moore }
86367daf270SPaul Moore 
864127c8c5fSYang Yang /* At syscall exit time, this filter is called if the audit_state is
865127c8c5fSYang Yang  * not low enough that auditing cannot take place, but is also not
866127c8c5fSYang Yang  * high enough that we already know we have to write an audit record
867619ed58aSSergey Nazarov  * (i.e., the state is AUDIT_STATE_BUILD).
8681da177e4SLinus Torvalds  */
audit_filter_syscall(struct task_struct * tsk,struct audit_context * ctx)869127c8c5fSYang Yang static void audit_filter_syscall(struct task_struct *tsk,
8705504a69aSRichard Guy Briggs 				 struct audit_context *ctx)
8711da177e4SLinus Torvalds {
8725b52330bSPaul Moore 	if (auditd_test_task(tsk))
873127c8c5fSYang Yang 		return;
874f7056d64SDavid Woodhouse 
8751da177e4SLinus Torvalds 	rcu_read_lock();
87650979953SAnkur Arora 	__audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_EXIT],
87750979953SAnkur Arora 			NULL, ctx->major);
8781da177e4SLinus Torvalds 	rcu_read_unlock();
8791da177e4SLinus Torvalds }
8801da177e4SLinus Torvalds 
8815195d8e2SEric Paris /*
8825195d8e2SEric Paris  * Given an audit_name check the inode hash table to see if they match.
8835195d8e2SEric Paris  * Called holding the rcu read lock to protect the use of audit_inode_hash
8845195d8e2SEric Paris  */
audit_filter_inode_name(struct task_struct * tsk,struct audit_names * n,struct audit_context * ctx)8855195d8e2SEric Paris static int audit_filter_inode_name(struct task_struct *tsk,
8865195d8e2SEric Paris 				   struct audit_names *n,
88722cde101SAtul Kumar Pant 				   struct audit_context *ctx)
88822cde101SAtul Kumar Pant {
8895195d8e2SEric Paris 	int h = audit_hash_ino((u32)n->ino);
8905195d8e2SEric Paris 	struct list_head *list = &audit_inode_hash[h];
8915195d8e2SEric Paris 
89250979953SAnkur Arora 	return __audit_filter_op(tsk, ctx, list, n, ctx->major);
8935195d8e2SEric Paris }
8945195d8e2SEric Paris 
8955195d8e2SEric Paris /* At syscall exit time, this filter is called if any audit_names have been
896f368c07dSAmy Griffis  * collected during syscall processing.  We only check rules in sublists at hash
8975195d8e2SEric Paris  * buckets applicable to the inode numbers in audit_names.
898f368c07dSAmy Griffis  * Regarding audit_state, same rules apply as for audit_filter_syscall().
899f368c07dSAmy Griffis  */
audit_filter_inodes(struct task_struct * tsk,struct audit_context * ctx)9000590b933SAl Viro void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
901f368c07dSAmy Griffis {
9025195d8e2SEric Paris 	struct audit_names *n;
903f368c07dSAmy Griffis 
9045b52330bSPaul Moore 	if (auditd_test_task(tsk))
9050590b933SAl Viro 		return;
906f368c07dSAmy Griffis 
907f368c07dSAmy Griffis 	rcu_read_lock();
908f368c07dSAmy Griffis 
9095195d8e2SEric Paris 	list_for_each_entry(n, &ctx->names_list, list) {
9105195d8e2SEric Paris 		if (audit_filter_inode_name(tsk, n, ctx))
9115195d8e2SEric Paris 			break;
912f368c07dSAmy Griffis 	}
913f368c07dSAmy Griffis 	rcu_read_unlock();
914f368c07dSAmy Griffis }
915f368c07dSAmy Griffis 
audit_proctitle_free(struct audit_context * context)9163f1c8250SWilliam Roberts static inline void audit_proctitle_free(struct audit_context *context)
9173f1c8250SWilliam Roberts {
9183f1c8250SWilliam Roberts 	kfree(context->proctitle.value);
9193f1c8250SWilliam Roberts 	context->proctitle.value = NULL;
9203f1c8250SWilliam Roberts 	context->proctitle.len = 0;
9213f1c8250SWilliam Roberts }
9223f1c8250SWilliam Roberts 
audit_free_module(struct audit_context * context)92395e0b46fSLi RongQing static inline void audit_free_module(struct audit_context *context)
92495e0b46fSLi RongQing {
92595e0b46fSLi RongQing 	if (context->type == AUDIT_KERN_MODULE) {
92695e0b46fSLi RongQing 		kfree(context->module.name);
92795e0b46fSLi RongQing 		context->module.name = NULL;
92895e0b46fSLi RongQing 	}
92995e0b46fSLi RongQing }
audit_free_names(struct audit_context * context)9301da177e4SLinus Torvalds static inline void audit_free_names(struct audit_context *context)
9311da177e4SLinus Torvalds {
9325195d8e2SEric Paris 	struct audit_names *n, *next;
9331da177e4SLinus Torvalds 
9345195d8e2SEric Paris 	list_for_each_entry_safe(n, next, &context->names_list, list) {
9355195d8e2SEric Paris 		list_del(&n->list);
93655422d0bSPaul Moore 		if (n->name)
93755422d0bSPaul Moore 			putname(n->name);
9385195d8e2SEric Paris 		if (n->should_free)
9395195d8e2SEric Paris 			kfree(n);
9408c8570fbSDustin Kirkland 	}
9411da177e4SLinus Torvalds 	context->name_count = 0;
94244707fdfSJan Blunck 	path_put(&context->pwd);
94344707fdfSJan Blunck 	context->pwd.dentry = NULL;
94444707fdfSJan Blunck 	context->pwd.mnt = NULL;
9451da177e4SLinus Torvalds }
9461da177e4SLinus Torvalds 
audit_free_aux(struct audit_context * context)9471da177e4SLinus Torvalds static inline void audit_free_aux(struct audit_context *context)
9481da177e4SLinus Torvalds {
9491da177e4SLinus Torvalds 	struct audit_aux_data *aux;
9501da177e4SLinus Torvalds 
9511da177e4SLinus Torvalds 	while ((aux = context->aux)) {
9521da177e4SLinus Torvalds 		context->aux = aux->next;
9531da177e4SLinus Torvalds 		kfree(aux);
9541da177e4SLinus Torvalds 	}
95512c5e81dSPaul Moore 	context->aux = NULL;
956e54dc243SAmy Griffis 	while ((aux = context->aux_pids)) {
957e54dc243SAmy Griffis 		context->aux_pids = aux->next;
958e54dc243SAmy Griffis 		kfree(aux);
959e54dc243SAmy Griffis 	}
96012c5e81dSPaul Moore 	context->aux_pids = NULL;
96112c5e81dSPaul Moore }
96212c5e81dSPaul Moore 
96312c5e81dSPaul Moore /**
96412c5e81dSPaul Moore  * audit_reset_context - reset a audit_context structure
96512c5e81dSPaul Moore  * @ctx: the audit_context to reset
96612c5e81dSPaul Moore  *
96712c5e81dSPaul Moore  * All fields in the audit_context will be reset to an initial state, all
96812c5e81dSPaul Moore  * references held by fields will be dropped, and private memory will be
96912c5e81dSPaul Moore  * released.  When this function returns the audit_context will be suitable
97012c5e81dSPaul Moore  * for reuse, so long as the passed context is not NULL or a dummy context.
97112c5e81dSPaul Moore  */
audit_reset_context(struct audit_context * ctx)97212c5e81dSPaul Moore static void audit_reset_context(struct audit_context *ctx)
97312c5e81dSPaul Moore {
97412c5e81dSPaul Moore 	if (!ctx)
97512c5e81dSPaul Moore 		return;
97612c5e81dSPaul Moore 
977e84d9f52SRichard Guy Briggs 	/* if ctx is non-null, reset the "ctx->context" regardless */
97812c5e81dSPaul Moore 	ctx->context = AUDIT_CTX_UNUSED;
97912c5e81dSPaul Moore 	if (ctx->dummy)
98012c5e81dSPaul Moore 		return;
98112c5e81dSPaul Moore 
98212c5e81dSPaul Moore 	/*
98312c5e81dSPaul Moore 	 * NOTE: It shouldn't matter in what order we release the fields, so
98412c5e81dSPaul Moore 	 *       release them in the order in which they appear in the struct;
98512c5e81dSPaul Moore 	 *       this gives us some hope of quickly making sure we are
98612c5e81dSPaul Moore 	 *       resetting the audit_context properly.
98712c5e81dSPaul Moore 	 *
98812c5e81dSPaul Moore 	 *       Other things worth mentioning:
98912c5e81dSPaul Moore 	 *       - we don't reset "dummy"
99012c5e81dSPaul Moore 	 *       - we don't reset "state", we do reset "current_state"
99112c5e81dSPaul Moore 	 *       - we preserve "filterkey" if "state" is AUDIT_STATE_RECORD
99212c5e81dSPaul Moore 	 *       - much of this is likely overkill, but play it safe for now
99312c5e81dSPaul Moore 	 *       - we really need to work on improving the audit_context struct
99412c5e81dSPaul Moore 	 */
99512c5e81dSPaul Moore 
99612c5e81dSPaul Moore 	ctx->current_state = ctx->state;
99712c5e81dSPaul Moore 	ctx->serial = 0;
99812c5e81dSPaul Moore 	ctx->major = 0;
9995bd2182dSPaul Moore 	ctx->uring_op = 0;
100012c5e81dSPaul Moore 	ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
100112c5e81dSPaul Moore 	memset(ctx->argv, 0, sizeof(ctx->argv));
100212c5e81dSPaul Moore 	ctx->return_code = 0;
100312c5e81dSPaul Moore 	ctx->prio = (ctx->state == AUDIT_STATE_RECORD ? ~0ULL : 0);
100412c5e81dSPaul Moore 	ctx->return_valid = AUDITSC_INVALID;
100512c5e81dSPaul Moore 	audit_free_names(ctx);
100612c5e81dSPaul Moore 	if (ctx->state != AUDIT_STATE_RECORD) {
100712c5e81dSPaul Moore 		kfree(ctx->filterkey);
100812c5e81dSPaul Moore 		ctx->filterkey = NULL;
100912c5e81dSPaul Moore 	}
101012c5e81dSPaul Moore 	audit_free_aux(ctx);
101112c5e81dSPaul Moore 	kfree(ctx->sockaddr);
101212c5e81dSPaul Moore 	ctx->sockaddr = NULL;
101312c5e81dSPaul Moore 	ctx->sockaddr_len = 0;
1014e84d9f52SRichard Guy Briggs 	ctx->ppid = 0;
101512c5e81dSPaul Moore 	ctx->uid = ctx->euid = ctx->suid = ctx->fsuid = KUIDT_INIT(0);
101612c5e81dSPaul Moore 	ctx->gid = ctx->egid = ctx->sgid = ctx->fsgid = KGIDT_INIT(0);
101712c5e81dSPaul Moore 	ctx->personality = 0;
101812c5e81dSPaul Moore 	ctx->arch = 0;
101912c5e81dSPaul Moore 	ctx->target_pid = 0;
102012c5e81dSPaul Moore 	ctx->target_auid = ctx->target_uid = KUIDT_INIT(0);
102112c5e81dSPaul Moore 	ctx->target_sessionid = 0;
102213d826e5SCasey Schaufler 	lsmprop_init(&ctx->target_ref);
102312c5e81dSPaul Moore 	ctx->target_comm[0] = '\0';
102412c5e81dSPaul Moore 	unroll_tree_refs(ctx, NULL, 0);
102512c5e81dSPaul Moore 	WARN_ON(!list_empty(&ctx->killed_trees));
102612c5e81dSPaul Moore 	audit_free_module(ctx);
102712c5e81dSPaul Moore 	ctx->fds[0] = -1;
1028ef79c396SChristian Göttsche 	ctx->type = 0; /* reset last for audit_free_*() */
10291da177e4SLinus Torvalds }
10301da177e4SLinus Torvalds 
audit_alloc_context(enum audit_state state)10311da177e4SLinus Torvalds static inline struct audit_context *audit_alloc_context(enum audit_state state)
10321da177e4SLinus Torvalds {
10331da177e4SLinus Torvalds 	struct audit_context *context;
10341da177e4SLinus Torvalds 
103517c6ee70SRakib Mullick 	context = kzalloc(sizeof(*context), GFP_KERNEL);
103617c6ee70SRakib Mullick 	if (!context)
10371da177e4SLinus Torvalds 		return NULL;
103812c5e81dSPaul Moore 	context->context = AUDIT_CTX_UNUSED;
1039e2c5adc8SAndrew Morton 	context->state = state;
1040619ed58aSSergey Nazarov 	context->prio = state == AUDIT_STATE_RECORD ? ~0ULL : 0;
1041916d7576SAl Viro 	INIT_LIST_HEAD(&context->killed_trees);
10425195d8e2SEric Paris 	INIT_LIST_HEAD(&context->names_list);
10436d915476SRichard Guy Briggs 	context->fds[0] = -1;
1044ba59eae7SAlex Shi 	context->return_valid = AUDITSC_INVALID;
10451da177e4SLinus Torvalds 	return context;
10461da177e4SLinus Torvalds }
10471da177e4SLinus Torvalds 
1048b0dd25a8SRandy Dunlap /**
1049b0dd25a8SRandy Dunlap  * audit_alloc - allocate an audit context block for a task
1050b0dd25a8SRandy Dunlap  * @tsk: task
1051b0dd25a8SRandy Dunlap  *
1052b0dd25a8SRandy Dunlap  * Filter on the task information and allocate a per-task audit context
10531da177e4SLinus Torvalds  * if necessary.  Doing so turns on system call auditing for the
10541da177e4SLinus Torvalds  * specified task.  This is called from copy_process, so no lock is
1055b0dd25a8SRandy Dunlap  * needed.
1056b0dd25a8SRandy Dunlap  */
audit_alloc(struct task_struct * tsk)10571da177e4SLinus Torvalds int audit_alloc(struct task_struct *tsk)
10581da177e4SLinus Torvalds {
10591da177e4SLinus Torvalds 	struct audit_context *context;
10601da177e4SLinus Torvalds 	enum audit_state     state;
1061e048e02cSAl Viro 	char *key = NULL;
10621da177e4SLinus Torvalds 
1063b593d384SEric Paris 	if (likely(!audit_ever_enabled))
106412c5e81dSPaul Moore 		return 0;
10651da177e4SLinus Torvalds 
1066e048e02cSAl Viro 	state = audit_filter_task(tsk, &key);
1067619ed58aSSergey Nazarov 	if (state == AUDIT_STATE_DISABLED) {
1068785dc4ebSGabriel Krisman Bertazi 		clear_task_syscall_work(tsk, SYSCALL_AUDIT);
10691da177e4SLinus Torvalds 		return 0;
1070d48d8051SOleg Nesterov 	}
10711da177e4SLinus Torvalds 
107222cde101SAtul Kumar Pant 	context = audit_alloc_context(state);
107322cde101SAtul Kumar Pant 	if (!context) {
1074e048e02cSAl Viro 		kfree(key);
10751da177e4SLinus Torvalds 		audit_log_lost("out of memory in audit_alloc");
10761da177e4SLinus Torvalds 		return -ENOMEM;
10771da177e4SLinus Torvalds 	}
1078e048e02cSAl Viro 	context->filterkey = key;
10791da177e4SLinus Torvalds 
1080c0b0ae8aSRichard Guy Briggs 	audit_set_context(tsk, context);
1081785dc4ebSGabriel Krisman Bertazi 	set_task_syscall_work(tsk, SYSCALL_AUDIT);
10821da177e4SLinus Torvalds 	return 0;
10831da177e4SLinus Torvalds }
10841da177e4SLinus Torvalds 
audit_free_context(struct audit_context * context)10851da177e4SLinus Torvalds static inline void audit_free_context(struct audit_context *context)
10861da177e4SLinus Torvalds {
108712c5e81dSPaul Moore 	/* resetting is extra work, but it is likely just noise */
108812c5e81dSPaul Moore 	audit_reset_context(context);
1089c3f3ea8aSRichard Guy Briggs 	audit_proctitle_free(context);
109074c3cbe3SAl Viro 	free_tree_refs(context);
10915adc8a6aSAmy Griffis 	kfree(context->filterkey);
10921da177e4SLinus Torvalds 	kfree(context);
10931da177e4SLinus Torvalds }
10941da177e4SLinus Torvalds 
audit_log_pid_context(struct audit_context * context,pid_t pid,kuid_t auid,kuid_t uid,unsigned int sessionid,struct lsm_prop * prop,char * comm)1095e54dc243SAmy Griffis static int audit_log_pid_context(struct audit_context *context, pid_t pid,
109613d826e5SCasey Schaufler 				 kuid_t auid, kuid_t uid,
109713d826e5SCasey Schaufler 				 unsigned int sessionid, struct lsm_prop *prop,
109813d826e5SCasey Schaufler 				 char *comm)
1099e54dc243SAmy Griffis {
1100e54dc243SAmy Griffis 	struct audit_buffer *ab;
11016fba8981SCasey Schaufler 	struct lsm_context ctx;
1102e54dc243SAmy Griffis 	int rc = 0;
1103e54dc243SAmy Griffis 
1104e54dc243SAmy Griffis 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
1105e54dc243SAmy Griffis 	if (!ab)
11066246ccabSEric Paris 		return rc;
1107e54dc243SAmy Griffis 
1108e1760bd5SEric W. Biederman 	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
1109e1760bd5SEric W. Biederman 			 from_kuid(&init_user_ns, auid),
1110cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, uid), sessionid);
111113d826e5SCasey Schaufler 	if (lsmprop_is_set(prop)) {
11122d470c77SCasey Schaufler 		if (security_lsmprop_to_secctx(prop, &ctx) < 0) {
1113c2a7780eSEric Paris 			audit_log_format(ab, " obj=(none)");
1114e54dc243SAmy Griffis 			rc = 1;
11152a862b32SAhmed S. Darwish 		} else {
11166fba8981SCasey Schaufler 			audit_log_format(ab, " obj=%s", ctx.context);
11176fba8981SCasey Schaufler 			security_release_secctx(&ctx);
11182a862b32SAhmed S. Darwish 		}
1119ad395abeSEric Paris 	}
1120c2a7780eSEric Paris 	audit_log_format(ab, " ocomm=");
1121c2a7780eSEric Paris 	audit_log_untrustedstring(ab, comm);
1122e54dc243SAmy Griffis 	audit_log_end(ab);
1123e54dc243SAmy Griffis 
1124e54dc243SAmy Griffis 	return rc;
1125e54dc243SAmy Griffis }
1126e54dc243SAmy Griffis 
audit_log_execve_info(struct audit_context * context,struct audit_buffer ** ab)1127de6bbd1dSEric Paris static void audit_log_execve_info(struct audit_context *context,
1128d9cfea91SRichard Guy Briggs 				  struct audit_buffer **ab)
1129de6bbd1dSEric Paris {
113043761473SPaul Moore 	long len_max;
113143761473SPaul Moore 	long len_rem;
113243761473SPaul Moore 	long len_full;
113343761473SPaul Moore 	long len_buf;
11348443075eSRichard Guy Briggs 	long len_abuf = 0;
113543761473SPaul Moore 	long len_tmp;
113643761473SPaul Moore 	bool require_data;
113743761473SPaul Moore 	bool encode;
113843761473SPaul Moore 	unsigned int iter;
113943761473SPaul Moore 	unsigned int arg;
114043761473SPaul Moore 	char *buf_head;
1141de6bbd1dSEric Paris 	char *buf;
114243761473SPaul Moore 	const char __user *p = (const char __user *)current->mm->arg_start;
1143de6bbd1dSEric Paris 
114443761473SPaul Moore 	/* NOTE: this buffer needs to be large enough to hold all the non-arg
114543761473SPaul Moore 	 *       data we put in the audit record for this argument (see the
114643761473SPaul Moore 	 *       code below) ... at this point in time 96 is plenty */
114743761473SPaul Moore 	char abuf[96];
1148de6bbd1dSEric Paris 
114943761473SPaul Moore 	/* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the
115043761473SPaul Moore 	 *       current value of 7500 is not as important as the fact that it
115143761473SPaul Moore 	 *       is less than 8k, a setting of 7500 gives us plenty of wiggle
115243761473SPaul Moore 	 *       room if we go over a little bit in the logging below */
115343761473SPaul Moore 	WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500);
115443761473SPaul Moore 	len_max = MAX_EXECVE_AUDIT_LEN;
1155de6bbd1dSEric Paris 
115643761473SPaul Moore 	/* scratch buffer to hold the userspace args */
115743761473SPaul Moore 	buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
115843761473SPaul Moore 	if (!buf_head) {
1159b7550787SJoe Perches 		audit_panic("out of memory for argv string");
1160de6bbd1dSEric Paris 		return;
1161de6bbd1dSEric Paris 	}
116243761473SPaul Moore 	buf = buf_head;
1163de6bbd1dSEric Paris 
116443761473SPaul Moore 	audit_log_format(*ab, "argc=%d", context->execve.argc);
116543761473SPaul Moore 
116643761473SPaul Moore 	len_rem = len_max;
116743761473SPaul Moore 	len_buf = 0;
116843761473SPaul Moore 	len_full = 0;
116943761473SPaul Moore 	require_data = true;
117043761473SPaul Moore 	encode = false;
117143761473SPaul Moore 	iter = 0;
117243761473SPaul Moore 	arg = 0;
117343761473SPaul Moore 	do {
117443761473SPaul Moore 		/* NOTE: we don't ever want to trust this value for anything
117543761473SPaul Moore 		 *       serious, but the audit record format insists we
117643761473SPaul Moore 		 *       provide an argument length for really long arguments,
117743761473SPaul Moore 		 *       e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but
117843761473SPaul Moore 		 *       to use strncpy_from_user() to obtain this value for
117943761473SPaul Moore 		 *       recording in the log, although we don't use it
118043761473SPaul Moore 		 *       anywhere here to avoid a double-fetch problem */
118143761473SPaul Moore 		if (len_full == 0)
118243761473SPaul Moore 			len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1;
118343761473SPaul Moore 
118443761473SPaul Moore 		/* read more data from userspace */
118543761473SPaul Moore 		if (require_data) {
118643761473SPaul Moore 			/* can we make more room in the buffer? */
118743761473SPaul Moore 			if (buf != buf_head) {
118843761473SPaul Moore 				memmove(buf_head, buf, len_buf);
118943761473SPaul Moore 				buf = buf_head;
1190de6bbd1dSEric Paris 			}
119143761473SPaul Moore 
119243761473SPaul Moore 			/* fetch as much as we can of the argument */
119343761473SPaul Moore 			len_tmp = strncpy_from_user(&buf_head[len_buf], p,
119443761473SPaul Moore 						    len_max - len_buf);
119543761473SPaul Moore 			if (len_tmp == -EFAULT) {
119643761473SPaul Moore 				/* unable to copy from userspace */
119743761473SPaul Moore 				send_sig(SIGKILL, current, 0);
119843761473SPaul Moore 				goto out;
119943761473SPaul Moore 			} else if (len_tmp == (len_max - len_buf)) {
120043761473SPaul Moore 				/* buffer is not large enough */
120143761473SPaul Moore 				require_data = true;
120243761473SPaul Moore 				/* NOTE: if we are going to span multiple
120343761473SPaul Moore 				 *       buffers force the encoding so we stand
120443761473SPaul Moore 				 *       a chance at a sane len_full value and
120543761473SPaul Moore 				 *       consistent record encoding */
120643761473SPaul Moore 				encode = true;
120743761473SPaul Moore 				len_full = len_full * 2;
120843761473SPaul Moore 				p += len_tmp;
120943761473SPaul Moore 			} else {
121043761473SPaul Moore 				require_data = false;
121143761473SPaul Moore 				if (!encode)
121243761473SPaul Moore 					encode = audit_string_contains_control(
121343761473SPaul Moore 								buf, len_tmp);
121443761473SPaul Moore 				/* try to use a trusted value for len_full */
121543761473SPaul Moore 				if (len_full < len_max)
121643761473SPaul Moore 					len_full = (encode ?
121743761473SPaul Moore 						    len_tmp * 2 : len_tmp);
121843761473SPaul Moore 				p += len_tmp + 1;
121943761473SPaul Moore 			}
122043761473SPaul Moore 			len_buf += len_tmp;
122143761473SPaul Moore 			buf_head[len_buf] = '\0';
122243761473SPaul Moore 
122343761473SPaul Moore 			/* length of the buffer in the audit record? */
122443761473SPaul Moore 			len_abuf = (encode ? len_buf * 2 : len_buf + 2);
122543761473SPaul Moore 		}
122643761473SPaul Moore 
122743761473SPaul Moore 		/* write as much as we can to the audit log */
1228ea956d8bSRichard Guy Briggs 		if (len_buf >= 0) {
122943761473SPaul Moore 			/* NOTE: some magic numbers here - basically if we
123043761473SPaul Moore 			 *       can't fit a reasonable amount of data into the
123143761473SPaul Moore 			 *       existing audit buffer, flush it and start with
123243761473SPaul Moore 			 *       a new buffer */
123343761473SPaul Moore 			if ((sizeof(abuf) + 8) > len_rem) {
123443761473SPaul Moore 				len_rem = len_max;
123543761473SPaul Moore 				audit_log_end(*ab);
123643761473SPaul Moore 				*ab = audit_log_start(context,
123743761473SPaul Moore 						      GFP_KERNEL, AUDIT_EXECVE);
123843761473SPaul Moore 				if (!*ab)
123943761473SPaul Moore 					goto out;
124043761473SPaul Moore 			}
124143761473SPaul Moore 
124243761473SPaul Moore 			/* create the non-arg portion of the arg record */
124343761473SPaul Moore 			len_tmp = 0;
124443761473SPaul Moore 			if (require_data || (iter > 0) ||
124543761473SPaul Moore 			    ((len_abuf + sizeof(abuf)) > len_rem)) {
124643761473SPaul Moore 				if (iter == 0) {
124743761473SPaul Moore 					len_tmp += snprintf(&abuf[len_tmp],
124843761473SPaul Moore 							sizeof(abuf) - len_tmp,
124943761473SPaul Moore 							" a%d_len=%lu",
125043761473SPaul Moore 							arg, len_full);
125143761473SPaul Moore 				}
125243761473SPaul Moore 				len_tmp += snprintf(&abuf[len_tmp],
125343761473SPaul Moore 						    sizeof(abuf) - len_tmp,
125443761473SPaul Moore 						    " a%d[%d]=", arg, iter++);
125543761473SPaul Moore 			} else
125643761473SPaul Moore 				len_tmp += snprintf(&abuf[len_tmp],
125743761473SPaul Moore 						    sizeof(abuf) - len_tmp,
125843761473SPaul Moore 						    " a%d=", arg);
125943761473SPaul Moore 			WARN_ON(len_tmp >= sizeof(abuf));
126043761473SPaul Moore 			abuf[sizeof(abuf) - 1] = '\0';
126143761473SPaul Moore 
126243761473SPaul Moore 			/* log the arg in the audit record */
126343761473SPaul Moore 			audit_log_format(*ab, "%s", abuf);
126443761473SPaul Moore 			len_rem -= len_tmp;
126543761473SPaul Moore 			len_tmp = len_buf;
126643761473SPaul Moore 			if (encode) {
126743761473SPaul Moore 				if (len_abuf > len_rem)
126843761473SPaul Moore 					len_tmp = len_rem / 2; /* encoding */
126943761473SPaul Moore 				audit_log_n_hex(*ab, buf, len_tmp);
127043761473SPaul Moore 				len_rem -= len_tmp * 2;
127143761473SPaul Moore 				len_abuf -= len_tmp * 2;
127243761473SPaul Moore 			} else {
127343761473SPaul Moore 				if (len_abuf > len_rem)
127443761473SPaul Moore 					len_tmp = len_rem - 2; /* quotes */
127543761473SPaul Moore 				audit_log_n_string(*ab, buf, len_tmp);
127643761473SPaul Moore 				len_rem -= len_tmp + 2;
127743761473SPaul Moore 				/* don't subtract the "2" because we still need
127843761473SPaul Moore 				 * to add quotes to the remaining string */
127943761473SPaul Moore 				len_abuf -= len_tmp;
128043761473SPaul Moore 			}
128143761473SPaul Moore 			len_buf -= len_tmp;
128243761473SPaul Moore 			buf += len_tmp;
128343761473SPaul Moore 		}
128443761473SPaul Moore 
128543761473SPaul Moore 		/* ready to move to the next argument? */
128643761473SPaul Moore 		if ((len_buf == 0) && !require_data) {
128743761473SPaul Moore 			arg++;
128843761473SPaul Moore 			iter = 0;
128943761473SPaul Moore 			len_full = 0;
129043761473SPaul Moore 			require_data = true;
129143761473SPaul Moore 			encode = false;
129243761473SPaul Moore 		}
129343761473SPaul Moore 	} while (arg < context->execve.argc);
129443761473SPaul Moore 
129543761473SPaul Moore 	/* NOTE: the caller handles the final audit_log_end() call */
129643761473SPaul Moore 
129743761473SPaul Moore out:
129843761473SPaul Moore 	kfree(buf_head);
1299bdf4c48aSPeter Zijlstra }
1300bdf4c48aSPeter Zijlstra 
audit_log_cap(struct audit_buffer * ab,char * prefix,kernel_cap_t * cap)13012efa48feSYueHaibing static void audit_log_cap(struct audit_buffer *ab, char *prefix,
13022efa48feSYueHaibing 			  kernel_cap_t *cap)
13035f3d544fSRichard Guy Briggs {
13045f3d544fSRichard Guy Briggs 	if (cap_isclear(*cap)) {
13055f3d544fSRichard Guy Briggs 		audit_log_format(ab, " %s=0", prefix);
13065f3d544fSRichard Guy Briggs 		return;
13075f3d544fSRichard Guy Briggs 	}
1308f122a08bSLinus Torvalds 	audit_log_format(ab, " %s=%016llx", prefix, cap->val);
13095f3d544fSRichard Guy Briggs }
13105f3d544fSRichard Guy Briggs 
audit_log_fcaps(struct audit_buffer * ab,struct audit_names * name)13115f3d544fSRichard Guy Briggs static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
13125f3d544fSRichard Guy Briggs {
13135f3d544fSRichard Guy Briggs 	if (name->fcap_ver == -1) {
13145f3d544fSRichard Guy Briggs 		audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?");
13155f3d544fSRichard Guy Briggs 		return;
13165f3d544fSRichard Guy Briggs 	}
13175f3d544fSRichard Guy Briggs 	audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
13185f3d544fSRichard Guy Briggs 	audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
13195f3d544fSRichard Guy Briggs 	audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d",
13205f3d544fSRichard Guy Briggs 			 name->fcap.fE, name->fcap_ver,
13215f3d544fSRichard Guy Briggs 			 from_kuid(&init_user_ns, name->fcap.rootid));
13225f3d544fSRichard Guy Briggs }
13235f3d544fSRichard Guy Briggs 
audit_log_time(struct audit_context * context,struct audit_buffer ** ab)1324272ceeaeSRichard Guy Briggs static void audit_log_time(struct audit_context *context, struct audit_buffer **ab)
1325272ceeaeSRichard Guy Briggs {
1326272ceeaeSRichard Guy Briggs 	const struct audit_ntp_data *ntp = &context->time.ntp_data;
1327272ceeaeSRichard Guy Briggs 	const struct timespec64 *tk = &context->time.tk_injoffset;
1328272ceeaeSRichard Guy Briggs 	static const char * const ntp_name[] = {
1329272ceeaeSRichard Guy Briggs 		"offset",
1330272ceeaeSRichard Guy Briggs 		"freq",
1331272ceeaeSRichard Guy Briggs 		"status",
1332272ceeaeSRichard Guy Briggs 		"tai",
1333272ceeaeSRichard Guy Briggs 		"tick",
1334272ceeaeSRichard Guy Briggs 		"adjust",
1335272ceeaeSRichard Guy Briggs 	};
1336272ceeaeSRichard Guy Briggs 	int type;
1337272ceeaeSRichard Guy Briggs 
1338272ceeaeSRichard Guy Briggs 	if (context->type == AUDIT_TIME_ADJNTPVAL) {
1339272ceeaeSRichard Guy Briggs 		for (type = 0; type < AUDIT_NTP_NVALS; type++) {
1340272ceeaeSRichard Guy Briggs 			if (ntp->vals[type].newval != ntp->vals[type].oldval) {
1341272ceeaeSRichard Guy Briggs 				if (!*ab) {
1342272ceeaeSRichard Guy Briggs 					*ab = audit_log_start(context,
1343272ceeaeSRichard Guy Briggs 							GFP_KERNEL,
1344272ceeaeSRichard Guy Briggs 							AUDIT_TIME_ADJNTPVAL);
1345272ceeaeSRichard Guy Briggs 					if (!*ab)
1346272ceeaeSRichard Guy Briggs 						return;
1347272ceeaeSRichard Guy Briggs 				}
1348272ceeaeSRichard Guy Briggs 				audit_log_format(*ab, "op=%s old=%lli new=%lli",
1349272ceeaeSRichard Guy Briggs 						 ntp_name[type],
1350272ceeaeSRichard Guy Briggs 						 ntp->vals[type].oldval,
1351272ceeaeSRichard Guy Briggs 						 ntp->vals[type].newval);
1352272ceeaeSRichard Guy Briggs 				audit_log_end(*ab);
1353272ceeaeSRichard Guy Briggs 				*ab = NULL;
1354272ceeaeSRichard Guy Briggs 			}
1355272ceeaeSRichard Guy Briggs 		}
1356272ceeaeSRichard Guy Briggs 	}
1357272ceeaeSRichard Guy Briggs 	if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
1358272ceeaeSRichard Guy Briggs 		if (!*ab) {
1359272ceeaeSRichard Guy Briggs 			*ab = audit_log_start(context, GFP_KERNEL,
1360272ceeaeSRichard Guy Briggs 					      AUDIT_TIME_INJOFFSET);
1361272ceeaeSRichard Guy Briggs 			if (!*ab)
1362272ceeaeSRichard Guy Briggs 				return;
1363272ceeaeSRichard Guy Briggs 		}
1364272ceeaeSRichard Guy Briggs 		audit_log_format(*ab, "sec=%lli nsec=%li",
1365272ceeaeSRichard Guy Briggs 				 (long long)tk->tv_sec, tk->tv_nsec);
1366272ceeaeSRichard Guy Briggs 		audit_log_end(*ab);
1367272ceeaeSRichard Guy Briggs 		*ab = NULL;
1368272ceeaeSRichard Guy Briggs 	}
1369272ceeaeSRichard Guy Briggs }
1370272ceeaeSRichard Guy Briggs 
show_special(struct audit_context * context,int * call_panic)1371a33e6751SAl Viro static void show_special(struct audit_context *context, int *call_panic)
1372f3298dc4SAl Viro {
1373f3298dc4SAl Viro 	struct audit_buffer *ab;
1374f3298dc4SAl Viro 	int i;
1375f3298dc4SAl Viro 
1376f3298dc4SAl Viro 	ab = audit_log_start(context, GFP_KERNEL, context->type);
1377f3298dc4SAl Viro 	if (!ab)
1378f3298dc4SAl Viro 		return;
1379f3298dc4SAl Viro 
1380f3298dc4SAl Viro 	switch (context->type) {
1381f3298dc4SAl Viro 	case AUDIT_SOCKETCALL: {
1382f3298dc4SAl Viro 		int nargs = context->socketcall.nargs;
1383254c8b96SRoni Nevalainen 
1384f3298dc4SAl Viro 		audit_log_format(ab, "nargs=%d", nargs);
1385f3298dc4SAl Viro 		for (i = 0; i < nargs; i++)
1386f3298dc4SAl Viro 			audit_log_format(ab, " a%d=%lx", i,
1387f3298dc4SAl Viro 				context->socketcall.args[i]);
1388f3298dc4SAl Viro 		break; }
13897183abccSCasey Schaufler 	case AUDIT_IPC:
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);
13947183abccSCasey Schaufler 		if (lsmprop_is_set(&context->ipc.oprop)) {
13952d470c77SCasey Schaufler 			struct lsm_context lsmctx;
1396254c8b96SRoni Nevalainen 
13977183abccSCasey Schaufler 			if (security_lsmprop_to_secctx(&context->ipc.oprop,
13982d470c77SCasey Schaufler 						       &lsmctx) < 0) {
1399a33e6751SAl Viro 				*call_panic = 1;
1400a33e6751SAl Viro 			} else {
14012d470c77SCasey Schaufler 				audit_log_format(ab, " obj=%s", lsmctx.context);
14022d470c77SCasey Schaufler 				security_release_secctx(&lsmctx);
1403a33e6751SAl Viro 			}
1404a33e6751SAl Viro 		}
1405e816f370SAl Viro 		if (context->ipc.has_perm) {
1406e816f370SAl Viro 			audit_log_end(ab);
1407e816f370SAl Viro 			ab = audit_log_start(context, GFP_KERNEL,
1408e816f370SAl Viro 					     AUDIT_IPC_SET_PERM);
14090644ec0cSKees Cook 			if (unlikely(!ab))
14100644ec0cSKees Cook 				return;
1411e816f370SAl Viro 			audit_log_format(ab,
14122570ebbdSAl Viro 				"qbytes=%lx ouid=%u ogid=%u mode=%#ho",
1413e816f370SAl Viro 				context->ipc.qbytes,
1414e816f370SAl Viro 				context->ipc.perm_uid,
1415e816f370SAl Viro 				context->ipc.perm_gid,
1416e816f370SAl Viro 				context->ipc.perm_mode);
1417e816f370SAl Viro 		}
14187183abccSCasey Schaufler 		break;
1419fe8e52b9SPaul Moore 	case AUDIT_MQ_OPEN:
1420564f6993SAl Viro 		audit_log_format(ab,
1421df0a4283SAl Viro 			"oflag=0x%x mode=%#ho mq_flags=0x%lx mq_maxmsg=%ld "
1422564f6993SAl Viro 			"mq_msgsize=%ld mq_curmsgs=%ld",
1423564f6993SAl Viro 			context->mq_open.oflag, context->mq_open.mode,
1424564f6993SAl Viro 			context->mq_open.attr.mq_flags,
1425564f6993SAl Viro 			context->mq_open.attr.mq_maxmsg,
1426564f6993SAl Viro 			context->mq_open.attr.mq_msgsize,
1427564f6993SAl Viro 			context->mq_open.attr.mq_curmsgs);
1428fe8e52b9SPaul Moore 		break;
1429fe8e52b9SPaul Moore 	case AUDIT_MQ_SENDRECV:
1430c32c8af4SAl Viro 		audit_log_format(ab,
1431c32c8af4SAl Viro 			"mqdes=%d msg_len=%zd msg_prio=%u "
1432b9047726SDeepa Dinamani 			"abs_timeout_sec=%lld abs_timeout_nsec=%ld",
1433c32c8af4SAl Viro 			context->mq_sendrecv.mqdes,
1434c32c8af4SAl Viro 			context->mq_sendrecv.msg_len,
1435c32c8af4SAl Viro 			context->mq_sendrecv.msg_prio,
1436b9047726SDeepa Dinamani 			(long long) context->mq_sendrecv.abs_timeout.tv_sec,
1437c32c8af4SAl Viro 			context->mq_sendrecv.abs_timeout.tv_nsec);
1438fe8e52b9SPaul Moore 		break;
1439fe8e52b9SPaul Moore 	case AUDIT_MQ_NOTIFY:
144020114f71SAl Viro 		audit_log_format(ab, "mqdes=%d sigev_signo=%d",
144120114f71SAl Viro 				context->mq_notify.mqdes,
144220114f71SAl Viro 				context->mq_notify.sigev_signo);
1443fe8e52b9SPaul Moore 		break;
14447392906eSAl Viro 	case AUDIT_MQ_GETSETATTR: {
14457392906eSAl Viro 		struct mq_attr *attr = &context->mq_getsetattr.mqstat;
1446254c8b96SRoni Nevalainen 
14477392906eSAl Viro 		audit_log_format(ab,
14487392906eSAl Viro 			"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
14497392906eSAl Viro 			"mq_curmsgs=%ld ",
14507392906eSAl Viro 			context->mq_getsetattr.mqdes,
14517392906eSAl Viro 			attr->mq_flags, attr->mq_maxmsg,
14527392906eSAl Viro 			attr->mq_msgsize, attr->mq_curmsgs);
14537392906eSAl Viro 		break; }
1454fe8e52b9SPaul Moore 	case AUDIT_CAPSET:
145557f71a0aSAl Viro 		audit_log_format(ab, "pid=%d", context->capset.pid);
145657f71a0aSAl Viro 		audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
145757f71a0aSAl Viro 		audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
145857f71a0aSAl Viro 		audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
14597786f6b6SRichard Guy Briggs 		audit_log_cap(ab, "cap_pa", &context->capset.cap.ambient);
1460fe8e52b9SPaul Moore 		break;
1461fe8e52b9SPaul Moore 	case AUDIT_MMAP:
1462120a795dSAl Viro 		audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
1463120a795dSAl Viro 				 context->mmap.flags);
1464fe8e52b9SPaul Moore 		break;
1465571e5c0eSRichard Guy Briggs 	case AUDIT_OPENAT2:
1466571e5c0eSRichard Guy Briggs 		audit_log_format(ab, "oflag=0%llo mode=0%llo resolve=0x%llx",
1467571e5c0eSRichard Guy Briggs 				 context->openat2.flags,
1468571e5c0eSRichard Guy Briggs 				 context->openat2.mode,
1469571e5c0eSRichard Guy Briggs 				 context->openat2.resolve);
1470571e5c0eSRichard Guy Briggs 		break;
1471fe8e52b9SPaul Moore 	case AUDIT_EXECVE:
1472d9cfea91SRichard Guy Briggs 		audit_log_execve_info(context, &ab);
1473fe8e52b9SPaul Moore 		break;
1474ca86cad7SRichard Guy Briggs 	case AUDIT_KERN_MODULE:
1475ca86cad7SRichard Guy Briggs 		audit_log_format(ab, "name=");
1476b305f7edSYi Wang 		if (context->module.name) {
1477ca86cad7SRichard Guy Briggs 			audit_log_untrustedstring(ab, context->module.name);
1478b305f7edSYi Wang 		} else
1479b305f7edSYi Wang 			audit_log_format(ab, "(null)");
1480b305f7edSYi Wang 
1481ca86cad7SRichard Guy Briggs 		break;
1482272ceeaeSRichard Guy Briggs 	case AUDIT_TIME_ADJNTPVAL:
1483272ceeaeSRichard Guy Briggs 	case AUDIT_TIME_INJOFFSET:
1484272ceeaeSRichard Guy Briggs 		/* this call deviates from the rest, eating the buffer */
1485272ceeaeSRichard Guy Briggs 		audit_log_time(context, &ab);
1486272ceeaeSRichard Guy Briggs 		break;
1487f3298dc4SAl Viro 	}
1488f3298dc4SAl Viro 	audit_log_end(ab);
1489f3298dc4SAl Viro }
1490f3298dc4SAl Viro 
audit_proctitle_rtrim(char * proctitle,int len)14913f1c8250SWilliam Roberts static inline int audit_proctitle_rtrim(char *proctitle, int len)
14923f1c8250SWilliam Roberts {
14933f1c8250SWilliam Roberts 	char *end = proctitle + len - 1;
1494254c8b96SRoni Nevalainen 
14953f1c8250SWilliam Roberts 	while (end > proctitle && !isprint(*end))
14963f1c8250SWilliam Roberts 		end--;
14973f1c8250SWilliam Roberts 
14983f1c8250SWilliam Roberts 	/* catch the case where proctitle is only 1 non-print character */
14993f1c8250SWilliam Roberts 	len = end - proctitle + 1;
15003f1c8250SWilliam Roberts 	len -= isprint(proctitle[len-1]) == 0;
15013f1c8250SWilliam Roberts 	return len;
15023f1c8250SWilliam Roberts }
15033f1c8250SWilliam Roberts 
15045f3d544fSRichard Guy Briggs /*
15055f3d544fSRichard Guy Briggs  * audit_log_name - produce AUDIT_PATH record from struct audit_names
15065f3d544fSRichard Guy Briggs  * @context: audit_context for the task
15075f3d544fSRichard Guy Briggs  * @n: audit_names structure with reportable details
15085f3d544fSRichard Guy Briggs  * @path: optional path to report instead of audit_names->name
15095f3d544fSRichard Guy Briggs  * @record_num: record number to report when handling a list of names
15105f3d544fSRichard Guy Briggs  * @call_panic: optional pointer to int that will be updated if secid fails
15115f3d544fSRichard Guy Briggs  */
audit_log_name(struct audit_context * context,struct audit_names * n,const struct path * path,int record_num,int * call_panic)15125f3d544fSRichard Guy Briggs static void audit_log_name(struct audit_context *context, struct audit_names *n,
15135f3d544fSRichard Guy Briggs 		    const struct path *path, int record_num, int *call_panic)
15145f3d544fSRichard Guy Briggs {
15155f3d544fSRichard Guy Briggs 	struct audit_buffer *ab;
15165f3d544fSRichard Guy Briggs 
15175f3d544fSRichard Guy Briggs 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
15185f3d544fSRichard Guy Briggs 	if (!ab)
15195f3d544fSRichard Guy Briggs 		return;
15205f3d544fSRichard Guy Briggs 
15215f3d544fSRichard Guy Briggs 	audit_log_format(ab, "item=%d", record_num);
15225f3d544fSRichard Guy Briggs 
15235f3d544fSRichard Guy Briggs 	if (path)
15245f3d544fSRichard Guy Briggs 		audit_log_d_path(ab, " name=", path);
15255f3d544fSRichard Guy Briggs 	else if (n->name) {
15265f3d544fSRichard Guy Briggs 		switch (n->name_len) {
15275f3d544fSRichard Guy Briggs 		case AUDIT_NAME_FULL:
15285f3d544fSRichard Guy Briggs 			/* log the full path */
15295f3d544fSRichard Guy Briggs 			audit_log_format(ab, " name=");
15305f3d544fSRichard Guy Briggs 			audit_log_untrustedstring(ab, n->name->name);
15315f3d544fSRichard Guy Briggs 			break;
15325f3d544fSRichard Guy Briggs 		case 0:
15335f3d544fSRichard Guy Briggs 			/* name was specified as a relative path and the
15345f3d544fSRichard Guy Briggs 			 * directory component is the cwd
15355f3d544fSRichard Guy Briggs 			 */
15366d915476SRichard Guy Briggs 			if (context->pwd.dentry && context->pwd.mnt)
15375f3d544fSRichard Guy Briggs 				audit_log_d_path(ab, " name=", &context->pwd);
15386d915476SRichard Guy Briggs 			else
15396d915476SRichard Guy Briggs 				audit_log_format(ab, " name=(null)");
15405f3d544fSRichard Guy Briggs 			break;
15415f3d544fSRichard Guy Briggs 		default:
15425f3d544fSRichard Guy Briggs 			/* log the name's directory component */
15435f3d544fSRichard Guy Briggs 			audit_log_format(ab, " name=");
15445f3d544fSRichard Guy Briggs 			audit_log_n_untrustedstring(ab, n->name->name,
15455f3d544fSRichard Guy Briggs 						    n->name_len);
15465f3d544fSRichard Guy Briggs 		}
15475f3d544fSRichard Guy Briggs 	} else
15485f3d544fSRichard Guy Briggs 		audit_log_format(ab, " name=(null)");
15495f3d544fSRichard Guy Briggs 
15505f3d544fSRichard Guy Briggs 	if (n->ino != AUDIT_INO_UNSET)
15515f3d544fSRichard Guy Briggs 		audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x",
15525f3d544fSRichard Guy Briggs 				 n->ino,
15535f3d544fSRichard Guy Briggs 				 MAJOR(n->dev),
15545f3d544fSRichard Guy Briggs 				 MINOR(n->dev),
15555f3d544fSRichard Guy Briggs 				 n->mode,
15565f3d544fSRichard Guy Briggs 				 from_kuid(&init_user_ns, n->uid),
15575f3d544fSRichard Guy Briggs 				 from_kgid(&init_user_ns, n->gid),
15585f3d544fSRichard Guy Briggs 				 MAJOR(n->rdev),
15595f3d544fSRichard Guy Briggs 				 MINOR(n->rdev));
1560e0a8dcbdSCasey Schaufler 	if (lsmprop_is_set(&n->oprop)) {
15616fba8981SCasey Schaufler 		struct lsm_context ctx;
15625f3d544fSRichard Guy Briggs 
15632d470c77SCasey Schaufler 		if (security_lsmprop_to_secctx(&n->oprop, &ctx) < 0) {
15645f3d544fSRichard Guy Briggs 			if (call_panic)
15655f3d544fSRichard Guy Briggs 				*call_panic = 2;
15665f3d544fSRichard Guy Briggs 		} else {
15676fba8981SCasey Schaufler 			audit_log_format(ab, " obj=%s", ctx.context);
15686fba8981SCasey Schaufler 			security_release_secctx(&ctx);
15695f3d544fSRichard Guy Briggs 		}
15705f3d544fSRichard Guy Briggs 	}
15715f3d544fSRichard Guy Briggs 
15725f3d544fSRichard Guy Briggs 	/* log the audit_names record type */
15735f3d544fSRichard Guy Briggs 	switch (n->type) {
15745f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_NORMAL:
15755f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=NORMAL");
15765f3d544fSRichard Guy Briggs 		break;
15775f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_PARENT:
15785f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=PARENT");
15795f3d544fSRichard Guy Briggs 		break;
15805f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_CHILD_DELETE:
15815f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=DELETE");
15825f3d544fSRichard Guy Briggs 		break;
15835f3d544fSRichard Guy Briggs 	case AUDIT_TYPE_CHILD_CREATE:
15845f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=CREATE");
15855f3d544fSRichard Guy Briggs 		break;
15865f3d544fSRichard Guy Briggs 	default:
15875f3d544fSRichard Guy Briggs 		audit_log_format(ab, " nametype=UNKNOWN");
15885f3d544fSRichard Guy Briggs 		break;
15895f3d544fSRichard Guy Briggs 	}
15905f3d544fSRichard Guy Briggs 
15915f3d544fSRichard Guy Briggs 	audit_log_fcaps(ab, n);
15925f3d544fSRichard Guy Briggs 	audit_log_end(ab);
15935f3d544fSRichard Guy Briggs }
15945f3d544fSRichard Guy Briggs 
audit_log_proctitle(void)15952a1fe215SPaul Moore static void audit_log_proctitle(void)
15963f1c8250SWilliam Roberts {
15973f1c8250SWilliam Roberts 	int res;
15983f1c8250SWilliam Roberts 	char *buf;
15993f1c8250SWilliam Roberts 	char *msg = "(null)";
16003f1c8250SWilliam Roberts 	int len = strlen(msg);
16012a1fe215SPaul Moore 	struct audit_context *context = audit_context();
16023f1c8250SWilliam Roberts 	struct audit_buffer *ab;
16033f1c8250SWilliam Roberts 
16043f1c8250SWilliam Roberts 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
16053f1c8250SWilliam Roberts 	if (!ab)
16063f1c8250SWilliam Roberts 		return;	/* audit_panic or being filtered */
16073f1c8250SWilliam Roberts 
16083f1c8250SWilliam Roberts 	audit_log_format(ab, "proctitle=");
16093f1c8250SWilliam Roberts 
16103f1c8250SWilliam Roberts 	/* Not  cached */
16113f1c8250SWilliam Roberts 	if (!context->proctitle.value) {
16123f1c8250SWilliam Roberts 		buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL);
16133f1c8250SWilliam Roberts 		if (!buf)
16143f1c8250SWilliam Roberts 			goto out;
16153f1c8250SWilliam Roberts 		/* Historically called this from procfs naming */
16162a1fe215SPaul Moore 		res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN);
16173f1c8250SWilliam Roberts 		if (res == 0) {
16183f1c8250SWilliam Roberts 			kfree(buf);
16193f1c8250SWilliam Roberts 			goto out;
16203f1c8250SWilliam Roberts 		}
16213f1c8250SWilliam Roberts 		res = audit_proctitle_rtrim(buf, res);
16223f1c8250SWilliam Roberts 		if (res == 0) {
16233f1c8250SWilliam Roberts 			kfree(buf);
16243f1c8250SWilliam Roberts 			goto out;
16253f1c8250SWilliam Roberts 		}
16263f1c8250SWilliam Roberts 		context->proctitle.value = buf;
16273f1c8250SWilliam Roberts 		context->proctitle.len = res;
16283f1c8250SWilliam Roberts 	}
16293f1c8250SWilliam Roberts 	msg = context->proctitle.value;
16303f1c8250SWilliam Roberts 	len = context->proctitle.len;
16313f1c8250SWilliam Roberts out:
16323f1c8250SWilliam Roberts 	audit_log_n_untrustedstring(ab, msg, len);
16333f1c8250SWilliam Roberts 	audit_log_end(ab);
16343f1c8250SWilliam Roberts }
16353f1c8250SWilliam Roberts 
16365bd2182dSPaul Moore /**
16375bd2182dSPaul Moore  * audit_log_uring - generate a AUDIT_URINGOP record
16385bd2182dSPaul Moore  * @ctx: the audit context
16395bd2182dSPaul Moore  */
audit_log_uring(struct audit_context * ctx)16405bd2182dSPaul Moore static void audit_log_uring(struct audit_context *ctx)
16415bd2182dSPaul Moore {
16425bd2182dSPaul Moore 	struct audit_buffer *ab;
16435bd2182dSPaul Moore 	const struct cred *cred;
16445bd2182dSPaul Moore 
16455bd2182dSPaul Moore 	ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_URINGOP);
16465bd2182dSPaul Moore 	if (!ab)
16475bd2182dSPaul Moore 		return;
16485bd2182dSPaul Moore 	cred = current_cred();
16495bd2182dSPaul Moore 	audit_log_format(ab, "uring_op=%d", ctx->uring_op);
16505bd2182dSPaul Moore 	if (ctx->return_valid != AUDITSC_INVALID)
16515bd2182dSPaul Moore 		audit_log_format(ab, " success=%s exit=%ld",
165289282beaSThorsten Blum 				 str_yes_no(ctx->return_valid ==
165389282beaSThorsten Blum 					    AUDITSC_SUCCESS),
16545bd2182dSPaul Moore 				 ctx->return_code);
16555bd2182dSPaul Moore 	audit_log_format(ab,
16565bd2182dSPaul Moore 			 " items=%d"
16575bd2182dSPaul Moore 			 " ppid=%d pid=%d uid=%u gid=%u euid=%u suid=%u"
16585bd2182dSPaul Moore 			 " fsuid=%u egid=%u sgid=%u fsgid=%u",
16595bd2182dSPaul Moore 			 ctx->name_count,
16605bd2182dSPaul Moore 			 task_ppid_nr(current), task_tgid_nr(current),
16615bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->uid),
16625bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->gid),
16635bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->euid),
16645bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->suid),
16655bd2182dSPaul Moore 			 from_kuid(&init_user_ns, cred->fsuid),
16665bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->egid),
16675bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->sgid),
16685bd2182dSPaul Moore 			 from_kgid(&init_user_ns, cred->fsgid));
16695bd2182dSPaul Moore 	audit_log_task_context(ab);
16705bd2182dSPaul Moore 	audit_log_key(ab, ctx->filterkey);
16715bd2182dSPaul Moore 	audit_log_end(ab);
16725bd2182dSPaul Moore }
16735bd2182dSPaul Moore 
audit_log_exit(void)16742a1fe215SPaul Moore static void audit_log_exit(void)
16751da177e4SLinus Torvalds {
16769c7aa6aaSSteve Grubb 	int i, call_panic = 0;
16772a1fe215SPaul Moore 	struct audit_context *context = audit_context();
16781da177e4SLinus Torvalds 	struct audit_buffer *ab;
16797551ced3SDavid Woodhouse 	struct audit_aux_data *aux;
16805195d8e2SEric Paris 	struct audit_names *n;
16811da177e4SLinus Torvalds 
16822a1fe215SPaul Moore 	context->personality = current->personality;
1683e495149bSAl Viro 
168412c5e81dSPaul Moore 	switch (context->context) {
168512c5e81dSPaul Moore 	case AUDIT_CTX_SYSCALL:
1686e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
16871da177e4SLinus Torvalds 		if (!ab)
168812c5e81dSPaul Moore 			return;
1689bccf6ae0SDavid Woodhouse 		audit_log_format(ab, "arch=%x syscall=%d",
1690bccf6ae0SDavid Woodhouse 				 context->arch, context->major);
16911da177e4SLinus Torvalds 		if (context->personality != PER_LINUX)
16921da177e4SLinus Torvalds 			audit_log_format(ab, " per=%lx", context->personality);
1693ba59eae7SAlex Shi 		if (context->return_valid != AUDITSC_INVALID)
16942fd6f58bS 			audit_log_format(ab, " success=%s exit=%ld",
169589282beaSThorsten Blum 					 str_yes_no(context->return_valid ==
169689282beaSThorsten Blum 						    AUDITSC_SUCCESS),
16972fd6f58bS 					 context->return_code);
16981da177e4SLinus Torvalds 		audit_log_format(ab,
1699e23eb920SPeter Moody 				 " a0=%lx a1=%lx a2=%lx a3=%lx items=%d",
17001da177e4SLinus Torvalds 				 context->argv[0],
17011da177e4SLinus Torvalds 				 context->argv[1],
17021da177e4SLinus Torvalds 				 context->argv[2],
17031da177e4SLinus Torvalds 				 context->argv[3],
1704e23eb920SPeter Moody 				 context->name_count);
17052a1fe215SPaul Moore 		audit_log_task_info(ab);
17069d960985SEric Paris 		audit_log_key(ab, context->filterkey);
17071da177e4SLinus Torvalds 		audit_log_end(ab);
170812c5e81dSPaul Moore 		break;
17095bd2182dSPaul Moore 	case AUDIT_CTX_URING:
17105bd2182dSPaul Moore 		audit_log_uring(context);
17115bd2182dSPaul Moore 		break;
171212c5e81dSPaul Moore 	default:
171312c5e81dSPaul Moore 		BUG();
171412c5e81dSPaul Moore 		break;
171512c5e81dSPaul Moore 	}
17161da177e4SLinus Torvalds 
17177551ced3SDavid Woodhouse 	for (aux = context->aux; aux; aux = aux->next) {
1718c0404993SSteve Grubb 
1719e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, aux->type);
17201da177e4SLinus Torvalds 		if (!ab)
17211da177e4SLinus Torvalds 			continue; /* audit_panic has been called */
17221da177e4SLinus Torvalds 
17231da177e4SLinus Torvalds 		switch (aux->type) {
172420ca73bcSGeorge C. Wilson 
17253fc689e9SEric Paris 		case AUDIT_BPRM_FCAPS: {
17263fc689e9SEric Paris 			struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
1727254c8b96SRoni Nevalainen 
17283fc689e9SEric Paris 			audit_log_format(ab, "fver=%x", axs->fcap_ver);
17293fc689e9SEric Paris 			audit_log_cap(ab, "fp", &axs->fcap.permitted);
17303fc689e9SEric Paris 			audit_log_cap(ab, "fi", &axs->fcap.inheritable);
17313fc689e9SEric Paris 			audit_log_format(ab, " fe=%d", axs->fcap.fE);
17323fc689e9SEric Paris 			audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
17333fc689e9SEric Paris 			audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
17343fc689e9SEric Paris 			audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
17357786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "old_pa", &axs->old_pcap.ambient);
17367786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pp", &axs->new_pcap.permitted);
17377786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pi", &axs->new_pcap.inheritable);
17387786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pe", &axs->new_pcap.effective);
17397786f6b6SRichard Guy Briggs 			audit_log_cap(ab, "pa", &axs->new_pcap.ambient);
17402fec30e2SRichard Guy Briggs 			audit_log_format(ab, " frootid=%d",
17412fec30e2SRichard Guy Briggs 					 from_kuid(&init_user_ns,
17422fec30e2SRichard Guy Briggs 						   axs->fcap.rootid));
17433fc689e9SEric Paris 			break; }
17443fc689e9SEric Paris 
17451da177e4SLinus Torvalds 		}
17461da177e4SLinus Torvalds 		audit_log_end(ab);
17471da177e4SLinus Torvalds 	}
17481da177e4SLinus Torvalds 
1749f3298dc4SAl Viro 	if (context->type)
1750a33e6751SAl Viro 		show_special(context, &call_panic);
1751f3298dc4SAl Viro 
1752157cf649SAl Viro 	if (context->fds[0] >= 0) {
1753157cf649SAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR);
1754157cf649SAl Viro 		if (ab) {
1755157cf649SAl Viro 			audit_log_format(ab, "fd0=%d fd1=%d",
1756157cf649SAl Viro 					context->fds[0], context->fds[1]);
1757157cf649SAl Viro 			audit_log_end(ab);
1758157cf649SAl Viro 		}
1759157cf649SAl Viro 	}
1760157cf649SAl Viro 
17614f6b434fSAl Viro 	if (context->sockaddr_len) {
17624f6b434fSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR);
17634f6b434fSAl Viro 		if (ab) {
17644f6b434fSAl Viro 			audit_log_format(ab, "saddr=");
17654f6b434fSAl Viro 			audit_log_n_hex(ab, (void *)context->sockaddr,
17664f6b434fSAl Viro 					context->sockaddr_len);
17674f6b434fSAl Viro 			audit_log_end(ab);
17684f6b434fSAl Viro 		}
17694f6b434fSAl Viro 	}
17704f6b434fSAl Viro 
1771e54dc243SAmy Griffis 	for (aux = context->aux_pids; aux; aux = aux->next) {
1772e54dc243SAmy Griffis 		struct audit_aux_data_pids *axs = (void *)aux;
1773e54dc243SAmy Griffis 
1774e54dc243SAmy Griffis 		for (i = 0; i < axs->pid_count; i++)
1775e54dc243SAmy Griffis 			if (audit_log_pid_context(context, axs->target_pid[i],
1776c2a7780eSEric Paris 						  axs->target_auid[i],
1777c2a7780eSEric Paris 						  axs->target_uid[i],
17784746ec5bSEric Paris 						  axs->target_sessionid[i],
177913d826e5SCasey Schaufler 						  &axs->target_ref[i],
1780c2a7780eSEric Paris 						  axs->target_comm[i]))
1781e54dc243SAmy Griffis 				call_panic = 1;
1782a5cb013dSAl Viro 	}
1783e54dc243SAmy Griffis 
1784e54dc243SAmy Griffis 	if (context->target_pid &&
1785e54dc243SAmy Griffis 	    audit_log_pid_context(context, context->target_pid,
1786c2a7780eSEric Paris 				  context->target_auid, context->target_uid,
17874746ec5bSEric Paris 				  context->target_sessionid,
178813d826e5SCasey Schaufler 				  &context->target_ref, context->target_comm))
1789e54dc243SAmy Griffis 			call_panic = 1;
1790a5cb013dSAl Viro 
179144707fdfSJan Blunck 	if (context->pwd.dentry && context->pwd.mnt) {
1792e495149bSAl Viro 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
17938f37d47cSDavid Woodhouse 		if (ab) {
179444707fdfSJan Blunck 			audit_log_d_path(ab, "cwd=", &context->pwd);
17958f37d47cSDavid Woodhouse 			audit_log_end(ab);
17968f37d47cSDavid Woodhouse 		}
17978f37d47cSDavid Woodhouse 	}
179873241cccSAmy Griffis 
17995195d8e2SEric Paris 	i = 0;
180079f6530cSJeff Layton 	list_for_each_entry(n, &context->names_list, list) {
180179f6530cSJeff Layton 		if (n->hidden)
180279f6530cSJeff Layton 			continue;
1803b24a30a7SEric Paris 		audit_log_name(context, n, NULL, i++, &call_panic);
180479f6530cSJeff Layton 	}
1805c0641f28SEric Paris 
180612c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_SYSCALL)
18072a1fe215SPaul Moore 		audit_log_proctitle();
18083f1c8250SWilliam Roberts 
1809c0641f28SEric Paris 	/* Send end of event record to help user space know we are finished */
1810c0641f28SEric Paris 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
1811c0641f28SEric Paris 	if (ab)
1812c0641f28SEric Paris 		audit_log_end(ab);
18131b50eed9SSteve Grubb 	if (call_panic)
181412c5e81dSPaul Moore 		audit_panic("error in audit_log_exit()");
18151da177e4SLinus Torvalds }
18161da177e4SLinus Torvalds 
1817b0dd25a8SRandy Dunlap /**
1818196a5085SGeliang Tang  * __audit_free - free a per-task audit context
1819b0dd25a8SRandy Dunlap  * @tsk: task whose audit context block to free
1820b0dd25a8SRandy Dunlap  *
182167daf270SPaul Moore  * Called from copy_process, do_exit, and the io_uring code
1822b0dd25a8SRandy Dunlap  */
__audit_free(struct task_struct * tsk)1823a4ff8dbaSEric Paris void __audit_free(struct task_struct *tsk)
18241da177e4SLinus Torvalds {
18252a1fe215SPaul Moore 	struct audit_context *context = tsk->audit_context;
18261da177e4SLinus Torvalds 
182756179a6eSEric Paris 	if (!context)
18281da177e4SLinus Torvalds 		return;
18291da177e4SLinus Torvalds 
183012c5e81dSPaul Moore 	/* this may generate CONFIG_CHANGE records */
18319e36a5d4SRichard Guy Briggs 	if (!list_empty(&context->killed_trees))
18329e36a5d4SRichard Guy Briggs 		audit_kill_trees(context);
18339e36a5d4SRichard Guy Briggs 
18342a1fe215SPaul Moore 	/* We are called either by do_exit() or the fork() error handling code;
18352a1fe215SPaul Moore 	 * in the former case tsk == current and in the latter tsk is a
18360351dc57SJilin Yuan 	 * random task_struct that doesn't have any meaningful data we
18372a1fe215SPaul Moore 	 * need to log via audit_log_exit().
18382a1fe215SPaul Moore 	 */
183967daf270SPaul Moore 	if (tsk == current && !context->dummy) {
1840ba59eae7SAlex Shi 		context->return_valid = AUDITSC_INVALID;
18412a1fe215SPaul Moore 		context->return_code = 0;
184267daf270SPaul Moore 		if (context->context == AUDIT_CTX_SYSCALL) {
18435504a69aSRichard Guy Briggs 			audit_filter_syscall(tsk, context);
18442a1fe215SPaul Moore 			audit_filter_inodes(tsk, context);
1845619ed58aSSergey Nazarov 			if (context->current_state == AUDIT_STATE_RECORD)
18462a1fe215SPaul Moore 				audit_log_exit();
184767daf270SPaul Moore 		} else if (context->context == AUDIT_CTX_URING) {
184867daf270SPaul Moore 			/* TODO: verify this case is real and valid */
184967daf270SPaul Moore 			audit_filter_uring(tsk, context);
185067daf270SPaul Moore 			audit_filter_inodes(tsk, context);
185167daf270SPaul Moore 			if (context->current_state == AUDIT_STATE_RECORD)
185267daf270SPaul Moore 				audit_log_uring(context);
185367daf270SPaul Moore 		}
18542a1fe215SPaul Moore 	}
18552a1fe215SPaul Moore 
18562a1fe215SPaul Moore 	audit_set_context(tsk, NULL);
18571da177e4SLinus Torvalds 	audit_free_context(context);
18581da177e4SLinus Torvalds }
18591da177e4SLinus Torvalds 
1860b0dd25a8SRandy Dunlap /**
186112c5e81dSPaul Moore  * audit_return_fixup - fixup the return codes in the audit_context
186212c5e81dSPaul Moore  * @ctx: the audit_context
186312c5e81dSPaul Moore  * @success: true/false value to indicate if the operation succeeded or not
186412c5e81dSPaul Moore  * @code: operation return code
186512c5e81dSPaul Moore  *
186612c5e81dSPaul Moore  * We need to fixup the return code in the audit logs if the actual return
186712c5e81dSPaul Moore  * codes are later going to be fixed by the arch specific signal handlers.
186812c5e81dSPaul Moore  */
audit_return_fixup(struct audit_context * ctx,int success,long code)186912c5e81dSPaul Moore static void audit_return_fixup(struct audit_context *ctx,
187012c5e81dSPaul Moore 			       int success, long code)
187112c5e81dSPaul Moore {
187212c5e81dSPaul Moore 	/*
187312c5e81dSPaul Moore 	 * This is actually a test for:
187412c5e81dSPaul Moore 	 * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
187512c5e81dSPaul Moore 	 * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
187612c5e81dSPaul Moore 	 *
187712c5e81dSPaul Moore 	 * but is faster than a bunch of ||
187812c5e81dSPaul Moore 	 */
187912c5e81dSPaul Moore 	if (unlikely(code <= -ERESTARTSYS) &&
188012c5e81dSPaul Moore 	    (code >= -ERESTART_RESTARTBLOCK) &&
188112c5e81dSPaul Moore 	    (code != -ENOIOCTLCMD))
188212c5e81dSPaul Moore 		ctx->return_code = -EINTR;
188312c5e81dSPaul Moore 	else
188412c5e81dSPaul Moore 		ctx->return_code  = code;
188512c5e81dSPaul Moore 	ctx->return_valid = (success ? AUDITSC_SUCCESS : AUDITSC_FAILURE);
188612c5e81dSPaul Moore }
188712c5e81dSPaul Moore 
188812c5e81dSPaul Moore /**
18895bd2182dSPaul Moore  * __audit_uring_entry - prepare the kernel task's audit context for io_uring
18905bd2182dSPaul Moore  * @op: the io_uring opcode
18915bd2182dSPaul Moore  *
18925bd2182dSPaul Moore  * This is similar to audit_syscall_entry() but is intended for use by io_uring
18935bd2182dSPaul Moore  * operations.  This function should only ever be called from
18945bd2182dSPaul Moore  * audit_uring_entry() as we rely on the audit context checking present in that
18955bd2182dSPaul Moore  * function.
18965bd2182dSPaul Moore  */
__audit_uring_entry(u8 op)18975bd2182dSPaul Moore void __audit_uring_entry(u8 op)
18985bd2182dSPaul Moore {
18995bd2182dSPaul Moore 	struct audit_context *ctx = audit_context();
19005bd2182dSPaul Moore 
19015bd2182dSPaul Moore 	if (ctx->state == AUDIT_STATE_DISABLED)
19025bd2182dSPaul Moore 		return;
19035bd2182dSPaul Moore 
19045bd2182dSPaul Moore 	/*
19055bd2182dSPaul Moore 	 * NOTE: It's possible that we can be called from the process' context
19065bd2182dSPaul Moore 	 *       before it returns to userspace, and before audit_syscall_exit()
19075bd2182dSPaul Moore 	 *       is called.  In this case there is not much to do, just record
19085bd2182dSPaul Moore 	 *       the io_uring details and return.
19095bd2182dSPaul Moore 	 */
19105bd2182dSPaul Moore 	ctx->uring_op = op;
19115bd2182dSPaul Moore 	if (ctx->context == AUDIT_CTX_SYSCALL)
19125bd2182dSPaul Moore 		return;
19135bd2182dSPaul Moore 
19145bd2182dSPaul Moore 	ctx->dummy = !audit_n_rules;
19155bd2182dSPaul Moore 	if (!ctx->dummy && ctx->state == AUDIT_STATE_BUILD)
19165bd2182dSPaul Moore 		ctx->prio = 0;
19175bd2182dSPaul Moore 
19185bd2182dSPaul Moore 	ctx->context = AUDIT_CTX_URING;
19195bd2182dSPaul Moore 	ctx->current_state = ctx->state;
19205bd2182dSPaul Moore 	ktime_get_coarse_real_ts64(&ctx->ctime);
19215bd2182dSPaul Moore }
19225bd2182dSPaul Moore 
19235bd2182dSPaul Moore /**
19245bd2182dSPaul Moore  * __audit_uring_exit - wrap up the kernel task's audit context after io_uring
19255bd2182dSPaul Moore  * @success: true/false value to indicate if the operation succeeded or not
19265bd2182dSPaul Moore  * @code: operation return code
19275bd2182dSPaul Moore  *
19285bd2182dSPaul Moore  * This is similar to audit_syscall_exit() but is intended for use by io_uring
19295bd2182dSPaul Moore  * operations.  This function should only ever be called from
19305bd2182dSPaul Moore  * audit_uring_exit() as we rely on the audit context checking present in that
19315bd2182dSPaul Moore  * function.
19325bd2182dSPaul Moore  */
__audit_uring_exit(int success,long code)19335bd2182dSPaul Moore void __audit_uring_exit(int success, long code)
19345bd2182dSPaul Moore {
19355bd2182dSPaul Moore 	struct audit_context *ctx = audit_context();
19365bd2182dSPaul Moore 
193769e9cd66SJulian Orth 	if (ctx->dummy) {
193869e9cd66SJulian Orth 		if (ctx->context != AUDIT_CTX_URING)
193969e9cd66SJulian Orth 			return;
194069e9cd66SJulian Orth 		goto out;
194169e9cd66SJulian Orth 	}
194269e9cd66SJulian Orth 
1943d4fefa48SRichard Guy Briggs 	audit_return_fixup(ctx, success, code);
19445bd2182dSPaul Moore 	if (ctx->context == AUDIT_CTX_SYSCALL) {
19455bd2182dSPaul Moore 		/*
19465bd2182dSPaul Moore 		 * NOTE: See the note in __audit_uring_entry() about the case
19475bd2182dSPaul Moore 		 *       where we may be called from process context before we
19485bd2182dSPaul Moore 		 *       return to userspace via audit_syscall_exit().  In this
19495bd2182dSPaul Moore 		 *       case we simply emit a URINGOP record and bail, the
19505bd2182dSPaul Moore 		 *       normal syscall exit handling will take care of
19515bd2182dSPaul Moore 		 *       everything else.
19525bd2182dSPaul Moore 		 *       It is also worth mentioning that when we are called,
19535bd2182dSPaul Moore 		 *       the current process creds may differ from the creds
19545bd2182dSPaul Moore 		 *       used during the normal syscall processing; keep that
19555bd2182dSPaul Moore 		 *       in mind if/when we move the record generation code.
19565bd2182dSPaul Moore 		 */
19575bd2182dSPaul Moore 
19585bd2182dSPaul Moore 		/*
19595bd2182dSPaul Moore 		 * We need to filter on the syscall info here to decide if we
19605bd2182dSPaul Moore 		 * should emit a URINGOP record.  I know it seems odd but this
19615bd2182dSPaul Moore 		 * solves the problem where users have a filter to block *all*
19625bd2182dSPaul Moore 		 * syscall records in the "exit" filter; we want to preserve
19635bd2182dSPaul Moore 		 * the behavior here.
19645bd2182dSPaul Moore 		 */
19655bd2182dSPaul Moore 		audit_filter_syscall(current, ctx);
196667daf270SPaul Moore 		if (ctx->current_state != AUDIT_STATE_RECORD)
196767daf270SPaul Moore 			audit_filter_uring(current, ctx);
19685bd2182dSPaul Moore 		audit_filter_inodes(current, ctx);
19695bd2182dSPaul Moore 		if (ctx->current_state != AUDIT_STATE_RECORD)
19705bd2182dSPaul Moore 			return;
19715bd2182dSPaul Moore 
19725bd2182dSPaul Moore 		audit_log_uring(ctx);
19735bd2182dSPaul Moore 		return;
19745bd2182dSPaul Moore 	}
19755bd2182dSPaul Moore 
19765bd2182dSPaul Moore 	/* this may generate CONFIG_CHANGE records */
19775bd2182dSPaul Moore 	if (!list_empty(&ctx->killed_trees))
19785bd2182dSPaul Moore 		audit_kill_trees(ctx);
19795bd2182dSPaul Moore 
198067daf270SPaul Moore 	/* run through both filters to ensure we set the filterkey properly */
198167daf270SPaul Moore 	audit_filter_uring(current, ctx);
19825bd2182dSPaul Moore 	audit_filter_inodes(current, ctx);
19835bd2182dSPaul Moore 	if (ctx->current_state != AUDIT_STATE_RECORD)
19845bd2182dSPaul Moore 		goto out;
19855bd2182dSPaul Moore 	audit_log_exit();
19865bd2182dSPaul Moore 
19875bd2182dSPaul Moore out:
19885bd2182dSPaul Moore 	audit_reset_context(ctx);
19895bd2182dSPaul Moore }
19905bd2182dSPaul Moore 
19915bd2182dSPaul Moore /**
1992196a5085SGeliang Tang  * __audit_syscall_entry - fill in an audit record at syscall entry
1993b0dd25a8SRandy Dunlap  * @major: major syscall type (function)
1994b0dd25a8SRandy Dunlap  * @a1: additional syscall register 1
1995b0dd25a8SRandy Dunlap  * @a2: additional syscall register 2
1996b0dd25a8SRandy Dunlap  * @a3: additional syscall register 3
1997b0dd25a8SRandy Dunlap  * @a4: additional syscall register 4
1998b0dd25a8SRandy Dunlap  *
1999b0dd25a8SRandy Dunlap  * Fill in audit context at syscall entry.  This only happens if the
20001da177e4SLinus Torvalds  * audit context was created when the task was created and the state or
20011da177e4SLinus Torvalds  * filters demand the audit context be built.  If the state from the
2002619ed58aSSergey Nazarov  * per-task filter or from the per-syscall filter is AUDIT_STATE_RECORD,
20031da177e4SLinus Torvalds  * then the record will be written at syscall exit time (otherwise, it
20041da177e4SLinus Torvalds  * will only be written if another part of the kernel requests that it
2005b0dd25a8SRandy Dunlap  * be written).
2006b0dd25a8SRandy Dunlap  */
__audit_syscall_entry(int major,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4)2007b4f0d375SRichard Guy Briggs void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
20081da177e4SLinus Torvalds 			   unsigned long a3, unsigned long a4)
20091da177e4SLinus Torvalds {
2010cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
20111da177e4SLinus Torvalds 	enum audit_state     state;
20121da177e4SLinus Torvalds 
201394d14e3eSRichard Guy Briggs 	if (!audit_enabled || !context)
201486a1c34aSRoland McGrath 		return;
20151da177e4SLinus Torvalds 
201612c5e81dSPaul Moore 	WARN_ON(context->context != AUDIT_CTX_UNUSED);
201712c5e81dSPaul Moore 	WARN_ON(context->name_count);
201812c5e81dSPaul Moore 	if (context->context != AUDIT_CTX_UNUSED || context->name_count) {
201912c5e81dSPaul Moore 		audit_panic("unrecoverable error in audit_syscall_entry()");
202012c5e81dSPaul Moore 		return;
202112c5e81dSPaul Moore 	}
20221da177e4SLinus Torvalds 
20235260ecc2SRichard Guy Briggs 	state = context->state;
2024619ed58aSSergey Nazarov 	if (state == AUDIT_STATE_DISABLED)
20255260ecc2SRichard Guy Briggs 		return;
20265260ecc2SRichard Guy Briggs 
20275260ecc2SRichard Guy Briggs 	context->dummy = !audit_n_rules;
2028619ed58aSSergey Nazarov 	if (!context->dummy && state == AUDIT_STATE_BUILD) {
20295260ecc2SRichard Guy Briggs 		context->prio = 0;
2030cdfb6b34SRichard Guy Briggs 		if (auditd_test_task(current))
20315260ecc2SRichard Guy Briggs 			return;
20325260ecc2SRichard Guy Briggs 	}
20335260ecc2SRichard Guy Briggs 
203416add411SDmitry V. Levin 	context->arch	    = syscall_get_arch(current);
20351da177e4SLinus Torvalds 	context->major      = major;
20361da177e4SLinus Torvalds 	context->argv[0]    = a1;
20371da177e4SLinus Torvalds 	context->argv[1]    = a2;
20381da177e4SLinus Torvalds 	context->argv[2]    = a3;
20391da177e4SLinus Torvalds 	context->argv[3]    = a4;
204012c5e81dSPaul Moore 	context->context = AUDIT_CTX_SYSCALL;
20410590b933SAl Viro 	context->current_state  = state;
2042290e44b7SPaul Moore 	ktime_get_coarse_real_ts64(&context->ctime);
20431da177e4SLinus Torvalds }
20441da177e4SLinus Torvalds 
2045b0dd25a8SRandy Dunlap /**
2046196a5085SGeliang Tang  * __audit_syscall_exit - deallocate audit context after a system call
204742ae610cSRandy Dunlap  * @success: success value of the syscall
204842ae610cSRandy Dunlap  * @return_code: return value of the syscall
2049b0dd25a8SRandy Dunlap  *
2050b0dd25a8SRandy Dunlap  * Tear down after system call.  If the audit context has been marked as
2051619ed58aSSergey Nazarov  * auditable (either because of the AUDIT_STATE_RECORD state from
205242ae610cSRandy Dunlap  * filtering, or because some other part of the kernel wrote an audit
20531da177e4SLinus Torvalds  * message), then write out the syscall information.  In call cases,
2054b0dd25a8SRandy Dunlap  * free the names stored from getname().
2055b0dd25a8SRandy Dunlap  */
__audit_syscall_exit(int success,long return_code)2056d7e7528bSEric Paris void __audit_syscall_exit(int success, long return_code)
20571da177e4SLinus Torvalds {
205812c5e81dSPaul Moore 	struct audit_context *context = audit_context();
20591da177e4SLinus Torvalds 
206012c5e81dSPaul Moore 	if (!context || context->dummy ||
206112c5e81dSPaul Moore 	    context->context != AUDIT_CTX_SYSCALL)
206212c5e81dSPaul Moore 		goto out;
20631da177e4SLinus Torvalds 
206412c5e81dSPaul Moore 	/* this may generate CONFIG_CHANGE records */
20659e36a5d4SRichard Guy Briggs 	if (!list_empty(&context->killed_trees))
20669e36a5d4SRichard Guy Briggs 		audit_kill_trees(context);
20679e36a5d4SRichard Guy Briggs 
2068d4fefa48SRichard Guy Briggs 	audit_return_fixup(context, success, return_code);
206912c5e81dSPaul Moore 	/* run through both filters to ensure we set the filterkey properly */
20705504a69aSRichard Guy Briggs 	audit_filter_syscall(current, context);
20712a1fe215SPaul Moore 	audit_filter_inodes(current, context);
20723ed66951SRichard Guy Briggs 	if (context->current_state != AUDIT_STATE_RECORD)
207312c5e81dSPaul Moore 		goto out;
207412c5e81dSPaul Moore 
20752a1fe215SPaul Moore 	audit_log_exit();
20761da177e4SLinus Torvalds 
207712c5e81dSPaul Moore out:
207812c5e81dSPaul Moore 	audit_reset_context(context);
20791da177e4SLinus Torvalds }
20801da177e4SLinus Torvalds 
handle_one(const struct inode * inode)208174c3cbe3SAl Viro static inline void handle_one(const struct inode *inode)
208274c3cbe3SAl Viro {
208374c3cbe3SAl Viro 	struct audit_context *context;
208474c3cbe3SAl Viro 	struct audit_tree_refs *p;
208574c3cbe3SAl Viro 	struct audit_chunk *chunk;
208674c3cbe3SAl Viro 	int count;
2087254c8b96SRoni Nevalainen 
208808991e83SJan Kara 	if (likely(!inode->i_fsnotify_marks))
208974c3cbe3SAl Viro 		return;
2090cdfb6b34SRichard Guy Briggs 	context = audit_context();
209174c3cbe3SAl Viro 	p = context->trees;
209274c3cbe3SAl Viro 	count = context->tree_count;
209374c3cbe3SAl Viro 	rcu_read_lock();
209474c3cbe3SAl Viro 	chunk = audit_tree_lookup(inode);
209574c3cbe3SAl Viro 	rcu_read_unlock();
209674c3cbe3SAl Viro 	if (!chunk)
209774c3cbe3SAl Viro 		return;
209874c3cbe3SAl Viro 	if (likely(put_tree_ref(context, chunk)))
209974c3cbe3SAl Viro 		return;
210074c3cbe3SAl Viro 	if (unlikely(!grow_tree_refs(context))) {
2101f952d10fSRichard Guy Briggs 		pr_warn("out of memory, audit has lost a tree reference\n");
210274c3cbe3SAl Viro 		audit_set_auditable(context);
210374c3cbe3SAl Viro 		audit_put_chunk(chunk);
210474c3cbe3SAl Viro 		unroll_tree_refs(context, p, count);
210574c3cbe3SAl Viro 		return;
210674c3cbe3SAl Viro 	}
210774c3cbe3SAl Viro 	put_tree_ref(context, chunk);
210874c3cbe3SAl Viro }
210974c3cbe3SAl Viro 
handle_path(const struct dentry * dentry)211074c3cbe3SAl Viro static void handle_path(const struct dentry *dentry)
211174c3cbe3SAl Viro {
211274c3cbe3SAl Viro 	struct audit_context *context;
211374c3cbe3SAl Viro 	struct audit_tree_refs *p;
211474c3cbe3SAl Viro 	const struct dentry *d, *parent;
211574c3cbe3SAl Viro 	struct audit_chunk *drop;
211674c3cbe3SAl Viro 	unsigned long seq;
211774c3cbe3SAl Viro 	int count;
211874c3cbe3SAl Viro 
2119cdfb6b34SRichard Guy Briggs 	context = audit_context();
212074c3cbe3SAl Viro 	p = context->trees;
212174c3cbe3SAl Viro 	count = context->tree_count;
212274c3cbe3SAl Viro retry:
212374c3cbe3SAl Viro 	drop = NULL;
212474c3cbe3SAl Viro 	d = dentry;
212574c3cbe3SAl Viro 	rcu_read_lock();
212674c3cbe3SAl Viro 	seq = read_seqbegin(&rename_lock);
212774c3cbe3SAl Viro 	for (;;) {
21283b362157SDavid Howells 		struct inode *inode = d_backing_inode(d);
2129254c8b96SRoni Nevalainen 
213008991e83SJan Kara 		if (inode && unlikely(inode->i_fsnotify_marks)) {
213174c3cbe3SAl Viro 			struct audit_chunk *chunk;
2132254c8b96SRoni Nevalainen 
213374c3cbe3SAl Viro 			chunk = audit_tree_lookup(inode);
213474c3cbe3SAl Viro 			if (chunk) {
213574c3cbe3SAl Viro 				if (unlikely(!put_tree_ref(context, chunk))) {
213674c3cbe3SAl Viro 					drop = chunk;
213774c3cbe3SAl Viro 					break;
213874c3cbe3SAl Viro 				}
213974c3cbe3SAl Viro 			}
214074c3cbe3SAl Viro 		}
214174c3cbe3SAl Viro 		parent = d->d_parent;
214274c3cbe3SAl Viro 		if (parent == d)
214374c3cbe3SAl Viro 			break;
214474c3cbe3SAl Viro 		d = parent;
214574c3cbe3SAl Viro 	}
214674c3cbe3SAl Viro 	if (unlikely(read_seqretry(&rename_lock, seq) || drop)) {  /* in this order */
214774c3cbe3SAl Viro 		rcu_read_unlock();
214874c3cbe3SAl Viro 		if (!drop) {
214974c3cbe3SAl Viro 			/* just a race with rename */
215074c3cbe3SAl Viro 			unroll_tree_refs(context, p, count);
215174c3cbe3SAl Viro 			goto retry;
215274c3cbe3SAl Viro 		}
215374c3cbe3SAl Viro 		audit_put_chunk(drop);
215474c3cbe3SAl Viro 		if (grow_tree_refs(context)) {
215574c3cbe3SAl Viro 			/* OK, got more space */
215674c3cbe3SAl Viro 			unroll_tree_refs(context, p, count);
215774c3cbe3SAl Viro 			goto retry;
215874c3cbe3SAl Viro 		}
215974c3cbe3SAl Viro 		/* too bad */
2160f952d10fSRichard Guy Briggs 		pr_warn("out of memory, audit has lost a tree reference\n");
216174c3cbe3SAl Viro 		unroll_tree_refs(context, p, count);
216274c3cbe3SAl Viro 		audit_set_auditable(context);
216374c3cbe3SAl Viro 		return;
216474c3cbe3SAl Viro 	}
216574c3cbe3SAl Viro 	rcu_read_unlock();
216674c3cbe3SAl Viro }
216774c3cbe3SAl Viro 
audit_alloc_name(struct audit_context * context,unsigned char type)216878e2e802SJeff Layton static struct audit_names *audit_alloc_name(struct audit_context *context,
216978e2e802SJeff Layton 						unsigned char type)
21705195d8e2SEric Paris {
21715195d8e2SEric Paris 	struct audit_names *aname;
21725195d8e2SEric Paris 
21735195d8e2SEric Paris 	if (context->name_count < AUDIT_NAMES) {
21745195d8e2SEric Paris 		aname = &context->preallocated_names[context->name_count];
21755195d8e2SEric Paris 		memset(aname, 0, sizeof(*aname));
21765195d8e2SEric Paris 	} else {
21775195d8e2SEric Paris 		aname = kzalloc(sizeof(*aname), GFP_NOFS);
21785195d8e2SEric Paris 		if (!aname)
21795195d8e2SEric Paris 			return NULL;
21805195d8e2SEric Paris 		aname->should_free = true;
21815195d8e2SEric Paris 	}
21825195d8e2SEric Paris 
218384cb777eSRichard Guy Briggs 	aname->ino = AUDIT_INO_UNSET;
218478e2e802SJeff Layton 	aname->type = type;
21855195d8e2SEric Paris 	list_add_tail(&aname->list, &context->names_list);
21865195d8e2SEric Paris 
21875195d8e2SEric Paris 	context->name_count++;
21886d915476SRichard Guy Briggs 	if (!context->pwd.dentry)
21896d915476SRichard Guy Briggs 		get_fs_pwd(current->fs, &context->pwd);
21905195d8e2SEric Paris 	return aname;
21915195d8e2SEric Paris }
21925195d8e2SEric Paris 
2193b0dd25a8SRandy Dunlap /**
2194196a5085SGeliang Tang  * __audit_reusename - fill out filename with info from existing entry
21957ac86265SJeff Layton  * @uptr: userland ptr to pathname
21967ac86265SJeff Layton  *
21977ac86265SJeff Layton  * Search the audit_names list for the current audit context. If there is an
21987ac86265SJeff Layton  * existing entry with a matching "uptr" then return the filename
21997ac86265SJeff Layton  * associated with that audit_name. If not, return NULL.
22007ac86265SJeff Layton  */
22017ac86265SJeff Layton struct filename *
__audit_reusename(const __user char * uptr)22027ac86265SJeff Layton __audit_reusename(const __user char *uptr)
22037ac86265SJeff Layton {
2204cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
22057ac86265SJeff Layton 	struct audit_names *n;
22067ac86265SJeff Layton 
22077ac86265SJeff Layton 	list_for_each_entry(n, &context->names_list, list) {
22087ac86265SJeff Layton 		if (!n->name)
22097ac86265SJeff Layton 			continue;
2210*61185101SMateusz Guzik 		if (n->name->uptr == uptr)
2211*61185101SMateusz Guzik 			return refname(n->name);
221255422d0bSPaul Moore 	}
22137ac86265SJeff Layton 	return NULL;
22147ac86265SJeff Layton }
22157ac86265SJeff Layton 
22167ac86265SJeff Layton /**
2217196a5085SGeliang Tang  * __audit_getname - add a name to the list
2218b0dd25a8SRandy Dunlap  * @name: name to add
2219b0dd25a8SRandy Dunlap  *
2220b0dd25a8SRandy Dunlap  * Add a name to the list of audit names for this context.
2221b0dd25a8SRandy Dunlap  * Called from fs/namei.c:getname().
2222b0dd25a8SRandy Dunlap  */
__audit_getname(struct filename * name)222391a27b2aSJeff Layton void __audit_getname(struct filename *name)
22241da177e4SLinus Torvalds {
2225cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
22265195d8e2SEric Paris 	struct audit_names *n;
22271da177e4SLinus Torvalds 
222812c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_UNUSED)
22291da177e4SLinus Torvalds 		return;
223091a27b2aSJeff Layton 
223178e2e802SJeff Layton 	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
22325195d8e2SEric Paris 	if (!n)
22335195d8e2SEric Paris 		return;
22345195d8e2SEric Paris 
22355195d8e2SEric Paris 	n->name = name;
22365195d8e2SEric Paris 	n->name_len = AUDIT_NAME_FULL;
2237adb5c247SJeff Layton 	name->aname = n;
2238*61185101SMateusz Guzik 	refname(name);
22391da177e4SLinus Torvalds }
22401da177e4SLinus Torvalds 
audit_copy_fcaps(struct audit_names * name,const struct dentry * dentry)22415f3d544fSRichard Guy Briggs static inline int audit_copy_fcaps(struct audit_names *name,
22425f3d544fSRichard Guy Briggs 				   const struct dentry *dentry)
22435f3d544fSRichard Guy Briggs {
22445f3d544fSRichard Guy Briggs 	struct cpu_vfs_cap_data caps;
22455f3d544fSRichard Guy Briggs 	int rc;
22465f3d544fSRichard Guy Briggs 
22475f3d544fSRichard Guy Briggs 	if (!dentry)
22485f3d544fSRichard Guy Briggs 		return 0;
22495f3d544fSRichard Guy Briggs 
225039f60c1cSChristian Brauner 	rc = get_vfs_caps_from_disk(&nop_mnt_idmap, dentry, &caps);
22515f3d544fSRichard Guy Briggs 	if (rc)
22525f3d544fSRichard Guy Briggs 		return rc;
22535f3d544fSRichard Guy Briggs 
22545f3d544fSRichard Guy Briggs 	name->fcap.permitted = caps.permitted;
22555f3d544fSRichard Guy Briggs 	name->fcap.inheritable = caps.inheritable;
22565f3d544fSRichard Guy Briggs 	name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
22575f3d544fSRichard Guy Briggs 	name->fcap.rootid = caps.rootid;
22585f3d544fSRichard Guy Briggs 	name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
22595f3d544fSRichard Guy Briggs 				VFS_CAP_REVISION_SHIFT;
22605f3d544fSRichard Guy Briggs 
22615f3d544fSRichard Guy Briggs 	return 0;
22625f3d544fSRichard Guy Briggs }
22635f3d544fSRichard Guy Briggs 
22645f3d544fSRichard 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)22652efa48feSYueHaibing static void audit_copy_inode(struct audit_names *name,
22662efa48feSYueHaibing 			     const struct dentry *dentry,
22675f3d544fSRichard Guy Briggs 			     struct inode *inode, unsigned int flags)
22685f3d544fSRichard Guy Briggs {
22695f3d544fSRichard Guy Briggs 	name->ino   = inode->i_ino;
22705f3d544fSRichard Guy Briggs 	name->dev   = inode->i_sb->s_dev;
22715f3d544fSRichard Guy Briggs 	name->mode  = inode->i_mode;
22725f3d544fSRichard Guy Briggs 	name->uid   = inode->i_uid;
22735f3d544fSRichard Guy Briggs 	name->gid   = inode->i_gid;
22745f3d544fSRichard Guy Briggs 	name->rdev  = inode->i_rdev;
2275e0a8dcbdSCasey Schaufler 	security_inode_getlsmprop(inode, &name->oprop);
22765f3d544fSRichard Guy Briggs 	if (flags & AUDIT_INODE_NOEVAL) {
22775f3d544fSRichard Guy Briggs 		name->fcap_ver = -1;
22785f3d544fSRichard Guy Briggs 		return;
22795f3d544fSRichard Guy Briggs 	}
22805f3d544fSRichard Guy Briggs 	audit_copy_fcaps(name, dentry);
22815f3d544fSRichard Guy Briggs }
22825f3d544fSRichard Guy Briggs 
2283b0dd25a8SRandy Dunlap /**
2284bfcec708SJeff Layton  * __audit_inode - store the inode and device from a lookup
2285b0dd25a8SRandy Dunlap  * @name: name being audited
2286481968f4SRandy Dunlap  * @dentry: dentry being audited
228779f6530cSJeff Layton  * @flags: attributes for this particular entry
2288b0dd25a8SRandy Dunlap  */
__audit_inode(struct filename * name,const struct dentry * dentry,unsigned int flags)2289adb5c247SJeff Layton void __audit_inode(struct filename *name, const struct dentry *dentry,
229079f6530cSJeff Layton 		   unsigned int flags)
22911da177e4SLinus Torvalds {
2292cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2293d6335d77SAndreas Gruenbacher 	struct inode *inode = d_backing_inode(dentry);
22945195d8e2SEric Paris 	struct audit_names *n;
229579f6530cSJeff Layton 	bool parent = flags & AUDIT_INODE_PARENT;
2296a252f56aSRichard Guy Briggs 	struct audit_entry *e;
2297a252f56aSRichard Guy Briggs 	struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
2298a252f56aSRichard Guy Briggs 	int i;
22991da177e4SLinus Torvalds 
230012c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_UNUSED)
23011da177e4SLinus Torvalds 		return;
23025195d8e2SEric Paris 
2303a252f56aSRichard Guy Briggs 	rcu_read_lock();
2304a252f56aSRichard Guy Briggs 	list_for_each_entry_rcu(e, list, list) {
2305a252f56aSRichard Guy Briggs 		for (i = 0; i < e->rule.field_count; i++) {
2306a252f56aSRichard Guy Briggs 			struct audit_field *f = &e->rule.fields[i];
2307a252f56aSRichard Guy Briggs 
2308a252f56aSRichard Guy Briggs 			if (f->type == AUDIT_FSTYPE
2309a252f56aSRichard Guy Briggs 			    && audit_comparator(inode->i_sb->s_magic,
2310a252f56aSRichard Guy Briggs 						f->op, f->val)
2311a252f56aSRichard Guy Briggs 			    && e->rule.action == AUDIT_NEVER) {
2312a252f56aSRichard Guy Briggs 				rcu_read_unlock();
2313a252f56aSRichard Guy Briggs 				return;
2314a252f56aSRichard Guy Briggs 			}
2315a252f56aSRichard Guy Briggs 		}
2316a252f56aSRichard Guy Briggs 	}
2317a252f56aSRichard Guy Briggs 	rcu_read_unlock();
2318a252f56aSRichard Guy Briggs 
23199cec9d68SJeff Layton 	if (!name)
23209cec9d68SJeff Layton 		goto out_alloc;
23219cec9d68SJeff Layton 
2322adb5c247SJeff Layton 	/*
2323adb5c247SJeff Layton 	 * If we have a pointer to an audit_names entry already, then we can
2324adb5c247SJeff Layton 	 * just use it directly if the type is correct.
2325adb5c247SJeff Layton 	 */
2326adb5c247SJeff Layton 	n = name->aname;
2327adb5c247SJeff Layton 	if (n) {
2328adb5c247SJeff Layton 		if (parent) {
2329adb5c247SJeff Layton 			if (n->type == AUDIT_TYPE_PARENT ||
2330adb5c247SJeff Layton 			    n->type == AUDIT_TYPE_UNKNOWN)
2331adb5c247SJeff Layton 				goto out;
2332adb5c247SJeff Layton 		} else {
2333adb5c247SJeff Layton 			if (n->type != AUDIT_TYPE_PARENT)
2334adb5c247SJeff Layton 				goto out;
2335adb5c247SJeff Layton 		}
2336adb5c247SJeff Layton 	}
2337adb5c247SJeff Layton 
23385195d8e2SEric Paris 	list_for_each_entry_reverse(n, &context->names_list, list) {
233957c59f58SPaul Moore 		if (n->ino) {
234057c59f58SPaul Moore 			/* valid inode number, use that for the comparison */
234157c59f58SPaul Moore 			if (n->ino != inode->i_ino ||
234257c59f58SPaul Moore 			    n->dev != inode->i_sb->s_dev)
234357c59f58SPaul Moore 				continue;
234457c59f58SPaul Moore 		} else if (n->name) {
234557c59f58SPaul Moore 			/* inode number has not been set, check the name */
234657c59f58SPaul Moore 			if (strcmp(n->name->name, name->name))
234757c59f58SPaul Moore 				continue;
234857c59f58SPaul Moore 		} else
234957c59f58SPaul Moore 			/* no inode and no name (?!) ... this is odd ... */
2350bfcec708SJeff Layton 			continue;
2351bfcec708SJeff Layton 
2352bfcec708SJeff Layton 		/* match the correct record type */
2353bfcec708SJeff Layton 		if (parent) {
2354bfcec708SJeff Layton 			if (n->type == AUDIT_TYPE_PARENT ||
2355bfcec708SJeff Layton 			    n->type == AUDIT_TYPE_UNKNOWN)
23565195d8e2SEric Paris 				goto out;
2357bfcec708SJeff Layton 		} else {
2358bfcec708SJeff Layton 			if (n->type != AUDIT_TYPE_PARENT)
2359bfcec708SJeff Layton 				goto out;
2360bfcec708SJeff Layton 		}
23611da177e4SLinus Torvalds 	}
23625195d8e2SEric Paris 
23639cec9d68SJeff Layton out_alloc:
23644a928436SPaul Moore 	/* unable to find an entry with both a matching name and type */
23654a928436SPaul Moore 	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
23665195d8e2SEric Paris 	if (!n)
23675195d8e2SEric Paris 		return;
2368fcf22d82SPaul Moore 	if (name) {
2369fd3522fdSPaul Moore 		n->name = name;
2370*61185101SMateusz Guzik 		refname(name);
2371fcf22d82SPaul Moore 	}
23724a928436SPaul Moore 
23735195d8e2SEric Paris out:
2374bfcec708SJeff Layton 	if (parent) {
237591a27b2aSJeff Layton 		n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
2376bfcec708SJeff Layton 		n->type = AUDIT_TYPE_PARENT;
237779f6530cSJeff Layton 		if (flags & AUDIT_INODE_HIDDEN)
237879f6530cSJeff Layton 			n->hidden = true;
2379bfcec708SJeff Layton 	} else {
2380bfcec708SJeff Layton 		n->name_len = AUDIT_NAME_FULL;
2381bfcec708SJeff Layton 		n->type = AUDIT_TYPE_NORMAL;
2382bfcec708SJeff Layton 	}
238374c3cbe3SAl Viro 	handle_path(dentry);
238457d46577SRichard Guy Briggs 	audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL);
238573241cccSAmy Griffis }
238673241cccSAmy Griffis 
__audit_file(const struct file * file)23879f45f5bfSAl Viro void __audit_file(const struct file *file)
23889f45f5bfSAl Viro {
23899f45f5bfSAl Viro 	__audit_inode(NULL, file->f_path.dentry, 0);
23909f45f5bfSAl Viro }
23919f45f5bfSAl Viro 
239273241cccSAmy Griffis /**
2393c43a25abSJeff Layton  * __audit_inode_child - collect inode info for created/removed objects
239473d3ec5aSAmy Griffis  * @parent: inode of dentry parent
2395c43a25abSJeff Layton  * @dentry: dentry being audited
23964fa6b5ecSJeff Layton  * @type:   AUDIT_TYPE_* value that we're looking for
239773241cccSAmy Griffis  *
239873241cccSAmy Griffis  * For syscalls that create or remove filesystem objects, audit_inode
239973241cccSAmy Griffis  * can only collect information for the filesystem object's parent.
240073241cccSAmy Griffis  * This call updates the audit context with the child's information.
240173241cccSAmy Griffis  * Syscalls that create a new filesystem object must be hooked after
240273241cccSAmy Griffis  * the object is created.  Syscalls that remove a filesystem object
240373241cccSAmy Griffis  * must be hooked prior, in order to capture the target inode during
240473241cccSAmy Griffis  * unsuccessful attempts.
240573241cccSAmy Griffis  */
__audit_inode_child(struct inode * parent,const struct dentry * dentry,const unsigned char type)2406d6335d77SAndreas Gruenbacher void __audit_inode_child(struct inode *parent,
24074fa6b5ecSJeff Layton 			 const struct dentry *dentry,
24084fa6b5ecSJeff Layton 			 const unsigned char type)
240973241cccSAmy Griffis {
2410cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2411d6335d77SAndreas Gruenbacher 	struct inode *inode = d_backing_inode(dentry);
2412795d673aSAl Viro 	const struct qstr *dname = &dentry->d_name;
24134fa6b5ecSJeff Layton 	struct audit_names *n, *found_parent = NULL, *found_child = NULL;
241442d5e376SRichard Guy Briggs 	struct audit_entry *e;
241542d5e376SRichard Guy Briggs 	struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
241642d5e376SRichard Guy Briggs 	int i;
241773241cccSAmy Griffis 
241812c5e81dSPaul Moore 	if (context->context == AUDIT_CTX_UNUSED)
241973241cccSAmy Griffis 		return;
242073241cccSAmy Griffis 
242142d5e376SRichard Guy Briggs 	rcu_read_lock();
242242d5e376SRichard Guy Briggs 	list_for_each_entry_rcu(e, list, list) {
242342d5e376SRichard Guy Briggs 		for (i = 0; i < e->rule.field_count; i++) {
242442d5e376SRichard Guy Briggs 			struct audit_field *f = &e->rule.fields[i];
242542d5e376SRichard Guy Briggs 
2426a252f56aSRichard Guy Briggs 			if (f->type == AUDIT_FSTYPE
2427a252f56aSRichard Guy Briggs 			    && audit_comparator(parent->i_sb->s_magic,
2428a252f56aSRichard Guy Briggs 						f->op, f->val)
2429a252f56aSRichard Guy Briggs 			    && e->rule.action == AUDIT_NEVER) {
243042d5e376SRichard Guy Briggs 				rcu_read_unlock();
243142d5e376SRichard Guy Briggs 				return;
243242d5e376SRichard Guy Briggs 			}
243342d5e376SRichard Guy Briggs 		}
243442d5e376SRichard Guy Briggs 	}
243542d5e376SRichard Guy Briggs 	rcu_read_unlock();
243642d5e376SRichard Guy Briggs 
243774c3cbe3SAl Viro 	if (inode)
243874c3cbe3SAl Viro 		handle_one(inode);
243973241cccSAmy Griffis 
24404fa6b5ecSJeff Layton 	/* look for a parent entry first */
24415195d8e2SEric Paris 	list_for_each_entry(n, &context->names_list, list) {
244257c59f58SPaul Moore 		if (!n->name ||
244357c59f58SPaul Moore 		    (n->type != AUDIT_TYPE_PARENT &&
244457c59f58SPaul Moore 		     n->type != AUDIT_TYPE_UNKNOWN))
244573241cccSAmy Griffis 			continue;
244673241cccSAmy Griffis 
244757c59f58SPaul Moore 		if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev &&
244857c59f58SPaul Moore 		    !audit_compare_dname_path(dname,
244957c59f58SPaul Moore 					      n->name->name, n->name_len)) {
245057c59f58SPaul Moore 			if (n->type == AUDIT_TYPE_UNKNOWN)
245157c59f58SPaul Moore 				n->type = AUDIT_TYPE_PARENT;
24524fa6b5ecSJeff Layton 			found_parent = n;
24534fa6b5ecSJeff Layton 			break;
24549c937dccSAmy Griffis 		}
245573241cccSAmy Griffis 	}
245673241cccSAmy Griffis 
2457b59bc6e3SGaosheng Cui 	cond_resched();
2458b59bc6e3SGaosheng Cui 
24594fa6b5ecSJeff Layton 	/* is there a matching child entry? */
24605195d8e2SEric Paris 	list_for_each_entry(n, &context->names_list, list) {
24614fa6b5ecSJeff Layton 		/* can only match entries that have a name */
246257c59f58SPaul Moore 		if (!n->name ||
246357c59f58SPaul Moore 		    (n->type != type && n->type != AUDIT_TYPE_UNKNOWN))
24644fa6b5ecSJeff Layton 			continue;
24654fa6b5ecSJeff Layton 
2466795d673aSAl Viro 		if (!strcmp(dname->name, n->name->name) ||
246791a27b2aSJeff Layton 		    !audit_compare_dname_path(dname, n->name->name,
24684fa6b5ecSJeff Layton 						found_parent ?
24694fa6b5ecSJeff Layton 						found_parent->name_len :
2470e3d6b07bSJeff Layton 						AUDIT_NAME_FULL)) {
247157c59f58SPaul Moore 			if (n->type == AUDIT_TYPE_UNKNOWN)
247257c59f58SPaul Moore 				n->type = type;
24734fa6b5ecSJeff Layton 			found_child = n;
24744fa6b5ecSJeff Layton 			break;
2475ac9910ceSSteve Grubb 		}
24765712e88fSAmy Griffis 	}
24775712e88fSAmy Griffis 
24785712e88fSAmy Griffis 	if (!found_parent) {
24794fa6b5ecSJeff Layton 		/* create a new, "anonymous" parent record */
24804fa6b5ecSJeff Layton 		n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
24815195d8e2SEric Paris 		if (!n)
24825712e88fSAmy Griffis 			return;
248357d46577SRichard Guy Briggs 		audit_copy_inode(n, NULL, parent, 0);
248473d3ec5aSAmy Griffis 	}
24855712e88fSAmy Griffis 
24865712e88fSAmy Griffis 	if (!found_child) {
24874fa6b5ecSJeff Layton 		found_child = audit_alloc_name(context, type);
24884fa6b5ecSJeff Layton 		if (!found_child)
24895712e88fSAmy Griffis 			return;
24905712e88fSAmy Griffis 
24915712e88fSAmy Griffis 		/* Re-use the name belonging to the slot for a matching parent
24925712e88fSAmy Griffis 		 * directory. All names for this context are relinquished in
24935712e88fSAmy Griffis 		 * audit_free_names() */
24945712e88fSAmy Griffis 		if (found_parent) {
24954fa6b5ecSJeff Layton 			found_child->name = found_parent->name;
24964fa6b5ecSJeff Layton 			found_child->name_len = AUDIT_NAME_FULL;
2497*61185101SMateusz Guzik 			refname(found_child->name);
24985712e88fSAmy Griffis 		}
24994fa6b5ecSJeff Layton 	}
250057c59f58SPaul Moore 
25015712e88fSAmy Griffis 	if (inode)
250257d46577SRichard Guy Briggs 		audit_copy_inode(found_child, dentry, inode, 0);
25034fa6b5ecSJeff Layton 	else
250484cb777eSRichard Guy Briggs 		found_child->ino = AUDIT_INO_UNSET;
25053e2efce0SAmy Griffis }
250650e437d5STrond Myklebust EXPORT_SYMBOL_GPL(__audit_inode_child);
25073e2efce0SAmy Griffis 
25083e2efce0SAmy Griffis /**
2509b0dd25a8SRandy Dunlap  * auditsc_get_stamp - get local copies of audit_context values
2510b0dd25a8SRandy Dunlap  * @ctx: audit_context for the task
25112115bb25SDeepa Dinamani  * @t: timespec64 to store time recorded in the audit_context
2512b0dd25a8SRandy Dunlap  * @serial: serial value that is recorded in the audit_context
2513b0dd25a8SRandy Dunlap  *
2514b0dd25a8SRandy Dunlap  * Also sets the context as auditable.
2515b0dd25a8SRandy Dunlap  */
auditsc_get_stamp(struct audit_context * ctx,struct timespec64 * t,unsigned int * serial)251648887e63SAl Viro int auditsc_get_stamp(struct audit_context *ctx,
25172115bb25SDeepa Dinamani 		       struct timespec64 *t, unsigned int *serial)
25181da177e4SLinus Torvalds {
251912c5e81dSPaul Moore 	if (ctx->context == AUDIT_CTX_UNUSED)
252048887e63SAl Viro 		return 0;
2521ce625a80SDavid Woodhouse 	if (!ctx->serial)
2522ce625a80SDavid Woodhouse 		ctx->serial = audit_serial();
25231da177e4SLinus Torvalds 	t->tv_sec  = ctx->ctime.tv_sec;
25241da177e4SLinus Torvalds 	t->tv_nsec = ctx->ctime.tv_nsec;
25251da177e4SLinus Torvalds 	*serial    = ctx->serial;
25260590b933SAl Viro 	if (!ctx->prio) {
25270590b933SAl Viro 		ctx->prio = 1;
2528619ed58aSSergey Nazarov 		ctx->current_state = AUDIT_STATE_RECORD;
25290590b933SAl Viro 	}
253048887e63SAl Viro 	return 1;
25311da177e4SLinus Torvalds }
25321da177e4SLinus Torvalds 
2533b0dd25a8SRandy Dunlap /**
253420ca73bcSGeorge C. Wilson  * __audit_mq_open - record audit data for a POSIX MQ open
253520ca73bcSGeorge C. Wilson  * @oflag: open flag
253620ca73bcSGeorge C. Wilson  * @mode: mode bits
25376b962559SRandy Dunlap  * @attr: queue attributes
253820ca73bcSGeorge C. Wilson  *
253920ca73bcSGeorge C. Wilson  */
__audit_mq_open(int oflag,umode_t mode,struct mq_attr * attr)2540df0a4283SAl Viro void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
254120ca73bcSGeorge C. Wilson {
2542cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
254320ca73bcSGeorge C. Wilson 
2544564f6993SAl Viro 	if (attr)
2545564f6993SAl Viro 		memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr));
2546564f6993SAl Viro 	else
2547564f6993SAl Viro 		memset(&context->mq_open.attr, 0, sizeof(struct mq_attr));
254820ca73bcSGeorge C. Wilson 
2549564f6993SAl Viro 	context->mq_open.oflag = oflag;
2550564f6993SAl Viro 	context->mq_open.mode = mode;
255120ca73bcSGeorge C. Wilson 
2552564f6993SAl Viro 	context->type = AUDIT_MQ_OPEN;
255320ca73bcSGeorge C. Wilson }
255420ca73bcSGeorge C. Wilson 
255520ca73bcSGeorge C. Wilson /**
2556c32c8af4SAl Viro  * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive
255720ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
255820ca73bcSGeorge C. Wilson  * @msg_len: Message length
255920ca73bcSGeorge C. Wilson  * @msg_prio: Message priority
2560c32c8af4SAl Viro  * @abs_timeout: Message timeout in absolute time
256120ca73bcSGeorge C. Wilson  *
256220ca73bcSGeorge C. Wilson  */
__audit_mq_sendrecv(mqd_t mqdes,size_t msg_len,unsigned int msg_prio,const struct timespec64 * abs_timeout)2563c32c8af4SAl Viro void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
2564b9047726SDeepa Dinamani 			const struct timespec64 *abs_timeout)
256520ca73bcSGeorge C. Wilson {
2566cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2567b9047726SDeepa Dinamani 	struct timespec64 *p = &context->mq_sendrecv.abs_timeout;
256820ca73bcSGeorge C. Wilson 
2569c32c8af4SAl Viro 	if (abs_timeout)
2570b9047726SDeepa Dinamani 		memcpy(p, abs_timeout, sizeof(*p));
2571c32c8af4SAl Viro 	else
2572b9047726SDeepa Dinamani 		memset(p, 0, sizeof(*p));
257320ca73bcSGeorge C. Wilson 
2574c32c8af4SAl Viro 	context->mq_sendrecv.mqdes = mqdes;
2575c32c8af4SAl Viro 	context->mq_sendrecv.msg_len = msg_len;
2576c32c8af4SAl Viro 	context->mq_sendrecv.msg_prio = msg_prio;
257720ca73bcSGeorge C. Wilson 
2578c32c8af4SAl Viro 	context->type = AUDIT_MQ_SENDRECV;
257920ca73bcSGeorge C. Wilson }
258020ca73bcSGeorge C. Wilson 
258120ca73bcSGeorge C. Wilson /**
258220ca73bcSGeorge C. Wilson  * __audit_mq_notify - record audit data for a POSIX MQ notify
258320ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
25846b962559SRandy Dunlap  * @notification: Notification event
258520ca73bcSGeorge C. Wilson  *
258620ca73bcSGeorge C. Wilson  */
258720ca73bcSGeorge C. Wilson 
__audit_mq_notify(mqd_t mqdes,const struct sigevent * notification)258820114f71SAl Viro void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
258920ca73bcSGeorge C. Wilson {
2590cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
259120ca73bcSGeorge C. Wilson 
259220114f71SAl Viro 	if (notification)
259320114f71SAl Viro 		context->mq_notify.sigev_signo = notification->sigev_signo;
259420114f71SAl Viro 	else
259520114f71SAl Viro 		context->mq_notify.sigev_signo = 0;
259620ca73bcSGeorge C. Wilson 
259720114f71SAl Viro 	context->mq_notify.mqdes = mqdes;
259820114f71SAl Viro 	context->type = AUDIT_MQ_NOTIFY;
259920ca73bcSGeorge C. Wilson }
260020ca73bcSGeorge C. Wilson 
260120ca73bcSGeorge C. Wilson /**
260220ca73bcSGeorge C. Wilson  * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
260320ca73bcSGeorge C. Wilson  * @mqdes: MQ descriptor
260420ca73bcSGeorge C. Wilson  * @mqstat: MQ flags
260520ca73bcSGeorge C. Wilson  *
260620ca73bcSGeorge C. Wilson  */
__audit_mq_getsetattr(mqd_t mqdes,struct mq_attr * mqstat)26077392906eSAl Viro void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
260820ca73bcSGeorge C. Wilson {
2609cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2610254c8b96SRoni Nevalainen 
26117392906eSAl Viro 	context->mq_getsetattr.mqdes = mqdes;
26127392906eSAl Viro 	context->mq_getsetattr.mqstat = *mqstat;
26137392906eSAl Viro 	context->type = AUDIT_MQ_GETSETATTR;
261420ca73bcSGeorge C. Wilson }
261520ca73bcSGeorge C. Wilson 
261620ca73bcSGeorge C. Wilson /**
2617196a5085SGeliang Tang  * __audit_ipc_obj - record audit data for ipc object
2618073115d6SSteve Grubb  * @ipcp: ipc permissions
2619073115d6SSteve Grubb  *
2620073115d6SSteve Grubb  */
__audit_ipc_obj(struct kern_ipc_perm * ipcp)2621a33e6751SAl Viro void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
2622073115d6SSteve Grubb {
2623cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2624254c8b96SRoni Nevalainen 
2625a33e6751SAl Viro 	context->ipc.uid = ipcp->uid;
2626a33e6751SAl Viro 	context->ipc.gid = ipcp->gid;
2627a33e6751SAl Viro 	context->ipc.mode = ipcp->mode;
2628e816f370SAl Viro 	context->ipc.has_perm = 0;
2629f4602f16SCasey Schaufler 	security_ipc_getlsmprop(ipcp, &context->ipc.oprop);
2630a33e6751SAl Viro 	context->type = AUDIT_IPC;
2631073115d6SSteve Grubb }
2632073115d6SSteve Grubb 
2633073115d6SSteve Grubb /**
2634196a5085SGeliang Tang  * __audit_ipc_set_perm - record audit data for new ipc permissions
2635b0dd25a8SRandy Dunlap  * @qbytes: msgq bytes
2636b0dd25a8SRandy Dunlap  * @uid: msgq user id
2637b0dd25a8SRandy Dunlap  * @gid: msgq group id
2638b0dd25a8SRandy Dunlap  * @mode: msgq mode (permissions)
2639b0dd25a8SRandy Dunlap  *
2640e816f370SAl Viro  * Called only after audit_ipc_obj().
2641b0dd25a8SRandy Dunlap  */
__audit_ipc_set_perm(unsigned long qbytes,uid_t uid,gid_t gid,umode_t mode)26422570ebbdSAl Viro void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode)
26431da177e4SLinus Torvalds {
2644cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
26451da177e4SLinus Torvalds 
2646e816f370SAl Viro 	context->ipc.qbytes = qbytes;
2647e816f370SAl Viro 	context->ipc.perm_uid = uid;
2648e816f370SAl Viro 	context->ipc.perm_gid = gid;
2649e816f370SAl Viro 	context->ipc.perm_mode = mode;
2650e816f370SAl Viro 	context->ipc.has_perm = 1;
26511da177e4SLinus Torvalds }
2652c2f0c7c3SSteve Grubb 
__audit_bprm(struct linux_binprm * bprm)2653d9cfea91SRichard Guy Briggs void __audit_bprm(struct linux_binprm *bprm)
2654473ae30bSAl Viro {
2655cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2656473ae30bSAl Viro 
2657d9cfea91SRichard Guy Briggs 	context->type = AUDIT_EXECVE;
2658d9cfea91SRichard Guy Briggs 	context->execve.argc = bprm->argc;
2659473ae30bSAl Viro }
2660473ae30bSAl Viro 
2661473ae30bSAl Viro 
2662b0dd25a8SRandy Dunlap /**
2663196a5085SGeliang Tang  * __audit_socketcall - record audit data for sys_socketcall
26642950fa9dSChen Gang  * @nargs: number of args, which should not be more than AUDITSC_ARGS.
2665b0dd25a8SRandy Dunlap  * @args: args array
2666b0dd25a8SRandy Dunlap  *
2667b0dd25a8SRandy Dunlap  */
__audit_socketcall(int nargs,unsigned long * args)26682950fa9dSChen Gang int __audit_socketcall(int nargs, unsigned long *args)
26693ec3b2fbSDavid Woodhouse {
2670cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
26713ec3b2fbSDavid Woodhouse 
26722950fa9dSChen Gang 	if (nargs <= 0 || nargs > AUDITSC_ARGS || !args)
26732950fa9dSChen Gang 		return -EINVAL;
2674f3298dc4SAl Viro 	context->type = AUDIT_SOCKETCALL;
2675f3298dc4SAl Viro 	context->socketcall.nargs = nargs;
2676f3298dc4SAl Viro 	memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
26772950fa9dSChen Gang 	return 0;
26783ec3b2fbSDavid Woodhouse }
26793ec3b2fbSDavid Woodhouse 
2680b0dd25a8SRandy Dunlap /**
2681db349509SAl Viro  * __audit_fd_pair - record audit data for pipe and socketpair
2682db349509SAl Viro  * @fd1: the first file descriptor
2683db349509SAl Viro  * @fd2: the second file descriptor
2684db349509SAl Viro  *
2685db349509SAl Viro  */
__audit_fd_pair(int fd1,int fd2)2686157cf649SAl Viro void __audit_fd_pair(int fd1, int fd2)
2687db349509SAl Viro {
2688cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2689254c8b96SRoni Nevalainen 
2690157cf649SAl Viro 	context->fds[0] = fd1;
2691157cf649SAl Viro 	context->fds[1] = fd2;
2692db349509SAl Viro }
2693db349509SAl Viro 
2694db349509SAl Viro /**
2695196a5085SGeliang Tang  * __audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
2696b0dd25a8SRandy Dunlap  * @len: data length in user space
2697b0dd25a8SRandy Dunlap  * @a: data address in kernel space
2698b0dd25a8SRandy Dunlap  *
2699b0dd25a8SRandy Dunlap  * Returns 0 for success or NULL context or < 0 on error.
2700b0dd25a8SRandy Dunlap  */
__audit_sockaddr(int len,void * a)270107c49417SEric Paris int __audit_sockaddr(int len, void *a)
27023ec3b2fbSDavid Woodhouse {
2703cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
27043ec3b2fbSDavid Woodhouse 
27054f6b434fSAl Viro 	if (!context->sockaddr) {
27064f6b434fSAl Viro 		void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
2707254c8b96SRoni Nevalainen 
27084f6b434fSAl Viro 		if (!p)
27093ec3b2fbSDavid Woodhouse 			return -ENOMEM;
27104f6b434fSAl Viro 		context->sockaddr = p;
27114f6b434fSAl Viro 	}
27123ec3b2fbSDavid Woodhouse 
27134f6b434fSAl Viro 	context->sockaddr_len = len;
27144f6b434fSAl Viro 	memcpy(context->sockaddr, a, len);
27153ec3b2fbSDavid Woodhouse 	return 0;
27163ec3b2fbSDavid Woodhouse }
27173ec3b2fbSDavid Woodhouse 
__audit_ptrace(struct task_struct * t)2718a5cb013dSAl Viro void __audit_ptrace(struct task_struct *t)
2719a5cb013dSAl Viro {
2720cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2721a5cb013dSAl Viro 
2722fa2bea2fSPaul Moore 	context->target_pid = task_tgid_nr(t);
2723c2a7780eSEric Paris 	context->target_auid = audit_get_loginuid(t);
2724c69e8d9cSDavid Howells 	context->target_uid = task_uid(t);
27254746ec5bSEric Paris 	context->target_sessionid = audit_get_sessionid(t);
2726286d7a54SYafang Shao 	strscpy(context->target_comm, t->comm);
2727d9381508SYafang shao 	security_task_getlsmprop_obj(t, &context->target_ref);
2728a5cb013dSAl Viro }
2729a5cb013dSAl Viro 
2730b0dd25a8SRandy Dunlap /**
2731b48345aaSRichard Guy Briggs  * audit_signal_info_syscall - record signal info for syscalls
2732b0dd25a8SRandy Dunlap  * @t: task being signaled
2733b0dd25a8SRandy Dunlap  *
2734b0dd25a8SRandy Dunlap  * If the audit subsystem is being terminated, record the task (pid)
2735b0dd25a8SRandy Dunlap  * and uid that is doing that.
2736b0dd25a8SRandy Dunlap  */
audit_signal_info_syscall(struct task_struct * t)2737b48345aaSRichard Guy Briggs int audit_signal_info_syscall(struct task_struct *t)
2738c2f0c7c3SSteve Grubb {
2739e54dc243SAmy Griffis 	struct audit_aux_data_pids *axp;
2740cdfb6b34SRichard Guy Briggs 	struct audit_context *ctx = audit_context();
2741b48345aaSRichard Guy Briggs 	kuid_t t_uid = task_uid(t);
2742ab6434a1SPaul Moore 
2743175fc484SAl Viro 	if (!audit_signals || audit_dummy_context())
2744e54dc243SAmy Griffis 		return 0;
2745e54dc243SAmy Griffis 
2746e54dc243SAmy Griffis 	/* optimize the common case by putting first signal recipient directly
2747e54dc243SAmy Griffis 	 * in audit_context */
2748e54dc243SAmy Griffis 	if (!ctx->target_pid) {
2749f1dc4867SRichard Guy Briggs 		ctx->target_pid = task_tgid_nr(t);
2750c2a7780eSEric Paris 		ctx->target_auid = audit_get_loginuid(t);
2751c69e8d9cSDavid Howells 		ctx->target_uid = t_uid;
27524746ec5bSEric Paris 		ctx->target_sessionid = audit_get_sessionid(t);
2753286d7a54SYafang Shao 		strscpy(ctx->target_comm, t->comm);
2754d9381508SYafang shao 		security_task_getlsmprop_obj(t, &ctx->target_ref);
2755e54dc243SAmy Griffis 		return 0;
2756e54dc243SAmy Griffis 	}
2757e54dc243SAmy Griffis 
2758e54dc243SAmy Griffis 	axp = (void *)ctx->aux_pids;
2759e54dc243SAmy Griffis 	if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
2760e54dc243SAmy Griffis 		axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
2761e54dc243SAmy Griffis 		if (!axp)
2762e54dc243SAmy Griffis 			return -ENOMEM;
2763e54dc243SAmy Griffis 
2764e54dc243SAmy Griffis 		axp->d.type = AUDIT_OBJ_PID;
2765e54dc243SAmy Griffis 		axp->d.next = ctx->aux_pids;
2766e54dc243SAmy Griffis 		ctx->aux_pids = (void *)axp;
2767e54dc243SAmy Griffis 	}
276888ae704cSAdrian Bunk 	BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
2769e54dc243SAmy Griffis 
2770f1dc4867SRichard Guy Briggs 	axp->target_pid[axp->pid_count] = task_tgid_nr(t);
2771c2a7780eSEric Paris 	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
2772c69e8d9cSDavid Howells 	axp->target_uid[axp->pid_count] = t_uid;
27734746ec5bSEric Paris 	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
277413d826e5SCasey Schaufler 	security_task_getlsmprop_obj(t, &axp->target_ref[axp->pid_count]);
2775286d7a54SYafang Shao 	strscpy(axp->target_comm[axp->pid_count], t->comm);
2776e54dc243SAmy Griffis 	axp->pid_count++;
2777e54dc243SAmy Griffis 
2778e54dc243SAmy Griffis 	return 0;
2779c2f0c7c3SSteve Grubb }
27800a4ff8c2SSteve Grubb 
27810a4ff8c2SSteve Grubb /**
27823fc689e9SEric Paris  * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps
2783d84f4f99SDavid Howells  * @bprm: pointer to the bprm being processed
2784d84f4f99SDavid Howells  * @new: the proposed new credentials
2785d84f4f99SDavid Howells  * @old: the old credentials
27863fc689e9SEric Paris  *
27873fc689e9SEric Paris  * Simply check if the proc already has the caps given by the file and if not
27883fc689e9SEric Paris  * store the priv escalation info for later auditing at the end of the syscall
27893fc689e9SEric Paris  *
27903fc689e9SEric Paris  * -Eric
27913fc689e9SEric Paris  */
__audit_log_bprm_fcaps(struct linux_binprm * bprm,const struct cred * new,const struct cred * old)2792d84f4f99SDavid Howells int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
2793d84f4f99SDavid Howells 			   const struct cred *new, const struct cred *old)
27943fc689e9SEric Paris {
27953fc689e9SEric Paris 	struct audit_aux_data_bprm_fcaps *ax;
2796cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
27973fc689e9SEric Paris 	struct cpu_vfs_cap_data vcaps;
27983fc689e9SEric Paris 
27993fc689e9SEric Paris 	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
28003fc689e9SEric Paris 	if (!ax)
2801d84f4f99SDavid Howells 		return -ENOMEM;
28023fc689e9SEric Paris 
28033fc689e9SEric Paris 	ax->d.type = AUDIT_BPRM_FCAPS;
28043fc689e9SEric Paris 	ax->d.next = context->aux;
28053fc689e9SEric Paris 	context->aux = (void *)ax;
28063fc689e9SEric Paris 
280739f60c1cSChristian Brauner 	get_vfs_caps_from_disk(&nop_mnt_idmap,
280871bc356fSChristian Brauner 			       bprm->file->f_path.dentry, &vcaps);
28093fc689e9SEric Paris 
28103fc689e9SEric Paris 	ax->fcap.permitted = vcaps.permitted;
28113fc689e9SEric Paris 	ax->fcap.inheritable = vcaps.inheritable;
28123fc689e9SEric Paris 	ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
28132fec30e2SRichard Guy Briggs 	ax->fcap.rootid = vcaps.rootid;
28143fc689e9SEric Paris 	ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
28153fc689e9SEric Paris 
2816d84f4f99SDavid Howells 	ax->old_pcap.permitted   = old->cap_permitted;
2817d84f4f99SDavid Howells 	ax->old_pcap.inheritable = old->cap_inheritable;
2818d84f4f99SDavid Howells 	ax->old_pcap.effective   = old->cap_effective;
28197786f6b6SRichard Guy Briggs 	ax->old_pcap.ambient     = old->cap_ambient;
28203fc689e9SEric Paris 
2821d84f4f99SDavid Howells 	ax->new_pcap.permitted   = new->cap_permitted;
2822d84f4f99SDavid Howells 	ax->new_pcap.inheritable = new->cap_inheritable;
2823d84f4f99SDavid Howells 	ax->new_pcap.effective   = new->cap_effective;
28247786f6b6SRichard Guy Briggs 	ax->new_pcap.ambient     = new->cap_ambient;
2825d84f4f99SDavid Howells 	return 0;
28263fc689e9SEric Paris }
28273fc689e9SEric Paris 
28283fc689e9SEric Paris /**
2829e68b75a0SEric Paris  * __audit_log_capset - store information about the arguments to the capset syscall
2830d84f4f99SDavid Howells  * @new: the new credentials
2831d84f4f99SDavid Howells  * @old: the old (current) credentials
2832e68b75a0SEric Paris  *
2833da3dae54SMasanari Iida  * Record the arguments userspace sent to sys_capset for later printing by the
2834e68b75a0SEric Paris  * audit system if applicable
2835e68b75a0SEric Paris  */
__audit_log_capset(const struct cred * new,const struct cred * old)2836ca24a23eSEric W. Biederman void __audit_log_capset(const struct cred *new, const struct cred *old)
2837e68b75a0SEric Paris {
2838cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2839254c8b96SRoni Nevalainen 
2840fa2bea2fSPaul Moore 	context->capset.pid = task_tgid_nr(current);
284157f71a0aSAl Viro 	context->capset.cap.effective   = new->cap_effective;
284257f71a0aSAl Viro 	context->capset.cap.inheritable = new->cap_effective;
284357f71a0aSAl Viro 	context->capset.cap.permitted   = new->cap_permitted;
28447786f6b6SRichard Guy Briggs 	context->capset.cap.ambient     = new->cap_ambient;
284557f71a0aSAl Viro 	context->type = AUDIT_CAPSET;
2846e68b75a0SEric Paris }
2847e68b75a0SEric Paris 
__audit_mmap_fd(int fd,int flags)2848120a795dSAl Viro void __audit_mmap_fd(int fd, int flags)
2849120a795dSAl Viro {
2850cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2851254c8b96SRoni Nevalainen 
2852120a795dSAl Viro 	context->mmap.fd = fd;
2853120a795dSAl Viro 	context->mmap.flags = flags;
2854120a795dSAl Viro 	context->type = AUDIT_MMAP;
2855120a795dSAl Viro }
2856120a795dSAl Viro 
__audit_openat2_how(struct open_how * how)2857571e5c0eSRichard Guy Briggs void __audit_openat2_how(struct open_how *how)
2858571e5c0eSRichard Guy Briggs {
2859571e5c0eSRichard Guy Briggs 	struct audit_context *context = audit_context();
2860571e5c0eSRichard Guy Briggs 
2861571e5c0eSRichard Guy Briggs 	context->openat2.flags = how->flags;
2862571e5c0eSRichard Guy Briggs 	context->openat2.mode = how->mode;
2863571e5c0eSRichard Guy Briggs 	context->openat2.resolve = how->resolve;
2864571e5c0eSRichard Guy Briggs 	context->type = AUDIT_OPENAT2;
2865571e5c0eSRichard Guy Briggs }
2866571e5c0eSRichard Guy Briggs 
__audit_log_kern_module(char * name)2867ca86cad7SRichard Guy Briggs void __audit_log_kern_module(char *name)
2868ca86cad7SRichard Guy Briggs {
2869cdfb6b34SRichard Guy Briggs 	struct audit_context *context = audit_context();
2870ca86cad7SRichard Guy Briggs 
2871b305f7edSYi Wang 	context->module.name = kstrdup(name, GFP_KERNEL);
2872b305f7edSYi Wang 	if (!context->module.name)
2873b305f7edSYi Wang 		audit_log_lost("out of memory in __audit_log_kern_module");
2874ca86cad7SRichard Guy Briggs 	context->type = AUDIT_KERN_MODULE;
2875ca86cad7SRichard Guy Briggs }
2876ca86cad7SRichard Guy Briggs 
__audit_fanotify(u32 response,struct fanotify_response_info_audit_rule * friar)2877032bffd4SRichard Guy Briggs void __audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
2878de8cd83eSSteve Grubb {
2879032bffd4SRichard Guy Briggs 	/* {subj,obj}_trust values are {0,1,2}: no,yes,unknown */
2880032bffd4SRichard Guy Briggs 	switch (friar->hdr.type) {
2881032bffd4SRichard Guy Briggs 	case FAN_RESPONSE_INFO_NONE:
2882032bffd4SRichard Guy Briggs 		audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2883032bffd4SRichard Guy Briggs 			  "resp=%u fan_type=%u fan_info=0 subj_trust=2 obj_trust=2",
2884032bffd4SRichard Guy Briggs 			  response, FAN_RESPONSE_INFO_NONE);
2885032bffd4SRichard Guy Briggs 		break;
2886032bffd4SRichard Guy Briggs 	case FAN_RESPONSE_INFO_AUDIT_RULE:
2887032bffd4SRichard Guy Briggs 		audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2888032bffd4SRichard Guy Briggs 			  "resp=%u fan_type=%u fan_info=%X subj_trust=%u obj_trust=%u",
2889032bffd4SRichard Guy Briggs 			  response, friar->hdr.type, friar->rule_number,
2890032bffd4SRichard Guy Briggs 			  friar->subj_trust, friar->obj_trust);
2891032bffd4SRichard Guy Briggs 	}
2892de8cd83eSSteve Grubb }
2893de8cd83eSSteve Grubb 
__audit_tk_injoffset(struct timespec64 offset)28942d87a067SOndrej Mosnacek void __audit_tk_injoffset(struct timespec64 offset)
28952d87a067SOndrej Mosnacek {
2896272ceeaeSRichard Guy Briggs 	struct audit_context *context = audit_context();
28972d87a067SOndrej Mosnacek 
2898272ceeaeSRichard Guy Briggs 	/* only set type if not already set by NTP */
2899272ceeaeSRichard Guy Briggs 	if (!context->type)
2900272ceeaeSRichard Guy Briggs 		context->type = AUDIT_TIME_INJOFFSET;
2901272ceeaeSRichard Guy Briggs 	memcpy(&context->time.tk_injoffset, &offset, sizeof(offset));
29027e8eda73SOndrej Mosnacek }
29037e8eda73SOndrej Mosnacek 
__audit_ntp_log(const struct audit_ntp_data * ad)29047e8eda73SOndrej Mosnacek void __audit_ntp_log(const struct audit_ntp_data *ad)
29057e8eda73SOndrej Mosnacek {
2906272ceeaeSRichard Guy Briggs 	struct audit_context *context = audit_context();
2907272ceeaeSRichard Guy Briggs 	int type;
2908272ceeaeSRichard Guy Briggs 
2909272ceeaeSRichard Guy Briggs 	for (type = 0; type < AUDIT_NTP_NVALS; type++)
2910272ceeaeSRichard Guy Briggs 		if (ad->vals[type].newval != ad->vals[type].oldval) {
2911272ceeaeSRichard Guy Briggs 			/* unconditionally set type, overwriting TK */
2912272ceeaeSRichard Guy Briggs 			context->type = AUDIT_TIME_ADJNTPVAL;
2913272ceeaeSRichard Guy Briggs 			memcpy(&context->time.ntp_data, ad, sizeof(*ad));
2914272ceeaeSRichard Guy Briggs 			break;
2915272ceeaeSRichard Guy Briggs 		}
29167e8eda73SOndrej Mosnacek }
29177e8eda73SOndrej Mosnacek 
__audit_log_nfcfg(const char * name,u8 af,unsigned int nentries,enum audit_nfcfgop op,gfp_t gfp)2918c4dad0aaSRichard Guy Briggs void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
291914224039SRichard Guy Briggs 		       enum audit_nfcfgop op, gfp_t gfp)
2920c4dad0aaSRichard Guy Briggs {
2921c4dad0aaSRichard Guy Briggs 	struct audit_buffer *ab;
29229d44a121SRichard Guy Briggs 	char comm[sizeof(current->comm)];
2923c4dad0aaSRichard Guy Briggs 
292414224039SRichard Guy Briggs 	ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG);
2925c4dad0aaSRichard Guy Briggs 	if (!ab)
2926c4dad0aaSRichard Guy Briggs 		return;
2927c4dad0aaSRichard Guy Briggs 	audit_log_format(ab, "table=%s family=%u entries=%u op=%s",
2928c4dad0aaSRichard Guy Briggs 			 name, af, nentries, audit_nfcfgs[op].s);
29299d44a121SRichard Guy Briggs 
293061c60977SRicardo Robaina 	audit_log_format(ab, " pid=%u", task_tgid_nr(current));
29319d44a121SRichard Guy Briggs 	audit_log_task_context(ab); /* subj= */
29329d44a121SRichard Guy Briggs 	audit_log_format(ab, " comm=");
29339d44a121SRichard Guy Briggs 	audit_log_untrustedstring(ab, get_task_comm(comm, current));
2934c4dad0aaSRichard Guy Briggs 	audit_log_end(ab);
2935c4dad0aaSRichard Guy Briggs }
2936c4dad0aaSRichard Guy Briggs EXPORT_SYMBOL_GPL(__audit_log_nfcfg);
2937c4dad0aaSRichard Guy Briggs 
audit_log_task(struct audit_buffer * ab)29387b9205bdSKees Cook static void audit_log_task(struct audit_buffer *ab)
293985e7bac3SEric Paris {
2940cca080d9SEric W. Biederman 	kuid_t auid, uid;
2941cca080d9SEric W. Biederman 	kgid_t gid;
294285e7bac3SEric Paris 	unsigned int sessionid;
29439eab339bSRichard Guy Briggs 	char comm[sizeof(current->comm)];
294485e7bac3SEric Paris 
294585e7bac3SEric Paris 	auid = audit_get_loginuid(current);
294685e7bac3SEric Paris 	sessionid = audit_get_sessionid(current);
294785e7bac3SEric Paris 	current_uid_gid(&uid, &gid);
294885e7bac3SEric Paris 
294985e7bac3SEric Paris 	audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
2950cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, auid),
2951cca080d9SEric W. Biederman 			 from_kuid(&init_user_ns, uid),
2952cca080d9SEric W. Biederman 			 from_kgid(&init_user_ns, gid),
2953cca080d9SEric W. Biederman 			 sessionid);
295485e7bac3SEric Paris 	audit_log_task_context(ab);
2955fa2bea2fSPaul Moore 	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
29569eab339bSRichard Guy Briggs 	audit_log_untrustedstring(ab, get_task_comm(comm, current));
29574766b199SDavidlohr Bueso 	audit_log_d_path_exe(ab, current->mm);
29587b9205bdSKees Cook }
29597b9205bdSKees Cook 
2960e68b75a0SEric Paris /**
29610a4ff8c2SSteve Grubb  * audit_core_dumps - record information about processes that end abnormally
29626d9525b5SHenrik Kretzschmar  * @signr: signal value
29630a4ff8c2SSteve Grubb  *
29640a4ff8c2SSteve Grubb  * If a process ends with a core dump, something fishy is going on and we
29650a4ff8c2SSteve Grubb  * should record the event for investigation.
29660a4ff8c2SSteve Grubb  */
audit_core_dumps(long signr)29670a4ff8c2SSteve Grubb void audit_core_dumps(long signr)
29680a4ff8c2SSteve Grubb {
29690a4ff8c2SSteve Grubb 	struct audit_buffer *ab;
29700a4ff8c2SSteve Grubb 
29710a4ff8c2SSteve Grubb 	if (!audit_enabled)
29720a4ff8c2SSteve Grubb 		return;
29730a4ff8c2SSteve Grubb 
29740a4ff8c2SSteve Grubb 	if (signr == SIGQUIT)	/* don't care for those */
29750a4ff8c2SSteve Grubb 		return;
29760a4ff8c2SSteve Grubb 
2977d87de4a8SRichard Guy Briggs 	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_ABEND);
29780644ec0cSKees Cook 	if (unlikely(!ab))
29790644ec0cSKees Cook 		return;
298061c0ee87SPaul Davies C 	audit_log_task(ab);
298189670affSSteve Grubb 	audit_log_format(ab, " sig=%ld res=1", signr);
298285e7bac3SEric Paris 	audit_log_end(ab);
298385e7bac3SEric Paris }
29840a4ff8c2SSteve Grubb 
2985326bee02STyler Hicks /**
2986326bee02STyler Hicks  * audit_seccomp - record information about a seccomp action
2987326bee02STyler Hicks  * @syscall: syscall number
2988326bee02STyler Hicks  * @signr: signal value
2989326bee02STyler Hicks  * @code: the seccomp action
2990326bee02STyler Hicks  *
2991326bee02STyler Hicks  * Record the information associated with a seccomp action. Event filtering for
2992326bee02STyler Hicks  * seccomp actions that are not to be logged is done in seccomp_log().
2993326bee02STyler Hicks  * Therefore, this function forces auditing independent of the audit_enabled
2994326bee02STyler Hicks  * and dummy context state because seccomp actions should be logged even when
2995326bee02STyler Hicks  * audit is not in use.
2996326bee02STyler Hicks  */
audit_seccomp(unsigned long syscall,long signr,int code)2997326bee02STyler Hicks void audit_seccomp(unsigned long syscall, long signr, int code)
299885e7bac3SEric Paris {
299985e7bac3SEric Paris 	struct audit_buffer *ab;
300085e7bac3SEric Paris 
30019b8753ffSRichard Guy Briggs 	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_SECCOMP);
30027b9205bdSKees Cook 	if (unlikely(!ab))
30037b9205bdSKees Cook 		return;
30047b9205bdSKees Cook 	audit_log_task(ab);
300584db564aSRichard Guy Briggs 	audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
300616add411SDmitry V. Levin 			 signr, syscall_get_arch(current), syscall,
3007efbc0fbfSAndy Lutomirski 			 in_compat_syscall(), KSTK_EIP(current), code);
30080a4ff8c2SSteve Grubb 	audit_log_end(ab);
30090a4ff8c2SSteve Grubb }
3010916d7576SAl Viro 
audit_seccomp_actions_logged(const char * names,const char * old_names,int res)3011ea6eca77STyler Hicks void audit_seccomp_actions_logged(const char *names, const char *old_names,
3012ea6eca77STyler Hicks 				  int res)
3013ea6eca77STyler Hicks {
3014ea6eca77STyler Hicks 	struct audit_buffer *ab;
3015ea6eca77STyler Hicks 
3016ea6eca77STyler Hicks 	if (!audit_enabled)
3017ea6eca77STyler Hicks 		return;
3018ea6eca77STyler Hicks 
30198982a1fbSRichard Guy Briggs 	ab = audit_log_start(audit_context(), GFP_KERNEL,
3020ea6eca77STyler Hicks 			     AUDIT_CONFIG_CHANGE);
3021ea6eca77STyler Hicks 	if (unlikely(!ab))
3022ea6eca77STyler Hicks 		return;
3023ea6eca77STyler Hicks 
3024d0a3f18aSPaul Moore 	audit_log_format(ab,
3025d0a3f18aSPaul Moore 			 "op=seccomp-logging actions=%s old-actions=%s res=%d",
3026d0a3f18aSPaul Moore 			 names, old_names, res);
3027ea6eca77STyler Hicks 	audit_log_end(ab);
3028ea6eca77STyler Hicks }
3029ea6eca77STyler Hicks 
audit_killed_trees(void)3030916d7576SAl Viro struct list_head *audit_killed_trees(void)
3031916d7576SAl Viro {
3032cdfb6b34SRichard Guy Briggs 	struct audit_context *ctx = audit_context();
303312c5e81dSPaul Moore 	if (likely(!ctx || ctx->context == AUDIT_CTX_UNUSED))
3034916d7576SAl Viro 		return NULL;
3035916d7576SAl Viro 	return &ctx->killed_trees;
3036916d7576SAl Viro }
3037