1d680c6b4SCai Huoqing // SPDX-License-Identifier: GPL-2.0-or-later
285c8721fS /* auditsc.c -- System-call auditing support
31da177e4SLinus Torvalds * Handles all system-call specific auditing features.
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
673241cccSAmy Griffis * Copyright 2005 Hewlett-Packard Development Company, L.P.
720ca73bcSGeorge C. Wilson * Copyright (C) 2005, 2006 IBM Corporation
81da177e4SLinus Torvalds * All Rights Reserved.
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * Written by Rickard E. (Rik) Faith <[email protected]>
111da177e4SLinus Torvalds *
121da177e4SLinus Torvalds * Many of the ideas implemented here are from Stephen C. Tweedie,
131da177e4SLinus Torvalds * especially the idea of avoiding a copy by using getname.
141da177e4SLinus Torvalds *
151da177e4SLinus Torvalds * The method for actual interception of syscall entry and exit (not in
161da177e4SLinus Torvalds * this file -- see entry.S) is based on a GPL'd patch written by
171da177e4SLinus Torvalds * [email protected] and Copyright 2003 SuSE Linux AG.
181da177e4SLinus Torvalds *
1920ca73bcSGeorge C. Wilson * POSIX message queue support added by George Wilson <[email protected]>,
2020ca73bcSGeorge C. Wilson * 2006.
2120ca73bcSGeorge C. Wilson *
22b63862f4SDustin Kirkland * The support of additional filter rules compares (>, <, >=, <=) was
23b63862f4SDustin Kirkland * added by Dustin Kirkland <[email protected]>, 2005.
24b63862f4SDustin Kirkland *
2573241cccSAmy Griffis * Modified by Amy Griffis <[email protected]> to collect additional
2673241cccSAmy Griffis * filesystem information.
278c8570fbSDustin Kirkland *
288c8570fbSDustin Kirkland * Subject and object context labeling support added by <[email protected]>
298c8570fbSDustin Kirkland * and <[email protected]> for LSPP certification compliance.
301da177e4SLinus Torvalds */
311da177e4SLinus Torvalds
32f952d10fSRichard Guy Briggs #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
33f952d10fSRichard Guy Briggs
341da177e4SLinus Torvalds #include <linux/init.h>
351da177e4SLinus Torvalds #include <asm/types.h>
3660063497SArun Sharma #include <linux/atomic.h>
3773241cccSAmy Griffis #include <linux/fs.h>
3873241cccSAmy Griffis #include <linux/namei.h>
391da177e4SLinus Torvalds #include <linux/mm.h>
409984de1aSPaul Gortmaker #include <linux/export.h>
415a0e3ad6STejun Heo #include <linux/slab.h>
4201116105SStephen Smalley #include <linux/mount.h>
433ec3b2fbSDavid Woodhouse #include <linux/socket.h>
4420ca73bcSGeorge C. Wilson #include <linux/mqueue.h>
451da177e4SLinus Torvalds #include <linux/audit.h>
461da177e4SLinus Torvalds #include <linux/personality.h>
471da177e4SLinus Torvalds #include <linux/time.h>
485bb289b5SDavid Woodhouse #include <linux/netlink.h>
49f5561964SDavid Woodhouse #include <linux/compiler.h>
501da177e4SLinus Torvalds #include <asm/unistd.h>
518c8570fbSDustin Kirkland #include <linux/security.h>
52fe7752baSDavid Woodhouse #include <linux/list.h>
53473ae30bSAl Viro #include <linux/binfmts.h>
54a1f8e7f7SAl Viro #include <linux/highmem.h>
55f46038ffSAl Viro #include <linux/syscalls.h>
5684db564aSRichard Guy Briggs #include <asm/syscall.h>
57851f7ff5SEric Paris #include <linux/capability.h>
585ad4e53bSAl Viro #include <linux/fs_struct.h>
593dc1c1b2SKees Cook #include <linux/compat.h>
603f1c8250SWilliam Roberts #include <linux/ctype.h>
61fcf22d82SPaul Moore #include <linux/string.h>
6243761473SPaul Moore #include <linux/uaccess.h>
639dd813c1SJan Kara #include <linux/fsnotify_backend.h>
64fcf22d82SPaul Moore #include <uapi/linux/limits.h>
658e6cf365SRichard Guy Briggs #include <uapi/linux/netfilter/nf_tables.h>
66571e5c0eSRichard Guy Briggs #include <uapi/linux/openat2.h> // struct open_how
67032bffd4SRichard Guy Briggs #include <uapi/linux/fanotify.h>
681da177e4SLinus Torvalds
69fe7752baSDavid Woodhouse #include "audit.h"
70fe7752baSDavid Woodhouse
71d7e7528bSEric Paris /* flags stating the success for a syscall */
72d7e7528bSEric Paris #define AUDITSC_INVALID 0
73d7e7528bSEric Paris #define AUDITSC_SUCCESS 1
74d7e7528bSEric Paris #define AUDITSC_FAILURE 2
75d7e7528bSEric Paris
7643761473SPaul Moore /* no execve audit message should be longer than this (userspace limits),
7743761473SPaul Moore * see the note near the top of audit_log_execve_info() about this value */
78de6bbd1dSEric Paris #define MAX_EXECVE_AUDIT_LEN 7500
79de6bbd1dSEric Paris
803f1c8250SWilliam Roberts /* max length to print of cmdline/proctitle value during audit */
813f1c8250SWilliam Roberts #define MAX_PROCTITLE_AUDIT_LEN 128
823f1c8250SWilliam Roberts
83471a5c7cSAl Viro /* number of audit rules */
84471a5c7cSAl Viro int audit_n_rules;
85471a5c7cSAl Viro
86e54dc243SAmy Griffis /* determines whether we collect data for signals sent */
87e54dc243SAmy Griffis int audit_signals;
88e54dc243SAmy Griffis
891da177e4SLinus Torvalds struct audit_aux_data {
901da177e4SLinus Torvalds struct audit_aux_data *next;
911da177e4SLinus Torvalds int type;
921da177e4SLinus Torvalds };
931da177e4SLinus Torvalds
94e54dc243SAmy Griffis /* Number of target pids per aux struct. */
95e54dc243SAmy Griffis #define AUDIT_AUX_PIDS 16
96e54dc243SAmy Griffis
97e54dc243SAmy Griffis struct audit_aux_data_pids {
98e54dc243SAmy Griffis struct audit_aux_data d;
99e54dc243SAmy Griffis pid_t target_pid[AUDIT_AUX_PIDS];
100e1760bd5SEric W. Biederman kuid_t target_auid[AUDIT_AUX_PIDS];
101cca080d9SEric W. Biederman kuid_t target_uid[AUDIT_AUX_PIDS];
1024746ec5bSEric Paris unsigned int target_sessionid[AUDIT_AUX_PIDS];
10313d826e5SCasey Schaufler struct lsm_prop target_ref[AUDIT_AUX_PIDS];
104c2a7780eSEric Paris char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
105e54dc243SAmy Griffis int pid_count;
106e54dc243SAmy Griffis };
107e54dc243SAmy Griffis
1083fc689e9SEric Paris struct audit_aux_data_bprm_fcaps {
1093fc689e9SEric Paris struct audit_aux_data d;
1103fc689e9SEric Paris struct audit_cap_data fcap;
1113fc689e9SEric Paris unsigned int fcap_ver;
1123fc689e9SEric Paris struct audit_cap_data old_pcap;
1133fc689e9SEric Paris struct audit_cap_data new_pcap;
1143fc689e9SEric Paris };
1153fc689e9SEric Paris
11674c3cbe3SAl Viro struct audit_tree_refs {
11774c3cbe3SAl Viro struct audit_tree_refs *next;
11874c3cbe3SAl Viro struct audit_chunk *c[31];
11974c3cbe3SAl Viro };
12074c3cbe3SAl Viro
121c4dad0aaSRichard Guy Briggs struct audit_nfcfgop_tab {
122c4dad0aaSRichard Guy Briggs enum audit_nfcfgop op;
123c4dad0aaSRichard Guy Briggs const char *s;
124c4dad0aaSRichard Guy Briggs };
125c4dad0aaSRichard Guy Briggs
126db9ff6ecSZheng Bin static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
1278e6cf365SRichard Guy Briggs { AUDIT_XT_OP_REGISTER, "xt_register" },
1288e6cf365SRichard Guy Briggs { AUDIT_XT_OP_REPLACE, "xt_replace" },
1298e6cf365SRichard Guy Briggs { AUDIT_XT_OP_UNREGISTER, "xt_unregister" },
1308e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_TABLE_REGISTER, "nft_register_table" },
1318e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_TABLE_UNREGISTER, "nft_unregister_table" },
1328e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_CHAIN_REGISTER, "nft_register_chain" },
1338e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_CHAIN_UNREGISTER, "nft_unregister_chain" },
1348e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_RULE_REGISTER, "nft_register_rule" },
1358e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_RULE_UNREGISTER, "nft_unregister_rule" },
1368e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_SET_REGISTER, "nft_register_set" },
1378e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_SET_UNREGISTER, "nft_unregister_set" },
1388e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_SETELEM_REGISTER, "nft_register_setelem" },
1398e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_SETELEM_UNREGISTER, "nft_unregister_setelem" },
1408e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_GEN_REGISTER, "nft_register_gen" },
1418e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_OBJ_REGISTER, "nft_register_obj" },
1428e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_OBJ_UNREGISTER, "nft_unregister_obj" },
1438e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_OBJ_RESET, "nft_reset_obj" },
1448e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_FLOWTABLE_REGISTER, "nft_register_flowtable" },
1458e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_FLOWTABLE_UNREGISTER, "nft_unregister_flowtable" },
1467e9be112SPhil Sutter { AUDIT_NFT_OP_SETELEM_RESET, "nft_reset_setelem" },
147ea078ae9SPhil Sutter { AUDIT_NFT_OP_RULE_RESET, "nft_reset_rule" },
1488e6cf365SRichard Guy Briggs { AUDIT_NFT_OP_INVALID, "nft_invalid" },
149c4dad0aaSRichard Guy Briggs };
150c4dad0aaSRichard Guy Briggs
audit_match_perm(struct audit_context * ctx,int mask)15155669bfaSAl Viro static int audit_match_perm(struct audit_context *ctx, int mask)
15255669bfaSAl Viro {
153c4bacefbSCordelia unsigned n;
154254c8b96SRoni Nevalainen
1551a61c88dSzhangxiliang if (unlikely(!ctx))
1561a61c88dSzhangxiliang return 0;
157c4bacefbSCordelia n = ctx->major;
158dbda4c0bSAlan Cox
15955669bfaSAl Viro switch (audit_classify_syscall(ctx->arch, n)) {
16042f355efSRichard Guy Briggs case AUDITSC_NATIVE:
16155669bfaSAl Viro if ((mask & AUDIT_PERM_WRITE) &&
16255669bfaSAl Viro audit_match_class(AUDIT_CLASS_WRITE, n))
16355669bfaSAl Viro return 1;
16455669bfaSAl Viro if ((mask & AUDIT_PERM_READ) &&
16555669bfaSAl Viro audit_match_class(AUDIT_CLASS_READ, n))
16655669bfaSAl Viro return 1;
16755669bfaSAl Viro if ((mask & AUDIT_PERM_ATTR) &&
16855669bfaSAl Viro audit_match_class(AUDIT_CLASS_CHATTR, n))
16955669bfaSAl Viro return 1;
17055669bfaSAl Viro return 0;
17142f355efSRichard Guy Briggs case AUDITSC_COMPAT: /* 32bit on biarch */
17255669bfaSAl Viro if ((mask & AUDIT_PERM_WRITE) &&
17355669bfaSAl Viro audit_match_class(AUDIT_CLASS_WRITE_32, n))
17455669bfaSAl Viro return 1;
17555669bfaSAl Viro if ((mask & AUDIT_PERM_READ) &&
17655669bfaSAl Viro audit_match_class(AUDIT_CLASS_READ_32, n))
17755669bfaSAl Viro return 1;
17855669bfaSAl Viro if ((mask & AUDIT_PERM_ATTR) &&
17955669bfaSAl Viro audit_match_class(AUDIT_CLASS_CHATTR_32, n))
18055669bfaSAl Viro return 1;
18155669bfaSAl Viro return 0;
18242f355efSRichard Guy Briggs case AUDITSC_OPEN:
18355669bfaSAl Viro return mask & ACC_MODE(ctx->argv[1]);
18442f355efSRichard Guy Briggs case AUDITSC_OPENAT:
18555669bfaSAl Viro return mask & ACC_MODE(ctx->argv[2]);
18642f355efSRichard Guy Briggs case AUDITSC_SOCKETCALL:
18755669bfaSAl Viro return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
18842f355efSRichard Guy Briggs case AUDITSC_EXECVE:
18955669bfaSAl Viro return mask & AUDIT_PERM_EXEC;
1901c30e3afSRichard Guy Briggs case AUDITSC_OPENAT2:
1917a82f89dSPaul Moore return mask & ACC_MODE((u32)ctx->openat2.flags);
19255669bfaSAl Viro default:
19355669bfaSAl Viro return 0;
19455669bfaSAl Viro }
19555669bfaSAl Viro }
19655669bfaSAl Viro
audit_match_filetype(struct audit_context * ctx,int val)1975ef30ee5SEric Paris static int audit_match_filetype(struct audit_context *ctx, int val)
1988b67dca9SAl Viro {
1995195d8e2SEric Paris struct audit_names *n;
2005ef30ee5SEric Paris umode_t mode = (umode_t)val;
2011a61c88dSzhangxiliang
2021a61c88dSzhangxiliang if (unlikely(!ctx))
2031a61c88dSzhangxiliang return 0;
2041a61c88dSzhangxiliang
2055195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) {
20684cb777eSRichard Guy Briggs if ((n->ino != AUDIT_INO_UNSET) &&
2075195d8e2SEric Paris ((n->mode & S_IFMT) == mode))
2088b67dca9SAl Viro return 1;
2098b67dca9SAl Viro }
2105195d8e2SEric Paris
2115ef30ee5SEric Paris return 0;
2125ef30ee5SEric Paris }
2138b67dca9SAl Viro
21474c3cbe3SAl Viro /*
21574c3cbe3SAl Viro * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
21674c3cbe3SAl Viro * ->first_trees points to its beginning, ->trees - to the current end of data.
21774c3cbe3SAl Viro * ->tree_count is the number of free entries in array pointed to by ->trees.
21874c3cbe3SAl Viro * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL,
21974c3cbe3SAl Viro * "empty" becomes (p, p, 31) afterwards. We don't shrink the list (and seriously,
22074c3cbe3SAl Viro * it's going to remain 1-element for almost any setup) until we free context itself.
22174c3cbe3SAl Viro * References in it _are_ dropped - at the same time we free/drop aux stuff.
22274c3cbe3SAl Viro */
22374c3cbe3SAl Viro
audit_set_auditable(struct audit_context * ctx)224679173b7SEric Paris static void audit_set_auditable(struct audit_context *ctx)
225679173b7SEric Paris {
226679173b7SEric Paris if (!ctx->prio) {
227679173b7SEric Paris ctx->prio = 1;
228619ed58aSSergey Nazarov ctx->current_state = AUDIT_STATE_RECORD;
229679173b7SEric Paris }
230679173b7SEric Paris }
231679173b7SEric Paris
put_tree_ref(struct audit_context * ctx,struct audit_chunk * chunk)23274c3cbe3SAl Viro static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
23374c3cbe3SAl Viro {
23474c3cbe3SAl Viro struct audit_tree_refs *p = ctx->trees;
23574c3cbe3SAl Viro int left = ctx->tree_count;
236254c8b96SRoni Nevalainen
23774c3cbe3SAl Viro if (likely(left)) {
23874c3cbe3SAl Viro p->c[--left] = chunk;
23974c3cbe3SAl Viro ctx->tree_count = left;
24074c3cbe3SAl Viro return 1;
24174c3cbe3SAl Viro }
24274c3cbe3SAl Viro if (!p)
24374c3cbe3SAl Viro return 0;
24474c3cbe3SAl Viro p = p->next;
24574c3cbe3SAl Viro if (p) {
24674c3cbe3SAl Viro p->c[30] = chunk;
24774c3cbe3SAl Viro ctx->trees = p;
24874c3cbe3SAl Viro ctx->tree_count = 30;
24974c3cbe3SAl Viro return 1;
25074c3cbe3SAl Viro }
25174c3cbe3SAl Viro return 0;
25274c3cbe3SAl Viro }
25374c3cbe3SAl Viro
grow_tree_refs(struct audit_context * ctx)25474c3cbe3SAl Viro static int grow_tree_refs(struct audit_context *ctx)
25574c3cbe3SAl Viro {
25674c3cbe3SAl Viro struct audit_tree_refs *p = ctx->trees;
257254c8b96SRoni Nevalainen
25874c3cbe3SAl Viro ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
25974c3cbe3SAl Viro if (!ctx->trees) {
26074c3cbe3SAl Viro ctx->trees = p;
26174c3cbe3SAl Viro return 0;
26274c3cbe3SAl Viro }
26374c3cbe3SAl Viro if (p)
26474c3cbe3SAl Viro p->next = ctx->trees;
26574c3cbe3SAl Viro else
26674c3cbe3SAl Viro ctx->first_trees = ctx->trees;
26774c3cbe3SAl Viro ctx->tree_count = 31;
26874c3cbe3SAl Viro return 1;
26974c3cbe3SAl Viro }
27074c3cbe3SAl Viro
unroll_tree_refs(struct audit_context * ctx,struct audit_tree_refs * p,int count)27174c3cbe3SAl Viro static void unroll_tree_refs(struct audit_context *ctx,
27274c3cbe3SAl Viro struct audit_tree_refs *p, int count)
27374c3cbe3SAl Viro {
27474c3cbe3SAl Viro struct audit_tree_refs *q;
27574c3cbe3SAl Viro int n;
276254c8b96SRoni Nevalainen
27774c3cbe3SAl Viro if (!p) {
27874c3cbe3SAl Viro /* we started with empty chain */
27974c3cbe3SAl Viro p = ctx->first_trees;
28074c3cbe3SAl Viro count = 31;
28174c3cbe3SAl Viro /* if the very first allocation has failed, nothing to do */
28274c3cbe3SAl Viro if (!p)
28374c3cbe3SAl Viro return;
28474c3cbe3SAl Viro }
28574c3cbe3SAl Viro n = count;
28674c3cbe3SAl Viro for (q = p; q != ctx->trees; q = q->next, n = 31) {
28774c3cbe3SAl Viro while (n--) {
28874c3cbe3SAl Viro audit_put_chunk(q->c[n]);
28974c3cbe3SAl Viro q->c[n] = NULL;
29074c3cbe3SAl Viro }
29174c3cbe3SAl Viro }
29274c3cbe3SAl Viro while (n-- > ctx->tree_count) {
29374c3cbe3SAl Viro audit_put_chunk(q->c[n]);
29474c3cbe3SAl Viro q->c[n] = NULL;
29574c3cbe3SAl Viro }
29674c3cbe3SAl Viro ctx->trees = p;
29774c3cbe3SAl Viro ctx->tree_count = count;
29874c3cbe3SAl Viro }
29974c3cbe3SAl Viro
free_tree_refs(struct audit_context * ctx)30074c3cbe3SAl Viro static void free_tree_refs(struct audit_context *ctx)
30174c3cbe3SAl Viro {
30274c3cbe3SAl Viro struct audit_tree_refs *p, *q;
303254c8b96SRoni Nevalainen
30474c3cbe3SAl Viro for (p = ctx->first_trees; p; p = q) {
30574c3cbe3SAl Viro q = p->next;
30674c3cbe3SAl Viro kfree(p);
30774c3cbe3SAl Viro }
30874c3cbe3SAl Viro }
30974c3cbe3SAl Viro
match_tree_refs(struct audit_context * ctx,struct audit_tree * tree)31074c3cbe3SAl Viro static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
31174c3cbe3SAl Viro {
31274c3cbe3SAl Viro struct audit_tree_refs *p;
31374c3cbe3SAl Viro int n;
314254c8b96SRoni Nevalainen
31574c3cbe3SAl Viro if (!tree)
31674c3cbe3SAl Viro return 0;
31774c3cbe3SAl Viro /* full ones */
31874c3cbe3SAl Viro for (p = ctx->first_trees; p != ctx->trees; p = p->next) {
31974c3cbe3SAl Viro for (n = 0; n < 31; n++)
32074c3cbe3SAl Viro if (audit_tree_match(p->c[n], tree))
32174c3cbe3SAl Viro return 1;
32274c3cbe3SAl Viro }
32374c3cbe3SAl Viro /* partial */
32474c3cbe3SAl Viro if (p) {
32574c3cbe3SAl Viro for (n = ctx->tree_count; n < 31; n++)
32674c3cbe3SAl Viro if (audit_tree_match(p->c[n], tree))
32774c3cbe3SAl Viro return 1;
32874c3cbe3SAl Viro }
32974c3cbe3SAl Viro return 0;
33074c3cbe3SAl Viro }
33174c3cbe3SAl Viro
audit_compare_uid(kuid_t uid,struct audit_names * name,struct audit_field * f,struct audit_context * ctx)332ca57ec0fSEric W. Biederman static int audit_compare_uid(kuid_t uid,
333b34b0393SEric Paris struct audit_names *name,
334b34b0393SEric Paris struct audit_field *f,
335b34b0393SEric Paris struct audit_context *ctx)
336b34b0393SEric Paris {
337b34b0393SEric Paris struct audit_names *n;
338b34b0393SEric Paris int rc;
339b34b0393SEric Paris
340b34b0393SEric Paris if (name) {
341ca57ec0fSEric W. Biederman rc = audit_uid_comparator(uid, f->op, name->uid);
342b34b0393SEric Paris if (rc)
343b34b0393SEric Paris return rc;
344b34b0393SEric Paris }
345b34b0393SEric Paris
346b34b0393SEric Paris if (ctx) {
347b34b0393SEric Paris list_for_each_entry(n, &ctx->names_list, list) {
348ca57ec0fSEric W. Biederman rc = audit_uid_comparator(uid, f->op, n->uid);
349ca57ec0fSEric W. Biederman if (rc)
350ca57ec0fSEric W. Biederman return rc;
351ca57ec0fSEric W. Biederman }
352ca57ec0fSEric W. Biederman }
353ca57ec0fSEric W. Biederman return 0;
354ca57ec0fSEric W. Biederman }
355b34b0393SEric Paris
audit_compare_gid(kgid_t gid,struct audit_names * name,struct audit_field * f,struct audit_context * ctx)356ca57ec0fSEric W. Biederman static int audit_compare_gid(kgid_t gid,
357ca57ec0fSEric W. Biederman struct audit_names *name,
358ca57ec0fSEric W. Biederman struct audit_field *f,
359ca57ec0fSEric W. Biederman struct audit_context *ctx)
360ca57ec0fSEric W. Biederman {
361ca57ec0fSEric W. Biederman struct audit_names *n;
362ca57ec0fSEric W. Biederman int rc;
363b34b0393SEric Paris
364ca57ec0fSEric W. Biederman if (name) {
365ca57ec0fSEric W. Biederman rc = audit_gid_comparator(gid, f->op, name->gid);
366ca57ec0fSEric W. Biederman if (rc)
367ca57ec0fSEric W. Biederman return rc;
368ca57ec0fSEric W. Biederman }
369ca57ec0fSEric W. Biederman
370ca57ec0fSEric W. Biederman if (ctx) {
371ca57ec0fSEric W. Biederman list_for_each_entry(n, &ctx->names_list, list) {
372ca57ec0fSEric W. Biederman rc = audit_gid_comparator(gid, f->op, n->gid);
373b34b0393SEric Paris if (rc)
374b34b0393SEric Paris return rc;
375b34b0393SEric Paris }
376b34b0393SEric Paris }
377b34b0393SEric Paris return 0;
378b34b0393SEric Paris }
379b34b0393SEric Paris
audit_field_compare(struct task_struct * tsk,const struct cred * cred,struct audit_field * f,struct audit_context * ctx,struct audit_names * name)38002d86a56SEric Paris static int audit_field_compare(struct task_struct *tsk,
38102d86a56SEric Paris const struct cred *cred,
38202d86a56SEric Paris struct audit_field *f,
38302d86a56SEric Paris struct audit_context *ctx,
38402d86a56SEric Paris struct audit_names *name)
38502d86a56SEric Paris {
38602d86a56SEric Paris switch (f->val) {
3874a6633edSPeter Moody /* process to file object comparisons */
38802d86a56SEric Paris case AUDIT_COMPARE_UID_TO_OBJ_UID:
389ca57ec0fSEric W. Biederman return audit_compare_uid(cred->uid, name, f, ctx);
390c9fe685fSEric Paris case AUDIT_COMPARE_GID_TO_OBJ_GID:
391ca57ec0fSEric W. Biederman return audit_compare_gid(cred->gid, name, f, ctx);
3924a6633edSPeter Moody case AUDIT_COMPARE_EUID_TO_OBJ_UID:
393ca57ec0fSEric W. Biederman return audit_compare_uid(cred->euid, name, f, ctx);
3944a6633edSPeter Moody case AUDIT_COMPARE_EGID_TO_OBJ_GID:
395ca57ec0fSEric W. Biederman return audit_compare_gid(cred->egid, name, f, ctx);
3964a6633edSPeter Moody case AUDIT_COMPARE_AUID_TO_OBJ_UID:
39738f80590SRichard Guy Briggs return audit_compare_uid(audit_get_loginuid(tsk), name, f, ctx);
3984a6633edSPeter Moody case AUDIT_COMPARE_SUID_TO_OBJ_UID:
399ca57ec0fSEric W. Biederman return audit_compare_uid(cred->suid, name, f, ctx);
4004a6633edSPeter Moody case AUDIT_COMPARE_SGID_TO_OBJ_GID:
401ca57ec0fSEric W. Biederman return audit_compare_gid(cred->sgid, name, f, ctx);
4024a6633edSPeter Moody case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
403ca57ec0fSEric W. Biederman return audit_compare_uid(cred->fsuid, name, f, ctx);
4044a6633edSPeter Moody case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
405ca57ec0fSEric W. Biederman return audit_compare_gid(cred->fsgid, name, f, ctx);
40610d68360SPeter Moody /* uid comparisons */
40710d68360SPeter Moody case AUDIT_COMPARE_UID_TO_AUID:
40838f80590SRichard Guy Briggs return audit_uid_comparator(cred->uid, f->op,
40938f80590SRichard Guy Briggs audit_get_loginuid(tsk));
41010d68360SPeter Moody case AUDIT_COMPARE_UID_TO_EUID:
411ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->uid, f->op, cred->euid);
41210d68360SPeter Moody case AUDIT_COMPARE_UID_TO_SUID:
413ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->uid, f->op, cred->suid);
41410d68360SPeter Moody case AUDIT_COMPARE_UID_TO_FSUID:
415ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->uid, f->op, cred->fsuid);
41610d68360SPeter Moody /* auid comparisons */
41710d68360SPeter Moody case AUDIT_COMPARE_AUID_TO_EUID:
41838f80590SRichard Guy Briggs return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
41938f80590SRichard Guy Briggs cred->euid);
42010d68360SPeter Moody case AUDIT_COMPARE_AUID_TO_SUID:
42138f80590SRichard Guy Briggs return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
42238f80590SRichard Guy Briggs cred->suid);
42310d68360SPeter Moody case AUDIT_COMPARE_AUID_TO_FSUID:
42438f80590SRichard Guy Briggs return audit_uid_comparator(audit_get_loginuid(tsk), f->op,
42538f80590SRichard Guy Briggs cred->fsuid);
42610d68360SPeter Moody /* euid comparisons */
42710d68360SPeter Moody case AUDIT_COMPARE_EUID_TO_SUID:
428ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->euid, f->op, cred->suid);
42910d68360SPeter Moody case AUDIT_COMPARE_EUID_TO_FSUID:
430ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->euid, f->op, cred->fsuid);
43110d68360SPeter Moody /* suid comparisons */
43210d68360SPeter Moody case AUDIT_COMPARE_SUID_TO_FSUID:
433ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->suid, f->op, cred->fsuid);
43410d68360SPeter Moody /* gid comparisons */
43510d68360SPeter Moody case AUDIT_COMPARE_GID_TO_EGID:
436ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->gid, f->op, cred->egid);
43710d68360SPeter Moody case AUDIT_COMPARE_GID_TO_SGID:
438ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->gid, f->op, cred->sgid);
43910d68360SPeter Moody case AUDIT_COMPARE_GID_TO_FSGID:
440ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->gid, f->op, cred->fsgid);
44110d68360SPeter Moody /* egid comparisons */
44210d68360SPeter Moody case AUDIT_COMPARE_EGID_TO_SGID:
443ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->egid, f->op, cred->sgid);
44410d68360SPeter Moody case AUDIT_COMPARE_EGID_TO_FSGID:
445ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->egid, f->op, cred->fsgid);
44610d68360SPeter Moody /* sgid comparison */
44710d68360SPeter Moody case AUDIT_COMPARE_SGID_TO_FSGID:
448ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->sgid, f->op, cred->fsgid);
44902d86a56SEric Paris default:
45002d86a56SEric Paris WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n");
45102d86a56SEric Paris return 0;
45202d86a56SEric Paris }
45302d86a56SEric Paris return 0;
45402d86a56SEric Paris }
45502d86a56SEric Paris
456f368c07dSAmy Griffis /* Determine if any context name data matches a rule's watch data */
4571da177e4SLinus Torvalds /* Compare a task_struct with an audit_rule. Return 1 on match, 0
458f5629883STony Jones * otherwise.
459f5629883STony Jones *
460f5629883STony Jones * If task_creation is true, this is an explicit indication that we are
461f5629883STony Jones * filtering a task rule at task creation time. This and tsk == current are
462f5629883STony Jones * the only situations where tsk->cred may be accessed without an rcu read lock.
463f5629883STony Jones */
audit_filter_rules(struct task_struct * tsk,struct audit_krule * rule,struct audit_context * ctx,struct audit_names * name,enum audit_state * state,bool task_creation)4641da177e4SLinus Torvalds static int audit_filter_rules(struct task_struct *tsk,
46593315ed6SAmy Griffis struct audit_krule *rule,
4661da177e4SLinus Torvalds struct audit_context *ctx,
467f368c07dSAmy Griffis struct audit_names *name,
468f5629883STony Jones enum audit_state *state,
469f5629883STony Jones bool task_creation)
4701da177e4SLinus Torvalds {
471f5629883STony Jones const struct cred *cred;
4725195d8e2SEric Paris int i, need_sid = 1;
473870b7fdcSCasey Schaufler struct lsm_prop prop = { };
4748fae4770SRichard Guy Briggs unsigned int sessionid;
4753dc7e315SDarrel Goeddel
476d9516f34SGaosheng Cui if (ctx && rule->prio <= ctx->prio)
477d9516f34SGaosheng Cui return 0;
478d9516f34SGaosheng Cui
479f5629883STony Jones cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);
480f5629883STony Jones
4811da177e4SLinus Torvalds for (i = 0; i < rule->field_count; i++) {
48293315ed6SAmy Griffis struct audit_field *f = &rule->fields[i];
4835195d8e2SEric Paris struct audit_names *n;
4841da177e4SLinus Torvalds int result = 0;
485f1dc4867SRichard Guy Briggs pid_t pid;
4861da177e4SLinus Torvalds
48793315ed6SAmy Griffis switch (f->type) {
4881da177e4SLinus Torvalds case AUDIT_PID:
489fa2bea2fSPaul Moore pid = task_tgid_nr(tsk);
490f1dc4867SRichard Guy Briggs result = audit_comparator(pid, f->op, f->val);
4911da177e4SLinus Torvalds break;
4923c66251eSAl Viro case AUDIT_PPID:
493419c58f1SAlexander Viro if (ctx) {
494419c58f1SAlexander Viro if (!ctx->ppid)
495c92cdeb4SRichard Guy Briggs ctx->ppid = task_ppid_nr(tsk);
4963c66251eSAl Viro result = audit_comparator(ctx->ppid, f->op, f->val);
497419c58f1SAlexander Viro }
4983c66251eSAl Viro break;
49934d99af5SRichard Guy Briggs case AUDIT_EXE:
50034d99af5SRichard Guy Briggs result = audit_exe_compare(tsk, rule->exe);
50123bcc480SOndrej Mosnáček if (f->op == Audit_not_equal)
50223bcc480SOndrej Mosnáček result = !result;
50334d99af5SRichard Guy Briggs break;
5041da177e4SLinus Torvalds case AUDIT_UID:
505ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->uid, f->op, f->uid);
5061da177e4SLinus Torvalds break;
5071da177e4SLinus Torvalds case AUDIT_EUID:
508ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->euid, f->op, f->uid);
5091da177e4SLinus Torvalds break;
5101da177e4SLinus Torvalds case AUDIT_SUID:
511ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->suid, f->op, f->uid);
5121da177e4SLinus Torvalds break;
5131da177e4SLinus Torvalds case AUDIT_FSUID:
514ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->fsuid, f->op, f->uid);
5151da177e4SLinus Torvalds break;
5161da177e4SLinus Torvalds case AUDIT_GID:
517ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->gid, f->op, f->gid);
51837eebe39SMatvejchikov Ilya if (f->op == Audit_equal) {
51937eebe39SMatvejchikov Ilya if (!result)
520af85d177SOndrej Mosnáček result = groups_search(cred->group_info, f->gid);
52137eebe39SMatvejchikov Ilya } else if (f->op == Audit_not_equal) {
52237eebe39SMatvejchikov Ilya if (result)
523af85d177SOndrej Mosnáček result = !groups_search(cred->group_info, f->gid);
52437eebe39SMatvejchikov Ilya }
5251da177e4SLinus Torvalds break;
5261da177e4SLinus Torvalds case AUDIT_EGID:
527ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->egid, f->op, f->gid);
52837eebe39SMatvejchikov Ilya if (f->op == Audit_equal) {
52937eebe39SMatvejchikov Ilya if (!result)
530af85d177SOndrej Mosnáček result = groups_search(cred->group_info, f->gid);
53137eebe39SMatvejchikov Ilya } else if (f->op == Audit_not_equal) {
53237eebe39SMatvejchikov Ilya if (result)
533af85d177SOndrej Mosnáček result = !groups_search(cred->group_info, f->gid);
53437eebe39SMatvejchikov Ilya }
5351da177e4SLinus Torvalds break;
5361da177e4SLinus Torvalds case AUDIT_SGID:
537ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->sgid, f->op, f->gid);
5381da177e4SLinus Torvalds break;
5391da177e4SLinus Torvalds case AUDIT_FSGID:
540ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->fsgid, f->op, f->gid);
5411da177e4SLinus Torvalds break;
5428fae4770SRichard Guy Briggs case AUDIT_SESSIONID:
5435b713886SOndrej Mosnáček sessionid = audit_get_sessionid(tsk);
5448fae4770SRichard Guy Briggs result = audit_comparator(sessionid, f->op, f->val);
5458fae4770SRichard Guy Briggs break;
5461da177e4SLinus Torvalds case AUDIT_PERS:
54793315ed6SAmy Griffis result = audit_comparator(tsk->personality, f->op, f->val);
5481da177e4SLinus Torvalds break;
5492fd6f58bS case AUDIT_ARCH:
5502fd6f58bS if (ctx)
55193315ed6SAmy Griffis result = audit_comparator(ctx->arch, f->op, f->val);
5522fd6f58bS break;
5531da177e4SLinus Torvalds
5541da177e4SLinus Torvalds case AUDIT_EXIT:
555ba59eae7SAlex Shi if (ctx && ctx->return_valid != AUDITSC_INVALID)
55693315ed6SAmy Griffis result = audit_comparator(ctx->return_code, f->op, f->val);
5571da177e4SLinus Torvalds break;
5581da177e4SLinus Torvalds case AUDIT_SUCCESS:
559ba59eae7SAlex Shi if (ctx && ctx->return_valid != AUDITSC_INVALID) {
56093315ed6SAmy Griffis if (f->val)
56193315ed6SAmy Griffis result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
562b01f2cc1SDavid Woodhouse else
56393315ed6SAmy Griffis result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
564b01f2cc1SDavid Woodhouse }
5651da177e4SLinus Torvalds break;
5661da177e4SLinus Torvalds case AUDIT_DEVMAJOR:
56716c174bdSEric Paris if (name) {
56816c174bdSEric Paris if (audit_comparator(MAJOR(name->dev), f->op, f->val) ||
56916c174bdSEric Paris audit_comparator(MAJOR(name->rdev), f->op, f->val))
57016c174bdSEric Paris ++result;
57116c174bdSEric Paris } else if (ctx) {
5725195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) {
57316c174bdSEric Paris if (audit_comparator(MAJOR(n->dev), f->op, f->val) ||
57416c174bdSEric Paris audit_comparator(MAJOR(n->rdev), f->op, f->val)) {
5751da177e4SLinus Torvalds ++result;
5761da177e4SLinus Torvalds break;
5771da177e4SLinus Torvalds }
5781da177e4SLinus Torvalds }
5791da177e4SLinus Torvalds }
5801da177e4SLinus Torvalds break;
5811da177e4SLinus Torvalds case AUDIT_DEVMINOR:
58216c174bdSEric Paris if (name) {
58316c174bdSEric Paris if (audit_comparator(MINOR(name->dev), f->op, f->val) ||
58416c174bdSEric Paris audit_comparator(MINOR(name->rdev), f->op, f->val))
58516c174bdSEric Paris ++result;
58616c174bdSEric Paris } else if (ctx) {
5875195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) {
58816c174bdSEric Paris if (audit_comparator(MINOR(n->dev), f->op, f->val) ||
58916c174bdSEric Paris audit_comparator(MINOR(n->rdev), f->op, f->val)) {
5901da177e4SLinus Torvalds ++result;
5911da177e4SLinus Torvalds break;
5921da177e4SLinus Torvalds }
5931da177e4SLinus Torvalds }
5941da177e4SLinus Torvalds }
5951da177e4SLinus Torvalds break;
5961da177e4SLinus Torvalds case AUDIT_INODE:
597f368c07dSAmy Griffis if (name)
598db510fc5SRichard Guy Briggs result = audit_comparator(name->ino, f->op, f->val);
599f368c07dSAmy Griffis else if (ctx) {
6005195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) {
6015195d8e2SEric Paris if (audit_comparator(n->ino, f->op, f->val)) {
6021da177e4SLinus Torvalds ++result;
6031da177e4SLinus Torvalds break;
6041da177e4SLinus Torvalds }
6051da177e4SLinus Torvalds }
6061da177e4SLinus Torvalds }
6071da177e4SLinus Torvalds break;
608efaffd6eSEric Paris case AUDIT_OBJ_UID:
609efaffd6eSEric Paris if (name) {
610ca57ec0fSEric W. Biederman result = audit_uid_comparator(name->uid, f->op, f->uid);
611efaffd6eSEric Paris } else if (ctx) {
612efaffd6eSEric Paris list_for_each_entry(n, &ctx->names_list, list) {
613ca57ec0fSEric W. Biederman if (audit_uid_comparator(n->uid, f->op, f->uid)) {
614efaffd6eSEric Paris ++result;
615efaffd6eSEric Paris break;
616efaffd6eSEric Paris }
617efaffd6eSEric Paris }
618efaffd6eSEric Paris }
619efaffd6eSEric Paris break;
62054d3218bSEric Paris case AUDIT_OBJ_GID:
62154d3218bSEric Paris if (name) {
622ca57ec0fSEric W. Biederman result = audit_gid_comparator(name->gid, f->op, f->gid);
62354d3218bSEric Paris } else if (ctx) {
62454d3218bSEric Paris list_for_each_entry(n, &ctx->names_list, list) {
625ca57ec0fSEric W. Biederman if (audit_gid_comparator(n->gid, f->op, f->gid)) {
62654d3218bSEric Paris ++result;
62754d3218bSEric Paris break;
62854d3218bSEric Paris }
62954d3218bSEric Paris }
63054d3218bSEric Paris }
63154d3218bSEric Paris break;
632f368c07dSAmy Griffis case AUDIT_WATCH:
6330223fad3SRichard Guy Briggs if (name) {
6340223fad3SRichard Guy Briggs result = audit_watch_compare(rule->watch,
6350223fad3SRichard Guy Briggs name->ino,
6360223fad3SRichard Guy Briggs name->dev);
6370223fad3SRichard Guy Briggs if (f->op == Audit_not_equal)
6380223fad3SRichard Guy Briggs result = !result;
6390223fad3SRichard Guy Briggs }
640f368c07dSAmy Griffis break;
64174c3cbe3SAl Viro case AUDIT_DIR:
6420223fad3SRichard Guy Briggs if (ctx) {
64374c3cbe3SAl Viro result = match_tree_refs(ctx, rule->tree);
6440223fad3SRichard Guy Briggs if (f->op == Audit_not_equal)
6450223fad3SRichard Guy Briggs result = !result;
6460223fad3SRichard Guy Briggs }
64774c3cbe3SAl Viro break;
6481da177e4SLinus Torvalds case AUDIT_LOGINUID:
64938f80590SRichard Guy Briggs result = audit_uid_comparator(audit_get_loginuid(tsk),
65038f80590SRichard Guy Briggs f->op, f->uid);
6511da177e4SLinus Torvalds break;
652780a7654SEric W. Biederman case AUDIT_LOGINUID_SET:
653780a7654SEric W. Biederman result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val);
654780a7654SEric W. Biederman break;
655bf361231SRichard Guy Briggs case AUDIT_SADDR_FAM:
6566e3ee990SGaosheng Cui if (ctx && ctx->sockaddr)
657bf361231SRichard Guy Briggs result = audit_comparator(ctx->sockaddr->ss_family,
658bf361231SRichard Guy Briggs f->op, f->val);
659bf361231SRichard Guy Briggs break;
6603a6b9f85SDarrel Goeddel case AUDIT_SUBJ_USER:
6613a6b9f85SDarrel Goeddel case AUDIT_SUBJ_ROLE:
6623a6b9f85SDarrel Goeddel case AUDIT_SUBJ_TYPE:
6633a6b9f85SDarrel Goeddel case AUDIT_SUBJ_SEN:
6643a6b9f85SDarrel Goeddel case AUDIT_SUBJ_CLR:
6653dc7e315SDarrel Goeddel /* NOTE: this may return negative values indicating
6663dc7e315SDarrel Goeddel a temporary error. We simply treat this as a
6673dc7e315SDarrel Goeddel match for now to avoid losing information that
6683dc7e315SDarrel Goeddel may be wanted. An error message will also be
6693dc7e315SDarrel Goeddel logged upon error */
67004305e4aSAhmed S. Darwish if (f->lsm_rule) {
6712ad312d2SSteve Grubb if (need_sid) {
6726326948fSPaul Moore /* @tsk should always be equal to
6736326948fSPaul Moore * @current with the exception of
6746326948fSPaul Moore * fork()/copy_process() in which case
6756326948fSPaul Moore * the new @tsk creds are still a dup
6766326948fSPaul Moore * of @current's creds so we can still
67737f670aaSCasey Schaufler * use
67837f670aaSCasey Schaufler * security_current_getlsmprop_subj()
6796326948fSPaul Moore * here even though it always refs
6806326948fSPaul Moore * @current's creds
6816326948fSPaul Moore */
68237f670aaSCasey Schaufler security_current_getlsmprop_subj(&prop);
6832ad312d2SSteve Grubb need_sid = 0;
6842ad312d2SSteve Grubb }
685870b7fdcSCasey Schaufler result = security_audit_rule_match(&prop,
686870b7fdcSCasey Schaufler f->type,
6873dc7e315SDarrel Goeddel f->op,
68890462a5bSRichard Guy Briggs f->lsm_rule);
6892ad312d2SSteve Grubb }
6903dc7e315SDarrel Goeddel break;
6916e5a2d1dSDarrel Goeddel case AUDIT_OBJ_USER:
6926e5a2d1dSDarrel Goeddel case AUDIT_OBJ_ROLE:
6936e5a2d1dSDarrel Goeddel case AUDIT_OBJ_TYPE:
6946e5a2d1dSDarrel Goeddel case AUDIT_OBJ_LEV_LOW:
6956e5a2d1dSDarrel Goeddel case AUDIT_OBJ_LEV_HIGH:
6966e5a2d1dSDarrel Goeddel /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
6976e5a2d1dSDarrel Goeddel also applies here */
69804305e4aSAhmed S. Darwish if (f->lsm_rule) {
6996e5a2d1dSDarrel Goeddel /* Find files that match */
7006e5a2d1dSDarrel Goeddel if (name) {
701d7a96f3aSAhmed S. Darwish result = security_audit_rule_match(
702e0a8dcbdSCasey Schaufler &name->oprop,
70390462a5bSRichard Guy Briggs f->type,
70490462a5bSRichard Guy Briggs f->op,
70590462a5bSRichard Guy Briggs f->lsm_rule);
7066e5a2d1dSDarrel Goeddel } else if (ctx) {
7075195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) {
70890462a5bSRichard Guy Briggs if (security_audit_rule_match(
709e0a8dcbdSCasey Schaufler &n->oprop,
71090462a5bSRichard Guy Briggs f->type,
71190462a5bSRichard Guy Briggs f->op,
71290462a5bSRichard Guy Briggs f->lsm_rule)) {
7136e5a2d1dSDarrel Goeddel ++result;
7146e5a2d1dSDarrel Goeddel break;
7156e5a2d1dSDarrel Goeddel }
7166e5a2d1dSDarrel Goeddel }
7176e5a2d1dSDarrel Goeddel }
7186e5a2d1dSDarrel Goeddel /* Find ipc objects that match */
719a33e6751SAl Viro if (!ctx || ctx->type != AUDIT_IPC)
7206e5a2d1dSDarrel Goeddel break;
7217183abccSCasey Schaufler if (security_audit_rule_match(&ctx->ipc.oprop,
722a33e6751SAl Viro f->type, f->op,
72390462a5bSRichard Guy Briggs f->lsm_rule))
724a33e6751SAl Viro ++result;
7256e5a2d1dSDarrel Goeddel }
7266e5a2d1dSDarrel Goeddel break;
7271da177e4SLinus Torvalds case AUDIT_ARG0:
7281da177e4SLinus Torvalds case AUDIT_ARG1:
7291da177e4SLinus Torvalds case AUDIT_ARG2:
7301da177e4SLinus Torvalds case AUDIT_ARG3:
7311da177e4SLinus Torvalds if (ctx)
73293315ed6SAmy Griffis result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
7331da177e4SLinus Torvalds break;
7345adc8a6aSAmy Griffis case AUDIT_FILTERKEY:
7355adc8a6aSAmy Griffis /* ignore this field for filtering */
7365adc8a6aSAmy Griffis result = 1;
7375adc8a6aSAmy Griffis break;
73855669bfaSAl Viro case AUDIT_PERM:
73955669bfaSAl Viro result = audit_match_perm(ctx, f->val);
7400223fad3SRichard Guy Briggs if (f->op == Audit_not_equal)
7410223fad3SRichard Guy Briggs result = !result;
74255669bfaSAl Viro break;
7438b67dca9SAl Viro case AUDIT_FILETYPE:
7448b67dca9SAl Viro result = audit_match_filetype(ctx, f->val);
7450223fad3SRichard Guy Briggs if (f->op == Audit_not_equal)
7460223fad3SRichard Guy Briggs result = !result;
7478b67dca9SAl Viro break;
74802d86a56SEric Paris case AUDIT_FIELD_COMPARE:
74902d86a56SEric Paris result = audit_field_compare(tsk, cred, f, ctx, name);
75002d86a56SEric Paris break;
7511da177e4SLinus Torvalds }
752f5629883STony Jones if (!result)
7531da177e4SLinus Torvalds return 0;
7541da177e4SLinus Torvalds }
7550590b933SAl Viro
7560590b933SAl Viro if (ctx) {
7570590b933SAl Viro if (rule->filterkey) {
7580590b933SAl Viro kfree(ctx->filterkey);
7595adc8a6aSAmy Griffis ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
7600590b933SAl Viro }
7610590b933SAl Viro ctx->prio = rule->prio;
7620590b933SAl Viro }
7631da177e4SLinus Torvalds switch (rule->action) {
76466b12abcSPaul Moore case AUDIT_NEVER:
765619ed58aSSergey Nazarov *state = AUDIT_STATE_DISABLED;
76666b12abcSPaul Moore break;
76766b12abcSPaul Moore case AUDIT_ALWAYS:
768619ed58aSSergey Nazarov *state = AUDIT_STATE_RECORD;
76966b12abcSPaul Moore break;
7701da177e4SLinus Torvalds }
7711da177e4SLinus Torvalds return 1;
7721da177e4SLinus Torvalds }
7731da177e4SLinus Torvalds
7741da177e4SLinus Torvalds /* At process creation time, we can determine if system-call auditing is
7751da177e4SLinus Torvalds * completely disabled for this task. Since we only have the task
7761da177e4SLinus Torvalds * structure at this point, we can only check uid and gid.
7771da177e4SLinus Torvalds */
audit_filter_task(struct task_struct * tsk,char ** key)778e048e02cSAl Viro static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
7791da177e4SLinus Torvalds {
7801da177e4SLinus Torvalds struct audit_entry *e;
7811da177e4SLinus Torvalds enum audit_state state;
7821da177e4SLinus Torvalds
7831da177e4SLinus Torvalds rcu_read_lock();
7840f45aa18SDavid Woodhouse list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
785f5629883STony Jones if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
786f5629883STony Jones &state, true)) {
787619ed58aSSergey Nazarov if (state == AUDIT_STATE_RECORD)
788e048e02cSAl Viro *key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
7891da177e4SLinus Torvalds rcu_read_unlock();
7901da177e4SLinus Torvalds return state;
7911da177e4SLinus Torvalds }
7921da177e4SLinus Torvalds }
7931da177e4SLinus Torvalds rcu_read_unlock();
794619ed58aSSergey Nazarov return AUDIT_STATE_BUILD;
7951da177e4SLinus Torvalds }
7961da177e4SLinus Torvalds
audit_in_mask(const struct audit_krule * rule,unsigned long val)797a3c54931SAndy Lutomirski static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
798a3c54931SAndy Lutomirski {
799a3c54931SAndy Lutomirski int word, bit;
800a3c54931SAndy Lutomirski
801a3c54931SAndy Lutomirski if (val > 0xffffffff)
802a3c54931SAndy Lutomirski return false;
803a3c54931SAndy Lutomirski
804a3c54931SAndy Lutomirski word = AUDIT_WORD(val);
805a3c54931SAndy Lutomirski if (word >= AUDIT_BITMASK_SIZE)
806a3c54931SAndy Lutomirski return false;
807a3c54931SAndy Lutomirski
808a3c54931SAndy Lutomirski bit = AUDIT_BIT(val);
809a3c54931SAndy Lutomirski
810a3c54931SAndy Lutomirski return rule->mask[word] & bit;
811a3c54931SAndy Lutomirski }
812a3c54931SAndy Lutomirski
81367daf270SPaul Moore /**
81450979953SAnkur Arora * __audit_filter_op - common filter helper for operations (syscall/uring/etc)
81550979953SAnkur Arora * @tsk: associated task
81650979953SAnkur Arora * @ctx: audit context
81750979953SAnkur Arora * @list: audit filter list
81850979953SAnkur Arora * @name: audit_name (can be NULL)
81950979953SAnkur Arora * @op: current syscall/uring_op
82050979953SAnkur Arora *
82150979953SAnkur Arora * Run the udit filters specified in @list against @tsk using @ctx,
82250979953SAnkur Arora * @name, and @op, as necessary; the caller is responsible for ensuring
82350979953SAnkur Arora * that the call is made while the RCU read lock is held. The @name
82450979953SAnkur Arora * parameter can be NULL, but all others must be specified.
82550979953SAnkur Arora * Returns 1/true if the filter finds a match, 0/false if none are found.
82650979953SAnkur Arora */
__audit_filter_op(struct task_struct * tsk,struct audit_context * ctx,struct list_head * list,struct audit_names * name,unsigned long op)82750979953SAnkur Arora static int __audit_filter_op(struct task_struct *tsk,
82850979953SAnkur Arora struct audit_context *ctx,
82950979953SAnkur Arora struct list_head *list,
83050979953SAnkur Arora struct audit_names *name,
83150979953SAnkur Arora unsigned long op)
83250979953SAnkur Arora {
83350979953SAnkur Arora struct audit_entry *e;
83450979953SAnkur Arora enum audit_state state;
83550979953SAnkur Arora
83650979953SAnkur Arora list_for_each_entry_rcu(e, list, list) {
83750979953SAnkur Arora if (audit_in_mask(&e->rule, op) &&
83850979953SAnkur Arora audit_filter_rules(tsk, &e->rule, ctx, name,
83950979953SAnkur Arora &state, false)) {
84050979953SAnkur Arora ctx->current_state = state;
84150979953SAnkur Arora return 1;
84250979953SAnkur Arora }
84350979953SAnkur Arora }
84450979953SAnkur Arora return 0;
84550979953SAnkur Arora }
84650979953SAnkur Arora
84750979953SAnkur Arora /**
84867daf270SPaul Moore * audit_filter_uring - apply filters to an io_uring operation
84967daf270SPaul Moore * @tsk: associated task
85067daf270SPaul Moore * @ctx: audit context
85167daf270SPaul Moore */
audit_filter_uring(struct task_struct * tsk,struct audit_context * ctx)85267daf270SPaul Moore static void audit_filter_uring(struct task_struct *tsk,
85367daf270SPaul Moore struct audit_context *ctx)
85467daf270SPaul Moore {
85567daf270SPaul Moore if (auditd_test_task(tsk))
85667daf270SPaul Moore return;
85767daf270SPaul Moore
85867daf270SPaul Moore rcu_read_lock();
85950979953SAnkur Arora __audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_URING_EXIT],
86050979953SAnkur Arora NULL, ctx->uring_op);
86167daf270SPaul Moore rcu_read_unlock();
86267daf270SPaul Moore }
86367daf270SPaul Moore
864127c8c5fSYang Yang /* At syscall exit time, this filter is called if the audit_state is
865127c8c5fSYang Yang * not low enough that auditing cannot take place, but is also not
866127c8c5fSYang Yang * high enough that we already know we have to write an audit record
867619ed58aSSergey Nazarov * (i.e., the state is AUDIT_STATE_BUILD).
8681da177e4SLinus Torvalds */
audit_filter_syscall(struct task_struct * tsk,struct audit_context * ctx)869127c8c5fSYang Yang static void audit_filter_syscall(struct task_struct *tsk,
8705504a69aSRichard Guy Briggs struct audit_context *ctx)
8711da177e4SLinus Torvalds {
8725b52330bSPaul Moore if (auditd_test_task(tsk))
873127c8c5fSYang Yang return;
874f7056d64SDavid Woodhouse
8751da177e4SLinus Torvalds rcu_read_lock();
87650979953SAnkur Arora __audit_filter_op(tsk, ctx, &audit_filter_list[AUDIT_FILTER_EXIT],
87750979953SAnkur Arora NULL, ctx->major);
8781da177e4SLinus Torvalds rcu_read_unlock();
8791da177e4SLinus Torvalds }
8801da177e4SLinus Torvalds
8815195d8e2SEric Paris /*
8825195d8e2SEric Paris * Given an audit_name check the inode hash table to see if they match.
8835195d8e2SEric Paris * Called holding the rcu read lock to protect the use of audit_inode_hash
8845195d8e2SEric Paris */
audit_filter_inode_name(struct task_struct * tsk,struct audit_names * n,struct audit_context * ctx)8855195d8e2SEric Paris static int audit_filter_inode_name(struct task_struct *tsk,
8865195d8e2SEric Paris struct audit_names *n,
88722cde101SAtul Kumar Pant struct audit_context *ctx)
88822cde101SAtul Kumar Pant {
8895195d8e2SEric Paris int h = audit_hash_ino((u32)n->ino);
8905195d8e2SEric Paris struct list_head *list = &audit_inode_hash[h];
8915195d8e2SEric Paris
89250979953SAnkur Arora return __audit_filter_op(tsk, ctx, list, n, ctx->major);
8935195d8e2SEric Paris }
8945195d8e2SEric Paris
8955195d8e2SEric Paris /* At syscall exit time, this filter is called if any audit_names have been
896f368c07dSAmy Griffis * collected during syscall processing. We only check rules in sublists at hash
8975195d8e2SEric Paris * buckets applicable to the inode numbers in audit_names.
898f368c07dSAmy Griffis * Regarding audit_state, same rules apply as for audit_filter_syscall().
899f368c07dSAmy Griffis */
audit_filter_inodes(struct task_struct * tsk,struct audit_context * ctx)9000590b933SAl Viro void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
901f368c07dSAmy Griffis {
9025195d8e2SEric Paris struct audit_names *n;
903f368c07dSAmy Griffis
9045b52330bSPaul Moore if (auditd_test_task(tsk))
9050590b933SAl Viro return;
906f368c07dSAmy Griffis
907f368c07dSAmy Griffis rcu_read_lock();
908f368c07dSAmy Griffis
9095195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) {
9105195d8e2SEric Paris if (audit_filter_inode_name(tsk, n, ctx))
9115195d8e2SEric Paris break;
912f368c07dSAmy Griffis }
913f368c07dSAmy Griffis rcu_read_unlock();
914f368c07dSAmy Griffis }
915f368c07dSAmy Griffis
audit_proctitle_free(struct audit_context * context)9163f1c8250SWilliam Roberts static inline void audit_proctitle_free(struct audit_context *context)
9173f1c8250SWilliam Roberts {
9183f1c8250SWilliam Roberts kfree(context->proctitle.value);
9193f1c8250SWilliam Roberts context->proctitle.value = NULL;
9203f1c8250SWilliam Roberts context->proctitle.len = 0;
9213f1c8250SWilliam Roberts }
9223f1c8250SWilliam Roberts
audit_free_module(struct audit_context * context)92395e0b46fSLi RongQing static inline void audit_free_module(struct audit_context *context)
92495e0b46fSLi RongQing {
92595e0b46fSLi RongQing if (context->type == AUDIT_KERN_MODULE) {
92695e0b46fSLi RongQing kfree(context->module.name);
92795e0b46fSLi RongQing context->module.name = NULL;
92895e0b46fSLi RongQing }
92995e0b46fSLi RongQing }
audit_free_names(struct audit_context * context)9301da177e4SLinus Torvalds static inline void audit_free_names(struct audit_context *context)
9311da177e4SLinus Torvalds {
9325195d8e2SEric Paris struct audit_names *n, *next;
9331da177e4SLinus Torvalds
9345195d8e2SEric Paris list_for_each_entry_safe(n, next, &context->names_list, list) {
9355195d8e2SEric Paris list_del(&n->list);
93655422d0bSPaul Moore if (n->name)
93755422d0bSPaul Moore putname(n->name);
9385195d8e2SEric Paris if (n->should_free)
9395195d8e2SEric Paris kfree(n);
9408c8570fbSDustin Kirkland }
9411da177e4SLinus Torvalds context->name_count = 0;
94244707fdfSJan Blunck path_put(&context->pwd);
94344707fdfSJan Blunck context->pwd.dentry = NULL;
94444707fdfSJan Blunck context->pwd.mnt = NULL;
9451da177e4SLinus Torvalds }
9461da177e4SLinus Torvalds
audit_free_aux(struct audit_context * context)9471da177e4SLinus Torvalds static inline void audit_free_aux(struct audit_context *context)
9481da177e4SLinus Torvalds {
9491da177e4SLinus Torvalds struct audit_aux_data *aux;
9501da177e4SLinus Torvalds
9511da177e4SLinus Torvalds while ((aux = context->aux)) {
9521da177e4SLinus Torvalds context->aux = aux->next;
9531da177e4SLinus Torvalds kfree(aux);
9541da177e4SLinus Torvalds }
95512c5e81dSPaul Moore context->aux = NULL;
956e54dc243SAmy Griffis while ((aux = context->aux_pids)) {
957e54dc243SAmy Griffis context->aux_pids = aux->next;
958e54dc243SAmy Griffis kfree(aux);
959e54dc243SAmy Griffis }
96012c5e81dSPaul Moore context->aux_pids = NULL;
96112c5e81dSPaul Moore }
96212c5e81dSPaul Moore
96312c5e81dSPaul Moore /**
96412c5e81dSPaul Moore * audit_reset_context - reset a audit_context structure
96512c5e81dSPaul Moore * @ctx: the audit_context to reset
96612c5e81dSPaul Moore *
96712c5e81dSPaul Moore * All fields in the audit_context will be reset to an initial state, all
96812c5e81dSPaul Moore * references held by fields will be dropped, and private memory will be
96912c5e81dSPaul Moore * released. When this function returns the audit_context will be suitable
97012c5e81dSPaul Moore * for reuse, so long as the passed context is not NULL or a dummy context.
97112c5e81dSPaul Moore */
audit_reset_context(struct audit_context * ctx)97212c5e81dSPaul Moore static void audit_reset_context(struct audit_context *ctx)
97312c5e81dSPaul Moore {
97412c5e81dSPaul Moore if (!ctx)
97512c5e81dSPaul Moore return;
97612c5e81dSPaul Moore
977e84d9f52SRichard Guy Briggs /* if ctx is non-null, reset the "ctx->context" regardless */
97812c5e81dSPaul Moore ctx->context = AUDIT_CTX_UNUSED;
97912c5e81dSPaul Moore if (ctx->dummy)
98012c5e81dSPaul Moore return;
98112c5e81dSPaul Moore
98212c5e81dSPaul Moore /*
98312c5e81dSPaul Moore * NOTE: It shouldn't matter in what order we release the fields, so
98412c5e81dSPaul Moore * release them in the order in which they appear in the struct;
98512c5e81dSPaul Moore * this gives us some hope of quickly making sure we are
98612c5e81dSPaul Moore * resetting the audit_context properly.
98712c5e81dSPaul Moore *
98812c5e81dSPaul Moore * Other things worth mentioning:
98912c5e81dSPaul Moore * - we don't reset "dummy"
99012c5e81dSPaul Moore * - we don't reset "state", we do reset "current_state"
99112c5e81dSPaul Moore * - we preserve "filterkey" if "state" is AUDIT_STATE_RECORD
99212c5e81dSPaul Moore * - much of this is likely overkill, but play it safe for now
99312c5e81dSPaul Moore * - we really need to work on improving the audit_context struct
99412c5e81dSPaul Moore */
99512c5e81dSPaul Moore
99612c5e81dSPaul Moore ctx->current_state = ctx->state;
99712c5e81dSPaul Moore ctx->serial = 0;
99812c5e81dSPaul Moore ctx->major = 0;
9995bd2182dSPaul Moore ctx->uring_op = 0;
100012c5e81dSPaul Moore ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
100112c5e81dSPaul Moore memset(ctx->argv, 0, sizeof(ctx->argv));
100212c5e81dSPaul Moore ctx->return_code = 0;
100312c5e81dSPaul Moore ctx->prio = (ctx->state == AUDIT_STATE_RECORD ? ~0ULL : 0);
100412c5e81dSPaul Moore ctx->return_valid = AUDITSC_INVALID;
100512c5e81dSPaul Moore audit_free_names(ctx);
100612c5e81dSPaul Moore if (ctx->state != AUDIT_STATE_RECORD) {
100712c5e81dSPaul Moore kfree(ctx->filterkey);
100812c5e81dSPaul Moore ctx->filterkey = NULL;
100912c5e81dSPaul Moore }
101012c5e81dSPaul Moore audit_free_aux(ctx);
101112c5e81dSPaul Moore kfree(ctx->sockaddr);
101212c5e81dSPaul Moore ctx->sockaddr = NULL;
101312c5e81dSPaul Moore ctx->sockaddr_len = 0;
1014e84d9f52SRichard Guy Briggs ctx->ppid = 0;
101512c5e81dSPaul Moore ctx->uid = ctx->euid = ctx->suid = ctx->fsuid = KUIDT_INIT(0);
101612c5e81dSPaul Moore ctx->gid = ctx->egid = ctx->sgid = ctx->fsgid = KGIDT_INIT(0);
101712c5e81dSPaul Moore ctx->personality = 0;
101812c5e81dSPaul Moore ctx->arch = 0;
101912c5e81dSPaul Moore ctx->target_pid = 0;
102012c5e81dSPaul Moore ctx->target_auid = ctx->target_uid = KUIDT_INIT(0);
102112c5e81dSPaul Moore ctx->target_sessionid = 0;
102213d826e5SCasey Schaufler lsmprop_init(&ctx->target_ref);
102312c5e81dSPaul Moore ctx->target_comm[0] = '\0';
102412c5e81dSPaul Moore unroll_tree_refs(ctx, NULL, 0);
102512c5e81dSPaul Moore WARN_ON(!list_empty(&ctx->killed_trees));
102612c5e81dSPaul Moore audit_free_module(ctx);
102712c5e81dSPaul Moore ctx->fds[0] = -1;
1028ef79c396SChristian Göttsche ctx->type = 0; /* reset last for audit_free_*() */
10291da177e4SLinus Torvalds }
10301da177e4SLinus Torvalds
audit_alloc_context(enum audit_state state)10311da177e4SLinus Torvalds static inline struct audit_context *audit_alloc_context(enum audit_state state)
10321da177e4SLinus Torvalds {
10331da177e4SLinus Torvalds struct audit_context *context;
10341da177e4SLinus Torvalds
103517c6ee70SRakib Mullick context = kzalloc(sizeof(*context), GFP_KERNEL);
103617c6ee70SRakib Mullick if (!context)
10371da177e4SLinus Torvalds return NULL;
103812c5e81dSPaul Moore context->context = AUDIT_CTX_UNUSED;
1039e2c5adc8SAndrew Morton context->state = state;
1040619ed58aSSergey Nazarov context->prio = state == AUDIT_STATE_RECORD ? ~0ULL : 0;
1041916d7576SAl Viro INIT_LIST_HEAD(&context->killed_trees);
10425195d8e2SEric Paris INIT_LIST_HEAD(&context->names_list);
10436d915476SRichard Guy Briggs context->fds[0] = -1;
1044ba59eae7SAlex Shi context->return_valid = AUDITSC_INVALID;
10451da177e4SLinus Torvalds return context;
10461da177e4SLinus Torvalds }
10471da177e4SLinus Torvalds
1048b0dd25a8SRandy Dunlap /**
1049b0dd25a8SRandy Dunlap * audit_alloc - allocate an audit context block for a task
1050b0dd25a8SRandy Dunlap * @tsk: task
1051b0dd25a8SRandy Dunlap *
1052b0dd25a8SRandy Dunlap * Filter on the task information and allocate a per-task audit context
10531da177e4SLinus Torvalds * if necessary. Doing so turns on system call auditing for the
10541da177e4SLinus Torvalds * specified task. This is called from copy_process, so no lock is
1055b0dd25a8SRandy Dunlap * needed.
1056b0dd25a8SRandy Dunlap */
audit_alloc(struct task_struct * tsk)10571da177e4SLinus Torvalds int audit_alloc(struct task_struct *tsk)
10581da177e4SLinus Torvalds {
10591da177e4SLinus Torvalds struct audit_context *context;
10601da177e4SLinus Torvalds enum audit_state state;
1061e048e02cSAl Viro char *key = NULL;
10621da177e4SLinus Torvalds
1063b593d384SEric Paris if (likely(!audit_ever_enabled))
106412c5e81dSPaul Moore return 0;
10651da177e4SLinus Torvalds
1066e048e02cSAl Viro state = audit_filter_task(tsk, &key);
1067619ed58aSSergey Nazarov if (state == AUDIT_STATE_DISABLED) {
1068785dc4ebSGabriel Krisman Bertazi clear_task_syscall_work(tsk, SYSCALL_AUDIT);
10691da177e4SLinus Torvalds return 0;
1070d48d8051SOleg Nesterov }
10711da177e4SLinus Torvalds
107222cde101SAtul Kumar Pant context = audit_alloc_context(state);
107322cde101SAtul Kumar Pant if (!context) {
1074e048e02cSAl Viro kfree(key);
10751da177e4SLinus Torvalds audit_log_lost("out of memory in audit_alloc");
10761da177e4SLinus Torvalds return -ENOMEM;
10771da177e4SLinus Torvalds }
1078e048e02cSAl Viro context->filterkey = key;
10791da177e4SLinus Torvalds
1080c0b0ae8aSRichard Guy Briggs audit_set_context(tsk, context);
1081785dc4ebSGabriel Krisman Bertazi set_task_syscall_work(tsk, SYSCALL_AUDIT);
10821da177e4SLinus Torvalds return 0;
10831da177e4SLinus Torvalds }
10841da177e4SLinus Torvalds
audit_free_context(struct audit_context * context)10851da177e4SLinus Torvalds static inline void audit_free_context(struct audit_context *context)
10861da177e4SLinus Torvalds {
108712c5e81dSPaul Moore /* resetting is extra work, but it is likely just noise */
108812c5e81dSPaul Moore audit_reset_context(context);
1089c3f3ea8aSRichard Guy Briggs audit_proctitle_free(context);
109074c3cbe3SAl Viro free_tree_refs(context);
10915adc8a6aSAmy Griffis kfree(context->filterkey);
10921da177e4SLinus Torvalds kfree(context);
10931da177e4SLinus Torvalds }
10941da177e4SLinus Torvalds
audit_log_pid_context(struct audit_context * context,pid_t pid,kuid_t auid,kuid_t uid,unsigned int sessionid,struct lsm_prop * prop,char * comm)1095e54dc243SAmy Griffis static int audit_log_pid_context(struct audit_context *context, pid_t pid,
109613d826e5SCasey Schaufler kuid_t auid, kuid_t uid,
109713d826e5SCasey Schaufler unsigned int sessionid, struct lsm_prop *prop,
109813d826e5SCasey Schaufler char *comm)
1099e54dc243SAmy Griffis {
1100e54dc243SAmy Griffis struct audit_buffer *ab;
11016fba8981SCasey Schaufler struct lsm_context ctx;
1102e54dc243SAmy Griffis int rc = 0;
1103e54dc243SAmy Griffis
1104e54dc243SAmy Griffis ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
1105e54dc243SAmy Griffis if (!ab)
11066246ccabSEric Paris return rc;
1107e54dc243SAmy Griffis
1108e1760bd5SEric W. Biederman audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid,
1109e1760bd5SEric W. Biederman from_kuid(&init_user_ns, auid),
1110cca080d9SEric W. Biederman from_kuid(&init_user_ns, uid), sessionid);
111113d826e5SCasey Schaufler if (lsmprop_is_set(prop)) {
11122d470c77SCasey Schaufler if (security_lsmprop_to_secctx(prop, &ctx) < 0) {
1113c2a7780eSEric Paris audit_log_format(ab, " obj=(none)");
1114e54dc243SAmy Griffis rc = 1;
11152a862b32SAhmed S. Darwish } else {
11166fba8981SCasey Schaufler audit_log_format(ab, " obj=%s", ctx.context);
11176fba8981SCasey Schaufler security_release_secctx(&ctx);
11182a862b32SAhmed S. Darwish }
1119ad395abeSEric Paris }
1120c2a7780eSEric Paris audit_log_format(ab, " ocomm=");
1121c2a7780eSEric Paris audit_log_untrustedstring(ab, comm);
1122e54dc243SAmy Griffis audit_log_end(ab);
1123e54dc243SAmy Griffis
1124e54dc243SAmy Griffis return rc;
1125e54dc243SAmy Griffis }
1126e54dc243SAmy Griffis
audit_log_execve_info(struct audit_context * context,struct audit_buffer ** ab)1127de6bbd1dSEric Paris static void audit_log_execve_info(struct audit_context *context,
1128d9cfea91SRichard Guy Briggs struct audit_buffer **ab)
1129de6bbd1dSEric Paris {
113043761473SPaul Moore long len_max;
113143761473SPaul Moore long len_rem;
113243761473SPaul Moore long len_full;
113343761473SPaul Moore long len_buf;
11348443075eSRichard Guy Briggs long len_abuf = 0;
113543761473SPaul Moore long len_tmp;
113643761473SPaul Moore bool require_data;
113743761473SPaul Moore bool encode;
113843761473SPaul Moore unsigned int iter;
113943761473SPaul Moore unsigned int arg;
114043761473SPaul Moore char *buf_head;
1141de6bbd1dSEric Paris char *buf;
114243761473SPaul Moore const char __user *p = (const char __user *)current->mm->arg_start;
1143de6bbd1dSEric Paris
114443761473SPaul Moore /* NOTE: this buffer needs to be large enough to hold all the non-arg
114543761473SPaul Moore * data we put in the audit record for this argument (see the
114643761473SPaul Moore * code below) ... at this point in time 96 is plenty */
114743761473SPaul Moore char abuf[96];
1148de6bbd1dSEric Paris
114943761473SPaul Moore /* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the
115043761473SPaul Moore * current value of 7500 is not as important as the fact that it
115143761473SPaul Moore * is less than 8k, a setting of 7500 gives us plenty of wiggle
115243761473SPaul Moore * room if we go over a little bit in the logging below */
115343761473SPaul Moore WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500);
115443761473SPaul Moore len_max = MAX_EXECVE_AUDIT_LEN;
1155de6bbd1dSEric Paris
115643761473SPaul Moore /* scratch buffer to hold the userspace args */
115743761473SPaul Moore buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
115843761473SPaul Moore if (!buf_head) {
1159b7550787SJoe Perches audit_panic("out of memory for argv string");
1160de6bbd1dSEric Paris return;
1161de6bbd1dSEric Paris }
116243761473SPaul Moore buf = buf_head;
1163de6bbd1dSEric Paris
116443761473SPaul Moore audit_log_format(*ab, "argc=%d", context->execve.argc);
116543761473SPaul Moore
116643761473SPaul Moore len_rem = len_max;
116743761473SPaul Moore len_buf = 0;
116843761473SPaul Moore len_full = 0;
116943761473SPaul Moore require_data = true;
117043761473SPaul Moore encode = false;
117143761473SPaul Moore iter = 0;
117243761473SPaul Moore arg = 0;
117343761473SPaul Moore do {
117443761473SPaul Moore /* NOTE: we don't ever want to trust this value for anything
117543761473SPaul Moore * serious, but the audit record format insists we
117643761473SPaul Moore * provide an argument length for really long arguments,
117743761473SPaul Moore * e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but
117843761473SPaul Moore * to use strncpy_from_user() to obtain this value for
117943761473SPaul Moore * recording in the log, although we don't use it
118043761473SPaul Moore * anywhere here to avoid a double-fetch problem */
118143761473SPaul Moore if (len_full == 0)
118243761473SPaul Moore len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1;
118343761473SPaul Moore
118443761473SPaul Moore /* read more data from userspace */
118543761473SPaul Moore if (require_data) {
118643761473SPaul Moore /* can we make more room in the buffer? */
118743761473SPaul Moore if (buf != buf_head) {
118843761473SPaul Moore memmove(buf_head, buf, len_buf);
118943761473SPaul Moore buf = buf_head;
1190de6bbd1dSEric Paris }
119143761473SPaul Moore
119243761473SPaul Moore /* fetch as much as we can of the argument */
119343761473SPaul Moore len_tmp = strncpy_from_user(&buf_head[len_buf], p,
119443761473SPaul Moore len_max - len_buf);
119543761473SPaul Moore if (len_tmp == -EFAULT) {
119643761473SPaul Moore /* unable to copy from userspace */
119743761473SPaul Moore send_sig(SIGKILL, current, 0);
119843761473SPaul Moore goto out;
119943761473SPaul Moore } else if (len_tmp == (len_max - len_buf)) {
120043761473SPaul Moore /* buffer is not large enough */
120143761473SPaul Moore require_data = true;
120243761473SPaul Moore /* NOTE: if we are going to span multiple
120343761473SPaul Moore * buffers force the encoding so we stand
120443761473SPaul Moore * a chance at a sane len_full value and
120543761473SPaul Moore * consistent record encoding */
120643761473SPaul Moore encode = true;
120743761473SPaul Moore len_full = len_full * 2;
120843761473SPaul Moore p += len_tmp;
120943761473SPaul Moore } else {
121043761473SPaul Moore require_data = false;
121143761473SPaul Moore if (!encode)
121243761473SPaul Moore encode = audit_string_contains_control(
121343761473SPaul Moore buf, len_tmp);
121443761473SPaul Moore /* try to use a trusted value for len_full */
121543761473SPaul Moore if (len_full < len_max)
121643761473SPaul Moore len_full = (encode ?
121743761473SPaul Moore len_tmp * 2 : len_tmp);
121843761473SPaul Moore p += len_tmp + 1;
121943761473SPaul Moore }
122043761473SPaul Moore len_buf += len_tmp;
122143761473SPaul Moore buf_head[len_buf] = '\0';
122243761473SPaul Moore
122343761473SPaul Moore /* length of the buffer in the audit record? */
122443761473SPaul Moore len_abuf = (encode ? len_buf * 2 : len_buf + 2);
122543761473SPaul Moore }
122643761473SPaul Moore
122743761473SPaul Moore /* write as much as we can to the audit log */
1228ea956d8bSRichard Guy Briggs if (len_buf >= 0) {
122943761473SPaul Moore /* NOTE: some magic numbers here - basically if we
123043761473SPaul Moore * can't fit a reasonable amount of data into the
123143761473SPaul Moore * existing audit buffer, flush it and start with
123243761473SPaul Moore * a new buffer */
123343761473SPaul Moore if ((sizeof(abuf) + 8) > len_rem) {
123443761473SPaul Moore len_rem = len_max;
123543761473SPaul Moore audit_log_end(*ab);
123643761473SPaul Moore *ab = audit_log_start(context,
123743761473SPaul Moore GFP_KERNEL, AUDIT_EXECVE);
123843761473SPaul Moore if (!*ab)
123943761473SPaul Moore goto out;
124043761473SPaul Moore }
124143761473SPaul Moore
124243761473SPaul Moore /* create the non-arg portion of the arg record */
124343761473SPaul Moore len_tmp = 0;
124443761473SPaul Moore if (require_data || (iter > 0) ||
124543761473SPaul Moore ((len_abuf + sizeof(abuf)) > len_rem)) {
124643761473SPaul Moore if (iter == 0) {
124743761473SPaul Moore len_tmp += snprintf(&abuf[len_tmp],
124843761473SPaul Moore sizeof(abuf) - len_tmp,
124943761473SPaul Moore " a%d_len=%lu",
125043761473SPaul Moore arg, len_full);
125143761473SPaul Moore }
125243761473SPaul Moore len_tmp += snprintf(&abuf[len_tmp],
125343761473SPaul Moore sizeof(abuf) - len_tmp,
125443761473SPaul Moore " a%d[%d]=", arg, iter++);
125543761473SPaul Moore } else
125643761473SPaul Moore len_tmp += snprintf(&abuf[len_tmp],
125743761473SPaul Moore sizeof(abuf) - len_tmp,
125843761473SPaul Moore " a%d=", arg);
125943761473SPaul Moore WARN_ON(len_tmp >= sizeof(abuf));
126043761473SPaul Moore abuf[sizeof(abuf) - 1] = '\0';
126143761473SPaul Moore
126243761473SPaul Moore /* log the arg in the audit record */
126343761473SPaul Moore audit_log_format(*ab, "%s", abuf);
126443761473SPaul Moore len_rem -= len_tmp;
126543761473SPaul Moore len_tmp = len_buf;
126643761473SPaul Moore if (encode) {
126743761473SPaul Moore if (len_abuf > len_rem)
126843761473SPaul Moore len_tmp = len_rem / 2; /* encoding */
126943761473SPaul Moore audit_log_n_hex(*ab, buf, len_tmp);
127043761473SPaul Moore len_rem -= len_tmp * 2;
127143761473SPaul Moore len_abuf -= len_tmp * 2;
127243761473SPaul Moore } else {
127343761473SPaul Moore if (len_abuf > len_rem)
127443761473SPaul Moore len_tmp = len_rem - 2; /* quotes */
127543761473SPaul Moore audit_log_n_string(*ab, buf, len_tmp);
127643761473SPaul Moore len_rem -= len_tmp + 2;
127743761473SPaul Moore /* don't subtract the "2" because we still need
127843761473SPaul Moore * to add quotes to the remaining string */
127943761473SPaul Moore len_abuf -= len_tmp;
128043761473SPaul Moore }
128143761473SPaul Moore len_buf -= len_tmp;
128243761473SPaul Moore buf += len_tmp;
128343761473SPaul Moore }
128443761473SPaul Moore
128543761473SPaul Moore /* ready to move to the next argument? */
128643761473SPaul Moore if ((len_buf == 0) && !require_data) {
128743761473SPaul Moore arg++;
128843761473SPaul Moore iter = 0;
128943761473SPaul Moore len_full = 0;
129043761473SPaul Moore require_data = true;
129143761473SPaul Moore encode = false;
129243761473SPaul Moore }
129343761473SPaul Moore } while (arg < context->execve.argc);
129443761473SPaul Moore
129543761473SPaul Moore /* NOTE: the caller handles the final audit_log_end() call */
129643761473SPaul Moore
129743761473SPaul Moore out:
129843761473SPaul Moore kfree(buf_head);
1299bdf4c48aSPeter Zijlstra }
1300bdf4c48aSPeter Zijlstra
audit_log_cap(struct audit_buffer * ab,char * prefix,kernel_cap_t * cap)13012efa48feSYueHaibing static void audit_log_cap(struct audit_buffer *ab, char *prefix,
13022efa48feSYueHaibing kernel_cap_t *cap)
13035f3d544fSRichard Guy Briggs {
13045f3d544fSRichard Guy Briggs if (cap_isclear(*cap)) {
13055f3d544fSRichard Guy Briggs audit_log_format(ab, " %s=0", prefix);
13065f3d544fSRichard Guy Briggs return;
13075f3d544fSRichard Guy Briggs }
1308f122a08bSLinus Torvalds audit_log_format(ab, " %s=%016llx", prefix, cap->val);
13095f3d544fSRichard Guy Briggs }
13105f3d544fSRichard Guy Briggs
audit_log_fcaps(struct audit_buffer * ab,struct audit_names * name)13115f3d544fSRichard Guy Briggs static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
13125f3d544fSRichard Guy Briggs {
13135f3d544fSRichard Guy Briggs if (name->fcap_ver == -1) {
13145f3d544fSRichard Guy Briggs audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?");
13155f3d544fSRichard Guy Briggs return;
13165f3d544fSRichard Guy Briggs }
13175f3d544fSRichard Guy Briggs audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
13185f3d544fSRichard Guy Briggs audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
13195f3d544fSRichard Guy Briggs audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d",
13205f3d544fSRichard Guy Briggs name->fcap.fE, name->fcap_ver,
13215f3d544fSRichard Guy Briggs from_kuid(&init_user_ns, name->fcap.rootid));
13225f3d544fSRichard Guy Briggs }
13235f3d544fSRichard Guy Briggs
audit_log_time(struct audit_context * context,struct audit_buffer ** ab)1324272ceeaeSRichard Guy Briggs static void audit_log_time(struct audit_context *context, struct audit_buffer **ab)
1325272ceeaeSRichard Guy Briggs {
1326272ceeaeSRichard Guy Briggs const struct audit_ntp_data *ntp = &context->time.ntp_data;
1327272ceeaeSRichard Guy Briggs const struct timespec64 *tk = &context->time.tk_injoffset;
1328272ceeaeSRichard Guy Briggs static const char * const ntp_name[] = {
1329272ceeaeSRichard Guy Briggs "offset",
1330272ceeaeSRichard Guy Briggs "freq",
1331272ceeaeSRichard Guy Briggs "status",
1332272ceeaeSRichard Guy Briggs "tai",
1333272ceeaeSRichard Guy Briggs "tick",
1334272ceeaeSRichard Guy Briggs "adjust",
1335272ceeaeSRichard Guy Briggs };
1336272ceeaeSRichard Guy Briggs int type;
1337272ceeaeSRichard Guy Briggs
1338272ceeaeSRichard Guy Briggs if (context->type == AUDIT_TIME_ADJNTPVAL) {
1339272ceeaeSRichard Guy Briggs for (type = 0; type < AUDIT_NTP_NVALS; type++) {
1340272ceeaeSRichard Guy Briggs if (ntp->vals[type].newval != ntp->vals[type].oldval) {
1341272ceeaeSRichard Guy Briggs if (!*ab) {
1342272ceeaeSRichard Guy Briggs *ab = audit_log_start(context,
1343272ceeaeSRichard Guy Briggs GFP_KERNEL,
1344272ceeaeSRichard Guy Briggs AUDIT_TIME_ADJNTPVAL);
1345272ceeaeSRichard Guy Briggs if (!*ab)
1346272ceeaeSRichard Guy Briggs return;
1347272ceeaeSRichard Guy Briggs }
1348272ceeaeSRichard Guy Briggs audit_log_format(*ab, "op=%s old=%lli new=%lli",
1349272ceeaeSRichard Guy Briggs ntp_name[type],
1350272ceeaeSRichard Guy Briggs ntp->vals[type].oldval,
1351272ceeaeSRichard Guy Briggs ntp->vals[type].newval);
1352272ceeaeSRichard Guy Briggs audit_log_end(*ab);
1353272ceeaeSRichard Guy Briggs *ab = NULL;
1354272ceeaeSRichard Guy Briggs }
1355272ceeaeSRichard Guy Briggs }
1356272ceeaeSRichard Guy Briggs }
1357272ceeaeSRichard Guy Briggs if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
1358272ceeaeSRichard Guy Briggs if (!*ab) {
1359272ceeaeSRichard Guy Briggs *ab = audit_log_start(context, GFP_KERNEL,
1360272ceeaeSRichard Guy Briggs AUDIT_TIME_INJOFFSET);
1361272ceeaeSRichard Guy Briggs if (!*ab)
1362272ceeaeSRichard Guy Briggs return;
1363272ceeaeSRichard Guy Briggs }
1364272ceeaeSRichard Guy Briggs audit_log_format(*ab, "sec=%lli nsec=%li",
1365272ceeaeSRichard Guy Briggs (long long)tk->tv_sec, tk->tv_nsec);
1366272ceeaeSRichard Guy Briggs audit_log_end(*ab);
1367272ceeaeSRichard Guy Briggs *ab = NULL;
1368272ceeaeSRichard Guy Briggs }
1369272ceeaeSRichard Guy Briggs }
1370272ceeaeSRichard Guy Briggs
show_special(struct audit_context * context,int * call_panic)1371a33e6751SAl Viro static void show_special(struct audit_context *context, int *call_panic)
1372f3298dc4SAl Viro {
1373f3298dc4SAl Viro struct audit_buffer *ab;
1374f3298dc4SAl Viro int i;
1375f3298dc4SAl Viro
1376f3298dc4SAl Viro ab = audit_log_start(context, GFP_KERNEL, context->type);
1377f3298dc4SAl Viro if (!ab)
1378f3298dc4SAl Viro return;
1379f3298dc4SAl Viro
1380f3298dc4SAl Viro switch (context->type) {
1381f3298dc4SAl Viro case AUDIT_SOCKETCALL: {
1382f3298dc4SAl Viro int nargs = context->socketcall.nargs;
1383254c8b96SRoni Nevalainen
1384f3298dc4SAl Viro audit_log_format(ab, "nargs=%d", nargs);
1385f3298dc4SAl Viro for (i = 0; i < nargs; i++)
1386f3298dc4SAl Viro audit_log_format(ab, " a%d=%lx", i,
1387f3298dc4SAl Viro context->socketcall.args[i]);
1388f3298dc4SAl Viro break; }
13897183abccSCasey Schaufler case AUDIT_IPC:
13902570ebbdSAl Viro audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho",
1391cca080d9SEric W. Biederman from_kuid(&init_user_ns, context->ipc.uid),
1392cca080d9SEric W. Biederman from_kgid(&init_user_ns, context->ipc.gid),
1393cca080d9SEric W. Biederman context->ipc.mode);
13947183abccSCasey Schaufler if (lsmprop_is_set(&context->ipc.oprop)) {
13952d470c77SCasey Schaufler struct lsm_context lsmctx;
1396254c8b96SRoni Nevalainen
13977183abccSCasey Schaufler if (security_lsmprop_to_secctx(&context->ipc.oprop,
13982d470c77SCasey Schaufler &lsmctx) < 0) {
1399a33e6751SAl Viro *call_panic = 1;
1400a33e6751SAl Viro } else {
14012d470c77SCasey Schaufler audit_log_format(ab, " obj=%s", lsmctx.context);
14022d470c77SCasey Schaufler security_release_secctx(&lsmctx);
1403a33e6751SAl Viro }
1404a33e6751SAl Viro }
1405e816f370SAl Viro if (context->ipc.has_perm) {
1406e816f370SAl Viro audit_log_end(ab);
1407e816f370SAl Viro ab = audit_log_start(context, GFP_KERNEL,
1408e816f370SAl Viro AUDIT_IPC_SET_PERM);
14090644ec0cSKees Cook if (unlikely(!ab))
14100644ec0cSKees Cook return;
1411e816f370SAl Viro audit_log_format(ab,
14122570ebbdSAl Viro "qbytes=%lx ouid=%u ogid=%u mode=%#ho",
1413e816f370SAl Viro context->ipc.qbytes,
1414e816f370SAl Viro context->ipc.perm_uid,
1415e816f370SAl Viro context->ipc.perm_gid,
1416e816f370SAl Viro context->ipc.perm_mode);
1417e816f370SAl Viro }
14187183abccSCasey Schaufler break;
1419fe8e52b9SPaul Moore case AUDIT_MQ_OPEN:
1420564f6993SAl Viro audit_log_format(ab,
1421df0a4283SAl Viro "oflag=0x%x mode=%#ho mq_flags=0x%lx mq_maxmsg=%ld "
1422564f6993SAl Viro "mq_msgsize=%ld mq_curmsgs=%ld",
1423564f6993SAl Viro context->mq_open.oflag, context->mq_open.mode,
1424564f6993SAl Viro context->mq_open.attr.mq_flags,
1425564f6993SAl Viro context->mq_open.attr.mq_maxmsg,
1426564f6993SAl Viro context->mq_open.attr.mq_msgsize,
1427564f6993SAl Viro context->mq_open.attr.mq_curmsgs);
1428fe8e52b9SPaul Moore break;
1429fe8e52b9SPaul Moore case AUDIT_MQ_SENDRECV:
1430c32c8af4SAl Viro audit_log_format(ab,
1431c32c8af4SAl Viro "mqdes=%d msg_len=%zd msg_prio=%u "
1432b9047726SDeepa Dinamani "abs_timeout_sec=%lld abs_timeout_nsec=%ld",
1433c32c8af4SAl Viro context->mq_sendrecv.mqdes,
1434c32c8af4SAl Viro context->mq_sendrecv.msg_len,
1435c32c8af4SAl Viro context->mq_sendrecv.msg_prio,
1436b9047726SDeepa Dinamani (long long) context->mq_sendrecv.abs_timeout.tv_sec,
1437c32c8af4SAl Viro context->mq_sendrecv.abs_timeout.tv_nsec);
1438fe8e52b9SPaul Moore break;
1439fe8e52b9SPaul Moore case AUDIT_MQ_NOTIFY:
144020114f71SAl Viro audit_log_format(ab, "mqdes=%d sigev_signo=%d",
144120114f71SAl Viro context->mq_notify.mqdes,
144220114f71SAl Viro context->mq_notify.sigev_signo);
1443fe8e52b9SPaul Moore break;
14447392906eSAl Viro case AUDIT_MQ_GETSETATTR: {
14457392906eSAl Viro struct mq_attr *attr = &context->mq_getsetattr.mqstat;
1446254c8b96SRoni Nevalainen
14477392906eSAl Viro audit_log_format(ab,
14487392906eSAl Viro "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
14497392906eSAl Viro "mq_curmsgs=%ld ",
14507392906eSAl Viro context->mq_getsetattr.mqdes,
14517392906eSAl Viro attr->mq_flags, attr->mq_maxmsg,
14527392906eSAl Viro attr->mq_msgsize, attr->mq_curmsgs);
14537392906eSAl Viro break; }
1454fe8e52b9SPaul Moore case AUDIT_CAPSET:
145557f71a0aSAl Viro audit_log_format(ab, "pid=%d", context->capset.pid);
145657f71a0aSAl Viro audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
145757f71a0aSAl Viro audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
145857f71a0aSAl Viro audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
14597786f6b6SRichard Guy Briggs audit_log_cap(ab, "cap_pa", &context->capset.cap.ambient);
1460fe8e52b9SPaul Moore break;
1461fe8e52b9SPaul Moore case AUDIT_MMAP:
1462120a795dSAl Viro audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
1463120a795dSAl Viro context->mmap.flags);
1464fe8e52b9SPaul Moore break;
1465571e5c0eSRichard Guy Briggs case AUDIT_OPENAT2:
1466571e5c0eSRichard Guy Briggs audit_log_format(ab, "oflag=0%llo mode=0%llo resolve=0x%llx",
1467571e5c0eSRichard Guy Briggs context->openat2.flags,
1468571e5c0eSRichard Guy Briggs context->openat2.mode,
1469571e5c0eSRichard Guy Briggs context->openat2.resolve);
1470571e5c0eSRichard Guy Briggs break;
1471fe8e52b9SPaul Moore case AUDIT_EXECVE:
1472d9cfea91SRichard Guy Briggs audit_log_execve_info(context, &ab);
1473fe8e52b9SPaul Moore break;
1474ca86cad7SRichard Guy Briggs case AUDIT_KERN_MODULE:
1475ca86cad7SRichard Guy Briggs audit_log_format(ab, "name=");
1476b305f7edSYi Wang if (context->module.name) {
1477ca86cad7SRichard Guy Briggs audit_log_untrustedstring(ab, context->module.name);
1478b305f7edSYi Wang } else
1479b305f7edSYi Wang audit_log_format(ab, "(null)");
1480b305f7edSYi Wang
1481ca86cad7SRichard Guy Briggs break;
1482272ceeaeSRichard Guy Briggs case AUDIT_TIME_ADJNTPVAL:
1483272ceeaeSRichard Guy Briggs case AUDIT_TIME_INJOFFSET:
1484272ceeaeSRichard Guy Briggs /* this call deviates from the rest, eating the buffer */
1485272ceeaeSRichard Guy Briggs audit_log_time(context, &ab);
1486272ceeaeSRichard Guy Briggs break;
1487f3298dc4SAl Viro }
1488f3298dc4SAl Viro audit_log_end(ab);
1489f3298dc4SAl Viro }
1490f3298dc4SAl Viro
audit_proctitle_rtrim(char * proctitle,int len)14913f1c8250SWilliam Roberts static inline int audit_proctitle_rtrim(char *proctitle, int len)
14923f1c8250SWilliam Roberts {
14933f1c8250SWilliam Roberts char *end = proctitle + len - 1;
1494254c8b96SRoni Nevalainen
14953f1c8250SWilliam Roberts while (end > proctitle && !isprint(*end))
14963f1c8250SWilliam Roberts end--;
14973f1c8250SWilliam Roberts
14983f1c8250SWilliam Roberts /* catch the case where proctitle is only 1 non-print character */
14993f1c8250SWilliam Roberts len = end - proctitle + 1;
15003f1c8250SWilliam Roberts len -= isprint(proctitle[len-1]) == 0;
15013f1c8250SWilliam Roberts return len;
15023f1c8250SWilliam Roberts }
15033f1c8250SWilliam Roberts
15045f3d544fSRichard Guy Briggs /*
15055f3d544fSRichard Guy Briggs * audit_log_name - produce AUDIT_PATH record from struct audit_names
15065f3d544fSRichard Guy Briggs * @context: audit_context for the task
15075f3d544fSRichard Guy Briggs * @n: audit_names structure with reportable details
15085f3d544fSRichard Guy Briggs * @path: optional path to report instead of audit_names->name
15095f3d544fSRichard Guy Briggs * @record_num: record number to report when handling a list of names
15105f3d544fSRichard Guy Briggs * @call_panic: optional pointer to int that will be updated if secid fails
15115f3d544fSRichard Guy Briggs */
audit_log_name(struct audit_context * context,struct audit_names * n,const struct path * path,int record_num,int * call_panic)15125f3d544fSRichard Guy Briggs static void audit_log_name(struct audit_context *context, struct audit_names *n,
15135f3d544fSRichard Guy Briggs const struct path *path, int record_num, int *call_panic)
15145f3d544fSRichard Guy Briggs {
15155f3d544fSRichard Guy Briggs struct audit_buffer *ab;
15165f3d544fSRichard Guy Briggs
15175f3d544fSRichard Guy Briggs ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
15185f3d544fSRichard Guy Briggs if (!ab)
15195f3d544fSRichard Guy Briggs return;
15205f3d544fSRichard Guy Briggs
15215f3d544fSRichard Guy Briggs audit_log_format(ab, "item=%d", record_num);
15225f3d544fSRichard Guy Briggs
15235f3d544fSRichard Guy Briggs if (path)
15245f3d544fSRichard Guy Briggs audit_log_d_path(ab, " name=", path);
15255f3d544fSRichard Guy Briggs else if (n->name) {
15265f3d544fSRichard Guy Briggs switch (n->name_len) {
15275f3d544fSRichard Guy Briggs case AUDIT_NAME_FULL:
15285f3d544fSRichard Guy Briggs /* log the full path */
15295f3d544fSRichard Guy Briggs audit_log_format(ab, " name=");
15305f3d544fSRichard Guy Briggs audit_log_untrustedstring(ab, n->name->name);
15315f3d544fSRichard Guy Briggs break;
15325f3d544fSRichard Guy Briggs case 0:
15335f3d544fSRichard Guy Briggs /* name was specified as a relative path and the
15345f3d544fSRichard Guy Briggs * directory component is the cwd
15355f3d544fSRichard Guy Briggs */
15366d915476SRichard Guy Briggs if (context->pwd.dentry && context->pwd.mnt)
15375f3d544fSRichard Guy Briggs audit_log_d_path(ab, " name=", &context->pwd);
15386d915476SRichard Guy Briggs else
15396d915476SRichard Guy Briggs audit_log_format(ab, " name=(null)");
15405f3d544fSRichard Guy Briggs break;
15415f3d544fSRichard Guy Briggs default:
15425f3d544fSRichard Guy Briggs /* log the name's directory component */
15435f3d544fSRichard Guy Briggs audit_log_format(ab, " name=");
15445f3d544fSRichard Guy Briggs audit_log_n_untrustedstring(ab, n->name->name,
15455f3d544fSRichard Guy Briggs n->name_len);
15465f3d544fSRichard Guy Briggs }
15475f3d544fSRichard Guy Briggs } else
15485f3d544fSRichard Guy Briggs audit_log_format(ab, " name=(null)");
15495f3d544fSRichard Guy Briggs
15505f3d544fSRichard Guy Briggs if (n->ino != AUDIT_INO_UNSET)
15515f3d544fSRichard Guy Briggs audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x",
15525f3d544fSRichard Guy Briggs n->ino,
15535f3d544fSRichard Guy Briggs MAJOR(n->dev),
15545f3d544fSRichard Guy Briggs MINOR(n->dev),
15555f3d544fSRichard Guy Briggs n->mode,
15565f3d544fSRichard Guy Briggs from_kuid(&init_user_ns, n->uid),
15575f3d544fSRichard Guy Briggs from_kgid(&init_user_ns, n->gid),
15585f3d544fSRichard Guy Briggs MAJOR(n->rdev),
15595f3d544fSRichard Guy Briggs MINOR(n->rdev));
1560e0a8dcbdSCasey Schaufler if (lsmprop_is_set(&n->oprop)) {
15616fba8981SCasey Schaufler struct lsm_context ctx;
15625f3d544fSRichard Guy Briggs
15632d470c77SCasey Schaufler if (security_lsmprop_to_secctx(&n->oprop, &ctx) < 0) {
15645f3d544fSRichard Guy Briggs if (call_panic)
15655f3d544fSRichard Guy Briggs *call_panic = 2;
15665f3d544fSRichard Guy Briggs } else {
15676fba8981SCasey Schaufler audit_log_format(ab, " obj=%s", ctx.context);
15686fba8981SCasey Schaufler security_release_secctx(&ctx);
15695f3d544fSRichard Guy Briggs }
15705f3d544fSRichard Guy Briggs }
15715f3d544fSRichard Guy Briggs
15725f3d544fSRichard Guy Briggs /* log the audit_names record type */
15735f3d544fSRichard Guy Briggs switch (n->type) {
15745f3d544fSRichard Guy Briggs case AUDIT_TYPE_NORMAL:
15755f3d544fSRichard Guy Briggs audit_log_format(ab, " nametype=NORMAL");
15765f3d544fSRichard Guy Briggs break;
15775f3d544fSRichard Guy Briggs case AUDIT_TYPE_PARENT:
15785f3d544fSRichard Guy Briggs audit_log_format(ab, " nametype=PARENT");
15795f3d544fSRichard Guy Briggs break;
15805f3d544fSRichard Guy Briggs case AUDIT_TYPE_CHILD_DELETE:
15815f3d544fSRichard Guy Briggs audit_log_format(ab, " nametype=DELETE");
15825f3d544fSRichard Guy Briggs break;
15835f3d544fSRichard Guy Briggs case AUDIT_TYPE_CHILD_CREATE:
15845f3d544fSRichard Guy Briggs audit_log_format(ab, " nametype=CREATE");
15855f3d544fSRichard Guy Briggs break;
15865f3d544fSRichard Guy Briggs default:
15875f3d544fSRichard Guy Briggs audit_log_format(ab, " nametype=UNKNOWN");
15885f3d544fSRichard Guy Briggs break;
15895f3d544fSRichard Guy Briggs }
15905f3d544fSRichard Guy Briggs
15915f3d544fSRichard Guy Briggs audit_log_fcaps(ab, n);
15925f3d544fSRichard Guy Briggs audit_log_end(ab);
15935f3d544fSRichard Guy Briggs }
15945f3d544fSRichard Guy Briggs
audit_log_proctitle(void)15952a1fe215SPaul Moore static void audit_log_proctitle(void)
15963f1c8250SWilliam Roberts {
15973f1c8250SWilliam Roberts int res;
15983f1c8250SWilliam Roberts char *buf;
15993f1c8250SWilliam Roberts char *msg = "(null)";
16003f1c8250SWilliam Roberts int len = strlen(msg);
16012a1fe215SPaul Moore struct audit_context *context = audit_context();
16023f1c8250SWilliam Roberts struct audit_buffer *ab;
16033f1c8250SWilliam Roberts
16043f1c8250SWilliam Roberts ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
16053f1c8250SWilliam Roberts if (!ab)
16063f1c8250SWilliam Roberts return; /* audit_panic or being filtered */
16073f1c8250SWilliam Roberts
16083f1c8250SWilliam Roberts audit_log_format(ab, "proctitle=");
16093f1c8250SWilliam Roberts
16103f1c8250SWilliam Roberts /* Not cached */
16113f1c8250SWilliam Roberts if (!context->proctitle.value) {
16123f1c8250SWilliam Roberts buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL);
16133f1c8250SWilliam Roberts if (!buf)
16143f1c8250SWilliam Roberts goto out;
16153f1c8250SWilliam Roberts /* Historically called this from procfs naming */
16162a1fe215SPaul Moore res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN);
16173f1c8250SWilliam Roberts if (res == 0) {
16183f1c8250SWilliam Roberts kfree(buf);
16193f1c8250SWilliam Roberts goto out;
16203f1c8250SWilliam Roberts }
16213f1c8250SWilliam Roberts res = audit_proctitle_rtrim(buf, res);
16223f1c8250SWilliam Roberts if (res == 0) {
16233f1c8250SWilliam Roberts kfree(buf);
16243f1c8250SWilliam Roberts goto out;
16253f1c8250SWilliam Roberts }
16263f1c8250SWilliam Roberts context->proctitle.value = buf;
16273f1c8250SWilliam Roberts context->proctitle.len = res;
16283f1c8250SWilliam Roberts }
16293f1c8250SWilliam Roberts msg = context->proctitle.value;
16303f1c8250SWilliam Roberts len = context->proctitle.len;
16313f1c8250SWilliam Roberts out:
16323f1c8250SWilliam Roberts audit_log_n_untrustedstring(ab, msg, len);
16333f1c8250SWilliam Roberts audit_log_end(ab);
16343f1c8250SWilliam Roberts }
16353f1c8250SWilliam Roberts
16365bd2182dSPaul Moore /**
16375bd2182dSPaul Moore * audit_log_uring - generate a AUDIT_URINGOP record
16385bd2182dSPaul Moore * @ctx: the audit context
16395bd2182dSPaul Moore */
audit_log_uring(struct audit_context * ctx)16405bd2182dSPaul Moore static void audit_log_uring(struct audit_context *ctx)
16415bd2182dSPaul Moore {
16425bd2182dSPaul Moore struct audit_buffer *ab;
16435bd2182dSPaul Moore const struct cred *cred;
16445bd2182dSPaul Moore
16455bd2182dSPaul Moore ab = audit_log_start(ctx, GFP_ATOMIC, AUDIT_URINGOP);
16465bd2182dSPaul Moore if (!ab)
16475bd2182dSPaul Moore return;
16485bd2182dSPaul Moore cred = current_cred();
16495bd2182dSPaul Moore audit_log_format(ab, "uring_op=%d", ctx->uring_op);
16505bd2182dSPaul Moore if (ctx->return_valid != AUDITSC_INVALID)
16515bd2182dSPaul Moore audit_log_format(ab, " success=%s exit=%ld",
165289282beaSThorsten Blum str_yes_no(ctx->return_valid ==
165389282beaSThorsten Blum AUDITSC_SUCCESS),
16545bd2182dSPaul Moore ctx->return_code);
16555bd2182dSPaul Moore audit_log_format(ab,
16565bd2182dSPaul Moore " items=%d"
16575bd2182dSPaul Moore " ppid=%d pid=%d uid=%u gid=%u euid=%u suid=%u"
16585bd2182dSPaul Moore " fsuid=%u egid=%u sgid=%u fsgid=%u",
16595bd2182dSPaul Moore ctx->name_count,
16605bd2182dSPaul Moore task_ppid_nr(current), task_tgid_nr(current),
16615bd2182dSPaul Moore from_kuid(&init_user_ns, cred->uid),
16625bd2182dSPaul Moore from_kgid(&init_user_ns, cred->gid),
16635bd2182dSPaul Moore from_kuid(&init_user_ns, cred->euid),
16645bd2182dSPaul Moore from_kuid(&init_user_ns, cred->suid),
16655bd2182dSPaul Moore from_kuid(&init_user_ns, cred->fsuid),
16665bd2182dSPaul Moore from_kgid(&init_user_ns, cred->egid),
16675bd2182dSPaul Moore from_kgid(&init_user_ns, cred->sgid),
16685bd2182dSPaul Moore from_kgid(&init_user_ns, cred->fsgid));
16695bd2182dSPaul Moore audit_log_task_context(ab);
16705bd2182dSPaul Moore audit_log_key(ab, ctx->filterkey);
16715bd2182dSPaul Moore audit_log_end(ab);
16725bd2182dSPaul Moore }
16735bd2182dSPaul Moore
audit_log_exit(void)16742a1fe215SPaul Moore static void audit_log_exit(void)
16751da177e4SLinus Torvalds {
16769c7aa6aaSSteve Grubb int i, call_panic = 0;
16772a1fe215SPaul Moore struct audit_context *context = audit_context();
16781da177e4SLinus Torvalds struct audit_buffer *ab;
16797551ced3SDavid Woodhouse struct audit_aux_data *aux;
16805195d8e2SEric Paris struct audit_names *n;
16811da177e4SLinus Torvalds
16822a1fe215SPaul Moore context->personality = current->personality;
1683e495149bSAl Viro
168412c5e81dSPaul Moore switch (context->context) {
168512c5e81dSPaul Moore case AUDIT_CTX_SYSCALL:
1686e495149bSAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
16871da177e4SLinus Torvalds if (!ab)
168812c5e81dSPaul Moore return;
1689bccf6ae0SDavid Woodhouse audit_log_format(ab, "arch=%x syscall=%d",
1690bccf6ae0SDavid Woodhouse context->arch, context->major);
16911da177e4SLinus Torvalds if (context->personality != PER_LINUX)
16921da177e4SLinus Torvalds audit_log_format(ab, " per=%lx", context->personality);
1693ba59eae7SAlex Shi if (context->return_valid != AUDITSC_INVALID)
16942fd6f58bS audit_log_format(ab, " success=%s exit=%ld",
169589282beaSThorsten Blum str_yes_no(context->return_valid ==
169689282beaSThorsten Blum AUDITSC_SUCCESS),
16972fd6f58bS context->return_code);
16981da177e4SLinus Torvalds audit_log_format(ab,
1699e23eb920SPeter Moody " a0=%lx a1=%lx a2=%lx a3=%lx items=%d",
17001da177e4SLinus Torvalds context->argv[0],
17011da177e4SLinus Torvalds context->argv[1],
17021da177e4SLinus Torvalds context->argv[2],
17031da177e4SLinus Torvalds context->argv[3],
1704e23eb920SPeter Moody context->name_count);
17052a1fe215SPaul Moore audit_log_task_info(ab);
17069d960985SEric Paris audit_log_key(ab, context->filterkey);
17071da177e4SLinus Torvalds audit_log_end(ab);
170812c5e81dSPaul Moore break;
17095bd2182dSPaul Moore case AUDIT_CTX_URING:
17105bd2182dSPaul Moore audit_log_uring(context);
17115bd2182dSPaul Moore break;
171212c5e81dSPaul Moore default:
171312c5e81dSPaul Moore BUG();
171412c5e81dSPaul Moore break;
171512c5e81dSPaul Moore }
17161da177e4SLinus Torvalds
17177551ced3SDavid Woodhouse for (aux = context->aux; aux; aux = aux->next) {
1718c0404993SSteve Grubb
1719e495149bSAl Viro ab = audit_log_start(context, GFP_KERNEL, aux->type);
17201da177e4SLinus Torvalds if (!ab)
17211da177e4SLinus Torvalds continue; /* audit_panic has been called */
17221da177e4SLinus Torvalds
17231da177e4SLinus Torvalds switch (aux->type) {
172420ca73bcSGeorge C. Wilson
17253fc689e9SEric Paris case AUDIT_BPRM_FCAPS: {
17263fc689e9SEric Paris struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
1727254c8b96SRoni Nevalainen
17283fc689e9SEric Paris audit_log_format(ab, "fver=%x", axs->fcap_ver);
17293fc689e9SEric Paris audit_log_cap(ab, "fp", &axs->fcap.permitted);
17303fc689e9SEric Paris audit_log_cap(ab, "fi", &axs->fcap.inheritable);
17313fc689e9SEric Paris audit_log_format(ab, " fe=%d", axs->fcap.fE);
17323fc689e9SEric Paris audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
17333fc689e9SEric Paris audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
17343fc689e9SEric Paris audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
17357786f6b6SRichard Guy Briggs audit_log_cap(ab, "old_pa", &axs->old_pcap.ambient);
17367786f6b6SRichard Guy Briggs audit_log_cap(ab, "pp", &axs->new_pcap.permitted);
17377786f6b6SRichard Guy Briggs audit_log_cap(ab, "pi", &axs->new_pcap.inheritable);
17387786f6b6SRichard Guy Briggs audit_log_cap(ab, "pe", &axs->new_pcap.effective);
17397786f6b6SRichard Guy Briggs audit_log_cap(ab, "pa", &axs->new_pcap.ambient);
17402fec30e2SRichard Guy Briggs audit_log_format(ab, " frootid=%d",
17412fec30e2SRichard Guy Briggs from_kuid(&init_user_ns,
17422fec30e2SRichard Guy Briggs axs->fcap.rootid));
17433fc689e9SEric Paris break; }
17443fc689e9SEric Paris
17451da177e4SLinus Torvalds }
17461da177e4SLinus Torvalds audit_log_end(ab);
17471da177e4SLinus Torvalds }
17481da177e4SLinus Torvalds
1749f3298dc4SAl Viro if (context->type)
1750a33e6751SAl Viro show_special(context, &call_panic);
1751f3298dc4SAl Viro
1752157cf649SAl Viro if (context->fds[0] >= 0) {
1753157cf649SAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR);
1754157cf649SAl Viro if (ab) {
1755157cf649SAl Viro audit_log_format(ab, "fd0=%d fd1=%d",
1756157cf649SAl Viro context->fds[0], context->fds[1]);
1757157cf649SAl Viro audit_log_end(ab);
1758157cf649SAl Viro }
1759157cf649SAl Viro }
1760157cf649SAl Viro
17614f6b434fSAl Viro if (context->sockaddr_len) {
17624f6b434fSAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR);
17634f6b434fSAl Viro if (ab) {
17644f6b434fSAl Viro audit_log_format(ab, "saddr=");
17654f6b434fSAl Viro audit_log_n_hex(ab, (void *)context->sockaddr,
17664f6b434fSAl Viro context->sockaddr_len);
17674f6b434fSAl Viro audit_log_end(ab);
17684f6b434fSAl Viro }
17694f6b434fSAl Viro }
17704f6b434fSAl Viro
1771e54dc243SAmy Griffis for (aux = context->aux_pids; aux; aux = aux->next) {
1772e54dc243SAmy Griffis struct audit_aux_data_pids *axs = (void *)aux;
1773e54dc243SAmy Griffis
1774e54dc243SAmy Griffis for (i = 0; i < axs->pid_count; i++)
1775e54dc243SAmy Griffis if (audit_log_pid_context(context, axs->target_pid[i],
1776c2a7780eSEric Paris axs->target_auid[i],
1777c2a7780eSEric Paris axs->target_uid[i],
17784746ec5bSEric Paris axs->target_sessionid[i],
177913d826e5SCasey Schaufler &axs->target_ref[i],
1780c2a7780eSEric Paris axs->target_comm[i]))
1781e54dc243SAmy Griffis call_panic = 1;
1782a5cb013dSAl Viro }
1783e54dc243SAmy Griffis
1784e54dc243SAmy Griffis if (context->target_pid &&
1785e54dc243SAmy Griffis audit_log_pid_context(context, context->target_pid,
1786c2a7780eSEric Paris context->target_auid, context->target_uid,
17874746ec5bSEric Paris context->target_sessionid,
178813d826e5SCasey Schaufler &context->target_ref, context->target_comm))
1789e54dc243SAmy Griffis call_panic = 1;
1790a5cb013dSAl Viro
179144707fdfSJan Blunck if (context->pwd.dentry && context->pwd.mnt) {
1792e495149bSAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
17938f37d47cSDavid Woodhouse if (ab) {
179444707fdfSJan Blunck audit_log_d_path(ab, "cwd=", &context->pwd);
17958f37d47cSDavid Woodhouse audit_log_end(ab);
17968f37d47cSDavid Woodhouse }
17978f37d47cSDavid Woodhouse }
179873241cccSAmy Griffis
17995195d8e2SEric Paris i = 0;
180079f6530cSJeff Layton list_for_each_entry(n, &context->names_list, list) {
180179f6530cSJeff Layton if (n->hidden)
180279f6530cSJeff Layton continue;
1803b24a30a7SEric Paris audit_log_name(context, n, NULL, i++, &call_panic);
180479f6530cSJeff Layton }
1805c0641f28SEric Paris
180612c5e81dSPaul Moore if (context->context == AUDIT_CTX_SYSCALL)
18072a1fe215SPaul Moore audit_log_proctitle();
18083f1c8250SWilliam Roberts
1809c0641f28SEric Paris /* Send end of event record to help user space know we are finished */
1810c0641f28SEric Paris ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
1811c0641f28SEric Paris if (ab)
1812c0641f28SEric Paris audit_log_end(ab);
18131b50eed9SSteve Grubb if (call_panic)
181412c5e81dSPaul Moore audit_panic("error in audit_log_exit()");
18151da177e4SLinus Torvalds }
18161da177e4SLinus Torvalds
1817b0dd25a8SRandy Dunlap /**
1818196a5085SGeliang Tang * __audit_free - free a per-task audit context
1819b0dd25a8SRandy Dunlap * @tsk: task whose audit context block to free
1820b0dd25a8SRandy Dunlap *
182167daf270SPaul Moore * Called from copy_process, do_exit, and the io_uring code
1822b0dd25a8SRandy Dunlap */
__audit_free(struct task_struct * tsk)1823a4ff8dbaSEric Paris void __audit_free(struct task_struct *tsk)
18241da177e4SLinus Torvalds {
18252a1fe215SPaul Moore struct audit_context *context = tsk->audit_context;
18261da177e4SLinus Torvalds
182756179a6eSEric Paris if (!context)
18281da177e4SLinus Torvalds return;
18291da177e4SLinus Torvalds
183012c5e81dSPaul Moore /* this may generate CONFIG_CHANGE records */
18319e36a5d4SRichard Guy Briggs if (!list_empty(&context->killed_trees))
18329e36a5d4SRichard Guy Briggs audit_kill_trees(context);
18339e36a5d4SRichard Guy Briggs
18342a1fe215SPaul Moore /* We are called either by do_exit() or the fork() error handling code;
18352a1fe215SPaul Moore * in the former case tsk == current and in the latter tsk is a
18360351dc57SJilin Yuan * random task_struct that doesn't have any meaningful data we
18372a1fe215SPaul Moore * need to log via audit_log_exit().
18382a1fe215SPaul Moore */
183967daf270SPaul Moore if (tsk == current && !context->dummy) {
1840ba59eae7SAlex Shi context->return_valid = AUDITSC_INVALID;
18412a1fe215SPaul Moore context->return_code = 0;
184267daf270SPaul Moore if (context->context == AUDIT_CTX_SYSCALL) {
18435504a69aSRichard Guy Briggs audit_filter_syscall(tsk, context);
18442a1fe215SPaul Moore audit_filter_inodes(tsk, context);
1845619ed58aSSergey Nazarov if (context->current_state == AUDIT_STATE_RECORD)
18462a1fe215SPaul Moore audit_log_exit();
184767daf270SPaul Moore } else if (context->context == AUDIT_CTX_URING) {
184867daf270SPaul Moore /* TODO: verify this case is real and valid */
184967daf270SPaul Moore audit_filter_uring(tsk, context);
185067daf270SPaul Moore audit_filter_inodes(tsk, context);
185167daf270SPaul Moore if (context->current_state == AUDIT_STATE_RECORD)
185267daf270SPaul Moore audit_log_uring(context);
185367daf270SPaul Moore }
18542a1fe215SPaul Moore }
18552a1fe215SPaul Moore
18562a1fe215SPaul Moore audit_set_context(tsk, NULL);
18571da177e4SLinus Torvalds audit_free_context(context);
18581da177e4SLinus Torvalds }
18591da177e4SLinus Torvalds
1860b0dd25a8SRandy Dunlap /**
186112c5e81dSPaul Moore * audit_return_fixup - fixup the return codes in the audit_context
186212c5e81dSPaul Moore * @ctx: the audit_context
186312c5e81dSPaul Moore * @success: true/false value to indicate if the operation succeeded or not
186412c5e81dSPaul Moore * @code: operation return code
186512c5e81dSPaul Moore *
186612c5e81dSPaul Moore * We need to fixup the return code in the audit logs if the actual return
186712c5e81dSPaul Moore * codes are later going to be fixed by the arch specific signal handlers.
186812c5e81dSPaul Moore */
audit_return_fixup(struct audit_context * ctx,int success,long code)186912c5e81dSPaul Moore static void audit_return_fixup(struct audit_context *ctx,
187012c5e81dSPaul Moore int success, long code)
187112c5e81dSPaul Moore {
187212c5e81dSPaul Moore /*
187312c5e81dSPaul Moore * This is actually a test for:
187412c5e81dSPaul Moore * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) ||
187512c5e81dSPaul Moore * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK)
187612c5e81dSPaul Moore *
187712c5e81dSPaul Moore * but is faster than a bunch of ||
187812c5e81dSPaul Moore */
187912c5e81dSPaul Moore if (unlikely(code <= -ERESTARTSYS) &&
188012c5e81dSPaul Moore (code >= -ERESTART_RESTARTBLOCK) &&
188112c5e81dSPaul Moore (code != -ENOIOCTLCMD))
188212c5e81dSPaul Moore ctx->return_code = -EINTR;
188312c5e81dSPaul Moore else
188412c5e81dSPaul Moore ctx->return_code = code;
188512c5e81dSPaul Moore ctx->return_valid = (success ? AUDITSC_SUCCESS : AUDITSC_FAILURE);
188612c5e81dSPaul Moore }
188712c5e81dSPaul Moore
188812c5e81dSPaul Moore /**
18895bd2182dSPaul Moore * __audit_uring_entry - prepare the kernel task's audit context for io_uring
18905bd2182dSPaul Moore * @op: the io_uring opcode
18915bd2182dSPaul Moore *
18925bd2182dSPaul Moore * This is similar to audit_syscall_entry() but is intended for use by io_uring
18935bd2182dSPaul Moore * operations. This function should only ever be called from
18945bd2182dSPaul Moore * audit_uring_entry() as we rely on the audit context checking present in that
18955bd2182dSPaul Moore * function.
18965bd2182dSPaul Moore */
__audit_uring_entry(u8 op)18975bd2182dSPaul Moore void __audit_uring_entry(u8 op)
18985bd2182dSPaul Moore {
18995bd2182dSPaul Moore struct audit_context *ctx = audit_context();
19005bd2182dSPaul Moore
19015bd2182dSPaul Moore if (ctx->state == AUDIT_STATE_DISABLED)
19025bd2182dSPaul Moore return;
19035bd2182dSPaul Moore
19045bd2182dSPaul Moore /*
19055bd2182dSPaul Moore * NOTE: It's possible that we can be called from the process' context
19065bd2182dSPaul Moore * before it returns to userspace, and before audit_syscall_exit()
19075bd2182dSPaul Moore * is called. In this case there is not much to do, just record
19085bd2182dSPaul Moore * the io_uring details and return.
19095bd2182dSPaul Moore */
19105bd2182dSPaul Moore ctx->uring_op = op;
19115bd2182dSPaul Moore if (ctx->context == AUDIT_CTX_SYSCALL)
19125bd2182dSPaul Moore return;
19135bd2182dSPaul Moore
19145bd2182dSPaul Moore ctx->dummy = !audit_n_rules;
19155bd2182dSPaul Moore if (!ctx->dummy && ctx->state == AUDIT_STATE_BUILD)
19165bd2182dSPaul Moore ctx->prio = 0;
19175bd2182dSPaul Moore
19185bd2182dSPaul Moore ctx->context = AUDIT_CTX_URING;
19195bd2182dSPaul Moore ctx->current_state = ctx->state;
19205bd2182dSPaul Moore ktime_get_coarse_real_ts64(&ctx->ctime);
19215bd2182dSPaul Moore }
19225bd2182dSPaul Moore
19235bd2182dSPaul Moore /**
19245bd2182dSPaul Moore * __audit_uring_exit - wrap up the kernel task's audit context after io_uring
19255bd2182dSPaul Moore * @success: true/false value to indicate if the operation succeeded or not
19265bd2182dSPaul Moore * @code: operation return code
19275bd2182dSPaul Moore *
19285bd2182dSPaul Moore * This is similar to audit_syscall_exit() but is intended for use by io_uring
19295bd2182dSPaul Moore * operations. This function should only ever be called from
19305bd2182dSPaul Moore * audit_uring_exit() as we rely on the audit context checking present in that
19315bd2182dSPaul Moore * function.
19325bd2182dSPaul Moore */
__audit_uring_exit(int success,long code)19335bd2182dSPaul Moore void __audit_uring_exit(int success, long code)
19345bd2182dSPaul Moore {
19355bd2182dSPaul Moore struct audit_context *ctx = audit_context();
19365bd2182dSPaul Moore
193769e9cd66SJulian Orth if (ctx->dummy) {
193869e9cd66SJulian Orth if (ctx->context != AUDIT_CTX_URING)
193969e9cd66SJulian Orth return;
194069e9cd66SJulian Orth goto out;
194169e9cd66SJulian Orth }
194269e9cd66SJulian Orth
1943d4fefa48SRichard Guy Briggs audit_return_fixup(ctx, success, code);
19445bd2182dSPaul Moore if (ctx->context == AUDIT_CTX_SYSCALL) {
19455bd2182dSPaul Moore /*
19465bd2182dSPaul Moore * NOTE: See the note in __audit_uring_entry() about the case
19475bd2182dSPaul Moore * where we may be called from process context before we
19485bd2182dSPaul Moore * return to userspace via audit_syscall_exit(). In this
19495bd2182dSPaul Moore * case we simply emit a URINGOP record and bail, the
19505bd2182dSPaul Moore * normal syscall exit handling will take care of
19515bd2182dSPaul Moore * everything else.
19525bd2182dSPaul Moore * It is also worth mentioning that when we are called,
19535bd2182dSPaul Moore * the current process creds may differ from the creds
19545bd2182dSPaul Moore * used during the normal syscall processing; keep that
19555bd2182dSPaul Moore * in mind if/when we move the record generation code.
19565bd2182dSPaul Moore */
19575bd2182dSPaul Moore
19585bd2182dSPaul Moore /*
19595bd2182dSPaul Moore * We need to filter on the syscall info here to decide if we
19605bd2182dSPaul Moore * should emit a URINGOP record. I know it seems odd but this
19615bd2182dSPaul Moore * solves the problem where users have a filter to block *all*
19625bd2182dSPaul Moore * syscall records in the "exit" filter; we want to preserve
19635bd2182dSPaul Moore * the behavior here.
19645bd2182dSPaul Moore */
19655bd2182dSPaul Moore audit_filter_syscall(current, ctx);
196667daf270SPaul Moore if (ctx->current_state != AUDIT_STATE_RECORD)
196767daf270SPaul Moore audit_filter_uring(current, ctx);
19685bd2182dSPaul Moore audit_filter_inodes(current, ctx);
19695bd2182dSPaul Moore if (ctx->current_state != AUDIT_STATE_RECORD)
19705bd2182dSPaul Moore return;
19715bd2182dSPaul Moore
19725bd2182dSPaul Moore audit_log_uring(ctx);
19735bd2182dSPaul Moore return;
19745bd2182dSPaul Moore }
19755bd2182dSPaul Moore
19765bd2182dSPaul Moore /* this may generate CONFIG_CHANGE records */
19775bd2182dSPaul Moore if (!list_empty(&ctx->killed_trees))
19785bd2182dSPaul Moore audit_kill_trees(ctx);
19795bd2182dSPaul Moore
198067daf270SPaul Moore /* run through both filters to ensure we set the filterkey properly */
198167daf270SPaul Moore audit_filter_uring(current, ctx);
19825bd2182dSPaul Moore audit_filter_inodes(current, ctx);
19835bd2182dSPaul Moore if (ctx->current_state != AUDIT_STATE_RECORD)
19845bd2182dSPaul Moore goto out;
19855bd2182dSPaul Moore audit_log_exit();
19865bd2182dSPaul Moore
19875bd2182dSPaul Moore out:
19885bd2182dSPaul Moore audit_reset_context(ctx);
19895bd2182dSPaul Moore }
19905bd2182dSPaul Moore
19915bd2182dSPaul Moore /**
1992196a5085SGeliang Tang * __audit_syscall_entry - fill in an audit record at syscall entry
1993b0dd25a8SRandy Dunlap * @major: major syscall type (function)
1994b0dd25a8SRandy Dunlap * @a1: additional syscall register 1
1995b0dd25a8SRandy Dunlap * @a2: additional syscall register 2
1996b0dd25a8SRandy Dunlap * @a3: additional syscall register 3
1997b0dd25a8SRandy Dunlap * @a4: additional syscall register 4
1998b0dd25a8SRandy Dunlap *
1999b0dd25a8SRandy Dunlap * Fill in audit context at syscall entry. This only happens if the
20001da177e4SLinus Torvalds * audit context was created when the task was created and the state or
20011da177e4SLinus Torvalds * filters demand the audit context be built. If the state from the
2002619ed58aSSergey Nazarov * per-task filter or from the per-syscall filter is AUDIT_STATE_RECORD,
20031da177e4SLinus Torvalds * then the record will be written at syscall exit time (otherwise, it
20041da177e4SLinus Torvalds * will only be written if another part of the kernel requests that it
2005b0dd25a8SRandy Dunlap * be written).
2006b0dd25a8SRandy Dunlap */
__audit_syscall_entry(int major,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4)2007b4f0d375SRichard Guy Briggs void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
20081da177e4SLinus Torvalds unsigned long a3, unsigned long a4)
20091da177e4SLinus Torvalds {
2010cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
20111da177e4SLinus Torvalds enum audit_state state;
20121da177e4SLinus Torvalds
201394d14e3eSRichard Guy Briggs if (!audit_enabled || !context)
201486a1c34aSRoland McGrath return;
20151da177e4SLinus Torvalds
201612c5e81dSPaul Moore WARN_ON(context->context != AUDIT_CTX_UNUSED);
201712c5e81dSPaul Moore WARN_ON(context->name_count);
201812c5e81dSPaul Moore if (context->context != AUDIT_CTX_UNUSED || context->name_count) {
201912c5e81dSPaul Moore audit_panic("unrecoverable error in audit_syscall_entry()");
202012c5e81dSPaul Moore return;
202112c5e81dSPaul Moore }
20221da177e4SLinus Torvalds
20235260ecc2SRichard Guy Briggs state = context->state;
2024619ed58aSSergey Nazarov if (state == AUDIT_STATE_DISABLED)
20255260ecc2SRichard Guy Briggs return;
20265260ecc2SRichard Guy Briggs
20275260ecc2SRichard Guy Briggs context->dummy = !audit_n_rules;
2028619ed58aSSergey Nazarov if (!context->dummy && state == AUDIT_STATE_BUILD) {
20295260ecc2SRichard Guy Briggs context->prio = 0;
2030cdfb6b34SRichard Guy Briggs if (auditd_test_task(current))
20315260ecc2SRichard Guy Briggs return;
20325260ecc2SRichard Guy Briggs }
20335260ecc2SRichard Guy Briggs
203416add411SDmitry V. Levin context->arch = syscall_get_arch(current);
20351da177e4SLinus Torvalds context->major = major;
20361da177e4SLinus Torvalds context->argv[0] = a1;
20371da177e4SLinus Torvalds context->argv[1] = a2;
20381da177e4SLinus Torvalds context->argv[2] = a3;
20391da177e4SLinus Torvalds context->argv[3] = a4;
204012c5e81dSPaul Moore context->context = AUDIT_CTX_SYSCALL;
20410590b933SAl Viro context->current_state = state;
2042290e44b7SPaul Moore ktime_get_coarse_real_ts64(&context->ctime);
20431da177e4SLinus Torvalds }
20441da177e4SLinus Torvalds
2045b0dd25a8SRandy Dunlap /**
2046196a5085SGeliang Tang * __audit_syscall_exit - deallocate audit context after a system call
204742ae610cSRandy Dunlap * @success: success value of the syscall
204842ae610cSRandy Dunlap * @return_code: return value of the syscall
2049b0dd25a8SRandy Dunlap *
2050b0dd25a8SRandy Dunlap * Tear down after system call. If the audit context has been marked as
2051619ed58aSSergey Nazarov * auditable (either because of the AUDIT_STATE_RECORD state from
205242ae610cSRandy Dunlap * filtering, or because some other part of the kernel wrote an audit
20531da177e4SLinus Torvalds * message), then write out the syscall information. In call cases,
2054b0dd25a8SRandy Dunlap * free the names stored from getname().
2055b0dd25a8SRandy Dunlap */
__audit_syscall_exit(int success,long return_code)2056d7e7528bSEric Paris void __audit_syscall_exit(int success, long return_code)
20571da177e4SLinus Torvalds {
205812c5e81dSPaul Moore struct audit_context *context = audit_context();
20591da177e4SLinus Torvalds
206012c5e81dSPaul Moore if (!context || context->dummy ||
206112c5e81dSPaul Moore context->context != AUDIT_CTX_SYSCALL)
206212c5e81dSPaul Moore goto out;
20631da177e4SLinus Torvalds
206412c5e81dSPaul Moore /* this may generate CONFIG_CHANGE records */
20659e36a5d4SRichard Guy Briggs if (!list_empty(&context->killed_trees))
20669e36a5d4SRichard Guy Briggs audit_kill_trees(context);
20679e36a5d4SRichard Guy Briggs
2068d4fefa48SRichard Guy Briggs audit_return_fixup(context, success, return_code);
206912c5e81dSPaul Moore /* run through both filters to ensure we set the filterkey properly */
20705504a69aSRichard Guy Briggs audit_filter_syscall(current, context);
20712a1fe215SPaul Moore audit_filter_inodes(current, context);
20723ed66951SRichard Guy Briggs if (context->current_state != AUDIT_STATE_RECORD)
207312c5e81dSPaul Moore goto out;
207412c5e81dSPaul Moore
20752a1fe215SPaul Moore audit_log_exit();
20761da177e4SLinus Torvalds
207712c5e81dSPaul Moore out:
207812c5e81dSPaul Moore audit_reset_context(context);
20791da177e4SLinus Torvalds }
20801da177e4SLinus Torvalds
handle_one(const struct inode * inode)208174c3cbe3SAl Viro static inline void handle_one(const struct inode *inode)
208274c3cbe3SAl Viro {
208374c3cbe3SAl Viro struct audit_context *context;
208474c3cbe3SAl Viro struct audit_tree_refs *p;
208574c3cbe3SAl Viro struct audit_chunk *chunk;
208674c3cbe3SAl Viro int count;
2087254c8b96SRoni Nevalainen
208808991e83SJan Kara if (likely(!inode->i_fsnotify_marks))
208974c3cbe3SAl Viro return;
2090cdfb6b34SRichard Guy Briggs context = audit_context();
209174c3cbe3SAl Viro p = context->trees;
209274c3cbe3SAl Viro count = context->tree_count;
209374c3cbe3SAl Viro rcu_read_lock();
209474c3cbe3SAl Viro chunk = audit_tree_lookup(inode);
209574c3cbe3SAl Viro rcu_read_unlock();
209674c3cbe3SAl Viro if (!chunk)
209774c3cbe3SAl Viro return;
209874c3cbe3SAl Viro if (likely(put_tree_ref(context, chunk)))
209974c3cbe3SAl Viro return;
210074c3cbe3SAl Viro if (unlikely(!grow_tree_refs(context))) {
2101f952d10fSRichard Guy Briggs pr_warn("out of memory, audit has lost a tree reference\n");
210274c3cbe3SAl Viro audit_set_auditable(context);
210374c3cbe3SAl Viro audit_put_chunk(chunk);
210474c3cbe3SAl Viro unroll_tree_refs(context, p, count);
210574c3cbe3SAl Viro return;
210674c3cbe3SAl Viro }
210774c3cbe3SAl Viro put_tree_ref(context, chunk);
210874c3cbe3SAl Viro }
210974c3cbe3SAl Viro
handle_path(const struct dentry * dentry)211074c3cbe3SAl Viro static void handle_path(const struct dentry *dentry)
211174c3cbe3SAl Viro {
211274c3cbe3SAl Viro struct audit_context *context;
211374c3cbe3SAl Viro struct audit_tree_refs *p;
211474c3cbe3SAl Viro const struct dentry *d, *parent;
211574c3cbe3SAl Viro struct audit_chunk *drop;
211674c3cbe3SAl Viro unsigned long seq;
211774c3cbe3SAl Viro int count;
211874c3cbe3SAl Viro
2119cdfb6b34SRichard Guy Briggs context = audit_context();
212074c3cbe3SAl Viro p = context->trees;
212174c3cbe3SAl Viro count = context->tree_count;
212274c3cbe3SAl Viro retry:
212374c3cbe3SAl Viro drop = NULL;
212474c3cbe3SAl Viro d = dentry;
212574c3cbe3SAl Viro rcu_read_lock();
212674c3cbe3SAl Viro seq = read_seqbegin(&rename_lock);
212774c3cbe3SAl Viro for (;;) {
21283b362157SDavid Howells struct inode *inode = d_backing_inode(d);
2129254c8b96SRoni Nevalainen
213008991e83SJan Kara if (inode && unlikely(inode->i_fsnotify_marks)) {
213174c3cbe3SAl Viro struct audit_chunk *chunk;
2132254c8b96SRoni Nevalainen
213374c3cbe3SAl Viro chunk = audit_tree_lookup(inode);
213474c3cbe3SAl Viro if (chunk) {
213574c3cbe3SAl Viro if (unlikely(!put_tree_ref(context, chunk))) {
213674c3cbe3SAl Viro drop = chunk;
213774c3cbe3SAl Viro break;
213874c3cbe3SAl Viro }
213974c3cbe3SAl Viro }
214074c3cbe3SAl Viro }
214174c3cbe3SAl Viro parent = d->d_parent;
214274c3cbe3SAl Viro if (parent == d)
214374c3cbe3SAl Viro break;
214474c3cbe3SAl Viro d = parent;
214574c3cbe3SAl Viro }
214674c3cbe3SAl Viro if (unlikely(read_seqretry(&rename_lock, seq) || drop)) { /* in this order */
214774c3cbe3SAl Viro rcu_read_unlock();
214874c3cbe3SAl Viro if (!drop) {
214974c3cbe3SAl Viro /* just a race with rename */
215074c3cbe3SAl Viro unroll_tree_refs(context, p, count);
215174c3cbe3SAl Viro goto retry;
215274c3cbe3SAl Viro }
215374c3cbe3SAl Viro audit_put_chunk(drop);
215474c3cbe3SAl Viro if (grow_tree_refs(context)) {
215574c3cbe3SAl Viro /* OK, got more space */
215674c3cbe3SAl Viro unroll_tree_refs(context, p, count);
215774c3cbe3SAl Viro goto retry;
215874c3cbe3SAl Viro }
215974c3cbe3SAl Viro /* too bad */
2160f952d10fSRichard Guy Briggs pr_warn("out of memory, audit has lost a tree reference\n");
216174c3cbe3SAl Viro unroll_tree_refs(context, p, count);
216274c3cbe3SAl Viro audit_set_auditable(context);
216374c3cbe3SAl Viro return;
216474c3cbe3SAl Viro }
216574c3cbe3SAl Viro rcu_read_unlock();
216674c3cbe3SAl Viro }
216774c3cbe3SAl Viro
audit_alloc_name(struct audit_context * context,unsigned char type)216878e2e802SJeff Layton static struct audit_names *audit_alloc_name(struct audit_context *context,
216978e2e802SJeff Layton unsigned char type)
21705195d8e2SEric Paris {
21715195d8e2SEric Paris struct audit_names *aname;
21725195d8e2SEric Paris
21735195d8e2SEric Paris if (context->name_count < AUDIT_NAMES) {
21745195d8e2SEric Paris aname = &context->preallocated_names[context->name_count];
21755195d8e2SEric Paris memset(aname, 0, sizeof(*aname));
21765195d8e2SEric Paris } else {
21775195d8e2SEric Paris aname = kzalloc(sizeof(*aname), GFP_NOFS);
21785195d8e2SEric Paris if (!aname)
21795195d8e2SEric Paris return NULL;
21805195d8e2SEric Paris aname->should_free = true;
21815195d8e2SEric Paris }
21825195d8e2SEric Paris
218384cb777eSRichard Guy Briggs aname->ino = AUDIT_INO_UNSET;
218478e2e802SJeff Layton aname->type = type;
21855195d8e2SEric Paris list_add_tail(&aname->list, &context->names_list);
21865195d8e2SEric Paris
21875195d8e2SEric Paris context->name_count++;
21886d915476SRichard Guy Briggs if (!context->pwd.dentry)
21896d915476SRichard Guy Briggs get_fs_pwd(current->fs, &context->pwd);
21905195d8e2SEric Paris return aname;
21915195d8e2SEric Paris }
21925195d8e2SEric Paris
2193b0dd25a8SRandy Dunlap /**
2194196a5085SGeliang Tang * __audit_reusename - fill out filename with info from existing entry
21957ac86265SJeff Layton * @uptr: userland ptr to pathname
21967ac86265SJeff Layton *
21977ac86265SJeff Layton * Search the audit_names list for the current audit context. If there is an
21987ac86265SJeff Layton * existing entry with a matching "uptr" then return the filename
21997ac86265SJeff Layton * associated with that audit_name. If not, return NULL.
22007ac86265SJeff Layton */
22017ac86265SJeff Layton struct filename *
__audit_reusename(const __user char * uptr)22027ac86265SJeff Layton __audit_reusename(const __user char *uptr)
22037ac86265SJeff Layton {
2204cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
22057ac86265SJeff Layton struct audit_names *n;
22067ac86265SJeff Layton
22077ac86265SJeff Layton list_for_each_entry(n, &context->names_list, list) {
22087ac86265SJeff Layton if (!n->name)
22097ac86265SJeff Layton continue;
2210*61185101SMateusz Guzik if (n->name->uptr == uptr)
2211*61185101SMateusz Guzik return refname(n->name);
221255422d0bSPaul Moore }
22137ac86265SJeff Layton return NULL;
22147ac86265SJeff Layton }
22157ac86265SJeff Layton
22167ac86265SJeff Layton /**
2217196a5085SGeliang Tang * __audit_getname - add a name to the list
2218b0dd25a8SRandy Dunlap * @name: name to add
2219b0dd25a8SRandy Dunlap *
2220b0dd25a8SRandy Dunlap * Add a name to the list of audit names for this context.
2221b0dd25a8SRandy Dunlap * Called from fs/namei.c:getname().
2222b0dd25a8SRandy Dunlap */
__audit_getname(struct filename * name)222391a27b2aSJeff Layton void __audit_getname(struct filename *name)
22241da177e4SLinus Torvalds {
2225cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
22265195d8e2SEric Paris struct audit_names *n;
22271da177e4SLinus Torvalds
222812c5e81dSPaul Moore if (context->context == AUDIT_CTX_UNUSED)
22291da177e4SLinus Torvalds return;
223091a27b2aSJeff Layton
223178e2e802SJeff Layton n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
22325195d8e2SEric Paris if (!n)
22335195d8e2SEric Paris return;
22345195d8e2SEric Paris
22355195d8e2SEric Paris n->name = name;
22365195d8e2SEric Paris n->name_len = AUDIT_NAME_FULL;
2237adb5c247SJeff Layton name->aname = n;
2238*61185101SMateusz Guzik refname(name);
22391da177e4SLinus Torvalds }
22401da177e4SLinus Torvalds
audit_copy_fcaps(struct audit_names * name,const struct dentry * dentry)22415f3d544fSRichard Guy Briggs static inline int audit_copy_fcaps(struct audit_names *name,
22425f3d544fSRichard Guy Briggs const struct dentry *dentry)
22435f3d544fSRichard Guy Briggs {
22445f3d544fSRichard Guy Briggs struct cpu_vfs_cap_data caps;
22455f3d544fSRichard Guy Briggs int rc;
22465f3d544fSRichard Guy Briggs
22475f3d544fSRichard Guy Briggs if (!dentry)
22485f3d544fSRichard Guy Briggs return 0;
22495f3d544fSRichard Guy Briggs
225039f60c1cSChristian Brauner rc = get_vfs_caps_from_disk(&nop_mnt_idmap, dentry, &caps);
22515f3d544fSRichard Guy Briggs if (rc)
22525f3d544fSRichard Guy Briggs return rc;
22535f3d544fSRichard Guy Briggs
22545f3d544fSRichard Guy Briggs name->fcap.permitted = caps.permitted;
22555f3d544fSRichard Guy Briggs name->fcap.inheritable = caps.inheritable;
22565f3d544fSRichard Guy Briggs name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
22575f3d544fSRichard Guy Briggs name->fcap.rootid = caps.rootid;
22585f3d544fSRichard Guy Briggs name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
22595f3d544fSRichard Guy Briggs VFS_CAP_REVISION_SHIFT;
22605f3d544fSRichard Guy Briggs
22615f3d544fSRichard Guy Briggs return 0;
22625f3d544fSRichard Guy Briggs }
22635f3d544fSRichard Guy Briggs
22645f3d544fSRichard Guy Briggs /* Copy inode data into an audit_names. */
audit_copy_inode(struct audit_names * name,const struct dentry * dentry,struct inode * inode,unsigned int flags)22652efa48feSYueHaibing static void audit_copy_inode(struct audit_names *name,
22662efa48feSYueHaibing const struct dentry *dentry,
22675f3d544fSRichard Guy Briggs struct inode *inode, unsigned int flags)
22685f3d544fSRichard Guy Briggs {
22695f3d544fSRichard Guy Briggs name->ino = inode->i_ino;
22705f3d544fSRichard Guy Briggs name->dev = inode->i_sb->s_dev;
22715f3d544fSRichard Guy Briggs name->mode = inode->i_mode;
22725f3d544fSRichard Guy Briggs name->uid = inode->i_uid;
22735f3d544fSRichard Guy Briggs name->gid = inode->i_gid;
22745f3d544fSRichard Guy Briggs name->rdev = inode->i_rdev;
2275e0a8dcbdSCasey Schaufler security_inode_getlsmprop(inode, &name->oprop);
22765f3d544fSRichard Guy Briggs if (flags & AUDIT_INODE_NOEVAL) {
22775f3d544fSRichard Guy Briggs name->fcap_ver = -1;
22785f3d544fSRichard Guy Briggs return;
22795f3d544fSRichard Guy Briggs }
22805f3d544fSRichard Guy Briggs audit_copy_fcaps(name, dentry);
22815f3d544fSRichard Guy Briggs }
22825f3d544fSRichard Guy Briggs
2283b0dd25a8SRandy Dunlap /**
2284bfcec708SJeff Layton * __audit_inode - store the inode and device from a lookup
2285b0dd25a8SRandy Dunlap * @name: name being audited
2286481968f4SRandy Dunlap * @dentry: dentry being audited
228779f6530cSJeff Layton * @flags: attributes for this particular entry
2288b0dd25a8SRandy Dunlap */
__audit_inode(struct filename * name,const struct dentry * dentry,unsigned int flags)2289adb5c247SJeff Layton void __audit_inode(struct filename *name, const struct dentry *dentry,
229079f6530cSJeff Layton unsigned int flags)
22911da177e4SLinus Torvalds {
2292cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2293d6335d77SAndreas Gruenbacher struct inode *inode = d_backing_inode(dentry);
22945195d8e2SEric Paris struct audit_names *n;
229579f6530cSJeff Layton bool parent = flags & AUDIT_INODE_PARENT;
2296a252f56aSRichard Guy Briggs struct audit_entry *e;
2297a252f56aSRichard Guy Briggs struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
2298a252f56aSRichard Guy Briggs int i;
22991da177e4SLinus Torvalds
230012c5e81dSPaul Moore if (context->context == AUDIT_CTX_UNUSED)
23011da177e4SLinus Torvalds return;
23025195d8e2SEric Paris
2303a252f56aSRichard Guy Briggs rcu_read_lock();
2304a252f56aSRichard Guy Briggs list_for_each_entry_rcu(e, list, list) {
2305a252f56aSRichard Guy Briggs for (i = 0; i < e->rule.field_count; i++) {
2306a252f56aSRichard Guy Briggs struct audit_field *f = &e->rule.fields[i];
2307a252f56aSRichard Guy Briggs
2308a252f56aSRichard Guy Briggs if (f->type == AUDIT_FSTYPE
2309a252f56aSRichard Guy Briggs && audit_comparator(inode->i_sb->s_magic,
2310a252f56aSRichard Guy Briggs f->op, f->val)
2311a252f56aSRichard Guy Briggs && e->rule.action == AUDIT_NEVER) {
2312a252f56aSRichard Guy Briggs rcu_read_unlock();
2313a252f56aSRichard Guy Briggs return;
2314a252f56aSRichard Guy Briggs }
2315a252f56aSRichard Guy Briggs }
2316a252f56aSRichard Guy Briggs }
2317a252f56aSRichard Guy Briggs rcu_read_unlock();
2318a252f56aSRichard Guy Briggs
23199cec9d68SJeff Layton if (!name)
23209cec9d68SJeff Layton goto out_alloc;
23219cec9d68SJeff Layton
2322adb5c247SJeff Layton /*
2323adb5c247SJeff Layton * If we have a pointer to an audit_names entry already, then we can
2324adb5c247SJeff Layton * just use it directly if the type is correct.
2325adb5c247SJeff Layton */
2326adb5c247SJeff Layton n = name->aname;
2327adb5c247SJeff Layton if (n) {
2328adb5c247SJeff Layton if (parent) {
2329adb5c247SJeff Layton if (n->type == AUDIT_TYPE_PARENT ||
2330adb5c247SJeff Layton n->type == AUDIT_TYPE_UNKNOWN)
2331adb5c247SJeff Layton goto out;
2332adb5c247SJeff Layton } else {
2333adb5c247SJeff Layton if (n->type != AUDIT_TYPE_PARENT)
2334adb5c247SJeff Layton goto out;
2335adb5c247SJeff Layton }
2336adb5c247SJeff Layton }
2337adb5c247SJeff Layton
23385195d8e2SEric Paris list_for_each_entry_reverse(n, &context->names_list, list) {
233957c59f58SPaul Moore if (n->ino) {
234057c59f58SPaul Moore /* valid inode number, use that for the comparison */
234157c59f58SPaul Moore if (n->ino != inode->i_ino ||
234257c59f58SPaul Moore n->dev != inode->i_sb->s_dev)
234357c59f58SPaul Moore continue;
234457c59f58SPaul Moore } else if (n->name) {
234557c59f58SPaul Moore /* inode number has not been set, check the name */
234657c59f58SPaul Moore if (strcmp(n->name->name, name->name))
234757c59f58SPaul Moore continue;
234857c59f58SPaul Moore } else
234957c59f58SPaul Moore /* no inode and no name (?!) ... this is odd ... */
2350bfcec708SJeff Layton continue;
2351bfcec708SJeff Layton
2352bfcec708SJeff Layton /* match the correct record type */
2353bfcec708SJeff Layton if (parent) {
2354bfcec708SJeff Layton if (n->type == AUDIT_TYPE_PARENT ||
2355bfcec708SJeff Layton n->type == AUDIT_TYPE_UNKNOWN)
23565195d8e2SEric Paris goto out;
2357bfcec708SJeff Layton } else {
2358bfcec708SJeff Layton if (n->type != AUDIT_TYPE_PARENT)
2359bfcec708SJeff Layton goto out;
2360bfcec708SJeff Layton }
23611da177e4SLinus Torvalds }
23625195d8e2SEric Paris
23639cec9d68SJeff Layton out_alloc:
23644a928436SPaul Moore /* unable to find an entry with both a matching name and type */
23654a928436SPaul Moore n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
23665195d8e2SEric Paris if (!n)
23675195d8e2SEric Paris return;
2368fcf22d82SPaul Moore if (name) {
2369fd3522fdSPaul Moore n->name = name;
2370*61185101SMateusz Guzik refname(name);
2371fcf22d82SPaul Moore }
23724a928436SPaul Moore
23735195d8e2SEric Paris out:
2374bfcec708SJeff Layton if (parent) {
237591a27b2aSJeff Layton n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
2376bfcec708SJeff Layton n->type = AUDIT_TYPE_PARENT;
237779f6530cSJeff Layton if (flags & AUDIT_INODE_HIDDEN)
237879f6530cSJeff Layton n->hidden = true;
2379bfcec708SJeff Layton } else {
2380bfcec708SJeff Layton n->name_len = AUDIT_NAME_FULL;
2381bfcec708SJeff Layton n->type = AUDIT_TYPE_NORMAL;
2382bfcec708SJeff Layton }
238374c3cbe3SAl Viro handle_path(dentry);
238457d46577SRichard Guy Briggs audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL);
238573241cccSAmy Griffis }
238673241cccSAmy Griffis
__audit_file(const struct file * file)23879f45f5bfSAl Viro void __audit_file(const struct file *file)
23889f45f5bfSAl Viro {
23899f45f5bfSAl Viro __audit_inode(NULL, file->f_path.dentry, 0);
23909f45f5bfSAl Viro }
23919f45f5bfSAl Viro
239273241cccSAmy Griffis /**
2393c43a25abSJeff Layton * __audit_inode_child - collect inode info for created/removed objects
239473d3ec5aSAmy Griffis * @parent: inode of dentry parent
2395c43a25abSJeff Layton * @dentry: dentry being audited
23964fa6b5ecSJeff Layton * @type: AUDIT_TYPE_* value that we're looking for
239773241cccSAmy Griffis *
239873241cccSAmy Griffis * For syscalls that create or remove filesystem objects, audit_inode
239973241cccSAmy Griffis * can only collect information for the filesystem object's parent.
240073241cccSAmy Griffis * This call updates the audit context with the child's information.
240173241cccSAmy Griffis * Syscalls that create a new filesystem object must be hooked after
240273241cccSAmy Griffis * the object is created. Syscalls that remove a filesystem object
240373241cccSAmy Griffis * must be hooked prior, in order to capture the target inode during
240473241cccSAmy Griffis * unsuccessful attempts.
240573241cccSAmy Griffis */
__audit_inode_child(struct inode * parent,const struct dentry * dentry,const unsigned char type)2406d6335d77SAndreas Gruenbacher void __audit_inode_child(struct inode *parent,
24074fa6b5ecSJeff Layton const struct dentry *dentry,
24084fa6b5ecSJeff Layton const unsigned char type)
240973241cccSAmy Griffis {
2410cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2411d6335d77SAndreas Gruenbacher struct inode *inode = d_backing_inode(dentry);
2412795d673aSAl Viro const struct qstr *dname = &dentry->d_name;
24134fa6b5ecSJeff Layton struct audit_names *n, *found_parent = NULL, *found_child = NULL;
241442d5e376SRichard Guy Briggs struct audit_entry *e;
241542d5e376SRichard Guy Briggs struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
241642d5e376SRichard Guy Briggs int i;
241773241cccSAmy Griffis
241812c5e81dSPaul Moore if (context->context == AUDIT_CTX_UNUSED)
241973241cccSAmy Griffis return;
242073241cccSAmy Griffis
242142d5e376SRichard Guy Briggs rcu_read_lock();
242242d5e376SRichard Guy Briggs list_for_each_entry_rcu(e, list, list) {
242342d5e376SRichard Guy Briggs for (i = 0; i < e->rule.field_count; i++) {
242442d5e376SRichard Guy Briggs struct audit_field *f = &e->rule.fields[i];
242542d5e376SRichard Guy Briggs
2426a252f56aSRichard Guy Briggs if (f->type == AUDIT_FSTYPE
2427a252f56aSRichard Guy Briggs && audit_comparator(parent->i_sb->s_magic,
2428a252f56aSRichard Guy Briggs f->op, f->val)
2429a252f56aSRichard Guy Briggs && e->rule.action == AUDIT_NEVER) {
243042d5e376SRichard Guy Briggs rcu_read_unlock();
243142d5e376SRichard Guy Briggs return;
243242d5e376SRichard Guy Briggs }
243342d5e376SRichard Guy Briggs }
243442d5e376SRichard Guy Briggs }
243542d5e376SRichard Guy Briggs rcu_read_unlock();
243642d5e376SRichard Guy Briggs
243774c3cbe3SAl Viro if (inode)
243874c3cbe3SAl Viro handle_one(inode);
243973241cccSAmy Griffis
24404fa6b5ecSJeff Layton /* look for a parent entry first */
24415195d8e2SEric Paris list_for_each_entry(n, &context->names_list, list) {
244257c59f58SPaul Moore if (!n->name ||
244357c59f58SPaul Moore (n->type != AUDIT_TYPE_PARENT &&
244457c59f58SPaul Moore n->type != AUDIT_TYPE_UNKNOWN))
244573241cccSAmy Griffis continue;
244673241cccSAmy Griffis
244757c59f58SPaul Moore if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev &&
244857c59f58SPaul Moore !audit_compare_dname_path(dname,
244957c59f58SPaul Moore n->name->name, n->name_len)) {
245057c59f58SPaul Moore if (n->type == AUDIT_TYPE_UNKNOWN)
245157c59f58SPaul Moore n->type = AUDIT_TYPE_PARENT;
24524fa6b5ecSJeff Layton found_parent = n;
24534fa6b5ecSJeff Layton break;
24549c937dccSAmy Griffis }
245573241cccSAmy Griffis }
245673241cccSAmy Griffis
2457b59bc6e3SGaosheng Cui cond_resched();
2458b59bc6e3SGaosheng Cui
24594fa6b5ecSJeff Layton /* is there a matching child entry? */
24605195d8e2SEric Paris list_for_each_entry(n, &context->names_list, list) {
24614fa6b5ecSJeff Layton /* can only match entries that have a name */
246257c59f58SPaul Moore if (!n->name ||
246357c59f58SPaul Moore (n->type != type && n->type != AUDIT_TYPE_UNKNOWN))
24644fa6b5ecSJeff Layton continue;
24654fa6b5ecSJeff Layton
2466795d673aSAl Viro if (!strcmp(dname->name, n->name->name) ||
246791a27b2aSJeff Layton !audit_compare_dname_path(dname, n->name->name,
24684fa6b5ecSJeff Layton found_parent ?
24694fa6b5ecSJeff Layton found_parent->name_len :
2470e3d6b07bSJeff Layton AUDIT_NAME_FULL)) {
247157c59f58SPaul Moore if (n->type == AUDIT_TYPE_UNKNOWN)
247257c59f58SPaul Moore n->type = type;
24734fa6b5ecSJeff Layton found_child = n;
24744fa6b5ecSJeff Layton break;
2475ac9910ceSSteve Grubb }
24765712e88fSAmy Griffis }
24775712e88fSAmy Griffis
24785712e88fSAmy Griffis if (!found_parent) {
24794fa6b5ecSJeff Layton /* create a new, "anonymous" parent record */
24804fa6b5ecSJeff Layton n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
24815195d8e2SEric Paris if (!n)
24825712e88fSAmy Griffis return;
248357d46577SRichard Guy Briggs audit_copy_inode(n, NULL, parent, 0);
248473d3ec5aSAmy Griffis }
24855712e88fSAmy Griffis
24865712e88fSAmy Griffis if (!found_child) {
24874fa6b5ecSJeff Layton found_child = audit_alloc_name(context, type);
24884fa6b5ecSJeff Layton if (!found_child)
24895712e88fSAmy Griffis return;
24905712e88fSAmy Griffis
24915712e88fSAmy Griffis /* Re-use the name belonging to the slot for a matching parent
24925712e88fSAmy Griffis * directory. All names for this context are relinquished in
24935712e88fSAmy Griffis * audit_free_names() */
24945712e88fSAmy Griffis if (found_parent) {
24954fa6b5ecSJeff Layton found_child->name = found_parent->name;
24964fa6b5ecSJeff Layton found_child->name_len = AUDIT_NAME_FULL;
2497*61185101SMateusz Guzik refname(found_child->name);
24985712e88fSAmy Griffis }
24994fa6b5ecSJeff Layton }
250057c59f58SPaul Moore
25015712e88fSAmy Griffis if (inode)
250257d46577SRichard Guy Briggs audit_copy_inode(found_child, dentry, inode, 0);
25034fa6b5ecSJeff Layton else
250484cb777eSRichard Guy Briggs found_child->ino = AUDIT_INO_UNSET;
25053e2efce0SAmy Griffis }
250650e437d5STrond Myklebust EXPORT_SYMBOL_GPL(__audit_inode_child);
25073e2efce0SAmy Griffis
25083e2efce0SAmy Griffis /**
2509b0dd25a8SRandy Dunlap * auditsc_get_stamp - get local copies of audit_context values
2510b0dd25a8SRandy Dunlap * @ctx: audit_context for the task
25112115bb25SDeepa Dinamani * @t: timespec64 to store time recorded in the audit_context
2512b0dd25a8SRandy Dunlap * @serial: serial value that is recorded in the audit_context
2513b0dd25a8SRandy Dunlap *
2514b0dd25a8SRandy Dunlap * Also sets the context as auditable.
2515b0dd25a8SRandy Dunlap */
auditsc_get_stamp(struct audit_context * ctx,struct timespec64 * t,unsigned int * serial)251648887e63SAl Viro int auditsc_get_stamp(struct audit_context *ctx,
25172115bb25SDeepa Dinamani struct timespec64 *t, unsigned int *serial)
25181da177e4SLinus Torvalds {
251912c5e81dSPaul Moore if (ctx->context == AUDIT_CTX_UNUSED)
252048887e63SAl Viro return 0;
2521ce625a80SDavid Woodhouse if (!ctx->serial)
2522ce625a80SDavid Woodhouse ctx->serial = audit_serial();
25231da177e4SLinus Torvalds t->tv_sec = ctx->ctime.tv_sec;
25241da177e4SLinus Torvalds t->tv_nsec = ctx->ctime.tv_nsec;
25251da177e4SLinus Torvalds *serial = ctx->serial;
25260590b933SAl Viro if (!ctx->prio) {
25270590b933SAl Viro ctx->prio = 1;
2528619ed58aSSergey Nazarov ctx->current_state = AUDIT_STATE_RECORD;
25290590b933SAl Viro }
253048887e63SAl Viro return 1;
25311da177e4SLinus Torvalds }
25321da177e4SLinus Torvalds
2533b0dd25a8SRandy Dunlap /**
253420ca73bcSGeorge C. Wilson * __audit_mq_open - record audit data for a POSIX MQ open
253520ca73bcSGeorge C. Wilson * @oflag: open flag
253620ca73bcSGeorge C. Wilson * @mode: mode bits
25376b962559SRandy Dunlap * @attr: queue attributes
253820ca73bcSGeorge C. Wilson *
253920ca73bcSGeorge C. Wilson */
__audit_mq_open(int oflag,umode_t mode,struct mq_attr * attr)2540df0a4283SAl Viro void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)
254120ca73bcSGeorge C. Wilson {
2542cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
254320ca73bcSGeorge C. Wilson
2544564f6993SAl Viro if (attr)
2545564f6993SAl Viro memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr));
2546564f6993SAl Viro else
2547564f6993SAl Viro memset(&context->mq_open.attr, 0, sizeof(struct mq_attr));
254820ca73bcSGeorge C. Wilson
2549564f6993SAl Viro context->mq_open.oflag = oflag;
2550564f6993SAl Viro context->mq_open.mode = mode;
255120ca73bcSGeorge C. Wilson
2552564f6993SAl Viro context->type = AUDIT_MQ_OPEN;
255320ca73bcSGeorge C. Wilson }
255420ca73bcSGeorge C. Wilson
255520ca73bcSGeorge C. Wilson /**
2556c32c8af4SAl Viro * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive
255720ca73bcSGeorge C. Wilson * @mqdes: MQ descriptor
255820ca73bcSGeorge C. Wilson * @msg_len: Message length
255920ca73bcSGeorge C. Wilson * @msg_prio: Message priority
2560c32c8af4SAl Viro * @abs_timeout: Message timeout in absolute time
256120ca73bcSGeorge C. Wilson *
256220ca73bcSGeorge C. Wilson */
__audit_mq_sendrecv(mqd_t mqdes,size_t msg_len,unsigned int msg_prio,const struct timespec64 * abs_timeout)2563c32c8af4SAl Viro void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
2564b9047726SDeepa Dinamani const struct timespec64 *abs_timeout)
256520ca73bcSGeorge C. Wilson {
2566cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2567b9047726SDeepa Dinamani struct timespec64 *p = &context->mq_sendrecv.abs_timeout;
256820ca73bcSGeorge C. Wilson
2569c32c8af4SAl Viro if (abs_timeout)
2570b9047726SDeepa Dinamani memcpy(p, abs_timeout, sizeof(*p));
2571c32c8af4SAl Viro else
2572b9047726SDeepa Dinamani memset(p, 0, sizeof(*p));
257320ca73bcSGeorge C. Wilson
2574c32c8af4SAl Viro context->mq_sendrecv.mqdes = mqdes;
2575c32c8af4SAl Viro context->mq_sendrecv.msg_len = msg_len;
2576c32c8af4SAl Viro context->mq_sendrecv.msg_prio = msg_prio;
257720ca73bcSGeorge C. Wilson
2578c32c8af4SAl Viro context->type = AUDIT_MQ_SENDRECV;
257920ca73bcSGeorge C. Wilson }
258020ca73bcSGeorge C. Wilson
258120ca73bcSGeorge C. Wilson /**
258220ca73bcSGeorge C. Wilson * __audit_mq_notify - record audit data for a POSIX MQ notify
258320ca73bcSGeorge C. Wilson * @mqdes: MQ descriptor
25846b962559SRandy Dunlap * @notification: Notification event
258520ca73bcSGeorge C. Wilson *
258620ca73bcSGeorge C. Wilson */
258720ca73bcSGeorge C. Wilson
__audit_mq_notify(mqd_t mqdes,const struct sigevent * notification)258820114f71SAl Viro void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
258920ca73bcSGeorge C. Wilson {
2590cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
259120ca73bcSGeorge C. Wilson
259220114f71SAl Viro if (notification)
259320114f71SAl Viro context->mq_notify.sigev_signo = notification->sigev_signo;
259420114f71SAl Viro else
259520114f71SAl Viro context->mq_notify.sigev_signo = 0;
259620ca73bcSGeorge C. Wilson
259720114f71SAl Viro context->mq_notify.mqdes = mqdes;
259820114f71SAl Viro context->type = AUDIT_MQ_NOTIFY;
259920ca73bcSGeorge C. Wilson }
260020ca73bcSGeorge C. Wilson
260120ca73bcSGeorge C. Wilson /**
260220ca73bcSGeorge C. Wilson * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
260320ca73bcSGeorge C. Wilson * @mqdes: MQ descriptor
260420ca73bcSGeorge C. Wilson * @mqstat: MQ flags
260520ca73bcSGeorge C. Wilson *
260620ca73bcSGeorge C. Wilson */
__audit_mq_getsetattr(mqd_t mqdes,struct mq_attr * mqstat)26077392906eSAl Viro void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
260820ca73bcSGeorge C. Wilson {
2609cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2610254c8b96SRoni Nevalainen
26117392906eSAl Viro context->mq_getsetattr.mqdes = mqdes;
26127392906eSAl Viro context->mq_getsetattr.mqstat = *mqstat;
26137392906eSAl Viro context->type = AUDIT_MQ_GETSETATTR;
261420ca73bcSGeorge C. Wilson }
261520ca73bcSGeorge C. Wilson
261620ca73bcSGeorge C. Wilson /**
2617196a5085SGeliang Tang * __audit_ipc_obj - record audit data for ipc object
2618073115d6SSteve Grubb * @ipcp: ipc permissions
2619073115d6SSteve Grubb *
2620073115d6SSteve Grubb */
__audit_ipc_obj(struct kern_ipc_perm * ipcp)2621a33e6751SAl Viro void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
2622073115d6SSteve Grubb {
2623cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2624254c8b96SRoni Nevalainen
2625a33e6751SAl Viro context->ipc.uid = ipcp->uid;
2626a33e6751SAl Viro context->ipc.gid = ipcp->gid;
2627a33e6751SAl Viro context->ipc.mode = ipcp->mode;
2628e816f370SAl Viro context->ipc.has_perm = 0;
2629f4602f16SCasey Schaufler security_ipc_getlsmprop(ipcp, &context->ipc.oprop);
2630a33e6751SAl Viro context->type = AUDIT_IPC;
2631073115d6SSteve Grubb }
2632073115d6SSteve Grubb
2633073115d6SSteve Grubb /**
2634196a5085SGeliang Tang * __audit_ipc_set_perm - record audit data for new ipc permissions
2635b0dd25a8SRandy Dunlap * @qbytes: msgq bytes
2636b0dd25a8SRandy Dunlap * @uid: msgq user id
2637b0dd25a8SRandy Dunlap * @gid: msgq group id
2638b0dd25a8SRandy Dunlap * @mode: msgq mode (permissions)
2639b0dd25a8SRandy Dunlap *
2640e816f370SAl Viro * Called only after audit_ipc_obj().
2641b0dd25a8SRandy Dunlap */
__audit_ipc_set_perm(unsigned long qbytes,uid_t uid,gid_t gid,umode_t mode)26422570ebbdSAl Viro void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode)
26431da177e4SLinus Torvalds {
2644cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
26451da177e4SLinus Torvalds
2646e816f370SAl Viro context->ipc.qbytes = qbytes;
2647e816f370SAl Viro context->ipc.perm_uid = uid;
2648e816f370SAl Viro context->ipc.perm_gid = gid;
2649e816f370SAl Viro context->ipc.perm_mode = mode;
2650e816f370SAl Viro context->ipc.has_perm = 1;
26511da177e4SLinus Torvalds }
2652c2f0c7c3SSteve Grubb
__audit_bprm(struct linux_binprm * bprm)2653d9cfea91SRichard Guy Briggs void __audit_bprm(struct linux_binprm *bprm)
2654473ae30bSAl Viro {
2655cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2656473ae30bSAl Viro
2657d9cfea91SRichard Guy Briggs context->type = AUDIT_EXECVE;
2658d9cfea91SRichard Guy Briggs context->execve.argc = bprm->argc;
2659473ae30bSAl Viro }
2660473ae30bSAl Viro
2661473ae30bSAl Viro
2662b0dd25a8SRandy Dunlap /**
2663196a5085SGeliang Tang * __audit_socketcall - record audit data for sys_socketcall
26642950fa9dSChen Gang * @nargs: number of args, which should not be more than AUDITSC_ARGS.
2665b0dd25a8SRandy Dunlap * @args: args array
2666b0dd25a8SRandy Dunlap *
2667b0dd25a8SRandy Dunlap */
__audit_socketcall(int nargs,unsigned long * args)26682950fa9dSChen Gang int __audit_socketcall(int nargs, unsigned long *args)
26693ec3b2fbSDavid Woodhouse {
2670cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
26713ec3b2fbSDavid Woodhouse
26722950fa9dSChen Gang if (nargs <= 0 || nargs > AUDITSC_ARGS || !args)
26732950fa9dSChen Gang return -EINVAL;
2674f3298dc4SAl Viro context->type = AUDIT_SOCKETCALL;
2675f3298dc4SAl Viro context->socketcall.nargs = nargs;
2676f3298dc4SAl Viro memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long));
26772950fa9dSChen Gang return 0;
26783ec3b2fbSDavid Woodhouse }
26793ec3b2fbSDavid Woodhouse
2680b0dd25a8SRandy Dunlap /**
2681db349509SAl Viro * __audit_fd_pair - record audit data for pipe and socketpair
2682db349509SAl Viro * @fd1: the first file descriptor
2683db349509SAl Viro * @fd2: the second file descriptor
2684db349509SAl Viro *
2685db349509SAl Viro */
__audit_fd_pair(int fd1,int fd2)2686157cf649SAl Viro void __audit_fd_pair(int fd1, int fd2)
2687db349509SAl Viro {
2688cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2689254c8b96SRoni Nevalainen
2690157cf649SAl Viro context->fds[0] = fd1;
2691157cf649SAl Viro context->fds[1] = fd2;
2692db349509SAl Viro }
2693db349509SAl Viro
2694db349509SAl Viro /**
2695196a5085SGeliang Tang * __audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
2696b0dd25a8SRandy Dunlap * @len: data length in user space
2697b0dd25a8SRandy Dunlap * @a: data address in kernel space
2698b0dd25a8SRandy Dunlap *
2699b0dd25a8SRandy Dunlap * Returns 0 for success or NULL context or < 0 on error.
2700b0dd25a8SRandy Dunlap */
__audit_sockaddr(int len,void * a)270107c49417SEric Paris int __audit_sockaddr(int len, void *a)
27023ec3b2fbSDavid Woodhouse {
2703cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
27043ec3b2fbSDavid Woodhouse
27054f6b434fSAl Viro if (!context->sockaddr) {
27064f6b434fSAl Viro void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
2707254c8b96SRoni Nevalainen
27084f6b434fSAl Viro if (!p)
27093ec3b2fbSDavid Woodhouse return -ENOMEM;
27104f6b434fSAl Viro context->sockaddr = p;
27114f6b434fSAl Viro }
27123ec3b2fbSDavid Woodhouse
27134f6b434fSAl Viro context->sockaddr_len = len;
27144f6b434fSAl Viro memcpy(context->sockaddr, a, len);
27153ec3b2fbSDavid Woodhouse return 0;
27163ec3b2fbSDavid Woodhouse }
27173ec3b2fbSDavid Woodhouse
__audit_ptrace(struct task_struct * t)2718a5cb013dSAl Viro void __audit_ptrace(struct task_struct *t)
2719a5cb013dSAl Viro {
2720cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2721a5cb013dSAl Viro
2722fa2bea2fSPaul Moore context->target_pid = task_tgid_nr(t);
2723c2a7780eSEric Paris context->target_auid = audit_get_loginuid(t);
2724c69e8d9cSDavid Howells context->target_uid = task_uid(t);
27254746ec5bSEric Paris context->target_sessionid = audit_get_sessionid(t);
2726286d7a54SYafang Shao strscpy(context->target_comm, t->comm);
2727d9381508SYafang shao security_task_getlsmprop_obj(t, &context->target_ref);
2728a5cb013dSAl Viro }
2729a5cb013dSAl Viro
2730b0dd25a8SRandy Dunlap /**
2731b48345aaSRichard Guy Briggs * audit_signal_info_syscall - record signal info for syscalls
2732b0dd25a8SRandy Dunlap * @t: task being signaled
2733b0dd25a8SRandy Dunlap *
2734b0dd25a8SRandy Dunlap * If the audit subsystem is being terminated, record the task (pid)
2735b0dd25a8SRandy Dunlap * and uid that is doing that.
2736b0dd25a8SRandy Dunlap */
audit_signal_info_syscall(struct task_struct * t)2737b48345aaSRichard Guy Briggs int audit_signal_info_syscall(struct task_struct *t)
2738c2f0c7c3SSteve Grubb {
2739e54dc243SAmy Griffis struct audit_aux_data_pids *axp;
2740cdfb6b34SRichard Guy Briggs struct audit_context *ctx = audit_context();
2741b48345aaSRichard Guy Briggs kuid_t t_uid = task_uid(t);
2742ab6434a1SPaul Moore
2743175fc484SAl Viro if (!audit_signals || audit_dummy_context())
2744e54dc243SAmy Griffis return 0;
2745e54dc243SAmy Griffis
2746e54dc243SAmy Griffis /* optimize the common case by putting first signal recipient directly
2747e54dc243SAmy Griffis * in audit_context */
2748e54dc243SAmy Griffis if (!ctx->target_pid) {
2749f1dc4867SRichard Guy Briggs ctx->target_pid = task_tgid_nr(t);
2750c2a7780eSEric Paris ctx->target_auid = audit_get_loginuid(t);
2751c69e8d9cSDavid Howells ctx->target_uid = t_uid;
27524746ec5bSEric Paris ctx->target_sessionid = audit_get_sessionid(t);
2753286d7a54SYafang Shao strscpy(ctx->target_comm, t->comm);
2754d9381508SYafang shao security_task_getlsmprop_obj(t, &ctx->target_ref);
2755e54dc243SAmy Griffis return 0;
2756e54dc243SAmy Griffis }
2757e54dc243SAmy Griffis
2758e54dc243SAmy Griffis axp = (void *)ctx->aux_pids;
2759e54dc243SAmy Griffis if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
2760e54dc243SAmy Griffis axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
2761e54dc243SAmy Griffis if (!axp)
2762e54dc243SAmy Griffis return -ENOMEM;
2763e54dc243SAmy Griffis
2764e54dc243SAmy Griffis axp->d.type = AUDIT_OBJ_PID;
2765e54dc243SAmy Griffis axp->d.next = ctx->aux_pids;
2766e54dc243SAmy Griffis ctx->aux_pids = (void *)axp;
2767e54dc243SAmy Griffis }
276888ae704cSAdrian Bunk BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS);
2769e54dc243SAmy Griffis
2770f1dc4867SRichard Guy Briggs axp->target_pid[axp->pid_count] = task_tgid_nr(t);
2771c2a7780eSEric Paris axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
2772c69e8d9cSDavid Howells axp->target_uid[axp->pid_count] = t_uid;
27734746ec5bSEric Paris axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
277413d826e5SCasey Schaufler security_task_getlsmprop_obj(t, &axp->target_ref[axp->pid_count]);
2775286d7a54SYafang Shao strscpy(axp->target_comm[axp->pid_count], t->comm);
2776e54dc243SAmy Griffis axp->pid_count++;
2777e54dc243SAmy Griffis
2778e54dc243SAmy Griffis return 0;
2779c2f0c7c3SSteve Grubb }
27800a4ff8c2SSteve Grubb
27810a4ff8c2SSteve Grubb /**
27823fc689e9SEric Paris * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps
2783d84f4f99SDavid Howells * @bprm: pointer to the bprm being processed
2784d84f4f99SDavid Howells * @new: the proposed new credentials
2785d84f4f99SDavid Howells * @old: the old credentials
27863fc689e9SEric Paris *
27873fc689e9SEric Paris * Simply check if the proc already has the caps given by the file and if not
27883fc689e9SEric Paris * store the priv escalation info for later auditing at the end of the syscall
27893fc689e9SEric Paris *
27903fc689e9SEric Paris * -Eric
27913fc689e9SEric Paris */
__audit_log_bprm_fcaps(struct linux_binprm * bprm,const struct cred * new,const struct cred * old)2792d84f4f99SDavid Howells int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
2793d84f4f99SDavid Howells const struct cred *new, const struct cred *old)
27943fc689e9SEric Paris {
27953fc689e9SEric Paris struct audit_aux_data_bprm_fcaps *ax;
2796cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
27973fc689e9SEric Paris struct cpu_vfs_cap_data vcaps;
27983fc689e9SEric Paris
27993fc689e9SEric Paris ax = kmalloc(sizeof(*ax), GFP_KERNEL);
28003fc689e9SEric Paris if (!ax)
2801d84f4f99SDavid Howells return -ENOMEM;
28023fc689e9SEric Paris
28033fc689e9SEric Paris ax->d.type = AUDIT_BPRM_FCAPS;
28043fc689e9SEric Paris ax->d.next = context->aux;
28053fc689e9SEric Paris context->aux = (void *)ax;
28063fc689e9SEric Paris
280739f60c1cSChristian Brauner get_vfs_caps_from_disk(&nop_mnt_idmap,
280871bc356fSChristian Brauner bprm->file->f_path.dentry, &vcaps);
28093fc689e9SEric Paris
28103fc689e9SEric Paris ax->fcap.permitted = vcaps.permitted;
28113fc689e9SEric Paris ax->fcap.inheritable = vcaps.inheritable;
28123fc689e9SEric Paris ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
28132fec30e2SRichard Guy Briggs ax->fcap.rootid = vcaps.rootid;
28143fc689e9SEric Paris ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT;
28153fc689e9SEric Paris
2816d84f4f99SDavid Howells ax->old_pcap.permitted = old->cap_permitted;
2817d84f4f99SDavid Howells ax->old_pcap.inheritable = old->cap_inheritable;
2818d84f4f99SDavid Howells ax->old_pcap.effective = old->cap_effective;
28197786f6b6SRichard Guy Briggs ax->old_pcap.ambient = old->cap_ambient;
28203fc689e9SEric Paris
2821d84f4f99SDavid Howells ax->new_pcap.permitted = new->cap_permitted;
2822d84f4f99SDavid Howells ax->new_pcap.inheritable = new->cap_inheritable;
2823d84f4f99SDavid Howells ax->new_pcap.effective = new->cap_effective;
28247786f6b6SRichard Guy Briggs ax->new_pcap.ambient = new->cap_ambient;
2825d84f4f99SDavid Howells return 0;
28263fc689e9SEric Paris }
28273fc689e9SEric Paris
28283fc689e9SEric Paris /**
2829e68b75a0SEric Paris * __audit_log_capset - store information about the arguments to the capset syscall
2830d84f4f99SDavid Howells * @new: the new credentials
2831d84f4f99SDavid Howells * @old: the old (current) credentials
2832e68b75a0SEric Paris *
2833da3dae54SMasanari Iida * Record the arguments userspace sent to sys_capset for later printing by the
2834e68b75a0SEric Paris * audit system if applicable
2835e68b75a0SEric Paris */
__audit_log_capset(const struct cred * new,const struct cred * old)2836ca24a23eSEric W. Biederman void __audit_log_capset(const struct cred *new, const struct cred *old)
2837e68b75a0SEric Paris {
2838cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2839254c8b96SRoni Nevalainen
2840fa2bea2fSPaul Moore context->capset.pid = task_tgid_nr(current);
284157f71a0aSAl Viro context->capset.cap.effective = new->cap_effective;
284257f71a0aSAl Viro context->capset.cap.inheritable = new->cap_effective;
284357f71a0aSAl Viro context->capset.cap.permitted = new->cap_permitted;
28447786f6b6SRichard Guy Briggs context->capset.cap.ambient = new->cap_ambient;
284557f71a0aSAl Viro context->type = AUDIT_CAPSET;
2846e68b75a0SEric Paris }
2847e68b75a0SEric Paris
__audit_mmap_fd(int fd,int flags)2848120a795dSAl Viro void __audit_mmap_fd(int fd, int flags)
2849120a795dSAl Viro {
2850cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2851254c8b96SRoni Nevalainen
2852120a795dSAl Viro context->mmap.fd = fd;
2853120a795dSAl Viro context->mmap.flags = flags;
2854120a795dSAl Viro context->type = AUDIT_MMAP;
2855120a795dSAl Viro }
2856120a795dSAl Viro
__audit_openat2_how(struct open_how * how)2857571e5c0eSRichard Guy Briggs void __audit_openat2_how(struct open_how *how)
2858571e5c0eSRichard Guy Briggs {
2859571e5c0eSRichard Guy Briggs struct audit_context *context = audit_context();
2860571e5c0eSRichard Guy Briggs
2861571e5c0eSRichard Guy Briggs context->openat2.flags = how->flags;
2862571e5c0eSRichard Guy Briggs context->openat2.mode = how->mode;
2863571e5c0eSRichard Guy Briggs context->openat2.resolve = how->resolve;
2864571e5c0eSRichard Guy Briggs context->type = AUDIT_OPENAT2;
2865571e5c0eSRichard Guy Briggs }
2866571e5c0eSRichard Guy Briggs
__audit_log_kern_module(char * name)2867ca86cad7SRichard Guy Briggs void __audit_log_kern_module(char *name)
2868ca86cad7SRichard Guy Briggs {
2869cdfb6b34SRichard Guy Briggs struct audit_context *context = audit_context();
2870ca86cad7SRichard Guy Briggs
2871b305f7edSYi Wang context->module.name = kstrdup(name, GFP_KERNEL);
2872b305f7edSYi Wang if (!context->module.name)
2873b305f7edSYi Wang audit_log_lost("out of memory in __audit_log_kern_module");
2874ca86cad7SRichard Guy Briggs context->type = AUDIT_KERN_MODULE;
2875ca86cad7SRichard Guy Briggs }
2876ca86cad7SRichard Guy Briggs
__audit_fanotify(u32 response,struct fanotify_response_info_audit_rule * friar)2877032bffd4SRichard Guy Briggs void __audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
2878de8cd83eSSteve Grubb {
2879032bffd4SRichard Guy Briggs /* {subj,obj}_trust values are {0,1,2}: no,yes,unknown */
2880032bffd4SRichard Guy Briggs switch (friar->hdr.type) {
2881032bffd4SRichard Guy Briggs case FAN_RESPONSE_INFO_NONE:
2882032bffd4SRichard Guy Briggs audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2883032bffd4SRichard Guy Briggs "resp=%u fan_type=%u fan_info=0 subj_trust=2 obj_trust=2",
2884032bffd4SRichard Guy Briggs response, FAN_RESPONSE_INFO_NONE);
2885032bffd4SRichard Guy Briggs break;
2886032bffd4SRichard Guy Briggs case FAN_RESPONSE_INFO_AUDIT_RULE:
2887032bffd4SRichard Guy Briggs audit_log(audit_context(), GFP_KERNEL, AUDIT_FANOTIFY,
2888032bffd4SRichard Guy Briggs "resp=%u fan_type=%u fan_info=%X subj_trust=%u obj_trust=%u",
2889032bffd4SRichard Guy Briggs response, friar->hdr.type, friar->rule_number,
2890032bffd4SRichard Guy Briggs friar->subj_trust, friar->obj_trust);
2891032bffd4SRichard Guy Briggs }
2892de8cd83eSSteve Grubb }
2893de8cd83eSSteve Grubb
__audit_tk_injoffset(struct timespec64 offset)28942d87a067SOndrej Mosnacek void __audit_tk_injoffset(struct timespec64 offset)
28952d87a067SOndrej Mosnacek {
2896272ceeaeSRichard Guy Briggs struct audit_context *context = audit_context();
28972d87a067SOndrej Mosnacek
2898272ceeaeSRichard Guy Briggs /* only set type if not already set by NTP */
2899272ceeaeSRichard Guy Briggs if (!context->type)
2900272ceeaeSRichard Guy Briggs context->type = AUDIT_TIME_INJOFFSET;
2901272ceeaeSRichard Guy Briggs memcpy(&context->time.tk_injoffset, &offset, sizeof(offset));
29027e8eda73SOndrej Mosnacek }
29037e8eda73SOndrej Mosnacek
__audit_ntp_log(const struct audit_ntp_data * ad)29047e8eda73SOndrej Mosnacek void __audit_ntp_log(const struct audit_ntp_data *ad)
29057e8eda73SOndrej Mosnacek {
2906272ceeaeSRichard Guy Briggs struct audit_context *context = audit_context();
2907272ceeaeSRichard Guy Briggs int type;
2908272ceeaeSRichard Guy Briggs
2909272ceeaeSRichard Guy Briggs for (type = 0; type < AUDIT_NTP_NVALS; type++)
2910272ceeaeSRichard Guy Briggs if (ad->vals[type].newval != ad->vals[type].oldval) {
2911272ceeaeSRichard Guy Briggs /* unconditionally set type, overwriting TK */
2912272ceeaeSRichard Guy Briggs context->type = AUDIT_TIME_ADJNTPVAL;
2913272ceeaeSRichard Guy Briggs memcpy(&context->time.ntp_data, ad, sizeof(*ad));
2914272ceeaeSRichard Guy Briggs break;
2915272ceeaeSRichard Guy Briggs }
29167e8eda73SOndrej Mosnacek }
29177e8eda73SOndrej Mosnacek
__audit_log_nfcfg(const char * name,u8 af,unsigned int nentries,enum audit_nfcfgop op,gfp_t gfp)2918c4dad0aaSRichard Guy Briggs void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
291914224039SRichard Guy Briggs enum audit_nfcfgop op, gfp_t gfp)
2920c4dad0aaSRichard Guy Briggs {
2921c4dad0aaSRichard Guy Briggs struct audit_buffer *ab;
29229d44a121SRichard Guy Briggs char comm[sizeof(current->comm)];
2923c4dad0aaSRichard Guy Briggs
292414224039SRichard Guy Briggs ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG);
2925c4dad0aaSRichard Guy Briggs if (!ab)
2926c4dad0aaSRichard Guy Briggs return;
2927c4dad0aaSRichard Guy Briggs audit_log_format(ab, "table=%s family=%u entries=%u op=%s",
2928c4dad0aaSRichard Guy Briggs name, af, nentries, audit_nfcfgs[op].s);
29299d44a121SRichard Guy Briggs
293061c60977SRicardo Robaina audit_log_format(ab, " pid=%u", task_tgid_nr(current));
29319d44a121SRichard Guy Briggs audit_log_task_context(ab); /* subj= */
29329d44a121SRichard Guy Briggs audit_log_format(ab, " comm=");
29339d44a121SRichard Guy Briggs audit_log_untrustedstring(ab, get_task_comm(comm, current));
2934c4dad0aaSRichard Guy Briggs audit_log_end(ab);
2935c4dad0aaSRichard Guy Briggs }
2936c4dad0aaSRichard Guy Briggs EXPORT_SYMBOL_GPL(__audit_log_nfcfg);
2937c4dad0aaSRichard Guy Briggs
audit_log_task(struct audit_buffer * ab)29387b9205bdSKees Cook static void audit_log_task(struct audit_buffer *ab)
293985e7bac3SEric Paris {
2940cca080d9SEric W. Biederman kuid_t auid, uid;
2941cca080d9SEric W. Biederman kgid_t gid;
294285e7bac3SEric Paris unsigned int sessionid;
29439eab339bSRichard Guy Briggs char comm[sizeof(current->comm)];
294485e7bac3SEric Paris
294585e7bac3SEric Paris auid = audit_get_loginuid(current);
294685e7bac3SEric Paris sessionid = audit_get_sessionid(current);
294785e7bac3SEric Paris current_uid_gid(&uid, &gid);
294885e7bac3SEric Paris
294985e7bac3SEric Paris audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
2950cca080d9SEric W. Biederman from_kuid(&init_user_ns, auid),
2951cca080d9SEric W. Biederman from_kuid(&init_user_ns, uid),
2952cca080d9SEric W. Biederman from_kgid(&init_user_ns, gid),
2953cca080d9SEric W. Biederman sessionid);
295485e7bac3SEric Paris audit_log_task_context(ab);
2955fa2bea2fSPaul Moore audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current));
29569eab339bSRichard Guy Briggs audit_log_untrustedstring(ab, get_task_comm(comm, current));
29574766b199SDavidlohr Bueso audit_log_d_path_exe(ab, current->mm);
29587b9205bdSKees Cook }
29597b9205bdSKees Cook
2960e68b75a0SEric Paris /**
29610a4ff8c2SSteve Grubb * audit_core_dumps - record information about processes that end abnormally
29626d9525b5SHenrik Kretzschmar * @signr: signal value
29630a4ff8c2SSteve Grubb *
29640a4ff8c2SSteve Grubb * If a process ends with a core dump, something fishy is going on and we
29650a4ff8c2SSteve Grubb * should record the event for investigation.
29660a4ff8c2SSteve Grubb */
audit_core_dumps(long signr)29670a4ff8c2SSteve Grubb void audit_core_dumps(long signr)
29680a4ff8c2SSteve Grubb {
29690a4ff8c2SSteve Grubb struct audit_buffer *ab;
29700a4ff8c2SSteve Grubb
29710a4ff8c2SSteve Grubb if (!audit_enabled)
29720a4ff8c2SSteve Grubb return;
29730a4ff8c2SSteve Grubb
29740a4ff8c2SSteve Grubb if (signr == SIGQUIT) /* don't care for those */
29750a4ff8c2SSteve Grubb return;
29760a4ff8c2SSteve Grubb
2977d87de4a8SRichard Guy Briggs ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_ABEND);
29780644ec0cSKees Cook if (unlikely(!ab))
29790644ec0cSKees Cook return;
298061c0ee87SPaul Davies C audit_log_task(ab);
298189670affSSteve Grubb audit_log_format(ab, " sig=%ld res=1", signr);
298285e7bac3SEric Paris audit_log_end(ab);
298385e7bac3SEric Paris }
29840a4ff8c2SSteve Grubb
2985326bee02STyler Hicks /**
2986326bee02STyler Hicks * audit_seccomp - record information about a seccomp action
2987326bee02STyler Hicks * @syscall: syscall number
2988326bee02STyler Hicks * @signr: signal value
2989326bee02STyler Hicks * @code: the seccomp action
2990326bee02STyler Hicks *
2991326bee02STyler Hicks * Record the information associated with a seccomp action. Event filtering for
2992326bee02STyler Hicks * seccomp actions that are not to be logged is done in seccomp_log().
2993326bee02STyler Hicks * Therefore, this function forces auditing independent of the audit_enabled
2994326bee02STyler Hicks * and dummy context state because seccomp actions should be logged even when
2995326bee02STyler Hicks * audit is not in use.
2996326bee02STyler Hicks */
audit_seccomp(unsigned long syscall,long signr,int code)2997326bee02STyler Hicks void audit_seccomp(unsigned long syscall, long signr, int code)
299885e7bac3SEric Paris {
299985e7bac3SEric Paris struct audit_buffer *ab;
300085e7bac3SEric Paris
30019b8753ffSRichard Guy Briggs ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_SECCOMP);
30027b9205bdSKees Cook if (unlikely(!ab))
30037b9205bdSKees Cook return;
30047b9205bdSKees Cook audit_log_task(ab);
300584db564aSRichard Guy Briggs audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
300616add411SDmitry V. Levin signr, syscall_get_arch(current), syscall,
3007efbc0fbfSAndy Lutomirski in_compat_syscall(), KSTK_EIP(current), code);
30080a4ff8c2SSteve Grubb audit_log_end(ab);
30090a4ff8c2SSteve Grubb }
3010916d7576SAl Viro
audit_seccomp_actions_logged(const char * names,const char * old_names,int res)3011ea6eca77STyler Hicks void audit_seccomp_actions_logged(const char *names, const char *old_names,
3012ea6eca77STyler Hicks int res)
3013ea6eca77STyler Hicks {
3014ea6eca77STyler Hicks struct audit_buffer *ab;
3015ea6eca77STyler Hicks
3016ea6eca77STyler Hicks if (!audit_enabled)
3017ea6eca77STyler Hicks return;
3018ea6eca77STyler Hicks
30198982a1fbSRichard Guy Briggs ab = audit_log_start(audit_context(), GFP_KERNEL,
3020ea6eca77STyler Hicks AUDIT_CONFIG_CHANGE);
3021ea6eca77STyler Hicks if (unlikely(!ab))
3022ea6eca77STyler Hicks return;
3023ea6eca77STyler Hicks
3024d0a3f18aSPaul Moore audit_log_format(ab,
3025d0a3f18aSPaul Moore "op=seccomp-logging actions=%s old-actions=%s res=%d",
3026d0a3f18aSPaul Moore names, old_names, res);
3027ea6eca77STyler Hicks audit_log_end(ab);
3028ea6eca77STyler Hicks }
3029ea6eca77STyler Hicks
audit_killed_trees(void)3030916d7576SAl Viro struct list_head *audit_killed_trees(void)
3031916d7576SAl Viro {
3032cdfb6b34SRichard Guy Briggs struct audit_context *ctx = audit_context();
303312c5e81dSPaul Moore if (likely(!ctx || ctx->context == AUDIT_CTX_UNUSED))
3034916d7576SAl Viro return NULL;
3035916d7576SAl Viro return &ctx->killed_trees;
3036916d7576SAl Viro }
3037