162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* auditsc.c -- System-call auditing support
362306a36Sopenharmony_ci * Handles all system-call specific auditing features.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
662306a36Sopenharmony_ci * Copyright 2005 Hewlett-Packard Development Company, L.P.
762306a36Sopenharmony_ci * Copyright (C) 2005, 2006 IBM Corporation
862306a36Sopenharmony_ci * All Rights Reserved.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Written by Rickard E. (Rik) Faith <faith@redhat.com>
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Many of the ideas implemented here are from Stephen C. Tweedie,
1362306a36Sopenharmony_ci * especially the idea of avoiding a copy by using getname.
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * The method for actual interception of syscall entry and exit (not in
1662306a36Sopenharmony_ci * this file -- see entry.S) is based on a GPL'd patch written by
1762306a36Sopenharmony_ci * okir@suse.de and Copyright 2003 SuSE Linux AG.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
2062306a36Sopenharmony_ci * 2006.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * The support of additional filter rules compares (>, <, >=, <=) was
2362306a36Sopenharmony_ci * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
2662306a36Sopenharmony_ci * filesystem information.
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * Subject and object context labeling support added by <danjones@us.ibm.com>
2962306a36Sopenharmony_ci * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#include <linux/init.h>
3562306a36Sopenharmony_ci#include <asm/types.h>
3662306a36Sopenharmony_ci#include <linux/atomic.h>
3762306a36Sopenharmony_ci#include <linux/fs.h>
3862306a36Sopenharmony_ci#include <linux/namei.h>
3962306a36Sopenharmony_ci#include <linux/mm.h>
4062306a36Sopenharmony_ci#include <linux/export.h>
4162306a36Sopenharmony_ci#include <linux/slab.h>
4262306a36Sopenharmony_ci#include <linux/mount.h>
4362306a36Sopenharmony_ci#include <linux/socket.h>
4462306a36Sopenharmony_ci#include <linux/mqueue.h>
4562306a36Sopenharmony_ci#include <linux/audit.h>
4662306a36Sopenharmony_ci#include <linux/personality.h>
4762306a36Sopenharmony_ci#include <linux/time.h>
4862306a36Sopenharmony_ci#include <linux/netlink.h>
4962306a36Sopenharmony_ci#include <linux/compiler.h>
5062306a36Sopenharmony_ci#include <asm/unistd.h>
5162306a36Sopenharmony_ci#include <linux/security.h>
5262306a36Sopenharmony_ci#include <linux/list.h>
5362306a36Sopenharmony_ci#include <linux/binfmts.h>
5462306a36Sopenharmony_ci#include <linux/highmem.h>
5562306a36Sopenharmony_ci#include <linux/syscalls.h>
5662306a36Sopenharmony_ci#include <asm/syscall.h>
5762306a36Sopenharmony_ci#include <linux/capability.h>
5862306a36Sopenharmony_ci#include <linux/fs_struct.h>
5962306a36Sopenharmony_ci#include <linux/compat.h>
6062306a36Sopenharmony_ci#include <linux/ctype.h>
6162306a36Sopenharmony_ci#include <linux/string.h>
6262306a36Sopenharmony_ci#include <linux/uaccess.h>
6362306a36Sopenharmony_ci#include <linux/fsnotify_backend.h>
6462306a36Sopenharmony_ci#include <uapi/linux/limits.h>
6562306a36Sopenharmony_ci#include <uapi/linux/netfilter/nf_tables.h>
6662306a36Sopenharmony_ci#include <uapi/linux/openat2.h> // struct open_how
6762306a36Sopenharmony_ci#include <uapi/linux/fanotify.h>
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#include "audit.h"
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/* flags stating the success for a syscall */
7262306a36Sopenharmony_ci#define AUDITSC_INVALID 0
7362306a36Sopenharmony_ci#define AUDITSC_SUCCESS 1
7462306a36Sopenharmony_ci#define AUDITSC_FAILURE 2
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/* no execve audit message should be longer than this (userspace limits),
7762306a36Sopenharmony_ci * see the note near the top of audit_log_execve_info() about this value */
7862306a36Sopenharmony_ci#define MAX_EXECVE_AUDIT_LEN 7500
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/* max length to print of cmdline/proctitle value during audit */
8162306a36Sopenharmony_ci#define MAX_PROCTITLE_AUDIT_LEN 128
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/* number of audit rules */
8462306a36Sopenharmony_ciint audit_n_rules;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/* determines whether we collect data for signals sent */
8762306a36Sopenharmony_ciint audit_signals;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistruct audit_aux_data {
9062306a36Sopenharmony_ci	struct audit_aux_data	*next;
9162306a36Sopenharmony_ci	int			type;
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/* Number of target pids per aux struct. */
9562306a36Sopenharmony_ci#define AUDIT_AUX_PIDS	16
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistruct audit_aux_data_pids {
9862306a36Sopenharmony_ci	struct audit_aux_data	d;
9962306a36Sopenharmony_ci	pid_t			target_pid[AUDIT_AUX_PIDS];
10062306a36Sopenharmony_ci	kuid_t			target_auid[AUDIT_AUX_PIDS];
10162306a36Sopenharmony_ci	kuid_t			target_uid[AUDIT_AUX_PIDS];
10262306a36Sopenharmony_ci	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
10362306a36Sopenharmony_ci	u32			target_sid[AUDIT_AUX_PIDS];
10462306a36Sopenharmony_ci	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
10562306a36Sopenharmony_ci	int			pid_count;
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistruct audit_aux_data_bprm_fcaps {
10962306a36Sopenharmony_ci	struct audit_aux_data	d;
11062306a36Sopenharmony_ci	struct audit_cap_data	fcap;
11162306a36Sopenharmony_ci	unsigned int		fcap_ver;
11262306a36Sopenharmony_ci	struct audit_cap_data	old_pcap;
11362306a36Sopenharmony_ci	struct audit_cap_data	new_pcap;
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistruct audit_tree_refs {
11762306a36Sopenharmony_ci	struct audit_tree_refs *next;
11862306a36Sopenharmony_ci	struct audit_chunk *c[31];
11962306a36Sopenharmony_ci};
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistruct audit_nfcfgop_tab {
12262306a36Sopenharmony_ci	enum audit_nfcfgop	op;
12362306a36Sopenharmony_ci	const char		*s;
12462306a36Sopenharmony_ci};
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic const struct audit_nfcfgop_tab audit_nfcfgs[] = {
12762306a36Sopenharmony_ci	{ AUDIT_XT_OP_REGISTER,			"xt_register"		   },
12862306a36Sopenharmony_ci	{ AUDIT_XT_OP_REPLACE,			"xt_replace"		   },
12962306a36Sopenharmony_ci	{ AUDIT_XT_OP_UNREGISTER,		"xt_unregister"		   },
13062306a36Sopenharmony_ci	{ AUDIT_NFT_OP_TABLE_REGISTER,		"nft_register_table"	   },
13162306a36Sopenharmony_ci	{ AUDIT_NFT_OP_TABLE_UNREGISTER,	"nft_unregister_table"	   },
13262306a36Sopenharmony_ci	{ AUDIT_NFT_OP_CHAIN_REGISTER,		"nft_register_chain"	   },
13362306a36Sopenharmony_ci	{ AUDIT_NFT_OP_CHAIN_UNREGISTER,	"nft_unregister_chain"	   },
13462306a36Sopenharmony_ci	{ AUDIT_NFT_OP_RULE_REGISTER,		"nft_register_rule"	   },
13562306a36Sopenharmony_ci	{ AUDIT_NFT_OP_RULE_UNREGISTER,		"nft_unregister_rule"	   },
13662306a36Sopenharmony_ci	{ AUDIT_NFT_OP_SET_REGISTER,		"nft_register_set"	   },
13762306a36Sopenharmony_ci	{ AUDIT_NFT_OP_SET_UNREGISTER,		"nft_unregister_set"	   },
13862306a36Sopenharmony_ci	{ AUDIT_NFT_OP_SETELEM_REGISTER,	"nft_register_setelem"	   },
13962306a36Sopenharmony_ci	{ AUDIT_NFT_OP_SETELEM_UNREGISTER,	"nft_unregister_setelem"   },
14062306a36Sopenharmony_ci	{ AUDIT_NFT_OP_GEN_REGISTER,		"nft_register_gen"	   },
14162306a36Sopenharmony_ci	{ AUDIT_NFT_OP_OBJ_REGISTER,		"nft_register_obj"	   },
14262306a36Sopenharmony_ci	{ AUDIT_NFT_OP_OBJ_UNREGISTER,		"nft_unregister_obj"	   },
14362306a36Sopenharmony_ci	{ AUDIT_NFT_OP_OBJ_RESET,		"nft_reset_obj"		   },
14462306a36Sopenharmony_ci	{ AUDIT_NFT_OP_FLOWTABLE_REGISTER,	"nft_register_flowtable"   },
14562306a36Sopenharmony_ci	{ AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,	"nft_unregister_flowtable" },
14662306a36Sopenharmony_ci	{ AUDIT_NFT_OP_SETELEM_RESET,		"nft_reset_setelem"        },
14762306a36Sopenharmony_ci	{ AUDIT_NFT_OP_RULE_RESET,		"nft_reset_rule"           },
14862306a36Sopenharmony_ci	{ AUDIT_NFT_OP_INVALID,			"nft_invalid"		   },
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic int audit_match_perm(struct audit_context *ctx, int mask)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	unsigned n;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	if (unlikely(!ctx))
15662306a36Sopenharmony_ci		return 0;
15762306a36Sopenharmony_ci	n = ctx->major;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	switch (audit_classify_syscall(ctx->arch, n)) {
16062306a36Sopenharmony_ci	case AUDITSC_NATIVE:
16162306a36Sopenharmony_ci		if ((mask & AUDIT_PERM_WRITE) &&
16262306a36Sopenharmony_ci		     audit_match_class(AUDIT_CLASS_WRITE, n))
16362306a36Sopenharmony_ci			return 1;
16462306a36Sopenharmony_ci		if ((mask & AUDIT_PERM_READ) &&
16562306a36Sopenharmony_ci		     audit_match_class(AUDIT_CLASS_READ, n))
16662306a36Sopenharmony_ci			return 1;
16762306a36Sopenharmony_ci		if ((mask & AUDIT_PERM_ATTR) &&
16862306a36Sopenharmony_ci		     audit_match_class(AUDIT_CLASS_CHATTR, n))
16962306a36Sopenharmony_ci			return 1;
17062306a36Sopenharmony_ci		return 0;
17162306a36Sopenharmony_ci	case AUDITSC_COMPAT: /* 32bit on biarch */
17262306a36Sopenharmony_ci		if ((mask & AUDIT_PERM_WRITE) &&
17362306a36Sopenharmony_ci		     audit_match_class(AUDIT_CLASS_WRITE_32, n))
17462306a36Sopenharmony_ci			return 1;
17562306a36Sopenharmony_ci		if ((mask & AUDIT_PERM_READ) &&
17662306a36Sopenharmony_ci		     audit_match_class(AUDIT_CLASS_READ_32, n))
17762306a36Sopenharmony_ci			return 1;
17862306a36Sopenharmony_ci		if ((mask & AUDIT_PERM_ATTR) &&
17962306a36Sopenharmony_ci		     audit_match_class(AUDIT_CLASS_CHATTR_32, n))
18062306a36Sopenharmony_ci			return 1;
18162306a36Sopenharmony_ci		return 0;
18262306a36Sopenharmony_ci	case AUDITSC_OPEN:
18362306a36Sopenharmony_ci		return mask & ACC_MODE(ctx->argv[1]);
18462306a36Sopenharmony_ci	case AUDITSC_OPENAT:
18562306a36Sopenharmony_ci		return mask & ACC_MODE(ctx->argv[2]);
18662306a36Sopenharmony_ci	case AUDITSC_SOCKETCALL:
18762306a36Sopenharmony_ci		return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
18862306a36Sopenharmony_ci	case AUDITSC_EXECVE:
18962306a36Sopenharmony_ci		return mask & AUDIT_PERM_EXEC;
19062306a36Sopenharmony_ci	case AUDITSC_OPENAT2:
19162306a36Sopenharmony_ci		return mask & ACC_MODE((u32)ctx->openat2.flags);
19262306a36Sopenharmony_ci	default:
19362306a36Sopenharmony_ci		return 0;
19462306a36Sopenharmony_ci	}
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic int audit_match_filetype(struct audit_context *ctx, int val)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	struct audit_names *n;
20062306a36Sopenharmony_ci	umode_t mode = (umode_t)val;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (unlikely(!ctx))
20362306a36Sopenharmony_ci		return 0;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	list_for_each_entry(n, &ctx->names_list, list) {
20662306a36Sopenharmony_ci		if ((n->ino != AUDIT_INO_UNSET) &&
20762306a36Sopenharmony_ci		    ((n->mode & S_IFMT) == mode))
20862306a36Sopenharmony_ci			return 1;
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	return 0;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci/*
21562306a36Sopenharmony_ci * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
21662306a36Sopenharmony_ci * ->first_trees points to its beginning, ->trees - to the current end of data.
21762306a36Sopenharmony_ci * ->tree_count is the number of free entries in array pointed to by ->trees.
21862306a36Sopenharmony_ci * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL,
21962306a36Sopenharmony_ci * "empty" becomes (p, p, 31) afterwards.  We don't shrink the list (and seriously,
22062306a36Sopenharmony_ci * it's going to remain 1-element for almost any setup) until we free context itself.
22162306a36Sopenharmony_ci * References in it _are_ dropped - at the same time we free/drop aux stuff.
22262306a36Sopenharmony_ci */
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic void audit_set_auditable(struct audit_context *ctx)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	if (!ctx->prio) {
22762306a36Sopenharmony_ci		ctx->prio = 1;
22862306a36Sopenharmony_ci		ctx->current_state = AUDIT_STATE_RECORD;
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
23362306a36Sopenharmony_ci{
23462306a36Sopenharmony_ci	struct audit_tree_refs *p = ctx->trees;
23562306a36Sopenharmony_ci	int left = ctx->tree_count;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	if (likely(left)) {
23862306a36Sopenharmony_ci		p->c[--left] = chunk;
23962306a36Sopenharmony_ci		ctx->tree_count = left;
24062306a36Sopenharmony_ci		return 1;
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci	if (!p)
24362306a36Sopenharmony_ci		return 0;
24462306a36Sopenharmony_ci	p = p->next;
24562306a36Sopenharmony_ci	if (p) {
24662306a36Sopenharmony_ci		p->c[30] = chunk;
24762306a36Sopenharmony_ci		ctx->trees = p;
24862306a36Sopenharmony_ci		ctx->tree_count = 30;
24962306a36Sopenharmony_ci		return 1;
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci	return 0;
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic int grow_tree_refs(struct audit_context *ctx)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	struct audit_tree_refs *p = ctx->trees;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
25962306a36Sopenharmony_ci	if (!ctx->trees) {
26062306a36Sopenharmony_ci		ctx->trees = p;
26162306a36Sopenharmony_ci		return 0;
26262306a36Sopenharmony_ci	}
26362306a36Sopenharmony_ci	if (p)
26462306a36Sopenharmony_ci		p->next = ctx->trees;
26562306a36Sopenharmony_ci	else
26662306a36Sopenharmony_ci		ctx->first_trees = ctx->trees;
26762306a36Sopenharmony_ci	ctx->tree_count = 31;
26862306a36Sopenharmony_ci	return 1;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic void unroll_tree_refs(struct audit_context *ctx,
27262306a36Sopenharmony_ci		      struct audit_tree_refs *p, int count)
27362306a36Sopenharmony_ci{
27462306a36Sopenharmony_ci	struct audit_tree_refs *q;
27562306a36Sopenharmony_ci	int n;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	if (!p) {
27862306a36Sopenharmony_ci		/* we started with empty chain */
27962306a36Sopenharmony_ci		p = ctx->first_trees;
28062306a36Sopenharmony_ci		count = 31;
28162306a36Sopenharmony_ci		/* if the very first allocation has failed, nothing to do */
28262306a36Sopenharmony_ci		if (!p)
28362306a36Sopenharmony_ci			return;
28462306a36Sopenharmony_ci	}
28562306a36Sopenharmony_ci	n = count;
28662306a36Sopenharmony_ci	for (q = p; q != ctx->trees; q = q->next, n = 31) {
28762306a36Sopenharmony_ci		while (n--) {
28862306a36Sopenharmony_ci			audit_put_chunk(q->c[n]);
28962306a36Sopenharmony_ci			q->c[n] = NULL;
29062306a36Sopenharmony_ci		}
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci	while (n-- > ctx->tree_count) {
29362306a36Sopenharmony_ci		audit_put_chunk(q->c[n]);
29462306a36Sopenharmony_ci		q->c[n] = NULL;
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci	ctx->trees = p;
29762306a36Sopenharmony_ci	ctx->tree_count = count;
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic void free_tree_refs(struct audit_context *ctx)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	struct audit_tree_refs *p, *q;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	for (p = ctx->first_trees; p; p = q) {
30562306a36Sopenharmony_ci		q = p->next;
30662306a36Sopenharmony_ci		kfree(p);
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
31162306a36Sopenharmony_ci{
31262306a36Sopenharmony_ci	struct audit_tree_refs *p;
31362306a36Sopenharmony_ci	int n;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	if (!tree)
31662306a36Sopenharmony_ci		return 0;
31762306a36Sopenharmony_ci	/* full ones */
31862306a36Sopenharmony_ci	for (p = ctx->first_trees; p != ctx->trees; p = p->next) {
31962306a36Sopenharmony_ci		for (n = 0; n < 31; n++)
32062306a36Sopenharmony_ci			if (audit_tree_match(p->c[n], tree))
32162306a36Sopenharmony_ci				return 1;
32262306a36Sopenharmony_ci	}
32362306a36Sopenharmony_ci	/* partial */
32462306a36Sopenharmony_ci	if (p) {
32562306a36Sopenharmony_ci		for (n = ctx->tree_count; n < 31; n++)
32662306a36Sopenharmony_ci			if (audit_tree_match(p->c[n], tree))
32762306a36Sopenharmony_ci				return 1;
32862306a36Sopenharmony_ci	}
32962306a36Sopenharmony_ci	return 0;
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistatic int audit_compare_uid(kuid_t uid,
33362306a36Sopenharmony_ci			     struct audit_names *name,
33462306a36Sopenharmony_ci			     struct audit_field *f,
33562306a36Sopenharmony_ci			     struct audit_context *ctx)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	struct audit_names *n;
33862306a36Sopenharmony_ci	int rc;
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	if (name) {
34162306a36Sopenharmony_ci		rc = audit_uid_comparator(uid, f->op, name->uid);
34262306a36Sopenharmony_ci		if (rc)
34362306a36Sopenharmony_ci			return rc;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	if (ctx) {
34762306a36Sopenharmony_ci		list_for_each_entry(n, &ctx->names_list, list) {
34862306a36Sopenharmony_ci			rc = audit_uid_comparator(uid, f->op, n->uid);
34962306a36Sopenharmony_ci			if (rc)
35062306a36Sopenharmony_ci				return rc;
35162306a36Sopenharmony_ci		}
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci	return 0;
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic int audit_compare_gid(kgid_t gid,
35762306a36Sopenharmony_ci			     struct audit_names *name,
35862306a36Sopenharmony_ci			     struct audit_field *f,
35962306a36Sopenharmony_ci			     struct audit_context *ctx)
36062306a36Sopenharmony_ci{
36162306a36Sopenharmony_ci	struct audit_names *n;
36262306a36Sopenharmony_ci	int rc;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	if (name) {
36562306a36Sopenharmony_ci		rc = audit_gid_comparator(gid, f->op, name->gid);
36662306a36Sopenharmony_ci		if (rc)
36762306a36Sopenharmony_ci			return rc;
36862306a36Sopenharmony_ci	}
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	if (ctx) {
37162306a36Sopenharmony_ci		list_for_each_entry(n, &ctx->names_list, list) {
37262306a36Sopenharmony_ci			rc = audit_gid_comparator(gid, f->op, n->gid);
37362306a36Sopenharmony_ci			if (rc)
37462306a36Sopenharmony_ci				return rc;
37562306a36Sopenharmony_ci		}
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci	return 0;
37862306a36Sopenharmony_ci}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_cistatic int audit_field_compare(struct task_struct *tsk,
38162306a36Sopenharmony_ci			       const struct cred *cred,
38262306a36Sopenharmony_ci			       struct audit_field *f,
38362306a36Sopenharmony_ci			       struct audit_context *ctx,
38462306a36Sopenharmony_ci			       struct audit_names *name)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	switch (f->val) {
38762306a36Sopenharmony_ci	/* process to file object comparisons */
38862306a36Sopenharmony_ci	case AUDIT_COMPARE_UID_TO_OBJ_UID:
38962306a36Sopenharmony_ci		return audit_compare_uid(cred->uid, name, f, ctx);
39062306a36Sopenharmony_ci	case AUDIT_COMPARE_GID_TO_OBJ_GID:
39162306a36Sopenharmony_ci		return audit_compare_gid(cred->gid, name, f, ctx);
39262306a36Sopenharmony_ci	case AUDIT_COMPARE_EUID_TO_OBJ_UID:
39362306a36Sopenharmony_ci		return audit_compare_uid(cred->euid, name, f, ctx);
39462306a36Sopenharmony_ci	case AUDIT_COMPARE_EGID_TO_OBJ_GID:
39562306a36Sopenharmony_ci		return audit_compare_gid(cred->egid, name, f, ctx);
39662306a36Sopenharmony_ci	case AUDIT_COMPARE_AUID_TO_OBJ_UID:
39762306a36Sopenharmony_ci		return audit_compare_uid(audit_get_loginuid(tsk), name, f, ctx);
39862306a36Sopenharmony_ci	case AUDIT_COMPARE_SUID_TO_OBJ_UID:
39962306a36Sopenharmony_ci		return audit_compare_uid(cred->suid, name, f, ctx);
40062306a36Sopenharmony_ci	case AUDIT_COMPARE_SGID_TO_OBJ_GID:
40162306a36Sopenharmony_ci		return audit_compare_gid(cred->sgid, name, f, ctx);
40262306a36Sopenharmony_ci	case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
40362306a36Sopenharmony_ci		return audit_compare_uid(cred->fsuid, name, f, ctx);
40462306a36Sopenharmony_ci	case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
40562306a36Sopenharmony_ci		return audit_compare_gid(cred->fsgid, name, f, ctx);
40662306a36Sopenharmony_ci	/* uid comparisons */
40762306a36Sopenharmony_ci	case AUDIT_COMPARE_UID_TO_AUID:
40862306a36Sopenharmony_ci		return audit_uid_comparator(cred->uid, f->op,
40962306a36Sopenharmony_ci					    audit_get_loginuid(tsk));
41062306a36Sopenharmony_ci	case AUDIT_COMPARE_UID_TO_EUID:
41162306a36Sopenharmony_ci		return audit_uid_comparator(cred->uid, f->op, cred->euid);
41262306a36Sopenharmony_ci	case AUDIT_COMPARE_UID_TO_SUID:
41362306a36Sopenharmony_ci		return audit_uid_comparator(cred->uid, f->op, cred->suid);
41462306a36Sopenharmony_ci	case AUDIT_COMPARE_UID_TO_FSUID:
41562306a36Sopenharmony_ci		return audit_uid_comparator(cred->uid, f->op, cred->fsuid);
41662306a36Sopenharmony_ci	/* auid comparisons */
41762306a36Sopenharmony_ci	case AUDIT_COMPARE_AUID_TO_EUID:
41862306a36Sopenharmony_ci		return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
41962306a36Sopenharmony_ci					    cred->euid);
42062306a36Sopenharmony_ci	case AUDIT_COMPARE_AUID_TO_SUID:
42162306a36Sopenharmony_ci		return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
42262306a36Sopenharmony_ci					    cred->suid);
42362306a36Sopenharmony_ci	case AUDIT_COMPARE_AUID_TO_FSUID:
42462306a36Sopenharmony_ci		return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
42562306a36Sopenharmony_ci					    cred->fsuid);
42662306a36Sopenharmony_ci	/* euid comparisons */
42762306a36Sopenharmony_ci	case AUDIT_COMPARE_EUID_TO_SUID:
42862306a36Sopenharmony_ci		return audit_uid_comparator(cred->euid, f->op, cred->suid);
42962306a36Sopenharmony_ci	case AUDIT_COMPARE_EUID_TO_FSUID:
43062306a36Sopenharmony_ci		return audit_uid_comparator(cred->euid, f->op, cred->fsuid);
43162306a36Sopenharmony_ci	/* suid comparisons */
43262306a36Sopenharmony_ci	case AUDIT_COMPARE_SUID_TO_FSUID:
43362306a36Sopenharmony_ci		return audit_uid_comparator(cred->suid, f->op, cred->fsuid);
43462306a36Sopenharmony_ci	/* gid comparisons */
43562306a36Sopenharmony_ci	case AUDIT_COMPARE_GID_TO_EGID:
43662306a36Sopenharmony_ci		return audit_gid_comparator(cred->gid, f->op, cred->egid);
43762306a36Sopenharmony_ci	case AUDIT_COMPARE_GID_TO_SGID:
43862306a36Sopenharmony_ci		return audit_gid_comparator(cred->gid, f->op, cred->sgid);
43962306a36Sopenharmony_ci	case AUDIT_COMPARE_GID_TO_FSGID:
44062306a36Sopenharmony_ci		return audit_gid_comparator(cred->gid, f->op, cred->fsgid);
44162306a36Sopenharmony_ci	/* egid comparisons */
44262306a36Sopenharmony_ci	case AUDIT_COMPARE_EGID_TO_SGID:
44362306a36Sopenharmony_ci		return audit_gid_comparator(cred->egid, f->op, cred->sgid);
44462306a36Sopenharmony_ci	case AUDIT_COMPARE_EGID_TO_FSGID:
44562306a36Sopenharmony_ci		return audit_gid_comparator(cred->egid, f->op, cred->fsgid);
44662306a36Sopenharmony_ci	/* sgid comparison */
44762306a36Sopenharmony_ci	case AUDIT_COMPARE_SGID_TO_FSGID:
44862306a36Sopenharmony_ci		return audit_gid_comparator(cred->sgid, f->op, cred->fsgid);
44962306a36Sopenharmony_ci	default:
45062306a36Sopenharmony_ci		WARN(1, "Missing AUDIT_COMPARE define.  Report as a bug\n");
45162306a36Sopenharmony_ci		return 0;
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci	return 0;
45462306a36Sopenharmony_ci}
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci/* Determine if any context name data matches a rule's watch data */
45762306a36Sopenharmony_ci/* Compare a task_struct with an audit_rule.  Return 1 on match, 0
45862306a36Sopenharmony_ci * otherwise.
45962306a36Sopenharmony_ci *
46062306a36Sopenharmony_ci * If task_creation is true, this is an explicit indication that we are
46162306a36Sopenharmony_ci * filtering a task rule at task creation time.  This and tsk == current are
46262306a36Sopenharmony_ci * the only situations where tsk->cred may be accessed without an rcu read lock.
46362306a36Sopenharmony_ci */
46462306a36Sopenharmony_cistatic int audit_filter_rules(struct task_struct *tsk,
46562306a36Sopenharmony_ci			      struct audit_krule *rule,
46662306a36Sopenharmony_ci			      struct audit_context *ctx,
46762306a36Sopenharmony_ci			      struct audit_names *name,
46862306a36Sopenharmony_ci			      enum audit_state *state,
46962306a36Sopenharmony_ci			      bool task_creation)
47062306a36Sopenharmony_ci{
47162306a36Sopenharmony_ci	const struct cred *cred;
47262306a36Sopenharmony_ci	int i, need_sid = 1;
47362306a36Sopenharmony_ci	u32 sid;
47462306a36Sopenharmony_ci	unsigned int sessionid;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	if (ctx && rule->prio <= ctx->prio)
47762306a36Sopenharmony_ci		return 0;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	for (i = 0; i < rule->field_count; i++) {
48262306a36Sopenharmony_ci		struct audit_field *f = &rule->fields[i];
48362306a36Sopenharmony_ci		struct audit_names *n;
48462306a36Sopenharmony_ci		int result = 0;
48562306a36Sopenharmony_ci		pid_t pid;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci		switch (f->type) {
48862306a36Sopenharmony_ci		case AUDIT_PID:
48962306a36Sopenharmony_ci			pid = task_tgid_nr(tsk);
49062306a36Sopenharmony_ci			result = audit_comparator(pid, f->op, f->val);
49162306a36Sopenharmony_ci			break;
49262306a36Sopenharmony_ci		case AUDIT_PPID:
49362306a36Sopenharmony_ci			if (ctx) {
49462306a36Sopenharmony_ci				if (!ctx->ppid)
49562306a36Sopenharmony_ci					ctx->ppid = task_ppid_nr(tsk);
49662306a36Sopenharmony_ci				result = audit_comparator(ctx->ppid, f->op, f->val);
49762306a36Sopenharmony_ci			}
49862306a36Sopenharmony_ci			break;
49962306a36Sopenharmony_ci		case AUDIT_EXE:
50062306a36Sopenharmony_ci			result = audit_exe_compare(tsk, rule->exe);
50162306a36Sopenharmony_ci			if (f->op == Audit_not_equal)
50262306a36Sopenharmony_ci				result = !result;
50362306a36Sopenharmony_ci			break;
50462306a36Sopenharmony_ci		case AUDIT_UID:
50562306a36Sopenharmony_ci			result = audit_uid_comparator(cred->uid, f->op, f->uid);
50662306a36Sopenharmony_ci			break;
50762306a36Sopenharmony_ci		case AUDIT_EUID:
50862306a36Sopenharmony_ci			result = audit_uid_comparator(cred->euid, f->op, f->uid);
50962306a36Sopenharmony_ci			break;
51062306a36Sopenharmony_ci		case AUDIT_SUID:
51162306a36Sopenharmony_ci			result = audit_uid_comparator(cred->suid, f->op, f->uid);
51262306a36Sopenharmony_ci			break;
51362306a36Sopenharmony_ci		case AUDIT_FSUID:
51462306a36Sopenharmony_ci			result = audit_uid_comparator(cred->fsuid, f->op, f->uid);
51562306a36Sopenharmony_ci			break;
51662306a36Sopenharmony_ci		case AUDIT_GID:
51762306a36Sopenharmony_ci			result = audit_gid_comparator(cred->gid, f->op, f->gid);
51862306a36Sopenharmony_ci			if (f->op == Audit_equal) {
51962306a36Sopenharmony_ci				if (!result)
52062306a36Sopenharmony_ci					result = groups_search(cred->group_info, f->gid);
52162306a36Sopenharmony_ci			} else if (f->op == Audit_not_equal) {
52262306a36Sopenharmony_ci				if (result)
52362306a36Sopenharmony_ci					result = !groups_search(cred->group_info, f->gid);
52462306a36Sopenharmony_ci			}
52562306a36Sopenharmony_ci			break;
52662306a36Sopenharmony_ci		case AUDIT_EGID:
52762306a36Sopenharmony_ci			result = audit_gid_comparator(cred->egid, f->op, f->gid);
52862306a36Sopenharmony_ci			if (f->op == Audit_equal) {
52962306a36Sopenharmony_ci				if (!result)
53062306a36Sopenharmony_ci					result = groups_search(cred->group_info, f->gid);
53162306a36Sopenharmony_ci			} else if (f->op == Audit_not_equal) {
53262306a36Sopenharmony_ci				if (result)
53362306a36Sopenharmony_ci					result = !groups_search(cred->group_info, f->gid);
53462306a36Sopenharmony_ci			}
53562306a36Sopenharmony_ci			break;
53662306a36Sopenharmony_ci		case AUDIT_SGID:
53762306a36Sopenharmony_ci			result = audit_gid_comparator(cred->sgid, f->op, f->gid);
53862306a36Sopenharmony_ci			break;
53962306a36Sopenharmony_ci		case AUDIT_FSGID:
54062306a36Sopenharmony_ci			result = audit_gid_comparator(cred->fsgid, f->op, f->gid);
54162306a36Sopenharmony_ci			break;
54262306a36Sopenharmony_ci		case AUDIT_SESSIONID:
54362306a36Sopenharmony_ci			sessionid = audit_get_sessionid(tsk);
54462306a36Sopenharmony_ci			result = audit_comparator(sessionid, f->op, f->val);
54562306a36Sopenharmony_ci			break;
54662306a36Sopenharmony_ci		case AUDIT_PERS:
54762306a36Sopenharmony_ci			result = audit_comparator(tsk->personality, f->op, f->val);
54862306a36Sopenharmony_ci			break;
54962306a36Sopenharmony_ci		case AUDIT_ARCH:
55062306a36Sopenharmony_ci			if (ctx)
55162306a36Sopenharmony_ci				result = audit_comparator(ctx->arch, f->op, f->val);
55262306a36Sopenharmony_ci			break;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci		case AUDIT_EXIT:
55562306a36Sopenharmony_ci			if (ctx && ctx->return_valid != AUDITSC_INVALID)
55662306a36Sopenharmony_ci				result = audit_comparator(ctx->return_code, f->op, f->val);
55762306a36Sopenharmony_ci			break;
55862306a36Sopenharmony_ci		case AUDIT_SUCCESS:
55962306a36Sopenharmony_ci			if (ctx && ctx->return_valid != AUDITSC_INVALID) {
56062306a36Sopenharmony_ci				if (f->val)
56162306a36Sopenharmony_ci					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
56262306a36Sopenharmony_ci				else
56362306a36Sopenharmony_ci					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
56462306a36Sopenharmony_ci			}
56562306a36Sopenharmony_ci			break;
56662306a36Sopenharmony_ci		case AUDIT_DEVMAJOR:
56762306a36Sopenharmony_ci			if (name) {
56862306a36Sopenharmony_ci				if (audit_comparator(MAJOR(name->dev), f->op, f->val) ||
56962306a36Sopenharmony_ci				    audit_comparator(MAJOR(name->rdev), f->op, f->val))
57062306a36Sopenharmony_ci					++result;
57162306a36Sopenharmony_ci			} else if (ctx) {
57262306a36Sopenharmony_ci				list_for_each_entry(n, &ctx->names_list, list) {
57362306a36Sopenharmony_ci					if (audit_comparator(MAJOR(n->dev), f->op, f->val) ||
57462306a36Sopenharmony_ci					    audit_comparator(MAJOR(n->rdev), f->op, f->val)) {
57562306a36Sopenharmony_ci						++result;
57662306a36Sopenharmony_ci						break;
57762306a36Sopenharmony_ci					}
57862306a36Sopenharmony_ci				}
57962306a36Sopenharmony_ci			}
58062306a36Sopenharmony_ci			break;
58162306a36Sopenharmony_ci		case AUDIT_DEVMINOR:
58262306a36Sopenharmony_ci			if (name) {
58362306a36Sopenharmony_ci				if (audit_comparator(MINOR(name->dev), f->op, f->val) ||
58462306a36Sopenharmony_ci				    audit_comparator(MINOR(name->rdev), f->op, f->val))
58562306a36Sopenharmony_ci					++result;
58662306a36Sopenharmony_ci			} else if (ctx) {
58762306a36Sopenharmony_ci				list_for_each_entry(n, &ctx->names_list, list) {
58862306a36Sopenharmony_ci					if (audit_comparator(MINOR(n->dev), f->op, f->val) ||
58962306a36Sopenharmony_ci					    audit_comparator(MINOR(n->rdev), f->op, f->val)) {
59062306a36Sopenharmony_ci						++result;
59162306a36Sopenharmony_ci						break;
59262306a36Sopenharmony_ci					}
59362306a36Sopenharmony_ci				}
59462306a36Sopenharmony_ci			}
59562306a36Sopenharmony_ci			break;
59662306a36Sopenharmony_ci		case AUDIT_INODE:
59762306a36Sopenharmony_ci			if (name)
59862306a36Sopenharmony_ci				result = audit_comparator(name->ino, f->op, f->val);
59962306a36Sopenharmony_ci			else if (ctx) {
60062306a36Sopenharmony_ci				list_for_each_entry(n, &ctx->names_list, list) {
60162306a36Sopenharmony_ci					if (audit_comparator(n->ino, f->op, f->val)) {
60262306a36Sopenharmony_ci						++result;
60362306a36Sopenharmony_ci						break;
60462306a36Sopenharmony_ci					}
60562306a36Sopenharmony_ci				}
60662306a36Sopenharmony_ci			}
60762306a36Sopenharmony_ci			break;
60862306a36Sopenharmony_ci		case AUDIT_OBJ_UID:
60962306a36Sopenharmony_ci			if (name) {
61062306a36Sopenharmony_ci				result = audit_uid_comparator(name->uid, f->op, f->uid);
61162306a36Sopenharmony_ci			} else if (ctx) {
61262306a36Sopenharmony_ci				list_for_each_entry(n, &ctx->names_list, list) {
61362306a36Sopenharmony_ci					if (audit_uid_comparator(n->uid, f->op, f->uid)) {
61462306a36Sopenharmony_ci						++result;
61562306a36Sopenharmony_ci						break;
61662306a36Sopenharmony_ci					}
61762306a36Sopenharmony_ci				}
61862306a36Sopenharmony_ci			}
61962306a36Sopenharmony_ci			break;
62062306a36Sopenharmony_ci		case AUDIT_OBJ_GID:
62162306a36Sopenharmony_ci			if (name) {
62262306a36Sopenharmony_ci				result = audit_gid_comparator(name->gid, f->op, f->gid);
62362306a36Sopenharmony_ci			} else if (ctx) {
62462306a36Sopenharmony_ci				list_for_each_entry(n, &ctx->names_list, list) {
62562306a36Sopenharmony_ci					if (audit_gid_comparator(n->gid, f->op, f->gid)) {
62662306a36Sopenharmony_ci						++result;
62762306a36Sopenharmony_ci						break;
62862306a36Sopenharmony_ci					}
62962306a36Sopenharmony_ci				}
63062306a36Sopenharmony_ci			}
63162306a36Sopenharmony_ci			break;
63262306a36Sopenharmony_ci		case AUDIT_WATCH:
63362306a36Sopenharmony_ci			if (name) {
63462306a36Sopenharmony_ci				result = audit_watch_compare(rule->watch,
63562306a36Sopenharmony_ci							     name->ino,
63662306a36Sopenharmony_ci							     name->dev);
63762306a36Sopenharmony_ci				if (f->op == Audit_not_equal)
63862306a36Sopenharmony_ci					result = !result;
63962306a36Sopenharmony_ci			}
64062306a36Sopenharmony_ci			break;
64162306a36Sopenharmony_ci		case AUDIT_DIR:
64262306a36Sopenharmony_ci			if (ctx) {
64362306a36Sopenharmony_ci				result = match_tree_refs(ctx, rule->tree);
64462306a36Sopenharmony_ci				if (f->op == Audit_not_equal)
64562306a36Sopenharmony_ci					result = !result;
64662306a36Sopenharmony_ci			}
64762306a36Sopenharmony_ci			break;
64862306a36Sopenharmony_ci		case AUDIT_LOGINUID:
64962306a36Sopenharmony_ci			result = audit_uid_comparator(audit_get_loginuid(tsk),
65062306a36Sopenharmony_ci						      f->op, f->uid);
65162306a36Sopenharmony_ci			break;
65262306a36Sopenharmony_ci		case AUDIT_LOGINUID_SET:
65362306a36Sopenharmony_ci			result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
65462306a36Sopenharmony_ci			break;
65562306a36Sopenharmony_ci		case AUDIT_SADDR_FAM:
65662306a36Sopenharmony_ci			if (ctx && ctx->sockaddr)
65762306a36Sopenharmony_ci				result = audit_comparator(ctx->sockaddr->ss_family,
65862306a36Sopenharmony_ci							  f->op, f->val);
65962306a36Sopenharmony_ci			break;
66062306a36Sopenharmony_ci		case AUDIT_SUBJ_USER:
66162306a36Sopenharmony_ci		case AUDIT_SUBJ_ROLE:
66262306a36Sopenharmony_ci		case AUDIT_SUBJ_TYPE:
66362306a36Sopenharmony_ci		case AUDIT_SUBJ_SEN:
66462306a36Sopenharmony_ci		case AUDIT_SUBJ_CLR:
66562306a36Sopenharmony_ci			/* NOTE: this may return negative values indicating
66662306a36Sopenharmony_ci			   a temporary error.  We simply treat this as a
66762306a36Sopenharmony_ci			   match for now to avoid losing information that
66862306a36Sopenharmony_ci			   may be wanted.   An error message will also be
66962306a36Sopenharmony_ci			   logged upon error */
67062306a36Sopenharmony_ci			if (f->lsm_rule) {
67162306a36Sopenharmony_ci				if (need_sid) {
67262306a36Sopenharmony_ci					/* @tsk should always be equal to
67362306a36Sopenharmony_ci					 * @current with the exception of
67462306a36Sopenharmony_ci					 * fork()/copy_process() in which case
67562306a36Sopenharmony_ci					 * the new @tsk creds are still a dup
67662306a36Sopenharmony_ci					 * of @current's creds so we can still
67762306a36Sopenharmony_ci					 * use security_current_getsecid_subj()
67862306a36Sopenharmony_ci					 * here even though it always refs
67962306a36Sopenharmony_ci					 * @current's creds
68062306a36Sopenharmony_ci					 */
68162306a36Sopenharmony_ci					security_current_getsecid_subj(&sid);
68262306a36Sopenharmony_ci					need_sid = 0;
68362306a36Sopenharmony_ci				}
68462306a36Sopenharmony_ci				result = security_audit_rule_match(sid, f->type,
68562306a36Sopenharmony_ci								   f->op,
68662306a36Sopenharmony_ci								   f->lsm_rule);
68762306a36Sopenharmony_ci			}
68862306a36Sopenharmony_ci			break;
68962306a36Sopenharmony_ci		case AUDIT_OBJ_USER:
69062306a36Sopenharmony_ci		case AUDIT_OBJ_ROLE:
69162306a36Sopenharmony_ci		case AUDIT_OBJ_TYPE:
69262306a36Sopenharmony_ci		case AUDIT_OBJ_LEV_LOW:
69362306a36Sopenharmony_ci		case AUDIT_OBJ_LEV_HIGH:
69462306a36Sopenharmony_ci			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
69562306a36Sopenharmony_ci			   also applies here */
69662306a36Sopenharmony_ci			if (f->lsm_rule) {
69762306a36Sopenharmony_ci				/* Find files that match */
69862306a36Sopenharmony_ci				if (name) {
69962306a36Sopenharmony_ci					result = security_audit_rule_match(
70062306a36Sopenharmony_ci								name->osid,
70162306a36Sopenharmony_ci								f->type,
70262306a36Sopenharmony_ci								f->op,
70362306a36Sopenharmony_ci								f->lsm_rule);
70462306a36Sopenharmony_ci				} else if (ctx) {
70562306a36Sopenharmony_ci					list_for_each_entry(n, &ctx->names_list, list) {
70662306a36Sopenharmony_ci						if (security_audit_rule_match(
70762306a36Sopenharmony_ci								n->osid,
70862306a36Sopenharmony_ci								f->type,
70962306a36Sopenharmony_ci								f->op,
71062306a36Sopenharmony_ci								f->lsm_rule)) {
71162306a36Sopenharmony_ci							++result;
71262306a36Sopenharmony_ci							break;
71362306a36Sopenharmony_ci						}
71462306a36Sopenharmony_ci					}
71562306a36Sopenharmony_ci				}
71662306a36Sopenharmony_ci				/* Find ipc objects that match */
71762306a36Sopenharmony_ci				if (!ctx || ctx->type != AUDIT_IPC)
71862306a36Sopenharmony_ci					break;
71962306a36Sopenharmony_ci				if (security_audit_rule_match(ctx->ipc.osid,
72062306a36Sopenharmony_ci							      f->type, f->op,
72162306a36Sopenharmony_ci							      f->lsm_rule))
72262306a36Sopenharmony_ci					++result;
72362306a36Sopenharmony_ci			}
72462306a36Sopenharmony_ci			break;
72562306a36Sopenharmony_ci		case AUDIT_ARG0:
72662306a36Sopenharmony_ci		case AUDIT_ARG1:
72762306a36Sopenharmony_ci		case AUDIT_ARG2:
72862306a36Sopenharmony_ci		case AUDIT_ARG3:
72962306a36Sopenharmony_ci			if (ctx)
73062306a36Sopenharmony_ci				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
73162306a36Sopenharmony_ci			break;
73262306a36Sopenharmony_ci		case AUDIT_FILTERKEY:
73362306a36Sopenharmony_ci			/* ignore this field for filtering */
73462306a36Sopenharmony_ci			result = 1;
73562306a36Sopenharmony_ci			break;
73662306a36Sopenharmony_ci		case AUDIT_PERM:
73762306a36Sopenharmony_ci			result = audit_match_perm(ctx, f->val);
73862306a36Sopenharmony_ci			if (f->op == Audit_not_equal)
73962306a36Sopenharmony_ci				result = !result;
74062306a36Sopenharmony_ci			break;
74162306a36Sopenharmony_ci		case AUDIT_FILETYPE:
74262306a36Sopenharmony_ci			result = audit_match_filetype(ctx, f->val);
74362306a36Sopenharmony_ci			if (f->op == Audit_not_equal)
74462306a36Sopenharmony_ci				result = !result;
74562306a36Sopenharmony_ci			break;
74662306a36Sopenharmony_ci		case AUDIT_FIELD_COMPARE:
74762306a36Sopenharmony_ci			result = audit_field_compare(tsk, cred, f, ctx, name);
74862306a36Sopenharmony_ci			break;
74962306a36Sopenharmony_ci		}
75062306a36Sopenharmony_ci		if (!result)
75162306a36Sopenharmony_ci			return 0;
75262306a36Sopenharmony_ci	}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	if (ctx) {
75562306a36Sopenharmony_ci		if (rule->filterkey) {
75662306a36Sopenharmony_ci			kfree(ctx->filterkey);
75762306a36Sopenharmony_ci			ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
75862306a36Sopenharmony_ci		}
75962306a36Sopenharmony_ci		ctx->prio = rule->prio;
76062306a36Sopenharmony_ci	}
76162306a36Sopenharmony_ci	switch (rule->action) {
76262306a36Sopenharmony_ci	case AUDIT_NEVER:
76362306a36Sopenharmony_ci		*state = AUDIT_STATE_DISABLED;
76462306a36Sopenharmony_ci		break;
76562306a36Sopenharmony_ci	case AUDIT_ALWAYS:
76662306a36Sopenharmony_ci		*state = AUDIT_STATE_RECORD;
76762306a36Sopenharmony_ci		break;
76862306a36Sopenharmony_ci	}
76962306a36Sopenharmony_ci	return 1;
77062306a36Sopenharmony_ci}
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci/* At process creation time, we can determine if system-call auditing is
77362306a36Sopenharmony_ci * completely disabled for this task.  Since we only have the task
77462306a36Sopenharmony_ci * structure at this point, we can only check uid and gid.
77562306a36Sopenharmony_ci */
77662306a36Sopenharmony_cistatic enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	struct audit_entry *e;
77962306a36Sopenharmony_ci	enum audit_state   state;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	rcu_read_lock();
78262306a36Sopenharmony_ci	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
78362306a36Sopenharmony_ci		if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
78462306a36Sopenharmony_ci				       &state, true)) {
78562306a36Sopenharmony_ci			if (state == AUDIT_STATE_RECORD)
78662306a36Sopenharmony_ci				*key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
78762306a36Sopenharmony_ci			rcu_read_unlock();
78862306a36Sopenharmony_ci			return state;
78962306a36Sopenharmony_ci		}
79062306a36Sopenharmony_ci	}
79162306a36Sopenharmony_ci	rcu_read_unlock();
79262306a36Sopenharmony_ci	return AUDIT_STATE_BUILD;
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_cistatic int audit_in_mask(const struct audit_krule *rule, unsigned long val)
79662306a36Sopenharmony_ci{
79762306a36Sopenharmony_ci	int word, bit;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	if (val > 0xffffffff)
80062306a36Sopenharmony_ci		return false;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	word = AUDIT_WORD(val);
80362306a36Sopenharmony_ci	if (word >= AUDIT_BITMASK_SIZE)
80462306a36Sopenharmony_ci		return false;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	bit = AUDIT_BIT(val);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	return rule->mask[word] & bit;
80962306a36Sopenharmony_ci}
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci/**
81262306a36Sopenharmony_ci * __audit_filter_op - common filter helper for operations (syscall/uring/etc)
81362306a36Sopenharmony_ci * @tsk: associated task
81462306a36Sopenharmony_ci * @ctx: audit context
81562306a36Sopenharmony_ci * @list: audit filter list
81662306a36Sopenharmony_ci * @name: audit_name (can be NULL)
81762306a36Sopenharmony_ci * @op: current syscall/uring_op
81862306a36Sopenharmony_ci *
81962306a36Sopenharmony_ci * Run the udit filters specified in @list against @tsk using @ctx,
82062306a36Sopenharmony_ci * @name, and @op, as necessary; the caller is responsible for ensuring
82162306a36Sopenharmony_ci * that the call is made while the RCU read lock is held. The @name
82262306a36Sopenharmony_ci * parameter can be NULL, but all others must be specified.
82362306a36Sopenharmony_ci * Returns 1/true if the filter finds a match, 0/false if none are found.
82462306a36Sopenharmony_ci */
82562306a36Sopenharmony_cistatic int __audit_filter_op(struct task_struct *tsk,
82662306a36Sopenharmony_ci			   struct audit_context *ctx,
82762306a36Sopenharmony_ci			   struct list_head *list,
82862306a36Sopenharmony_ci			   struct audit_names *name,
82962306a36Sopenharmony_ci			   unsigned long op)
83062306a36Sopenharmony_ci{
83162306a36Sopenharmony_ci	struct audit_entry *e;
83262306a36Sopenharmony_ci	enum audit_state state;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	list_for_each_entry_rcu(e, list, list) {
83562306a36Sopenharmony_ci		if (audit_in_mask(&e->rule, op) &&
83662306a36Sopenharmony_ci		    audit_filter_rules(tsk, &e->rule, ctx, name,
83762306a36Sopenharmony_ci				       &state, false)) {
83862306a36Sopenharmony_ci			ctx->current_state = state;
83962306a36Sopenharmony_ci			return 1;
84062306a36Sopenharmony_ci		}
84162306a36Sopenharmony_ci	}
84262306a36Sopenharmony_ci	return 0;
84362306a36Sopenharmony_ci}
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci/**
84662306a36Sopenharmony_ci * audit_filter_uring - apply filters to an io_uring operation
84762306a36Sopenharmony_ci * @tsk: associated task
84862306a36Sopenharmony_ci * @ctx: audit context
84962306a36Sopenharmony_ci */
85062306a36Sopenharmony_cistatic void audit_filter_uring(struct task_struct *tsk,
85162306a36Sopenharmony_ci			       struct audit_context *ctx)
85262306a36Sopenharmony_ci{
85362306a36Sopenharmony_ci	if (auditd_test_task(tsk))
85462306a36Sopenharmony_ci		return;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	rcu_read_lock();
85762306a36Sopenharmony_ci	__audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_URING_EXIT],
85862306a36Sopenharmony_ci			NULL, ctx->uring_op);
85962306a36Sopenharmony_ci	rcu_read_unlock();
86062306a36Sopenharmony_ci}
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci/* At syscall exit time, this filter is called if the audit_state is
86362306a36Sopenharmony_ci * not low enough that auditing cannot take place, but is also not
86462306a36Sopenharmony_ci * high enough that we already know we have to write an audit record
86562306a36Sopenharmony_ci * (i.e., the state is AUDIT_STATE_BUILD).
86662306a36Sopenharmony_ci */
86762306a36Sopenharmony_cistatic void audit_filter_syscall(struct task_struct *tsk,
86862306a36Sopenharmony_ci				 struct audit_context *ctx)
86962306a36Sopenharmony_ci{
87062306a36Sopenharmony_ci	if (auditd_test_task(tsk))
87162306a36Sopenharmony_ci		return;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	rcu_read_lock();
87462306a36Sopenharmony_ci	__audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_EXIT],
87562306a36Sopenharmony_ci			NULL, ctx->major);
87662306a36Sopenharmony_ci	rcu_read_unlock();
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci/*
88062306a36Sopenharmony_ci * Given an audit_name check the inode hash table to see if they match.
88162306a36Sopenharmony_ci * Called holding the rcu read lock to protect the use of audit_inode_hash
88262306a36Sopenharmony_ci */
88362306a36Sopenharmony_cistatic int audit_filter_inode_name(struct task_struct *tsk,
88462306a36Sopenharmony_ci				   struct audit_names *n,
88562306a36Sopenharmony_ci				   struct audit_context *ctx)
88662306a36Sopenharmony_ci{
88762306a36Sopenharmony_ci	int h = audit_hash_ino((u32)n->ino);
88862306a36Sopenharmony_ci	struct list_head *list = &audit_inode_hash[h];
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	return __audit_filter_op(tsk, ctx, list, n, ctx->major);
89162306a36Sopenharmony_ci}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci/* At syscall exit time, this filter is called if any audit_names have been
89462306a36Sopenharmony_ci * collected during syscall processing.  We only check rules in sublists at hash
89562306a36Sopenharmony_ci * buckets applicable to the inode numbers in audit_names.
89662306a36Sopenharmony_ci * Regarding audit_state, same rules apply as for audit_filter_syscall().
89762306a36Sopenharmony_ci */
89862306a36Sopenharmony_civoid audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	struct audit_names *n;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	if (auditd_test_task(tsk))
90362306a36Sopenharmony_ci		return;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	rcu_read_lock();
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	list_for_each_entry(n, &ctx->names_list, list) {
90862306a36Sopenharmony_ci		if (audit_filter_inode_name(tsk, n, ctx))
90962306a36Sopenharmony_ci			break;
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci	rcu_read_unlock();
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_cistatic inline void audit_proctitle_free(struct audit_context *context)
91562306a36Sopenharmony_ci{
91662306a36Sopenharmony_ci	kfree(context->proctitle.value);
91762306a36Sopenharmony_ci	context->proctitle.value = NULL;
91862306a36Sopenharmony_ci	context->proctitle.len = 0;
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_cistatic inline void audit_free_module(struct audit_context *context)
92262306a36Sopenharmony_ci{
92362306a36Sopenharmony_ci	if (context->type == AUDIT_KERN_MODULE) {
92462306a36Sopenharmony_ci		kfree(context->module.name);
92562306a36Sopenharmony_ci		context->module.name = NULL;
92662306a36Sopenharmony_ci	}
92762306a36Sopenharmony_ci}
92862306a36Sopenharmony_cistatic inline void audit_free_names(struct audit_context *context)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	struct audit_names *n, *next;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	list_for_each_entry_safe(n, next, &context->names_list, list) {
93362306a36Sopenharmony_ci		list_del(&n->list);
93462306a36Sopenharmony_ci		if (n->name)
93562306a36Sopenharmony_ci			putname(n->name);
93662306a36Sopenharmony_ci		if (n->should_free)
93762306a36Sopenharmony_ci			kfree(n);
93862306a36Sopenharmony_ci	}
93962306a36Sopenharmony_ci	context->name_count = 0;
94062306a36Sopenharmony_ci	path_put(&context->pwd);
94162306a36Sopenharmony_ci	context->pwd.dentry = NULL;
94262306a36Sopenharmony_ci	context->pwd.mnt = NULL;
94362306a36Sopenharmony_ci}
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_cistatic inline void audit_free_aux(struct audit_context *context)
94662306a36Sopenharmony_ci{
94762306a36Sopenharmony_ci	struct audit_aux_data *aux;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	while ((aux = context->aux)) {
95062306a36Sopenharmony_ci		context->aux = aux->next;
95162306a36Sopenharmony_ci		kfree(aux);
95262306a36Sopenharmony_ci	}
95362306a36Sopenharmony_ci	context->aux = NULL;
95462306a36Sopenharmony_ci	while ((aux = context->aux_pids)) {
95562306a36Sopenharmony_ci		context->aux_pids = aux->next;
95662306a36Sopenharmony_ci		kfree(aux);
95762306a36Sopenharmony_ci	}
95862306a36Sopenharmony_ci	context->aux_pids = NULL;
95962306a36Sopenharmony_ci}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci/**
96262306a36Sopenharmony_ci * audit_reset_context - reset a audit_context structure
96362306a36Sopenharmony_ci * @ctx: the audit_context to reset
96462306a36Sopenharmony_ci *
96562306a36Sopenharmony_ci * All fields in the audit_context will be reset to an initial state, all
96662306a36Sopenharmony_ci * references held by fields will be dropped, and private memory will be
96762306a36Sopenharmony_ci * released.  When this function returns the audit_context will be suitable
96862306a36Sopenharmony_ci * for reuse, so long as the passed context is not NULL or a dummy context.
96962306a36Sopenharmony_ci */
97062306a36Sopenharmony_cistatic void audit_reset_context(struct audit_context *ctx)
97162306a36Sopenharmony_ci{
97262306a36Sopenharmony_ci	if (!ctx)
97362306a36Sopenharmony_ci		return;
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	/* if ctx is non-null, reset the "ctx->context" regardless */
97662306a36Sopenharmony_ci	ctx->context = AUDIT_CTX_UNUSED;
97762306a36Sopenharmony_ci	if (ctx->dummy)
97862306a36Sopenharmony_ci		return;
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	/*
98162306a36Sopenharmony_ci	 * NOTE: It shouldn't matter in what order we release the fields, so
98262306a36Sopenharmony_ci	 *       release them in the order in which they appear in the struct;
98362306a36Sopenharmony_ci	 *       this gives us some hope of quickly making sure we are
98462306a36Sopenharmony_ci	 *       resetting the audit_context properly.
98562306a36Sopenharmony_ci	 *
98662306a36Sopenharmony_ci	 *       Other things worth mentioning:
98762306a36Sopenharmony_ci	 *       - we don't reset "dummy"
98862306a36Sopenharmony_ci	 *       - we don't reset "state", we do reset "current_state"
98962306a36Sopenharmony_ci	 *       - we preserve "filterkey" if "state" is AUDIT_STATE_RECORD
99062306a36Sopenharmony_ci	 *       - much of this is likely overkill, but play it safe for now
99162306a36Sopenharmony_ci	 *       - we really need to work on improving the audit_context struct
99262306a36Sopenharmony_ci	 */
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	ctx->current_state = ctx->state;
99562306a36Sopenharmony_ci	ctx->serial = 0;
99662306a36Sopenharmony_ci	ctx->major = 0;
99762306a36Sopenharmony_ci	ctx->uring_op = 0;
99862306a36Sopenharmony_ci	ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
99962306a36Sopenharmony_ci	memset(ctx->argv, 0, sizeof(ctx->argv));
100062306a36Sopenharmony_ci	ctx->return_code = 0;
100162306a36Sopenharmony_ci	ctx->prio = (ctx->state == AUDIT_STATE_RECORD ? ~0ULL : 0);
100262306a36Sopenharmony_ci	ctx->return_valid = AUDITSC_INVALID;
100362306a36Sopenharmony_ci	audit_free_names(ctx);
100462306a36Sopenharmony_ci	if (ctx->state != AUDIT_STATE_RECORD) {
100562306a36Sopenharmony_ci		kfree(ctx->filterkey);
100662306a36Sopenharmony_ci		ctx->filterkey = NULL;
100762306a36Sopenharmony_ci	}
100862306a36Sopenharmony_ci	audit_free_aux(ctx);
100962306a36Sopenharmony_ci	kfree(ctx->sockaddr);
101062306a36Sopenharmony_ci	ctx->sockaddr = NULL;
101162306a36Sopenharmony_ci	ctx->sockaddr_len = 0;
101262306a36Sopenharmony_ci	ctx->ppid = 0;
101362306a36Sopenharmony_ci	ctx->uid = ctx->euid = ctx->suid = ctx->fsuid = KUIDT_INIT(0);
101462306a36Sopenharmony_ci	ctx->gid = ctx->egid = ctx->sgid = ctx->fsgid = KGIDT_INIT(0);
101562306a36Sopenharmony_ci	ctx->personality = 0;
101662306a36Sopenharmony_ci	ctx->arch = 0;
101762306a36Sopenharmony_ci	ctx->target_pid = 0;
101862306a36Sopenharmony_ci	ctx->target_auid = ctx->target_uid = KUIDT_INIT(0);
101962306a36Sopenharmony_ci	ctx->target_sessionid = 0;
102062306a36Sopenharmony_ci	ctx->target_sid = 0;
102162306a36Sopenharmony_ci	ctx->target_comm[0] = '\0';
102262306a36Sopenharmony_ci	unroll_tree_refs(ctx, NULL, 0);
102362306a36Sopenharmony_ci	WARN_ON(!list_empty(&ctx->killed_trees));
102462306a36Sopenharmony_ci	audit_free_module(ctx);
102562306a36Sopenharmony_ci	ctx->fds[0] = -1;
102662306a36Sopenharmony_ci	ctx->type = 0; /* reset last for audit_free_*() */
102762306a36Sopenharmony_ci}
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_cistatic inline struct audit_context *audit_alloc_context(enum audit_state state)
103062306a36Sopenharmony_ci{
103162306a36Sopenharmony_ci	struct audit_context *context;
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	context = kzalloc(sizeof(*context), GFP_KERNEL);
103462306a36Sopenharmony_ci	if (!context)
103562306a36Sopenharmony_ci		return NULL;
103662306a36Sopenharmony_ci	context->context = AUDIT_CTX_UNUSED;
103762306a36Sopenharmony_ci	context->state = state;
103862306a36Sopenharmony_ci	context->prio = state == AUDIT_STATE_RECORD ? ~0ULL : 0;
103962306a36Sopenharmony_ci	INIT_LIST_HEAD(&context->killed_trees);
104062306a36Sopenharmony_ci	INIT_LIST_HEAD(&context->names_list);
104162306a36Sopenharmony_ci	context->fds[0] = -1;
104262306a36Sopenharmony_ci	context->return_valid = AUDITSC_INVALID;
104362306a36Sopenharmony_ci	return context;
104462306a36Sopenharmony_ci}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci/**
104762306a36Sopenharmony_ci * audit_alloc - allocate an audit context block for a task
104862306a36Sopenharmony_ci * @tsk: task
104962306a36Sopenharmony_ci *
105062306a36Sopenharmony_ci * Filter on the task information and allocate a per-task audit context
105162306a36Sopenharmony_ci * if necessary.  Doing so turns on system call auditing for the
105262306a36Sopenharmony_ci * specified task.  This is called from copy_process, so no lock is
105362306a36Sopenharmony_ci * needed.
105462306a36Sopenharmony_ci */
105562306a36Sopenharmony_ciint audit_alloc(struct task_struct *tsk)
105662306a36Sopenharmony_ci{
105762306a36Sopenharmony_ci	struct audit_context *context;
105862306a36Sopenharmony_ci	enum audit_state     state;
105962306a36Sopenharmony_ci	char *key = NULL;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	if (likely(!audit_ever_enabled))
106262306a36Sopenharmony_ci		return 0;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	state = audit_filter_task(tsk, &key);
106562306a36Sopenharmony_ci	if (state == AUDIT_STATE_DISABLED) {
106662306a36Sopenharmony_ci		clear_task_syscall_work(tsk, SYSCALL_AUDIT);
106762306a36Sopenharmony_ci		return 0;
106862306a36Sopenharmony_ci	}
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	context = audit_alloc_context(state);
107162306a36Sopenharmony_ci	if (!context) {
107262306a36Sopenharmony_ci		kfree(key);
107362306a36Sopenharmony_ci		audit_log_lost("out of memory in audit_alloc");
107462306a36Sopenharmony_ci		return -ENOMEM;
107562306a36Sopenharmony_ci	}
107662306a36Sopenharmony_ci	context->filterkey = key;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	audit_set_context(tsk, context);
107962306a36Sopenharmony_ci	set_task_syscall_work(tsk, SYSCALL_AUDIT);
108062306a36Sopenharmony_ci	return 0;
108162306a36Sopenharmony_ci}
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_cistatic inline void audit_free_context(struct audit_context *context)
108462306a36Sopenharmony_ci{
108562306a36Sopenharmony_ci	/* resetting is extra work, but it is likely just noise */
108662306a36Sopenharmony_ci	audit_reset_context(context);
108762306a36Sopenharmony_ci	audit_proctitle_free(context);
108862306a36Sopenharmony_ci	free_tree_refs(context);
108962306a36Sopenharmony_ci	kfree(context->filterkey);
109062306a36Sopenharmony_ci	kfree(context);
109162306a36Sopenharmony_ci}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_cistatic int audit_log_pid_context(struct audit_context *context, pid_t pid,
109462306a36Sopenharmony_ci				 kuid_t auid, kuid_t uid, unsigned int sessionid,
109562306a36Sopenharmony_ci				 u32 sid, char *comm)
109662306a36Sopenharmony_ci{
109762306a36Sopenharmony_ci	struct audit_buffer *ab;
109862306a36Sopenharmony_ci	char *ctx = NULL;
109962306a36Sopenharmony_ci	u32 len;
110062306a36Sopenharmony_ci	int rc = 0;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
110362306a36Sopenharmony_ci	if (!ab)
110462306a36Sopenharmony_ci		return rc;
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
110762306a36Sopenharmony_ci			 from_kuid(&init_user_ns, auid),
110862306a36Sopenharmony_ci			 from_kuid(&init_user_ns, uid), sessionid);
110962306a36Sopenharmony_ci	if (sid) {
111062306a36Sopenharmony_ci		if (security_secid_to_secctx(sid, &ctx, &len)) {
111162306a36Sopenharmony_ci			audit_log_format(ab, " obj=(none)");
111262306a36Sopenharmony_ci			rc = 1;
111362306a36Sopenharmony_ci		} else {
111462306a36Sopenharmony_ci			audit_log_format(ab, " obj=%s", ctx);
111562306a36Sopenharmony_ci			security_release_secctx(ctx, len);
111662306a36Sopenharmony_ci		}
111762306a36Sopenharmony_ci	}
111862306a36Sopenharmony_ci	audit_log_format(ab, " ocomm=");
111962306a36Sopenharmony_ci	audit_log_untrustedstring(ab, comm);
112062306a36Sopenharmony_ci	audit_log_end(ab);
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	return rc;
112362306a36Sopenharmony_ci}
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_cistatic void audit_log_execve_info(struct audit_context *context,
112662306a36Sopenharmony_ci				  struct audit_buffer **ab)
112762306a36Sopenharmony_ci{
112862306a36Sopenharmony_ci	long len_max;
112962306a36Sopenharmony_ci	long len_rem;
113062306a36Sopenharmony_ci	long len_full;
113162306a36Sopenharmony_ci	long len_buf;
113262306a36Sopenharmony_ci	long len_abuf = 0;
113362306a36Sopenharmony_ci	long len_tmp;
113462306a36Sopenharmony_ci	bool require_data;
113562306a36Sopenharmony_ci	bool encode;
113662306a36Sopenharmony_ci	unsigned int iter;
113762306a36Sopenharmony_ci	unsigned int arg;
113862306a36Sopenharmony_ci	char *buf_head;
113962306a36Sopenharmony_ci	char *buf;
114062306a36Sopenharmony_ci	const char __user *p = (const char __user *)current->mm->arg_start;
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	/* NOTE: this buffer needs to be large enough to hold all the non-arg
114362306a36Sopenharmony_ci	 *       data we put in the audit record for this argument (see the
114462306a36Sopenharmony_ci	 *       code below) ... at this point in time 96 is plenty */
114562306a36Sopenharmony_ci	char abuf[96];
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	/* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the
114862306a36Sopenharmony_ci	 *       current value of 7500 is not as important as the fact that it
114962306a36Sopenharmony_ci	 *       is less than 8k, a setting of 7500 gives us plenty of wiggle
115062306a36Sopenharmony_ci	 *       room if we go over a little bit in the logging below */
115162306a36Sopenharmony_ci	WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500);
115262306a36Sopenharmony_ci	len_max = MAX_EXECVE_AUDIT_LEN;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	/* scratch buffer to hold the userspace args */
115562306a36Sopenharmony_ci	buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
115662306a36Sopenharmony_ci	if (!buf_head) {
115762306a36Sopenharmony_ci		audit_panic("out of memory for argv string");
115862306a36Sopenharmony_ci		return;
115962306a36Sopenharmony_ci	}
116062306a36Sopenharmony_ci	buf = buf_head;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	audit_log_format(*ab, "argc=%d", context->execve.argc);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	len_rem = len_max;
116562306a36Sopenharmony_ci	len_buf = 0;
116662306a36Sopenharmony_ci	len_full = 0;
116762306a36Sopenharmony_ci	require_data = true;
116862306a36Sopenharmony_ci	encode = false;
116962306a36Sopenharmony_ci	iter = 0;
117062306a36Sopenharmony_ci	arg = 0;
117162306a36Sopenharmony_ci	do {
117262306a36Sopenharmony_ci		/* NOTE: we don't ever want to trust this value for anything
117362306a36Sopenharmony_ci		 *       serious, but the audit record format insists we
117462306a36Sopenharmony_ci		 *       provide an argument length for really long arguments,
117562306a36Sopenharmony_ci		 *       e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but
117662306a36Sopenharmony_ci		 *       to use strncpy_from_user() to obtain this value for
117762306a36Sopenharmony_ci		 *       recording in the log, although we don't use it
117862306a36Sopenharmony_ci		 *       anywhere here to avoid a double-fetch problem */
117962306a36Sopenharmony_ci		if (len_full == 0)
118062306a36Sopenharmony_ci			len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci		/* read more data from userspace */
118362306a36Sopenharmony_ci		if (require_data) {
118462306a36Sopenharmony_ci			/* can we make more room in the buffer? */
118562306a36Sopenharmony_ci			if (buf != buf_head) {
118662306a36Sopenharmony_ci				memmove(buf_head, buf, len_buf);
118762306a36Sopenharmony_ci				buf = buf_head;
118862306a36Sopenharmony_ci			}
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci			/* fetch as much as we can of the argument */
119162306a36Sopenharmony_ci			len_tmp = strncpy_from_user(&buf_head[len_buf], p,
119262306a36Sopenharmony_ci						    len_max - len_buf);
119362306a36Sopenharmony_ci			if (len_tmp == -EFAULT) {
119462306a36Sopenharmony_ci				/* unable to copy from userspace */
119562306a36Sopenharmony_ci				send_sig(SIGKILL, current, 0);
119662306a36Sopenharmony_ci				goto out;
119762306a36Sopenharmony_ci			} else if (len_tmp == (len_max - len_buf)) {
119862306a36Sopenharmony_ci				/* buffer is not large enough */
119962306a36Sopenharmony_ci				require_data = true;
120062306a36Sopenharmony_ci				/* NOTE: if we are going to span multiple
120162306a36Sopenharmony_ci				 *       buffers force the encoding so we stand
120262306a36Sopenharmony_ci				 *       a chance at a sane len_full value and
120362306a36Sopenharmony_ci				 *       consistent record encoding */
120462306a36Sopenharmony_ci				encode = true;
120562306a36Sopenharmony_ci				len_full = len_full * 2;
120662306a36Sopenharmony_ci				p += len_tmp;
120762306a36Sopenharmony_ci			} else {
120862306a36Sopenharmony_ci				require_data = false;
120962306a36Sopenharmony_ci				if (!encode)
121062306a36Sopenharmony_ci					encode = audit_string_contains_control(
121162306a36Sopenharmony_ci								buf, len_tmp);
121262306a36Sopenharmony_ci				/* try to use a trusted value for len_full */
121362306a36Sopenharmony_ci				if (len_full < len_max)
121462306a36Sopenharmony_ci					len_full = (encode ?
121562306a36Sopenharmony_ci						    len_tmp * 2 : len_tmp);
121662306a36Sopenharmony_ci				p += len_tmp + 1;
121762306a36Sopenharmony_ci			}
121862306a36Sopenharmony_ci			len_buf += len_tmp;
121962306a36Sopenharmony_ci			buf_head[len_buf] = '\0';
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci			/* length of the buffer in the audit record? */
122262306a36Sopenharmony_ci			len_abuf = (encode ? len_buf * 2 : len_buf + 2);
122362306a36Sopenharmony_ci		}
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci		/* write as much as we can to the audit log */
122662306a36Sopenharmony_ci		if (len_buf >= 0) {
122762306a36Sopenharmony_ci			/* NOTE: some magic numbers here - basically if we
122862306a36Sopenharmony_ci			 *       can't fit a reasonable amount of data into the
122962306a36Sopenharmony_ci			 *       existing audit buffer, flush it and start with
123062306a36Sopenharmony_ci			 *       a new buffer */
123162306a36Sopenharmony_ci			if ((sizeof(abuf) + 8) > len_rem) {
123262306a36Sopenharmony_ci				len_rem = len_max;
123362306a36Sopenharmony_ci				audit_log_end(*ab);
123462306a36Sopenharmony_ci				*ab = audit_log_start(context,
123562306a36Sopenharmony_ci						      GFP_KERNEL, AUDIT_EXECVE);
123662306a36Sopenharmony_ci				if (!*ab)
123762306a36Sopenharmony_ci					goto out;
123862306a36Sopenharmony_ci			}
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci			/* create the non-arg portion of the arg record */
124162306a36Sopenharmony_ci			len_tmp = 0;
124262306a36Sopenharmony_ci			if (require_data || (iter > 0) ||
124362306a36Sopenharmony_ci			    ((len_abuf + sizeof(abuf)) > len_rem)) {
124462306a36Sopenharmony_ci				if (iter == 0) {
124562306a36Sopenharmony_ci					len_tmp += snprintf(&abuf[len_tmp],
124662306a36Sopenharmony_ci							sizeof(abuf) - len_tmp,
124762306a36Sopenharmony_ci							" a%d_len=%lu",
124862306a36Sopenharmony_ci							arg, len_full);
124962306a36Sopenharmony_ci				}
125062306a36Sopenharmony_ci				len_tmp += snprintf(&abuf[len_tmp],
125162306a36Sopenharmony_ci						    sizeof(abuf) - len_tmp,
125262306a36Sopenharmony_ci						    " a%d[%d]=", arg, iter++);
125362306a36Sopenharmony_ci			} else
125462306a36Sopenharmony_ci				len_tmp += snprintf(&abuf[len_tmp],
125562306a36Sopenharmony_ci						    sizeof(abuf) - len_tmp,
125662306a36Sopenharmony_ci						    " a%d=", arg);
125762306a36Sopenharmony_ci			WARN_ON(len_tmp >= sizeof(abuf));
125862306a36Sopenharmony_ci			abuf[sizeof(abuf) - 1] = '\0';
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci			/* log the arg in the audit record */
126162306a36Sopenharmony_ci			audit_log_format(*ab, "%s", abuf);
126262306a36Sopenharmony_ci			len_rem -= len_tmp;
126362306a36Sopenharmony_ci			len_tmp = len_buf;
126462306a36Sopenharmony_ci			if (encode) {
126562306a36Sopenharmony_ci				if (len_abuf > len_rem)
126662306a36Sopenharmony_ci					len_tmp = len_rem / 2; /* encoding */
126762306a36Sopenharmony_ci				audit_log_n_hex(*ab, buf, len_tmp);
126862306a36Sopenharmony_ci				len_rem -= len_tmp * 2;
126962306a36Sopenharmony_ci				len_abuf -= len_tmp * 2;
127062306a36Sopenharmony_ci			} else {
127162306a36Sopenharmony_ci				if (len_abuf > len_rem)
127262306a36Sopenharmony_ci					len_tmp = len_rem - 2; /* quotes */
127362306a36Sopenharmony_ci				audit_log_n_string(*ab, buf, len_tmp);
127462306a36Sopenharmony_ci				len_rem -= len_tmp + 2;
127562306a36Sopenharmony_ci				/* don't subtract the "2" because we still need
127662306a36Sopenharmony_ci				 * to add quotes to the remaining string */
127762306a36Sopenharmony_ci				len_abuf -= len_tmp;
127862306a36Sopenharmony_ci			}
127962306a36Sopenharmony_ci			len_buf -= len_tmp;
128062306a36Sopenharmony_ci			buf += len_tmp;
128162306a36Sopenharmony_ci		}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci		/* ready to move to the next argument? */
128462306a36Sopenharmony_ci		if ((len_buf == 0) && !require_data) {
128562306a36Sopenharmony_ci			arg++;
128662306a36Sopenharmony_ci			iter = 0;
128762306a36Sopenharmony_ci			len_full = 0;
128862306a36Sopenharmony_ci			require_data = true;
128962306a36Sopenharmony_ci			encode = false;
129062306a36Sopenharmony_ci		}
129162306a36Sopenharmony_ci	} while (arg < context->execve.argc);
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci	/* NOTE: the caller handles the final audit_log_end() call */
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ciout:
129662306a36Sopenharmony_ci	kfree(buf_head);
129762306a36Sopenharmony_ci}
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_cistatic void audit_log_cap(struct audit_buffer *ab, char *prefix,
130062306a36Sopenharmony_ci			  kernel_cap_t *cap)
130162306a36Sopenharmony_ci{
130262306a36Sopenharmony_ci	if (cap_isclear(*cap)) {
130362306a36Sopenharmony_ci		audit_log_format(ab, " %s=0", prefix);
130462306a36Sopenharmony_ci		return;
130562306a36Sopenharmony_ci	}
130662306a36Sopenharmony_ci	audit_log_format(ab, " %s=%016llx", prefix, cap->val);
130762306a36Sopenharmony_ci}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_cistatic void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
131062306a36Sopenharmony_ci{
131162306a36Sopenharmony_ci	if (name->fcap_ver == -1) {
131262306a36Sopenharmony_ci		audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?");
131362306a36Sopenharmony_ci		return;
131462306a36Sopenharmony_ci	}
131562306a36Sopenharmony_ci	audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
131662306a36Sopenharmony_ci	audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
131762306a36Sopenharmony_ci	audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d",
131862306a36Sopenharmony_ci			 name->fcap.fE, name->fcap_ver,
131962306a36Sopenharmony_ci			 from_kuid(&init_user_ns, name->fcap.rootid));
132062306a36Sopenharmony_ci}
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_cistatic void audit_log_time(struct audit_context *context, struct audit_buffer **ab)
132362306a36Sopenharmony_ci{
132462306a36Sopenharmony_ci	const struct audit_ntp_data *ntp = &context->time.ntp_data;
132562306a36Sopenharmony_ci	const struct timespec64 *tk = &context->time.tk_injoffset;
132662306a36Sopenharmony_ci	static const char * const ntp_name[] = {
132762306a36Sopenharmony_ci		"offset",
132862306a36Sopenharmony_ci		"freq",
132962306a36Sopenharmony_ci		"status",
133062306a36Sopenharmony_ci		"tai",
133162306a36Sopenharmony_ci		"tick",
133262306a36Sopenharmony_ci		"adjust",
133362306a36Sopenharmony_ci	};
133462306a36Sopenharmony_ci	int type;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	if (context->type == AUDIT_TIME_ADJNTPVAL) {
133762306a36Sopenharmony_ci		for (type = 0; type < AUDIT_NTP_NVALS; type++) {
133862306a36Sopenharmony_ci			if (ntp->vals[type].newval != ntp->vals[type].oldval) {
133962306a36Sopenharmony_ci				if (!*ab) {
134062306a36Sopenharmony_ci					*ab = audit_log_start(context,
134162306a36Sopenharmony_ci							GFP_KERNEL,
134262306a36Sopenharmony_ci							AUDIT_TIME_ADJNTPVAL);
134362306a36Sopenharmony_ci					if (!*ab)
134462306a36Sopenharmony_ci						return;
134562306a36Sopenharmony_ci				}
134662306a36Sopenharmony_ci				audit_log_format(*ab, "op=%s old=%lli new=%lli",
134762306a36Sopenharmony_ci						 ntp_name[type],
134862306a36Sopenharmony_ci						 ntp->vals[type].oldval,
134962306a36Sopenharmony_ci						 ntp->vals[type].newval);
135062306a36Sopenharmony_ci				audit_log_end(*ab);
135162306a36Sopenharmony_ci				*ab = NULL;
135262306a36Sopenharmony_ci			}
135362306a36Sopenharmony_ci		}
135462306a36Sopenharmony_ci	}
135562306a36Sopenharmony_ci	if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
135662306a36Sopenharmony_ci		if (!*ab) {
135762306a36Sopenharmony_ci			*ab = audit_log_start(context, GFP_KERNEL,
135862306a36Sopenharmony_ci					      AUDIT_TIME_INJOFFSET);
135962306a36Sopenharmony_ci			if (!*ab)
136062306a36Sopenharmony_ci				return;
136162306a36Sopenharmony_ci		}
136262306a36Sopenharmony_ci		audit_log_format(*ab, "sec=%lli nsec=%li",
136362306a36Sopenharmony_ci				 (long long)tk->tv_sec, tk->tv_nsec);
136462306a36Sopenharmony_ci		audit_log_end(*ab);
136562306a36Sopenharmony_ci		*ab = NULL;
136662306a36Sopenharmony_ci	}
136762306a36Sopenharmony_ci}
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_cistatic void show_special(struct audit_context *context, int *call_panic)
137062306a36Sopenharmony_ci{
137162306a36Sopenharmony_ci	struct audit_buffer *ab;
137262306a36Sopenharmony_ci	int i;
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	ab = audit_log_start(context, GFP_KERNEL, context->type);
137562306a36Sopenharmony_ci	if (!ab)
137662306a36Sopenharmony_ci		return;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	switch (context->type) {
137962306a36Sopenharmony_ci	case AUDIT_SOCKETCALL: {
138062306a36Sopenharmony_ci		int nargs = context->socketcall.nargs;
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci		audit_log_format(ab, "nargs=%d", nargs);
138362306a36Sopenharmony_ci		for (i = 0; i < nargs; i++)
138462306a36Sopenharmony_ci			audit_log_format(ab, " a%d=%lx", i,
138562306a36Sopenharmony_ci				context->socketcall.args[i]);
138662306a36Sopenharmony_ci		break; }
138762306a36Sopenharmony_ci	case AUDIT_IPC: {
138862306a36Sopenharmony_ci		u32 osid = context->ipc.osid;
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci		audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho",
139162306a36Sopenharmony_ci				 from_kuid(&init_user_ns, context->ipc.uid),
139262306a36Sopenharmony_ci				 from_kgid(&init_user_ns, context->ipc.gid),
139362306a36Sopenharmony_ci				 context->ipc.mode);
139462306a36Sopenharmony_ci		if (osid) {
139562306a36Sopenharmony_ci			char *ctx = NULL;
139662306a36Sopenharmony_ci			u32 len;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci			if (security_secid_to_secctx(osid, &ctx, &len)) {
139962306a36Sopenharmony_ci				audit_log_format(ab, " osid=%u", osid);
140062306a36Sopenharmony_ci				*call_panic = 1;
140162306a36Sopenharmony_ci			} else {
140262306a36Sopenharmony_ci				audit_log_format(ab, " obj=%s", ctx);
140362306a36Sopenharmony_ci				security_release_secctx(ctx, len);
140462306a36Sopenharmony_ci			}
140562306a36Sopenharmony_ci		}
140662306a36Sopenharmony_ci		if (context->ipc.has_perm) {
140762306a36Sopenharmony_ci			audit_log_end(ab);
140862306a36Sopenharmony_ci			ab = audit_log_start(context, GFP_KERNEL,
140962306a36Sopenharmony_ci					     AUDIT_IPC_SET_PERM);
141062306a36Sopenharmony_ci			if (unlikely(!ab))
141162306a36Sopenharmony_ci				return;
141262306a36Sopenharmony_ci			audit_log_format(ab,
141362306a36Sopenharmony_ci				"qbytes=%lx ouid=%u ogid=%u mode=%#ho",
141462306a36Sopenharmony_ci				context->ipc.qbytes,
141562306a36Sopenharmony_ci				context->ipc.perm_uid,
141662306a36Sopenharmony_ci				context->ipc.perm_gid,
141762306a36Sopenharmony_ci				context->ipc.perm_mode);
141862306a36Sopenharmony_ci		}
141962306a36Sopenharmony_ci		break; }
142062306a36Sopenharmony_ci	case AUDIT_MQ_OPEN:
142162306a36Sopenharmony_ci		audit_log_format(ab,
142262306a36Sopenharmony_ci			"oflag=0x%x mode=%#ho mq_flags=0x%lx mq_maxmsg=%ld "
142362306a36Sopenharmony_ci			"mq_msgsize=%ld mq_curmsgs=%ld",
142462306a36Sopenharmony_ci			context->mq_open.oflag, context->mq_open.mode,
142562306a36Sopenharmony_ci			context->mq_open.attr.mq_flags,
142662306a36Sopenharmony_ci			context->mq_open.attr.mq_maxmsg,
142762306a36Sopenharmony_ci			context->mq_open.attr.mq_msgsize,
142862306a36Sopenharmony_ci			context->mq_open.attr.mq_curmsgs);
142962306a36Sopenharmony_ci		break;
143062306a36Sopenharmony_ci	case AUDIT_MQ_SENDRECV:
143162306a36Sopenharmony_ci		audit_log_format(ab,
143262306a36Sopenharmony_ci			"mqdes=%d msg_len=%zd msg_prio=%u "
143362306a36Sopenharmony_ci			"abs_timeout_sec=%lld abs_timeout_nsec=%ld",
143462306a36Sopenharmony_ci			context->mq_sendrecv.mqdes,
143562306a36Sopenharmony_ci			context->mq_sendrecv.msg_len,
143662306a36Sopenharmony_ci			context->mq_sendrecv.msg_prio,
143762306a36Sopenharmony_ci			(long long) context->mq_sendrecv.abs_timeout.tv_sec,
143862306a36Sopenharmony_ci			context->mq_sendrecv.abs_timeout.tv_nsec);
143962306a36Sopenharmony_ci		break;
144062306a36Sopenharmony_ci	case AUDIT_MQ_NOTIFY:
144162306a36Sopenharmony_ci		audit_log_format(ab, "mqdes=%d sigev_signo=%d",
144262306a36Sopenharmony_ci				context->mq_notify.mqdes,
144362306a36Sopenharmony_ci				context->mq_notify.sigev_signo);
144462306a36Sopenharmony_ci		break;
144562306a36Sopenharmony_ci	case AUDIT_MQ_GETSETATTR: {
144662306a36Sopenharmony_ci		struct mq_attr *attr = &context->mq_getsetattr.mqstat;
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci		audit_log_format(ab,
144962306a36Sopenharmony_ci			"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
145062306a36Sopenharmony_ci			"mq_curmsgs=%ld ",
145162306a36Sopenharmony_ci			context->mq_getsetattr.mqdes,
145262306a36Sopenharmony_ci			attr->mq_flags, attr->mq_maxmsg,
145362306a36Sopenharmony_ci			attr->mq_msgsize, attr->mq_curmsgs);
145462306a36Sopenharmony_ci		break; }
145562306a36Sopenharmony_ci	case AUDIT_CAPSET:
145662306a36Sopenharmony_ci		audit_log_format(ab, "pid=%d", context->capset.pid);
145762306a36Sopenharmony_ci		audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
145862306a36Sopenharmony_ci		audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
145962306a36Sopenharmony_ci		audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
146062306a36Sopenharmony_ci		audit_log_cap(ab, "cap_pa", &context->capset.cap.ambient);
146162306a36Sopenharmony_ci		break;
146262306a36Sopenharmony_ci	case AUDIT_MMAP:
146362306a36Sopenharmony_ci		audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
146462306a36Sopenharmony_ci				 context->mmap.flags);
146562306a36Sopenharmony_ci		break;
146662306a36Sopenharmony_ci	case AUDIT_OPENAT2:
146762306a36Sopenharmony_ci		audit_log_format(ab, "oflag=0%llo mode=0%llo resolve=0x%llx",
146862306a36Sopenharmony_ci				 context->openat2.flags,
146962306a36Sopenharmony_ci				 context->openat2.mode,
147062306a36Sopenharmony_ci				 context->openat2.resolve);
147162306a36Sopenharmony_ci		break;
147262306a36Sopenharmony_ci	case AUDIT_EXECVE:
147362306a36Sopenharmony_ci		audit_log_execve_info(context, &ab);
147462306a36Sopenharmony_ci		break;
147562306a36Sopenharmony_ci	case AUDIT_KERN_MODULE:
147662306a36Sopenharmony_ci		audit_log_format(ab, "name=");
147762306a36Sopenharmony_ci		if (context->module.name) {
147862306a36Sopenharmony_ci			audit_log_untrustedstring(ab, context->module.name);
147962306a36Sopenharmony_ci		} else
148062306a36Sopenharmony_ci			audit_log_format(ab, "(null)");
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci		break;
148362306a36Sopenharmony_ci	case AUDIT_TIME_ADJNTPVAL:
148462306a36Sopenharmony_ci	case AUDIT_TIME_INJOFFSET:
148562306a36Sopenharmony_ci		/* this call deviates from the rest, eating the buffer */
148662306a36Sopenharmony_ci		audit_log_time(context, &ab);
148762306a36Sopenharmony_ci		break;
148862306a36Sopenharmony_ci	}
148962306a36Sopenharmony_ci	audit_log_end(ab);
149062306a36Sopenharmony_ci}
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_cistatic inline int audit_proctitle_rtrim(char *proctitle, int len)
149362306a36Sopenharmony_ci{
149462306a36Sopenharmony_ci	char *end = proctitle + len - 1;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	while (end > proctitle && !isprint(*end))
149762306a36Sopenharmony_ci		end--;
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	/* catch the case where proctitle is only 1 non-print character */
150062306a36Sopenharmony_ci	len = end - proctitle + 1;
150162306a36Sopenharmony_ci	len -= isprint(proctitle[len-1]) == 0;
150262306a36Sopenharmony_ci	return len;
150362306a36Sopenharmony_ci}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci/*
150662306a36Sopenharmony_ci * audit_log_name - produce AUDIT_PATH record from struct audit_names
150762306a36Sopenharmony_ci * @context: audit_context for the task
150862306a36Sopenharmony_ci * @n: audit_names structure with reportable details
150962306a36Sopenharmony_ci * @path: optional path to report instead of audit_names->name
151062306a36Sopenharmony_ci * @record_num: record number to report when handling a list of names
151162306a36Sopenharmony_ci * @call_panic: optional pointer to int that will be updated if secid fails
151262306a36Sopenharmony_ci */
151362306a36Sopenharmony_cistatic void audit_log_name(struct audit_context *context, struct audit_names *n,
151462306a36Sopenharmony_ci		    const struct path *path, int record_num, int *call_panic)
151562306a36Sopenharmony_ci{
151662306a36Sopenharmony_ci	struct audit_buffer *ab;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
151962306a36Sopenharmony_ci	if (!ab)
152062306a36Sopenharmony_ci		return;
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	audit_log_format(ab, "item=%d", record_num);
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	if (path)
152562306a36Sopenharmony_ci		audit_log_d_path(ab, " name=", path);
152662306a36Sopenharmony_ci	else if (n->name) {
152762306a36Sopenharmony_ci		switch (n->name_len) {
152862306a36Sopenharmony_ci		case AUDIT_NAME_FULL:
152962306a36Sopenharmony_ci			/* log the full path */
153062306a36Sopenharmony_ci			audit_log_format(ab, " name=");
153162306a36Sopenharmony_ci			audit_log_untrustedstring(ab, n->name->name);
153262306a36Sopenharmony_ci			break;
153362306a36Sopenharmony_ci		case 0:
153462306a36Sopenharmony_ci			/* name was specified as a relative path and the
153562306a36Sopenharmony_ci			 * directory component is the cwd
153662306a36Sopenharmony_ci			 */
153762306a36Sopenharmony_ci			if (context->pwd.dentry && context->pwd.mnt)
153862306a36Sopenharmony_ci				audit_log_d_path(ab, " name=", &context->pwd);
153962306a36Sopenharmony_ci			else
154062306a36Sopenharmony_ci				audit_log_format(ab, " name=(null)");
154162306a36Sopenharmony_ci			break;
154262306a36Sopenharmony_ci		default:
154362306a36Sopenharmony_ci			/* log the name's directory component */
154462306a36Sopenharmony_ci			audit_log_format(ab, " name=");
154562306a36Sopenharmony_ci			audit_log_n_untrustedstring(ab, n->name->name,
154662306a36Sopenharmony_ci						    n->name_len);
154762306a36Sopenharmony_ci		}
154862306a36Sopenharmony_ci	} else
154962306a36Sopenharmony_ci		audit_log_format(ab, " name=(null)");
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	if (n->ino != AUDIT_INO_UNSET)
155262306a36Sopenharmony_ci		audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x",
155362306a36Sopenharmony_ci				 n->ino,
155462306a36Sopenharmony_ci				 MAJOR(n->dev),
155562306a36Sopenharmony_ci				 MINOR(n->dev),
155662306a36Sopenharmony_ci				 n->mode,
155762306a36Sopenharmony_ci				 from_kuid(&init_user_ns, n->uid),
155862306a36Sopenharmony_ci				 from_kgid(&init_user_ns, n->gid),
155962306a36Sopenharmony_ci				 MAJOR(n->rdev),
156062306a36Sopenharmony_ci				 MINOR(n->rdev));
156162306a36Sopenharmony_ci	if (n->osid != 0) {
156262306a36Sopenharmony_ci		char *ctx = NULL;
156362306a36Sopenharmony_ci		u32 len;
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci		if (security_secid_to_secctx(
156662306a36Sopenharmony_ci			n->osid, &ctx, &len)) {
156762306a36Sopenharmony_ci			audit_log_format(ab, " osid=%u", n->osid);
156862306a36Sopenharmony_ci			if (call_panic)
156962306a36Sopenharmony_ci				*call_panic = 2;
157062306a36Sopenharmony_ci		} else {
157162306a36Sopenharmony_ci			audit_log_format(ab, " obj=%s", ctx);
157262306a36Sopenharmony_ci			security_release_secctx(ctx, len);
157362306a36Sopenharmony_ci		}
157462306a36Sopenharmony_ci	}
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	/* log the audit_names record type */
157762306a36Sopenharmony_ci	switch (n->type) {
157862306a36Sopenharmony_ci	case AUDIT_TYPE_NORMAL:
157962306a36Sopenharmony_ci		audit_log_format(ab, " nametype=NORMAL");
158062306a36Sopenharmony_ci		break;
158162306a36Sopenharmony_ci	case AUDIT_TYPE_PARENT:
158262306a36Sopenharmony_ci		audit_log_format(ab, " nametype=PARENT");
158362306a36Sopenharmony_ci		break;
158462306a36Sopenharmony_ci	case AUDIT_TYPE_CHILD_DELETE:
158562306a36Sopenharmony_ci		audit_log_format(ab, " nametype=DELETE");
158662306a36Sopenharmony_ci		break;
158762306a36Sopenharmony_ci	case AUDIT_TYPE_CHILD_CREATE:
158862306a36Sopenharmony_ci		audit_log_format(ab, " nametype=CREATE");
158962306a36Sopenharmony_ci		break;
159062306a36Sopenharmony_ci	default:
159162306a36Sopenharmony_ci		audit_log_format(ab, " nametype=UNKNOWN");
159262306a36Sopenharmony_ci		break;
159362306a36Sopenharmony_ci	}
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	audit_log_fcaps(ab, n);
159662306a36Sopenharmony_ci	audit_log_end(ab);
159762306a36Sopenharmony_ci}
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_cistatic void audit_log_proctitle(void)
160062306a36Sopenharmony_ci{
160162306a36Sopenharmony_ci	int res;
160262306a36Sopenharmony_ci	char *buf;
160362306a36Sopenharmony_ci	char *msg = "(null)";
160462306a36Sopenharmony_ci	int len = strlen(msg);
160562306a36Sopenharmony_ci	struct audit_context *context = audit_context();
160662306a36Sopenharmony_ci	struct audit_buffer *ab;
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
160962306a36Sopenharmony_ci	if (!ab)
161062306a36Sopenharmony_ci		return;	/* audit_panic or being filtered */
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci	audit_log_format(ab, "proctitle=");
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	/* Not  cached */
161562306a36Sopenharmony_ci	if (!context->proctitle.value) {
161662306a36Sopenharmony_ci		buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL);
161762306a36Sopenharmony_ci		if (!buf)
161862306a36Sopenharmony_ci			goto out;
161962306a36Sopenharmony_ci		/* Historically called this from procfs naming */
162062306a36Sopenharmony_ci		res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN);
162162306a36Sopenharmony_ci		if (res == 0) {
162262306a36Sopenharmony_ci			kfree(buf);
162362306a36Sopenharmony_ci			goto out;
162462306a36Sopenharmony_ci		}
162562306a36Sopenharmony_ci		res = audit_proctitle_rtrim(buf, res);
162662306a36Sopenharmony_ci		if (res == 0) {
162762306a36Sopenharmony_ci			kfree(buf);
162862306a36Sopenharmony_ci			goto out;
162962306a36Sopenharmony_ci		}
163062306a36Sopenharmony_ci		context->proctitle.value = buf;
163162306a36Sopenharmony_ci		context->proctitle.len = res;
163262306a36Sopenharmony_ci	}
163362306a36Sopenharmony_ci	msg = context->proctitle.value;
163462306a36Sopenharmony_ci	len = context->proctitle.len;
163562306a36Sopenharmony_ciout:
163662306a36Sopenharmony_ci	audit_log_n_untrustedstring(ab, msg, len);
163762306a36Sopenharmony_ci	audit_log_end(ab);
163862306a36Sopenharmony_ci}
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci/**
164162306a36Sopenharmony_ci * audit_log_uring - generate a AUDIT_URINGOP record
164262306a36Sopenharmony_ci * @ctx: the audit context
164362306a36Sopenharmony_ci */
164462306a36Sopenharmony_cistatic void audit_log_uring(struct audit_context *ctx)
164562306a36Sopenharmony_ci{
164662306a36Sopenharmony_ci	struct audit_buffer *ab;
164762306a36Sopenharmony_ci	const struct cred *cred;
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_URINGOP);
165062306a36Sopenharmony_ci	if (!ab)
165162306a36Sopenharmony_ci		return;
165262306a36Sopenharmony_ci	cred = current_cred();
165362306a36Sopenharmony_ci	audit_log_format(ab, "uring_op=%d", ctx->uring_op);
165462306a36Sopenharmony_ci	if (ctx->return_valid != AUDITSC_INVALID)
165562306a36Sopenharmony_ci		audit_log_format(ab, " success=%s exit=%ld",
165662306a36Sopenharmony_ci				 (ctx->return_valid == AUDITSC_SUCCESS ?
165762306a36Sopenharmony_ci				  "yes" : "no"),
165862306a36Sopenharmony_ci				 ctx->return_code);
165962306a36Sopenharmony_ci	audit_log_format(ab,
166062306a36Sopenharmony_ci			 " items=%d"
166162306a36Sopenharmony_ci			 " ppid=%d pid=%d uid=%u gid=%u euid=%u suid=%u"
166262306a36Sopenharmony_ci			 " fsuid=%u egid=%u sgid=%u fsgid=%u",
166362306a36Sopenharmony_ci			 ctx->name_count,
166462306a36Sopenharmony_ci			 task_ppid_nr(current), task_tgid_nr(current),
166562306a36Sopenharmony_ci			 from_kuid(&init_user_ns, cred->uid),
166662306a36Sopenharmony_ci			 from_kgid(&init_user_ns, cred->gid),
166762306a36Sopenharmony_ci			 from_kuid(&init_user_ns, cred->euid),
166862306a36Sopenharmony_ci			 from_kuid(&init_user_ns, cred->suid),
166962306a36Sopenharmony_ci			 from_kuid(&init_user_ns, cred->fsuid),
167062306a36Sopenharmony_ci			 from_kgid(&init_user_ns, cred->egid),
167162306a36Sopenharmony_ci			 from_kgid(&init_user_ns, cred->sgid),
167262306a36Sopenharmony_ci			 from_kgid(&init_user_ns, cred->fsgid));
167362306a36Sopenharmony_ci	audit_log_task_context(ab);
167462306a36Sopenharmony_ci	audit_log_key(ab, ctx->filterkey);
167562306a36Sopenharmony_ci	audit_log_end(ab);
167662306a36Sopenharmony_ci}
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_cistatic void audit_log_exit(void)
167962306a36Sopenharmony_ci{
168062306a36Sopenharmony_ci	int i, call_panic = 0;
168162306a36Sopenharmony_ci	struct audit_context *context = audit_context();
168262306a36Sopenharmony_ci	struct audit_buffer *ab;
168362306a36Sopenharmony_ci	struct audit_aux_data *aux;
168462306a36Sopenharmony_ci	struct audit_names *n;
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	context->personality = current->personality;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	switch (context->context) {
168962306a36Sopenharmony_ci	case AUDIT_CTX_SYSCALL:
169062306a36Sopenharmony_ci		ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
169162306a36Sopenharmony_ci		if (!ab)
169262306a36Sopenharmony_ci			return;
169362306a36Sopenharmony_ci		audit_log_format(ab, "arch=%x syscall=%d",
169462306a36Sopenharmony_ci				 context->arch, context->major);
169562306a36Sopenharmony_ci		if (context->personality != PER_LINUX)
169662306a36Sopenharmony_ci			audit_log_format(ab, " per=%lx", context->personality);
169762306a36Sopenharmony_ci		if (context->return_valid != AUDITSC_INVALID)
169862306a36Sopenharmony_ci			audit_log_format(ab, " success=%s exit=%ld",
169962306a36Sopenharmony_ci					 (context->return_valid == AUDITSC_SUCCESS ?
170062306a36Sopenharmony_ci					  "yes" : "no"),
170162306a36Sopenharmony_ci					 context->return_code);
170262306a36Sopenharmony_ci		audit_log_format(ab,
170362306a36Sopenharmony_ci				 " a0=%lx a1=%lx a2=%lx a3=%lx items=%d",
170462306a36Sopenharmony_ci				 context->argv[0],
170562306a36Sopenharmony_ci				 context->argv[1],
170662306a36Sopenharmony_ci				 context->argv[2],
170762306a36Sopenharmony_ci				 context->argv[3],
170862306a36Sopenharmony_ci				 context->name_count);
170962306a36Sopenharmony_ci		audit_log_task_info(ab);
171062306a36Sopenharmony_ci		audit_log_key(ab, context->filterkey);
171162306a36Sopenharmony_ci		audit_log_end(ab);
171262306a36Sopenharmony_ci		break;
171362306a36Sopenharmony_ci	case AUDIT_CTX_URING:
171462306a36Sopenharmony_ci		audit_log_uring(context);
171562306a36Sopenharmony_ci		break;
171662306a36Sopenharmony_ci	default:
171762306a36Sopenharmony_ci		BUG();
171862306a36Sopenharmony_ci		break;
171962306a36Sopenharmony_ci	}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	for (aux = context->aux; aux; aux = aux->next) {
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci		ab = audit_log_start(context, GFP_KERNEL, aux->type);
172462306a36Sopenharmony_ci		if (!ab)
172562306a36Sopenharmony_ci			continue; /* audit_panic has been called */
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci		switch (aux->type) {
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci		case AUDIT_BPRM_FCAPS: {
173062306a36Sopenharmony_ci			struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci			audit_log_format(ab, "fver=%x", axs->fcap_ver);
173362306a36Sopenharmony_ci			audit_log_cap(ab, "fp", &axs->fcap.permitted);
173462306a36Sopenharmony_ci			audit_log_cap(ab, "fi", &axs->fcap.inheritable);
173562306a36Sopenharmony_ci			audit_log_format(ab, " fe=%d", axs->fcap.fE);
173662306a36Sopenharmony_ci			audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
173762306a36Sopenharmony_ci			audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
173862306a36Sopenharmony_ci			audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
173962306a36Sopenharmony_ci			audit_log_cap(ab, "old_pa", &axs->old_pcap.ambient);
174062306a36Sopenharmony_ci			audit_log_cap(ab, "pp", &axs->new_pcap.permitted);
174162306a36Sopenharmony_ci			audit_log_cap(ab, "pi", &axs->new_pcap.inheritable);
174262306a36Sopenharmony_ci			audit_log_cap(ab, "pe", &axs->new_pcap.effective);
174362306a36Sopenharmony_ci			audit_log_cap(ab, "pa", &axs->new_pcap.ambient);
174462306a36Sopenharmony_ci			audit_log_format(ab, " frootid=%d",
174562306a36Sopenharmony_ci					 from_kuid(&init_user_ns,
174662306a36Sopenharmony_ci						   axs->fcap.rootid));
174762306a36Sopenharmony_ci			break; }
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci		}
175062306a36Sopenharmony_ci		audit_log_end(ab);
175162306a36Sopenharmony_ci	}
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	if (context->type)
175462306a36Sopenharmony_ci		show_special(context, &call_panic);
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	if (context->fds[0] >= 0) {
175762306a36Sopenharmony_ci		ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR);
175862306a36Sopenharmony_ci		if (ab) {
175962306a36Sopenharmony_ci			audit_log_format(ab, "fd0=%d fd1=%d",
176062306a36Sopenharmony_ci					context->fds[0], context->fds[1]);
176162306a36Sopenharmony_ci			audit_log_end(ab);
176262306a36Sopenharmony_ci		}
176362306a36Sopenharmony_ci	}
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	if (context->sockaddr_len) {
176662306a36Sopenharmony_ci		ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR);
176762306a36Sopenharmony_ci		if (ab) {
176862306a36Sopenharmony_ci			audit_log_format(ab, "saddr=");
176962306a36Sopenharmony_ci			audit_log_n_hex(ab, (void *)context->sockaddr,
177062306a36Sopenharmony_ci					context->sockaddr_len);
177162306a36Sopenharmony_ci			audit_log_end(ab);
177262306a36Sopenharmony_ci		}
177362306a36Sopenharmony_ci	}
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	for (aux = context->aux_pids; aux; aux = aux->next) {
177662306a36Sopenharmony_ci		struct audit_aux_data_pids *axs = (void *)aux;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci		for (i = 0; i < axs->pid_count; i++)
177962306a36Sopenharmony_ci			if (audit_log_pid_context(context, axs->target_pid[i],
178062306a36Sopenharmony_ci						  axs->target_auid[i],
178162306a36Sopenharmony_ci						  axs->target_uid[i],
178262306a36Sopenharmony_ci						  axs->target_sessionid[i],
178362306a36Sopenharmony_ci						  axs->target_sid[i],
178462306a36Sopenharmony_ci						  axs->target_comm[i]))
178562306a36Sopenharmony_ci				call_panic = 1;
178662306a36Sopenharmony_ci	}
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	if (context->target_pid &&
178962306a36Sopenharmony_ci	    audit_log_pid_context(context, context->target_pid,
179062306a36Sopenharmony_ci				  context->target_auid, context->target_uid,
179162306a36Sopenharmony_ci				  context->target_sessionid,
179262306a36Sopenharmony_ci				  context->target_sid, context->target_comm))
179362306a36Sopenharmony_ci			call_panic = 1;
179462306a36Sopenharmony_ci
179562306a36Sopenharmony_ci	if (context->pwd.dentry && context->pwd.mnt) {
179662306a36Sopenharmony_ci		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
179762306a36Sopenharmony_ci		if (ab) {
179862306a36Sopenharmony_ci			audit_log_d_path(ab, "cwd=", &context->pwd);
179962306a36Sopenharmony_ci			audit_log_end(ab);
180062306a36Sopenharmony_ci		}
180162306a36Sopenharmony_ci	}
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci	i = 0;
180462306a36Sopenharmony_ci	list_for_each_entry(n, &context->names_list, list) {
180562306a36Sopenharmony_ci		if (n->hidden)
180662306a36Sopenharmony_ci			continue;
180762306a36Sopenharmony_ci		audit_log_name(context, n, NULL, i++, &call_panic);
180862306a36Sopenharmony_ci	}
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	if (context->context == AUDIT_CTX_SYSCALL)
181162306a36Sopenharmony_ci		audit_log_proctitle();
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	/* Send end of event record to help user space know we are finished */
181462306a36Sopenharmony_ci	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
181562306a36Sopenharmony_ci	if (ab)
181662306a36Sopenharmony_ci		audit_log_end(ab);
181762306a36Sopenharmony_ci	if (call_panic)
181862306a36Sopenharmony_ci		audit_panic("error in audit_log_exit()");
181962306a36Sopenharmony_ci}
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci/**
182262306a36Sopenharmony_ci * __audit_free - free a per-task audit context
182362306a36Sopenharmony_ci * @tsk: task whose audit context block to free
182462306a36Sopenharmony_ci *
182562306a36Sopenharmony_ci * Called from copy_process, do_exit, and the io_uring code
182662306a36Sopenharmony_ci */
182762306a36Sopenharmony_civoid __audit_free(struct task_struct *tsk)
182862306a36Sopenharmony_ci{
182962306a36Sopenharmony_ci	struct audit_context *context = tsk->audit_context;
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	if (!context)
183262306a36Sopenharmony_ci		return;
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	/* this may generate CONFIG_CHANGE records */
183562306a36Sopenharmony_ci	if (!list_empty(&context->killed_trees))
183662306a36Sopenharmony_ci		audit_kill_trees(context);
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci	/* We are called either by do_exit() or the fork() error handling code;
183962306a36Sopenharmony_ci	 * in the former case tsk == current and in the latter tsk is a
184062306a36Sopenharmony_ci	 * random task_struct that doesn't have any meaningful data we
184162306a36Sopenharmony_ci	 * need to log via audit_log_exit().
184262306a36Sopenharmony_ci	 */
184362306a36Sopenharmony_ci	if (tsk == current && !context->dummy) {
184462306a36Sopenharmony_ci		context->return_valid = AUDITSC_INVALID;
184562306a36Sopenharmony_ci		context->return_code = 0;
184662306a36Sopenharmony_ci		if (context->context == AUDIT_CTX_SYSCALL) {
184762306a36Sopenharmony_ci			audit_filter_syscall(tsk, context);
184862306a36Sopenharmony_ci			audit_filter_inodes(tsk, context);
184962306a36Sopenharmony_ci			if (context->current_state == AUDIT_STATE_RECORD)
185062306a36Sopenharmony_ci				audit_log_exit();
185162306a36Sopenharmony_ci		} else if (context->context == AUDIT_CTX_URING) {
185262306a36Sopenharmony_ci			/* TODO: verify this case is real and valid */
185362306a36Sopenharmony_ci			audit_filter_uring(tsk, context);
185462306a36Sopenharmony_ci			audit_filter_inodes(tsk, context);
185562306a36Sopenharmony_ci			if (context->current_state == AUDIT_STATE_RECORD)
185662306a36Sopenharmony_ci				audit_log_uring(context);
185762306a36Sopenharmony_ci		}
185862306a36Sopenharmony_ci	}
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci	audit_set_context(tsk, NULL);
186162306a36Sopenharmony_ci	audit_free_context(context);
186262306a36Sopenharmony_ci}
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_ci/**
186562306a36Sopenharmony_ci * audit_return_fixup - fixup the return codes in the audit_context
186662306a36Sopenharmony_ci * @ctx: the audit_context
186762306a36Sopenharmony_ci * @success: true/false value to indicate if the operation succeeded or not
186862306a36Sopenharmony_ci * @code: operation return code
186962306a36Sopenharmony_ci *
187062306a36Sopenharmony_ci * We need to fixup the return code in the audit logs if the actual return
187162306a36Sopenharmony_ci * codes are later going to be fixed by the arch specific signal handlers.
187262306a36Sopenharmony_ci */
187362306a36Sopenharmony_cistatic void audit_return_fixup(struct audit_context *ctx,
187462306a36Sopenharmony_ci			       int success, long code)
187562306a36Sopenharmony_ci{
187662306a36Sopenharmony_ci	/*
187762306a36Sopenharmony_ci	 * This is actually a test for:
187862306a36Sopenharmony_ci	 * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
187962306a36Sopenharmony_ci	 * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
188062306a36Sopenharmony_ci	 *
188162306a36Sopenharmony_ci	 * but is faster than a bunch of ||
188262306a36Sopenharmony_ci	 */
188362306a36Sopenharmony_ci	if (unlikely(code <= -ERESTARTSYS) &&
188462306a36Sopenharmony_ci	    (code >= -ERESTART_RESTARTBLOCK) &&
188562306a36Sopenharmony_ci	    (code != -ENOIOCTLCMD))
188662306a36Sopenharmony_ci		ctx->return_code = -EINTR;
188762306a36Sopenharmony_ci	else
188862306a36Sopenharmony_ci		ctx->return_code  = code;
188962306a36Sopenharmony_ci	ctx->return_valid = (success ? AUDITSC_SUCCESS : AUDITSC_FAILURE);
189062306a36Sopenharmony_ci}
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci/**
189362306a36Sopenharmony_ci * __audit_uring_entry - prepare the kernel task's audit context for io_uring
189462306a36Sopenharmony_ci * @op: the io_uring opcode
189562306a36Sopenharmony_ci *
189662306a36Sopenharmony_ci * This is similar to audit_syscall_entry() but is intended for use by io_uring
189762306a36Sopenharmony_ci * operations.  This function should only ever be called from
189862306a36Sopenharmony_ci * audit_uring_entry() as we rely on the audit context checking present in that
189962306a36Sopenharmony_ci * function.
190062306a36Sopenharmony_ci */
190162306a36Sopenharmony_civoid __audit_uring_entry(u8 op)
190262306a36Sopenharmony_ci{
190362306a36Sopenharmony_ci	struct audit_context *ctx = audit_context();
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	if (ctx->state == AUDIT_STATE_DISABLED)
190662306a36Sopenharmony_ci		return;
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_ci	/*
190962306a36Sopenharmony_ci	 * NOTE: It's possible that we can be called from the process' context
191062306a36Sopenharmony_ci	 *       before it returns to userspace, and before audit_syscall_exit()
191162306a36Sopenharmony_ci	 *       is called.  In this case there is not much to do, just record
191262306a36Sopenharmony_ci	 *       the io_uring details and return.
191362306a36Sopenharmony_ci	 */
191462306a36Sopenharmony_ci	ctx->uring_op = op;
191562306a36Sopenharmony_ci	if (ctx->context == AUDIT_CTX_SYSCALL)
191662306a36Sopenharmony_ci		return;
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci	ctx->dummy = !audit_n_rules;
191962306a36Sopenharmony_ci	if (!ctx->dummy && ctx->state == AUDIT_STATE_BUILD)
192062306a36Sopenharmony_ci		ctx->prio = 0;
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci	ctx->context = AUDIT_CTX_URING;
192362306a36Sopenharmony_ci	ctx->current_state = ctx->state;
192462306a36Sopenharmony_ci	ktime_get_coarse_real_ts64(&ctx->ctime);
192562306a36Sopenharmony_ci}
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci/**
192862306a36Sopenharmony_ci * __audit_uring_exit - wrap up the kernel task's audit context after io_uring
192962306a36Sopenharmony_ci * @success: true/false value to indicate if the operation succeeded or not
193062306a36Sopenharmony_ci * @code: operation return code
193162306a36Sopenharmony_ci *
193262306a36Sopenharmony_ci * This is similar to audit_syscall_exit() but is intended for use by io_uring
193362306a36Sopenharmony_ci * operations.  This function should only ever be called from
193462306a36Sopenharmony_ci * audit_uring_exit() as we rely on the audit context checking present in that
193562306a36Sopenharmony_ci * function.
193662306a36Sopenharmony_ci */
193762306a36Sopenharmony_civoid __audit_uring_exit(int success, long code)
193862306a36Sopenharmony_ci{
193962306a36Sopenharmony_ci	struct audit_context *ctx = audit_context();
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci	if (ctx->dummy) {
194262306a36Sopenharmony_ci		if (ctx->context != AUDIT_CTX_URING)
194362306a36Sopenharmony_ci			return;
194462306a36Sopenharmony_ci		goto out;
194562306a36Sopenharmony_ci	}
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	audit_return_fixup(ctx, success, code);
194862306a36Sopenharmony_ci	if (ctx->context == AUDIT_CTX_SYSCALL) {
194962306a36Sopenharmony_ci		/*
195062306a36Sopenharmony_ci		 * NOTE: See the note in __audit_uring_entry() about the case
195162306a36Sopenharmony_ci		 *       where we may be called from process context before we
195262306a36Sopenharmony_ci		 *       return to userspace via audit_syscall_exit().  In this
195362306a36Sopenharmony_ci		 *       case we simply emit a URINGOP record and bail, the
195462306a36Sopenharmony_ci		 *       normal syscall exit handling will take care of
195562306a36Sopenharmony_ci		 *       everything else.
195662306a36Sopenharmony_ci		 *       It is also worth mentioning that when we are called,
195762306a36Sopenharmony_ci		 *       the current process creds may differ from the creds
195862306a36Sopenharmony_ci		 *       used during the normal syscall processing; keep that
195962306a36Sopenharmony_ci		 *       in mind if/when we move the record generation code.
196062306a36Sopenharmony_ci		 */
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci		/*
196362306a36Sopenharmony_ci		 * We need to filter on the syscall info here to decide if we
196462306a36Sopenharmony_ci		 * should emit a URINGOP record.  I know it seems odd but this
196562306a36Sopenharmony_ci		 * solves the problem where users have a filter to block *all*
196662306a36Sopenharmony_ci		 * syscall records in the "exit" filter; we want to preserve
196762306a36Sopenharmony_ci		 * the behavior here.
196862306a36Sopenharmony_ci		 */
196962306a36Sopenharmony_ci		audit_filter_syscall(current, ctx);
197062306a36Sopenharmony_ci		if (ctx->current_state != AUDIT_STATE_RECORD)
197162306a36Sopenharmony_ci			audit_filter_uring(current, ctx);
197262306a36Sopenharmony_ci		audit_filter_inodes(current, ctx);
197362306a36Sopenharmony_ci		if (ctx->current_state != AUDIT_STATE_RECORD)
197462306a36Sopenharmony_ci			return;
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci		audit_log_uring(ctx);
197762306a36Sopenharmony_ci		return;
197862306a36Sopenharmony_ci	}
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_ci	/* this may generate CONFIG_CHANGE records */
198162306a36Sopenharmony_ci	if (!list_empty(&ctx->killed_trees))
198262306a36Sopenharmony_ci		audit_kill_trees(ctx);
198362306a36Sopenharmony_ci
198462306a36Sopenharmony_ci	/* run through both filters to ensure we set the filterkey properly */
198562306a36Sopenharmony_ci	audit_filter_uring(current, ctx);
198662306a36Sopenharmony_ci	audit_filter_inodes(current, ctx);
198762306a36Sopenharmony_ci	if (ctx->current_state != AUDIT_STATE_RECORD)
198862306a36Sopenharmony_ci		goto out;
198962306a36Sopenharmony_ci	audit_log_exit();
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ciout:
199262306a36Sopenharmony_ci	audit_reset_context(ctx);
199362306a36Sopenharmony_ci}
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci/**
199662306a36Sopenharmony_ci * __audit_syscall_entry - fill in an audit record at syscall entry
199762306a36Sopenharmony_ci * @major: major syscall type (function)
199862306a36Sopenharmony_ci * @a1: additional syscall register 1
199962306a36Sopenharmony_ci * @a2: additional syscall register 2
200062306a36Sopenharmony_ci * @a3: additional syscall register 3
200162306a36Sopenharmony_ci * @a4: additional syscall register 4
200262306a36Sopenharmony_ci *
200362306a36Sopenharmony_ci * Fill in audit context at syscall entry.  This only happens if the
200462306a36Sopenharmony_ci * audit context was created when the task was created and the state or
200562306a36Sopenharmony_ci * filters demand the audit context be built.  If the state from the
200662306a36Sopenharmony_ci * per-task filter or from the per-syscall filter is AUDIT_STATE_RECORD,
200762306a36Sopenharmony_ci * then the record will be written at syscall exit time (otherwise, it
200862306a36Sopenharmony_ci * will only be written if another part of the kernel requests that it
200962306a36Sopenharmony_ci * be written).
201062306a36Sopenharmony_ci */
201162306a36Sopenharmony_civoid __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
201262306a36Sopenharmony_ci			   unsigned long a3, unsigned long a4)
201362306a36Sopenharmony_ci{
201462306a36Sopenharmony_ci	struct audit_context *context = audit_context();
201562306a36Sopenharmony_ci	enum audit_state     state;
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	if (!audit_enabled || !context)
201862306a36Sopenharmony_ci		return;
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci	WARN_ON(context->context != AUDIT_CTX_UNUSED);
202162306a36Sopenharmony_ci	WARN_ON(context->name_count);
202262306a36Sopenharmony_ci	if (context->context != AUDIT_CTX_UNUSED || context->name_count) {
202362306a36Sopenharmony_ci		audit_panic("unrecoverable error in audit_syscall_entry()");
202462306a36Sopenharmony_ci		return;
202562306a36Sopenharmony_ci	}
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	state = context->state;
202862306a36Sopenharmony_ci	if (state == AUDIT_STATE_DISABLED)
202962306a36Sopenharmony_ci		return;
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci	context->dummy = !audit_n_rules;
203262306a36Sopenharmony_ci	if (!context->dummy && state == AUDIT_STATE_BUILD) {
203362306a36Sopenharmony_ci		context->prio = 0;
203462306a36Sopenharmony_ci		if (auditd_test_task(current))
203562306a36Sopenharmony_ci			return;
203662306a36Sopenharmony_ci	}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci	context->arch	    = syscall_get_arch(current);
203962306a36Sopenharmony_ci	context->major      = major;
204062306a36Sopenharmony_ci	context->argv[0]    = a1;
204162306a36Sopenharmony_ci	context->argv[1]    = a2;
204262306a36Sopenharmony_ci	context->argv[2]    = a3;
204362306a36Sopenharmony_ci	context->argv[3]    = a4;
204462306a36Sopenharmony_ci	context->context = AUDIT_CTX_SYSCALL;
204562306a36Sopenharmony_ci	context->current_state  = state;
204662306a36Sopenharmony_ci	ktime_get_coarse_real_ts64(&context->ctime);
204762306a36Sopenharmony_ci}
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci/**
205062306a36Sopenharmony_ci * __audit_syscall_exit - deallocate audit context after a system call
205162306a36Sopenharmony_ci * @success: success value of the syscall
205262306a36Sopenharmony_ci * @return_code: return value of the syscall
205362306a36Sopenharmony_ci *
205462306a36Sopenharmony_ci * Tear down after system call.  If the audit context has been marked as
205562306a36Sopenharmony_ci * auditable (either because of the AUDIT_STATE_RECORD state from
205662306a36Sopenharmony_ci * filtering, or because some other part of the kernel wrote an audit
205762306a36Sopenharmony_ci * message), then write out the syscall information.  In call cases,
205862306a36Sopenharmony_ci * free the names stored from getname().
205962306a36Sopenharmony_ci */
206062306a36Sopenharmony_civoid __audit_syscall_exit(int success, long return_code)
206162306a36Sopenharmony_ci{
206262306a36Sopenharmony_ci	struct audit_context *context = audit_context();
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	if (!context || context->dummy ||
206562306a36Sopenharmony_ci	    context->context != AUDIT_CTX_SYSCALL)
206662306a36Sopenharmony_ci		goto out;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci	/* this may generate CONFIG_CHANGE records */
206962306a36Sopenharmony_ci	if (!list_empty(&context->killed_trees))
207062306a36Sopenharmony_ci		audit_kill_trees(context);
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci	audit_return_fixup(context, success, return_code);
207362306a36Sopenharmony_ci	/* run through both filters to ensure we set the filterkey properly */
207462306a36Sopenharmony_ci	audit_filter_syscall(current, context);
207562306a36Sopenharmony_ci	audit_filter_inodes(current, context);
207662306a36Sopenharmony_ci	if (context->current_state != AUDIT_STATE_RECORD)
207762306a36Sopenharmony_ci		goto out;
207862306a36Sopenharmony_ci
207962306a36Sopenharmony_ci	audit_log_exit();
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ciout:
208262306a36Sopenharmony_ci	audit_reset_context(context);
208362306a36Sopenharmony_ci}
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_cistatic inline void handle_one(const struct inode *inode)
208662306a36Sopenharmony_ci{
208762306a36Sopenharmony_ci	struct audit_context *context;
208862306a36Sopenharmony_ci	struct audit_tree_refs *p;
208962306a36Sopenharmony_ci	struct audit_chunk *chunk;
209062306a36Sopenharmony_ci	int count;
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	if (likely(!inode->i_fsnotify_marks))
209362306a36Sopenharmony_ci		return;
209462306a36Sopenharmony_ci	context = audit_context();
209562306a36Sopenharmony_ci	p = context->trees;
209662306a36Sopenharmony_ci	count = context->tree_count;
209762306a36Sopenharmony_ci	rcu_read_lock();
209862306a36Sopenharmony_ci	chunk = audit_tree_lookup(inode);
209962306a36Sopenharmony_ci	rcu_read_unlock();
210062306a36Sopenharmony_ci	if (!chunk)
210162306a36Sopenharmony_ci		return;
210262306a36Sopenharmony_ci	if (likely(put_tree_ref(context, chunk)))
210362306a36Sopenharmony_ci		return;
210462306a36Sopenharmony_ci	if (unlikely(!grow_tree_refs(context))) {
210562306a36Sopenharmony_ci		pr_warn("out of memory, audit has lost a tree reference\n");
210662306a36Sopenharmony_ci		audit_set_auditable(context);
210762306a36Sopenharmony_ci		audit_put_chunk(chunk);
210862306a36Sopenharmony_ci		unroll_tree_refs(context, p, count);
210962306a36Sopenharmony_ci		return;
211062306a36Sopenharmony_ci	}
211162306a36Sopenharmony_ci	put_tree_ref(context, chunk);
211262306a36Sopenharmony_ci}
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_cistatic void handle_path(const struct dentry *dentry)
211562306a36Sopenharmony_ci{
211662306a36Sopenharmony_ci	struct audit_context *context;
211762306a36Sopenharmony_ci	struct audit_tree_refs *p;
211862306a36Sopenharmony_ci	const struct dentry *d, *parent;
211962306a36Sopenharmony_ci	struct audit_chunk *drop;
212062306a36Sopenharmony_ci	unsigned long seq;
212162306a36Sopenharmony_ci	int count;
212262306a36Sopenharmony_ci
212362306a36Sopenharmony_ci	context = audit_context();
212462306a36Sopenharmony_ci	p = context->trees;
212562306a36Sopenharmony_ci	count = context->tree_count;
212662306a36Sopenharmony_ciretry:
212762306a36Sopenharmony_ci	drop = NULL;
212862306a36Sopenharmony_ci	d = dentry;
212962306a36Sopenharmony_ci	rcu_read_lock();
213062306a36Sopenharmony_ci	seq = read_seqbegin(&rename_lock);
213162306a36Sopenharmony_ci	for (;;) {
213262306a36Sopenharmony_ci		struct inode *inode = d_backing_inode(d);
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ci		if (inode && unlikely(inode->i_fsnotify_marks)) {
213562306a36Sopenharmony_ci			struct audit_chunk *chunk;
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci			chunk = audit_tree_lookup(inode);
213862306a36Sopenharmony_ci			if (chunk) {
213962306a36Sopenharmony_ci				if (unlikely(!put_tree_ref(context, chunk))) {
214062306a36Sopenharmony_ci					drop = chunk;
214162306a36Sopenharmony_ci					break;
214262306a36Sopenharmony_ci				}
214362306a36Sopenharmony_ci			}
214462306a36Sopenharmony_ci		}
214562306a36Sopenharmony_ci		parent = d->d_parent;
214662306a36Sopenharmony_ci		if (parent == d)
214762306a36Sopenharmony_ci			break;
214862306a36Sopenharmony_ci		d = parent;
214962306a36Sopenharmony_ci	}
215062306a36Sopenharmony_ci	if (unlikely(read_seqretry(&rename_lock, seq) || drop)) {  /* in this order */
215162306a36Sopenharmony_ci		rcu_read_unlock();
215262306a36Sopenharmony_ci		if (!drop) {
215362306a36Sopenharmony_ci			/* just a race with rename */
215462306a36Sopenharmony_ci			unroll_tree_refs(context, p, count);
215562306a36Sopenharmony_ci			goto retry;
215662306a36Sopenharmony_ci		}
215762306a36Sopenharmony_ci		audit_put_chunk(drop);
215862306a36Sopenharmony_ci		if (grow_tree_refs(context)) {
215962306a36Sopenharmony_ci			/* OK, got more space */
216062306a36Sopenharmony_ci			unroll_tree_refs(context, p, count);
216162306a36Sopenharmony_ci			goto retry;
216262306a36Sopenharmony_ci		}
216362306a36Sopenharmony_ci		/* too bad */
216462306a36Sopenharmony_ci		pr_warn("out of memory, audit has lost a tree reference\n");
216562306a36Sopenharmony_ci		unroll_tree_refs(context, p, count);
216662306a36Sopenharmony_ci		audit_set_auditable(context);
216762306a36Sopenharmony_ci		return;
216862306a36Sopenharmony_ci	}
216962306a36Sopenharmony_ci	rcu_read_unlock();
217062306a36Sopenharmony_ci}
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_cistatic struct audit_names *audit_alloc_name(struct audit_context *context,
217362306a36Sopenharmony_ci						unsigned char type)
217462306a36Sopenharmony_ci{
217562306a36Sopenharmony_ci	struct audit_names *aname;
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci	if (context->name_count < AUDIT_NAMES) {
217862306a36Sopenharmony_ci		aname = &context->preallocated_names[context->name_count];
217962306a36Sopenharmony_ci		memset(aname, 0, sizeof(*aname));
218062306a36Sopenharmony_ci	} else {
218162306a36Sopenharmony_ci		aname = kzalloc(sizeof(*aname), GFP_NOFS);
218262306a36Sopenharmony_ci		if (!aname)
218362306a36Sopenharmony_ci			return NULL;
218462306a36Sopenharmony_ci		aname->should_free = true;
218562306a36Sopenharmony_ci	}
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci	aname->ino = AUDIT_INO_UNSET;
218862306a36Sopenharmony_ci	aname->type = type;
218962306a36Sopenharmony_ci	list_add_tail(&aname->list, &context->names_list);
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci	context->name_count++;
219262306a36Sopenharmony_ci	if (!context->pwd.dentry)
219362306a36Sopenharmony_ci		get_fs_pwd(current->fs, &context->pwd);
219462306a36Sopenharmony_ci	return aname;
219562306a36Sopenharmony_ci}
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci/**
219862306a36Sopenharmony_ci * __audit_reusename - fill out filename with info from existing entry
219962306a36Sopenharmony_ci * @uptr: userland ptr to pathname
220062306a36Sopenharmony_ci *
220162306a36Sopenharmony_ci * Search the audit_names list for the current audit context. If there is an
220262306a36Sopenharmony_ci * existing entry with a matching "uptr" then return the filename
220362306a36Sopenharmony_ci * associated with that audit_name. If not, return NULL.
220462306a36Sopenharmony_ci */
220562306a36Sopenharmony_cistruct filename *
220662306a36Sopenharmony_ci__audit_reusename(const __user char *uptr)
220762306a36Sopenharmony_ci{
220862306a36Sopenharmony_ci	struct audit_context *context = audit_context();
220962306a36Sopenharmony_ci	struct audit_names *n;
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci	list_for_each_entry(n, &context->names_list, list) {
221262306a36Sopenharmony_ci		if (!n->name)
221362306a36Sopenharmony_ci			continue;
221462306a36Sopenharmony_ci		if (n->name->uptr == uptr) {
221562306a36Sopenharmony_ci			atomic_inc(&n->name->refcnt);
221662306a36Sopenharmony_ci			return n->name;
221762306a36Sopenharmony_ci		}
221862306a36Sopenharmony_ci	}
221962306a36Sopenharmony_ci	return NULL;
222062306a36Sopenharmony_ci}
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci/**
222362306a36Sopenharmony_ci * __audit_getname - add a name to the list
222462306a36Sopenharmony_ci * @name: name to add
222562306a36Sopenharmony_ci *
222662306a36Sopenharmony_ci * Add a name to the list of audit names for this context.
222762306a36Sopenharmony_ci * Called from fs/namei.c:getname().
222862306a36Sopenharmony_ci */
222962306a36Sopenharmony_civoid __audit_getname(struct filename *name)
223062306a36Sopenharmony_ci{
223162306a36Sopenharmony_ci	struct audit_context *context = audit_context();
223262306a36Sopenharmony_ci	struct audit_names *n;
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci	if (context->context == AUDIT_CTX_UNUSED)
223562306a36Sopenharmony_ci		return;
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
223862306a36Sopenharmony_ci	if (!n)
223962306a36Sopenharmony_ci		return;
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	n->name = name;
224262306a36Sopenharmony_ci	n->name_len = AUDIT_NAME_FULL;
224362306a36Sopenharmony_ci	name->aname = n;
224462306a36Sopenharmony_ci	atomic_inc(&name->refcnt);
224562306a36Sopenharmony_ci}
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_cistatic inline int audit_copy_fcaps(struct audit_names *name,
224862306a36Sopenharmony_ci				   const struct dentry *dentry)
224962306a36Sopenharmony_ci{
225062306a36Sopenharmony_ci	struct cpu_vfs_cap_data caps;
225162306a36Sopenharmony_ci	int rc;
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_ci	if (!dentry)
225462306a36Sopenharmony_ci		return 0;
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci	rc = get_vfs_caps_from_disk(&nop_mnt_idmap, dentry, &caps);
225762306a36Sopenharmony_ci	if (rc)
225862306a36Sopenharmony_ci		return rc;
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci	name->fcap.permitted = caps.permitted;
226162306a36Sopenharmony_ci	name->fcap.inheritable = caps.inheritable;
226262306a36Sopenharmony_ci	name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
226362306a36Sopenharmony_ci	name->fcap.rootid = caps.rootid;
226462306a36Sopenharmony_ci	name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
226562306a36Sopenharmony_ci				VFS_CAP_REVISION_SHIFT;
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	return 0;
226862306a36Sopenharmony_ci}
226962306a36Sopenharmony_ci
227062306a36Sopenharmony_ci/* Copy inode data into an audit_names. */
227162306a36Sopenharmony_cistatic void audit_copy_inode(struct audit_names *name,
227262306a36Sopenharmony_ci			     const struct dentry *dentry,
227362306a36Sopenharmony_ci			     struct inode *inode, unsigned int flags)
227462306a36Sopenharmony_ci{
227562306a36Sopenharmony_ci	name->ino   = inode->i_ino;
227662306a36Sopenharmony_ci	name->dev   = inode->i_sb->s_dev;
227762306a36Sopenharmony_ci	name->mode  = inode->i_mode;
227862306a36Sopenharmony_ci	name->uid   = inode->i_uid;
227962306a36Sopenharmony_ci	name->gid   = inode->i_gid;
228062306a36Sopenharmony_ci	name->rdev  = inode->i_rdev;
228162306a36Sopenharmony_ci	security_inode_getsecid(inode, &name->osid);
228262306a36Sopenharmony_ci	if (flags & AUDIT_INODE_NOEVAL) {
228362306a36Sopenharmony_ci		name->fcap_ver = -1;
228462306a36Sopenharmony_ci		return;
228562306a36Sopenharmony_ci	}
228662306a36Sopenharmony_ci	audit_copy_fcaps(name, dentry);
228762306a36Sopenharmony_ci}
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci/**
229062306a36Sopenharmony_ci * __audit_inode - store the inode and device from a lookup
229162306a36Sopenharmony_ci * @name: name being audited
229262306a36Sopenharmony_ci * @dentry: dentry being audited
229362306a36Sopenharmony_ci * @flags: attributes for this particular entry
229462306a36Sopenharmony_ci */
229562306a36Sopenharmony_civoid __audit_inode(struct filename *name, const struct dentry *dentry,
229662306a36Sopenharmony_ci		   unsigned int flags)
229762306a36Sopenharmony_ci{
229862306a36Sopenharmony_ci	struct audit_context *context = audit_context();
229962306a36Sopenharmony_ci	struct inode *inode = d_backing_inode(dentry);
230062306a36Sopenharmony_ci	struct audit_names *n;
230162306a36Sopenharmony_ci	bool parent = flags & AUDIT_INODE_PARENT;
230262306a36Sopenharmony_ci	struct audit_entry *e;
230362306a36Sopenharmony_ci	struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
230462306a36Sopenharmony_ci	int i;
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_ci	if (context->context == AUDIT_CTX_UNUSED)
230762306a36Sopenharmony_ci		return;
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_ci	rcu_read_lock();
231062306a36Sopenharmony_ci	list_for_each_entry_rcu(e, list, list) {
231162306a36Sopenharmony_ci		for (i = 0; i < e->rule.field_count; i++) {
231262306a36Sopenharmony_ci			struct audit_field *f = &e->rule.fields[i];
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_ci			if (f->type == AUDIT_FSTYPE
231562306a36Sopenharmony_ci			    && audit_comparator(inode->i_sb->s_magic,
231662306a36Sopenharmony_ci						f->op, f->val)
231762306a36Sopenharmony_ci			    && e->rule.action == AUDIT_NEVER) {
231862306a36Sopenharmony_ci				rcu_read_unlock();
231962306a36Sopenharmony_ci				return;
232062306a36Sopenharmony_ci			}
232162306a36Sopenharmony_ci		}
232262306a36Sopenharmony_ci	}
232362306a36Sopenharmony_ci	rcu_read_unlock();
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	if (!name)
232662306a36Sopenharmony_ci		goto out_alloc;
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci	/*
232962306a36Sopenharmony_ci	 * If we have a pointer to an audit_names entry already, then we can
233062306a36Sopenharmony_ci	 * just use it directly if the type is correct.
233162306a36Sopenharmony_ci	 */
233262306a36Sopenharmony_ci	n = name->aname;
233362306a36Sopenharmony_ci	if (n) {
233462306a36Sopenharmony_ci		if (parent) {
233562306a36Sopenharmony_ci			if (n->type == AUDIT_TYPE_PARENT ||
233662306a36Sopenharmony_ci			    n->type == AUDIT_TYPE_UNKNOWN)
233762306a36Sopenharmony_ci				goto out;
233862306a36Sopenharmony_ci		} else {
233962306a36Sopenharmony_ci			if (n->type != AUDIT_TYPE_PARENT)
234062306a36Sopenharmony_ci				goto out;
234162306a36Sopenharmony_ci		}
234262306a36Sopenharmony_ci	}
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci	list_for_each_entry_reverse(n, &context->names_list, list) {
234562306a36Sopenharmony_ci		if (n->ino) {
234662306a36Sopenharmony_ci			/* valid inode number, use that for the comparison */
234762306a36Sopenharmony_ci			if (n->ino != inode->i_ino ||
234862306a36Sopenharmony_ci			    n->dev != inode->i_sb->s_dev)
234962306a36Sopenharmony_ci				continue;
235062306a36Sopenharmony_ci		} else if (n->name) {
235162306a36Sopenharmony_ci			/* inode number has not been set, check the name */
235262306a36Sopenharmony_ci			if (strcmp(n->name->name, name->name))
235362306a36Sopenharmony_ci				continue;
235462306a36Sopenharmony_ci		} else
235562306a36Sopenharmony_ci			/* no inode and no name (?!) ... this is odd ... */
235662306a36Sopenharmony_ci			continue;
235762306a36Sopenharmony_ci
235862306a36Sopenharmony_ci		/* match the correct record type */
235962306a36Sopenharmony_ci		if (parent) {
236062306a36Sopenharmony_ci			if (n->type == AUDIT_TYPE_PARENT ||
236162306a36Sopenharmony_ci			    n->type == AUDIT_TYPE_UNKNOWN)
236262306a36Sopenharmony_ci				goto out;
236362306a36Sopenharmony_ci		} else {
236462306a36Sopenharmony_ci			if (n->type != AUDIT_TYPE_PARENT)
236562306a36Sopenharmony_ci				goto out;
236662306a36Sopenharmony_ci		}
236762306a36Sopenharmony_ci	}
236862306a36Sopenharmony_ci
236962306a36Sopenharmony_ciout_alloc:
237062306a36Sopenharmony_ci	/* unable to find an entry with both a matching name and type */
237162306a36Sopenharmony_ci	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
237262306a36Sopenharmony_ci	if (!n)
237362306a36Sopenharmony_ci		return;
237462306a36Sopenharmony_ci	if (name) {
237562306a36Sopenharmony_ci		n->name = name;
237662306a36Sopenharmony_ci		atomic_inc(&name->refcnt);
237762306a36Sopenharmony_ci	}
237862306a36Sopenharmony_ci
237962306a36Sopenharmony_ciout:
238062306a36Sopenharmony_ci	if (parent) {
238162306a36Sopenharmony_ci		n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
238262306a36Sopenharmony_ci		n->type = AUDIT_TYPE_PARENT;
238362306a36Sopenharmony_ci		if (flags & AUDIT_INODE_HIDDEN)
238462306a36Sopenharmony_ci			n->hidden = true;
238562306a36Sopenharmony_ci	} else {
238662306a36Sopenharmony_ci		n->name_len = AUDIT_NAME_FULL;
238762306a36Sopenharmony_ci		n->type = AUDIT_TYPE_NORMAL;
238862306a36Sopenharmony_ci	}
238962306a36Sopenharmony_ci	handle_path(dentry);
239062306a36Sopenharmony_ci	audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL);
239162306a36Sopenharmony_ci}
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_civoid __audit_file(const struct file *file)
239462306a36Sopenharmony_ci{
239562306a36Sopenharmony_ci	__audit_inode(NULL, file->f_path.dentry, 0);
239662306a36Sopenharmony_ci}
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci/**
239962306a36Sopenharmony_ci * __audit_inode_child - collect inode info for created/removed objects
240062306a36Sopenharmony_ci * @parent: inode of dentry parent
240162306a36Sopenharmony_ci * @dentry: dentry being audited
240262306a36Sopenharmony_ci * @type:   AUDIT_TYPE_* value that we're looking for
240362306a36Sopenharmony_ci *
240462306a36Sopenharmony_ci * For syscalls that create or remove filesystem objects, audit_inode
240562306a36Sopenharmony_ci * can only collect information for the filesystem object's parent.
240662306a36Sopenharmony_ci * This call updates the audit context with the child's information.
240762306a36Sopenharmony_ci * Syscalls that create a new filesystem object must be hooked after
240862306a36Sopenharmony_ci * the object is created.  Syscalls that remove a filesystem object
240962306a36Sopenharmony_ci * must be hooked prior, in order to capture the target inode during
241062306a36Sopenharmony_ci * unsuccessful attempts.
241162306a36Sopenharmony_ci */
241262306a36Sopenharmony_civoid __audit_inode_child(struct inode *parent,
241362306a36Sopenharmony_ci			 const struct dentry *dentry,
241462306a36Sopenharmony_ci			 const unsigned char type)
241562306a36Sopenharmony_ci{
241662306a36Sopenharmony_ci	struct audit_context *context = audit_context();
241762306a36Sopenharmony_ci	struct inode *inode = d_backing_inode(dentry);
241862306a36Sopenharmony_ci	const struct qstr *dname = &dentry->d_name;
241962306a36Sopenharmony_ci	struct audit_names *n, *found_parent = NULL, *found_child = NULL;
242062306a36Sopenharmony_ci	struct audit_entry *e;
242162306a36Sopenharmony_ci	struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
242262306a36Sopenharmony_ci	int i;
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci	if (context->context == AUDIT_CTX_UNUSED)
242562306a36Sopenharmony_ci		return;
242662306a36Sopenharmony_ci
242762306a36Sopenharmony_ci	rcu_read_lock();
242862306a36Sopenharmony_ci	list_for_each_entry_rcu(e, list, list) {
242962306a36Sopenharmony_ci		for (i = 0; i < e->rule.field_count; i++) {
243062306a36Sopenharmony_ci			struct audit_field *f = &e->rule.fields[i];
243162306a36Sopenharmony_ci
243262306a36Sopenharmony_ci			if (f->type == AUDIT_FSTYPE
243362306a36Sopenharmony_ci			    && audit_comparator(parent->i_sb->s_magic,
243462306a36Sopenharmony_ci						f->op, f->val)
243562306a36Sopenharmony_ci			    && e->rule.action == AUDIT_NEVER) {
243662306a36Sopenharmony_ci				rcu_read_unlock();
243762306a36Sopenharmony_ci				return;
243862306a36Sopenharmony_ci			}
243962306a36Sopenharmony_ci		}
244062306a36Sopenharmony_ci	}
244162306a36Sopenharmony_ci	rcu_read_unlock();
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_ci	if (inode)
244462306a36Sopenharmony_ci		handle_one(inode);
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_ci	/* look for a parent entry first */
244762306a36Sopenharmony_ci	list_for_each_entry(n, &context->names_list, list) {
244862306a36Sopenharmony_ci		if (!n->name ||
244962306a36Sopenharmony_ci		    (n->type != AUDIT_TYPE_PARENT &&
245062306a36Sopenharmony_ci		     n->type != AUDIT_TYPE_UNKNOWN))
245162306a36Sopenharmony_ci			continue;
245262306a36Sopenharmony_ci
245362306a36Sopenharmony_ci		if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev &&
245462306a36Sopenharmony_ci		    !audit_compare_dname_path(dname,
245562306a36Sopenharmony_ci					      n->name->name, n->name_len)) {
245662306a36Sopenharmony_ci			if (n->type == AUDIT_TYPE_UNKNOWN)
245762306a36Sopenharmony_ci				n->type = AUDIT_TYPE_PARENT;
245862306a36Sopenharmony_ci			found_parent = n;
245962306a36Sopenharmony_ci			break;
246062306a36Sopenharmony_ci		}
246162306a36Sopenharmony_ci	}
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	cond_resched();
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_ci	/* is there a matching child entry? */
246662306a36Sopenharmony_ci	list_for_each_entry(n, &context->names_list, list) {
246762306a36Sopenharmony_ci		/* can only match entries that have a name */
246862306a36Sopenharmony_ci		if (!n->name ||
246962306a36Sopenharmony_ci		    (n->type != type && n->type != AUDIT_TYPE_UNKNOWN))
247062306a36Sopenharmony_ci			continue;
247162306a36Sopenharmony_ci
247262306a36Sopenharmony_ci		if (!strcmp(dname->name, n->name->name) ||
247362306a36Sopenharmony_ci		    !audit_compare_dname_path(dname, n->name->name,
247462306a36Sopenharmony_ci						found_parent ?
247562306a36Sopenharmony_ci						found_parent->name_len :
247662306a36Sopenharmony_ci						AUDIT_NAME_FULL)) {
247762306a36Sopenharmony_ci			if (n->type == AUDIT_TYPE_UNKNOWN)
247862306a36Sopenharmony_ci				n->type = type;
247962306a36Sopenharmony_ci			found_child = n;
248062306a36Sopenharmony_ci			break;
248162306a36Sopenharmony_ci		}
248262306a36Sopenharmony_ci	}
248362306a36Sopenharmony_ci
248462306a36Sopenharmony_ci	if (!found_parent) {
248562306a36Sopenharmony_ci		/* create a new, "anonymous" parent record */
248662306a36Sopenharmony_ci		n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
248762306a36Sopenharmony_ci		if (!n)
248862306a36Sopenharmony_ci			return;
248962306a36Sopenharmony_ci		audit_copy_inode(n, NULL, parent, 0);
249062306a36Sopenharmony_ci	}
249162306a36Sopenharmony_ci
249262306a36Sopenharmony_ci	if (!found_child) {
249362306a36Sopenharmony_ci		found_child = audit_alloc_name(context, type);
249462306a36Sopenharmony_ci		if (!found_child)
249562306a36Sopenharmony_ci			return;
249662306a36Sopenharmony_ci
249762306a36Sopenharmony_ci		/* Re-use the name belonging to the slot for a matching parent
249862306a36Sopenharmony_ci		 * directory. All names for this context are relinquished in
249962306a36Sopenharmony_ci		 * audit_free_names() */
250062306a36Sopenharmony_ci		if (found_parent) {
250162306a36Sopenharmony_ci			found_child->name = found_parent->name;
250262306a36Sopenharmony_ci			found_child->name_len = AUDIT_NAME_FULL;
250362306a36Sopenharmony_ci			atomic_inc(&found_child->name->refcnt);
250462306a36Sopenharmony_ci		}
250562306a36Sopenharmony_ci	}
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_ci	if (inode)
250862306a36Sopenharmony_ci		audit_copy_inode(found_child, dentry, inode, 0);
250962306a36Sopenharmony_ci	else
251062306a36Sopenharmony_ci		found_child->ino = AUDIT_INO_UNSET;
251162306a36Sopenharmony_ci}
251262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__audit_inode_child);
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_ci/**
251562306a36Sopenharmony_ci * auditsc_get_stamp - get local copies of audit_context values
251662306a36Sopenharmony_ci * @ctx: audit_context for the task
251762306a36Sopenharmony_ci * @t: timespec64 to store time recorded in the audit_context
251862306a36Sopenharmony_ci * @serial: serial value that is recorded in the audit_context
251962306a36Sopenharmony_ci *
252062306a36Sopenharmony_ci * Also sets the context as auditable.
252162306a36Sopenharmony_ci */
252262306a36Sopenharmony_ciint auditsc_get_stamp(struct audit_context *ctx,
252362306a36Sopenharmony_ci		       struct timespec64 *t, unsigned int *serial)
252462306a36Sopenharmony_ci{
252562306a36Sopenharmony_ci	if (ctx->context == AUDIT_CTX_UNUSED)
252662306a36Sopenharmony_ci		return 0;
252762306a36Sopenharmony_ci	if (!ctx->serial)
252862306a36Sopenharmony_ci		ctx->serial = audit_serial();
252962306a36Sopenharmony_ci	t->tv_sec  = ctx->ctime.tv_sec;
253062306a36Sopenharmony_ci	t->tv_nsec = ctx->ctime.tv_nsec;
253162306a36Sopenharmony_ci	*serial    = ctx->serial;
253262306a36Sopenharmony_ci	if (!ctx->prio) {
253362306a36Sopenharmony_ci		ctx->prio = 1;
253462306a36Sopenharmony_ci		ctx->current_state = AUDIT_STATE_RECORD;
253562306a36Sopenharmony_ci	}
253662306a36Sopenharmony_ci	return 1;
253762306a36Sopenharmony_ci}
253862306a36Sopenharmony_ci
253962306a36Sopenharmony_ci/**
254062306a36Sopenharmony_ci * __audit_mq_open - record audit data for a POSIX MQ open
254162306a36Sopenharmony_ci * @oflag: open flag
254262306a36Sopenharmony_ci * @mode: mode bits
254362306a36Sopenharmony_ci * @attr: queue attributes
254462306a36Sopenharmony_ci *
254562306a36Sopenharmony_ci */
254662306a36Sopenharmony_civoid __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
254762306a36Sopenharmony_ci{
254862306a36Sopenharmony_ci	struct audit_context *context = audit_context();
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	if (attr)
255162306a36Sopenharmony_ci		memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr));
255262306a36Sopenharmony_ci	else
255362306a36Sopenharmony_ci		memset(&context->mq_open.attr, 0, sizeof(struct mq_attr));
255462306a36Sopenharmony_ci
255562306a36Sopenharmony_ci	context->mq_open.oflag = oflag;
255662306a36Sopenharmony_ci	context->mq_open.mode = mode;
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	context->type = AUDIT_MQ_OPEN;
255962306a36Sopenharmony_ci}
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci/**
256262306a36Sopenharmony_ci * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive
256362306a36Sopenharmony_ci * @mqdes: MQ descriptor
256462306a36Sopenharmony_ci * @msg_len: Message length
256562306a36Sopenharmony_ci * @msg_prio: Message priority
256662306a36Sopenharmony_ci * @abs_timeout: Message timeout in absolute time
256762306a36Sopenharmony_ci *
256862306a36Sopenharmony_ci */
256962306a36Sopenharmony_civoid __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
257062306a36Sopenharmony_ci			const struct timespec64 *abs_timeout)
257162306a36Sopenharmony_ci{
257262306a36Sopenharmony_ci	struct audit_context *context = audit_context();
257362306a36Sopenharmony_ci	struct timespec64 *p = &context->mq_sendrecv.abs_timeout;
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ci	if (abs_timeout)
257662306a36Sopenharmony_ci		memcpy(p, abs_timeout, sizeof(*p));
257762306a36Sopenharmony_ci	else
257862306a36Sopenharmony_ci		memset(p, 0, sizeof(*p));
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_ci	context->mq_sendrecv.mqdes = mqdes;
258162306a36Sopenharmony_ci	context->mq_sendrecv.msg_len = msg_len;
258262306a36Sopenharmony_ci	context->mq_sendrecv.msg_prio = msg_prio;
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci	context->type = AUDIT_MQ_SENDRECV;
258562306a36Sopenharmony_ci}
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci/**
258862306a36Sopenharmony_ci * __audit_mq_notify - record audit data for a POSIX MQ notify
258962306a36Sopenharmony_ci * @mqdes: MQ descriptor
259062306a36Sopenharmony_ci * @notification: Notification event
259162306a36Sopenharmony_ci *
259262306a36Sopenharmony_ci */
259362306a36Sopenharmony_ci
259462306a36Sopenharmony_civoid __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
259562306a36Sopenharmony_ci{
259662306a36Sopenharmony_ci	struct audit_context *context = audit_context();
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	if (notification)
259962306a36Sopenharmony_ci		context->mq_notify.sigev_signo = notification->sigev_signo;
260062306a36Sopenharmony_ci	else
260162306a36Sopenharmony_ci		context->mq_notify.sigev_signo = 0;
260262306a36Sopenharmony_ci
260362306a36Sopenharmony_ci	context->mq_notify.mqdes = mqdes;
260462306a36Sopenharmony_ci	context->type = AUDIT_MQ_NOTIFY;
260562306a36Sopenharmony_ci}
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_ci/**
260862306a36Sopenharmony_ci * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
260962306a36Sopenharmony_ci * @mqdes: MQ descriptor
261062306a36Sopenharmony_ci * @mqstat: MQ flags
261162306a36Sopenharmony_ci *
261262306a36Sopenharmony_ci */
261362306a36Sopenharmony_civoid __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
261462306a36Sopenharmony_ci{
261562306a36Sopenharmony_ci	struct audit_context *context = audit_context();
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_ci	context->mq_getsetattr.mqdes = mqdes;
261862306a36Sopenharmony_ci	context->mq_getsetattr.mqstat = *mqstat;
261962306a36Sopenharmony_ci	context->type = AUDIT_MQ_GETSETATTR;
262062306a36Sopenharmony_ci}
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ci/**
262362306a36Sopenharmony_ci * __audit_ipc_obj - record audit data for ipc object
262462306a36Sopenharmony_ci * @ipcp: ipc permissions
262562306a36Sopenharmony_ci *
262662306a36Sopenharmony_ci */
262762306a36Sopenharmony_civoid __audit_ipc_obj(struct kern_ipc_perm *ipcp)
262862306a36Sopenharmony_ci{
262962306a36Sopenharmony_ci	struct audit_context *context = audit_context();
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci	context->ipc.uid = ipcp->uid;
263262306a36Sopenharmony_ci	context->ipc.gid = ipcp->gid;
263362306a36Sopenharmony_ci	context->ipc.mode = ipcp->mode;
263462306a36Sopenharmony_ci	context->ipc.has_perm = 0;
263562306a36Sopenharmony_ci	security_ipc_getsecid(ipcp, &context->ipc.osid);
263662306a36Sopenharmony_ci	context->type = AUDIT_IPC;
263762306a36Sopenharmony_ci}
263862306a36Sopenharmony_ci
263962306a36Sopenharmony_ci/**
264062306a36Sopenharmony_ci * __audit_ipc_set_perm - record audit data for new ipc permissions
264162306a36Sopenharmony_ci * @qbytes: msgq bytes
264262306a36Sopenharmony_ci * @uid: msgq user id
264362306a36Sopenharmony_ci * @gid: msgq group id
264462306a36Sopenharmony_ci * @mode: msgq mode (permissions)
264562306a36Sopenharmony_ci *
264662306a36Sopenharmony_ci * Called only after audit_ipc_obj().
264762306a36Sopenharmony_ci */
264862306a36Sopenharmony_civoid __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode)
264962306a36Sopenharmony_ci{
265062306a36Sopenharmony_ci	struct audit_context *context = audit_context();
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci	context->ipc.qbytes = qbytes;
265362306a36Sopenharmony_ci	context->ipc.perm_uid = uid;
265462306a36Sopenharmony_ci	context->ipc.perm_gid = gid;
265562306a36Sopenharmony_ci	context->ipc.perm_mode = mode;
265662306a36Sopenharmony_ci	context->ipc.has_perm = 1;
265762306a36Sopenharmony_ci}
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_civoid __audit_bprm(struct linux_binprm *bprm)
266062306a36Sopenharmony_ci{
266162306a36Sopenharmony_ci	struct audit_context *context = audit_context();
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_ci	context->type = AUDIT_EXECVE;
266462306a36Sopenharmony_ci	context->execve.argc = bprm->argc;
266562306a36Sopenharmony_ci}
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_ci
266862306a36Sopenharmony_ci/**
266962306a36Sopenharmony_ci * __audit_socketcall - record audit data for sys_socketcall
267062306a36Sopenharmony_ci * @nargs: number of args, which should not be more than AUDITSC_ARGS.
267162306a36Sopenharmony_ci * @args: args array
267262306a36Sopenharmony_ci *
267362306a36Sopenharmony_ci */
267462306a36Sopenharmony_ciint __audit_socketcall(int nargs, unsigned long *args)
267562306a36Sopenharmony_ci{
267662306a36Sopenharmony_ci	struct audit_context *context = audit_context();
267762306a36Sopenharmony_ci
267862306a36Sopenharmony_ci	if (nargs <= 0 || nargs > AUDITSC_ARGS || !args)
267962306a36Sopenharmony_ci		return -EINVAL;
268062306a36Sopenharmony_ci	context->type = AUDIT_SOCKETCALL;
268162306a36Sopenharmony_ci	context->socketcall.nargs = nargs;
268262306a36Sopenharmony_ci	memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
268362306a36Sopenharmony_ci	return 0;
268462306a36Sopenharmony_ci}
268562306a36Sopenharmony_ci
268662306a36Sopenharmony_ci/**
268762306a36Sopenharmony_ci * __audit_fd_pair - record audit data for pipe and socketpair
268862306a36Sopenharmony_ci * @fd1: the first file descriptor
268962306a36Sopenharmony_ci * @fd2: the second file descriptor
269062306a36Sopenharmony_ci *
269162306a36Sopenharmony_ci */
269262306a36Sopenharmony_civoid __audit_fd_pair(int fd1, int fd2)
269362306a36Sopenharmony_ci{
269462306a36Sopenharmony_ci	struct audit_context *context = audit_context();
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	context->fds[0] = fd1;
269762306a36Sopenharmony_ci	context->fds[1] = fd2;
269862306a36Sopenharmony_ci}
269962306a36Sopenharmony_ci
270062306a36Sopenharmony_ci/**
270162306a36Sopenharmony_ci * __audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
270262306a36Sopenharmony_ci * @len: data length in user space
270362306a36Sopenharmony_ci * @a: data address in kernel space
270462306a36Sopenharmony_ci *
270562306a36Sopenharmony_ci * Returns 0 for success or NULL context or < 0 on error.
270662306a36Sopenharmony_ci */
270762306a36Sopenharmony_ciint __audit_sockaddr(int len, void *a)
270862306a36Sopenharmony_ci{
270962306a36Sopenharmony_ci	struct audit_context *context = audit_context();
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci	if (!context->sockaddr) {
271262306a36Sopenharmony_ci		void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_ci		if (!p)
271562306a36Sopenharmony_ci			return -ENOMEM;
271662306a36Sopenharmony_ci		context->sockaddr = p;
271762306a36Sopenharmony_ci	}
271862306a36Sopenharmony_ci
271962306a36Sopenharmony_ci	context->sockaddr_len = len;
272062306a36Sopenharmony_ci	memcpy(context->sockaddr, a, len);
272162306a36Sopenharmony_ci	return 0;
272262306a36Sopenharmony_ci}
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_civoid __audit_ptrace(struct task_struct *t)
272562306a36Sopenharmony_ci{
272662306a36Sopenharmony_ci	struct audit_context *context = audit_context();
272762306a36Sopenharmony_ci
272862306a36Sopenharmony_ci	context->target_pid = task_tgid_nr(t);
272962306a36Sopenharmony_ci	context->target_auid = audit_get_loginuid(t);
273062306a36Sopenharmony_ci	context->target_uid = task_uid(t);
273162306a36Sopenharmony_ci	context->target_sessionid = audit_get_sessionid(t);
273262306a36Sopenharmony_ci	security_task_getsecid_obj(t, &context->target_sid);
273362306a36Sopenharmony_ci	memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
273462306a36Sopenharmony_ci}
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci/**
273762306a36Sopenharmony_ci * audit_signal_info_syscall - record signal info for syscalls
273862306a36Sopenharmony_ci * @t: task being signaled
273962306a36Sopenharmony_ci *
274062306a36Sopenharmony_ci * If the audit subsystem is being terminated, record the task (pid)
274162306a36Sopenharmony_ci * and uid that is doing that.
274262306a36Sopenharmony_ci */
274362306a36Sopenharmony_ciint audit_signal_info_syscall(struct task_struct *t)
274462306a36Sopenharmony_ci{
274562306a36Sopenharmony_ci	struct audit_aux_data_pids *axp;
274662306a36Sopenharmony_ci	struct audit_context *ctx = audit_context();
274762306a36Sopenharmony_ci	kuid_t t_uid = task_uid(t);
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_ci	if (!audit_signals || audit_dummy_context())
275062306a36Sopenharmony_ci		return 0;
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	/* optimize the common case by putting first signal recipient directly
275362306a36Sopenharmony_ci	 * in audit_context */
275462306a36Sopenharmony_ci	if (!ctx->target_pid) {
275562306a36Sopenharmony_ci		ctx->target_pid = task_tgid_nr(t);
275662306a36Sopenharmony_ci		ctx->target_auid = audit_get_loginuid(t);
275762306a36Sopenharmony_ci		ctx->target_uid = t_uid;
275862306a36Sopenharmony_ci		ctx->target_sessionid = audit_get_sessionid(t);
275962306a36Sopenharmony_ci		security_task_getsecid_obj(t, &ctx->target_sid);
276062306a36Sopenharmony_ci		memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
276162306a36Sopenharmony_ci		return 0;
276262306a36Sopenharmony_ci	}
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci	axp = (void *)ctx->aux_pids;
276562306a36Sopenharmony_ci	if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
276662306a36Sopenharmony_ci		axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
276762306a36Sopenharmony_ci		if (!axp)
276862306a36Sopenharmony_ci			return -ENOMEM;
276962306a36Sopenharmony_ci
277062306a36Sopenharmony_ci		axp->d.type = AUDIT_OBJ_PID;
277162306a36Sopenharmony_ci		axp->d.next = ctx->aux_pids;
277262306a36Sopenharmony_ci		ctx->aux_pids = (void *)axp;
277362306a36Sopenharmony_ci	}
277462306a36Sopenharmony_ci	BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
277562306a36Sopenharmony_ci
277662306a36Sopenharmony_ci	axp->target_pid[axp->pid_count] = task_tgid_nr(t);
277762306a36Sopenharmony_ci	axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
277862306a36Sopenharmony_ci	axp->target_uid[axp->pid_count] = t_uid;
277962306a36Sopenharmony_ci	axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
278062306a36Sopenharmony_ci	security_task_getsecid_obj(t, &axp->target_sid[axp->pid_count]);
278162306a36Sopenharmony_ci	memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
278262306a36Sopenharmony_ci	axp->pid_count++;
278362306a36Sopenharmony_ci
278462306a36Sopenharmony_ci	return 0;
278562306a36Sopenharmony_ci}
278662306a36Sopenharmony_ci
278762306a36Sopenharmony_ci/**
278862306a36Sopenharmony_ci * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps
278962306a36Sopenharmony_ci * @bprm: pointer to the bprm being processed
279062306a36Sopenharmony_ci * @new: the proposed new credentials
279162306a36Sopenharmony_ci * @old: the old credentials
279262306a36Sopenharmony_ci *
279362306a36Sopenharmony_ci * Simply check if the proc already has the caps given by the file and if not
279462306a36Sopenharmony_ci * store the priv escalation info for later auditing at the end of the syscall
279562306a36Sopenharmony_ci *
279662306a36Sopenharmony_ci * -Eric
279762306a36Sopenharmony_ci */
279862306a36Sopenharmony_ciint __audit_log_bprm_fcaps(struct linux_binprm *bprm,
279962306a36Sopenharmony_ci			   const struct cred *new, const struct cred *old)
280062306a36Sopenharmony_ci{
280162306a36Sopenharmony_ci	struct audit_aux_data_bprm_fcaps *ax;
280262306a36Sopenharmony_ci	struct audit_context *context = audit_context();
280362306a36Sopenharmony_ci	struct cpu_vfs_cap_data vcaps;
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
280662306a36Sopenharmony_ci	if (!ax)
280762306a36Sopenharmony_ci		return -ENOMEM;
280862306a36Sopenharmony_ci
280962306a36Sopenharmony_ci	ax->d.type = AUDIT_BPRM_FCAPS;
281062306a36Sopenharmony_ci	ax->d.next = context->aux;
281162306a36Sopenharmony_ci	context->aux = (void *)ax;
281262306a36Sopenharmony_ci
281362306a36Sopenharmony_ci	get_vfs_caps_from_disk(&nop_mnt_idmap,
281462306a36Sopenharmony_ci			       bprm->file->f_path.dentry, &vcaps);
281562306a36Sopenharmony_ci
281662306a36Sopenharmony_ci	ax->fcap.permitted = vcaps.permitted;
281762306a36Sopenharmony_ci	ax->fcap.inheritable = vcaps.inheritable;
281862306a36Sopenharmony_ci	ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
281962306a36Sopenharmony_ci	ax->fcap.rootid = vcaps.rootid;
282062306a36Sopenharmony_ci	ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
282162306a36Sopenharmony_ci
282262306a36Sopenharmony_ci	ax->old_pcap.permitted   = old->cap_permitted;
282362306a36Sopenharmony_ci	ax->old_pcap.inheritable = old->cap_inheritable;
282462306a36Sopenharmony_ci	ax->old_pcap.effective   = old->cap_effective;
282562306a36Sopenharmony_ci	ax->old_pcap.ambient     = old->cap_ambient;
282662306a36Sopenharmony_ci
282762306a36Sopenharmony_ci	ax->new_pcap.permitted   = new->cap_permitted;
282862306a36Sopenharmony_ci	ax->new_pcap.inheritable = new->cap_inheritable;
282962306a36Sopenharmony_ci	ax->new_pcap.effective   = new->cap_effective;
283062306a36Sopenharmony_ci	ax->new_pcap.ambient     = new->cap_ambient;
283162306a36Sopenharmony_ci	return 0;
283262306a36Sopenharmony_ci}
283362306a36Sopenharmony_ci
283462306a36Sopenharmony_ci/**
283562306a36Sopenharmony_ci * __audit_log_capset - store information about the arguments to the capset syscall
283662306a36Sopenharmony_ci * @new: the new credentials
283762306a36Sopenharmony_ci * @old: the old (current) credentials
283862306a36Sopenharmony_ci *
283962306a36Sopenharmony_ci * Record the arguments userspace sent to sys_capset for later printing by the
284062306a36Sopenharmony_ci * audit system if applicable
284162306a36Sopenharmony_ci */
284262306a36Sopenharmony_civoid __audit_log_capset(const struct cred *new, const struct cred *old)
284362306a36Sopenharmony_ci{
284462306a36Sopenharmony_ci	struct audit_context *context = audit_context();
284562306a36Sopenharmony_ci
284662306a36Sopenharmony_ci	context->capset.pid = task_tgid_nr(current);
284762306a36Sopenharmony_ci	context->capset.cap.effective   = new->cap_effective;
284862306a36Sopenharmony_ci	context->capset.cap.inheritable = new->cap_effective;
284962306a36Sopenharmony_ci	context->capset.cap.permitted   = new->cap_permitted;
285062306a36Sopenharmony_ci	context->capset.cap.ambient     = new->cap_ambient;
285162306a36Sopenharmony_ci	context->type = AUDIT_CAPSET;
285262306a36Sopenharmony_ci}
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_civoid __audit_mmap_fd(int fd, int flags)
285562306a36Sopenharmony_ci{
285662306a36Sopenharmony_ci	struct audit_context *context = audit_context();
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci	context->mmap.fd = fd;
285962306a36Sopenharmony_ci	context->mmap.flags = flags;
286062306a36Sopenharmony_ci	context->type = AUDIT_MMAP;
286162306a36Sopenharmony_ci}
286262306a36Sopenharmony_ci
286362306a36Sopenharmony_civoid __audit_openat2_how(struct open_how *how)
286462306a36Sopenharmony_ci{
286562306a36Sopenharmony_ci	struct audit_context *context = audit_context();
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	context->openat2.flags = how->flags;
286862306a36Sopenharmony_ci	context->openat2.mode = how->mode;
286962306a36Sopenharmony_ci	context->openat2.resolve = how->resolve;
287062306a36Sopenharmony_ci	context->type = AUDIT_OPENAT2;
287162306a36Sopenharmony_ci}
287262306a36Sopenharmony_ci
287362306a36Sopenharmony_civoid __audit_log_kern_module(char *name)
287462306a36Sopenharmony_ci{
287562306a36Sopenharmony_ci	struct audit_context *context = audit_context();
287662306a36Sopenharmony_ci
287762306a36Sopenharmony_ci	context->module.name = kstrdup(name, GFP_KERNEL);
287862306a36Sopenharmony_ci	if (!context->module.name)
287962306a36Sopenharmony_ci		audit_log_lost("out of memory in __audit_log_kern_module");
288062306a36Sopenharmony_ci	context->type = AUDIT_KERN_MODULE;
288162306a36Sopenharmony_ci}
288262306a36Sopenharmony_ci
288362306a36Sopenharmony_civoid __audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
288462306a36Sopenharmony_ci{
288562306a36Sopenharmony_ci	/* {subj,obj}_trust values are {0,1,2}: no,yes,unknown */
288662306a36Sopenharmony_ci	switch (friar->hdr.type) {
288762306a36Sopenharmony_ci	case FAN_RESPONSE_INFO_NONE:
288862306a36Sopenharmony_ci		audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
288962306a36Sopenharmony_ci			  "resp=%u fan_type=%u fan_info=0 subj_trust=2 obj_trust=2",
289062306a36Sopenharmony_ci			  response, FAN_RESPONSE_INFO_NONE);
289162306a36Sopenharmony_ci		break;
289262306a36Sopenharmony_ci	case FAN_RESPONSE_INFO_AUDIT_RULE:
289362306a36Sopenharmony_ci		audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
289462306a36Sopenharmony_ci			  "resp=%u fan_type=%u fan_info=%X subj_trust=%u obj_trust=%u",
289562306a36Sopenharmony_ci			  response, friar->hdr.type, friar->rule_number,
289662306a36Sopenharmony_ci			  friar->subj_trust, friar->obj_trust);
289762306a36Sopenharmony_ci	}
289862306a36Sopenharmony_ci}
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_civoid __audit_tk_injoffset(struct timespec64 offset)
290162306a36Sopenharmony_ci{
290262306a36Sopenharmony_ci	struct audit_context *context = audit_context();
290362306a36Sopenharmony_ci
290462306a36Sopenharmony_ci	/* only set type if not already set by NTP */
290562306a36Sopenharmony_ci	if (!context->type)
290662306a36Sopenharmony_ci		context->type = AUDIT_TIME_INJOFFSET;
290762306a36Sopenharmony_ci	memcpy(&context->time.tk_injoffset, &offset, sizeof(offset));
290862306a36Sopenharmony_ci}
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_civoid __audit_ntp_log(const struct audit_ntp_data *ad)
291162306a36Sopenharmony_ci{
291262306a36Sopenharmony_ci	struct audit_context *context = audit_context();
291362306a36Sopenharmony_ci	int type;
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_ci	for (type = 0; type < AUDIT_NTP_NVALS; type++)
291662306a36Sopenharmony_ci		if (ad->vals[type].newval != ad->vals[type].oldval) {
291762306a36Sopenharmony_ci			/* unconditionally set type, overwriting TK */
291862306a36Sopenharmony_ci			context->type = AUDIT_TIME_ADJNTPVAL;
291962306a36Sopenharmony_ci			memcpy(&context->time.ntp_data, ad, sizeof(*ad));
292062306a36Sopenharmony_ci			break;
292162306a36Sopenharmony_ci		}
292262306a36Sopenharmony_ci}
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_civoid __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
292562306a36Sopenharmony_ci		       enum audit_nfcfgop op, gfp_t gfp)
292662306a36Sopenharmony_ci{
292762306a36Sopenharmony_ci	struct audit_buffer *ab;
292862306a36Sopenharmony_ci	char comm[sizeof(current->comm)];
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_ci	ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG);
293162306a36Sopenharmony_ci	if (!ab)
293262306a36Sopenharmony_ci		return;
293362306a36Sopenharmony_ci	audit_log_format(ab, "table=%s family=%u entries=%u op=%s",
293462306a36Sopenharmony_ci			 name, af, nentries, audit_nfcfgs[op].s);
293562306a36Sopenharmony_ci
293662306a36Sopenharmony_ci	audit_log_format(ab, " pid=%u", task_pid_nr(current));
293762306a36Sopenharmony_ci	audit_log_task_context(ab); /* subj= */
293862306a36Sopenharmony_ci	audit_log_format(ab, " comm=");
293962306a36Sopenharmony_ci	audit_log_untrustedstring(ab, get_task_comm(comm, current));
294062306a36Sopenharmony_ci	audit_log_end(ab);
294162306a36Sopenharmony_ci}
294262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__audit_log_nfcfg);
294362306a36Sopenharmony_ci
294462306a36Sopenharmony_cistatic void audit_log_task(struct audit_buffer *ab)
294562306a36Sopenharmony_ci{
294662306a36Sopenharmony_ci	kuid_t auid, uid;
294762306a36Sopenharmony_ci	kgid_t gid;
294862306a36Sopenharmony_ci	unsigned int sessionid;
294962306a36Sopenharmony_ci	char comm[sizeof(current->comm)];
295062306a36Sopenharmony_ci
295162306a36Sopenharmony_ci	auid = audit_get_loginuid(current);
295262306a36Sopenharmony_ci	sessionid = audit_get_sessionid(current);
295362306a36Sopenharmony_ci	current_uid_gid(&uid, &gid);
295462306a36Sopenharmony_ci
295562306a36Sopenharmony_ci	audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
295662306a36Sopenharmony_ci			 from_kuid(&init_user_ns, auid),
295762306a36Sopenharmony_ci			 from_kuid(&init_user_ns, uid),
295862306a36Sopenharmony_ci			 from_kgid(&init_user_ns, gid),
295962306a36Sopenharmony_ci			 sessionid);
296062306a36Sopenharmony_ci	audit_log_task_context(ab);
296162306a36Sopenharmony_ci	audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
296262306a36Sopenharmony_ci	audit_log_untrustedstring(ab, get_task_comm(comm, current));
296362306a36Sopenharmony_ci	audit_log_d_path_exe(ab, current->mm);
296462306a36Sopenharmony_ci}
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci/**
296762306a36Sopenharmony_ci * audit_core_dumps - record information about processes that end abnormally
296862306a36Sopenharmony_ci * @signr: signal value
296962306a36Sopenharmony_ci *
297062306a36Sopenharmony_ci * If a process ends with a core dump, something fishy is going on and we
297162306a36Sopenharmony_ci * should record the event for investigation.
297262306a36Sopenharmony_ci */
297362306a36Sopenharmony_civoid audit_core_dumps(long signr)
297462306a36Sopenharmony_ci{
297562306a36Sopenharmony_ci	struct audit_buffer *ab;
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	if (!audit_enabled)
297862306a36Sopenharmony_ci		return;
297962306a36Sopenharmony_ci
298062306a36Sopenharmony_ci	if (signr == SIGQUIT)	/* don't care for those */
298162306a36Sopenharmony_ci		return;
298262306a36Sopenharmony_ci
298362306a36Sopenharmony_ci	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_ABEND);
298462306a36Sopenharmony_ci	if (unlikely(!ab))
298562306a36Sopenharmony_ci		return;
298662306a36Sopenharmony_ci	audit_log_task(ab);
298762306a36Sopenharmony_ci	audit_log_format(ab, " sig=%ld res=1", signr);
298862306a36Sopenharmony_ci	audit_log_end(ab);
298962306a36Sopenharmony_ci}
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci/**
299262306a36Sopenharmony_ci * audit_seccomp - record information about a seccomp action
299362306a36Sopenharmony_ci * @syscall: syscall number
299462306a36Sopenharmony_ci * @signr: signal value
299562306a36Sopenharmony_ci * @code: the seccomp action
299662306a36Sopenharmony_ci *
299762306a36Sopenharmony_ci * Record the information associated with a seccomp action. Event filtering for
299862306a36Sopenharmony_ci * seccomp actions that are not to be logged is done in seccomp_log().
299962306a36Sopenharmony_ci * Therefore, this function forces auditing independent of the audit_enabled
300062306a36Sopenharmony_ci * and dummy context state because seccomp actions should be logged even when
300162306a36Sopenharmony_ci * audit is not in use.
300262306a36Sopenharmony_ci */
300362306a36Sopenharmony_civoid audit_seccomp(unsigned long syscall, long signr, int code)
300462306a36Sopenharmony_ci{
300562306a36Sopenharmony_ci	struct audit_buffer *ab;
300662306a36Sopenharmony_ci
300762306a36Sopenharmony_ci	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_SECCOMP);
300862306a36Sopenharmony_ci	if (unlikely(!ab))
300962306a36Sopenharmony_ci		return;
301062306a36Sopenharmony_ci	audit_log_task(ab);
301162306a36Sopenharmony_ci	audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
301262306a36Sopenharmony_ci			 signr, syscall_get_arch(current), syscall,
301362306a36Sopenharmony_ci			 in_compat_syscall(), KSTK_EIP(current), code);
301462306a36Sopenharmony_ci	audit_log_end(ab);
301562306a36Sopenharmony_ci}
301662306a36Sopenharmony_ci
301762306a36Sopenharmony_civoid audit_seccomp_actions_logged(const char *names, const char *old_names,
301862306a36Sopenharmony_ci				  int res)
301962306a36Sopenharmony_ci{
302062306a36Sopenharmony_ci	struct audit_buffer *ab;
302162306a36Sopenharmony_ci
302262306a36Sopenharmony_ci	if (!audit_enabled)
302362306a36Sopenharmony_ci		return;
302462306a36Sopenharmony_ci
302562306a36Sopenharmony_ci	ab = audit_log_start(audit_context(), GFP_KERNEL,
302662306a36Sopenharmony_ci			     AUDIT_CONFIG_CHANGE);
302762306a36Sopenharmony_ci	if (unlikely(!ab))
302862306a36Sopenharmony_ci		return;
302962306a36Sopenharmony_ci
303062306a36Sopenharmony_ci	audit_log_format(ab,
303162306a36Sopenharmony_ci			 "op=seccomp-logging actions=%s old-actions=%s res=%d",
303262306a36Sopenharmony_ci			 names, old_names, res);
303362306a36Sopenharmony_ci	audit_log_end(ab);
303462306a36Sopenharmony_ci}
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_cistruct list_head *audit_killed_trees(void)
303762306a36Sopenharmony_ci{
303862306a36Sopenharmony_ci	struct audit_context *ctx = audit_context();
303962306a36Sopenharmony_ci	if (likely(!ctx || ctx->context == AUDIT_CTX_UNUSED))
304062306a36Sopenharmony_ci		return NULL;
304162306a36Sopenharmony_ci	return &ctx->killed_trees;
304262306a36Sopenharmony_ci}
3043