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