185c8721fS /* auditsc.c -- System-call auditing support 21da177e4SLinus Torvalds * Handles all system-call specific auditing features. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 573241cccSAmy Griffis * Copyright 2005 Hewlett-Packard Development Company, L.P. 620ca73bcSGeorge C. Wilson * Copyright (C) 2005, 2006 IBM Corporation 71da177e4SLinus Torvalds * All Rights Reserved. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 101da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 111da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 121da177e4SLinus Torvalds * (at your option) any later version. 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 151da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 161da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 171da177e4SLinus Torvalds * GNU General Public License for more details. 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 201da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 211da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * Written by Rickard E. (Rik) Faith <faith@redhat.com> 241da177e4SLinus Torvalds * 251da177e4SLinus Torvalds * Many of the ideas implemented here are from Stephen C. Tweedie, 261da177e4SLinus Torvalds * especially the idea of avoiding a copy by using getname. 271da177e4SLinus Torvalds * 281da177e4SLinus Torvalds * The method for actual interception of syscall entry and exit (not in 291da177e4SLinus Torvalds * this file -- see entry.S) is based on a GPL'd patch written by 301da177e4SLinus Torvalds * okir@suse.de and Copyright 2003 SuSE Linux AG. 311da177e4SLinus Torvalds * 3220ca73bcSGeorge C. Wilson * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>, 3320ca73bcSGeorge C. Wilson * 2006. 3420ca73bcSGeorge C. Wilson * 35b63862f4SDustin Kirkland * The support of additional filter rules compares (>, <, >=, <=) was 36b63862f4SDustin Kirkland * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005. 37b63862f4SDustin Kirkland * 3873241cccSAmy Griffis * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional 3973241cccSAmy Griffis * filesystem information. 408c8570fbSDustin Kirkland * 418c8570fbSDustin Kirkland * Subject and object context labeling support added by <danjones@us.ibm.com> 428c8570fbSDustin Kirkland * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. 431da177e4SLinus Torvalds */ 441da177e4SLinus Torvalds 45f952d10fSRichard Guy Briggs #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 46f952d10fSRichard Guy Briggs 471da177e4SLinus Torvalds #include <linux/init.h> 481da177e4SLinus Torvalds #include <asm/types.h> 4960063497SArun Sharma #include <linux/atomic.h> 5073241cccSAmy Griffis #include <linux/fs.h> 5173241cccSAmy Griffis #include <linux/namei.h> 521da177e4SLinus Torvalds #include <linux/mm.h> 539984de1aSPaul Gortmaker #include <linux/export.h> 545a0e3ad6STejun Heo #include <linux/slab.h> 5501116105SStephen Smalley #include <linux/mount.h> 563ec3b2fbSDavid Woodhouse #include <linux/socket.h> 5720ca73bcSGeorge C. Wilson #include <linux/mqueue.h> 581da177e4SLinus Torvalds #include <linux/audit.h> 591da177e4SLinus Torvalds #include <linux/personality.h> 601da177e4SLinus Torvalds #include <linux/time.h> 615bb289b5SDavid Woodhouse #include <linux/netlink.h> 62f5561964SDavid Woodhouse #include <linux/compiler.h> 631da177e4SLinus Torvalds #include <asm/unistd.h> 648c8570fbSDustin Kirkland #include <linux/security.h> 65fe7752baSDavid Woodhouse #include <linux/list.h> 66a6c043a8SSteve Grubb #include <linux/tty.h> 67473ae30bSAl Viro #include <linux/binfmts.h> 68a1f8e7f7SAl Viro #include <linux/highmem.h> 69f46038ffSAl Viro #include <linux/syscalls.h> 7084db564aSRichard Guy Briggs #include <asm/syscall.h> 71851f7ff5SEric Paris #include <linux/capability.h> 725ad4e53bSAl Viro #include <linux/fs_struct.h> 733dc1c1b2SKees Cook #include <linux/compat.h> 743f1c8250SWilliam Roberts #include <linux/ctype.h> 75fcf22d82SPaul Moore #include <linux/string.h> 76fcf22d82SPaul Moore #include <uapi/linux/limits.h> 771da177e4SLinus Torvalds 78fe7752baSDavid Woodhouse #include "audit.h" 79fe7752baSDavid Woodhouse 80d7e7528bSEric Paris /* flags stating the success for a syscall */ 81d7e7528bSEric Paris #define AUDITSC_INVALID 0 82d7e7528bSEric Paris #define AUDITSC_SUCCESS 1 83d7e7528bSEric Paris #define AUDITSC_FAILURE 2 84d7e7528bSEric Paris 85de6bbd1dSEric Paris /* no execve audit message should be longer than this (userspace limits) */ 86de6bbd1dSEric Paris #define MAX_EXECVE_AUDIT_LEN 7500 87de6bbd1dSEric Paris 883f1c8250SWilliam Roberts /* max length to print of cmdline/proctitle value during audit */ 893f1c8250SWilliam Roberts #define MAX_PROCTITLE_AUDIT_LEN 128 903f1c8250SWilliam Roberts 91471a5c7cSAl Viro /* number of audit rules */ 92471a5c7cSAl Viro int audit_n_rules; 93471a5c7cSAl Viro 94e54dc243SAmy Griffis /* determines whether we collect data for signals sent */ 95e54dc243SAmy Griffis int audit_signals; 96e54dc243SAmy Griffis 971da177e4SLinus Torvalds struct audit_aux_data { 981da177e4SLinus Torvalds struct audit_aux_data *next; 991da177e4SLinus Torvalds int type; 1001da177e4SLinus Torvalds }; 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds #define AUDIT_AUX_IPCPERM 0 1031da177e4SLinus Torvalds 104e54dc243SAmy Griffis /* Number of target pids per aux struct. */ 105e54dc243SAmy Griffis #define AUDIT_AUX_PIDS 16 106e54dc243SAmy Griffis 107e54dc243SAmy Griffis struct audit_aux_data_pids { 108e54dc243SAmy Griffis struct audit_aux_data d; 109e54dc243SAmy Griffis pid_t target_pid[AUDIT_AUX_PIDS]; 110e1760bd5SEric W. Biederman kuid_t target_auid[AUDIT_AUX_PIDS]; 111cca080d9SEric W. Biederman kuid_t target_uid[AUDIT_AUX_PIDS]; 1124746ec5bSEric Paris unsigned int target_sessionid[AUDIT_AUX_PIDS]; 113e54dc243SAmy Griffis u32 target_sid[AUDIT_AUX_PIDS]; 114c2a7780eSEric Paris char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN]; 115e54dc243SAmy Griffis int pid_count; 116e54dc243SAmy Griffis }; 117e54dc243SAmy Griffis 1183fc689e9SEric Paris struct audit_aux_data_bprm_fcaps { 1193fc689e9SEric Paris struct audit_aux_data d; 1203fc689e9SEric Paris struct audit_cap_data fcap; 1213fc689e9SEric Paris unsigned int fcap_ver; 1223fc689e9SEric Paris struct audit_cap_data old_pcap; 1233fc689e9SEric Paris struct audit_cap_data new_pcap; 1243fc689e9SEric Paris }; 1253fc689e9SEric Paris 12674c3cbe3SAl Viro struct audit_tree_refs { 12774c3cbe3SAl Viro struct audit_tree_refs *next; 12874c3cbe3SAl Viro struct audit_chunk *c[31]; 12974c3cbe3SAl Viro }; 13074c3cbe3SAl Viro 13155669bfaSAl Viro static int audit_match_perm(struct audit_context *ctx, int mask) 13255669bfaSAl Viro { 133c4bacefbSCordelia unsigned n; 1341a61c88dSzhangxiliang if (unlikely(!ctx)) 1351a61c88dSzhangxiliang return 0; 136c4bacefbSCordelia n = ctx->major; 137dbda4c0bSAlan Cox 13855669bfaSAl Viro switch (audit_classify_syscall(ctx->arch, n)) { 13955669bfaSAl Viro case 0: /* native */ 14055669bfaSAl Viro if ((mask & AUDIT_PERM_WRITE) && 14155669bfaSAl Viro audit_match_class(AUDIT_CLASS_WRITE, n)) 14255669bfaSAl Viro return 1; 14355669bfaSAl Viro if ((mask & AUDIT_PERM_READ) && 14455669bfaSAl Viro audit_match_class(AUDIT_CLASS_READ, n)) 14555669bfaSAl Viro return 1; 14655669bfaSAl Viro if ((mask & AUDIT_PERM_ATTR) && 14755669bfaSAl Viro audit_match_class(AUDIT_CLASS_CHATTR, n)) 14855669bfaSAl Viro return 1; 14955669bfaSAl Viro return 0; 15055669bfaSAl Viro case 1: /* 32bit on biarch */ 15155669bfaSAl Viro if ((mask & AUDIT_PERM_WRITE) && 15255669bfaSAl Viro audit_match_class(AUDIT_CLASS_WRITE_32, n)) 15355669bfaSAl Viro return 1; 15455669bfaSAl Viro if ((mask & AUDIT_PERM_READ) && 15555669bfaSAl Viro audit_match_class(AUDIT_CLASS_READ_32, n)) 15655669bfaSAl Viro return 1; 15755669bfaSAl Viro if ((mask & AUDIT_PERM_ATTR) && 15855669bfaSAl Viro audit_match_class(AUDIT_CLASS_CHATTR_32, n)) 15955669bfaSAl Viro return 1; 16055669bfaSAl Viro return 0; 16155669bfaSAl Viro case 2: /* open */ 16255669bfaSAl Viro return mask & ACC_MODE(ctx->argv[1]); 16355669bfaSAl Viro case 3: /* openat */ 16455669bfaSAl Viro return mask & ACC_MODE(ctx->argv[2]); 16555669bfaSAl Viro case 4: /* socketcall */ 16655669bfaSAl Viro return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND); 16755669bfaSAl Viro case 5: /* execve */ 16855669bfaSAl Viro return mask & AUDIT_PERM_EXEC; 16955669bfaSAl Viro default: 17055669bfaSAl Viro return 0; 17155669bfaSAl Viro } 17255669bfaSAl Viro } 17355669bfaSAl Viro 1745ef30ee5SEric Paris static int audit_match_filetype(struct audit_context *ctx, int val) 1758b67dca9SAl Viro { 1765195d8e2SEric Paris struct audit_names *n; 1775ef30ee5SEric Paris umode_t mode = (umode_t)val; 1781a61c88dSzhangxiliang 1791a61c88dSzhangxiliang if (unlikely(!ctx)) 1801a61c88dSzhangxiliang return 0; 1811a61c88dSzhangxiliang 1825195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) { 18384cb777eSRichard Guy Briggs if ((n->ino != AUDIT_INO_UNSET) && 1845195d8e2SEric Paris ((n->mode & S_IFMT) == mode)) 1858b67dca9SAl Viro return 1; 1868b67dca9SAl Viro } 1875195d8e2SEric Paris 1885ef30ee5SEric Paris return 0; 1895ef30ee5SEric Paris } 1908b67dca9SAl Viro 19174c3cbe3SAl Viro /* 19274c3cbe3SAl Viro * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *; 19374c3cbe3SAl Viro * ->first_trees points to its beginning, ->trees - to the current end of data. 19474c3cbe3SAl Viro * ->tree_count is the number of free entries in array pointed to by ->trees. 19574c3cbe3SAl Viro * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL, 19674c3cbe3SAl Viro * "empty" becomes (p, p, 31) afterwards. We don't shrink the list (and seriously, 19774c3cbe3SAl Viro * it's going to remain 1-element for almost any setup) until we free context itself. 19874c3cbe3SAl Viro * References in it _are_ dropped - at the same time we free/drop aux stuff. 19974c3cbe3SAl Viro */ 20074c3cbe3SAl Viro 20174c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE 202679173b7SEric Paris static void audit_set_auditable(struct audit_context *ctx) 203679173b7SEric Paris { 204679173b7SEric Paris if (!ctx->prio) { 205679173b7SEric Paris ctx->prio = 1; 206679173b7SEric Paris ctx->current_state = AUDIT_RECORD_CONTEXT; 207679173b7SEric Paris } 208679173b7SEric Paris } 209679173b7SEric Paris 21074c3cbe3SAl Viro static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk) 21174c3cbe3SAl Viro { 21274c3cbe3SAl Viro struct audit_tree_refs *p = ctx->trees; 21374c3cbe3SAl Viro int left = ctx->tree_count; 21474c3cbe3SAl Viro if (likely(left)) { 21574c3cbe3SAl Viro p->c[--left] = chunk; 21674c3cbe3SAl Viro ctx->tree_count = left; 21774c3cbe3SAl Viro return 1; 21874c3cbe3SAl Viro } 21974c3cbe3SAl Viro if (!p) 22074c3cbe3SAl Viro return 0; 22174c3cbe3SAl Viro p = p->next; 22274c3cbe3SAl Viro if (p) { 22374c3cbe3SAl Viro p->c[30] = chunk; 22474c3cbe3SAl Viro ctx->trees = p; 22574c3cbe3SAl Viro ctx->tree_count = 30; 22674c3cbe3SAl Viro return 1; 22774c3cbe3SAl Viro } 22874c3cbe3SAl Viro return 0; 22974c3cbe3SAl Viro } 23074c3cbe3SAl Viro 23174c3cbe3SAl Viro static int grow_tree_refs(struct audit_context *ctx) 23274c3cbe3SAl Viro { 23374c3cbe3SAl Viro struct audit_tree_refs *p = ctx->trees; 23474c3cbe3SAl Viro ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL); 23574c3cbe3SAl Viro if (!ctx->trees) { 23674c3cbe3SAl Viro ctx->trees = p; 23774c3cbe3SAl Viro return 0; 23874c3cbe3SAl Viro } 23974c3cbe3SAl Viro if (p) 24074c3cbe3SAl Viro p->next = ctx->trees; 24174c3cbe3SAl Viro else 24274c3cbe3SAl Viro ctx->first_trees = ctx->trees; 24374c3cbe3SAl Viro ctx->tree_count = 31; 24474c3cbe3SAl Viro return 1; 24574c3cbe3SAl Viro } 24674c3cbe3SAl Viro #endif 24774c3cbe3SAl Viro 24874c3cbe3SAl Viro static void unroll_tree_refs(struct audit_context *ctx, 24974c3cbe3SAl Viro struct audit_tree_refs *p, int count) 25074c3cbe3SAl Viro { 25174c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE 25274c3cbe3SAl Viro struct audit_tree_refs *q; 25374c3cbe3SAl Viro int n; 25474c3cbe3SAl Viro if (!p) { 25574c3cbe3SAl Viro /* we started with empty chain */ 25674c3cbe3SAl Viro p = ctx->first_trees; 25774c3cbe3SAl Viro count = 31; 25874c3cbe3SAl Viro /* if the very first allocation has failed, nothing to do */ 25974c3cbe3SAl Viro if (!p) 26074c3cbe3SAl Viro return; 26174c3cbe3SAl Viro } 26274c3cbe3SAl Viro n = count; 26374c3cbe3SAl Viro for (q = p; q != ctx->trees; q = q->next, n = 31) { 26474c3cbe3SAl Viro while (n--) { 26574c3cbe3SAl Viro audit_put_chunk(q->c[n]); 26674c3cbe3SAl Viro q->c[n] = NULL; 26774c3cbe3SAl Viro } 26874c3cbe3SAl Viro } 26974c3cbe3SAl Viro while (n-- > ctx->tree_count) { 27074c3cbe3SAl Viro audit_put_chunk(q->c[n]); 27174c3cbe3SAl Viro q->c[n] = NULL; 27274c3cbe3SAl Viro } 27374c3cbe3SAl Viro ctx->trees = p; 27474c3cbe3SAl Viro ctx->tree_count = count; 27574c3cbe3SAl Viro #endif 27674c3cbe3SAl Viro } 27774c3cbe3SAl Viro 27874c3cbe3SAl Viro static void free_tree_refs(struct audit_context *ctx) 27974c3cbe3SAl Viro { 28074c3cbe3SAl Viro struct audit_tree_refs *p, *q; 28174c3cbe3SAl Viro for (p = ctx->first_trees; p; p = q) { 28274c3cbe3SAl Viro q = p->next; 28374c3cbe3SAl Viro kfree(p); 28474c3cbe3SAl Viro } 28574c3cbe3SAl Viro } 28674c3cbe3SAl Viro 28774c3cbe3SAl Viro static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) 28874c3cbe3SAl Viro { 28974c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE 29074c3cbe3SAl Viro struct audit_tree_refs *p; 29174c3cbe3SAl Viro int n; 29274c3cbe3SAl Viro if (!tree) 29374c3cbe3SAl Viro return 0; 29474c3cbe3SAl Viro /* full ones */ 29574c3cbe3SAl Viro for (p = ctx->first_trees; p != ctx->trees; p = p->next) { 29674c3cbe3SAl Viro for (n = 0; n < 31; n++) 29774c3cbe3SAl Viro if (audit_tree_match(p->c[n], tree)) 29874c3cbe3SAl Viro return 1; 29974c3cbe3SAl Viro } 30074c3cbe3SAl Viro /* partial */ 30174c3cbe3SAl Viro if (p) { 30274c3cbe3SAl Viro for (n = ctx->tree_count; n < 31; n++) 30374c3cbe3SAl Viro if (audit_tree_match(p->c[n], tree)) 30474c3cbe3SAl Viro return 1; 30574c3cbe3SAl Viro } 30674c3cbe3SAl Viro #endif 30774c3cbe3SAl Viro return 0; 30874c3cbe3SAl Viro } 30974c3cbe3SAl Viro 310ca57ec0fSEric W. Biederman static int audit_compare_uid(kuid_t uid, 311b34b0393SEric Paris struct audit_names *name, 312b34b0393SEric Paris struct audit_field *f, 313b34b0393SEric Paris struct audit_context *ctx) 314b34b0393SEric Paris { 315b34b0393SEric Paris struct audit_names *n; 316b34b0393SEric Paris int rc; 317b34b0393SEric Paris 318b34b0393SEric Paris if (name) { 319ca57ec0fSEric W. Biederman rc = audit_uid_comparator(uid, f->op, name->uid); 320b34b0393SEric Paris if (rc) 321b34b0393SEric Paris return rc; 322b34b0393SEric Paris } 323b34b0393SEric Paris 324b34b0393SEric Paris if (ctx) { 325b34b0393SEric Paris list_for_each_entry(n, &ctx->names_list, list) { 326ca57ec0fSEric W. Biederman rc = audit_uid_comparator(uid, f->op, n->uid); 327ca57ec0fSEric W. Biederman if (rc) 328ca57ec0fSEric W. Biederman return rc; 329ca57ec0fSEric W. Biederman } 330ca57ec0fSEric W. Biederman } 331ca57ec0fSEric W. Biederman return 0; 332ca57ec0fSEric W. Biederman } 333b34b0393SEric Paris 334ca57ec0fSEric W. Biederman static int audit_compare_gid(kgid_t gid, 335ca57ec0fSEric W. Biederman struct audit_names *name, 336ca57ec0fSEric W. Biederman struct audit_field *f, 337ca57ec0fSEric W. Biederman struct audit_context *ctx) 338ca57ec0fSEric W. Biederman { 339ca57ec0fSEric W. Biederman struct audit_names *n; 340ca57ec0fSEric W. Biederman int rc; 341b34b0393SEric Paris 342ca57ec0fSEric W. Biederman if (name) { 343ca57ec0fSEric W. Biederman rc = audit_gid_comparator(gid, f->op, name->gid); 344ca57ec0fSEric W. Biederman if (rc) 345ca57ec0fSEric W. Biederman return rc; 346ca57ec0fSEric W. Biederman } 347ca57ec0fSEric W. Biederman 348ca57ec0fSEric W. Biederman if (ctx) { 349ca57ec0fSEric W. Biederman list_for_each_entry(n, &ctx->names_list, list) { 350ca57ec0fSEric W. Biederman rc = audit_gid_comparator(gid, f->op, n->gid); 351b34b0393SEric Paris if (rc) 352b34b0393SEric Paris return rc; 353b34b0393SEric Paris } 354b34b0393SEric Paris } 355b34b0393SEric Paris return 0; 356b34b0393SEric Paris } 357b34b0393SEric Paris 35802d86a56SEric Paris static int audit_field_compare(struct task_struct *tsk, 35902d86a56SEric Paris const struct cred *cred, 36002d86a56SEric Paris struct audit_field *f, 36102d86a56SEric Paris struct audit_context *ctx, 36202d86a56SEric Paris struct audit_names *name) 36302d86a56SEric Paris { 36402d86a56SEric Paris switch (f->val) { 3654a6633edSPeter Moody /* process to file object comparisons */ 36602d86a56SEric Paris case AUDIT_COMPARE_UID_TO_OBJ_UID: 367ca57ec0fSEric W. Biederman return audit_compare_uid(cred->uid, name, f, ctx); 368c9fe685fSEric Paris case AUDIT_COMPARE_GID_TO_OBJ_GID: 369ca57ec0fSEric W. Biederman return audit_compare_gid(cred->gid, name, f, ctx); 3704a6633edSPeter Moody case AUDIT_COMPARE_EUID_TO_OBJ_UID: 371ca57ec0fSEric W. Biederman return audit_compare_uid(cred->euid, name, f, ctx); 3724a6633edSPeter Moody case AUDIT_COMPARE_EGID_TO_OBJ_GID: 373ca57ec0fSEric W. Biederman return audit_compare_gid(cred->egid, name, f, ctx); 3744a6633edSPeter Moody case AUDIT_COMPARE_AUID_TO_OBJ_UID: 375ca57ec0fSEric W. Biederman return audit_compare_uid(tsk->loginuid, name, f, ctx); 3764a6633edSPeter Moody case AUDIT_COMPARE_SUID_TO_OBJ_UID: 377ca57ec0fSEric W. Biederman return audit_compare_uid(cred->suid, name, f, ctx); 3784a6633edSPeter Moody case AUDIT_COMPARE_SGID_TO_OBJ_GID: 379ca57ec0fSEric W. Biederman return audit_compare_gid(cred->sgid, name, f, ctx); 3804a6633edSPeter Moody case AUDIT_COMPARE_FSUID_TO_OBJ_UID: 381ca57ec0fSEric W. Biederman return audit_compare_uid(cred->fsuid, name, f, ctx); 3824a6633edSPeter Moody case AUDIT_COMPARE_FSGID_TO_OBJ_GID: 383ca57ec0fSEric W. Biederman return audit_compare_gid(cred->fsgid, name, f, ctx); 38410d68360SPeter Moody /* uid comparisons */ 38510d68360SPeter Moody case AUDIT_COMPARE_UID_TO_AUID: 386ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->uid, f->op, tsk->loginuid); 38710d68360SPeter Moody case AUDIT_COMPARE_UID_TO_EUID: 388ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->uid, f->op, cred->euid); 38910d68360SPeter Moody case AUDIT_COMPARE_UID_TO_SUID: 390ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->uid, f->op, cred->suid); 39110d68360SPeter Moody case AUDIT_COMPARE_UID_TO_FSUID: 392ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->uid, f->op, cred->fsuid); 39310d68360SPeter Moody /* auid comparisons */ 39410d68360SPeter Moody case AUDIT_COMPARE_AUID_TO_EUID: 395ca57ec0fSEric W. Biederman return audit_uid_comparator(tsk->loginuid, f->op, cred->euid); 39610d68360SPeter Moody case AUDIT_COMPARE_AUID_TO_SUID: 397ca57ec0fSEric W. Biederman return audit_uid_comparator(tsk->loginuid, f->op, cred->suid); 39810d68360SPeter Moody case AUDIT_COMPARE_AUID_TO_FSUID: 399ca57ec0fSEric W. Biederman return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid); 40010d68360SPeter Moody /* euid comparisons */ 40110d68360SPeter Moody case AUDIT_COMPARE_EUID_TO_SUID: 402ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->euid, f->op, cred->suid); 40310d68360SPeter Moody case AUDIT_COMPARE_EUID_TO_FSUID: 404ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->euid, f->op, cred->fsuid); 40510d68360SPeter Moody /* suid comparisons */ 40610d68360SPeter Moody case AUDIT_COMPARE_SUID_TO_FSUID: 407ca57ec0fSEric W. Biederman return audit_uid_comparator(cred->suid, f->op, cred->fsuid); 40810d68360SPeter Moody /* gid comparisons */ 40910d68360SPeter Moody case AUDIT_COMPARE_GID_TO_EGID: 410ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->gid, f->op, cred->egid); 41110d68360SPeter Moody case AUDIT_COMPARE_GID_TO_SGID: 412ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->gid, f->op, cred->sgid); 41310d68360SPeter Moody case AUDIT_COMPARE_GID_TO_FSGID: 414ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->gid, f->op, cred->fsgid); 41510d68360SPeter Moody /* egid comparisons */ 41610d68360SPeter Moody case AUDIT_COMPARE_EGID_TO_SGID: 417ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->egid, f->op, cred->sgid); 41810d68360SPeter Moody case AUDIT_COMPARE_EGID_TO_FSGID: 419ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->egid, f->op, cred->fsgid); 42010d68360SPeter Moody /* sgid comparison */ 42110d68360SPeter Moody case AUDIT_COMPARE_SGID_TO_FSGID: 422ca57ec0fSEric W. Biederman return audit_gid_comparator(cred->sgid, f->op, cred->fsgid); 42302d86a56SEric Paris default: 42402d86a56SEric Paris WARN(1, "Missing AUDIT_COMPARE define. Report as a bug\n"); 42502d86a56SEric Paris return 0; 42602d86a56SEric Paris } 42702d86a56SEric Paris return 0; 42802d86a56SEric Paris } 42902d86a56SEric Paris 430f368c07dSAmy Griffis /* Determine if any context name data matches a rule's watch data */ 4311da177e4SLinus Torvalds /* Compare a task_struct with an audit_rule. Return 1 on match, 0 432f5629883STony Jones * otherwise. 433f5629883STony Jones * 434f5629883STony Jones * If task_creation is true, this is an explicit indication that we are 435f5629883STony Jones * filtering a task rule at task creation time. This and tsk == current are 436f5629883STony Jones * the only situations where tsk->cred may be accessed without an rcu read lock. 437f5629883STony Jones */ 4381da177e4SLinus Torvalds static int audit_filter_rules(struct task_struct *tsk, 43993315ed6SAmy Griffis struct audit_krule *rule, 4401da177e4SLinus Torvalds struct audit_context *ctx, 441f368c07dSAmy Griffis struct audit_names *name, 442f5629883STony Jones enum audit_state *state, 443f5629883STony Jones bool task_creation) 4441da177e4SLinus Torvalds { 445f5629883STony Jones const struct cred *cred; 4465195d8e2SEric Paris int i, need_sid = 1; 4473dc7e315SDarrel Goeddel u32 sid; 4483dc7e315SDarrel Goeddel 449f5629883STony Jones cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation); 450f5629883STony Jones 4511da177e4SLinus Torvalds for (i = 0; i < rule->field_count; i++) { 45293315ed6SAmy Griffis struct audit_field *f = &rule->fields[i]; 4535195d8e2SEric Paris struct audit_names *n; 4541da177e4SLinus Torvalds int result = 0; 455f1dc4867SRichard Guy Briggs pid_t pid; 4561da177e4SLinus Torvalds 45793315ed6SAmy Griffis switch (f->type) { 4581da177e4SLinus Torvalds case AUDIT_PID: 459f1dc4867SRichard Guy Briggs pid = task_pid_nr(tsk); 460f1dc4867SRichard Guy Briggs result = audit_comparator(pid, f->op, f->val); 4611da177e4SLinus Torvalds break; 4623c66251eSAl Viro case AUDIT_PPID: 463419c58f1SAlexander Viro if (ctx) { 464419c58f1SAlexander Viro if (!ctx->ppid) 465c92cdeb4SRichard Guy Briggs ctx->ppid = task_ppid_nr(tsk); 4663c66251eSAl Viro result = audit_comparator(ctx->ppid, f->op, f->val); 467419c58f1SAlexander Viro } 4683c66251eSAl Viro break; 46934d99af5SRichard Guy Briggs case AUDIT_EXE: 47034d99af5SRichard Guy Briggs result = audit_exe_compare(tsk, rule->exe); 47134d99af5SRichard Guy Briggs break; 4721da177e4SLinus Torvalds case AUDIT_UID: 473ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->uid, f->op, f->uid); 4741da177e4SLinus Torvalds break; 4751da177e4SLinus Torvalds case AUDIT_EUID: 476ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->euid, f->op, f->uid); 4771da177e4SLinus Torvalds break; 4781da177e4SLinus Torvalds case AUDIT_SUID: 479ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->suid, f->op, f->uid); 4801da177e4SLinus Torvalds break; 4811da177e4SLinus Torvalds case AUDIT_FSUID: 482ca57ec0fSEric W. Biederman result = audit_uid_comparator(cred->fsuid, f->op, f->uid); 4831da177e4SLinus Torvalds break; 4841da177e4SLinus Torvalds case AUDIT_GID: 485ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->gid, f->op, f->gid); 48637eebe39SMatvejchikov Ilya if (f->op == Audit_equal) { 48737eebe39SMatvejchikov Ilya if (!result) 48837eebe39SMatvejchikov Ilya result = in_group_p(f->gid); 48937eebe39SMatvejchikov Ilya } else if (f->op == Audit_not_equal) { 49037eebe39SMatvejchikov Ilya if (result) 49137eebe39SMatvejchikov Ilya result = !in_group_p(f->gid); 49237eebe39SMatvejchikov Ilya } 4931da177e4SLinus Torvalds break; 4941da177e4SLinus Torvalds case AUDIT_EGID: 495ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->egid, f->op, f->gid); 49637eebe39SMatvejchikov Ilya if (f->op == Audit_equal) { 49737eebe39SMatvejchikov Ilya if (!result) 49837eebe39SMatvejchikov Ilya result = in_egroup_p(f->gid); 49937eebe39SMatvejchikov Ilya } else if (f->op == Audit_not_equal) { 50037eebe39SMatvejchikov Ilya if (result) 50137eebe39SMatvejchikov Ilya result = !in_egroup_p(f->gid); 50237eebe39SMatvejchikov Ilya } 5031da177e4SLinus Torvalds break; 5041da177e4SLinus Torvalds case AUDIT_SGID: 505ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->sgid, f->op, f->gid); 5061da177e4SLinus Torvalds break; 5071da177e4SLinus Torvalds case AUDIT_FSGID: 508ca57ec0fSEric W. Biederman result = audit_gid_comparator(cred->fsgid, f->op, f->gid); 5091da177e4SLinus Torvalds break; 5101da177e4SLinus Torvalds case AUDIT_PERS: 51193315ed6SAmy Griffis result = audit_comparator(tsk->personality, f->op, f->val); 5121da177e4SLinus Torvalds break; 5132fd6f58bS case AUDIT_ARCH: 5142fd6f58bS if (ctx) 51593315ed6SAmy Griffis result = audit_comparator(ctx->arch, f->op, f->val); 5162fd6f58bS break; 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds case AUDIT_EXIT: 5191da177e4SLinus Torvalds if (ctx && ctx->return_valid) 52093315ed6SAmy Griffis result = audit_comparator(ctx->return_code, f->op, f->val); 5211da177e4SLinus Torvalds break; 5221da177e4SLinus Torvalds case AUDIT_SUCCESS: 523b01f2cc1SDavid Woodhouse if (ctx && ctx->return_valid) { 52493315ed6SAmy Griffis if (f->val) 52593315ed6SAmy Griffis result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS); 526b01f2cc1SDavid Woodhouse else 52793315ed6SAmy Griffis result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE); 528b01f2cc1SDavid Woodhouse } 5291da177e4SLinus Torvalds break; 5301da177e4SLinus Torvalds case AUDIT_DEVMAJOR: 53116c174bdSEric Paris if (name) { 53216c174bdSEric Paris if (audit_comparator(MAJOR(name->dev), f->op, f->val) || 53316c174bdSEric Paris audit_comparator(MAJOR(name->rdev), f->op, f->val)) 53416c174bdSEric Paris ++result; 53516c174bdSEric Paris } else if (ctx) { 5365195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) { 53716c174bdSEric Paris if (audit_comparator(MAJOR(n->dev), f->op, f->val) || 53816c174bdSEric Paris audit_comparator(MAJOR(n->rdev), f->op, f->val)) { 5391da177e4SLinus Torvalds ++result; 5401da177e4SLinus Torvalds break; 5411da177e4SLinus Torvalds } 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds } 5441da177e4SLinus Torvalds break; 5451da177e4SLinus Torvalds case AUDIT_DEVMINOR: 54616c174bdSEric Paris if (name) { 54716c174bdSEric Paris if (audit_comparator(MINOR(name->dev), f->op, f->val) || 54816c174bdSEric Paris audit_comparator(MINOR(name->rdev), f->op, f->val)) 54916c174bdSEric Paris ++result; 55016c174bdSEric Paris } else if (ctx) { 5515195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) { 55216c174bdSEric Paris if (audit_comparator(MINOR(n->dev), f->op, f->val) || 55316c174bdSEric Paris audit_comparator(MINOR(n->rdev), f->op, f->val)) { 5541da177e4SLinus Torvalds ++result; 5551da177e4SLinus Torvalds break; 5561da177e4SLinus Torvalds } 5571da177e4SLinus Torvalds } 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds break; 5601da177e4SLinus Torvalds case AUDIT_INODE: 561f368c07dSAmy Griffis if (name) 562db510fc5SRichard Guy Briggs result = audit_comparator(name->ino, f->op, f->val); 563f368c07dSAmy Griffis else if (ctx) { 5645195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) { 5655195d8e2SEric Paris if (audit_comparator(n->ino, f->op, f->val)) { 5661da177e4SLinus Torvalds ++result; 5671da177e4SLinus Torvalds break; 5681da177e4SLinus Torvalds } 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds } 5711da177e4SLinus Torvalds break; 572efaffd6eSEric Paris case AUDIT_OBJ_UID: 573efaffd6eSEric Paris if (name) { 574ca57ec0fSEric W. Biederman result = audit_uid_comparator(name->uid, f->op, f->uid); 575efaffd6eSEric Paris } else if (ctx) { 576efaffd6eSEric Paris list_for_each_entry(n, &ctx->names_list, list) { 577ca57ec0fSEric W. Biederman if (audit_uid_comparator(n->uid, f->op, f->uid)) { 578efaffd6eSEric Paris ++result; 579efaffd6eSEric Paris break; 580efaffd6eSEric Paris } 581efaffd6eSEric Paris } 582efaffd6eSEric Paris } 583efaffd6eSEric Paris break; 58454d3218bSEric Paris case AUDIT_OBJ_GID: 58554d3218bSEric Paris if (name) { 586ca57ec0fSEric W. Biederman result = audit_gid_comparator(name->gid, f->op, f->gid); 58754d3218bSEric Paris } else if (ctx) { 58854d3218bSEric Paris list_for_each_entry(n, &ctx->names_list, list) { 589ca57ec0fSEric W. Biederman if (audit_gid_comparator(n->gid, f->op, f->gid)) { 59054d3218bSEric Paris ++result; 59154d3218bSEric Paris break; 59254d3218bSEric Paris } 59354d3218bSEric Paris } 59454d3218bSEric Paris } 59554d3218bSEric Paris break; 596f368c07dSAmy Griffis case AUDIT_WATCH: 597ae7b8f41SEric Paris if (name) 598ae7b8f41SEric Paris result = audit_watch_compare(rule->watch, name->ino, name->dev); 599f368c07dSAmy Griffis break; 60074c3cbe3SAl Viro case AUDIT_DIR: 60174c3cbe3SAl Viro if (ctx) 60274c3cbe3SAl Viro result = match_tree_refs(ctx, rule->tree); 60374c3cbe3SAl Viro break; 6041da177e4SLinus Torvalds case AUDIT_LOGINUID: 605ca57ec0fSEric W. Biederman result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); 6061da177e4SLinus Torvalds break; 607780a7654SEric W. Biederman case AUDIT_LOGINUID_SET: 608780a7654SEric W. Biederman result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); 609780a7654SEric W. Biederman break; 6103a6b9f85SDarrel Goeddel case AUDIT_SUBJ_USER: 6113a6b9f85SDarrel Goeddel case AUDIT_SUBJ_ROLE: 6123a6b9f85SDarrel Goeddel case AUDIT_SUBJ_TYPE: 6133a6b9f85SDarrel Goeddel case AUDIT_SUBJ_SEN: 6143a6b9f85SDarrel Goeddel case AUDIT_SUBJ_CLR: 6153dc7e315SDarrel Goeddel /* NOTE: this may return negative values indicating 6163dc7e315SDarrel Goeddel a temporary error. We simply treat this as a 6173dc7e315SDarrel Goeddel match for now to avoid losing information that 6183dc7e315SDarrel Goeddel may be wanted. An error message will also be 6193dc7e315SDarrel Goeddel logged upon error */ 62004305e4aSAhmed S. Darwish if (f->lsm_rule) { 6212ad312d2SSteve Grubb if (need_sid) { 6222a862b32SAhmed S. Darwish security_task_getsecid(tsk, &sid); 6232ad312d2SSteve Grubb need_sid = 0; 6242ad312d2SSteve Grubb } 625d7a96f3aSAhmed S. Darwish result = security_audit_rule_match(sid, f->type, 6263dc7e315SDarrel Goeddel f->op, 62704305e4aSAhmed S. Darwish f->lsm_rule, 6283dc7e315SDarrel Goeddel ctx); 6292ad312d2SSteve Grubb } 6303dc7e315SDarrel Goeddel break; 6316e5a2d1dSDarrel Goeddel case AUDIT_OBJ_USER: 6326e5a2d1dSDarrel Goeddel case AUDIT_OBJ_ROLE: 6336e5a2d1dSDarrel Goeddel case AUDIT_OBJ_TYPE: 6346e5a2d1dSDarrel Goeddel case AUDIT_OBJ_LEV_LOW: 6356e5a2d1dSDarrel Goeddel case AUDIT_OBJ_LEV_HIGH: 6366e5a2d1dSDarrel Goeddel /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR 6376e5a2d1dSDarrel Goeddel also applies here */ 63804305e4aSAhmed S. Darwish if (f->lsm_rule) { 6396e5a2d1dSDarrel Goeddel /* Find files that match */ 6406e5a2d1dSDarrel Goeddel if (name) { 641d7a96f3aSAhmed S. Darwish result = security_audit_rule_match( 6426e5a2d1dSDarrel Goeddel name->osid, f->type, f->op, 64304305e4aSAhmed S. Darwish f->lsm_rule, ctx); 6446e5a2d1dSDarrel Goeddel } else if (ctx) { 6455195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) { 6465195d8e2SEric Paris if (security_audit_rule_match(n->osid, f->type, 6475195d8e2SEric Paris f->op, f->lsm_rule, 6485195d8e2SEric Paris ctx)) { 6496e5a2d1dSDarrel Goeddel ++result; 6506e5a2d1dSDarrel Goeddel break; 6516e5a2d1dSDarrel Goeddel } 6526e5a2d1dSDarrel Goeddel } 6536e5a2d1dSDarrel Goeddel } 6546e5a2d1dSDarrel Goeddel /* Find ipc objects that match */ 655a33e6751SAl Viro if (!ctx || ctx->type != AUDIT_IPC) 6566e5a2d1dSDarrel Goeddel break; 657a33e6751SAl Viro if (security_audit_rule_match(ctx->ipc.osid, 658a33e6751SAl Viro f->type, f->op, 659a33e6751SAl Viro f->lsm_rule, ctx)) 660a33e6751SAl Viro ++result; 6616e5a2d1dSDarrel Goeddel } 6626e5a2d1dSDarrel Goeddel break; 6631da177e4SLinus Torvalds case AUDIT_ARG0: 6641da177e4SLinus Torvalds case AUDIT_ARG1: 6651da177e4SLinus Torvalds case AUDIT_ARG2: 6661da177e4SLinus Torvalds case AUDIT_ARG3: 6671da177e4SLinus Torvalds if (ctx) 66893315ed6SAmy Griffis result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); 6691da177e4SLinus Torvalds break; 6705adc8a6aSAmy Griffis case AUDIT_FILTERKEY: 6715adc8a6aSAmy Griffis /* ignore this field for filtering */ 6725adc8a6aSAmy Griffis result = 1; 6735adc8a6aSAmy Griffis break; 67455669bfaSAl Viro case AUDIT_PERM: 67555669bfaSAl Viro result = audit_match_perm(ctx, f->val); 67655669bfaSAl Viro break; 6778b67dca9SAl Viro case AUDIT_FILETYPE: 6788b67dca9SAl Viro result = audit_match_filetype(ctx, f->val); 6798b67dca9SAl Viro break; 68002d86a56SEric Paris case AUDIT_FIELD_COMPARE: 68102d86a56SEric Paris result = audit_field_compare(tsk, cred, f, ctx, name); 68202d86a56SEric Paris break; 6831da177e4SLinus Torvalds } 684f5629883STony Jones if (!result) 6851da177e4SLinus Torvalds return 0; 6861da177e4SLinus Torvalds } 6870590b933SAl Viro 6880590b933SAl Viro if (ctx) { 6890590b933SAl Viro if (rule->prio <= ctx->prio) 6900590b933SAl Viro return 0; 6910590b933SAl Viro if (rule->filterkey) { 6920590b933SAl Viro kfree(ctx->filterkey); 6935adc8a6aSAmy Griffis ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); 6940590b933SAl Viro } 6950590b933SAl Viro ctx->prio = rule->prio; 6960590b933SAl Viro } 6971da177e4SLinus Torvalds switch (rule->action) { 6981da177e4SLinus Torvalds case AUDIT_NEVER: *state = AUDIT_DISABLED; break; 6991da177e4SLinus Torvalds case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; 7001da177e4SLinus Torvalds } 7011da177e4SLinus Torvalds return 1; 7021da177e4SLinus Torvalds } 7031da177e4SLinus Torvalds 7041da177e4SLinus Torvalds /* At process creation time, we can determine if system-call auditing is 7051da177e4SLinus Torvalds * completely disabled for this task. Since we only have the task 7061da177e4SLinus Torvalds * structure at this point, we can only check uid and gid. 7071da177e4SLinus Torvalds */ 708e048e02cSAl Viro static enum audit_state audit_filter_task(struct task_struct *tsk, char **key) 7091da177e4SLinus Torvalds { 7101da177e4SLinus Torvalds struct audit_entry *e; 7111da177e4SLinus Torvalds enum audit_state state; 7121da177e4SLinus Torvalds 7131da177e4SLinus Torvalds rcu_read_lock(); 7140f45aa18SDavid Woodhouse list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) { 715f5629883STony Jones if (audit_filter_rules(tsk, &e->rule, NULL, NULL, 716f5629883STony Jones &state, true)) { 717e048e02cSAl Viro if (state == AUDIT_RECORD_CONTEXT) 718e048e02cSAl Viro *key = kstrdup(e->rule.filterkey, GFP_ATOMIC); 7191da177e4SLinus Torvalds rcu_read_unlock(); 7201da177e4SLinus Torvalds return state; 7211da177e4SLinus Torvalds } 7221da177e4SLinus Torvalds } 7231da177e4SLinus Torvalds rcu_read_unlock(); 7241da177e4SLinus Torvalds return AUDIT_BUILD_CONTEXT; 7251da177e4SLinus Torvalds } 7261da177e4SLinus Torvalds 727a3c54931SAndy Lutomirski static int audit_in_mask(const struct audit_krule *rule, unsigned long val) 728a3c54931SAndy Lutomirski { 729a3c54931SAndy Lutomirski int word, bit; 730a3c54931SAndy Lutomirski 731a3c54931SAndy Lutomirski if (val > 0xffffffff) 732a3c54931SAndy Lutomirski return false; 733a3c54931SAndy Lutomirski 734a3c54931SAndy Lutomirski word = AUDIT_WORD(val); 735a3c54931SAndy Lutomirski if (word >= AUDIT_BITMASK_SIZE) 736a3c54931SAndy Lutomirski return false; 737a3c54931SAndy Lutomirski 738a3c54931SAndy Lutomirski bit = AUDIT_BIT(val); 739a3c54931SAndy Lutomirski 740a3c54931SAndy Lutomirski return rule->mask[word] & bit; 741a3c54931SAndy Lutomirski } 742a3c54931SAndy Lutomirski 7431da177e4SLinus Torvalds /* At syscall entry and exit time, this filter is called if the 7441da177e4SLinus Torvalds * audit_state is not low enough that auditing cannot take place, but is 74523f32d18SSteve Grubb * also not high enough that we already know we have to write an audit 7461da177e4SLinus Torvalds * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT). 7471da177e4SLinus Torvalds */ 7481da177e4SLinus Torvalds static enum audit_state audit_filter_syscall(struct task_struct *tsk, 7491da177e4SLinus Torvalds struct audit_context *ctx, 7501da177e4SLinus Torvalds struct list_head *list) 7511da177e4SLinus Torvalds { 7521da177e4SLinus Torvalds struct audit_entry *e; 7531da177e4SLinus Torvalds enum audit_state state; 7541da177e4SLinus Torvalds 755351bb722SDavid Woodhouse if (audit_pid && tsk->tgid == audit_pid) 756f7056d64SDavid Woodhouse return AUDIT_DISABLED; 757f7056d64SDavid Woodhouse 7581da177e4SLinus Torvalds rcu_read_lock(); 759c3896495SDavid Woodhouse if (!list_empty(list)) { 7601da177e4SLinus Torvalds list_for_each_entry_rcu(e, list, list) { 761a3c54931SAndy Lutomirski if (audit_in_mask(&e->rule, ctx->major) && 762f368c07dSAmy Griffis audit_filter_rules(tsk, &e->rule, ctx, NULL, 763f5629883STony Jones &state, false)) { 7641da177e4SLinus Torvalds rcu_read_unlock(); 7650590b933SAl Viro ctx->current_state = state; 7661da177e4SLinus Torvalds return state; 7671da177e4SLinus Torvalds } 7681da177e4SLinus Torvalds } 769c3896495SDavid Woodhouse } 7701da177e4SLinus Torvalds rcu_read_unlock(); 7711da177e4SLinus Torvalds return AUDIT_BUILD_CONTEXT; 7721da177e4SLinus Torvalds } 7731da177e4SLinus Torvalds 7745195d8e2SEric Paris /* 7755195d8e2SEric Paris * Given an audit_name check the inode hash table to see if they match. 7765195d8e2SEric Paris * Called holding the rcu read lock to protect the use of audit_inode_hash 7775195d8e2SEric Paris */ 7785195d8e2SEric Paris static int audit_filter_inode_name(struct task_struct *tsk, 7795195d8e2SEric Paris struct audit_names *n, 7805195d8e2SEric Paris struct audit_context *ctx) { 7815195d8e2SEric Paris int h = audit_hash_ino((u32)n->ino); 7825195d8e2SEric Paris struct list_head *list = &audit_inode_hash[h]; 7835195d8e2SEric Paris struct audit_entry *e; 7845195d8e2SEric Paris enum audit_state state; 7855195d8e2SEric Paris 7865195d8e2SEric Paris if (list_empty(list)) 7875195d8e2SEric Paris return 0; 7885195d8e2SEric Paris 7895195d8e2SEric Paris list_for_each_entry_rcu(e, list, list) { 790a3c54931SAndy Lutomirski if (audit_in_mask(&e->rule, ctx->major) && 7915195d8e2SEric Paris audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) { 7925195d8e2SEric Paris ctx->current_state = state; 7935195d8e2SEric Paris return 1; 7945195d8e2SEric Paris } 7955195d8e2SEric Paris } 7965195d8e2SEric Paris 7975195d8e2SEric Paris return 0; 7985195d8e2SEric Paris } 7995195d8e2SEric Paris 8005195d8e2SEric Paris /* At syscall exit time, this filter is called if any audit_names have been 801f368c07dSAmy Griffis * collected during syscall processing. We only check rules in sublists at hash 8025195d8e2SEric Paris * buckets applicable to the inode numbers in audit_names. 803f368c07dSAmy Griffis * Regarding audit_state, same rules apply as for audit_filter_syscall(). 804f368c07dSAmy Griffis */ 8050590b933SAl Viro void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) 806f368c07dSAmy Griffis { 8075195d8e2SEric Paris struct audit_names *n; 808f368c07dSAmy Griffis 809f368c07dSAmy Griffis if (audit_pid && tsk->tgid == audit_pid) 8100590b933SAl Viro return; 811f368c07dSAmy Griffis 812f368c07dSAmy Griffis rcu_read_lock(); 813f368c07dSAmy Griffis 8145195d8e2SEric Paris list_for_each_entry(n, &ctx->names_list, list) { 8155195d8e2SEric Paris if (audit_filter_inode_name(tsk, n, ctx)) 8165195d8e2SEric Paris break; 817f368c07dSAmy Griffis } 818f368c07dSAmy Griffis rcu_read_unlock(); 819f368c07dSAmy Griffis } 820f368c07dSAmy Griffis 8214a3eb726SRichard Guy Briggs /* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */ 8224a3eb726SRichard Guy Briggs static inline struct audit_context *audit_take_context(struct task_struct *tsk, 8231da177e4SLinus Torvalds int return_valid, 8246d208da8SPaul Moore long return_code) 8251da177e4SLinus Torvalds { 8261da177e4SLinus Torvalds struct audit_context *context = tsk->audit_context; 8271da177e4SLinus Torvalds 82856179a6eSEric Paris if (!context) 8291da177e4SLinus Torvalds return NULL; 8301da177e4SLinus Torvalds context->return_valid = return_valid; 831f701b75eSEric Paris 832f701b75eSEric Paris /* 833f701b75eSEric Paris * we need to fix up the return code in the audit logs if the actual 834f701b75eSEric Paris * return codes are later going to be fixed up by the arch specific 835f701b75eSEric Paris * signal handlers 836f701b75eSEric Paris * 837f701b75eSEric Paris * This is actually a test for: 838f701b75eSEric Paris * (rc == ERESTARTSYS ) || (rc == ERESTARTNOINTR) || 839f701b75eSEric Paris * (rc == ERESTARTNOHAND) || (rc == ERESTART_RESTARTBLOCK) 840f701b75eSEric Paris * 841f701b75eSEric Paris * but is faster than a bunch of || 842f701b75eSEric Paris */ 843f701b75eSEric Paris if (unlikely(return_code <= -ERESTARTSYS) && 844f701b75eSEric Paris (return_code >= -ERESTART_RESTARTBLOCK) && 845f701b75eSEric Paris (return_code != -ENOIOCTLCMD)) 846f701b75eSEric Paris context->return_code = -EINTR; 847f701b75eSEric Paris else 8481da177e4SLinus Torvalds context->return_code = return_code; 8491da177e4SLinus Torvalds 8500590b933SAl Viro if (context->in_syscall && !context->dummy) { 8510590b933SAl Viro audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); 8520590b933SAl Viro audit_filter_inodes(tsk, context); 8531da177e4SLinus Torvalds } 8541da177e4SLinus Torvalds 8551da177e4SLinus Torvalds tsk->audit_context = NULL; 8561da177e4SLinus Torvalds return context; 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds 8593f1c8250SWilliam Roberts static inline void audit_proctitle_free(struct audit_context *context) 8603f1c8250SWilliam Roberts { 8613f1c8250SWilliam Roberts kfree(context->proctitle.value); 8623f1c8250SWilliam Roberts context->proctitle.value = NULL; 8633f1c8250SWilliam Roberts context->proctitle.len = 0; 8643f1c8250SWilliam Roberts } 8653f1c8250SWilliam Roberts 8661da177e4SLinus Torvalds static inline void audit_free_names(struct audit_context *context) 8671da177e4SLinus Torvalds { 8685195d8e2SEric Paris struct audit_names *n, *next; 8691da177e4SLinus Torvalds 8705195d8e2SEric Paris list_for_each_entry_safe(n, next, &context->names_list, list) { 8715195d8e2SEric Paris list_del(&n->list); 87255422d0bSPaul Moore if (n->name) 87355422d0bSPaul Moore putname(n->name); 8745195d8e2SEric Paris if (n->should_free) 8755195d8e2SEric Paris kfree(n); 8768c8570fbSDustin Kirkland } 8771da177e4SLinus Torvalds context->name_count = 0; 87844707fdfSJan Blunck path_put(&context->pwd); 87944707fdfSJan Blunck context->pwd.dentry = NULL; 88044707fdfSJan Blunck context->pwd.mnt = NULL; 8811da177e4SLinus Torvalds } 8821da177e4SLinus Torvalds 8831da177e4SLinus Torvalds static inline void audit_free_aux(struct audit_context *context) 8841da177e4SLinus Torvalds { 8851da177e4SLinus Torvalds struct audit_aux_data *aux; 8861da177e4SLinus Torvalds 8871da177e4SLinus Torvalds while ((aux = context->aux)) { 8881da177e4SLinus Torvalds context->aux = aux->next; 8891da177e4SLinus Torvalds kfree(aux); 8901da177e4SLinus Torvalds } 891e54dc243SAmy Griffis while ((aux = context->aux_pids)) { 892e54dc243SAmy Griffis context->aux_pids = aux->next; 893e54dc243SAmy Griffis kfree(aux); 894e54dc243SAmy Griffis } 8951da177e4SLinus Torvalds } 8961da177e4SLinus Torvalds 8971da177e4SLinus Torvalds static inline struct audit_context *audit_alloc_context(enum audit_state state) 8981da177e4SLinus Torvalds { 8991da177e4SLinus Torvalds struct audit_context *context; 9001da177e4SLinus Torvalds 90117c6ee70SRakib Mullick context = kzalloc(sizeof(*context), GFP_KERNEL); 90217c6ee70SRakib Mullick if (!context) 9031da177e4SLinus Torvalds return NULL; 904e2c5adc8SAndrew Morton context->state = state; 905e2c5adc8SAndrew Morton context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; 906916d7576SAl Viro INIT_LIST_HEAD(&context->killed_trees); 9075195d8e2SEric Paris INIT_LIST_HEAD(&context->names_list); 9081da177e4SLinus Torvalds return context; 9091da177e4SLinus Torvalds } 9101da177e4SLinus Torvalds 911b0dd25a8SRandy Dunlap /** 912b0dd25a8SRandy Dunlap * audit_alloc - allocate an audit context block for a task 913b0dd25a8SRandy Dunlap * @tsk: task 914b0dd25a8SRandy Dunlap * 915b0dd25a8SRandy Dunlap * Filter on the task information and allocate a per-task audit context 9161da177e4SLinus Torvalds * if necessary. Doing so turns on system call auditing for the 9171da177e4SLinus Torvalds * specified task. This is called from copy_process, so no lock is 918b0dd25a8SRandy Dunlap * needed. 919b0dd25a8SRandy Dunlap */ 9201da177e4SLinus Torvalds int audit_alloc(struct task_struct *tsk) 9211da177e4SLinus Torvalds { 9221da177e4SLinus Torvalds struct audit_context *context; 9231da177e4SLinus Torvalds enum audit_state state; 924e048e02cSAl Viro char *key = NULL; 9251da177e4SLinus Torvalds 926b593d384SEric Paris if (likely(!audit_ever_enabled)) 9271da177e4SLinus Torvalds return 0; /* Return if not auditing. */ 9281da177e4SLinus Torvalds 929e048e02cSAl Viro state = audit_filter_task(tsk, &key); 930d48d8051SOleg Nesterov if (state == AUDIT_DISABLED) { 931d48d8051SOleg Nesterov clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); 9321da177e4SLinus Torvalds return 0; 933d48d8051SOleg Nesterov } 9341da177e4SLinus Torvalds 9351da177e4SLinus Torvalds if (!(context = audit_alloc_context(state))) { 936e048e02cSAl Viro kfree(key); 9371da177e4SLinus Torvalds audit_log_lost("out of memory in audit_alloc"); 9381da177e4SLinus Torvalds return -ENOMEM; 9391da177e4SLinus Torvalds } 940e048e02cSAl Viro context->filterkey = key; 9411da177e4SLinus Torvalds 9421da177e4SLinus Torvalds tsk->audit_context = context; 9431da177e4SLinus Torvalds set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); 9441da177e4SLinus Torvalds return 0; 9451da177e4SLinus Torvalds } 9461da177e4SLinus Torvalds 9471da177e4SLinus Torvalds static inline void audit_free_context(struct audit_context *context) 9481da177e4SLinus Torvalds { 9491da177e4SLinus Torvalds audit_free_names(context); 95074c3cbe3SAl Viro unroll_tree_refs(context, NULL, 0); 95174c3cbe3SAl Viro free_tree_refs(context); 9521da177e4SLinus Torvalds audit_free_aux(context); 9535adc8a6aSAmy Griffis kfree(context->filterkey); 9544f6b434fSAl Viro kfree(context->sockaddr); 9553f1c8250SWilliam Roberts audit_proctitle_free(context); 9561da177e4SLinus Torvalds kfree(context); 9571da177e4SLinus Torvalds } 9581da177e4SLinus Torvalds 959e54dc243SAmy Griffis static int audit_log_pid_context(struct audit_context *context, pid_t pid, 960cca080d9SEric W. Biederman kuid_t auid, kuid_t uid, unsigned int sessionid, 9614746ec5bSEric Paris u32 sid, char *comm) 962e54dc243SAmy Griffis { 963e54dc243SAmy Griffis struct audit_buffer *ab; 9642a862b32SAhmed S. Darwish char *ctx = NULL; 965e54dc243SAmy Griffis u32 len; 966e54dc243SAmy Griffis int rc = 0; 967e54dc243SAmy Griffis 968e54dc243SAmy Griffis ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); 969e54dc243SAmy Griffis if (!ab) 9706246ccabSEric Paris return rc; 971e54dc243SAmy Griffis 972e1760bd5SEric W. Biederman audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, 973e1760bd5SEric W. Biederman from_kuid(&init_user_ns, auid), 974cca080d9SEric W. Biederman from_kuid(&init_user_ns, uid), sessionid); 975ad395abeSEric Paris if (sid) { 9762a862b32SAhmed S. Darwish if (security_secid_to_secctx(sid, &ctx, &len)) { 977c2a7780eSEric Paris audit_log_format(ab, " obj=(none)"); 978e54dc243SAmy Griffis rc = 1; 9792a862b32SAhmed S. Darwish } else { 9802a862b32SAhmed S. Darwish audit_log_format(ab, " obj=%s", ctx); 9812a862b32SAhmed S. Darwish security_release_secctx(ctx, len); 9822a862b32SAhmed S. Darwish } 983ad395abeSEric Paris } 984c2a7780eSEric Paris audit_log_format(ab, " ocomm="); 985c2a7780eSEric Paris audit_log_untrustedstring(ab, comm); 986e54dc243SAmy Griffis audit_log_end(ab); 987e54dc243SAmy Griffis 988e54dc243SAmy Griffis return rc; 989e54dc243SAmy Griffis } 990e54dc243SAmy Griffis 991de6bbd1dSEric Paris /* 992de6bbd1dSEric Paris * to_send and len_sent accounting are very loose estimates. We aren't 993de6bbd1dSEric Paris * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being 99425985edcSLucas De Marchi * within about 500 bytes (next page boundary) 995de6bbd1dSEric Paris * 996de6bbd1dSEric Paris * why snprintf? an int is up to 12 digits long. if we just assumed when 997de6bbd1dSEric Paris * logging that a[%d]= was going to be 16 characters long we would be wasting 998de6bbd1dSEric Paris * space in every audit message. In one 7500 byte message we can log up to 999de6bbd1dSEric Paris * about 1000 min size arguments. That comes down to about 50% waste of space 1000de6bbd1dSEric Paris * if we didn't do the snprintf to find out how long arg_num_len was. 1001de6bbd1dSEric Paris */ 1002de6bbd1dSEric Paris static int audit_log_single_execve_arg(struct audit_context *context, 1003de6bbd1dSEric Paris struct audit_buffer **ab, 1004de6bbd1dSEric Paris int arg_num, 1005de6bbd1dSEric Paris size_t *len_sent, 1006de6bbd1dSEric Paris const char __user *p, 1007de6bbd1dSEric Paris char *buf) 1008bdf4c48aSPeter Zijlstra { 1009de6bbd1dSEric Paris char arg_num_len_buf[12]; 1010de6bbd1dSEric Paris const char __user *tmp_p = p; 1011b87ce6e4SEric Paris /* how many digits are in arg_num? 5 is the length of ' a=""' */ 1012b87ce6e4SEric Paris size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5; 1013de6bbd1dSEric Paris size_t len, len_left, to_send; 1014de6bbd1dSEric Paris size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN; 1015de6bbd1dSEric Paris unsigned int i, has_cntl = 0, too_long = 0; 1016de6bbd1dSEric Paris int ret; 1017bdf4c48aSPeter Zijlstra 1018de6bbd1dSEric Paris /* strnlen_user includes the null we don't want to send */ 1019de6bbd1dSEric Paris len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1; 1020bdf4c48aSPeter Zijlstra 1021bdf4c48aSPeter Zijlstra /* 1022bdf4c48aSPeter Zijlstra * We just created this mm, if we can't find the strings 1023bdf4c48aSPeter Zijlstra * we just copied into it something is _very_ wrong. Similar 1024bdf4c48aSPeter Zijlstra * for strings that are too long, we should not have created 1025bdf4c48aSPeter Zijlstra * any. 1026bdf4c48aSPeter Zijlstra */ 102745820c29SLinus Torvalds if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) { 1028bdf4c48aSPeter Zijlstra send_sig(SIGKILL, current, 0); 1029b0abcfc1SEric Paris return -1; 1030bdf4c48aSPeter Zijlstra } 1031bdf4c48aSPeter Zijlstra 1032de6bbd1dSEric Paris /* walk the whole argument looking for non-ascii chars */ 1033de6bbd1dSEric Paris do { 1034de6bbd1dSEric Paris if (len_left > MAX_EXECVE_AUDIT_LEN) 1035de6bbd1dSEric Paris to_send = MAX_EXECVE_AUDIT_LEN; 1036de6bbd1dSEric Paris else 1037de6bbd1dSEric Paris to_send = len_left; 1038de6bbd1dSEric Paris ret = copy_from_user(buf, tmp_p, to_send); 1039bdf4c48aSPeter Zijlstra /* 1040bdf4c48aSPeter Zijlstra * There is no reason for this copy to be short. We just 1041bdf4c48aSPeter Zijlstra * copied them here, and the mm hasn't been exposed to user- 1042bdf4c48aSPeter Zijlstra * space yet. 1043bdf4c48aSPeter Zijlstra */ 1044040b3a2dSPeter Zijlstra if (ret) { 1045bdf4c48aSPeter Zijlstra WARN_ON(1); 1046bdf4c48aSPeter Zijlstra send_sig(SIGKILL, current, 0); 1047b0abcfc1SEric Paris return -1; 1048bdf4c48aSPeter Zijlstra } 1049de6bbd1dSEric Paris buf[to_send] = '\0'; 1050de6bbd1dSEric Paris has_cntl = audit_string_contains_control(buf, to_send); 1051de6bbd1dSEric Paris if (has_cntl) { 1052de6bbd1dSEric Paris /* 1053de6bbd1dSEric Paris * hex messages get logged as 2 bytes, so we can only 1054de6bbd1dSEric Paris * send half as much in each message 1055de6bbd1dSEric Paris */ 1056de6bbd1dSEric Paris max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2; 1057de6bbd1dSEric Paris break; 1058bdf4c48aSPeter Zijlstra } 1059de6bbd1dSEric Paris len_left -= to_send; 1060de6bbd1dSEric Paris tmp_p += to_send; 1061de6bbd1dSEric Paris } while (len_left > 0); 1062de6bbd1dSEric Paris 1063de6bbd1dSEric Paris len_left = len; 1064de6bbd1dSEric Paris 1065de6bbd1dSEric Paris if (len > max_execve_audit_len) 1066de6bbd1dSEric Paris too_long = 1; 1067de6bbd1dSEric Paris 1068de6bbd1dSEric Paris /* rewalk the argument actually logging the message */ 1069de6bbd1dSEric Paris for (i = 0; len_left > 0; i++) { 1070de6bbd1dSEric Paris int room_left; 1071de6bbd1dSEric Paris 1072de6bbd1dSEric Paris if (len_left > max_execve_audit_len) 1073de6bbd1dSEric Paris to_send = max_execve_audit_len; 1074de6bbd1dSEric Paris else 1075de6bbd1dSEric Paris to_send = len_left; 1076de6bbd1dSEric Paris 1077de6bbd1dSEric Paris /* do we have space left to send this argument in this ab? */ 1078de6bbd1dSEric Paris room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent; 1079de6bbd1dSEric Paris if (has_cntl) 1080de6bbd1dSEric Paris room_left -= (to_send * 2); 1081de6bbd1dSEric Paris else 1082de6bbd1dSEric Paris room_left -= to_send; 1083de6bbd1dSEric Paris if (room_left < 0) { 1084de6bbd1dSEric Paris *len_sent = 0; 1085de6bbd1dSEric Paris audit_log_end(*ab); 1086de6bbd1dSEric Paris *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE); 1087de6bbd1dSEric Paris if (!*ab) 1088de6bbd1dSEric Paris return 0; 1089de6bbd1dSEric Paris } 1090de6bbd1dSEric Paris 1091de6bbd1dSEric Paris /* 1092de6bbd1dSEric Paris * first record needs to say how long the original string was 1093de6bbd1dSEric Paris * so we can be sure nothing was lost. 1094de6bbd1dSEric Paris */ 1095de6bbd1dSEric Paris if ((i == 0) && (too_long)) 1096422b03cfSPaul Moore audit_log_format(*ab, " a%d_len=%zu", arg_num, 1097de6bbd1dSEric Paris has_cntl ? 2*len : len); 1098de6bbd1dSEric Paris 1099de6bbd1dSEric Paris /* 1100de6bbd1dSEric Paris * normally arguments are small enough to fit and we already 1101de6bbd1dSEric Paris * filled buf above when we checked for control characters 1102de6bbd1dSEric Paris * so don't bother with another copy_from_user 1103de6bbd1dSEric Paris */ 1104de6bbd1dSEric Paris if (len >= max_execve_audit_len) 1105de6bbd1dSEric Paris ret = copy_from_user(buf, p, to_send); 1106de6bbd1dSEric Paris else 1107de6bbd1dSEric Paris ret = 0; 1108de6bbd1dSEric Paris if (ret) { 1109de6bbd1dSEric Paris WARN_ON(1); 1110de6bbd1dSEric Paris send_sig(SIGKILL, current, 0); 1111b0abcfc1SEric Paris return -1; 1112de6bbd1dSEric Paris } 1113de6bbd1dSEric Paris buf[to_send] = '\0'; 1114de6bbd1dSEric Paris 1115de6bbd1dSEric Paris /* actually log it */ 1116de6bbd1dSEric Paris audit_log_format(*ab, " a%d", arg_num); 1117de6bbd1dSEric Paris if (too_long) 1118de6bbd1dSEric Paris audit_log_format(*ab, "[%d]", i); 1119de6bbd1dSEric Paris audit_log_format(*ab, "="); 1120de6bbd1dSEric Paris if (has_cntl) 1121b556f8adSEric Paris audit_log_n_hex(*ab, buf, to_send); 1122de6bbd1dSEric Paris else 11239d960985SEric Paris audit_log_string(*ab, buf); 1124de6bbd1dSEric Paris 1125de6bbd1dSEric Paris p += to_send; 1126de6bbd1dSEric Paris len_left -= to_send; 1127de6bbd1dSEric Paris *len_sent += arg_num_len; 1128de6bbd1dSEric Paris if (has_cntl) 1129de6bbd1dSEric Paris *len_sent += to_send * 2; 1130de6bbd1dSEric Paris else 1131de6bbd1dSEric Paris *len_sent += to_send; 1132de6bbd1dSEric Paris } 1133de6bbd1dSEric Paris /* include the null we didn't log */ 1134de6bbd1dSEric Paris return len + 1; 1135de6bbd1dSEric Paris } 1136de6bbd1dSEric Paris 1137de6bbd1dSEric Paris static void audit_log_execve_info(struct audit_context *context, 1138d9cfea91SRichard Guy Briggs struct audit_buffer **ab) 1139de6bbd1dSEric Paris { 11405afb8a3fSXi Wang int i, len; 11415afb8a3fSXi Wang size_t len_sent = 0; 1142de6bbd1dSEric Paris const char __user *p; 1143de6bbd1dSEric Paris char *buf; 1144de6bbd1dSEric Paris 1145d9cfea91SRichard Guy Briggs p = (const char __user *)current->mm->arg_start; 1146de6bbd1dSEric Paris 1147d9cfea91SRichard Guy Briggs audit_log_format(*ab, "argc=%d", context->execve.argc); 1148de6bbd1dSEric Paris 1149de6bbd1dSEric Paris /* 1150de6bbd1dSEric Paris * we need some kernel buffer to hold the userspace args. Just 1151de6bbd1dSEric Paris * allocate one big one rather than allocating one of the right size 1152de6bbd1dSEric Paris * for every single argument inside audit_log_single_execve_arg() 1153de6bbd1dSEric Paris * should be <8k allocation so should be pretty safe. 1154de6bbd1dSEric Paris */ 1155de6bbd1dSEric Paris buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); 1156de6bbd1dSEric Paris if (!buf) { 1157b7550787SJoe Perches audit_panic("out of memory for argv string"); 1158de6bbd1dSEric Paris return; 1159de6bbd1dSEric Paris } 1160de6bbd1dSEric Paris 1161d9cfea91SRichard Guy Briggs for (i = 0; i < context->execve.argc; i++) { 1162de6bbd1dSEric Paris len = audit_log_single_execve_arg(context, ab, i, 1163de6bbd1dSEric Paris &len_sent, p, buf); 1164de6bbd1dSEric Paris if (len <= 0) 1165de6bbd1dSEric Paris break; 1166de6bbd1dSEric Paris p += len; 1167de6bbd1dSEric Paris } 1168de6bbd1dSEric Paris kfree(buf); 1169bdf4c48aSPeter Zijlstra } 1170bdf4c48aSPeter Zijlstra 1171a33e6751SAl Viro static void show_special(struct audit_context *context, int *call_panic) 1172f3298dc4SAl Viro { 1173f3298dc4SAl Viro struct audit_buffer *ab; 1174f3298dc4SAl Viro int i; 1175f3298dc4SAl Viro 1176f3298dc4SAl Viro ab = audit_log_start(context, GFP_KERNEL, context->type); 1177f3298dc4SAl Viro if (!ab) 1178f3298dc4SAl Viro return; 1179f3298dc4SAl Viro 1180f3298dc4SAl Viro switch (context->type) { 1181f3298dc4SAl Viro case AUDIT_SOCKETCALL: { 1182f3298dc4SAl Viro int nargs = context->socketcall.nargs; 1183f3298dc4SAl Viro audit_log_format(ab, "nargs=%d", nargs); 1184f3298dc4SAl Viro for (i = 0; i < nargs; i++) 1185f3298dc4SAl Viro audit_log_format(ab, " a%d=%lx", i, 1186f3298dc4SAl Viro context->socketcall.args[i]); 1187f3298dc4SAl Viro break; } 1188a33e6751SAl Viro case AUDIT_IPC: { 1189a33e6751SAl Viro u32 osid = context->ipc.osid; 1190a33e6751SAl Viro 11912570ebbdSAl Viro audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho", 1192cca080d9SEric W. Biederman from_kuid(&init_user_ns, context->ipc.uid), 1193cca080d9SEric W. Biederman from_kgid(&init_user_ns, context->ipc.gid), 1194cca080d9SEric W. Biederman context->ipc.mode); 1195a33e6751SAl Viro if (osid) { 1196a33e6751SAl Viro char *ctx = NULL; 1197a33e6751SAl Viro u32 len; 1198a33e6751SAl Viro if (security_secid_to_secctx(osid, &ctx, &len)) { 1199a33e6751SAl Viro audit_log_format(ab, " osid=%u", osid); 1200a33e6751SAl Viro *call_panic = 1; 1201a33e6751SAl Viro } else { 1202a33e6751SAl Viro audit_log_format(ab, " obj=%s", ctx); 1203a33e6751SAl Viro security_release_secctx(ctx, len); 1204a33e6751SAl Viro } 1205a33e6751SAl Viro } 1206e816f370SAl Viro if (context->ipc.has_perm) { 1207e816f370SAl Viro audit_log_end(ab); 1208e816f370SAl Viro ab = audit_log_start(context, GFP_KERNEL, 1209e816f370SAl Viro AUDIT_IPC_SET_PERM); 12100644ec0cSKees Cook if (unlikely(!ab)) 12110644ec0cSKees Cook return; 1212e816f370SAl Viro audit_log_format(ab, 12132570ebbdSAl Viro "qbytes=%lx ouid=%u ogid=%u mode=%#ho", 1214e816f370SAl Viro context->ipc.qbytes, 1215e816f370SAl Viro context->ipc.perm_uid, 1216e816f370SAl Viro context->ipc.perm_gid, 1217e816f370SAl Viro context->ipc.perm_mode); 1218e816f370SAl Viro } 1219a33e6751SAl Viro break; } 1220564f6993SAl Viro case AUDIT_MQ_OPEN: { 1221564f6993SAl Viro audit_log_format(ab, 1222df0a4283SAl Viro "oflag=0x%x mode=%#ho mq_flags=0x%lx mq_maxmsg=%ld " 1223564f6993SAl Viro "mq_msgsize=%ld mq_curmsgs=%ld", 1224564f6993SAl Viro context->mq_open.oflag, context->mq_open.mode, 1225564f6993SAl Viro context->mq_open.attr.mq_flags, 1226564f6993SAl Viro context->mq_open.attr.mq_maxmsg, 1227564f6993SAl Viro context->mq_open.attr.mq_msgsize, 1228564f6993SAl Viro context->mq_open.attr.mq_curmsgs); 1229564f6993SAl Viro break; } 1230c32c8af4SAl Viro case AUDIT_MQ_SENDRECV: { 1231c32c8af4SAl Viro audit_log_format(ab, 1232c32c8af4SAl Viro "mqdes=%d msg_len=%zd msg_prio=%u " 1233c32c8af4SAl Viro "abs_timeout_sec=%ld abs_timeout_nsec=%ld", 1234c32c8af4SAl Viro context->mq_sendrecv.mqdes, 1235c32c8af4SAl Viro context->mq_sendrecv.msg_len, 1236c32c8af4SAl Viro context->mq_sendrecv.msg_prio, 1237c32c8af4SAl Viro context->mq_sendrecv.abs_timeout.tv_sec, 1238c32c8af4SAl Viro context->mq_sendrecv.abs_timeout.tv_nsec); 1239c32c8af4SAl Viro break; } 124020114f71SAl Viro case AUDIT_MQ_NOTIFY: { 124120114f71SAl Viro audit_log_format(ab, "mqdes=%d sigev_signo=%d", 124220114f71SAl Viro context->mq_notify.mqdes, 124320114f71SAl Viro context->mq_notify.sigev_signo); 124420114f71SAl Viro break; } 12457392906eSAl Viro case AUDIT_MQ_GETSETATTR: { 12467392906eSAl Viro struct mq_attr *attr = &context->mq_getsetattr.mqstat; 12477392906eSAl Viro audit_log_format(ab, 12487392906eSAl Viro "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld " 12497392906eSAl Viro "mq_curmsgs=%ld ", 12507392906eSAl Viro context->mq_getsetattr.mqdes, 12517392906eSAl Viro attr->mq_flags, attr->mq_maxmsg, 12527392906eSAl Viro attr->mq_msgsize, attr->mq_curmsgs); 12537392906eSAl Viro break; } 125457f71a0aSAl Viro case AUDIT_CAPSET: { 125557f71a0aSAl Viro audit_log_format(ab, "pid=%d", context->capset.pid); 125657f71a0aSAl Viro audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable); 125757f71a0aSAl Viro audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted); 125857f71a0aSAl Viro audit_log_cap(ab, "cap_pe", &context->capset.cap.effective); 125957f71a0aSAl Viro break; } 1260120a795dSAl Viro case AUDIT_MMAP: { 1261120a795dSAl Viro audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, 1262120a795dSAl Viro context->mmap.flags); 1263120a795dSAl Viro break; } 1264d9cfea91SRichard Guy Briggs case AUDIT_EXECVE: { 1265d9cfea91SRichard Guy Briggs audit_log_execve_info(context, &ab); 1266d9cfea91SRichard Guy Briggs break; } 1267f3298dc4SAl Viro } 1268f3298dc4SAl Viro audit_log_end(ab); 1269f3298dc4SAl Viro } 1270f3298dc4SAl Viro 12713f1c8250SWilliam Roberts static inline int audit_proctitle_rtrim(char *proctitle, int len) 12723f1c8250SWilliam Roberts { 12733f1c8250SWilliam Roberts char *end = proctitle + len - 1; 12743f1c8250SWilliam Roberts while (end > proctitle && !isprint(*end)) 12753f1c8250SWilliam Roberts end--; 12763f1c8250SWilliam Roberts 12773f1c8250SWilliam Roberts /* catch the case where proctitle is only 1 non-print character */ 12783f1c8250SWilliam Roberts len = end - proctitle + 1; 12793f1c8250SWilliam Roberts len -= isprint(proctitle[len-1]) == 0; 12803f1c8250SWilliam Roberts return len; 12813f1c8250SWilliam Roberts } 12823f1c8250SWilliam Roberts 12833f1c8250SWilliam Roberts static void audit_log_proctitle(struct task_struct *tsk, 12843f1c8250SWilliam Roberts struct audit_context *context) 12853f1c8250SWilliam Roberts { 12863f1c8250SWilliam Roberts int res; 12873f1c8250SWilliam Roberts char *buf; 12883f1c8250SWilliam Roberts char *msg = "(null)"; 12893f1c8250SWilliam Roberts int len = strlen(msg); 12903f1c8250SWilliam Roberts struct audit_buffer *ab; 12913f1c8250SWilliam Roberts 12923f1c8250SWilliam Roberts ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); 12933f1c8250SWilliam Roberts if (!ab) 12943f1c8250SWilliam Roberts return; /* audit_panic or being filtered */ 12953f1c8250SWilliam Roberts 12963f1c8250SWilliam Roberts audit_log_format(ab, "proctitle="); 12973f1c8250SWilliam Roberts 12983f1c8250SWilliam Roberts /* Not cached */ 12993f1c8250SWilliam Roberts if (!context->proctitle.value) { 13003f1c8250SWilliam Roberts buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL); 13013f1c8250SWilliam Roberts if (!buf) 13023f1c8250SWilliam Roberts goto out; 13033f1c8250SWilliam Roberts /* Historically called this from procfs naming */ 13043f1c8250SWilliam Roberts res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN); 13053f1c8250SWilliam Roberts if (res == 0) { 13063f1c8250SWilliam Roberts kfree(buf); 13073f1c8250SWilliam Roberts goto out; 13083f1c8250SWilliam Roberts } 13093f1c8250SWilliam Roberts res = audit_proctitle_rtrim(buf, res); 13103f1c8250SWilliam Roberts if (res == 0) { 13113f1c8250SWilliam Roberts kfree(buf); 13123f1c8250SWilliam Roberts goto out; 13133f1c8250SWilliam Roberts } 13143f1c8250SWilliam Roberts context->proctitle.value = buf; 13153f1c8250SWilliam Roberts context->proctitle.len = res; 13163f1c8250SWilliam Roberts } 13173f1c8250SWilliam Roberts msg = context->proctitle.value; 13183f1c8250SWilliam Roberts len = context->proctitle.len; 13193f1c8250SWilliam Roberts out: 13203f1c8250SWilliam Roberts audit_log_n_untrustedstring(ab, msg, len); 13213f1c8250SWilliam Roberts audit_log_end(ab); 13223f1c8250SWilliam Roberts } 13233f1c8250SWilliam Roberts 1324e495149bSAl Viro static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) 13251da177e4SLinus Torvalds { 13269c7aa6aaSSteve Grubb int i, call_panic = 0; 13271da177e4SLinus Torvalds struct audit_buffer *ab; 13287551ced3SDavid Woodhouse struct audit_aux_data *aux; 13295195d8e2SEric Paris struct audit_names *n; 13301da177e4SLinus Torvalds 1331e495149bSAl Viro /* tsk == current */ 13323f2792ffSAl Viro context->personality = tsk->personality; 1333e495149bSAl Viro 1334e495149bSAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); 13351da177e4SLinus Torvalds if (!ab) 13361da177e4SLinus Torvalds return; /* audit_panic has been called */ 1337bccf6ae0SDavid Woodhouse audit_log_format(ab, "arch=%x syscall=%d", 1338bccf6ae0SDavid Woodhouse context->arch, context->major); 13391da177e4SLinus Torvalds if (context->personality != PER_LINUX) 13401da177e4SLinus Torvalds audit_log_format(ab, " per=%lx", context->personality); 13411da177e4SLinus Torvalds if (context->return_valid) 13422fd6f58bS audit_log_format(ab, " success=%s exit=%ld", 13432fd6f58bS (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", 13442fd6f58bS context->return_code); 1345eb84a20eSAlan Cox 13461da177e4SLinus Torvalds audit_log_format(ab, 1347e23eb920SPeter Moody " a0=%lx a1=%lx a2=%lx a3=%lx items=%d", 13481da177e4SLinus Torvalds context->argv[0], 13491da177e4SLinus Torvalds context->argv[1], 13501da177e4SLinus Torvalds context->argv[2], 13511da177e4SLinus Torvalds context->argv[3], 1352e23eb920SPeter Moody context->name_count); 1353eb84a20eSAlan Cox 1354e495149bSAl Viro audit_log_task_info(ab, tsk); 13559d960985SEric Paris audit_log_key(ab, context->filterkey); 13561da177e4SLinus Torvalds audit_log_end(ab); 13571da177e4SLinus Torvalds 13587551ced3SDavid Woodhouse for (aux = context->aux; aux; aux = aux->next) { 1359c0404993SSteve Grubb 1360e495149bSAl Viro ab = audit_log_start(context, GFP_KERNEL, aux->type); 13611da177e4SLinus Torvalds if (!ab) 13621da177e4SLinus Torvalds continue; /* audit_panic has been called */ 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds switch (aux->type) { 136520ca73bcSGeorge C. Wilson 13663fc689e9SEric Paris case AUDIT_BPRM_FCAPS: { 13673fc689e9SEric Paris struct audit_aux_data_bprm_fcaps *axs = (void *)aux; 13683fc689e9SEric Paris audit_log_format(ab, "fver=%x", axs->fcap_ver); 13693fc689e9SEric Paris audit_log_cap(ab, "fp", &axs->fcap.permitted); 13703fc689e9SEric Paris audit_log_cap(ab, "fi", &axs->fcap.inheritable); 13713fc689e9SEric Paris audit_log_format(ab, " fe=%d", axs->fcap.fE); 13723fc689e9SEric Paris audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted); 13733fc689e9SEric Paris audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable); 13743fc689e9SEric Paris audit_log_cap(ab, "old_pe", &axs->old_pcap.effective); 13753fc689e9SEric Paris audit_log_cap(ab, "new_pp", &axs->new_pcap.permitted); 13763fc689e9SEric Paris audit_log_cap(ab, "new_pi", &axs->new_pcap.inheritable); 13773fc689e9SEric Paris audit_log_cap(ab, "new_pe", &axs->new_pcap.effective); 13783fc689e9SEric Paris break; } 13793fc689e9SEric Paris 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds audit_log_end(ab); 13821da177e4SLinus Torvalds } 13831da177e4SLinus Torvalds 1384f3298dc4SAl Viro if (context->type) 1385a33e6751SAl Viro show_special(context, &call_panic); 1386f3298dc4SAl Viro 1387157cf649SAl Viro if (context->fds[0] >= 0) { 1388157cf649SAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR); 1389157cf649SAl Viro if (ab) { 1390157cf649SAl Viro audit_log_format(ab, "fd0=%d fd1=%d", 1391157cf649SAl Viro context->fds[0], context->fds[1]); 1392157cf649SAl Viro audit_log_end(ab); 1393157cf649SAl Viro } 1394157cf649SAl Viro } 1395157cf649SAl Viro 13964f6b434fSAl Viro if (context->sockaddr_len) { 13974f6b434fSAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR); 13984f6b434fSAl Viro if (ab) { 13994f6b434fSAl Viro audit_log_format(ab, "saddr="); 14004f6b434fSAl Viro audit_log_n_hex(ab, (void *)context->sockaddr, 14014f6b434fSAl Viro context->sockaddr_len); 14024f6b434fSAl Viro audit_log_end(ab); 14034f6b434fSAl Viro } 14044f6b434fSAl Viro } 14054f6b434fSAl Viro 1406e54dc243SAmy Griffis for (aux = context->aux_pids; aux; aux = aux->next) { 1407e54dc243SAmy Griffis struct audit_aux_data_pids *axs = (void *)aux; 1408e54dc243SAmy Griffis 1409e54dc243SAmy Griffis for (i = 0; i < axs->pid_count; i++) 1410e54dc243SAmy Griffis if (audit_log_pid_context(context, axs->target_pid[i], 1411c2a7780eSEric Paris axs->target_auid[i], 1412c2a7780eSEric Paris axs->target_uid[i], 14134746ec5bSEric Paris axs->target_sessionid[i], 1414c2a7780eSEric Paris axs->target_sid[i], 1415c2a7780eSEric Paris axs->target_comm[i])) 1416e54dc243SAmy Griffis call_panic = 1; 1417a5cb013dSAl Viro } 1418e54dc243SAmy Griffis 1419e54dc243SAmy Griffis if (context->target_pid && 1420e54dc243SAmy Griffis audit_log_pid_context(context, context->target_pid, 1421c2a7780eSEric Paris context->target_auid, context->target_uid, 14224746ec5bSEric Paris context->target_sessionid, 1423c2a7780eSEric Paris context->target_sid, context->target_comm)) 1424e54dc243SAmy Griffis call_panic = 1; 1425a5cb013dSAl Viro 142644707fdfSJan Blunck if (context->pwd.dentry && context->pwd.mnt) { 1427e495149bSAl Viro ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); 14288f37d47cSDavid Woodhouse if (ab) { 142944707fdfSJan Blunck audit_log_d_path(ab, " cwd=", &context->pwd); 14308f37d47cSDavid Woodhouse audit_log_end(ab); 14318f37d47cSDavid Woodhouse } 14328f37d47cSDavid Woodhouse } 143373241cccSAmy Griffis 14345195d8e2SEric Paris i = 0; 143579f6530cSJeff Layton list_for_each_entry(n, &context->names_list, list) { 143679f6530cSJeff Layton if (n->hidden) 143779f6530cSJeff Layton continue; 1438b24a30a7SEric Paris audit_log_name(context, n, NULL, i++, &call_panic); 143979f6530cSJeff Layton } 1440c0641f28SEric Paris 14413f1c8250SWilliam Roberts audit_log_proctitle(tsk, context); 14423f1c8250SWilliam Roberts 1443c0641f28SEric Paris /* Send end of event record to help user space know we are finished */ 1444c0641f28SEric Paris ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); 1445c0641f28SEric Paris if (ab) 1446c0641f28SEric Paris audit_log_end(ab); 14471b50eed9SSteve Grubb if (call_panic) 14481b50eed9SSteve Grubb audit_panic("error converting sid to string"); 14491da177e4SLinus Torvalds } 14501da177e4SLinus Torvalds 1451b0dd25a8SRandy Dunlap /** 1452b0dd25a8SRandy Dunlap * audit_free - free a per-task audit context 1453b0dd25a8SRandy Dunlap * @tsk: task whose audit context block to free 1454b0dd25a8SRandy Dunlap * 1455fa84cb93SAl Viro * Called from copy_process and do_exit 1456b0dd25a8SRandy Dunlap */ 1457a4ff8dbaSEric Paris void __audit_free(struct task_struct *tsk) 14581da177e4SLinus Torvalds { 14591da177e4SLinus Torvalds struct audit_context *context; 14601da177e4SLinus Torvalds 14614a3eb726SRichard Guy Briggs context = audit_take_context(tsk, 0, 0); 146256179a6eSEric Paris if (!context) 14631da177e4SLinus Torvalds return; 14641da177e4SLinus Torvalds 14651da177e4SLinus Torvalds /* Check for system calls that do not go through the exit 1466f5561964SDavid Woodhouse * function (e.g., exit_group), then free context block. 1467f5561964SDavid Woodhouse * We use GFP_ATOMIC here because we might be doing this 1468f5561964SDavid Woodhouse * in the context of the idle thread */ 1469e495149bSAl Viro /* that can happen only if we are called from do_exit() */ 14700590b933SAl Viro if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) 1471e495149bSAl Viro audit_log_exit(context, tsk); 1472916d7576SAl Viro if (!list_empty(&context->killed_trees)) 1473916d7576SAl Viro audit_kill_trees(&context->killed_trees); 14741da177e4SLinus Torvalds 14751da177e4SLinus Torvalds audit_free_context(context); 14761da177e4SLinus Torvalds } 14771da177e4SLinus Torvalds 1478b0dd25a8SRandy Dunlap /** 1479b0dd25a8SRandy Dunlap * audit_syscall_entry - fill in an audit record at syscall entry 1480b0dd25a8SRandy Dunlap * @major: major syscall type (function) 1481b0dd25a8SRandy Dunlap * @a1: additional syscall register 1 1482b0dd25a8SRandy Dunlap * @a2: additional syscall register 2 1483b0dd25a8SRandy Dunlap * @a3: additional syscall register 3 1484b0dd25a8SRandy Dunlap * @a4: additional syscall register 4 1485b0dd25a8SRandy Dunlap * 1486b0dd25a8SRandy Dunlap * Fill in audit context at syscall entry. This only happens if the 14871da177e4SLinus Torvalds * audit context was created when the task was created and the state or 14881da177e4SLinus Torvalds * filters demand the audit context be built. If the state from the 14891da177e4SLinus Torvalds * per-task filter or from the per-syscall filter is AUDIT_RECORD_CONTEXT, 14901da177e4SLinus Torvalds * then the record will be written at syscall exit time (otherwise, it 14911da177e4SLinus Torvalds * will only be written if another part of the kernel requests that it 1492b0dd25a8SRandy Dunlap * be written). 1493b0dd25a8SRandy Dunlap */ 1494b4f0d375SRichard Guy Briggs void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, 14951da177e4SLinus Torvalds unsigned long a3, unsigned long a4) 14961da177e4SLinus Torvalds { 14975411be59SAl Viro struct task_struct *tsk = current; 14981da177e4SLinus Torvalds struct audit_context *context = tsk->audit_context; 14991da177e4SLinus Torvalds enum audit_state state; 15001da177e4SLinus Torvalds 150156179a6eSEric Paris if (!context) 150286a1c34aSRoland McGrath return; 15031da177e4SLinus Torvalds 15041da177e4SLinus Torvalds BUG_ON(context->in_syscall || context->name_count); 15051da177e4SLinus Torvalds 15061da177e4SLinus Torvalds if (!audit_enabled) 15071da177e4SLinus Torvalds return; 15081da177e4SLinus Torvalds 15094a99854cSRichard Guy Briggs context->arch = syscall_get_arch(); 15101da177e4SLinus Torvalds context->major = major; 15111da177e4SLinus Torvalds context->argv[0] = a1; 15121da177e4SLinus Torvalds context->argv[1] = a2; 15131da177e4SLinus Torvalds context->argv[2] = a3; 15141da177e4SLinus Torvalds context->argv[3] = a4; 15151da177e4SLinus Torvalds 15161da177e4SLinus Torvalds state = context->state; 1517d51374adSAl Viro context->dummy = !audit_n_rules; 15180590b933SAl Viro if (!context->dummy && state == AUDIT_BUILD_CONTEXT) { 15190590b933SAl Viro context->prio = 0; 15200f45aa18SDavid Woodhouse state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); 15210590b933SAl Viro } 152256179a6eSEric Paris if (state == AUDIT_DISABLED) 15231da177e4SLinus Torvalds return; 15241da177e4SLinus Torvalds 1525ce625a80SDavid Woodhouse context->serial = 0; 15261da177e4SLinus Torvalds context->ctime = CURRENT_TIME; 15271da177e4SLinus Torvalds context->in_syscall = 1; 15280590b933SAl Viro context->current_state = state; 1529419c58f1SAlexander Viro context->ppid = 0; 15301da177e4SLinus Torvalds } 15311da177e4SLinus Torvalds 1532b0dd25a8SRandy Dunlap /** 1533b0dd25a8SRandy Dunlap * audit_syscall_exit - deallocate audit context after a system call 153442ae610cSRandy Dunlap * @success: success value of the syscall 153542ae610cSRandy Dunlap * @return_code: return value of the syscall 1536b0dd25a8SRandy Dunlap * 1537b0dd25a8SRandy Dunlap * Tear down after system call. If the audit context has been marked as 15381da177e4SLinus Torvalds * auditable (either because of the AUDIT_RECORD_CONTEXT state from 153942ae610cSRandy Dunlap * filtering, or because some other part of the kernel wrote an audit 15401da177e4SLinus Torvalds * message), then write out the syscall information. In call cases, 1541b0dd25a8SRandy Dunlap * free the names stored from getname(). 1542b0dd25a8SRandy Dunlap */ 1543d7e7528bSEric Paris void __audit_syscall_exit(int success, long return_code) 15441da177e4SLinus Torvalds { 15455411be59SAl Viro struct task_struct *tsk = current; 15461da177e4SLinus Torvalds struct audit_context *context; 15471da177e4SLinus Torvalds 1548d7e7528bSEric Paris if (success) 1549d7e7528bSEric Paris success = AUDITSC_SUCCESS; 1550d7e7528bSEric Paris else 1551d7e7528bSEric Paris success = AUDITSC_FAILURE; 15521da177e4SLinus Torvalds 15534a3eb726SRichard Guy Briggs context = audit_take_context(tsk, success, return_code); 155456179a6eSEric Paris if (!context) 155597e94c45SAl Viro return; 15561da177e4SLinus Torvalds 15570590b933SAl Viro if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) 1558e495149bSAl Viro audit_log_exit(context, tsk); 15591da177e4SLinus Torvalds 15601da177e4SLinus Torvalds context->in_syscall = 0; 15610590b933SAl Viro context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; 15622fd6f58bS 1563916d7576SAl Viro if (!list_empty(&context->killed_trees)) 1564916d7576SAl Viro audit_kill_trees(&context->killed_trees); 1565916d7576SAl Viro 15661da177e4SLinus Torvalds audit_free_names(context); 156774c3cbe3SAl Viro unroll_tree_refs(context, NULL, 0); 15681da177e4SLinus Torvalds audit_free_aux(context); 1569e54dc243SAmy Griffis context->aux = NULL; 1570e54dc243SAmy Griffis context->aux_pids = NULL; 1571a5cb013dSAl Viro context->target_pid = 0; 1572e54dc243SAmy Griffis context->target_sid = 0; 15734f6b434fSAl Viro context->sockaddr_len = 0; 1574f3298dc4SAl Viro context->type = 0; 1575157cf649SAl Viro context->fds[0] = -1; 1576e048e02cSAl Viro if (context->state != AUDIT_RECORD_CONTEXT) { 15775adc8a6aSAmy Griffis kfree(context->filterkey); 15785adc8a6aSAmy Griffis context->filterkey = NULL; 1579e048e02cSAl Viro } 15801da177e4SLinus Torvalds tsk->audit_context = context; 15811da177e4SLinus Torvalds } 15821da177e4SLinus Torvalds 158374c3cbe3SAl Viro static inline void handle_one(const struct inode *inode) 158474c3cbe3SAl Viro { 158574c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE 158674c3cbe3SAl Viro struct audit_context *context; 158774c3cbe3SAl Viro struct audit_tree_refs *p; 158874c3cbe3SAl Viro struct audit_chunk *chunk; 158974c3cbe3SAl Viro int count; 1590e61ce867SEric Paris if (likely(hlist_empty(&inode->i_fsnotify_marks))) 159174c3cbe3SAl Viro return; 159274c3cbe3SAl Viro context = current->audit_context; 159374c3cbe3SAl Viro p = context->trees; 159474c3cbe3SAl Viro count = context->tree_count; 159574c3cbe3SAl Viro rcu_read_lock(); 159674c3cbe3SAl Viro chunk = audit_tree_lookup(inode); 159774c3cbe3SAl Viro rcu_read_unlock(); 159874c3cbe3SAl Viro if (!chunk) 159974c3cbe3SAl Viro return; 160074c3cbe3SAl Viro if (likely(put_tree_ref(context, chunk))) 160174c3cbe3SAl Viro return; 160274c3cbe3SAl Viro if (unlikely(!grow_tree_refs(context))) { 1603f952d10fSRichard Guy Briggs pr_warn("out of memory, audit has lost a tree reference\n"); 160474c3cbe3SAl Viro audit_set_auditable(context); 160574c3cbe3SAl Viro audit_put_chunk(chunk); 160674c3cbe3SAl Viro unroll_tree_refs(context, p, count); 160774c3cbe3SAl Viro return; 160874c3cbe3SAl Viro } 160974c3cbe3SAl Viro put_tree_ref(context, chunk); 161074c3cbe3SAl Viro #endif 161174c3cbe3SAl Viro } 161274c3cbe3SAl Viro 161374c3cbe3SAl Viro static void handle_path(const struct dentry *dentry) 161474c3cbe3SAl Viro { 161574c3cbe3SAl Viro #ifdef CONFIG_AUDIT_TREE 161674c3cbe3SAl Viro struct audit_context *context; 161774c3cbe3SAl Viro struct audit_tree_refs *p; 161874c3cbe3SAl Viro const struct dentry *d, *parent; 161974c3cbe3SAl Viro struct audit_chunk *drop; 162074c3cbe3SAl Viro unsigned long seq; 162174c3cbe3SAl Viro int count; 162274c3cbe3SAl Viro 162374c3cbe3SAl Viro context = current->audit_context; 162474c3cbe3SAl Viro p = context->trees; 162574c3cbe3SAl Viro count = context->tree_count; 162674c3cbe3SAl Viro retry: 162774c3cbe3SAl Viro drop = NULL; 162874c3cbe3SAl Viro d = dentry; 162974c3cbe3SAl Viro rcu_read_lock(); 163074c3cbe3SAl Viro seq = read_seqbegin(&rename_lock); 163174c3cbe3SAl Viro for(;;) { 16323b362157SDavid Howells struct inode *inode = d_backing_inode(d); 1633e61ce867SEric Paris if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_marks))) { 163474c3cbe3SAl Viro struct audit_chunk *chunk; 163574c3cbe3SAl Viro chunk = audit_tree_lookup(inode); 163674c3cbe3SAl Viro if (chunk) { 163774c3cbe3SAl Viro if (unlikely(!put_tree_ref(context, chunk))) { 163874c3cbe3SAl Viro drop = chunk; 163974c3cbe3SAl Viro break; 164074c3cbe3SAl Viro } 164174c3cbe3SAl Viro } 164274c3cbe3SAl Viro } 164374c3cbe3SAl Viro parent = d->d_parent; 164474c3cbe3SAl Viro if (parent == d) 164574c3cbe3SAl Viro break; 164674c3cbe3SAl Viro d = parent; 164774c3cbe3SAl Viro } 164874c3cbe3SAl Viro if (unlikely(read_seqretry(&rename_lock, seq) || drop)) { /* in this order */ 164974c3cbe3SAl Viro rcu_read_unlock(); 165074c3cbe3SAl Viro if (!drop) { 165174c3cbe3SAl Viro /* just a race with rename */ 165274c3cbe3SAl Viro unroll_tree_refs(context, p, count); 165374c3cbe3SAl Viro goto retry; 165474c3cbe3SAl Viro } 165574c3cbe3SAl Viro audit_put_chunk(drop); 165674c3cbe3SAl Viro if (grow_tree_refs(context)) { 165774c3cbe3SAl Viro /* OK, got more space */ 165874c3cbe3SAl Viro unroll_tree_refs(context, p, count); 165974c3cbe3SAl Viro goto retry; 166074c3cbe3SAl Viro } 166174c3cbe3SAl Viro /* too bad */ 1662f952d10fSRichard Guy Briggs pr_warn("out of memory, audit has lost a tree reference\n"); 166374c3cbe3SAl Viro unroll_tree_refs(context, p, count); 166474c3cbe3SAl Viro audit_set_auditable(context); 166574c3cbe3SAl Viro return; 166674c3cbe3SAl Viro } 166774c3cbe3SAl Viro rcu_read_unlock(); 166874c3cbe3SAl Viro #endif 166974c3cbe3SAl Viro } 167074c3cbe3SAl Viro 167178e2e802SJeff Layton static struct audit_names *audit_alloc_name(struct audit_context *context, 167278e2e802SJeff Layton unsigned char type) 16735195d8e2SEric Paris { 16745195d8e2SEric Paris struct audit_names *aname; 16755195d8e2SEric Paris 16765195d8e2SEric Paris if (context->name_count < AUDIT_NAMES) { 16775195d8e2SEric Paris aname = &context->preallocated_names[context->name_count]; 16785195d8e2SEric Paris memset(aname, 0, sizeof(*aname)); 16795195d8e2SEric Paris } else { 16805195d8e2SEric Paris aname = kzalloc(sizeof(*aname), GFP_NOFS); 16815195d8e2SEric Paris if (!aname) 16825195d8e2SEric Paris return NULL; 16835195d8e2SEric Paris aname->should_free = true; 16845195d8e2SEric Paris } 16855195d8e2SEric Paris 168684cb777eSRichard Guy Briggs aname->ino = AUDIT_INO_UNSET; 168778e2e802SJeff Layton aname->type = type; 16885195d8e2SEric Paris list_add_tail(&aname->list, &context->names_list); 16895195d8e2SEric Paris 16905195d8e2SEric Paris context->name_count++; 16915195d8e2SEric Paris return aname; 16925195d8e2SEric Paris } 16935195d8e2SEric Paris 1694b0dd25a8SRandy Dunlap /** 16957ac86265SJeff Layton * audit_reusename - fill out filename with info from existing entry 16967ac86265SJeff Layton * @uptr: userland ptr to pathname 16977ac86265SJeff Layton * 16987ac86265SJeff Layton * Search the audit_names list for the current audit context. If there is an 16997ac86265SJeff Layton * existing entry with a matching "uptr" then return the filename 17007ac86265SJeff Layton * associated with that audit_name. If not, return NULL. 17017ac86265SJeff Layton */ 17027ac86265SJeff Layton struct filename * 17037ac86265SJeff Layton __audit_reusename(const __user char *uptr) 17047ac86265SJeff Layton { 17057ac86265SJeff Layton struct audit_context *context = current->audit_context; 17067ac86265SJeff Layton struct audit_names *n; 17077ac86265SJeff Layton 17087ac86265SJeff Layton list_for_each_entry(n, &context->names_list, list) { 17097ac86265SJeff Layton if (!n->name) 17107ac86265SJeff Layton continue; 171155422d0bSPaul Moore if (n->name->uptr == uptr) { 171255422d0bSPaul Moore n->name->refcnt++; 17137ac86265SJeff Layton return n->name; 17147ac86265SJeff Layton } 171555422d0bSPaul Moore } 17167ac86265SJeff Layton return NULL; 17177ac86265SJeff Layton } 17187ac86265SJeff Layton 17197ac86265SJeff Layton /** 1720b0dd25a8SRandy Dunlap * audit_getname - add a name to the list 1721b0dd25a8SRandy Dunlap * @name: name to add 1722b0dd25a8SRandy Dunlap * 1723b0dd25a8SRandy Dunlap * Add a name to the list of audit names for this context. 1724b0dd25a8SRandy Dunlap * Called from fs/namei.c:getname(). 1725b0dd25a8SRandy Dunlap */ 172691a27b2aSJeff Layton void __audit_getname(struct filename *name) 17271da177e4SLinus Torvalds { 17281da177e4SLinus Torvalds struct audit_context *context = current->audit_context; 17295195d8e2SEric Paris struct audit_names *n; 17301da177e4SLinus Torvalds 173155422d0bSPaul Moore if (!context->in_syscall) 17321da177e4SLinus Torvalds return; 173391a27b2aSJeff Layton 173478e2e802SJeff Layton n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); 17355195d8e2SEric Paris if (!n) 17365195d8e2SEric Paris return; 17375195d8e2SEric Paris 17385195d8e2SEric Paris n->name = name; 17395195d8e2SEric Paris n->name_len = AUDIT_NAME_FULL; 1740adb5c247SJeff Layton name->aname = n; 174155422d0bSPaul Moore name->refcnt++; 17425195d8e2SEric Paris 1743f7ad3c6bSMiklos Szeredi if (!context->pwd.dentry) 1744f7ad3c6bSMiklos Szeredi get_fs_pwd(current->fs, &context->pwd); 17451da177e4SLinus Torvalds } 17461da177e4SLinus Torvalds 1747b0dd25a8SRandy Dunlap /** 1748bfcec708SJeff Layton * __audit_inode - store the inode and device from a lookup 1749b0dd25a8SRandy Dunlap * @name: name being audited 1750481968f4SRandy Dunlap * @dentry: dentry being audited 175179f6530cSJeff Layton * @flags: attributes for this particular entry 1752b0dd25a8SRandy Dunlap */ 1753adb5c247SJeff Layton void __audit_inode(struct filename *name, const struct dentry *dentry, 175479f6530cSJeff Layton unsigned int flags) 17551da177e4SLinus Torvalds { 17561da177e4SLinus Torvalds struct audit_context *context = current->audit_context; 17573b362157SDavid Howells const struct inode *inode = d_backing_inode(dentry); 17585195d8e2SEric Paris struct audit_names *n; 175979f6530cSJeff Layton bool parent = flags & AUDIT_INODE_PARENT; 17601da177e4SLinus Torvalds 17611da177e4SLinus Torvalds if (!context->in_syscall) 17621da177e4SLinus Torvalds return; 17635195d8e2SEric Paris 17649cec9d68SJeff Layton if (!name) 17659cec9d68SJeff Layton goto out_alloc; 17669cec9d68SJeff Layton 1767adb5c247SJeff Layton /* 1768adb5c247SJeff Layton * If we have a pointer to an audit_names entry already, then we can 1769adb5c247SJeff Layton * just use it directly if the type is correct. 1770adb5c247SJeff Layton */ 1771adb5c247SJeff Layton n = name->aname; 1772adb5c247SJeff Layton if (n) { 1773adb5c247SJeff Layton if (parent) { 1774adb5c247SJeff Layton if (n->type == AUDIT_TYPE_PARENT || 1775adb5c247SJeff Layton n->type == AUDIT_TYPE_UNKNOWN) 1776adb5c247SJeff Layton goto out; 1777adb5c247SJeff Layton } else { 1778adb5c247SJeff Layton if (n->type != AUDIT_TYPE_PARENT) 1779adb5c247SJeff Layton goto out; 1780adb5c247SJeff Layton } 1781adb5c247SJeff Layton } 1782adb5c247SJeff Layton 17835195d8e2SEric Paris list_for_each_entry_reverse(n, &context->names_list, list) { 178457c59f58SPaul Moore if (n->ino) { 178557c59f58SPaul Moore /* valid inode number, use that for the comparison */ 178657c59f58SPaul Moore if (n->ino != inode->i_ino || 178757c59f58SPaul Moore n->dev != inode->i_sb->s_dev) 178857c59f58SPaul Moore continue; 178957c59f58SPaul Moore } else if (n->name) { 179057c59f58SPaul Moore /* inode number has not been set, check the name */ 179157c59f58SPaul Moore if (strcmp(n->name->name, name->name)) 179257c59f58SPaul Moore continue; 179357c59f58SPaul Moore } else 179457c59f58SPaul Moore /* no inode and no name (?!) ... this is odd ... */ 1795bfcec708SJeff Layton continue; 1796bfcec708SJeff Layton 1797bfcec708SJeff Layton /* match the correct record type */ 1798bfcec708SJeff Layton if (parent) { 1799bfcec708SJeff Layton if (n->type == AUDIT_TYPE_PARENT || 1800bfcec708SJeff Layton n->type == AUDIT_TYPE_UNKNOWN) 18015195d8e2SEric Paris goto out; 1802bfcec708SJeff Layton } else { 1803bfcec708SJeff Layton if (n->type != AUDIT_TYPE_PARENT) 1804bfcec708SJeff Layton goto out; 1805bfcec708SJeff Layton } 18061da177e4SLinus Torvalds } 18075195d8e2SEric Paris 18089cec9d68SJeff Layton out_alloc: 18094a928436SPaul Moore /* unable to find an entry with both a matching name and type */ 18104a928436SPaul Moore n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); 18115195d8e2SEric Paris if (!n) 18125195d8e2SEric Paris return; 1813fcf22d82SPaul Moore if (name) { 1814fd3522fdSPaul Moore n->name = name; 181555422d0bSPaul Moore name->refcnt++; 1816fcf22d82SPaul Moore } 18174a928436SPaul Moore 18185195d8e2SEric Paris out: 1819bfcec708SJeff Layton if (parent) { 182091a27b2aSJeff Layton n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; 1821bfcec708SJeff Layton n->type = AUDIT_TYPE_PARENT; 182279f6530cSJeff Layton if (flags & AUDIT_INODE_HIDDEN) 182379f6530cSJeff Layton n->hidden = true; 1824bfcec708SJeff Layton } else { 1825bfcec708SJeff Layton n->name_len = AUDIT_NAME_FULL; 1826bfcec708SJeff Layton n->type = AUDIT_TYPE_NORMAL; 1827bfcec708SJeff Layton } 182874c3cbe3SAl Viro handle_path(dentry); 18295195d8e2SEric Paris audit_copy_inode(n, dentry, inode); 183073241cccSAmy Griffis } 183173241cccSAmy Griffis 18329f45f5bfSAl Viro void __audit_file(const struct file *file) 18339f45f5bfSAl Viro { 18349f45f5bfSAl Viro __audit_inode(NULL, file->f_path.dentry, 0); 18359f45f5bfSAl Viro } 18369f45f5bfSAl Viro 183773241cccSAmy Griffis /** 1838c43a25abSJeff Layton * __audit_inode_child - collect inode info for created/removed objects 183973d3ec5aSAmy Griffis * @parent: inode of dentry parent 1840c43a25abSJeff Layton * @dentry: dentry being audited 18414fa6b5ecSJeff Layton * @type: AUDIT_TYPE_* value that we're looking for 184273241cccSAmy Griffis * 184373241cccSAmy Griffis * For syscalls that create or remove filesystem objects, audit_inode 184473241cccSAmy Griffis * can only collect information for the filesystem object's parent. 184573241cccSAmy Griffis * This call updates the audit context with the child's information. 184673241cccSAmy Griffis * Syscalls that create a new filesystem object must be hooked after 184773241cccSAmy Griffis * the object is created. Syscalls that remove a filesystem object 184873241cccSAmy Griffis * must be hooked prior, in order to capture the target inode during 184973241cccSAmy Griffis * unsuccessful attempts. 185073241cccSAmy Griffis */ 1851c43a25abSJeff Layton void __audit_inode_child(const struct inode *parent, 18524fa6b5ecSJeff Layton const struct dentry *dentry, 18534fa6b5ecSJeff Layton const unsigned char type) 185473241cccSAmy Griffis { 185573241cccSAmy Griffis struct audit_context *context = current->audit_context; 18563b362157SDavid Howells const struct inode *inode = d_backing_inode(dentry); 1857cccc6bbaSAl Viro const char *dname = dentry->d_name.name; 18584fa6b5ecSJeff Layton struct audit_names *n, *found_parent = NULL, *found_child = NULL; 185973241cccSAmy Griffis 186073241cccSAmy Griffis if (!context->in_syscall) 186173241cccSAmy Griffis return; 186273241cccSAmy Griffis 186374c3cbe3SAl Viro if (inode) 186474c3cbe3SAl Viro handle_one(inode); 186573241cccSAmy Griffis 18664fa6b5ecSJeff Layton /* look for a parent entry first */ 18675195d8e2SEric Paris list_for_each_entry(n, &context->names_list, list) { 186857c59f58SPaul Moore if (!n->name || 186957c59f58SPaul Moore (n->type != AUDIT_TYPE_PARENT && 187057c59f58SPaul Moore n->type != AUDIT_TYPE_UNKNOWN)) 187173241cccSAmy Griffis continue; 187273241cccSAmy Griffis 187357c59f58SPaul Moore if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev && 187457c59f58SPaul Moore !audit_compare_dname_path(dname, 187557c59f58SPaul Moore n->name->name, n->name_len)) { 187657c59f58SPaul Moore if (n->type == AUDIT_TYPE_UNKNOWN) 187757c59f58SPaul Moore n->type = AUDIT_TYPE_PARENT; 18784fa6b5ecSJeff Layton found_parent = n; 18794fa6b5ecSJeff Layton break; 18809c937dccSAmy Griffis } 188173241cccSAmy Griffis } 188273241cccSAmy Griffis 18834fa6b5ecSJeff Layton /* is there a matching child entry? */ 18845195d8e2SEric Paris list_for_each_entry(n, &context->names_list, list) { 18854fa6b5ecSJeff Layton /* can only match entries that have a name */ 188657c59f58SPaul Moore if (!n->name || 188757c59f58SPaul Moore (n->type != type && n->type != AUDIT_TYPE_UNKNOWN)) 18884fa6b5ecSJeff Layton continue; 18894fa6b5ecSJeff Layton 189091a27b2aSJeff Layton if (!strcmp(dname, n->name->name) || 189191a27b2aSJeff Layton !audit_compare_dname_path(dname, n->name->name, 18924fa6b5ecSJeff Layton found_parent ? 18934fa6b5ecSJeff Layton found_parent->name_len : 1894e3d6b07bSJeff Layton AUDIT_NAME_FULL)) { 189557c59f58SPaul Moore if (n->type == AUDIT_TYPE_UNKNOWN) 189657c59f58SPaul Moore n->type = type; 18974fa6b5ecSJeff Layton found_child = n; 18984fa6b5ecSJeff Layton break; 1899ac9910ceSSteve Grubb } 19005712e88fSAmy Griffis } 19015712e88fSAmy Griffis 19025712e88fSAmy Griffis if (!found_parent) { 19034fa6b5ecSJeff Layton /* create a new, "anonymous" parent record */ 19044fa6b5ecSJeff Layton n = audit_alloc_name(context, AUDIT_TYPE_PARENT); 19055195d8e2SEric Paris if (!n) 19065712e88fSAmy Griffis return; 19075195d8e2SEric Paris audit_copy_inode(n, NULL, parent); 190873d3ec5aSAmy Griffis } 19095712e88fSAmy Griffis 19105712e88fSAmy Griffis if (!found_child) { 19114fa6b5ecSJeff Layton found_child = audit_alloc_name(context, type); 19124fa6b5ecSJeff Layton if (!found_child) 19135712e88fSAmy Griffis return; 19145712e88fSAmy Griffis 19155712e88fSAmy Griffis /* Re-use the name belonging to the slot for a matching parent 19165712e88fSAmy Griffis * directory. All names for this context are relinquished in 19175712e88fSAmy Griffis * audit_free_names() */ 19185712e88fSAmy Griffis if (found_parent) { 19194fa6b5ecSJeff Layton found_child->name = found_parent->name; 19204fa6b5ecSJeff Layton found_child->name_len = AUDIT_NAME_FULL; 192155422d0bSPaul Moore found_child->name->refcnt++; 19225712e88fSAmy Griffis } 19234fa6b5ecSJeff Layton } 192457c59f58SPaul Moore 19255712e88fSAmy Griffis if (inode) 19264fa6b5ecSJeff Layton audit_copy_inode(found_child, dentry, inode); 19274fa6b5ecSJeff Layton else 192884cb777eSRichard Guy Briggs found_child->ino = AUDIT_INO_UNSET; 19293e2efce0SAmy Griffis } 193050e437d5STrond Myklebust EXPORT_SYMBOL_GPL(__audit_inode_child); 19313e2efce0SAmy Griffis 19323e2efce0SAmy Griffis /** 1933b0dd25a8SRandy Dunlap * auditsc_get_stamp - get local copies of audit_context values 1934b0dd25a8SRandy Dunlap * @ctx: audit_context for the task 1935b0dd25a8SRandy Dunlap * @t: timespec to store time recorded in the audit_context 1936b0dd25a8SRandy Dunlap * @serial: serial value that is recorded in the audit_context 1937b0dd25a8SRandy Dunlap * 1938b0dd25a8SRandy Dunlap * Also sets the context as auditable. 1939b0dd25a8SRandy Dunlap */ 194048887e63SAl Viro int auditsc_get_stamp(struct audit_context *ctx, 1941d812ddbbSSteve Grubb struct timespec *t, unsigned int *serial) 19421da177e4SLinus Torvalds { 194348887e63SAl Viro if (!ctx->in_syscall) 194448887e63SAl Viro return 0; 1945ce625a80SDavid Woodhouse if (!ctx->serial) 1946ce625a80SDavid Woodhouse ctx->serial = audit_serial(); 19471da177e4SLinus Torvalds t->tv_sec = ctx->ctime.tv_sec; 19481da177e4SLinus Torvalds t->tv_nsec = ctx->ctime.tv_nsec; 19491da177e4SLinus Torvalds *serial = ctx->serial; 19500590b933SAl Viro if (!ctx->prio) { 19510590b933SAl Viro ctx->prio = 1; 19520590b933SAl Viro ctx->current_state = AUDIT_RECORD_CONTEXT; 19530590b933SAl Viro } 195448887e63SAl Viro return 1; 19551da177e4SLinus Torvalds } 19561da177e4SLinus Torvalds 19574746ec5bSEric Paris /* global counter which is incremented every time something logs in */ 19584746ec5bSEric Paris static atomic_t session_id = ATOMIC_INIT(0); 19594746ec5bSEric Paris 1960da0a6104SEric Paris static int audit_set_loginuid_perm(kuid_t loginuid) 1961da0a6104SEric Paris { 1962da0a6104SEric Paris /* if we are unset, we don't need privs */ 1963da0a6104SEric Paris if (!audit_loginuid_set(current)) 1964da0a6104SEric Paris return 0; 196521b85c31SEric Paris /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ 196621b85c31SEric Paris if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) 196721b85c31SEric Paris return -EPERM; 196883fa6bbeSEric Paris /* it is set, you need permission */ 196983fa6bbeSEric Paris if (!capable(CAP_AUDIT_CONTROL)) 1970da0a6104SEric Paris return -EPERM; 1971d040e5afSEric Paris /* reject if this is not an unset and we don't allow that */ 1972d040e5afSEric Paris if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) && uid_valid(loginuid)) 1973d040e5afSEric Paris return -EPERM; 197483fa6bbeSEric Paris return 0; 1975da0a6104SEric Paris } 1976da0a6104SEric Paris 1977da0a6104SEric Paris static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, 1978da0a6104SEric Paris unsigned int oldsessionid, unsigned int sessionid, 1979da0a6104SEric Paris int rc) 1980da0a6104SEric Paris { 1981da0a6104SEric Paris struct audit_buffer *ab; 19825ee9a75cSRichard Guy Briggs uid_t uid, oldloginuid, loginuid; 1983da0a6104SEric Paris 1984c2412d91SGao feng if (!audit_enabled) 1985c2412d91SGao feng return; 1986c2412d91SGao feng 1987da0a6104SEric Paris uid = from_kuid(&init_user_ns, task_uid(current)); 19885ee9a75cSRichard Guy Briggs oldloginuid = from_kuid(&init_user_ns, koldloginuid); 19895ee9a75cSRichard Guy Briggs loginuid = from_kuid(&init_user_ns, kloginuid), 1990da0a6104SEric Paris 1991da0a6104SEric Paris ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); 1992da0a6104SEric Paris if (!ab) 1993da0a6104SEric Paris return; 1994ddfad8afSEric Paris audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); 1995ddfad8afSEric Paris audit_log_task_context(ab); 1996ddfad8afSEric Paris audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", 1997ddfad8afSEric Paris oldloginuid, loginuid, oldsessionid, sessionid, !rc); 1998da0a6104SEric Paris audit_log_end(ab); 1999da0a6104SEric Paris } 2000da0a6104SEric Paris 2001b0dd25a8SRandy Dunlap /** 20020a300be6SEric Paris * audit_set_loginuid - set current task's audit_context loginuid 2003b0dd25a8SRandy Dunlap * @loginuid: loginuid value 2004b0dd25a8SRandy Dunlap * 2005b0dd25a8SRandy Dunlap * Returns 0. 2006b0dd25a8SRandy Dunlap * 2007b0dd25a8SRandy Dunlap * Called (set) from fs/proc/base.c::proc_loginuid_write(). 2008b0dd25a8SRandy Dunlap */ 2009e1760bd5SEric W. Biederman int audit_set_loginuid(kuid_t loginuid) 20101da177e4SLinus Torvalds { 20110a300be6SEric Paris struct task_struct *task = current; 20129175c9d2SEric Paris unsigned int oldsessionid, sessionid = (unsigned int)-1; 20139175c9d2SEric Paris kuid_t oldloginuid; 2014da0a6104SEric Paris int rc; 201541757106SSteve Grubb 2016da0a6104SEric Paris oldloginuid = audit_get_loginuid(current); 2017da0a6104SEric Paris oldsessionid = audit_get_sessionid(current); 2018da0a6104SEric Paris 2019da0a6104SEric Paris rc = audit_set_loginuid_perm(loginuid); 2020da0a6104SEric Paris if (rc) 2021da0a6104SEric Paris goto out; 2022633b4545SEric Paris 202381407c84SEric Paris /* are we setting or clearing? */ 202481407c84SEric Paris if (uid_valid(loginuid)) 20254440e854SEric Paris sessionid = (unsigned int)atomic_inc_return(&session_id); 2026c0404993SSteve Grubb 20274746ec5bSEric Paris task->sessionid = sessionid; 2028bfef93a5SAl Viro task->loginuid = loginuid; 2029da0a6104SEric Paris out: 2030da0a6104SEric Paris audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); 2031da0a6104SEric Paris return rc; 20321da177e4SLinus Torvalds } 20331da177e4SLinus Torvalds 2034b0dd25a8SRandy Dunlap /** 203520ca73bcSGeorge C. Wilson * __audit_mq_open - record audit data for a POSIX MQ open 203620ca73bcSGeorge C. Wilson * @oflag: open flag 203720ca73bcSGeorge C. Wilson * @mode: mode bits 20386b962559SRandy Dunlap * @attr: queue attributes 203920ca73bcSGeorge C. Wilson * 204020ca73bcSGeorge C. Wilson */ 2041df0a4283SAl Viro void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr) 204220ca73bcSGeorge C. Wilson { 204320ca73bcSGeorge C. Wilson struct audit_context *context = current->audit_context; 204420ca73bcSGeorge C. Wilson 2045564f6993SAl Viro if (attr) 2046564f6993SAl Viro memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr)); 2047564f6993SAl Viro else 2048564f6993SAl Viro memset(&context->mq_open.attr, 0, sizeof(struct mq_attr)); 204920ca73bcSGeorge C. Wilson 2050564f6993SAl Viro context->mq_open.oflag = oflag; 2051564f6993SAl Viro context->mq_open.mode = mode; 205220ca73bcSGeorge C. Wilson 2053564f6993SAl Viro context->type = AUDIT_MQ_OPEN; 205420ca73bcSGeorge C. Wilson } 205520ca73bcSGeorge C. Wilson 205620ca73bcSGeorge C. Wilson /** 2057c32c8af4SAl Viro * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive 205820ca73bcSGeorge C. Wilson * @mqdes: MQ descriptor 205920ca73bcSGeorge C. Wilson * @msg_len: Message length 206020ca73bcSGeorge C. Wilson * @msg_prio: Message priority 2061c32c8af4SAl Viro * @abs_timeout: Message timeout in absolute time 206220ca73bcSGeorge C. Wilson * 206320ca73bcSGeorge C. Wilson */ 2064c32c8af4SAl Viro void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, 2065c32c8af4SAl Viro const struct timespec *abs_timeout) 206620ca73bcSGeorge C. Wilson { 206720ca73bcSGeorge C. Wilson struct audit_context *context = current->audit_context; 2068c32c8af4SAl Viro struct timespec *p = &context->mq_sendrecv.abs_timeout; 206920ca73bcSGeorge C. Wilson 2070c32c8af4SAl Viro if (abs_timeout) 2071c32c8af4SAl Viro memcpy(p, abs_timeout, sizeof(struct timespec)); 2072c32c8af4SAl Viro else 2073c32c8af4SAl Viro memset(p, 0, sizeof(struct timespec)); 207420ca73bcSGeorge C. Wilson 2075c32c8af4SAl Viro context->mq_sendrecv.mqdes = mqdes; 2076c32c8af4SAl Viro context->mq_sendrecv.msg_len = msg_len; 2077c32c8af4SAl Viro context->mq_sendrecv.msg_prio = msg_prio; 207820ca73bcSGeorge C. Wilson 2079c32c8af4SAl Viro context->type = AUDIT_MQ_SENDRECV; 208020ca73bcSGeorge C. Wilson } 208120ca73bcSGeorge C. Wilson 208220ca73bcSGeorge C. Wilson /** 208320ca73bcSGeorge C. Wilson * __audit_mq_notify - record audit data for a POSIX MQ notify 208420ca73bcSGeorge C. Wilson * @mqdes: MQ descriptor 20856b962559SRandy Dunlap * @notification: Notification event 208620ca73bcSGeorge C. Wilson * 208720ca73bcSGeorge C. Wilson */ 208820ca73bcSGeorge C. Wilson 208920114f71SAl Viro void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification) 209020ca73bcSGeorge C. Wilson { 209120ca73bcSGeorge C. Wilson struct audit_context *context = current->audit_context; 209220ca73bcSGeorge C. Wilson 209320114f71SAl Viro if (notification) 209420114f71SAl Viro context->mq_notify.sigev_signo = notification->sigev_signo; 209520114f71SAl Viro else 209620114f71SAl Viro context->mq_notify.sigev_signo = 0; 209720ca73bcSGeorge C. Wilson 209820114f71SAl Viro context->mq_notify.mqdes = mqdes; 209920114f71SAl Viro context->type = AUDIT_MQ_NOTIFY; 210020ca73bcSGeorge C. Wilson } 210120ca73bcSGeorge C. Wilson 210220ca73bcSGeorge C. Wilson /** 210320ca73bcSGeorge C. Wilson * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute 210420ca73bcSGeorge C. Wilson * @mqdes: MQ descriptor 210520ca73bcSGeorge C. Wilson * @mqstat: MQ flags 210620ca73bcSGeorge C. Wilson * 210720ca73bcSGeorge C. Wilson */ 21087392906eSAl Viro void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) 210920ca73bcSGeorge C. Wilson { 211020ca73bcSGeorge C. Wilson struct audit_context *context = current->audit_context; 21117392906eSAl Viro context->mq_getsetattr.mqdes = mqdes; 21127392906eSAl Viro context->mq_getsetattr.mqstat = *mqstat; 21137392906eSAl Viro context->type = AUDIT_MQ_GETSETATTR; 211420ca73bcSGeorge C. Wilson } 211520ca73bcSGeorge C. Wilson 211620ca73bcSGeorge C. Wilson /** 2117073115d6SSteve Grubb * audit_ipc_obj - record audit data for ipc object 2118073115d6SSteve Grubb * @ipcp: ipc permissions 2119073115d6SSteve Grubb * 2120073115d6SSteve Grubb */ 2121a33e6751SAl Viro void __audit_ipc_obj(struct kern_ipc_perm *ipcp) 2122073115d6SSteve Grubb { 2123073115d6SSteve Grubb struct audit_context *context = current->audit_context; 2124a33e6751SAl Viro context->ipc.uid = ipcp->uid; 2125a33e6751SAl Viro context->ipc.gid = ipcp->gid; 2126a33e6751SAl Viro context->ipc.mode = ipcp->mode; 2127e816f370SAl Viro context->ipc.has_perm = 0; 2128a33e6751SAl Viro security_ipc_getsecid(ipcp, &context->ipc.osid); 2129a33e6751SAl Viro context->type = AUDIT_IPC; 2130073115d6SSteve Grubb } 2131073115d6SSteve Grubb 2132073115d6SSteve Grubb /** 2133073115d6SSteve Grubb * audit_ipc_set_perm - record audit data for new ipc permissions 2134b0dd25a8SRandy Dunlap * @qbytes: msgq bytes 2135b0dd25a8SRandy Dunlap * @uid: msgq user id 2136b0dd25a8SRandy Dunlap * @gid: msgq group id 2137b0dd25a8SRandy Dunlap * @mode: msgq mode (permissions) 2138b0dd25a8SRandy Dunlap * 2139e816f370SAl Viro * Called only after audit_ipc_obj(). 2140b0dd25a8SRandy Dunlap */ 21412570ebbdSAl Viro void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode) 21421da177e4SLinus Torvalds { 21431da177e4SLinus Torvalds struct audit_context *context = current->audit_context; 21441da177e4SLinus Torvalds 2145e816f370SAl Viro context->ipc.qbytes = qbytes; 2146e816f370SAl Viro context->ipc.perm_uid = uid; 2147e816f370SAl Viro context->ipc.perm_gid = gid; 2148e816f370SAl Viro context->ipc.perm_mode = mode; 2149e816f370SAl Viro context->ipc.has_perm = 1; 21501da177e4SLinus Torvalds } 2151c2f0c7c3SSteve Grubb 2152d9cfea91SRichard Guy Briggs void __audit_bprm(struct linux_binprm *bprm) 2153473ae30bSAl Viro { 2154473ae30bSAl Viro struct audit_context *context = current->audit_context; 2155473ae30bSAl Viro 2156d9cfea91SRichard Guy Briggs context->type = AUDIT_EXECVE; 2157d9cfea91SRichard Guy Briggs context->execve.argc = bprm->argc; 2158473ae30bSAl Viro } 2159473ae30bSAl Viro 2160473ae30bSAl Viro 2161b0dd25a8SRandy Dunlap /** 2162b0dd25a8SRandy Dunlap * audit_socketcall - record audit data for sys_socketcall 21632950fa9dSChen Gang * @nargs: number of args, which should not be more than AUDITSC_ARGS. 2164b0dd25a8SRandy Dunlap * @args: args array 2165b0dd25a8SRandy Dunlap * 2166b0dd25a8SRandy Dunlap */ 21672950fa9dSChen Gang int __audit_socketcall(int nargs, unsigned long *args) 21683ec3b2fbSDavid Woodhouse { 21693ec3b2fbSDavid Woodhouse struct audit_context *context = current->audit_context; 21703ec3b2fbSDavid Woodhouse 21712950fa9dSChen Gang if (nargs <= 0 || nargs > AUDITSC_ARGS || !args) 21722950fa9dSChen Gang return -EINVAL; 2173f3298dc4SAl Viro context->type = AUDIT_SOCKETCALL; 2174f3298dc4SAl Viro context->socketcall.nargs = nargs; 2175f3298dc4SAl Viro memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long)); 21762950fa9dSChen Gang return 0; 21773ec3b2fbSDavid Woodhouse } 21783ec3b2fbSDavid Woodhouse 2179b0dd25a8SRandy Dunlap /** 2180db349509SAl Viro * __audit_fd_pair - record audit data for pipe and socketpair 2181db349509SAl Viro * @fd1: the first file descriptor 2182db349509SAl Viro * @fd2: the second file descriptor 2183db349509SAl Viro * 2184db349509SAl Viro */ 2185157cf649SAl Viro void __audit_fd_pair(int fd1, int fd2) 2186db349509SAl Viro { 2187db349509SAl Viro struct audit_context *context = current->audit_context; 2188157cf649SAl Viro context->fds[0] = fd1; 2189157cf649SAl Viro context->fds[1] = fd2; 2190db349509SAl Viro } 2191db349509SAl Viro 2192db349509SAl Viro /** 2193b0dd25a8SRandy Dunlap * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto 2194b0dd25a8SRandy Dunlap * @len: data length in user space 2195b0dd25a8SRandy Dunlap * @a: data address in kernel space 2196b0dd25a8SRandy Dunlap * 2197b0dd25a8SRandy Dunlap * Returns 0 for success or NULL context or < 0 on error. 2198b0dd25a8SRandy Dunlap */ 219907c49417SEric Paris int __audit_sockaddr(int len, void *a) 22003ec3b2fbSDavid Woodhouse { 22013ec3b2fbSDavid Woodhouse struct audit_context *context = current->audit_context; 22023ec3b2fbSDavid Woodhouse 22034f6b434fSAl Viro if (!context->sockaddr) { 22044f6b434fSAl Viro void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL); 22054f6b434fSAl Viro if (!p) 22063ec3b2fbSDavid Woodhouse return -ENOMEM; 22074f6b434fSAl Viro context->sockaddr = p; 22084f6b434fSAl Viro } 22093ec3b2fbSDavid Woodhouse 22104f6b434fSAl Viro context->sockaddr_len = len; 22114f6b434fSAl Viro memcpy(context->sockaddr, a, len); 22123ec3b2fbSDavid Woodhouse return 0; 22133ec3b2fbSDavid Woodhouse } 22143ec3b2fbSDavid Woodhouse 2215a5cb013dSAl Viro void __audit_ptrace(struct task_struct *t) 2216a5cb013dSAl Viro { 2217a5cb013dSAl Viro struct audit_context *context = current->audit_context; 2218a5cb013dSAl Viro 2219f1dc4867SRichard Guy Briggs context->target_pid = task_pid_nr(t); 2220c2a7780eSEric Paris context->target_auid = audit_get_loginuid(t); 2221c69e8d9cSDavid Howells context->target_uid = task_uid(t); 22224746ec5bSEric Paris context->target_sessionid = audit_get_sessionid(t); 22232a862b32SAhmed S. Darwish security_task_getsecid(t, &context->target_sid); 2224c2a7780eSEric Paris memcpy(context->target_comm, t->comm, TASK_COMM_LEN); 2225a5cb013dSAl Viro } 2226a5cb013dSAl Viro 2227b0dd25a8SRandy Dunlap /** 2228b0dd25a8SRandy Dunlap * audit_signal_info - record signal info for shutting down audit subsystem 2229b0dd25a8SRandy Dunlap * @sig: signal value 2230b0dd25a8SRandy Dunlap * @t: task being signaled 2231b0dd25a8SRandy Dunlap * 2232b0dd25a8SRandy Dunlap * If the audit subsystem is being terminated, record the task (pid) 2233b0dd25a8SRandy Dunlap * and uid that is doing that. 2234b0dd25a8SRandy Dunlap */ 2235e54dc243SAmy Griffis int __audit_signal_info(int sig, struct task_struct *t) 2236c2f0c7c3SSteve Grubb { 2237e54dc243SAmy Griffis struct audit_aux_data_pids *axp; 2238e54dc243SAmy Griffis struct task_struct *tsk = current; 2239e54dc243SAmy Griffis struct audit_context *ctx = tsk->audit_context; 2240cca080d9SEric W. Biederman kuid_t uid = current_uid(), t_uid = task_uid(t); 2241c2f0c7c3SSteve Grubb 2242175fc484SAl Viro if (audit_pid && t->tgid == audit_pid) { 2243ee1d3156SEric Paris if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { 2244f1dc4867SRichard Guy Briggs audit_sig_pid = task_pid_nr(tsk); 2245e1760bd5SEric W. Biederman if (uid_valid(tsk->loginuid)) 2246bfef93a5SAl Viro audit_sig_uid = tsk->loginuid; 2247c2f0c7c3SSteve Grubb else 2248c69e8d9cSDavid Howells audit_sig_uid = uid; 22492a862b32SAhmed S. Darwish security_task_getsecid(tsk, &audit_sig_sid); 2250c2f0c7c3SSteve Grubb } 2251175fc484SAl Viro if (!audit_signals || audit_dummy_context()) 2252e54dc243SAmy Griffis return 0; 2253175fc484SAl Viro } 2254e54dc243SAmy Griffis 2255e54dc243SAmy Griffis /* optimize the common case by putting first signal recipient directly 2256e54dc243SAmy Griffis * in audit_context */ 2257e54dc243SAmy Griffis if (!ctx->target_pid) { 2258f1dc4867SRichard Guy Briggs ctx->target_pid = task_tgid_nr(t); 2259c2a7780eSEric Paris ctx->target_auid = audit_get_loginuid(t); 2260c69e8d9cSDavid Howells ctx->target_uid = t_uid; 22614746ec5bSEric Paris ctx->target_sessionid = audit_get_sessionid(t); 22622a862b32SAhmed S. Darwish security_task_getsecid(t, &ctx->target_sid); 2263c2a7780eSEric Paris memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN); 2264e54dc243SAmy Griffis return 0; 2265e54dc243SAmy Griffis } 2266e54dc243SAmy Griffis 2267e54dc243SAmy Griffis axp = (void *)ctx->aux_pids; 2268e54dc243SAmy Griffis if (!axp || axp->pid_count == AUDIT_AUX_PIDS) { 2269e54dc243SAmy Griffis axp = kzalloc(sizeof(*axp), GFP_ATOMIC); 2270e54dc243SAmy Griffis if (!axp) 2271e54dc243SAmy Griffis return -ENOMEM; 2272e54dc243SAmy Griffis 2273e54dc243SAmy Griffis axp->d.type = AUDIT_OBJ_PID; 2274e54dc243SAmy Griffis axp->d.next = ctx->aux_pids; 2275e54dc243SAmy Griffis ctx->aux_pids = (void *)axp; 2276e54dc243SAmy Griffis } 227788ae704cSAdrian Bunk BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); 2278e54dc243SAmy Griffis 2279f1dc4867SRichard Guy Briggs axp->target_pid[axp->pid_count] = task_tgid_nr(t); 2280c2a7780eSEric Paris axp->target_auid[axp->pid_count] = audit_get_loginuid(t); 2281c69e8d9cSDavid Howells axp->target_uid[axp->pid_count] = t_uid; 22824746ec5bSEric Paris axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); 22832a862b32SAhmed S. Darwish security_task_getsecid(t, &axp->target_sid[axp->pid_count]); 2284c2a7780eSEric Paris memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN); 2285e54dc243SAmy Griffis axp->pid_count++; 2286e54dc243SAmy Griffis 2287e54dc243SAmy Griffis return 0; 2288c2f0c7c3SSteve Grubb } 22890a4ff8c2SSteve Grubb 22900a4ff8c2SSteve Grubb /** 22913fc689e9SEric Paris * __audit_log_bprm_fcaps - store information about a loading bprm and relevant fcaps 2292d84f4f99SDavid Howells * @bprm: pointer to the bprm being processed 2293d84f4f99SDavid Howells * @new: the proposed new credentials 2294d84f4f99SDavid Howells * @old: the old credentials 22953fc689e9SEric Paris * 22963fc689e9SEric Paris * Simply check if the proc already has the caps given by the file and if not 22973fc689e9SEric Paris * store the priv escalation info for later auditing at the end of the syscall 22983fc689e9SEric Paris * 22993fc689e9SEric Paris * -Eric 23003fc689e9SEric Paris */ 2301d84f4f99SDavid Howells int __audit_log_bprm_fcaps(struct linux_binprm *bprm, 2302d84f4f99SDavid Howells const struct cred *new, const struct cred *old) 23033fc689e9SEric Paris { 23043fc689e9SEric Paris struct audit_aux_data_bprm_fcaps *ax; 23053fc689e9SEric Paris struct audit_context *context = current->audit_context; 23063fc689e9SEric Paris struct cpu_vfs_cap_data vcaps; 23073fc689e9SEric Paris 23083fc689e9SEric Paris ax = kmalloc(sizeof(*ax), GFP_KERNEL); 23093fc689e9SEric Paris if (!ax) 2310d84f4f99SDavid Howells return -ENOMEM; 23113fc689e9SEric Paris 23123fc689e9SEric Paris ax->d.type = AUDIT_BPRM_FCAPS; 23133fc689e9SEric Paris ax->d.next = context->aux; 23143fc689e9SEric Paris context->aux = (void *)ax; 23153fc689e9SEric Paris 2316f4a4a8b1SAl Viro get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps); 23173fc689e9SEric Paris 23183fc689e9SEric Paris ax->fcap.permitted = vcaps.permitted; 23193fc689e9SEric Paris ax->fcap.inheritable = vcaps.inheritable; 23203fc689e9SEric Paris ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); 23213fc689e9SEric Paris ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; 23223fc689e9SEric Paris 2323d84f4f99SDavid Howells ax->old_pcap.permitted = old->cap_permitted; 2324d84f4f99SDavid Howells ax->old_pcap.inheritable = old->cap_inheritable; 2325d84f4f99SDavid Howells ax->old_pcap.effective = old->cap_effective; 23263fc689e9SEric Paris 2327d84f4f99SDavid Howells ax->new_pcap.permitted = new->cap_permitted; 2328d84f4f99SDavid Howells ax->new_pcap.inheritable = new->cap_inheritable; 2329d84f4f99SDavid Howells ax->new_pcap.effective = new->cap_effective; 2330d84f4f99SDavid Howells return 0; 23313fc689e9SEric Paris } 23323fc689e9SEric Paris 23333fc689e9SEric Paris /** 2334e68b75a0SEric Paris * __audit_log_capset - store information about the arguments to the capset syscall 2335d84f4f99SDavid Howells * @new: the new credentials 2336d84f4f99SDavid Howells * @old: the old (current) credentials 2337e68b75a0SEric Paris * 2338da3dae54SMasanari Iida * Record the arguments userspace sent to sys_capset for later printing by the 2339e68b75a0SEric Paris * audit system if applicable 2340e68b75a0SEric Paris */ 2341ca24a23eSEric W. Biederman void __audit_log_capset(const struct cred *new, const struct cred *old) 2342e68b75a0SEric Paris { 2343e68b75a0SEric Paris struct audit_context *context = current->audit_context; 2344ca24a23eSEric W. Biederman context->capset.pid = task_pid_nr(current); 234557f71a0aSAl Viro context->capset.cap.effective = new->cap_effective; 234657f71a0aSAl Viro context->capset.cap.inheritable = new->cap_effective; 234757f71a0aSAl Viro context->capset.cap.permitted = new->cap_permitted; 234857f71a0aSAl Viro context->type = AUDIT_CAPSET; 2349e68b75a0SEric Paris } 2350e68b75a0SEric Paris 2351120a795dSAl Viro void __audit_mmap_fd(int fd, int flags) 2352120a795dSAl Viro { 2353120a795dSAl Viro struct audit_context *context = current->audit_context; 2354120a795dSAl Viro context->mmap.fd = fd; 2355120a795dSAl Viro context->mmap.flags = flags; 2356120a795dSAl Viro context->type = AUDIT_MMAP; 2357120a795dSAl Viro } 2358120a795dSAl Viro 23597b9205bdSKees Cook static void audit_log_task(struct audit_buffer *ab) 236085e7bac3SEric Paris { 2361cca080d9SEric W. Biederman kuid_t auid, uid; 2362cca080d9SEric W. Biederman kgid_t gid; 236385e7bac3SEric Paris unsigned int sessionid; 23649eab339bSRichard Guy Briggs char comm[sizeof(current->comm)]; 236585e7bac3SEric Paris 236685e7bac3SEric Paris auid = audit_get_loginuid(current); 236785e7bac3SEric Paris sessionid = audit_get_sessionid(current); 236885e7bac3SEric Paris current_uid_gid(&uid, &gid); 236985e7bac3SEric Paris 237085e7bac3SEric Paris audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u", 2371cca080d9SEric W. Biederman from_kuid(&init_user_ns, auid), 2372cca080d9SEric W. Biederman from_kuid(&init_user_ns, uid), 2373cca080d9SEric W. Biederman from_kgid(&init_user_ns, gid), 2374cca080d9SEric W. Biederman sessionid); 237585e7bac3SEric Paris audit_log_task_context(ab); 2376f1dc4867SRichard Guy Briggs audit_log_format(ab, " pid=%d comm=", task_pid_nr(current)); 23779eab339bSRichard Guy Briggs audit_log_untrustedstring(ab, get_task_comm(comm, current)); 23784766b199SDavidlohr Bueso audit_log_d_path_exe(ab, current->mm); 23797b9205bdSKees Cook } 23807b9205bdSKees Cook 2381e68b75a0SEric Paris /** 23820a4ff8c2SSteve Grubb * audit_core_dumps - record information about processes that end abnormally 23836d9525b5SHenrik Kretzschmar * @signr: signal value 23840a4ff8c2SSteve Grubb * 23850a4ff8c2SSteve Grubb * If a process ends with a core dump, something fishy is going on and we 23860a4ff8c2SSteve Grubb * should record the event for investigation. 23870a4ff8c2SSteve Grubb */ 23880a4ff8c2SSteve Grubb void audit_core_dumps(long signr) 23890a4ff8c2SSteve Grubb { 23900a4ff8c2SSteve Grubb struct audit_buffer *ab; 23910a4ff8c2SSteve Grubb 23920a4ff8c2SSteve Grubb if (!audit_enabled) 23930a4ff8c2SSteve Grubb return; 23940a4ff8c2SSteve Grubb 23950a4ff8c2SSteve Grubb if (signr == SIGQUIT) /* don't care for those */ 23960a4ff8c2SSteve Grubb return; 23970a4ff8c2SSteve Grubb 23980a4ff8c2SSteve Grubb ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); 23990644ec0cSKees Cook if (unlikely(!ab)) 24000644ec0cSKees Cook return; 240161c0ee87SPaul Davies C audit_log_task(ab); 240261c0ee87SPaul Davies C audit_log_format(ab, " sig=%ld", signr); 240385e7bac3SEric Paris audit_log_end(ab); 240485e7bac3SEric Paris } 24050a4ff8c2SSteve Grubb 24063dc1c1b2SKees Cook void __audit_seccomp(unsigned long syscall, long signr, int code) 240785e7bac3SEric Paris { 240885e7bac3SEric Paris struct audit_buffer *ab; 240985e7bac3SEric Paris 24107b9205bdSKees Cook ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); 24117b9205bdSKees Cook if (unlikely(!ab)) 24127b9205bdSKees Cook return; 24137b9205bdSKees Cook audit_log_task(ab); 241484db564aSRichard Guy Briggs audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x", 241584db564aSRichard Guy Briggs signr, syscall_get_arch(), syscall, is_compat_task(), 241684db564aSRichard Guy Briggs KSTK_EIP(current), code); 24170a4ff8c2SSteve Grubb audit_log_end(ab); 24180a4ff8c2SSteve Grubb } 2419916d7576SAl Viro 2420916d7576SAl Viro struct list_head *audit_killed_trees(void) 2421916d7576SAl Viro { 2422916d7576SAl Viro struct audit_context *ctx = current->audit_context; 2423916d7576SAl Viro if (likely(!ctx || !ctx->in_syscall)) 2424916d7576SAl Viro return NULL; 2425916d7576SAl Viro return &ctx->killed_trees; 2426916d7576SAl Viro } 2427