18c2ecf20Sopenharmony_ci/* auditsc.c -- System-call auditing support 28c2ecf20Sopenharmony_ci * Handles all system-call specific auditing features. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 58c2ecf20Sopenharmony_ci * Copyright 2005 Hewlett-Packard Development Company, L.P. 68c2ecf20Sopenharmony_ci * Copyright (C) 2005, 2006 IBM Corporation 78c2ecf20Sopenharmony_ci * All Rights Reserved. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 118c2ecf20Sopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 128c2ecf20Sopenharmony_ci * (at your option) any later version. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, 158c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 168c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 178c2ecf20Sopenharmony_ci * GNU General Public License for more details. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 208c2ecf20Sopenharmony_ci * along with this program; if not, write to the Free Software 218c2ecf20Sopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Written by Rickard E. (Rik) Faith <faith@redhat.com> 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * Many of the ideas implemented here are from Stephen C. Tweedie, 268c2ecf20Sopenharmony_ci * especially the idea of avoiding a copy by using getname. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * The method for actual interception of syscall entry and exit (not in 298c2ecf20Sopenharmony_ci * this file -- see entry.S) is based on a GPL'd patch written by 308c2ecf20Sopenharmony_ci * okir@suse.de and Copyright 2003 SuSE Linux AG. 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>, 338c2ecf20Sopenharmony_ci * 2006. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * The support of additional filter rules compares (>, <, >=, <=) was 368c2ecf20Sopenharmony_ci * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005. 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional 398c2ecf20Sopenharmony_ci * filesystem information. 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * Subject and object context labeling support added by <danjones@us.ibm.com> 428c2ecf20Sopenharmony_ci * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#include <linux/init.h> 488c2ecf20Sopenharmony_ci#include <asm/types.h> 498c2ecf20Sopenharmony_ci#include <linux/atomic.h> 508c2ecf20Sopenharmony_ci#include <linux/fs.h> 518c2ecf20Sopenharmony_ci#include <linux/namei.h> 528c2ecf20Sopenharmony_ci#include <linux/mm.h> 538c2ecf20Sopenharmony_ci#include <linux/export.h> 548c2ecf20Sopenharmony_ci#include <linux/slab.h> 558c2ecf20Sopenharmony_ci#include <linux/mount.h> 568c2ecf20Sopenharmony_ci#include <linux/socket.h> 578c2ecf20Sopenharmony_ci#include <linux/mqueue.h> 588c2ecf20Sopenharmony_ci#include <linux/audit.h> 598c2ecf20Sopenharmony_ci#include <linux/personality.h> 608c2ecf20Sopenharmony_ci#include <linux/time.h> 618c2ecf20Sopenharmony_ci#include <linux/netlink.h> 628c2ecf20Sopenharmony_ci#include <linux/compiler.h> 638c2ecf20Sopenharmony_ci#include <asm/unistd.h> 648c2ecf20Sopenharmony_ci#include <linux/security.h> 658c2ecf20Sopenharmony_ci#include <linux/list.h> 668c2ecf20Sopenharmony_ci#include <linux/binfmts.h> 678c2ecf20Sopenharmony_ci#include <linux/highmem.h> 688c2ecf20Sopenharmony_ci#include <linux/syscalls.h> 698c2ecf20Sopenharmony_ci#include <asm/syscall.h> 708c2ecf20Sopenharmony_ci#include <linux/capability.h> 718c2ecf20Sopenharmony_ci#include <linux/fs_struct.h> 728c2ecf20Sopenharmony_ci#include <linux/compat.h> 738c2ecf20Sopenharmony_ci#include <linux/ctype.h> 748c2ecf20Sopenharmony_ci#include <linux/string.h> 758c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 768c2ecf20Sopenharmony_ci#include <linux/fsnotify_backend.h> 778c2ecf20Sopenharmony_ci#include <uapi/linux/limits.h> 788c2ecf20Sopenharmony_ci#include <uapi/linux/netfilter/nf_tables.h> 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#include "audit.h" 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* flags stating the success for a syscall */ 838c2ecf20Sopenharmony_ci#define AUDITSC_INVALID 0 848c2ecf20Sopenharmony_ci#define AUDITSC_SUCCESS 1 858c2ecf20Sopenharmony_ci#define AUDITSC_FAILURE 2 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* no execve audit message should be longer than this (userspace limits), 888c2ecf20Sopenharmony_ci * see the note near the top of audit_log_execve_info() about this value */ 898c2ecf20Sopenharmony_ci#define MAX_EXECVE_AUDIT_LEN 7500 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* max length to print of cmdline/proctitle value during audit */ 928c2ecf20Sopenharmony_ci#define MAX_PROCTITLE_AUDIT_LEN 128 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* number of audit rules */ 958c2ecf20Sopenharmony_ciint audit_n_rules; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* determines whether we collect data for signals sent */ 988c2ecf20Sopenharmony_ciint audit_signals; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistruct audit_aux_data { 1018c2ecf20Sopenharmony_ci struct audit_aux_data *next; 1028c2ecf20Sopenharmony_ci int type; 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#define AUDIT_AUX_IPCPERM 0 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* Number of target pids per aux struct. */ 1088c2ecf20Sopenharmony_ci#define AUDIT_AUX_PIDS 16 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistruct audit_aux_data_pids { 1118c2ecf20Sopenharmony_ci struct audit_aux_data d; 1128c2ecf20Sopenharmony_ci pid_t target_pid[AUDIT_AUX_PIDS]; 1138c2ecf20Sopenharmony_ci kuid_t target_auid[AUDIT_AUX_PIDS]; 1148c2ecf20Sopenharmony_ci kuid_t target_uid[AUDIT_AUX_PIDS]; 1158c2ecf20Sopenharmony_ci unsigned int target_sessionid[AUDIT_AUX_PIDS]; 1168c2ecf20Sopenharmony_ci u32 target_sid[AUDIT_AUX_PIDS]; 1178c2ecf20Sopenharmony_ci char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN]; 1188c2ecf20Sopenharmony_ci int pid_count; 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistruct audit_aux_data_bprm_fcaps { 1228c2ecf20Sopenharmony_ci struct audit_aux_data d; 1238c2ecf20Sopenharmony_ci struct audit_cap_data fcap; 1248c2ecf20Sopenharmony_ci unsigned int fcap_ver; 1258c2ecf20Sopenharmony_ci struct audit_cap_data old_pcap; 1268c2ecf20Sopenharmony_ci struct audit_cap_data new_pcap; 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistruct audit_tree_refs { 1308c2ecf20Sopenharmony_ci struct audit_tree_refs *next; 1318c2ecf20Sopenharmony_ci struct audit_chunk *c[31]; 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistruct audit_nfcfgop_tab { 1358c2ecf20Sopenharmony_ci enum audit_nfcfgop op; 1368c2ecf20Sopenharmony_ci const char *s; 1378c2ecf20Sopenharmony_ci}; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic const struct audit_nfcfgop_tab audit_nfcfgs[] = { 1408c2ecf20Sopenharmony_ci { AUDIT_XT_OP_REGISTER, "xt_register" }, 1418c2ecf20Sopenharmony_ci { AUDIT_XT_OP_REPLACE, "xt_replace" }, 1428c2ecf20Sopenharmony_ci { AUDIT_XT_OP_UNREGISTER, "xt_unregister" }, 1438c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_TABLE_REGISTER, "nft_register_table" }, 1448c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_TABLE_UNREGISTER, "nft_unregister_table" }, 1458c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_CHAIN_REGISTER, "nft_register_chain" }, 1468c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_CHAIN_UNREGISTER, "nft_unregister_chain" }, 1478c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_RULE_REGISTER, "nft_register_rule" }, 1488c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_RULE_UNREGISTER, "nft_unregister_rule" }, 1498c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_SET_REGISTER, "nft_register_set" }, 1508c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_SET_UNREGISTER, "nft_unregister_set" }, 1518c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_SETELEM_REGISTER, "nft_register_setelem" }, 1528c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_SETELEM_UNREGISTER, "nft_unregister_setelem" }, 1538c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_GEN_REGISTER, "nft_register_gen" }, 1548c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_OBJ_REGISTER, "nft_register_obj" }, 1558c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_OBJ_UNREGISTER, "nft_unregister_obj" }, 1568c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_OBJ_RESET, "nft_reset_obj" }, 1578c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_FLOWTABLE_REGISTER, "nft_register_flowtable" }, 1588c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_FLOWTABLE_UNREGISTER, "nft_unregister_flowtable" }, 1598c2ecf20Sopenharmony_ci { AUDIT_NFT_OP_INVALID, "nft_invalid" }, 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic int audit_match_perm(struct audit_context *ctx, int mask) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci unsigned n; 1658c2ecf20Sopenharmony_ci if (unlikely(!ctx)) 1668c2ecf20Sopenharmony_ci return 0; 1678c2ecf20Sopenharmony_ci n = ctx->major; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci switch (audit_classify_syscall(ctx->arch, n)) { 1708c2ecf20Sopenharmony_ci case 0: /* native */ 1718c2ecf20Sopenharmony_ci if ((mask & AUDIT_PERM_WRITE) && 1728c2ecf20Sopenharmony_ci audit_match_class(AUDIT_CLASS_WRITE, n)) 1738c2ecf20Sopenharmony_ci return 1; 1748c2ecf20Sopenharmony_ci if ((mask & AUDIT_PERM_READ) && 1758c2ecf20Sopenharmony_ci audit_match_class(AUDIT_CLASS_READ, n)) 1768c2ecf20Sopenharmony_ci return 1; 1778c2ecf20Sopenharmony_ci if ((mask & AUDIT_PERM_ATTR) && 1788c2ecf20Sopenharmony_ci audit_match_class(AUDIT_CLASS_CHATTR, n)) 1798c2ecf20Sopenharmony_ci return 1; 1808c2ecf20Sopenharmony_ci return 0; 1818c2ecf20Sopenharmony_ci case 1: /* 32bit on biarch */ 1828c2ecf20Sopenharmony_ci if ((mask & AUDIT_PERM_WRITE) && 1838c2ecf20Sopenharmony_ci audit_match_class(AUDIT_CLASS_WRITE_32, n)) 1848c2ecf20Sopenharmony_ci return 1; 1858c2ecf20Sopenharmony_ci if ((mask & AUDIT_PERM_READ) && 1868c2ecf20Sopenharmony_ci audit_match_class(AUDIT_CLASS_READ_32, n)) 1878c2ecf20Sopenharmony_ci return 1; 1888c2ecf20Sopenharmony_ci if ((mask & AUDIT_PERM_ATTR) && 1898c2ecf20Sopenharmony_ci audit_match_class(AUDIT_CLASS_CHATTR_32, n)) 1908c2ecf20Sopenharmony_ci return 1; 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci case 2: /* open */ 1938c2ecf20Sopenharmony_ci return mask & ACC_MODE(ctx->argv[1]); 1948c2ecf20Sopenharmony_ci case 3: /* openat */ 1958c2ecf20Sopenharmony_ci return mask & ACC_MODE(ctx->argv[2]); 1968c2ecf20Sopenharmony_ci case 4: /* socketcall */ 1978c2ecf20Sopenharmony_ci return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND); 1988c2ecf20Sopenharmony_ci case 5: /* execve */ 1998c2ecf20Sopenharmony_ci return mask & AUDIT_PERM_EXEC; 2008c2ecf20Sopenharmony_ci default: 2018c2ecf20Sopenharmony_ci return 0; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic int audit_match_filetype(struct audit_context *ctx, int val) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct audit_names *n; 2088c2ecf20Sopenharmony_ci umode_t mode = (umode_t)val; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (unlikely(!ctx)) 2118c2ecf20Sopenharmony_ci return 0; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 2148c2ecf20Sopenharmony_ci if ((n->ino != AUDIT_INO_UNSET) && 2158c2ecf20Sopenharmony_ci ((n->mode & S_IFMT) == mode)) 2168c2ecf20Sopenharmony_ci return 1; 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci return 0; 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/* 2238c2ecf20Sopenharmony_ci * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *; 2248c2ecf20Sopenharmony_ci * ->first_trees points to its beginning, ->trees - to the current end of data. 2258c2ecf20Sopenharmony_ci * ->tree_count is the number of free entries in array pointed to by ->trees. 2268c2ecf20Sopenharmony_ci * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL, 2278c2ecf20Sopenharmony_ci * "empty" becomes (p, p, 31) afterwards. We don't shrink the list (and seriously, 2288c2ecf20Sopenharmony_ci * it's going to remain 1-element for almost any setup) until we free context itself. 2298c2ecf20Sopenharmony_ci * References in it _are_ dropped - at the same time we free/drop aux stuff. 2308c2ecf20Sopenharmony_ci */ 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void audit_set_auditable(struct audit_context *ctx) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci if (!ctx->prio) { 2358c2ecf20Sopenharmony_ci ctx->prio = 1; 2368c2ecf20Sopenharmony_ci ctx->current_state = AUDIT_RECORD_CONTEXT; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci struct audit_tree_refs *p = ctx->trees; 2438c2ecf20Sopenharmony_ci int left = ctx->tree_count; 2448c2ecf20Sopenharmony_ci if (likely(left)) { 2458c2ecf20Sopenharmony_ci p->c[--left] = chunk; 2468c2ecf20Sopenharmony_ci ctx->tree_count = left; 2478c2ecf20Sopenharmony_ci return 1; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci if (!p) 2508c2ecf20Sopenharmony_ci return 0; 2518c2ecf20Sopenharmony_ci p = p->next; 2528c2ecf20Sopenharmony_ci if (p) { 2538c2ecf20Sopenharmony_ci p->c[30] = chunk; 2548c2ecf20Sopenharmony_ci ctx->trees = p; 2558c2ecf20Sopenharmony_ci ctx->tree_count = 30; 2568c2ecf20Sopenharmony_ci return 1; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci return 0; 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic int grow_tree_refs(struct audit_context *ctx) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci struct audit_tree_refs *p = ctx->trees; 2648c2ecf20Sopenharmony_ci ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL); 2658c2ecf20Sopenharmony_ci if (!ctx->trees) { 2668c2ecf20Sopenharmony_ci ctx->trees = p; 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci if (p) 2708c2ecf20Sopenharmony_ci p->next = ctx->trees; 2718c2ecf20Sopenharmony_ci else 2728c2ecf20Sopenharmony_ci ctx->first_trees = ctx->trees; 2738c2ecf20Sopenharmony_ci ctx->tree_count = 31; 2748c2ecf20Sopenharmony_ci return 1; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic void unroll_tree_refs(struct audit_context *ctx, 2788c2ecf20Sopenharmony_ci struct audit_tree_refs *p, int count) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci struct audit_tree_refs *q; 2818c2ecf20Sopenharmony_ci int n; 2828c2ecf20Sopenharmony_ci if (!p) { 2838c2ecf20Sopenharmony_ci /* we started with empty chain */ 2848c2ecf20Sopenharmony_ci p = ctx->first_trees; 2858c2ecf20Sopenharmony_ci count = 31; 2868c2ecf20Sopenharmony_ci /* if the very first allocation has failed, nothing to do */ 2878c2ecf20Sopenharmony_ci if (!p) 2888c2ecf20Sopenharmony_ci return; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci n = count; 2918c2ecf20Sopenharmony_ci for (q = p; q != ctx->trees; q = q->next, n = 31) { 2928c2ecf20Sopenharmony_ci while (n--) { 2938c2ecf20Sopenharmony_ci audit_put_chunk(q->c[n]); 2948c2ecf20Sopenharmony_ci q->c[n] = NULL; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci while (n-- > ctx->tree_count) { 2988c2ecf20Sopenharmony_ci audit_put_chunk(q->c[n]); 2998c2ecf20Sopenharmony_ci q->c[n] = NULL; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci ctx->trees = p; 3028c2ecf20Sopenharmony_ci ctx->tree_count = count; 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic void free_tree_refs(struct audit_context *ctx) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct audit_tree_refs *p, *q; 3088c2ecf20Sopenharmony_ci for (p = ctx->first_trees; p; p = q) { 3098c2ecf20Sopenharmony_ci q = p->next; 3108c2ecf20Sopenharmony_ci kfree(p); 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct audit_tree_refs *p; 3178c2ecf20Sopenharmony_ci int n; 3188c2ecf20Sopenharmony_ci if (!tree) 3198c2ecf20Sopenharmony_ci return 0; 3208c2ecf20Sopenharmony_ci /* full ones */ 3218c2ecf20Sopenharmony_ci for (p = ctx->first_trees; p != ctx->trees; p = p->next) { 3228c2ecf20Sopenharmony_ci for (n = 0; n < 31; n++) 3238c2ecf20Sopenharmony_ci if (audit_tree_match(p->c[n], tree)) 3248c2ecf20Sopenharmony_ci return 1; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci /* partial */ 3278c2ecf20Sopenharmony_ci if (p) { 3288c2ecf20Sopenharmony_ci for (n = ctx->tree_count; n < 31; n++) 3298c2ecf20Sopenharmony_ci if (audit_tree_match(p->c[n], tree)) 3308c2ecf20Sopenharmony_ci return 1; 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci return 0; 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic int audit_compare_uid(kuid_t uid, 3368c2ecf20Sopenharmony_ci struct audit_names *name, 3378c2ecf20Sopenharmony_ci struct audit_field *f, 3388c2ecf20Sopenharmony_ci struct audit_context *ctx) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci struct audit_names *n; 3418c2ecf20Sopenharmony_ci int rc; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (name) { 3448c2ecf20Sopenharmony_ci rc = audit_uid_comparator(uid, f->op, name->uid); 3458c2ecf20Sopenharmony_ci if (rc) 3468c2ecf20Sopenharmony_ci return rc; 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (ctx) { 3508c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 3518c2ecf20Sopenharmony_ci rc = audit_uid_comparator(uid, f->op, n->uid); 3528c2ecf20Sopenharmony_ci if (rc) 3538c2ecf20Sopenharmony_ci return rc; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci return 0; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic int audit_compare_gid(kgid_t gid, 3608c2ecf20Sopenharmony_ci struct audit_names *name, 3618c2ecf20Sopenharmony_ci struct audit_field *f, 3628c2ecf20Sopenharmony_ci struct audit_context *ctx) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci struct audit_names *n; 3658c2ecf20Sopenharmony_ci int rc; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (name) { 3688c2ecf20Sopenharmony_ci rc = audit_gid_comparator(gid, f->op, name->gid); 3698c2ecf20Sopenharmony_ci if (rc) 3708c2ecf20Sopenharmony_ci return rc; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (ctx) { 3748c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 3758c2ecf20Sopenharmony_ci rc = audit_gid_comparator(gid, f->op, n->gid); 3768c2ecf20Sopenharmony_ci if (rc) 3778c2ecf20Sopenharmony_ci return rc; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci return 0; 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic int audit_field_compare(struct task_struct *tsk, 3848c2ecf20Sopenharmony_ci const struct cred *cred, 3858c2ecf20Sopenharmony_ci struct audit_field *f, 3868c2ecf20Sopenharmony_ci struct audit_context *ctx, 3878c2ecf20Sopenharmony_ci struct audit_names *name) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci switch (f->val) { 3908c2ecf20Sopenharmony_ci /* process to file object comparisons */ 3918c2ecf20Sopenharmony_ci case AUDIT_COMPARE_UID_TO_OBJ_UID: 3928c2ecf20Sopenharmony_ci return audit_compare_uid(cred->uid, name, f, ctx); 3938c2ecf20Sopenharmony_ci case AUDIT_COMPARE_GID_TO_OBJ_GID: 3948c2ecf20Sopenharmony_ci return audit_compare_gid(cred->gid, name, f, ctx); 3958c2ecf20Sopenharmony_ci case AUDIT_COMPARE_EUID_TO_OBJ_UID: 3968c2ecf20Sopenharmony_ci return audit_compare_uid(cred->euid, name, f, ctx); 3978c2ecf20Sopenharmony_ci case AUDIT_COMPARE_EGID_TO_OBJ_GID: 3988c2ecf20Sopenharmony_ci return audit_compare_gid(cred->egid, name, f, ctx); 3998c2ecf20Sopenharmony_ci case AUDIT_COMPARE_AUID_TO_OBJ_UID: 4008c2ecf20Sopenharmony_ci return audit_compare_uid(audit_get_loginuid(tsk), name, f, ctx); 4018c2ecf20Sopenharmony_ci case AUDIT_COMPARE_SUID_TO_OBJ_UID: 4028c2ecf20Sopenharmony_ci return audit_compare_uid(cred->suid, name, f, ctx); 4038c2ecf20Sopenharmony_ci case AUDIT_COMPARE_SGID_TO_OBJ_GID: 4048c2ecf20Sopenharmony_ci return audit_compare_gid(cred->sgid, name, f, ctx); 4058c2ecf20Sopenharmony_ci case AUDIT_COMPARE_FSUID_TO_OBJ_UID: 4068c2ecf20Sopenharmony_ci return audit_compare_uid(cred->fsuid, name, f, ctx); 4078c2ecf20Sopenharmony_ci case AUDIT_COMPARE_FSGID_TO_OBJ_GID: 4088c2ecf20Sopenharmony_ci return audit_compare_gid(cred->fsgid, name, f, ctx); 4098c2ecf20Sopenharmony_ci /* uid comparisons */ 4108c2ecf20Sopenharmony_ci case AUDIT_COMPARE_UID_TO_AUID: 4118c2ecf20Sopenharmony_ci return audit_uid_comparator(cred->uid, f->op, 4128c2ecf20Sopenharmony_ci audit_get_loginuid(tsk)); 4138c2ecf20Sopenharmony_ci case AUDIT_COMPARE_UID_TO_EUID: 4148c2ecf20Sopenharmony_ci return audit_uid_comparator(cred->uid, f->op, cred->euid); 4158c2ecf20Sopenharmony_ci case AUDIT_COMPARE_UID_TO_SUID: 4168c2ecf20Sopenharmony_ci return audit_uid_comparator(cred->uid, f->op, cred->suid); 4178c2ecf20Sopenharmony_ci case AUDIT_COMPARE_UID_TO_FSUID: 4188c2ecf20Sopenharmony_ci return audit_uid_comparator(cred->uid, f->op, cred->fsuid); 4198c2ecf20Sopenharmony_ci /* auid comparisons */ 4208c2ecf20Sopenharmony_ci case AUDIT_COMPARE_AUID_TO_EUID: 4218c2ecf20Sopenharmony_ci return audit_uid_comparator(audit_get_loginuid(tsk), f->op, 4228c2ecf20Sopenharmony_ci cred->euid); 4238c2ecf20Sopenharmony_ci case AUDIT_COMPARE_AUID_TO_SUID: 4248c2ecf20Sopenharmony_ci return audit_uid_comparator(audit_get_loginuid(tsk), f->op, 4258c2ecf20Sopenharmony_ci cred->suid); 4268c2ecf20Sopenharmony_ci case AUDIT_COMPARE_AUID_TO_FSUID: 4278c2ecf20Sopenharmony_ci return audit_uid_comparator(audit_get_loginuid(tsk), f->op, 4288c2ecf20Sopenharmony_ci cred->fsuid); 4298c2ecf20Sopenharmony_ci /* euid comparisons */ 4308c2ecf20Sopenharmony_ci case AUDIT_COMPARE_EUID_TO_SUID: 4318c2ecf20Sopenharmony_ci return audit_uid_comparator(cred->euid, f->op, cred->suid); 4328c2ecf20Sopenharmony_ci case AUDIT_COMPARE_EUID_TO_FSUID: 4338c2ecf20Sopenharmony_ci return audit_uid_comparator(cred->euid, f->op, cred->fsuid); 4348c2ecf20Sopenharmony_ci /* suid comparisons */ 4358c2ecf20Sopenharmony_ci case AUDIT_COMPARE_SUID_TO_FSUID: 4368c2ecf20Sopenharmony_ci return audit_uid_comparator(cred->suid, f->op, cred->fsuid); 4378c2ecf20Sopenharmony_ci /* gid comparisons */ 4388c2ecf20Sopenharmony_ci case AUDIT_COMPARE_GID_TO_EGID: 4398c2ecf20Sopenharmony_ci return audit_gid_comparator(cred->gid, f->op, cred->egid); 4408c2ecf20Sopenharmony_ci case AUDIT_COMPARE_GID_TO_SGID: 4418c2ecf20Sopenharmony_ci return audit_gid_comparator(cred->gid, f->op, cred->sgid); 4428c2ecf20Sopenharmony_ci case AUDIT_COMPARE_GID_TO_FSGID: 4438c2ecf20Sopenharmony_ci return audit_gid_comparator(cred->gid, f->op, cred->fsgid); 4448c2ecf20Sopenharmony_ci /* egid comparisons */ 4458c2ecf20Sopenharmony_ci case AUDIT_COMPARE_EGID_TO_SGID: 4468c2ecf20Sopenharmony_ci return audit_gid_comparator(cred->egid, f->op, cred->sgid); 4478c2ecf20Sopenharmony_ci case AUDIT_COMPARE_EGID_TO_FSGID: 4488c2ecf20Sopenharmony_ci return audit_gid_comparator(cred->egid, f->op, cred->fsgid); 4498c2ecf20Sopenharmony_ci /* sgid comparison */ 4508c2ecf20Sopenharmony_ci case AUDIT_COMPARE_SGID_TO_FSGID: 4518c2ecf20Sopenharmony_ci return audit_gid_comparator(cred->sgid, f->op, cred->fsgid); 4528c2ecf20Sopenharmony_ci default: 4538c2ecf20Sopenharmony_ci WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); 4548c2ecf20Sopenharmony_ci return 0; 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci return 0; 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci/* Determine if any context name data matches a rule's watch data */ 4608c2ecf20Sopenharmony_ci/* Compare a task_struct with an audit_rule. Return 1 on match, 0 4618c2ecf20Sopenharmony_ci * otherwise. 4628c2ecf20Sopenharmony_ci * 4638c2ecf20Sopenharmony_ci * If task_creation is true, this is an explicit indication that we are 4648c2ecf20Sopenharmony_ci * filtering a task rule at task creation time. This and tsk == current are 4658c2ecf20Sopenharmony_ci * the only situations where tsk->cred may be accessed without an rcu read lock. 4668c2ecf20Sopenharmony_ci */ 4678c2ecf20Sopenharmony_cistatic int audit_filter_rules(struct task_struct *tsk, 4688c2ecf20Sopenharmony_ci struct audit_krule *rule, 4698c2ecf20Sopenharmony_ci struct audit_context *ctx, 4708c2ecf20Sopenharmony_ci struct audit_names *name, 4718c2ecf20Sopenharmony_ci enum audit_state *state, 4728c2ecf20Sopenharmony_ci bool task_creation) 4738c2ecf20Sopenharmony_ci{ 4748c2ecf20Sopenharmony_ci const struct cred *cred; 4758c2ecf20Sopenharmony_ci int i, need_sid = 1; 4768c2ecf20Sopenharmony_ci u32 sid; 4778c2ecf20Sopenharmony_ci unsigned int sessionid; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci for (i = 0; i < rule->field_count; i++) { 4828c2ecf20Sopenharmony_ci struct audit_field *f = &rule->fields[i]; 4838c2ecf20Sopenharmony_ci struct audit_names *n; 4848c2ecf20Sopenharmony_ci int result = 0; 4858c2ecf20Sopenharmony_ci pid_t pid; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci switch (f->type) { 4888c2ecf20Sopenharmony_ci case AUDIT_PID: 4898c2ecf20Sopenharmony_ci pid = task_tgid_nr(tsk); 4908c2ecf20Sopenharmony_ci result = audit_comparator(pid, f->op, f->val); 4918c2ecf20Sopenharmony_ci break; 4928c2ecf20Sopenharmony_ci case AUDIT_PPID: 4938c2ecf20Sopenharmony_ci if (ctx) { 4948c2ecf20Sopenharmony_ci if (!ctx->ppid) 4958c2ecf20Sopenharmony_ci ctx->ppid = task_ppid_nr(tsk); 4968c2ecf20Sopenharmony_ci result = audit_comparator(ctx->ppid, f->op, f->val); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci break; 4998c2ecf20Sopenharmony_ci case AUDIT_EXE: 5008c2ecf20Sopenharmony_ci result = audit_exe_compare(tsk, rule->exe); 5018c2ecf20Sopenharmony_ci if (f->op == Audit_not_equal) 5028c2ecf20Sopenharmony_ci result = !result; 5038c2ecf20Sopenharmony_ci break; 5048c2ecf20Sopenharmony_ci case AUDIT_UID: 5058c2ecf20Sopenharmony_ci result = audit_uid_comparator(cred->uid, f->op, f->uid); 5068c2ecf20Sopenharmony_ci break; 5078c2ecf20Sopenharmony_ci case AUDIT_EUID: 5088c2ecf20Sopenharmony_ci result = audit_uid_comparator(cred->euid, f->op, f->uid); 5098c2ecf20Sopenharmony_ci break; 5108c2ecf20Sopenharmony_ci case AUDIT_SUID: 5118c2ecf20Sopenharmony_ci result = audit_uid_comparator(cred->suid, f->op, f->uid); 5128c2ecf20Sopenharmony_ci break; 5138c2ecf20Sopenharmony_ci case AUDIT_FSUID: 5148c2ecf20Sopenharmony_ci result = audit_uid_comparator(cred->fsuid, f->op, f->uid); 5158c2ecf20Sopenharmony_ci break; 5168c2ecf20Sopenharmony_ci case AUDIT_GID: 5178c2ecf20Sopenharmony_ci result = audit_gid_comparator(cred->gid, f->op, f->gid); 5188c2ecf20Sopenharmony_ci if (f->op == Audit_equal) { 5198c2ecf20Sopenharmony_ci if (!result) 5208c2ecf20Sopenharmony_ci result = groups_search(cred->group_info, f->gid); 5218c2ecf20Sopenharmony_ci } else if (f->op == Audit_not_equal) { 5228c2ecf20Sopenharmony_ci if (result) 5238c2ecf20Sopenharmony_ci result = !groups_search(cred->group_info, f->gid); 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci break; 5268c2ecf20Sopenharmony_ci case AUDIT_EGID: 5278c2ecf20Sopenharmony_ci result = audit_gid_comparator(cred->egid, f->op, f->gid); 5288c2ecf20Sopenharmony_ci if (f->op == Audit_equal) { 5298c2ecf20Sopenharmony_ci if (!result) 5308c2ecf20Sopenharmony_ci result = groups_search(cred->group_info, f->gid); 5318c2ecf20Sopenharmony_ci } else if (f->op == Audit_not_equal) { 5328c2ecf20Sopenharmony_ci if (result) 5338c2ecf20Sopenharmony_ci result = !groups_search(cred->group_info, f->gid); 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci break; 5368c2ecf20Sopenharmony_ci case AUDIT_SGID: 5378c2ecf20Sopenharmony_ci result = audit_gid_comparator(cred->sgid, f->op, f->gid); 5388c2ecf20Sopenharmony_ci break; 5398c2ecf20Sopenharmony_ci case AUDIT_FSGID: 5408c2ecf20Sopenharmony_ci result = audit_gid_comparator(cred->fsgid, f->op, f->gid); 5418c2ecf20Sopenharmony_ci break; 5428c2ecf20Sopenharmony_ci case AUDIT_SESSIONID: 5438c2ecf20Sopenharmony_ci sessionid = audit_get_sessionid(tsk); 5448c2ecf20Sopenharmony_ci result = audit_comparator(sessionid, f->op, f->val); 5458c2ecf20Sopenharmony_ci break; 5468c2ecf20Sopenharmony_ci case AUDIT_PERS: 5478c2ecf20Sopenharmony_ci result = audit_comparator(tsk->personality, f->op, f->val); 5488c2ecf20Sopenharmony_ci break; 5498c2ecf20Sopenharmony_ci case AUDIT_ARCH: 5508c2ecf20Sopenharmony_ci if (ctx) 5518c2ecf20Sopenharmony_ci result = audit_comparator(ctx->arch, f->op, f->val); 5528c2ecf20Sopenharmony_ci break; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci case AUDIT_EXIT: 5558c2ecf20Sopenharmony_ci if (ctx && ctx->return_valid) 5568c2ecf20Sopenharmony_ci result = audit_comparator(ctx->return_code, f->op, f->val); 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci case AUDIT_SUCCESS: 5598c2ecf20Sopenharmony_ci if (ctx && ctx->return_valid) { 5608c2ecf20Sopenharmony_ci if (f->val) 5618c2ecf20Sopenharmony_ci result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS); 5628c2ecf20Sopenharmony_ci else 5638c2ecf20Sopenharmony_ci result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE); 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci break; 5668c2ecf20Sopenharmony_ci case AUDIT_DEVMAJOR: 5678c2ecf20Sopenharmony_ci if (name) { 5688c2ecf20Sopenharmony_ci if (audit_comparator(MAJOR(name->dev), f->op, f->val) || 5698c2ecf20Sopenharmony_ci audit_comparator(MAJOR(name->rdev), f->op, f->val)) 5708c2ecf20Sopenharmony_ci ++result; 5718c2ecf20Sopenharmony_ci } else if (ctx) { 5728c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 5738c2ecf20Sopenharmony_ci if (audit_comparator(MAJOR(n->dev), f->op, f->val) || 5748c2ecf20Sopenharmony_ci audit_comparator(MAJOR(n->rdev), f->op, f->val)) { 5758c2ecf20Sopenharmony_ci ++result; 5768c2ecf20Sopenharmony_ci break; 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci break; 5818c2ecf20Sopenharmony_ci case AUDIT_DEVMINOR: 5828c2ecf20Sopenharmony_ci if (name) { 5838c2ecf20Sopenharmony_ci if (audit_comparator(MINOR(name->dev), f->op, f->val) || 5848c2ecf20Sopenharmony_ci audit_comparator(MINOR(name->rdev), f->op, f->val)) 5858c2ecf20Sopenharmony_ci ++result; 5868c2ecf20Sopenharmony_ci } else if (ctx) { 5878c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 5888c2ecf20Sopenharmony_ci if (audit_comparator(MINOR(n->dev), f->op, f->val) || 5898c2ecf20Sopenharmony_ci audit_comparator(MINOR(n->rdev), f->op, f->val)) { 5908c2ecf20Sopenharmony_ci ++result; 5918c2ecf20Sopenharmony_ci break; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci break; 5968c2ecf20Sopenharmony_ci case AUDIT_INODE: 5978c2ecf20Sopenharmony_ci if (name) 5988c2ecf20Sopenharmony_ci result = audit_comparator(name->ino, f->op, f->val); 5998c2ecf20Sopenharmony_ci else if (ctx) { 6008c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 6018c2ecf20Sopenharmony_ci if (audit_comparator(n->ino, f->op, f->val)) { 6028c2ecf20Sopenharmony_ci ++result; 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci } 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci break; 6088c2ecf20Sopenharmony_ci case AUDIT_OBJ_UID: 6098c2ecf20Sopenharmony_ci if (name) { 6108c2ecf20Sopenharmony_ci result = audit_uid_comparator(name->uid, f->op, f->uid); 6118c2ecf20Sopenharmony_ci } else if (ctx) { 6128c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 6138c2ecf20Sopenharmony_ci if (audit_uid_comparator(n->uid, f->op, f->uid)) { 6148c2ecf20Sopenharmony_ci ++result; 6158c2ecf20Sopenharmony_ci break; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci break; 6208c2ecf20Sopenharmony_ci case AUDIT_OBJ_GID: 6218c2ecf20Sopenharmony_ci if (name) { 6228c2ecf20Sopenharmony_ci result = audit_gid_comparator(name->gid, f->op, f->gid); 6238c2ecf20Sopenharmony_ci } else if (ctx) { 6248c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 6258c2ecf20Sopenharmony_ci if (audit_gid_comparator(n->gid, f->op, f->gid)) { 6268c2ecf20Sopenharmony_ci ++result; 6278c2ecf20Sopenharmony_ci break; 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci } 6318c2ecf20Sopenharmony_ci break; 6328c2ecf20Sopenharmony_ci case AUDIT_WATCH: 6338c2ecf20Sopenharmony_ci if (name) { 6348c2ecf20Sopenharmony_ci result = audit_watch_compare(rule->watch, 6358c2ecf20Sopenharmony_ci name->ino, 6368c2ecf20Sopenharmony_ci name->dev); 6378c2ecf20Sopenharmony_ci if (f->op == Audit_not_equal) 6388c2ecf20Sopenharmony_ci result = !result; 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci break; 6418c2ecf20Sopenharmony_ci case AUDIT_DIR: 6428c2ecf20Sopenharmony_ci if (ctx) { 6438c2ecf20Sopenharmony_ci result = match_tree_refs(ctx, rule->tree); 6448c2ecf20Sopenharmony_ci if (f->op == Audit_not_equal) 6458c2ecf20Sopenharmony_ci result = !result; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci break; 6488c2ecf20Sopenharmony_ci case AUDIT_LOGINUID: 6498c2ecf20Sopenharmony_ci result = audit_uid_comparator(audit_get_loginuid(tsk), 6508c2ecf20Sopenharmony_ci f->op, f->uid); 6518c2ecf20Sopenharmony_ci break; 6528c2ecf20Sopenharmony_ci case AUDIT_LOGINUID_SET: 6538c2ecf20Sopenharmony_ci result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); 6548c2ecf20Sopenharmony_ci break; 6558c2ecf20Sopenharmony_ci case AUDIT_SADDR_FAM: 6568c2ecf20Sopenharmony_ci if (ctx && ctx->sockaddr) 6578c2ecf20Sopenharmony_ci result = audit_comparator(ctx->sockaddr->ss_family, 6588c2ecf20Sopenharmony_ci f->op, f->val); 6598c2ecf20Sopenharmony_ci break; 6608c2ecf20Sopenharmony_ci case AUDIT_SUBJ_USER: 6618c2ecf20Sopenharmony_ci case AUDIT_SUBJ_ROLE: 6628c2ecf20Sopenharmony_ci case AUDIT_SUBJ_TYPE: 6638c2ecf20Sopenharmony_ci case AUDIT_SUBJ_SEN: 6648c2ecf20Sopenharmony_ci case AUDIT_SUBJ_CLR: 6658c2ecf20Sopenharmony_ci /* NOTE: this may return negative values indicating 6668c2ecf20Sopenharmony_ci a temporary error. We simply treat this as a 6678c2ecf20Sopenharmony_ci match for now to avoid losing information that 6688c2ecf20Sopenharmony_ci may be wanted. An error message will also be 6698c2ecf20Sopenharmony_ci logged upon error */ 6708c2ecf20Sopenharmony_ci if (f->lsm_rule) { 6718c2ecf20Sopenharmony_ci if (need_sid) { 6728c2ecf20Sopenharmony_ci security_task_getsecid(tsk, &sid); 6738c2ecf20Sopenharmony_ci need_sid = 0; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci result = security_audit_rule_match(sid, f->type, 6768c2ecf20Sopenharmony_ci f->op, 6778c2ecf20Sopenharmony_ci f->lsm_rule); 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci break; 6808c2ecf20Sopenharmony_ci case AUDIT_OBJ_USER: 6818c2ecf20Sopenharmony_ci case AUDIT_OBJ_ROLE: 6828c2ecf20Sopenharmony_ci case AUDIT_OBJ_TYPE: 6838c2ecf20Sopenharmony_ci case AUDIT_OBJ_LEV_LOW: 6848c2ecf20Sopenharmony_ci case AUDIT_OBJ_LEV_HIGH: 6858c2ecf20Sopenharmony_ci /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR 6868c2ecf20Sopenharmony_ci also applies here */ 6878c2ecf20Sopenharmony_ci if (f->lsm_rule) { 6888c2ecf20Sopenharmony_ci /* Find files that match */ 6898c2ecf20Sopenharmony_ci if (name) { 6908c2ecf20Sopenharmony_ci result = security_audit_rule_match( 6918c2ecf20Sopenharmony_ci name->osid, 6928c2ecf20Sopenharmony_ci f->type, 6938c2ecf20Sopenharmony_ci f->op, 6948c2ecf20Sopenharmony_ci f->lsm_rule); 6958c2ecf20Sopenharmony_ci } else if (ctx) { 6968c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 6978c2ecf20Sopenharmony_ci if (security_audit_rule_match( 6988c2ecf20Sopenharmony_ci n->osid, 6998c2ecf20Sopenharmony_ci f->type, 7008c2ecf20Sopenharmony_ci f->op, 7018c2ecf20Sopenharmony_ci f->lsm_rule)) { 7028c2ecf20Sopenharmony_ci ++result; 7038c2ecf20Sopenharmony_ci break; 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci /* Find ipc objects that match */ 7088c2ecf20Sopenharmony_ci if (!ctx || ctx->type != AUDIT_IPC) 7098c2ecf20Sopenharmony_ci break; 7108c2ecf20Sopenharmony_ci if (security_audit_rule_match(ctx->ipc.osid, 7118c2ecf20Sopenharmony_ci f->type, f->op, 7128c2ecf20Sopenharmony_ci f->lsm_rule)) 7138c2ecf20Sopenharmony_ci ++result; 7148c2ecf20Sopenharmony_ci } 7158c2ecf20Sopenharmony_ci break; 7168c2ecf20Sopenharmony_ci case AUDIT_ARG0: 7178c2ecf20Sopenharmony_ci case AUDIT_ARG1: 7188c2ecf20Sopenharmony_ci case AUDIT_ARG2: 7198c2ecf20Sopenharmony_ci case AUDIT_ARG3: 7208c2ecf20Sopenharmony_ci if (ctx) 7218c2ecf20Sopenharmony_ci result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); 7228c2ecf20Sopenharmony_ci break; 7238c2ecf20Sopenharmony_ci case AUDIT_FILTERKEY: 7248c2ecf20Sopenharmony_ci /* ignore this field for filtering */ 7258c2ecf20Sopenharmony_ci result = 1; 7268c2ecf20Sopenharmony_ci break; 7278c2ecf20Sopenharmony_ci case AUDIT_PERM: 7288c2ecf20Sopenharmony_ci result = audit_match_perm(ctx, f->val); 7298c2ecf20Sopenharmony_ci if (f->op == Audit_not_equal) 7308c2ecf20Sopenharmony_ci result = !result; 7318c2ecf20Sopenharmony_ci break; 7328c2ecf20Sopenharmony_ci case AUDIT_FILETYPE: 7338c2ecf20Sopenharmony_ci result = audit_match_filetype(ctx, f->val); 7348c2ecf20Sopenharmony_ci if (f->op == Audit_not_equal) 7358c2ecf20Sopenharmony_ci result = !result; 7368c2ecf20Sopenharmony_ci break; 7378c2ecf20Sopenharmony_ci case AUDIT_FIELD_COMPARE: 7388c2ecf20Sopenharmony_ci result = audit_field_compare(tsk, cred, f, ctx, name); 7398c2ecf20Sopenharmony_ci break; 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci if (!result) 7428c2ecf20Sopenharmony_ci return 0; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (ctx) { 7468c2ecf20Sopenharmony_ci if (rule->prio <= ctx->prio) 7478c2ecf20Sopenharmony_ci return 0; 7488c2ecf20Sopenharmony_ci if (rule->filterkey) { 7498c2ecf20Sopenharmony_ci kfree(ctx->filterkey); 7508c2ecf20Sopenharmony_ci ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci ctx->prio = rule->prio; 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci switch (rule->action) { 7558c2ecf20Sopenharmony_ci case AUDIT_NEVER: 7568c2ecf20Sopenharmony_ci *state = AUDIT_DISABLED; 7578c2ecf20Sopenharmony_ci break; 7588c2ecf20Sopenharmony_ci case AUDIT_ALWAYS: 7598c2ecf20Sopenharmony_ci *state = AUDIT_RECORD_CONTEXT; 7608c2ecf20Sopenharmony_ci break; 7618c2ecf20Sopenharmony_ci } 7628c2ecf20Sopenharmony_ci return 1; 7638c2ecf20Sopenharmony_ci} 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci/* At process creation time, we can determine if system-call auditing is 7668c2ecf20Sopenharmony_ci * completely disabled for this task. Since we only have the task 7678c2ecf20Sopenharmony_ci * structure at this point, we can only check uid and gid. 7688c2ecf20Sopenharmony_ci */ 7698c2ecf20Sopenharmony_cistatic enum audit_state audit_filter_task(struct task_struct *tsk, char **key) 7708c2ecf20Sopenharmony_ci{ 7718c2ecf20Sopenharmony_ci struct audit_entry *e; 7728c2ecf20Sopenharmony_ci enum audit_state state; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci rcu_read_lock(); 7758c2ecf20Sopenharmony_ci list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) { 7768c2ecf20Sopenharmony_ci if (audit_filter_rules(tsk, &e->rule, NULL, NULL, 7778c2ecf20Sopenharmony_ci &state, true)) { 7788c2ecf20Sopenharmony_ci if (state == AUDIT_RECORD_CONTEXT) 7798c2ecf20Sopenharmony_ci *key = kstrdup(e->rule.filterkey, GFP_ATOMIC); 7808c2ecf20Sopenharmony_ci rcu_read_unlock(); 7818c2ecf20Sopenharmony_ci return state; 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci rcu_read_unlock(); 7858c2ecf20Sopenharmony_ci return AUDIT_BUILD_CONTEXT; 7868c2ecf20Sopenharmony_ci} 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_cistatic int audit_in_mask(const struct audit_krule *rule, unsigned long val) 7898c2ecf20Sopenharmony_ci{ 7908c2ecf20Sopenharmony_ci int word, bit; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci if (val > 0xffffffff) 7938c2ecf20Sopenharmony_ci return false; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci word = AUDIT_WORD(val); 7968c2ecf20Sopenharmony_ci if (word >= AUDIT_BITMASK_SIZE) 7978c2ecf20Sopenharmony_ci return false; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci bit = AUDIT_BIT(val); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci return rule->mask[word] & bit; 8028c2ecf20Sopenharmony_ci} 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci/* At syscall entry and exit time, this filter is called if the 8058c2ecf20Sopenharmony_ci * audit_state is not low enough that auditing cannot take place, but is 8068c2ecf20Sopenharmony_ci * also not high enough that we already know we have to write an audit 8078c2ecf20Sopenharmony_ci * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT). 8088c2ecf20Sopenharmony_ci */ 8098c2ecf20Sopenharmony_cistatic enum audit_state audit_filter_syscall(struct task_struct *tsk, 8108c2ecf20Sopenharmony_ci struct audit_context *ctx, 8118c2ecf20Sopenharmony_ci struct list_head *list) 8128c2ecf20Sopenharmony_ci{ 8138c2ecf20Sopenharmony_ci struct audit_entry *e; 8148c2ecf20Sopenharmony_ci enum audit_state state; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci if (auditd_test_task(tsk)) 8178c2ecf20Sopenharmony_ci return AUDIT_DISABLED; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci rcu_read_lock(); 8208c2ecf20Sopenharmony_ci list_for_each_entry_rcu(e, list, list) { 8218c2ecf20Sopenharmony_ci if (audit_in_mask(&e->rule, ctx->major) && 8228c2ecf20Sopenharmony_ci audit_filter_rules(tsk, &e->rule, ctx, NULL, 8238c2ecf20Sopenharmony_ci &state, false)) { 8248c2ecf20Sopenharmony_ci rcu_read_unlock(); 8258c2ecf20Sopenharmony_ci ctx->current_state = state; 8268c2ecf20Sopenharmony_ci return state; 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci rcu_read_unlock(); 8308c2ecf20Sopenharmony_ci return AUDIT_BUILD_CONTEXT; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci/* 8348c2ecf20Sopenharmony_ci * Given an audit_name check the inode hash table to see if they match. 8358c2ecf20Sopenharmony_ci * Called holding the rcu read lock to protect the use of audit_inode_hash 8368c2ecf20Sopenharmony_ci */ 8378c2ecf20Sopenharmony_cistatic int audit_filter_inode_name(struct task_struct *tsk, 8388c2ecf20Sopenharmony_ci struct audit_names *n, 8398c2ecf20Sopenharmony_ci struct audit_context *ctx) { 8408c2ecf20Sopenharmony_ci int h = audit_hash_ino((u32)n->ino); 8418c2ecf20Sopenharmony_ci struct list_head *list = &audit_inode_hash[h]; 8428c2ecf20Sopenharmony_ci struct audit_entry *e; 8438c2ecf20Sopenharmony_ci enum audit_state state; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci list_for_each_entry_rcu(e, list, list) { 8468c2ecf20Sopenharmony_ci if (audit_in_mask(&e->rule, ctx->major) && 8478c2ecf20Sopenharmony_ci audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) { 8488c2ecf20Sopenharmony_ci ctx->current_state = state; 8498c2ecf20Sopenharmony_ci return 1; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci return 0; 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci/* At syscall exit time, this filter is called if any audit_names have been 8568c2ecf20Sopenharmony_ci * collected during syscall processing. We only check rules in sublists at hash 8578c2ecf20Sopenharmony_ci * buckets applicable to the inode numbers in audit_names. 8588c2ecf20Sopenharmony_ci * Regarding audit_state, same rules apply as for audit_filter_syscall(). 8598c2ecf20Sopenharmony_ci */ 8608c2ecf20Sopenharmony_civoid audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci struct audit_names *n; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci if (auditd_test_task(tsk)) 8658c2ecf20Sopenharmony_ci return; 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci rcu_read_lock(); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci list_for_each_entry(n, &ctx->names_list, list) { 8708c2ecf20Sopenharmony_ci if (audit_filter_inode_name(tsk, n, ctx)) 8718c2ecf20Sopenharmony_ci break; 8728c2ecf20Sopenharmony_ci } 8738c2ecf20Sopenharmony_ci rcu_read_unlock(); 8748c2ecf20Sopenharmony_ci} 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_cistatic inline void audit_proctitle_free(struct audit_context *context) 8778c2ecf20Sopenharmony_ci{ 8788c2ecf20Sopenharmony_ci kfree(context->proctitle.value); 8798c2ecf20Sopenharmony_ci context->proctitle.value = NULL; 8808c2ecf20Sopenharmony_ci context->proctitle.len = 0; 8818c2ecf20Sopenharmony_ci} 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_cistatic inline void audit_free_module(struct audit_context *context) 8848c2ecf20Sopenharmony_ci{ 8858c2ecf20Sopenharmony_ci if (context->type == AUDIT_KERN_MODULE) { 8868c2ecf20Sopenharmony_ci kfree(context->module.name); 8878c2ecf20Sopenharmony_ci context->module.name = NULL; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_cistatic inline void audit_free_names(struct audit_context *context) 8918c2ecf20Sopenharmony_ci{ 8928c2ecf20Sopenharmony_ci struct audit_names *n, *next; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci list_for_each_entry_safe(n, next, &context->names_list, list) { 8958c2ecf20Sopenharmony_ci list_del(&n->list); 8968c2ecf20Sopenharmony_ci if (n->name) 8978c2ecf20Sopenharmony_ci putname(n->name); 8988c2ecf20Sopenharmony_ci if (n->should_free) 8998c2ecf20Sopenharmony_ci kfree(n); 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci context->name_count = 0; 9028c2ecf20Sopenharmony_ci path_put(&context->pwd); 9038c2ecf20Sopenharmony_ci context->pwd.dentry = NULL; 9048c2ecf20Sopenharmony_ci context->pwd.mnt = NULL; 9058c2ecf20Sopenharmony_ci} 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_cistatic inline void audit_free_aux(struct audit_context *context) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci struct audit_aux_data *aux; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci while ((aux = context->aux)) { 9128c2ecf20Sopenharmony_ci context->aux = aux->next; 9138c2ecf20Sopenharmony_ci kfree(aux); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci while ((aux = context->aux_pids)) { 9168c2ecf20Sopenharmony_ci context->aux_pids = aux->next; 9178c2ecf20Sopenharmony_ci kfree(aux); 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_cistatic inline struct audit_context *audit_alloc_context(enum audit_state state) 9228c2ecf20Sopenharmony_ci{ 9238c2ecf20Sopenharmony_ci struct audit_context *context; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci context = kzalloc(sizeof(*context), GFP_KERNEL); 9268c2ecf20Sopenharmony_ci if (!context) 9278c2ecf20Sopenharmony_ci return NULL; 9288c2ecf20Sopenharmony_ci context->state = state; 9298c2ecf20Sopenharmony_ci context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; 9308c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&context->killed_trees); 9318c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&context->names_list); 9328c2ecf20Sopenharmony_ci return context; 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci/** 9368c2ecf20Sopenharmony_ci * audit_alloc - allocate an audit context block for a task 9378c2ecf20Sopenharmony_ci * @tsk: task 9388c2ecf20Sopenharmony_ci * 9398c2ecf20Sopenharmony_ci * Filter on the task information and allocate a per-task audit context 9408c2ecf20Sopenharmony_ci * if necessary. Doing so turns on system call auditing for the 9418c2ecf20Sopenharmony_ci * specified task. This is called from copy_process, so no lock is 9428c2ecf20Sopenharmony_ci * needed. 9438c2ecf20Sopenharmony_ci */ 9448c2ecf20Sopenharmony_ciint audit_alloc(struct task_struct *tsk) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci struct audit_context *context; 9478c2ecf20Sopenharmony_ci enum audit_state state; 9488c2ecf20Sopenharmony_ci char *key = NULL; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci if (likely(!audit_ever_enabled)) 9518c2ecf20Sopenharmony_ci return 0; /* Return if not auditing. */ 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci state = audit_filter_task(tsk, &key); 9548c2ecf20Sopenharmony_ci if (state == AUDIT_DISABLED) { 9558c2ecf20Sopenharmony_ci clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); 9568c2ecf20Sopenharmony_ci return 0; 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci if (!(context = audit_alloc_context(state))) { 9608c2ecf20Sopenharmony_ci kfree(key); 9618c2ecf20Sopenharmony_ci audit_log_lost("out of memory in audit_alloc"); 9628c2ecf20Sopenharmony_ci return -ENOMEM; 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci context->filterkey = key; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci audit_set_context(tsk, context); 9678c2ecf20Sopenharmony_ci set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); 9688c2ecf20Sopenharmony_ci return 0; 9698c2ecf20Sopenharmony_ci} 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_cistatic inline void audit_free_context(struct audit_context *context) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci audit_free_module(context); 9748c2ecf20Sopenharmony_ci audit_free_names(context); 9758c2ecf20Sopenharmony_ci unroll_tree_refs(context, NULL, 0); 9768c2ecf20Sopenharmony_ci free_tree_refs(context); 9778c2ecf20Sopenharmony_ci audit_free_aux(context); 9788c2ecf20Sopenharmony_ci kfree(context->filterkey); 9798c2ecf20Sopenharmony_ci kfree(context->sockaddr); 9808c2ecf20Sopenharmony_ci audit_proctitle_free(context); 9818c2ecf20Sopenharmony_ci kfree(context); 9828c2ecf20Sopenharmony_ci} 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_cistatic int audit_log_pid_context(struct audit_context *context, pid_t pid, 9858c2ecf20Sopenharmony_ci kuid_t auid, kuid_t uid, unsigned int sessionid, 9868c2ecf20Sopenharmony_ci u32 sid, char *comm) 9878c2ecf20Sopenharmony_ci{ 9888c2ecf20Sopenharmony_ci struct audit_buffer *ab; 9898c2ecf20Sopenharmony_ci char *ctx = NULL; 9908c2ecf20Sopenharmony_ci u32 len; 9918c2ecf20Sopenharmony_ci int rc = 0; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); 9948c2ecf20Sopenharmony_ci if (!ab) 9958c2ecf20Sopenharmony_ci return rc; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, 9988c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, auid), 9998c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, uid), sessionid); 10008c2ecf20Sopenharmony_ci if (sid) { 10018c2ecf20Sopenharmony_ci if (security_secid_to_secctx(sid, &ctx, &len)) { 10028c2ecf20Sopenharmony_ci audit_log_format(ab, " obj=(none)"); 10038c2ecf20Sopenharmony_ci rc = 1; 10048c2ecf20Sopenharmony_ci } else { 10058c2ecf20Sopenharmony_ci audit_log_format(ab, " obj=%s", ctx); 10068c2ecf20Sopenharmony_ci security_release_secctx(ctx, len); 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci audit_log_format(ab, " ocomm="); 10108c2ecf20Sopenharmony_ci audit_log_untrustedstring(ab, comm); 10118c2ecf20Sopenharmony_ci audit_log_end(ab); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci return rc; 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_cistatic void audit_log_execve_info(struct audit_context *context, 10178c2ecf20Sopenharmony_ci struct audit_buffer **ab) 10188c2ecf20Sopenharmony_ci{ 10198c2ecf20Sopenharmony_ci long len_max; 10208c2ecf20Sopenharmony_ci long len_rem; 10218c2ecf20Sopenharmony_ci long len_full; 10228c2ecf20Sopenharmony_ci long len_buf; 10238c2ecf20Sopenharmony_ci long len_abuf = 0; 10248c2ecf20Sopenharmony_ci long len_tmp; 10258c2ecf20Sopenharmony_ci bool require_data; 10268c2ecf20Sopenharmony_ci bool encode; 10278c2ecf20Sopenharmony_ci unsigned int iter; 10288c2ecf20Sopenharmony_ci unsigned int arg; 10298c2ecf20Sopenharmony_ci char *buf_head; 10308c2ecf20Sopenharmony_ci char *buf; 10318c2ecf20Sopenharmony_ci const char __user *p = (const char __user *)current->mm->arg_start; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci /* NOTE: this buffer needs to be large enough to hold all the non-arg 10348c2ecf20Sopenharmony_ci * data we put in the audit record for this argument (see the 10358c2ecf20Sopenharmony_ci * code below) ... at this point in time 96 is plenty */ 10368c2ecf20Sopenharmony_ci char abuf[96]; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci /* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the 10398c2ecf20Sopenharmony_ci * current value of 7500 is not as important as the fact that it 10408c2ecf20Sopenharmony_ci * is less than 8k, a setting of 7500 gives us plenty of wiggle 10418c2ecf20Sopenharmony_ci * room if we go over a little bit in the logging below */ 10428c2ecf20Sopenharmony_ci WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500); 10438c2ecf20Sopenharmony_ci len_max = MAX_EXECVE_AUDIT_LEN; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* scratch buffer to hold the userspace args */ 10468c2ecf20Sopenharmony_ci buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); 10478c2ecf20Sopenharmony_ci if (!buf_head) { 10488c2ecf20Sopenharmony_ci audit_panic("out of memory for argv string"); 10498c2ecf20Sopenharmony_ci return; 10508c2ecf20Sopenharmony_ci } 10518c2ecf20Sopenharmony_ci buf = buf_head; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci audit_log_format(*ab, "argc=%d", context->execve.argc); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci len_rem = len_max; 10568c2ecf20Sopenharmony_ci len_buf = 0; 10578c2ecf20Sopenharmony_ci len_full = 0; 10588c2ecf20Sopenharmony_ci require_data = true; 10598c2ecf20Sopenharmony_ci encode = false; 10608c2ecf20Sopenharmony_ci iter = 0; 10618c2ecf20Sopenharmony_ci arg = 0; 10628c2ecf20Sopenharmony_ci do { 10638c2ecf20Sopenharmony_ci /* NOTE: we don't ever want to trust this value for anything 10648c2ecf20Sopenharmony_ci * serious, but the audit record format insists we 10658c2ecf20Sopenharmony_ci * provide an argument length for really long arguments, 10668c2ecf20Sopenharmony_ci * e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but 10678c2ecf20Sopenharmony_ci * to use strncpy_from_user() to obtain this value for 10688c2ecf20Sopenharmony_ci * recording in the log, although we don't use it 10698c2ecf20Sopenharmony_ci * anywhere here to avoid a double-fetch problem */ 10708c2ecf20Sopenharmony_ci if (len_full == 0) 10718c2ecf20Sopenharmony_ci len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci /* read more data from userspace */ 10748c2ecf20Sopenharmony_ci if (require_data) { 10758c2ecf20Sopenharmony_ci /* can we make more room in the buffer? */ 10768c2ecf20Sopenharmony_ci if (buf != buf_head) { 10778c2ecf20Sopenharmony_ci memmove(buf_head, buf, len_buf); 10788c2ecf20Sopenharmony_ci buf = buf_head; 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci /* fetch as much as we can of the argument */ 10828c2ecf20Sopenharmony_ci len_tmp = strncpy_from_user(&buf_head[len_buf], p, 10838c2ecf20Sopenharmony_ci len_max - len_buf); 10848c2ecf20Sopenharmony_ci if (len_tmp == -EFAULT) { 10858c2ecf20Sopenharmony_ci /* unable to copy from userspace */ 10868c2ecf20Sopenharmony_ci send_sig(SIGKILL, current, 0); 10878c2ecf20Sopenharmony_ci goto out; 10888c2ecf20Sopenharmony_ci } else if (len_tmp == (len_max - len_buf)) { 10898c2ecf20Sopenharmony_ci /* buffer is not large enough */ 10908c2ecf20Sopenharmony_ci require_data = true; 10918c2ecf20Sopenharmony_ci /* NOTE: if we are going to span multiple 10928c2ecf20Sopenharmony_ci * buffers force the encoding so we stand 10938c2ecf20Sopenharmony_ci * a chance at a sane len_full value and 10948c2ecf20Sopenharmony_ci * consistent record encoding */ 10958c2ecf20Sopenharmony_ci encode = true; 10968c2ecf20Sopenharmony_ci len_full = len_full * 2; 10978c2ecf20Sopenharmony_ci p += len_tmp; 10988c2ecf20Sopenharmony_ci } else { 10998c2ecf20Sopenharmony_ci require_data = false; 11008c2ecf20Sopenharmony_ci if (!encode) 11018c2ecf20Sopenharmony_ci encode = audit_string_contains_control( 11028c2ecf20Sopenharmony_ci buf, len_tmp); 11038c2ecf20Sopenharmony_ci /* try to use a trusted value for len_full */ 11048c2ecf20Sopenharmony_ci if (len_full < len_max) 11058c2ecf20Sopenharmony_ci len_full = (encode ? 11068c2ecf20Sopenharmony_ci len_tmp * 2 : len_tmp); 11078c2ecf20Sopenharmony_ci p += len_tmp + 1; 11088c2ecf20Sopenharmony_ci } 11098c2ecf20Sopenharmony_ci len_buf += len_tmp; 11108c2ecf20Sopenharmony_ci buf_head[len_buf] = '\0'; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci /* length of the buffer in the audit record? */ 11138c2ecf20Sopenharmony_ci len_abuf = (encode ? len_buf * 2 : len_buf + 2); 11148c2ecf20Sopenharmony_ci } 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci /* write as much as we can to the audit log */ 11178c2ecf20Sopenharmony_ci if (len_buf >= 0) { 11188c2ecf20Sopenharmony_ci /* NOTE: some magic numbers here - basically if we 11198c2ecf20Sopenharmony_ci * can't fit a reasonable amount of data into the 11208c2ecf20Sopenharmony_ci * existing audit buffer, flush it and start with 11218c2ecf20Sopenharmony_ci * a new buffer */ 11228c2ecf20Sopenharmony_ci if ((sizeof(abuf) + 8) > len_rem) { 11238c2ecf20Sopenharmony_ci len_rem = len_max; 11248c2ecf20Sopenharmony_ci audit_log_end(*ab); 11258c2ecf20Sopenharmony_ci *ab = audit_log_start(context, 11268c2ecf20Sopenharmony_ci GFP_KERNEL, AUDIT_EXECVE); 11278c2ecf20Sopenharmony_ci if (!*ab) 11288c2ecf20Sopenharmony_ci goto out; 11298c2ecf20Sopenharmony_ci } 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci /* create the non-arg portion of the arg record */ 11328c2ecf20Sopenharmony_ci len_tmp = 0; 11338c2ecf20Sopenharmony_ci if (require_data || (iter > 0) || 11348c2ecf20Sopenharmony_ci ((len_abuf + sizeof(abuf)) > len_rem)) { 11358c2ecf20Sopenharmony_ci if (iter == 0) { 11368c2ecf20Sopenharmony_ci len_tmp += snprintf(&abuf[len_tmp], 11378c2ecf20Sopenharmony_ci sizeof(abuf) - len_tmp, 11388c2ecf20Sopenharmony_ci " a%d_len=%lu", 11398c2ecf20Sopenharmony_ci arg, len_full); 11408c2ecf20Sopenharmony_ci } 11418c2ecf20Sopenharmony_ci len_tmp += snprintf(&abuf[len_tmp], 11428c2ecf20Sopenharmony_ci sizeof(abuf) - len_tmp, 11438c2ecf20Sopenharmony_ci " a%d[%d]=", arg, iter++); 11448c2ecf20Sopenharmony_ci } else 11458c2ecf20Sopenharmony_ci len_tmp += snprintf(&abuf[len_tmp], 11468c2ecf20Sopenharmony_ci sizeof(abuf) - len_tmp, 11478c2ecf20Sopenharmony_ci " a%d=", arg); 11488c2ecf20Sopenharmony_ci WARN_ON(len_tmp >= sizeof(abuf)); 11498c2ecf20Sopenharmony_ci abuf[sizeof(abuf) - 1] = '\0'; 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci /* log the arg in the audit record */ 11528c2ecf20Sopenharmony_ci audit_log_format(*ab, "%s", abuf); 11538c2ecf20Sopenharmony_ci len_rem -= len_tmp; 11548c2ecf20Sopenharmony_ci len_tmp = len_buf; 11558c2ecf20Sopenharmony_ci if (encode) { 11568c2ecf20Sopenharmony_ci if (len_abuf > len_rem) 11578c2ecf20Sopenharmony_ci len_tmp = len_rem / 2; /* encoding */ 11588c2ecf20Sopenharmony_ci audit_log_n_hex(*ab, buf, len_tmp); 11598c2ecf20Sopenharmony_ci len_rem -= len_tmp * 2; 11608c2ecf20Sopenharmony_ci len_abuf -= len_tmp * 2; 11618c2ecf20Sopenharmony_ci } else { 11628c2ecf20Sopenharmony_ci if (len_abuf > len_rem) 11638c2ecf20Sopenharmony_ci len_tmp = len_rem - 2; /* quotes */ 11648c2ecf20Sopenharmony_ci audit_log_n_string(*ab, buf, len_tmp); 11658c2ecf20Sopenharmony_ci len_rem -= len_tmp + 2; 11668c2ecf20Sopenharmony_ci /* don't subtract the "2" because we still need 11678c2ecf20Sopenharmony_ci * to add quotes to the remaining string */ 11688c2ecf20Sopenharmony_ci len_abuf -= len_tmp; 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci len_buf -= len_tmp; 11718c2ecf20Sopenharmony_ci buf += len_tmp; 11728c2ecf20Sopenharmony_ci } 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci /* ready to move to the next argument? */ 11758c2ecf20Sopenharmony_ci if ((len_buf == 0) && !require_data) { 11768c2ecf20Sopenharmony_ci arg++; 11778c2ecf20Sopenharmony_ci iter = 0; 11788c2ecf20Sopenharmony_ci len_full = 0; 11798c2ecf20Sopenharmony_ci require_data = true; 11808c2ecf20Sopenharmony_ci encode = false; 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci } while (arg < context->execve.argc); 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci /* NOTE: the caller handles the final audit_log_end() call */ 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ciout: 11878c2ecf20Sopenharmony_ci kfree(buf_head); 11888c2ecf20Sopenharmony_ci} 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_cistatic void audit_log_cap(struct audit_buffer *ab, char *prefix, 11918c2ecf20Sopenharmony_ci kernel_cap_t *cap) 11928c2ecf20Sopenharmony_ci{ 11938c2ecf20Sopenharmony_ci int i; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (cap_isclear(*cap)) { 11968c2ecf20Sopenharmony_ci audit_log_format(ab, " %s=0", prefix); 11978c2ecf20Sopenharmony_ci return; 11988c2ecf20Sopenharmony_ci } 11998c2ecf20Sopenharmony_ci audit_log_format(ab, " %s=", prefix); 12008c2ecf20Sopenharmony_ci CAP_FOR_EACH_U32(i) 12018c2ecf20Sopenharmony_ci audit_log_format(ab, "%08x", cap->cap[CAP_LAST_U32 - i]); 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_cistatic void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) 12058c2ecf20Sopenharmony_ci{ 12068c2ecf20Sopenharmony_ci if (name->fcap_ver == -1) { 12078c2ecf20Sopenharmony_ci audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?"); 12088c2ecf20Sopenharmony_ci return; 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci audit_log_cap(ab, "cap_fp", &name->fcap.permitted); 12118c2ecf20Sopenharmony_ci audit_log_cap(ab, "cap_fi", &name->fcap.inheritable); 12128c2ecf20Sopenharmony_ci audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d", 12138c2ecf20Sopenharmony_ci name->fcap.fE, name->fcap_ver, 12148c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, name->fcap.rootid)); 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic void audit_log_time(struct audit_context *context, struct audit_buffer **ab) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci const struct audit_ntp_data *ntp = &context->time.ntp_data; 12208c2ecf20Sopenharmony_ci const struct timespec64 *tk = &context->time.tk_injoffset; 12218c2ecf20Sopenharmony_ci static const char * const ntp_name[] = { 12228c2ecf20Sopenharmony_ci "offset", 12238c2ecf20Sopenharmony_ci "freq", 12248c2ecf20Sopenharmony_ci "status", 12258c2ecf20Sopenharmony_ci "tai", 12268c2ecf20Sopenharmony_ci "tick", 12278c2ecf20Sopenharmony_ci "adjust", 12288c2ecf20Sopenharmony_ci }; 12298c2ecf20Sopenharmony_ci int type; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci if (context->type == AUDIT_TIME_ADJNTPVAL) { 12328c2ecf20Sopenharmony_ci for (type = 0; type < AUDIT_NTP_NVALS; type++) { 12338c2ecf20Sopenharmony_ci if (ntp->vals[type].newval != ntp->vals[type].oldval) { 12348c2ecf20Sopenharmony_ci if (!*ab) { 12358c2ecf20Sopenharmony_ci *ab = audit_log_start(context, 12368c2ecf20Sopenharmony_ci GFP_KERNEL, 12378c2ecf20Sopenharmony_ci AUDIT_TIME_ADJNTPVAL); 12388c2ecf20Sopenharmony_ci if (!*ab) 12398c2ecf20Sopenharmony_ci return; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci audit_log_format(*ab, "op=%s old=%lli new=%lli", 12428c2ecf20Sopenharmony_ci ntp_name[type], 12438c2ecf20Sopenharmony_ci ntp->vals[type].oldval, 12448c2ecf20Sopenharmony_ci ntp->vals[type].newval); 12458c2ecf20Sopenharmony_ci audit_log_end(*ab); 12468c2ecf20Sopenharmony_ci *ab = NULL; 12478c2ecf20Sopenharmony_ci } 12488c2ecf20Sopenharmony_ci } 12498c2ecf20Sopenharmony_ci } 12508c2ecf20Sopenharmony_ci if (tk->tv_sec != 0 || tk->tv_nsec != 0) { 12518c2ecf20Sopenharmony_ci if (!*ab) { 12528c2ecf20Sopenharmony_ci *ab = audit_log_start(context, GFP_KERNEL, 12538c2ecf20Sopenharmony_ci AUDIT_TIME_INJOFFSET); 12548c2ecf20Sopenharmony_ci if (!*ab) 12558c2ecf20Sopenharmony_ci return; 12568c2ecf20Sopenharmony_ci } 12578c2ecf20Sopenharmony_ci audit_log_format(*ab, "sec=%lli nsec=%li", 12588c2ecf20Sopenharmony_ci (long long)tk->tv_sec, tk->tv_nsec); 12598c2ecf20Sopenharmony_ci audit_log_end(*ab); 12608c2ecf20Sopenharmony_ci *ab = NULL; 12618c2ecf20Sopenharmony_ci } 12628c2ecf20Sopenharmony_ci} 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_cistatic void show_special(struct audit_context *context, int *call_panic) 12658c2ecf20Sopenharmony_ci{ 12668c2ecf20Sopenharmony_ci struct audit_buffer *ab; 12678c2ecf20Sopenharmony_ci int i; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, context->type); 12708c2ecf20Sopenharmony_ci if (!ab) 12718c2ecf20Sopenharmony_ci return; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci switch (context->type) { 12748c2ecf20Sopenharmony_ci case AUDIT_SOCKETCALL: { 12758c2ecf20Sopenharmony_ci int nargs = context->socketcall.nargs; 12768c2ecf20Sopenharmony_ci audit_log_format(ab, "nargs=%d", nargs); 12778c2ecf20Sopenharmony_ci for (i = 0; i < nargs; i++) 12788c2ecf20Sopenharmony_ci audit_log_format(ab, " a%d=%lx", i, 12798c2ecf20Sopenharmony_ci context->socketcall.args[i]); 12808c2ecf20Sopenharmony_ci break; } 12818c2ecf20Sopenharmony_ci case AUDIT_IPC: { 12828c2ecf20Sopenharmony_ci u32 osid = context->ipc.osid; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho", 12858c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, context->ipc.uid), 12868c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, context->ipc.gid), 12878c2ecf20Sopenharmony_ci context->ipc.mode); 12888c2ecf20Sopenharmony_ci if (osid) { 12898c2ecf20Sopenharmony_ci char *ctx = NULL; 12908c2ecf20Sopenharmony_ci u32 len; 12918c2ecf20Sopenharmony_ci if (security_secid_to_secctx(osid, &ctx, &len)) { 12928c2ecf20Sopenharmony_ci audit_log_format(ab, " osid=%u", osid); 12938c2ecf20Sopenharmony_ci *call_panic = 1; 12948c2ecf20Sopenharmony_ci } else { 12958c2ecf20Sopenharmony_ci audit_log_format(ab, " obj=%s", ctx); 12968c2ecf20Sopenharmony_ci security_release_secctx(ctx, len); 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci } 12998c2ecf20Sopenharmony_ci if (context->ipc.has_perm) { 13008c2ecf20Sopenharmony_ci audit_log_end(ab); 13018c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, 13028c2ecf20Sopenharmony_ci AUDIT_IPC_SET_PERM); 13038c2ecf20Sopenharmony_ci if (unlikely(!ab)) 13048c2ecf20Sopenharmony_ci return; 13058c2ecf20Sopenharmony_ci audit_log_format(ab, 13068c2ecf20Sopenharmony_ci "qbytes=%lx ouid=%u ogid=%u mode=%#ho", 13078c2ecf20Sopenharmony_ci context->ipc.qbytes, 13088c2ecf20Sopenharmony_ci context->ipc.perm_uid, 13098c2ecf20Sopenharmony_ci context->ipc.perm_gid, 13108c2ecf20Sopenharmony_ci context->ipc.perm_mode); 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci break; } 13138c2ecf20Sopenharmony_ci case AUDIT_MQ_OPEN: 13148c2ecf20Sopenharmony_ci audit_log_format(ab, 13158c2ecf20Sopenharmony_ci "oflag=0x%x mode=%#ho mq_flags=0x%lx mq_maxmsg=%ld " 13168c2ecf20Sopenharmony_ci "mq_msgsize=%ld mq_curmsgs=%ld", 13178c2ecf20Sopenharmony_ci context->mq_open.oflag, context->mq_open.mode, 13188c2ecf20Sopenharmony_ci context->mq_open.attr.mq_flags, 13198c2ecf20Sopenharmony_ci context->mq_open.attr.mq_maxmsg, 13208c2ecf20Sopenharmony_ci context->mq_open.attr.mq_msgsize, 13218c2ecf20Sopenharmony_ci context->mq_open.attr.mq_curmsgs); 13228c2ecf20Sopenharmony_ci break; 13238c2ecf20Sopenharmony_ci case AUDIT_MQ_SENDRECV: 13248c2ecf20Sopenharmony_ci audit_log_format(ab, 13258c2ecf20Sopenharmony_ci "mqdes=%d msg_len=%zd msg_prio=%u " 13268c2ecf20Sopenharmony_ci "abs_timeout_sec=%lld abs_timeout_nsec=%ld", 13278c2ecf20Sopenharmony_ci context->mq_sendrecv.mqdes, 13288c2ecf20Sopenharmony_ci context->mq_sendrecv.msg_len, 13298c2ecf20Sopenharmony_ci context->mq_sendrecv.msg_prio, 13308c2ecf20Sopenharmony_ci (long long) context->mq_sendrecv.abs_timeout.tv_sec, 13318c2ecf20Sopenharmony_ci context->mq_sendrecv.abs_timeout.tv_nsec); 13328c2ecf20Sopenharmony_ci break; 13338c2ecf20Sopenharmony_ci case AUDIT_MQ_NOTIFY: 13348c2ecf20Sopenharmony_ci audit_log_format(ab, "mqdes=%d sigev_signo=%d", 13358c2ecf20Sopenharmony_ci context->mq_notify.mqdes, 13368c2ecf20Sopenharmony_ci context->mq_notify.sigev_signo); 13378c2ecf20Sopenharmony_ci break; 13388c2ecf20Sopenharmony_ci case AUDIT_MQ_GETSETATTR: { 13398c2ecf20Sopenharmony_ci struct mq_attr *attr = &context->mq_getsetattr.mqstat; 13408c2ecf20Sopenharmony_ci audit_log_format(ab, 13418c2ecf20Sopenharmony_ci "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld " 13428c2ecf20Sopenharmony_ci "mq_curmsgs=%ld ", 13438c2ecf20Sopenharmony_ci context->mq_getsetattr.mqdes, 13448c2ecf20Sopenharmony_ci attr->mq_flags, attr->mq_maxmsg, 13458c2ecf20Sopenharmony_ci attr->mq_msgsize, attr->mq_curmsgs); 13468c2ecf20Sopenharmony_ci break; } 13478c2ecf20Sopenharmony_ci case AUDIT_CAPSET: 13488c2ecf20Sopenharmony_ci audit_log_format(ab, "pid=%d", context->capset.pid); 13498c2ecf20Sopenharmony_ci audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable); 13508c2ecf20Sopenharmony_ci audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted); 13518c2ecf20Sopenharmony_ci audit_log_cap(ab, "cap_pe", &context->capset.cap.effective); 13528c2ecf20Sopenharmony_ci audit_log_cap(ab, "cap_pa", &context->capset.cap.ambient); 13538c2ecf20Sopenharmony_ci break; 13548c2ecf20Sopenharmony_ci case AUDIT_MMAP: 13558c2ecf20Sopenharmony_ci audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, 13568c2ecf20Sopenharmony_ci context->mmap.flags); 13578c2ecf20Sopenharmony_ci break; 13588c2ecf20Sopenharmony_ci case AUDIT_EXECVE: 13598c2ecf20Sopenharmony_ci audit_log_execve_info(context, &ab); 13608c2ecf20Sopenharmony_ci break; 13618c2ecf20Sopenharmony_ci case AUDIT_KERN_MODULE: 13628c2ecf20Sopenharmony_ci audit_log_format(ab, "name="); 13638c2ecf20Sopenharmony_ci if (context->module.name) { 13648c2ecf20Sopenharmony_ci audit_log_untrustedstring(ab, context->module.name); 13658c2ecf20Sopenharmony_ci } else 13668c2ecf20Sopenharmony_ci audit_log_format(ab, "(null)"); 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci break; 13698c2ecf20Sopenharmony_ci case AUDIT_TIME_ADJNTPVAL: 13708c2ecf20Sopenharmony_ci case AUDIT_TIME_INJOFFSET: 13718c2ecf20Sopenharmony_ci /* this call deviates from the rest, eating the buffer */ 13728c2ecf20Sopenharmony_ci audit_log_time(context, &ab); 13738c2ecf20Sopenharmony_ci break; 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci audit_log_end(ab); 13768c2ecf20Sopenharmony_ci} 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_cistatic inline int audit_proctitle_rtrim(char *proctitle, int len) 13798c2ecf20Sopenharmony_ci{ 13808c2ecf20Sopenharmony_ci char *end = proctitle + len - 1; 13818c2ecf20Sopenharmony_ci while (end > proctitle && !isprint(*end)) 13828c2ecf20Sopenharmony_ci end--; 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci /* catch the case where proctitle is only 1 non-print character */ 13858c2ecf20Sopenharmony_ci len = end - proctitle + 1; 13868c2ecf20Sopenharmony_ci len -= isprint(proctitle[len-1]) == 0; 13878c2ecf20Sopenharmony_ci return len; 13888c2ecf20Sopenharmony_ci} 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci/* 13918c2ecf20Sopenharmony_ci * audit_log_name - produce AUDIT_PATH record from struct audit_names 13928c2ecf20Sopenharmony_ci * @context: audit_context for the task 13938c2ecf20Sopenharmony_ci * @n: audit_names structure with reportable details 13948c2ecf20Sopenharmony_ci * @path: optional path to report instead of audit_names->name 13958c2ecf20Sopenharmony_ci * @record_num: record number to report when handling a list of names 13968c2ecf20Sopenharmony_ci * @call_panic: optional pointer to int that will be updated if secid fails 13978c2ecf20Sopenharmony_ci */ 13988c2ecf20Sopenharmony_cistatic void audit_log_name(struct audit_context *context, struct audit_names *n, 13998c2ecf20Sopenharmony_ci const struct path *path, int record_num, int *call_panic) 14008c2ecf20Sopenharmony_ci{ 14018c2ecf20Sopenharmony_ci struct audit_buffer *ab; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); 14048c2ecf20Sopenharmony_ci if (!ab) 14058c2ecf20Sopenharmony_ci return; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci audit_log_format(ab, "item=%d", record_num); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci if (path) 14108c2ecf20Sopenharmony_ci audit_log_d_path(ab, " name=", path); 14118c2ecf20Sopenharmony_ci else if (n->name) { 14128c2ecf20Sopenharmony_ci switch (n->name_len) { 14138c2ecf20Sopenharmony_ci case AUDIT_NAME_FULL: 14148c2ecf20Sopenharmony_ci /* log the full path */ 14158c2ecf20Sopenharmony_ci audit_log_format(ab, " name="); 14168c2ecf20Sopenharmony_ci audit_log_untrustedstring(ab, n->name->name); 14178c2ecf20Sopenharmony_ci break; 14188c2ecf20Sopenharmony_ci case 0: 14198c2ecf20Sopenharmony_ci /* name was specified as a relative path and the 14208c2ecf20Sopenharmony_ci * directory component is the cwd 14218c2ecf20Sopenharmony_ci */ 14228c2ecf20Sopenharmony_ci audit_log_d_path(ab, " name=", &context->pwd); 14238c2ecf20Sopenharmony_ci break; 14248c2ecf20Sopenharmony_ci default: 14258c2ecf20Sopenharmony_ci /* log the name's directory component */ 14268c2ecf20Sopenharmony_ci audit_log_format(ab, " name="); 14278c2ecf20Sopenharmony_ci audit_log_n_untrustedstring(ab, n->name->name, 14288c2ecf20Sopenharmony_ci n->name_len); 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci } else 14318c2ecf20Sopenharmony_ci audit_log_format(ab, " name=(null)"); 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci if (n->ino != AUDIT_INO_UNSET) 14348c2ecf20Sopenharmony_ci audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x", 14358c2ecf20Sopenharmony_ci n->ino, 14368c2ecf20Sopenharmony_ci MAJOR(n->dev), 14378c2ecf20Sopenharmony_ci MINOR(n->dev), 14388c2ecf20Sopenharmony_ci n->mode, 14398c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, n->uid), 14408c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, n->gid), 14418c2ecf20Sopenharmony_ci MAJOR(n->rdev), 14428c2ecf20Sopenharmony_ci MINOR(n->rdev)); 14438c2ecf20Sopenharmony_ci if (n->osid != 0) { 14448c2ecf20Sopenharmony_ci char *ctx = NULL; 14458c2ecf20Sopenharmony_ci u32 len; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci if (security_secid_to_secctx( 14488c2ecf20Sopenharmony_ci n->osid, &ctx, &len)) { 14498c2ecf20Sopenharmony_ci audit_log_format(ab, " osid=%u", n->osid); 14508c2ecf20Sopenharmony_ci if (call_panic) 14518c2ecf20Sopenharmony_ci *call_panic = 2; 14528c2ecf20Sopenharmony_ci } else { 14538c2ecf20Sopenharmony_ci audit_log_format(ab, " obj=%s", ctx); 14548c2ecf20Sopenharmony_ci security_release_secctx(ctx, len); 14558c2ecf20Sopenharmony_ci } 14568c2ecf20Sopenharmony_ci } 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci /* log the audit_names record type */ 14598c2ecf20Sopenharmony_ci switch (n->type) { 14608c2ecf20Sopenharmony_ci case AUDIT_TYPE_NORMAL: 14618c2ecf20Sopenharmony_ci audit_log_format(ab, " nametype=NORMAL"); 14628c2ecf20Sopenharmony_ci break; 14638c2ecf20Sopenharmony_ci case AUDIT_TYPE_PARENT: 14648c2ecf20Sopenharmony_ci audit_log_format(ab, " nametype=PARENT"); 14658c2ecf20Sopenharmony_ci break; 14668c2ecf20Sopenharmony_ci case AUDIT_TYPE_CHILD_DELETE: 14678c2ecf20Sopenharmony_ci audit_log_format(ab, " nametype=DELETE"); 14688c2ecf20Sopenharmony_ci break; 14698c2ecf20Sopenharmony_ci case AUDIT_TYPE_CHILD_CREATE: 14708c2ecf20Sopenharmony_ci audit_log_format(ab, " nametype=CREATE"); 14718c2ecf20Sopenharmony_ci break; 14728c2ecf20Sopenharmony_ci default: 14738c2ecf20Sopenharmony_ci audit_log_format(ab, " nametype=UNKNOWN"); 14748c2ecf20Sopenharmony_ci break; 14758c2ecf20Sopenharmony_ci } 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci audit_log_fcaps(ab, n); 14788c2ecf20Sopenharmony_ci audit_log_end(ab); 14798c2ecf20Sopenharmony_ci} 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_cistatic void audit_log_proctitle(void) 14828c2ecf20Sopenharmony_ci{ 14838c2ecf20Sopenharmony_ci int res; 14848c2ecf20Sopenharmony_ci char *buf; 14858c2ecf20Sopenharmony_ci char *msg = "(null)"; 14868c2ecf20Sopenharmony_ci int len = strlen(msg); 14878c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 14888c2ecf20Sopenharmony_ci struct audit_buffer *ab; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci if (!context || context->dummy) 14918c2ecf20Sopenharmony_ci return; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); 14948c2ecf20Sopenharmony_ci if (!ab) 14958c2ecf20Sopenharmony_ci return; /* audit_panic or being filtered */ 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci audit_log_format(ab, "proctitle="); 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci /* Not cached */ 15008c2ecf20Sopenharmony_ci if (!context->proctitle.value) { 15018c2ecf20Sopenharmony_ci buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL); 15028c2ecf20Sopenharmony_ci if (!buf) 15038c2ecf20Sopenharmony_ci goto out; 15048c2ecf20Sopenharmony_ci /* Historically called this from procfs naming */ 15058c2ecf20Sopenharmony_ci res = get_cmdline(current, buf, MAX_PROCTITLE_AUDIT_LEN); 15068c2ecf20Sopenharmony_ci if (res == 0) { 15078c2ecf20Sopenharmony_ci kfree(buf); 15088c2ecf20Sopenharmony_ci goto out; 15098c2ecf20Sopenharmony_ci } 15108c2ecf20Sopenharmony_ci res = audit_proctitle_rtrim(buf, res); 15118c2ecf20Sopenharmony_ci if (res == 0) { 15128c2ecf20Sopenharmony_ci kfree(buf); 15138c2ecf20Sopenharmony_ci goto out; 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci context->proctitle.value = buf; 15168c2ecf20Sopenharmony_ci context->proctitle.len = res; 15178c2ecf20Sopenharmony_ci } 15188c2ecf20Sopenharmony_ci msg = context->proctitle.value; 15198c2ecf20Sopenharmony_ci len = context->proctitle.len; 15208c2ecf20Sopenharmony_ciout: 15218c2ecf20Sopenharmony_ci audit_log_n_untrustedstring(ab, msg, len); 15228c2ecf20Sopenharmony_ci audit_log_end(ab); 15238c2ecf20Sopenharmony_ci} 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_cistatic void audit_log_exit(void) 15268c2ecf20Sopenharmony_ci{ 15278c2ecf20Sopenharmony_ci int i, call_panic = 0; 15288c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 15298c2ecf20Sopenharmony_ci struct audit_buffer *ab; 15308c2ecf20Sopenharmony_ci struct audit_aux_data *aux; 15318c2ecf20Sopenharmony_ci struct audit_names *n; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci context->personality = current->personality; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); 15368c2ecf20Sopenharmony_ci if (!ab) 15378c2ecf20Sopenharmony_ci return; /* audit_panic has been called */ 15388c2ecf20Sopenharmony_ci audit_log_format(ab, "arch=%x syscall=%d", 15398c2ecf20Sopenharmony_ci context->arch, context->major); 15408c2ecf20Sopenharmony_ci if (context->personality != PER_LINUX) 15418c2ecf20Sopenharmony_ci audit_log_format(ab, " per=%lx", context->personality); 15428c2ecf20Sopenharmony_ci if (context->return_valid) 15438c2ecf20Sopenharmony_ci audit_log_format(ab, " success=%s exit=%ld", 15448c2ecf20Sopenharmony_ci (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", 15458c2ecf20Sopenharmony_ci context->return_code); 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci audit_log_format(ab, 15488c2ecf20Sopenharmony_ci " a0=%lx a1=%lx a2=%lx a3=%lx items=%d", 15498c2ecf20Sopenharmony_ci context->argv[0], 15508c2ecf20Sopenharmony_ci context->argv[1], 15518c2ecf20Sopenharmony_ci context->argv[2], 15528c2ecf20Sopenharmony_ci context->argv[3], 15538c2ecf20Sopenharmony_ci context->name_count); 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci audit_log_task_info(ab); 15568c2ecf20Sopenharmony_ci audit_log_key(ab, context->filterkey); 15578c2ecf20Sopenharmony_ci audit_log_end(ab); 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci for (aux = context->aux; aux; aux = aux->next) { 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, aux->type); 15628c2ecf20Sopenharmony_ci if (!ab) 15638c2ecf20Sopenharmony_ci continue; /* audit_panic has been called */ 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci switch (aux->type) { 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci case AUDIT_BPRM_FCAPS: { 15688c2ecf20Sopenharmony_ci struct audit_aux_data_bprm_fcaps *axs = (void *)aux; 15698c2ecf20Sopenharmony_ci audit_log_format(ab, "fver=%x", axs->fcap_ver); 15708c2ecf20Sopenharmony_ci audit_log_cap(ab, "fp", &axs->fcap.permitted); 15718c2ecf20Sopenharmony_ci audit_log_cap(ab, "fi", &axs->fcap.inheritable); 15728c2ecf20Sopenharmony_ci audit_log_format(ab, " fe=%d", axs->fcap.fE); 15738c2ecf20Sopenharmony_ci audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted); 15748c2ecf20Sopenharmony_ci audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable); 15758c2ecf20Sopenharmony_ci audit_log_cap(ab, "old_pe", &axs->old_pcap.effective); 15768c2ecf20Sopenharmony_ci audit_log_cap(ab, "old_pa", &axs->old_pcap.ambient); 15778c2ecf20Sopenharmony_ci audit_log_cap(ab, "pp", &axs->new_pcap.permitted); 15788c2ecf20Sopenharmony_ci audit_log_cap(ab, "pi", &axs->new_pcap.inheritable); 15798c2ecf20Sopenharmony_ci audit_log_cap(ab, "pe", &axs->new_pcap.effective); 15808c2ecf20Sopenharmony_ci audit_log_cap(ab, "pa", &axs->new_pcap.ambient); 15818c2ecf20Sopenharmony_ci audit_log_format(ab, " frootid=%d", 15828c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, 15838c2ecf20Sopenharmony_ci axs->fcap.rootid)); 15848c2ecf20Sopenharmony_ci break; } 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_ci audit_log_end(ab); 15888c2ecf20Sopenharmony_ci } 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci if (context->type) 15918c2ecf20Sopenharmony_ci show_special(context, &call_panic); 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci if (context->fds[0] >= 0) { 15948c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR); 15958c2ecf20Sopenharmony_ci if (ab) { 15968c2ecf20Sopenharmony_ci audit_log_format(ab, "fd0=%d fd1=%d", 15978c2ecf20Sopenharmony_ci context->fds[0], context->fds[1]); 15988c2ecf20Sopenharmony_ci audit_log_end(ab); 15998c2ecf20Sopenharmony_ci } 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci if (context->sockaddr_len) { 16038c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR); 16048c2ecf20Sopenharmony_ci if (ab) { 16058c2ecf20Sopenharmony_ci audit_log_format(ab, "saddr="); 16068c2ecf20Sopenharmony_ci audit_log_n_hex(ab, (void *)context->sockaddr, 16078c2ecf20Sopenharmony_ci context->sockaddr_len); 16088c2ecf20Sopenharmony_ci audit_log_end(ab); 16098c2ecf20Sopenharmony_ci } 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci for (aux = context->aux_pids; aux; aux = aux->next) { 16138c2ecf20Sopenharmony_ci struct audit_aux_data_pids *axs = (void *)aux; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci for (i = 0; i < axs->pid_count; i++) 16168c2ecf20Sopenharmony_ci if (audit_log_pid_context(context, axs->target_pid[i], 16178c2ecf20Sopenharmony_ci axs->target_auid[i], 16188c2ecf20Sopenharmony_ci axs->target_uid[i], 16198c2ecf20Sopenharmony_ci axs->target_sessionid[i], 16208c2ecf20Sopenharmony_ci axs->target_sid[i], 16218c2ecf20Sopenharmony_ci axs->target_comm[i])) 16228c2ecf20Sopenharmony_ci call_panic = 1; 16238c2ecf20Sopenharmony_ci } 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ci if (context->target_pid && 16268c2ecf20Sopenharmony_ci audit_log_pid_context(context, context->target_pid, 16278c2ecf20Sopenharmony_ci context->target_auid, context->target_uid, 16288c2ecf20Sopenharmony_ci context->target_sessionid, 16298c2ecf20Sopenharmony_ci context->target_sid, context->target_comm)) 16308c2ecf20Sopenharmony_ci call_panic = 1; 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci if (context->pwd.dentry && context->pwd.mnt) { 16338c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); 16348c2ecf20Sopenharmony_ci if (ab) { 16358c2ecf20Sopenharmony_ci audit_log_d_path(ab, "cwd=", &context->pwd); 16368c2ecf20Sopenharmony_ci audit_log_end(ab); 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci } 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci i = 0; 16418c2ecf20Sopenharmony_ci list_for_each_entry(n, &context->names_list, list) { 16428c2ecf20Sopenharmony_ci if (n->hidden) 16438c2ecf20Sopenharmony_ci continue; 16448c2ecf20Sopenharmony_ci audit_log_name(context, n, NULL, i++, &call_panic); 16458c2ecf20Sopenharmony_ci } 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci audit_log_proctitle(); 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci /* Send end of event record to help user space know we are finished */ 16508c2ecf20Sopenharmony_ci ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); 16518c2ecf20Sopenharmony_ci if (ab) 16528c2ecf20Sopenharmony_ci audit_log_end(ab); 16538c2ecf20Sopenharmony_ci if (call_panic) 16548c2ecf20Sopenharmony_ci audit_panic("error converting sid to string"); 16558c2ecf20Sopenharmony_ci} 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci/** 16588c2ecf20Sopenharmony_ci * __audit_free - free a per-task audit context 16598c2ecf20Sopenharmony_ci * @tsk: task whose audit context block to free 16608c2ecf20Sopenharmony_ci * 16618c2ecf20Sopenharmony_ci * Called from copy_process and do_exit 16628c2ecf20Sopenharmony_ci */ 16638c2ecf20Sopenharmony_civoid __audit_free(struct task_struct *tsk) 16648c2ecf20Sopenharmony_ci{ 16658c2ecf20Sopenharmony_ci struct audit_context *context = tsk->audit_context; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (!context) 16688c2ecf20Sopenharmony_ci return; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci if (!list_empty(&context->killed_trees)) 16718c2ecf20Sopenharmony_ci audit_kill_trees(context); 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci /* We are called either by do_exit() or the fork() error handling code; 16748c2ecf20Sopenharmony_ci * in the former case tsk == current and in the latter tsk is a 16758c2ecf20Sopenharmony_ci * random task_struct that doesn't doesn't have any meaningful data we 16768c2ecf20Sopenharmony_ci * need to log via audit_log_exit(). 16778c2ecf20Sopenharmony_ci */ 16788c2ecf20Sopenharmony_ci if (tsk == current && !context->dummy && context->in_syscall) { 16798c2ecf20Sopenharmony_ci context->return_valid = 0; 16808c2ecf20Sopenharmony_ci context->return_code = 0; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci audit_filter_syscall(tsk, context, 16838c2ecf20Sopenharmony_ci &audit_filter_list[AUDIT_FILTER_EXIT]); 16848c2ecf20Sopenharmony_ci audit_filter_inodes(tsk, context); 16858c2ecf20Sopenharmony_ci if (context->current_state == AUDIT_RECORD_CONTEXT) 16868c2ecf20Sopenharmony_ci audit_log_exit(); 16878c2ecf20Sopenharmony_ci } 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci audit_set_context(tsk, NULL); 16908c2ecf20Sopenharmony_ci audit_free_context(context); 16918c2ecf20Sopenharmony_ci} 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci/** 16948c2ecf20Sopenharmony_ci * __audit_syscall_entry - fill in an audit record at syscall entry 16958c2ecf20Sopenharmony_ci * @major: major syscall type (function) 16968c2ecf20Sopenharmony_ci * @a1: additional syscall register 1 16978c2ecf20Sopenharmony_ci * @a2: additional syscall register 2 16988c2ecf20Sopenharmony_ci * @a3: additional syscall register 3 16998c2ecf20Sopenharmony_ci * @a4: additional syscall register 4 17008c2ecf20Sopenharmony_ci * 17018c2ecf20Sopenharmony_ci * Fill in audit context at syscall entry. This only happens if the 17028c2ecf20Sopenharmony_ci * audit context was created when the task was created and the state or 17038c2ecf20Sopenharmony_ci * filters demand the audit context be built. If the state from the 17048c2ecf20Sopenharmony_ci * per-task filter or from the per-syscall filter is AUDIT_RECORD_CONTEXT, 17058c2ecf20Sopenharmony_ci * then the record will be written at syscall exit time (otherwise, it 17068c2ecf20Sopenharmony_ci * will only be written if another part of the kernel requests that it 17078c2ecf20Sopenharmony_ci * be written). 17088c2ecf20Sopenharmony_ci */ 17098c2ecf20Sopenharmony_civoid __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, 17108c2ecf20Sopenharmony_ci unsigned long a3, unsigned long a4) 17118c2ecf20Sopenharmony_ci{ 17128c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 17138c2ecf20Sopenharmony_ci enum audit_state state; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci if (!audit_enabled || !context) 17168c2ecf20Sopenharmony_ci return; 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci BUG_ON(context->in_syscall || context->name_count); 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci state = context->state; 17218c2ecf20Sopenharmony_ci if (state == AUDIT_DISABLED) 17228c2ecf20Sopenharmony_ci return; 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci context->dummy = !audit_n_rules; 17258c2ecf20Sopenharmony_ci if (!context->dummy && state == AUDIT_BUILD_CONTEXT) { 17268c2ecf20Sopenharmony_ci context->prio = 0; 17278c2ecf20Sopenharmony_ci if (auditd_test_task(current)) 17288c2ecf20Sopenharmony_ci return; 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci context->arch = syscall_get_arch(current); 17328c2ecf20Sopenharmony_ci context->major = major; 17338c2ecf20Sopenharmony_ci context->argv[0] = a1; 17348c2ecf20Sopenharmony_ci context->argv[1] = a2; 17358c2ecf20Sopenharmony_ci context->argv[2] = a3; 17368c2ecf20Sopenharmony_ci context->argv[3] = a4; 17378c2ecf20Sopenharmony_ci context->serial = 0; 17388c2ecf20Sopenharmony_ci context->in_syscall = 1; 17398c2ecf20Sopenharmony_ci context->current_state = state; 17408c2ecf20Sopenharmony_ci context->ppid = 0; 17418c2ecf20Sopenharmony_ci ktime_get_coarse_real_ts64(&context->ctime); 17428c2ecf20Sopenharmony_ci} 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci/** 17458c2ecf20Sopenharmony_ci * __audit_syscall_exit - deallocate audit context after a system call 17468c2ecf20Sopenharmony_ci * @success: success value of the syscall 17478c2ecf20Sopenharmony_ci * @return_code: return value of the syscall 17488c2ecf20Sopenharmony_ci * 17498c2ecf20Sopenharmony_ci * Tear down after system call. If the audit context has been marked as 17508c2ecf20Sopenharmony_ci * auditable (either because of the AUDIT_RECORD_CONTEXT state from 17518c2ecf20Sopenharmony_ci * filtering, or because some other part of the kernel wrote an audit 17528c2ecf20Sopenharmony_ci * message), then write out the syscall information. In call cases, 17538c2ecf20Sopenharmony_ci * free the names stored from getname(). 17548c2ecf20Sopenharmony_ci */ 17558c2ecf20Sopenharmony_civoid __audit_syscall_exit(int success, long return_code) 17568c2ecf20Sopenharmony_ci{ 17578c2ecf20Sopenharmony_ci struct audit_context *context; 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci context = audit_context(); 17608c2ecf20Sopenharmony_ci if (!context) 17618c2ecf20Sopenharmony_ci return; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci if (!list_empty(&context->killed_trees)) 17648c2ecf20Sopenharmony_ci audit_kill_trees(context); 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci if (!context->dummy && context->in_syscall) { 17678c2ecf20Sopenharmony_ci if (success) 17688c2ecf20Sopenharmony_ci context->return_valid = AUDITSC_SUCCESS; 17698c2ecf20Sopenharmony_ci else 17708c2ecf20Sopenharmony_ci context->return_valid = AUDITSC_FAILURE; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci /* 17738c2ecf20Sopenharmony_ci * we need to fix up the return code in the audit logs if the 17748c2ecf20Sopenharmony_ci * actual return codes are later going to be fixed up by the 17758c2ecf20Sopenharmony_ci * arch specific signal handlers 17768c2ecf20Sopenharmony_ci * 17778c2ecf20Sopenharmony_ci * This is actually a test for: 17788c2ecf20Sopenharmony_ci * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || 17798c2ecf20Sopenharmony_ci * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) 17808c2ecf20Sopenharmony_ci * 17818c2ecf20Sopenharmony_ci * but is faster than a bunch of || 17828c2ecf20Sopenharmony_ci */ 17838c2ecf20Sopenharmony_ci if (unlikely(return_code <= -ERESTARTSYS) && 17848c2ecf20Sopenharmony_ci (return_code >= -ERESTART_RESTARTBLOCK) && 17858c2ecf20Sopenharmony_ci (return_code != -ENOIOCTLCMD)) 17868c2ecf20Sopenharmony_ci context->return_code = -EINTR; 17878c2ecf20Sopenharmony_ci else 17888c2ecf20Sopenharmony_ci context->return_code = return_code; 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci audit_filter_syscall(current, context, 17918c2ecf20Sopenharmony_ci &audit_filter_list[AUDIT_FILTER_EXIT]); 17928c2ecf20Sopenharmony_ci audit_filter_inodes(current, context); 17938c2ecf20Sopenharmony_ci if (context->current_state == AUDIT_RECORD_CONTEXT) 17948c2ecf20Sopenharmony_ci audit_log_exit(); 17958c2ecf20Sopenharmony_ci } 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci context->in_syscall = 0; 17988c2ecf20Sopenharmony_ci context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci audit_free_module(context); 18018c2ecf20Sopenharmony_ci audit_free_names(context); 18028c2ecf20Sopenharmony_ci unroll_tree_refs(context, NULL, 0); 18038c2ecf20Sopenharmony_ci audit_free_aux(context); 18048c2ecf20Sopenharmony_ci context->aux = NULL; 18058c2ecf20Sopenharmony_ci context->aux_pids = NULL; 18068c2ecf20Sopenharmony_ci context->target_pid = 0; 18078c2ecf20Sopenharmony_ci context->target_sid = 0; 18088c2ecf20Sopenharmony_ci context->sockaddr_len = 0; 18098c2ecf20Sopenharmony_ci context->type = 0; 18108c2ecf20Sopenharmony_ci context->fds[0] = -1; 18118c2ecf20Sopenharmony_ci if (context->state != AUDIT_RECORD_CONTEXT) { 18128c2ecf20Sopenharmony_ci kfree(context->filterkey); 18138c2ecf20Sopenharmony_ci context->filterkey = NULL; 18148c2ecf20Sopenharmony_ci } 18158c2ecf20Sopenharmony_ci} 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_cistatic inline void handle_one(const struct inode *inode) 18188c2ecf20Sopenharmony_ci{ 18198c2ecf20Sopenharmony_ci struct audit_context *context; 18208c2ecf20Sopenharmony_ci struct audit_tree_refs *p; 18218c2ecf20Sopenharmony_ci struct audit_chunk *chunk; 18228c2ecf20Sopenharmony_ci int count; 18238c2ecf20Sopenharmony_ci if (likely(!inode->i_fsnotify_marks)) 18248c2ecf20Sopenharmony_ci return; 18258c2ecf20Sopenharmony_ci context = audit_context(); 18268c2ecf20Sopenharmony_ci p = context->trees; 18278c2ecf20Sopenharmony_ci count = context->tree_count; 18288c2ecf20Sopenharmony_ci rcu_read_lock(); 18298c2ecf20Sopenharmony_ci chunk = audit_tree_lookup(inode); 18308c2ecf20Sopenharmony_ci rcu_read_unlock(); 18318c2ecf20Sopenharmony_ci if (!chunk) 18328c2ecf20Sopenharmony_ci return; 18338c2ecf20Sopenharmony_ci if (likely(put_tree_ref(context, chunk))) 18348c2ecf20Sopenharmony_ci return; 18358c2ecf20Sopenharmony_ci if (unlikely(!grow_tree_refs(context))) { 18368c2ecf20Sopenharmony_ci pr_warn("out of memory, audit has lost a tree reference\n"); 18378c2ecf20Sopenharmony_ci audit_set_auditable(context); 18388c2ecf20Sopenharmony_ci audit_put_chunk(chunk); 18398c2ecf20Sopenharmony_ci unroll_tree_refs(context, p, count); 18408c2ecf20Sopenharmony_ci return; 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci put_tree_ref(context, chunk); 18438c2ecf20Sopenharmony_ci} 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_cistatic void handle_path(const struct dentry *dentry) 18468c2ecf20Sopenharmony_ci{ 18478c2ecf20Sopenharmony_ci struct audit_context *context; 18488c2ecf20Sopenharmony_ci struct audit_tree_refs *p; 18498c2ecf20Sopenharmony_ci const struct dentry *d, *parent; 18508c2ecf20Sopenharmony_ci struct audit_chunk *drop; 18518c2ecf20Sopenharmony_ci unsigned long seq; 18528c2ecf20Sopenharmony_ci int count; 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci context = audit_context(); 18558c2ecf20Sopenharmony_ci p = context->trees; 18568c2ecf20Sopenharmony_ci count = context->tree_count; 18578c2ecf20Sopenharmony_ciretry: 18588c2ecf20Sopenharmony_ci drop = NULL; 18598c2ecf20Sopenharmony_ci d = dentry; 18608c2ecf20Sopenharmony_ci rcu_read_lock(); 18618c2ecf20Sopenharmony_ci seq = read_seqbegin(&rename_lock); 18628c2ecf20Sopenharmony_ci for(;;) { 18638c2ecf20Sopenharmony_ci struct inode *inode = d_backing_inode(d); 18648c2ecf20Sopenharmony_ci if (inode && unlikely(inode->i_fsnotify_marks)) { 18658c2ecf20Sopenharmony_ci struct audit_chunk *chunk; 18668c2ecf20Sopenharmony_ci chunk = audit_tree_lookup(inode); 18678c2ecf20Sopenharmony_ci if (chunk) { 18688c2ecf20Sopenharmony_ci if (unlikely(!put_tree_ref(context, chunk))) { 18698c2ecf20Sopenharmony_ci drop = chunk; 18708c2ecf20Sopenharmony_ci break; 18718c2ecf20Sopenharmony_ci } 18728c2ecf20Sopenharmony_ci } 18738c2ecf20Sopenharmony_ci } 18748c2ecf20Sopenharmony_ci parent = d->d_parent; 18758c2ecf20Sopenharmony_ci if (parent == d) 18768c2ecf20Sopenharmony_ci break; 18778c2ecf20Sopenharmony_ci d = parent; 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci if (unlikely(read_seqretry(&rename_lock, seq) || drop)) { /* in this order */ 18808c2ecf20Sopenharmony_ci rcu_read_unlock(); 18818c2ecf20Sopenharmony_ci if (!drop) { 18828c2ecf20Sopenharmony_ci /* just a race with rename */ 18838c2ecf20Sopenharmony_ci unroll_tree_refs(context, p, count); 18848c2ecf20Sopenharmony_ci goto retry; 18858c2ecf20Sopenharmony_ci } 18868c2ecf20Sopenharmony_ci audit_put_chunk(drop); 18878c2ecf20Sopenharmony_ci if (grow_tree_refs(context)) { 18888c2ecf20Sopenharmony_ci /* OK, got more space */ 18898c2ecf20Sopenharmony_ci unroll_tree_refs(context, p, count); 18908c2ecf20Sopenharmony_ci goto retry; 18918c2ecf20Sopenharmony_ci } 18928c2ecf20Sopenharmony_ci /* too bad */ 18938c2ecf20Sopenharmony_ci pr_warn("out of memory, audit has lost a tree reference\n"); 18948c2ecf20Sopenharmony_ci unroll_tree_refs(context, p, count); 18958c2ecf20Sopenharmony_ci audit_set_auditable(context); 18968c2ecf20Sopenharmony_ci return; 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci rcu_read_unlock(); 18998c2ecf20Sopenharmony_ci} 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_cistatic struct audit_names *audit_alloc_name(struct audit_context *context, 19028c2ecf20Sopenharmony_ci unsigned char type) 19038c2ecf20Sopenharmony_ci{ 19048c2ecf20Sopenharmony_ci struct audit_names *aname; 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci if (context->name_count < AUDIT_NAMES) { 19078c2ecf20Sopenharmony_ci aname = &context->preallocated_names[context->name_count]; 19088c2ecf20Sopenharmony_ci memset(aname, 0, sizeof(*aname)); 19098c2ecf20Sopenharmony_ci } else { 19108c2ecf20Sopenharmony_ci aname = kzalloc(sizeof(*aname), GFP_NOFS); 19118c2ecf20Sopenharmony_ci if (!aname) 19128c2ecf20Sopenharmony_ci return NULL; 19138c2ecf20Sopenharmony_ci aname->should_free = true; 19148c2ecf20Sopenharmony_ci } 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci aname->ino = AUDIT_INO_UNSET; 19178c2ecf20Sopenharmony_ci aname->type = type; 19188c2ecf20Sopenharmony_ci list_add_tail(&aname->list, &context->names_list); 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci context->name_count++; 19218c2ecf20Sopenharmony_ci return aname; 19228c2ecf20Sopenharmony_ci} 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci/** 19258c2ecf20Sopenharmony_ci * __audit_reusename - fill out filename with info from existing entry 19268c2ecf20Sopenharmony_ci * @uptr: userland ptr to pathname 19278c2ecf20Sopenharmony_ci * 19288c2ecf20Sopenharmony_ci * Search the audit_names list for the current audit context. If there is an 19298c2ecf20Sopenharmony_ci * existing entry with a matching "uptr" then return the filename 19308c2ecf20Sopenharmony_ci * associated with that audit_name. If not, return NULL. 19318c2ecf20Sopenharmony_ci */ 19328c2ecf20Sopenharmony_cistruct filename * 19338c2ecf20Sopenharmony_ci__audit_reusename(const __user char *uptr) 19348c2ecf20Sopenharmony_ci{ 19358c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 19368c2ecf20Sopenharmony_ci struct audit_names *n; 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci list_for_each_entry(n, &context->names_list, list) { 19398c2ecf20Sopenharmony_ci if (!n->name) 19408c2ecf20Sopenharmony_ci continue; 19418c2ecf20Sopenharmony_ci if (n->name->uptr == uptr) { 19428c2ecf20Sopenharmony_ci n->name->refcnt++; 19438c2ecf20Sopenharmony_ci return n->name; 19448c2ecf20Sopenharmony_ci } 19458c2ecf20Sopenharmony_ci } 19468c2ecf20Sopenharmony_ci return NULL; 19478c2ecf20Sopenharmony_ci} 19488c2ecf20Sopenharmony_ci 19498c2ecf20Sopenharmony_ciinline void _audit_getcwd(struct audit_context *context) 19508c2ecf20Sopenharmony_ci{ 19518c2ecf20Sopenharmony_ci if (!context->pwd.dentry) 19528c2ecf20Sopenharmony_ci get_fs_pwd(current->fs, &context->pwd); 19538c2ecf20Sopenharmony_ci} 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_civoid __audit_getcwd(void) 19568c2ecf20Sopenharmony_ci{ 19578c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci if (context->in_syscall) 19608c2ecf20Sopenharmony_ci _audit_getcwd(context); 19618c2ecf20Sopenharmony_ci} 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci/** 19648c2ecf20Sopenharmony_ci * __audit_getname - add a name to the list 19658c2ecf20Sopenharmony_ci * @name: name to add 19668c2ecf20Sopenharmony_ci * 19678c2ecf20Sopenharmony_ci * Add a name to the list of audit names for this context. 19688c2ecf20Sopenharmony_ci * Called from fs/namei.c:getname(). 19698c2ecf20Sopenharmony_ci */ 19708c2ecf20Sopenharmony_civoid __audit_getname(struct filename *name) 19718c2ecf20Sopenharmony_ci{ 19728c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 19738c2ecf20Sopenharmony_ci struct audit_names *n; 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci if (!context->in_syscall) 19768c2ecf20Sopenharmony_ci return; 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); 19798c2ecf20Sopenharmony_ci if (!n) 19808c2ecf20Sopenharmony_ci return; 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci n->name = name; 19838c2ecf20Sopenharmony_ci n->name_len = AUDIT_NAME_FULL; 19848c2ecf20Sopenharmony_ci name->aname = n; 19858c2ecf20Sopenharmony_ci name->refcnt++; 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci _audit_getcwd(context); 19888c2ecf20Sopenharmony_ci} 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_cistatic inline int audit_copy_fcaps(struct audit_names *name, 19918c2ecf20Sopenharmony_ci const struct dentry *dentry) 19928c2ecf20Sopenharmony_ci{ 19938c2ecf20Sopenharmony_ci struct cpu_vfs_cap_data caps; 19948c2ecf20Sopenharmony_ci int rc; 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci if (!dentry) 19978c2ecf20Sopenharmony_ci return 0; 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci rc = get_vfs_caps_from_disk(dentry, &caps); 20008c2ecf20Sopenharmony_ci if (rc) 20018c2ecf20Sopenharmony_ci return rc; 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci name->fcap.permitted = caps.permitted; 20048c2ecf20Sopenharmony_ci name->fcap.inheritable = caps.inheritable; 20058c2ecf20Sopenharmony_ci name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); 20068c2ecf20Sopenharmony_ci name->fcap.rootid = caps.rootid; 20078c2ecf20Sopenharmony_ci name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> 20088c2ecf20Sopenharmony_ci VFS_CAP_REVISION_SHIFT; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci return 0; 20118c2ecf20Sopenharmony_ci} 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci/* Copy inode data into an audit_names. */ 20148c2ecf20Sopenharmony_cistatic void audit_copy_inode(struct audit_names *name, 20158c2ecf20Sopenharmony_ci const struct dentry *dentry, 20168c2ecf20Sopenharmony_ci struct inode *inode, unsigned int flags) 20178c2ecf20Sopenharmony_ci{ 20188c2ecf20Sopenharmony_ci name->ino = inode->i_ino; 20198c2ecf20Sopenharmony_ci name->dev = inode->i_sb->s_dev; 20208c2ecf20Sopenharmony_ci name->mode = inode->i_mode; 20218c2ecf20Sopenharmony_ci name->uid = inode->i_uid; 20228c2ecf20Sopenharmony_ci name->gid = inode->i_gid; 20238c2ecf20Sopenharmony_ci name->rdev = inode->i_rdev; 20248c2ecf20Sopenharmony_ci security_inode_getsecid(inode, &name->osid); 20258c2ecf20Sopenharmony_ci if (flags & AUDIT_INODE_NOEVAL) { 20268c2ecf20Sopenharmony_ci name->fcap_ver = -1; 20278c2ecf20Sopenharmony_ci return; 20288c2ecf20Sopenharmony_ci } 20298c2ecf20Sopenharmony_ci audit_copy_fcaps(name, dentry); 20308c2ecf20Sopenharmony_ci} 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci/** 20338c2ecf20Sopenharmony_ci * __audit_inode - store the inode and device from a lookup 20348c2ecf20Sopenharmony_ci * @name: name being audited 20358c2ecf20Sopenharmony_ci * @dentry: dentry being audited 20368c2ecf20Sopenharmony_ci * @flags: attributes for this particular entry 20378c2ecf20Sopenharmony_ci */ 20388c2ecf20Sopenharmony_civoid __audit_inode(struct filename *name, const struct dentry *dentry, 20398c2ecf20Sopenharmony_ci unsigned int flags) 20408c2ecf20Sopenharmony_ci{ 20418c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 20428c2ecf20Sopenharmony_ci struct inode *inode = d_backing_inode(dentry); 20438c2ecf20Sopenharmony_ci struct audit_names *n; 20448c2ecf20Sopenharmony_ci bool parent = flags & AUDIT_INODE_PARENT; 20458c2ecf20Sopenharmony_ci struct audit_entry *e; 20468c2ecf20Sopenharmony_ci struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS]; 20478c2ecf20Sopenharmony_ci int i; 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci if (!context->in_syscall) 20508c2ecf20Sopenharmony_ci return; 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci rcu_read_lock(); 20538c2ecf20Sopenharmony_ci list_for_each_entry_rcu(e, list, list) { 20548c2ecf20Sopenharmony_ci for (i = 0; i < e->rule.field_count; i++) { 20558c2ecf20Sopenharmony_ci struct audit_field *f = &e->rule.fields[i]; 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_ci if (f->type == AUDIT_FSTYPE 20588c2ecf20Sopenharmony_ci && audit_comparator(inode->i_sb->s_magic, 20598c2ecf20Sopenharmony_ci f->op, f->val) 20608c2ecf20Sopenharmony_ci && e->rule.action == AUDIT_NEVER) { 20618c2ecf20Sopenharmony_ci rcu_read_unlock(); 20628c2ecf20Sopenharmony_ci return; 20638c2ecf20Sopenharmony_ci } 20648c2ecf20Sopenharmony_ci } 20658c2ecf20Sopenharmony_ci } 20668c2ecf20Sopenharmony_ci rcu_read_unlock(); 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci if (!name) 20698c2ecf20Sopenharmony_ci goto out_alloc; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci /* 20728c2ecf20Sopenharmony_ci * If we have a pointer to an audit_names entry already, then we can 20738c2ecf20Sopenharmony_ci * just use it directly if the type is correct. 20748c2ecf20Sopenharmony_ci */ 20758c2ecf20Sopenharmony_ci n = name->aname; 20768c2ecf20Sopenharmony_ci if (n) { 20778c2ecf20Sopenharmony_ci if (parent) { 20788c2ecf20Sopenharmony_ci if (n->type == AUDIT_TYPE_PARENT || 20798c2ecf20Sopenharmony_ci n->type == AUDIT_TYPE_UNKNOWN) 20808c2ecf20Sopenharmony_ci goto out; 20818c2ecf20Sopenharmony_ci } else { 20828c2ecf20Sopenharmony_ci if (n->type != AUDIT_TYPE_PARENT) 20838c2ecf20Sopenharmony_ci goto out; 20848c2ecf20Sopenharmony_ci } 20858c2ecf20Sopenharmony_ci } 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci list_for_each_entry_reverse(n, &context->names_list, list) { 20888c2ecf20Sopenharmony_ci if (n->ino) { 20898c2ecf20Sopenharmony_ci /* valid inode number, use that for the comparison */ 20908c2ecf20Sopenharmony_ci if (n->ino != inode->i_ino || 20918c2ecf20Sopenharmony_ci n->dev != inode->i_sb->s_dev) 20928c2ecf20Sopenharmony_ci continue; 20938c2ecf20Sopenharmony_ci } else if (n->name) { 20948c2ecf20Sopenharmony_ci /* inode number has not been set, check the name */ 20958c2ecf20Sopenharmony_ci if (strcmp(n->name->name, name->name)) 20968c2ecf20Sopenharmony_ci continue; 20978c2ecf20Sopenharmony_ci } else 20988c2ecf20Sopenharmony_ci /* no inode and no name (?!) ... this is odd ... */ 20998c2ecf20Sopenharmony_ci continue; 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci /* match the correct record type */ 21028c2ecf20Sopenharmony_ci if (parent) { 21038c2ecf20Sopenharmony_ci if (n->type == AUDIT_TYPE_PARENT || 21048c2ecf20Sopenharmony_ci n->type == AUDIT_TYPE_UNKNOWN) 21058c2ecf20Sopenharmony_ci goto out; 21068c2ecf20Sopenharmony_ci } else { 21078c2ecf20Sopenharmony_ci if (n->type != AUDIT_TYPE_PARENT) 21088c2ecf20Sopenharmony_ci goto out; 21098c2ecf20Sopenharmony_ci } 21108c2ecf20Sopenharmony_ci } 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ciout_alloc: 21138c2ecf20Sopenharmony_ci /* unable to find an entry with both a matching name and type */ 21148c2ecf20Sopenharmony_ci n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); 21158c2ecf20Sopenharmony_ci if (!n) 21168c2ecf20Sopenharmony_ci return; 21178c2ecf20Sopenharmony_ci if (name) { 21188c2ecf20Sopenharmony_ci n->name = name; 21198c2ecf20Sopenharmony_ci name->refcnt++; 21208c2ecf20Sopenharmony_ci } 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ciout: 21238c2ecf20Sopenharmony_ci if (parent) { 21248c2ecf20Sopenharmony_ci n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; 21258c2ecf20Sopenharmony_ci n->type = AUDIT_TYPE_PARENT; 21268c2ecf20Sopenharmony_ci if (flags & AUDIT_INODE_HIDDEN) 21278c2ecf20Sopenharmony_ci n->hidden = true; 21288c2ecf20Sopenharmony_ci } else { 21298c2ecf20Sopenharmony_ci n->name_len = AUDIT_NAME_FULL; 21308c2ecf20Sopenharmony_ci n->type = AUDIT_TYPE_NORMAL; 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci handle_path(dentry); 21338c2ecf20Sopenharmony_ci audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL); 21348c2ecf20Sopenharmony_ci} 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_civoid __audit_file(const struct file *file) 21378c2ecf20Sopenharmony_ci{ 21388c2ecf20Sopenharmony_ci __audit_inode(NULL, file->f_path.dentry, 0); 21398c2ecf20Sopenharmony_ci} 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci/** 21428c2ecf20Sopenharmony_ci * __audit_inode_child - collect inode info for created/removed objects 21438c2ecf20Sopenharmony_ci * @parent: inode of dentry parent 21448c2ecf20Sopenharmony_ci * @dentry: dentry being audited 21458c2ecf20Sopenharmony_ci * @type: AUDIT_TYPE_* value that we're looking for 21468c2ecf20Sopenharmony_ci * 21478c2ecf20Sopenharmony_ci * For syscalls that create or remove filesystem objects, audit_inode 21488c2ecf20Sopenharmony_ci * can only collect information for the filesystem object's parent. 21498c2ecf20Sopenharmony_ci * This call updates the audit context with the child's information. 21508c2ecf20Sopenharmony_ci * Syscalls that create a new filesystem object must be hooked after 21518c2ecf20Sopenharmony_ci * the object is created. Syscalls that remove a filesystem object 21528c2ecf20Sopenharmony_ci * must be hooked prior, in order to capture the target inode during 21538c2ecf20Sopenharmony_ci * unsuccessful attempts. 21548c2ecf20Sopenharmony_ci */ 21558c2ecf20Sopenharmony_civoid __audit_inode_child(struct inode *parent, 21568c2ecf20Sopenharmony_ci const struct dentry *dentry, 21578c2ecf20Sopenharmony_ci const unsigned char type) 21588c2ecf20Sopenharmony_ci{ 21598c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 21608c2ecf20Sopenharmony_ci struct inode *inode = d_backing_inode(dentry); 21618c2ecf20Sopenharmony_ci const struct qstr *dname = &dentry->d_name; 21628c2ecf20Sopenharmony_ci struct audit_names *n, *found_parent = NULL, *found_child = NULL; 21638c2ecf20Sopenharmony_ci struct audit_entry *e; 21648c2ecf20Sopenharmony_ci struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS]; 21658c2ecf20Sopenharmony_ci int i; 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci if (!context->in_syscall) 21688c2ecf20Sopenharmony_ci return; 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci rcu_read_lock(); 21718c2ecf20Sopenharmony_ci list_for_each_entry_rcu(e, list, list) { 21728c2ecf20Sopenharmony_ci for (i = 0; i < e->rule.field_count; i++) { 21738c2ecf20Sopenharmony_ci struct audit_field *f = &e->rule.fields[i]; 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_ci if (f->type == AUDIT_FSTYPE 21768c2ecf20Sopenharmony_ci && audit_comparator(parent->i_sb->s_magic, 21778c2ecf20Sopenharmony_ci f->op, f->val) 21788c2ecf20Sopenharmony_ci && e->rule.action == AUDIT_NEVER) { 21798c2ecf20Sopenharmony_ci rcu_read_unlock(); 21808c2ecf20Sopenharmony_ci return; 21818c2ecf20Sopenharmony_ci } 21828c2ecf20Sopenharmony_ci } 21838c2ecf20Sopenharmony_ci } 21848c2ecf20Sopenharmony_ci rcu_read_unlock(); 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci if (inode) 21878c2ecf20Sopenharmony_ci handle_one(inode); 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci /* look for a parent entry first */ 21908c2ecf20Sopenharmony_ci list_for_each_entry(n, &context->names_list, list) { 21918c2ecf20Sopenharmony_ci if (!n->name || 21928c2ecf20Sopenharmony_ci (n->type != AUDIT_TYPE_PARENT && 21938c2ecf20Sopenharmony_ci n->type != AUDIT_TYPE_UNKNOWN)) 21948c2ecf20Sopenharmony_ci continue; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev && 21978c2ecf20Sopenharmony_ci !audit_compare_dname_path(dname, 21988c2ecf20Sopenharmony_ci n->name->name, n->name_len)) { 21998c2ecf20Sopenharmony_ci if (n->type == AUDIT_TYPE_UNKNOWN) 22008c2ecf20Sopenharmony_ci n->type = AUDIT_TYPE_PARENT; 22018c2ecf20Sopenharmony_ci found_parent = n; 22028c2ecf20Sopenharmony_ci break; 22038c2ecf20Sopenharmony_ci } 22048c2ecf20Sopenharmony_ci } 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci cond_resched(); 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci /* is there a matching child entry? */ 22098c2ecf20Sopenharmony_ci list_for_each_entry(n, &context->names_list, list) { 22108c2ecf20Sopenharmony_ci /* can only match entries that have a name */ 22118c2ecf20Sopenharmony_ci if (!n->name || 22128c2ecf20Sopenharmony_ci (n->type != type && n->type != AUDIT_TYPE_UNKNOWN)) 22138c2ecf20Sopenharmony_ci continue; 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci if (!strcmp(dname->name, n->name->name) || 22168c2ecf20Sopenharmony_ci !audit_compare_dname_path(dname, n->name->name, 22178c2ecf20Sopenharmony_ci found_parent ? 22188c2ecf20Sopenharmony_ci found_parent->name_len : 22198c2ecf20Sopenharmony_ci AUDIT_NAME_FULL)) { 22208c2ecf20Sopenharmony_ci if (n->type == AUDIT_TYPE_UNKNOWN) 22218c2ecf20Sopenharmony_ci n->type = type; 22228c2ecf20Sopenharmony_ci found_child = n; 22238c2ecf20Sopenharmony_ci break; 22248c2ecf20Sopenharmony_ci } 22258c2ecf20Sopenharmony_ci } 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci if (!found_parent) { 22288c2ecf20Sopenharmony_ci /* create a new, "anonymous" parent record */ 22298c2ecf20Sopenharmony_ci n = audit_alloc_name(context, AUDIT_TYPE_PARENT); 22308c2ecf20Sopenharmony_ci if (!n) 22318c2ecf20Sopenharmony_ci return; 22328c2ecf20Sopenharmony_ci audit_copy_inode(n, NULL, parent, 0); 22338c2ecf20Sopenharmony_ci } 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci if (!found_child) { 22368c2ecf20Sopenharmony_ci found_child = audit_alloc_name(context, type); 22378c2ecf20Sopenharmony_ci if (!found_child) 22388c2ecf20Sopenharmony_ci return; 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci /* Re-use the name belonging to the slot for a matching parent 22418c2ecf20Sopenharmony_ci * directory. All names for this context are relinquished in 22428c2ecf20Sopenharmony_ci * audit_free_names() */ 22438c2ecf20Sopenharmony_ci if (found_parent) { 22448c2ecf20Sopenharmony_ci found_child->name = found_parent->name; 22458c2ecf20Sopenharmony_ci found_child->name_len = AUDIT_NAME_FULL; 22468c2ecf20Sopenharmony_ci found_child->name->refcnt++; 22478c2ecf20Sopenharmony_ci } 22488c2ecf20Sopenharmony_ci } 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_ci if (inode) 22518c2ecf20Sopenharmony_ci audit_copy_inode(found_child, dentry, inode, 0); 22528c2ecf20Sopenharmony_ci else 22538c2ecf20Sopenharmony_ci found_child->ino = AUDIT_INO_UNSET; 22548c2ecf20Sopenharmony_ci} 22558c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__audit_inode_child); 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci/** 22588c2ecf20Sopenharmony_ci * auditsc_get_stamp - get local copies of audit_context values 22598c2ecf20Sopenharmony_ci * @ctx: audit_context for the task 22608c2ecf20Sopenharmony_ci * @t: timespec64 to store time recorded in the audit_context 22618c2ecf20Sopenharmony_ci * @serial: serial value that is recorded in the audit_context 22628c2ecf20Sopenharmony_ci * 22638c2ecf20Sopenharmony_ci * Also sets the context as auditable. 22648c2ecf20Sopenharmony_ci */ 22658c2ecf20Sopenharmony_ciint auditsc_get_stamp(struct audit_context *ctx, 22668c2ecf20Sopenharmony_ci struct timespec64 *t, unsigned int *serial) 22678c2ecf20Sopenharmony_ci{ 22688c2ecf20Sopenharmony_ci if (!ctx->in_syscall) 22698c2ecf20Sopenharmony_ci return 0; 22708c2ecf20Sopenharmony_ci if (!ctx->serial) 22718c2ecf20Sopenharmony_ci ctx->serial = audit_serial(); 22728c2ecf20Sopenharmony_ci t->tv_sec = ctx->ctime.tv_sec; 22738c2ecf20Sopenharmony_ci t->tv_nsec = ctx->ctime.tv_nsec; 22748c2ecf20Sopenharmony_ci *serial = ctx->serial; 22758c2ecf20Sopenharmony_ci if (!ctx->prio) { 22768c2ecf20Sopenharmony_ci ctx->prio = 1; 22778c2ecf20Sopenharmony_ci ctx->current_state = AUDIT_RECORD_CONTEXT; 22788c2ecf20Sopenharmony_ci } 22798c2ecf20Sopenharmony_ci return 1; 22808c2ecf20Sopenharmony_ci} 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci/** 22838c2ecf20Sopenharmony_ci * __audit_mq_open - record audit data for a POSIX MQ open 22848c2ecf20Sopenharmony_ci * @oflag: open flag 22858c2ecf20Sopenharmony_ci * @mode: mode bits 22868c2ecf20Sopenharmony_ci * @attr: queue attributes 22878c2ecf20Sopenharmony_ci * 22888c2ecf20Sopenharmony_ci */ 22898c2ecf20Sopenharmony_civoid __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr) 22908c2ecf20Sopenharmony_ci{ 22918c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci if (attr) 22948c2ecf20Sopenharmony_ci memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr)); 22958c2ecf20Sopenharmony_ci else 22968c2ecf20Sopenharmony_ci memset(&context->mq_open.attr, 0, sizeof(struct mq_attr)); 22978c2ecf20Sopenharmony_ci 22988c2ecf20Sopenharmony_ci context->mq_open.oflag = oflag; 22998c2ecf20Sopenharmony_ci context->mq_open.mode = mode; 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci context->type = AUDIT_MQ_OPEN; 23028c2ecf20Sopenharmony_ci} 23038c2ecf20Sopenharmony_ci 23048c2ecf20Sopenharmony_ci/** 23058c2ecf20Sopenharmony_ci * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive 23068c2ecf20Sopenharmony_ci * @mqdes: MQ descriptor 23078c2ecf20Sopenharmony_ci * @msg_len: Message length 23088c2ecf20Sopenharmony_ci * @msg_prio: Message priority 23098c2ecf20Sopenharmony_ci * @abs_timeout: Message timeout in absolute time 23108c2ecf20Sopenharmony_ci * 23118c2ecf20Sopenharmony_ci */ 23128c2ecf20Sopenharmony_civoid __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, 23138c2ecf20Sopenharmony_ci const struct timespec64 *abs_timeout) 23148c2ecf20Sopenharmony_ci{ 23158c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 23168c2ecf20Sopenharmony_ci struct timespec64 *p = &context->mq_sendrecv.abs_timeout; 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_ci if (abs_timeout) 23198c2ecf20Sopenharmony_ci memcpy(p, abs_timeout, sizeof(*p)); 23208c2ecf20Sopenharmony_ci else 23218c2ecf20Sopenharmony_ci memset(p, 0, sizeof(*p)); 23228c2ecf20Sopenharmony_ci 23238c2ecf20Sopenharmony_ci context->mq_sendrecv.mqdes = mqdes; 23248c2ecf20Sopenharmony_ci context->mq_sendrecv.msg_len = msg_len; 23258c2ecf20Sopenharmony_ci context->mq_sendrecv.msg_prio = msg_prio; 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci context->type = AUDIT_MQ_SENDRECV; 23288c2ecf20Sopenharmony_ci} 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci/** 23318c2ecf20Sopenharmony_ci * __audit_mq_notify - record audit data for a POSIX MQ notify 23328c2ecf20Sopenharmony_ci * @mqdes: MQ descriptor 23338c2ecf20Sopenharmony_ci * @notification: Notification event 23348c2ecf20Sopenharmony_ci * 23358c2ecf20Sopenharmony_ci */ 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_civoid __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification) 23388c2ecf20Sopenharmony_ci{ 23398c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 23408c2ecf20Sopenharmony_ci 23418c2ecf20Sopenharmony_ci if (notification) 23428c2ecf20Sopenharmony_ci context->mq_notify.sigev_signo = notification->sigev_signo; 23438c2ecf20Sopenharmony_ci else 23448c2ecf20Sopenharmony_ci context->mq_notify.sigev_signo = 0; 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ci context->mq_notify.mqdes = mqdes; 23478c2ecf20Sopenharmony_ci context->type = AUDIT_MQ_NOTIFY; 23488c2ecf20Sopenharmony_ci} 23498c2ecf20Sopenharmony_ci 23508c2ecf20Sopenharmony_ci/** 23518c2ecf20Sopenharmony_ci * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute 23528c2ecf20Sopenharmony_ci * @mqdes: MQ descriptor 23538c2ecf20Sopenharmony_ci * @mqstat: MQ flags 23548c2ecf20Sopenharmony_ci * 23558c2ecf20Sopenharmony_ci */ 23568c2ecf20Sopenharmony_civoid __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) 23578c2ecf20Sopenharmony_ci{ 23588c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 23598c2ecf20Sopenharmony_ci context->mq_getsetattr.mqdes = mqdes; 23608c2ecf20Sopenharmony_ci context->mq_getsetattr.mqstat = *mqstat; 23618c2ecf20Sopenharmony_ci context->type = AUDIT_MQ_GETSETATTR; 23628c2ecf20Sopenharmony_ci} 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci/** 23658c2ecf20Sopenharmony_ci * __audit_ipc_obj - record audit data for ipc object 23668c2ecf20Sopenharmony_ci * @ipcp: ipc permissions 23678c2ecf20Sopenharmony_ci * 23688c2ecf20Sopenharmony_ci */ 23698c2ecf20Sopenharmony_civoid __audit_ipc_obj(struct kern_ipc_perm *ipcp) 23708c2ecf20Sopenharmony_ci{ 23718c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 23728c2ecf20Sopenharmony_ci context->ipc.uid = ipcp->uid; 23738c2ecf20Sopenharmony_ci context->ipc.gid = ipcp->gid; 23748c2ecf20Sopenharmony_ci context->ipc.mode = ipcp->mode; 23758c2ecf20Sopenharmony_ci context->ipc.has_perm = 0; 23768c2ecf20Sopenharmony_ci security_ipc_getsecid(ipcp, &context->ipc.osid); 23778c2ecf20Sopenharmony_ci context->type = AUDIT_IPC; 23788c2ecf20Sopenharmony_ci} 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_ci/** 23818c2ecf20Sopenharmony_ci * __audit_ipc_set_perm - record audit data for new ipc permissions 23828c2ecf20Sopenharmony_ci * @qbytes: msgq bytes 23838c2ecf20Sopenharmony_ci * @uid: msgq user id 23848c2ecf20Sopenharmony_ci * @gid: msgq group id 23858c2ecf20Sopenharmony_ci * @mode: msgq mode (permissions) 23868c2ecf20Sopenharmony_ci * 23878c2ecf20Sopenharmony_ci * Called only after audit_ipc_obj(). 23888c2ecf20Sopenharmony_ci */ 23898c2ecf20Sopenharmony_civoid __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode) 23908c2ecf20Sopenharmony_ci{ 23918c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_ci context->ipc.qbytes = qbytes; 23948c2ecf20Sopenharmony_ci context->ipc.perm_uid = uid; 23958c2ecf20Sopenharmony_ci context->ipc.perm_gid = gid; 23968c2ecf20Sopenharmony_ci context->ipc.perm_mode = mode; 23978c2ecf20Sopenharmony_ci context->ipc.has_perm = 1; 23988c2ecf20Sopenharmony_ci} 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_civoid __audit_bprm(struct linux_binprm *bprm) 24018c2ecf20Sopenharmony_ci{ 24028c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 24038c2ecf20Sopenharmony_ci 24048c2ecf20Sopenharmony_ci context->type = AUDIT_EXECVE; 24058c2ecf20Sopenharmony_ci context->execve.argc = bprm->argc; 24068c2ecf20Sopenharmony_ci} 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci/** 24108c2ecf20Sopenharmony_ci * __audit_socketcall - record audit data for sys_socketcall 24118c2ecf20Sopenharmony_ci * @nargs: number of args, which should not be more than AUDITSC_ARGS. 24128c2ecf20Sopenharmony_ci * @args: args array 24138c2ecf20Sopenharmony_ci * 24148c2ecf20Sopenharmony_ci */ 24158c2ecf20Sopenharmony_ciint __audit_socketcall(int nargs, unsigned long *args) 24168c2ecf20Sopenharmony_ci{ 24178c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci if (nargs <= 0 || nargs > AUDITSC_ARGS || !args) 24208c2ecf20Sopenharmony_ci return -EINVAL; 24218c2ecf20Sopenharmony_ci context->type = AUDIT_SOCKETCALL; 24228c2ecf20Sopenharmony_ci context->socketcall.nargs = nargs; 24238c2ecf20Sopenharmony_ci memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long)); 24248c2ecf20Sopenharmony_ci return 0; 24258c2ecf20Sopenharmony_ci} 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci/** 24288c2ecf20Sopenharmony_ci * __audit_fd_pair - record audit data for pipe and socketpair 24298c2ecf20Sopenharmony_ci * @fd1: the first file descriptor 24308c2ecf20Sopenharmony_ci * @fd2: the second file descriptor 24318c2ecf20Sopenharmony_ci * 24328c2ecf20Sopenharmony_ci */ 24338c2ecf20Sopenharmony_civoid __audit_fd_pair(int fd1, int fd2) 24348c2ecf20Sopenharmony_ci{ 24358c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 24368c2ecf20Sopenharmony_ci context->fds[0] = fd1; 24378c2ecf20Sopenharmony_ci context->fds[1] = fd2; 24388c2ecf20Sopenharmony_ci} 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci/** 24418c2ecf20Sopenharmony_ci * __audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto 24428c2ecf20Sopenharmony_ci * @len: data length in user space 24438c2ecf20Sopenharmony_ci * @a: data address in kernel space 24448c2ecf20Sopenharmony_ci * 24458c2ecf20Sopenharmony_ci * Returns 0 for success or NULL context or < 0 on error. 24468c2ecf20Sopenharmony_ci */ 24478c2ecf20Sopenharmony_ciint __audit_sockaddr(int len, void *a) 24488c2ecf20Sopenharmony_ci{ 24498c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 24508c2ecf20Sopenharmony_ci 24518c2ecf20Sopenharmony_ci if (!context->sockaddr) { 24528c2ecf20Sopenharmony_ci void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL); 24538c2ecf20Sopenharmony_ci if (!p) 24548c2ecf20Sopenharmony_ci return -ENOMEM; 24558c2ecf20Sopenharmony_ci context->sockaddr = p; 24568c2ecf20Sopenharmony_ci } 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci context->sockaddr_len = len; 24598c2ecf20Sopenharmony_ci memcpy(context->sockaddr, a, len); 24608c2ecf20Sopenharmony_ci return 0; 24618c2ecf20Sopenharmony_ci} 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_civoid __audit_ptrace(struct task_struct *t) 24648c2ecf20Sopenharmony_ci{ 24658c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci context->target_pid = task_tgid_nr(t); 24688c2ecf20Sopenharmony_ci context->target_auid = audit_get_loginuid(t); 24698c2ecf20Sopenharmony_ci context->target_uid = task_uid(t); 24708c2ecf20Sopenharmony_ci context->target_sessionid = audit_get_sessionid(t); 24718c2ecf20Sopenharmony_ci security_task_getsecid(t, &context->target_sid); 24728c2ecf20Sopenharmony_ci memcpy(context->target_comm, t->comm, TASK_COMM_LEN); 24738c2ecf20Sopenharmony_ci} 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_ci/** 24768c2ecf20Sopenharmony_ci * audit_signal_info_syscall - record signal info for syscalls 24778c2ecf20Sopenharmony_ci * @t: task being signaled 24788c2ecf20Sopenharmony_ci * 24798c2ecf20Sopenharmony_ci * If the audit subsystem is being terminated, record the task (pid) 24808c2ecf20Sopenharmony_ci * and uid that is doing that. 24818c2ecf20Sopenharmony_ci */ 24828c2ecf20Sopenharmony_ciint audit_signal_info_syscall(struct task_struct *t) 24838c2ecf20Sopenharmony_ci{ 24848c2ecf20Sopenharmony_ci struct audit_aux_data_pids *axp; 24858c2ecf20Sopenharmony_ci struct audit_context *ctx = audit_context(); 24868c2ecf20Sopenharmony_ci kuid_t t_uid = task_uid(t); 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci if (!audit_signals || audit_dummy_context()) 24898c2ecf20Sopenharmony_ci return 0; 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ci /* optimize the common case by putting first signal recipient directly 24928c2ecf20Sopenharmony_ci * in audit_context */ 24938c2ecf20Sopenharmony_ci if (!ctx->target_pid) { 24948c2ecf20Sopenharmony_ci ctx->target_pid = task_tgid_nr(t); 24958c2ecf20Sopenharmony_ci ctx->target_auid = audit_get_loginuid(t); 24968c2ecf20Sopenharmony_ci ctx->target_uid = t_uid; 24978c2ecf20Sopenharmony_ci ctx->target_sessionid = audit_get_sessionid(t); 24988c2ecf20Sopenharmony_ci security_task_getsecid(t, &ctx->target_sid); 24998c2ecf20Sopenharmony_ci memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN); 25008c2ecf20Sopenharmony_ci return 0; 25018c2ecf20Sopenharmony_ci } 25028c2ecf20Sopenharmony_ci 25038c2ecf20Sopenharmony_ci axp = (void *)ctx->aux_pids; 25048c2ecf20Sopenharmony_ci if (!axp || axp->pid_count == AUDIT_AUX_PIDS) { 25058c2ecf20Sopenharmony_ci axp = kzalloc(sizeof(*axp), GFP_ATOMIC); 25068c2ecf20Sopenharmony_ci if (!axp) 25078c2ecf20Sopenharmony_ci return -ENOMEM; 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci axp->d.type = AUDIT_OBJ_PID; 25108c2ecf20Sopenharmony_ci axp->d.next = ctx->aux_pids; 25118c2ecf20Sopenharmony_ci ctx->aux_pids = (void *)axp; 25128c2ecf20Sopenharmony_ci } 25138c2ecf20Sopenharmony_ci BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); 25148c2ecf20Sopenharmony_ci 25158c2ecf20Sopenharmony_ci axp->target_pid[axp->pid_count] = task_tgid_nr(t); 25168c2ecf20Sopenharmony_ci axp->target_auid[axp->pid_count] = audit_get_loginuid(t); 25178c2ecf20Sopenharmony_ci axp->target_uid[axp->pid_count] = t_uid; 25188c2ecf20Sopenharmony_ci axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); 25198c2ecf20Sopenharmony_ci security_task_getsecid(t, &axp->target_sid[axp->pid_count]); 25208c2ecf20Sopenharmony_ci memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN); 25218c2ecf20Sopenharmony_ci axp->pid_count++; 25228c2ecf20Sopenharmony_ci 25238c2ecf20Sopenharmony_ci return 0; 25248c2ecf20Sopenharmony_ci} 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci/** 25278c2ecf20Sopenharmony_ci * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps 25288c2ecf20Sopenharmony_ci * @bprm: pointer to the bprm being processed 25298c2ecf20Sopenharmony_ci * @new: the proposed new credentials 25308c2ecf20Sopenharmony_ci * @old: the old credentials 25318c2ecf20Sopenharmony_ci * 25328c2ecf20Sopenharmony_ci * Simply check if the proc already has the caps given by the file and if not 25338c2ecf20Sopenharmony_ci * store the priv escalation info for later auditing at the end of the syscall 25348c2ecf20Sopenharmony_ci * 25358c2ecf20Sopenharmony_ci * -Eric 25368c2ecf20Sopenharmony_ci */ 25378c2ecf20Sopenharmony_ciint __audit_log_bprm_fcaps(struct linux_binprm *bprm, 25388c2ecf20Sopenharmony_ci const struct cred *new, const struct cred *old) 25398c2ecf20Sopenharmony_ci{ 25408c2ecf20Sopenharmony_ci struct audit_aux_data_bprm_fcaps *ax; 25418c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 25428c2ecf20Sopenharmony_ci struct cpu_vfs_cap_data vcaps; 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci ax = kmalloc(sizeof(*ax), GFP_KERNEL); 25458c2ecf20Sopenharmony_ci if (!ax) 25468c2ecf20Sopenharmony_ci return -ENOMEM; 25478c2ecf20Sopenharmony_ci 25488c2ecf20Sopenharmony_ci ax->d.type = AUDIT_BPRM_FCAPS; 25498c2ecf20Sopenharmony_ci ax->d.next = context->aux; 25508c2ecf20Sopenharmony_ci context->aux = (void *)ax; 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps); 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci ax->fcap.permitted = vcaps.permitted; 25558c2ecf20Sopenharmony_ci ax->fcap.inheritable = vcaps.inheritable; 25568c2ecf20Sopenharmony_ci ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); 25578c2ecf20Sopenharmony_ci ax->fcap.rootid = vcaps.rootid; 25588c2ecf20Sopenharmony_ci ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; 25598c2ecf20Sopenharmony_ci 25608c2ecf20Sopenharmony_ci ax->old_pcap.permitted = old->cap_permitted; 25618c2ecf20Sopenharmony_ci ax->old_pcap.inheritable = old->cap_inheritable; 25628c2ecf20Sopenharmony_ci ax->old_pcap.effective = old->cap_effective; 25638c2ecf20Sopenharmony_ci ax->old_pcap.ambient = old->cap_ambient; 25648c2ecf20Sopenharmony_ci 25658c2ecf20Sopenharmony_ci ax->new_pcap.permitted = new->cap_permitted; 25668c2ecf20Sopenharmony_ci ax->new_pcap.inheritable = new->cap_inheritable; 25678c2ecf20Sopenharmony_ci ax->new_pcap.effective = new->cap_effective; 25688c2ecf20Sopenharmony_ci ax->new_pcap.ambient = new->cap_ambient; 25698c2ecf20Sopenharmony_ci return 0; 25708c2ecf20Sopenharmony_ci} 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ci/** 25738c2ecf20Sopenharmony_ci * __audit_log_capset - store information about the arguments to the capset syscall 25748c2ecf20Sopenharmony_ci * @new: the new credentials 25758c2ecf20Sopenharmony_ci * @old: the old (current) credentials 25768c2ecf20Sopenharmony_ci * 25778c2ecf20Sopenharmony_ci * Record the arguments userspace sent to sys_capset for later printing by the 25788c2ecf20Sopenharmony_ci * audit system if applicable 25798c2ecf20Sopenharmony_ci */ 25808c2ecf20Sopenharmony_civoid __audit_log_capset(const struct cred *new, const struct cred *old) 25818c2ecf20Sopenharmony_ci{ 25828c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 25838c2ecf20Sopenharmony_ci context->capset.pid = task_tgid_nr(current); 25848c2ecf20Sopenharmony_ci context->capset.cap.effective = new->cap_effective; 25858c2ecf20Sopenharmony_ci context->capset.cap.inheritable = new->cap_effective; 25868c2ecf20Sopenharmony_ci context->capset.cap.permitted = new->cap_permitted; 25878c2ecf20Sopenharmony_ci context->capset.cap.ambient = new->cap_ambient; 25888c2ecf20Sopenharmony_ci context->type = AUDIT_CAPSET; 25898c2ecf20Sopenharmony_ci} 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_civoid __audit_mmap_fd(int fd, int flags) 25928c2ecf20Sopenharmony_ci{ 25938c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 25948c2ecf20Sopenharmony_ci context->mmap.fd = fd; 25958c2ecf20Sopenharmony_ci context->mmap.flags = flags; 25968c2ecf20Sopenharmony_ci context->type = AUDIT_MMAP; 25978c2ecf20Sopenharmony_ci} 25988c2ecf20Sopenharmony_ci 25998c2ecf20Sopenharmony_civoid __audit_log_kern_module(char *name) 26008c2ecf20Sopenharmony_ci{ 26018c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_ci context->module.name = kstrdup(name, GFP_KERNEL); 26048c2ecf20Sopenharmony_ci if (!context->module.name) 26058c2ecf20Sopenharmony_ci audit_log_lost("out of memory in __audit_log_kern_module"); 26068c2ecf20Sopenharmony_ci context->type = AUDIT_KERN_MODULE; 26078c2ecf20Sopenharmony_ci} 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_civoid __audit_fanotify(unsigned int response) 26108c2ecf20Sopenharmony_ci{ 26118c2ecf20Sopenharmony_ci audit_log(audit_context(), GFP_KERNEL, 26128c2ecf20Sopenharmony_ci AUDIT_FANOTIFY, "resp=%u", response); 26138c2ecf20Sopenharmony_ci} 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_civoid __audit_tk_injoffset(struct timespec64 offset) 26168c2ecf20Sopenharmony_ci{ 26178c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 26188c2ecf20Sopenharmony_ci 26198c2ecf20Sopenharmony_ci /* only set type if not already set by NTP */ 26208c2ecf20Sopenharmony_ci if (!context->type) 26218c2ecf20Sopenharmony_ci context->type = AUDIT_TIME_INJOFFSET; 26228c2ecf20Sopenharmony_ci memcpy(&context->time.tk_injoffset, &offset, sizeof(offset)); 26238c2ecf20Sopenharmony_ci} 26248c2ecf20Sopenharmony_ci 26258c2ecf20Sopenharmony_civoid __audit_ntp_log(const struct audit_ntp_data *ad) 26268c2ecf20Sopenharmony_ci{ 26278c2ecf20Sopenharmony_ci struct audit_context *context = audit_context(); 26288c2ecf20Sopenharmony_ci int type; 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ci for (type = 0; type < AUDIT_NTP_NVALS; type++) 26318c2ecf20Sopenharmony_ci if (ad->vals[type].newval != ad->vals[type].oldval) { 26328c2ecf20Sopenharmony_ci /* unconditionally set type, overwriting TK */ 26338c2ecf20Sopenharmony_ci context->type = AUDIT_TIME_ADJNTPVAL; 26348c2ecf20Sopenharmony_ci memcpy(&context->time.ntp_data, ad, sizeof(*ad)); 26358c2ecf20Sopenharmony_ci break; 26368c2ecf20Sopenharmony_ci } 26378c2ecf20Sopenharmony_ci} 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_civoid __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries, 26408c2ecf20Sopenharmony_ci enum audit_nfcfgop op, gfp_t gfp) 26418c2ecf20Sopenharmony_ci{ 26428c2ecf20Sopenharmony_ci struct audit_buffer *ab; 26438c2ecf20Sopenharmony_ci char comm[sizeof(current->comm)]; 26448c2ecf20Sopenharmony_ci 26458c2ecf20Sopenharmony_ci ab = audit_log_start(audit_context(), gfp, AUDIT_NETFILTER_CFG); 26468c2ecf20Sopenharmony_ci if (!ab) 26478c2ecf20Sopenharmony_ci return; 26488c2ecf20Sopenharmony_ci audit_log_format(ab, "table=%s family=%u entries=%u op=%s", 26498c2ecf20Sopenharmony_ci name, af, nentries, audit_nfcfgs[op].s); 26508c2ecf20Sopenharmony_ci 26518c2ecf20Sopenharmony_ci audit_log_format(ab, " pid=%u", task_pid_nr(current)); 26528c2ecf20Sopenharmony_ci audit_log_task_context(ab); /* subj= */ 26538c2ecf20Sopenharmony_ci audit_log_format(ab, " comm="); 26548c2ecf20Sopenharmony_ci audit_log_untrustedstring(ab, get_task_comm(comm, current)); 26558c2ecf20Sopenharmony_ci audit_log_end(ab); 26568c2ecf20Sopenharmony_ci} 26578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__audit_log_nfcfg); 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_cistatic void audit_log_task(struct audit_buffer *ab) 26608c2ecf20Sopenharmony_ci{ 26618c2ecf20Sopenharmony_ci kuid_t auid, uid; 26628c2ecf20Sopenharmony_ci kgid_t gid; 26638c2ecf20Sopenharmony_ci unsigned int sessionid; 26648c2ecf20Sopenharmony_ci char comm[sizeof(current->comm)]; 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci auid = audit_get_loginuid(current); 26678c2ecf20Sopenharmony_ci sessionid = audit_get_sessionid(current); 26688c2ecf20Sopenharmony_ci current_uid_gid(&uid, &gid); 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_ci audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u", 26718c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, auid), 26728c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, uid), 26738c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, gid), 26748c2ecf20Sopenharmony_ci sessionid); 26758c2ecf20Sopenharmony_ci audit_log_task_context(ab); 26768c2ecf20Sopenharmony_ci audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current)); 26778c2ecf20Sopenharmony_ci audit_log_untrustedstring(ab, get_task_comm(comm, current)); 26788c2ecf20Sopenharmony_ci audit_log_d_path_exe(ab, current->mm); 26798c2ecf20Sopenharmony_ci} 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ci/** 26828c2ecf20Sopenharmony_ci * audit_core_dumps - record information about processes that end abnormally 26838c2ecf20Sopenharmony_ci * @signr: signal value 26848c2ecf20Sopenharmony_ci * 26858c2ecf20Sopenharmony_ci * If a process ends with a core dump, something fishy is going on and we 26868c2ecf20Sopenharmony_ci * should record the event for investigation. 26878c2ecf20Sopenharmony_ci */ 26888c2ecf20Sopenharmony_civoid audit_core_dumps(long signr) 26898c2ecf20Sopenharmony_ci{ 26908c2ecf20Sopenharmony_ci struct audit_buffer *ab; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci if (!audit_enabled) 26938c2ecf20Sopenharmony_ci return; 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci if (signr == SIGQUIT) /* don't care for those */ 26968c2ecf20Sopenharmony_ci return; 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_ANOM_ABEND); 26998c2ecf20Sopenharmony_ci if (unlikely(!ab)) 27008c2ecf20Sopenharmony_ci return; 27018c2ecf20Sopenharmony_ci audit_log_task(ab); 27028c2ecf20Sopenharmony_ci audit_log_format(ab, " sig=%ld res=1", signr); 27038c2ecf20Sopenharmony_ci audit_log_end(ab); 27048c2ecf20Sopenharmony_ci} 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci/** 27078c2ecf20Sopenharmony_ci * audit_seccomp - record information about a seccomp action 27088c2ecf20Sopenharmony_ci * @syscall: syscall number 27098c2ecf20Sopenharmony_ci * @signr: signal value 27108c2ecf20Sopenharmony_ci * @code: the seccomp action 27118c2ecf20Sopenharmony_ci * 27128c2ecf20Sopenharmony_ci * Record the information associated with a seccomp action. Event filtering for 27138c2ecf20Sopenharmony_ci * seccomp actions that are not to be logged is done in seccomp_log(). 27148c2ecf20Sopenharmony_ci * Therefore, this function forces auditing independent of the audit_enabled 27158c2ecf20Sopenharmony_ci * and dummy context state because seccomp actions should be logged even when 27168c2ecf20Sopenharmony_ci * audit is not in use. 27178c2ecf20Sopenharmony_ci */ 27188c2ecf20Sopenharmony_civoid audit_seccomp(unsigned long syscall, long signr, int code) 27198c2ecf20Sopenharmony_ci{ 27208c2ecf20Sopenharmony_ci struct audit_buffer *ab; 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ci ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_SECCOMP); 27238c2ecf20Sopenharmony_ci if (unlikely(!ab)) 27248c2ecf20Sopenharmony_ci return; 27258c2ecf20Sopenharmony_ci audit_log_task(ab); 27268c2ecf20Sopenharmony_ci audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x", 27278c2ecf20Sopenharmony_ci signr, syscall_get_arch(current), syscall, 27288c2ecf20Sopenharmony_ci in_compat_syscall(), KSTK_EIP(current), code); 27298c2ecf20Sopenharmony_ci audit_log_end(ab); 27308c2ecf20Sopenharmony_ci} 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_civoid audit_seccomp_actions_logged(const char *names, const char *old_names, 27338c2ecf20Sopenharmony_ci int res) 27348c2ecf20Sopenharmony_ci{ 27358c2ecf20Sopenharmony_ci struct audit_buffer *ab; 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_ci if (!audit_enabled) 27388c2ecf20Sopenharmony_ci return; 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci ab = audit_log_start(audit_context(), GFP_KERNEL, 27418c2ecf20Sopenharmony_ci AUDIT_CONFIG_CHANGE); 27428c2ecf20Sopenharmony_ci if (unlikely(!ab)) 27438c2ecf20Sopenharmony_ci return; 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_ci audit_log_format(ab, 27468c2ecf20Sopenharmony_ci "op=seccomp-logging actions=%s old-actions=%s res=%d", 27478c2ecf20Sopenharmony_ci names, old_names, res); 27488c2ecf20Sopenharmony_ci audit_log_end(ab); 27498c2ecf20Sopenharmony_ci} 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_cistruct list_head *audit_killed_trees(void) 27528c2ecf20Sopenharmony_ci{ 27538c2ecf20Sopenharmony_ci struct audit_context *ctx = audit_context(); 27548c2ecf20Sopenharmony_ci if (likely(!ctx || !ctx->in_syscall)) 27558c2ecf20Sopenharmony_ci return NULL; 27568c2ecf20Sopenharmony_ci return &ctx->killed_trees; 27578c2ecf20Sopenharmony_ci} 2758