Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] audit signal recipients

When auditing syscalls that send signals, log the pid and security
context for each target process. Optimize the data collection by
adding a counter for signal-related rules, and avoiding allocating an
aux struct unless we have more than one target process. For process
groups, collect pid/context data in blocks of 16. Move the
audit_signal_info() hook up in check_kill_permission() so we audit
attempts where permission is denied.

Signed-off-by: Amy Griffis <amy.griffis@hp.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

Amy Griffis and committed by
Al Viro
e54dc243 7f13da40

+206 -29
+9
arch/ia64/kernel/audit.c
··· 28 28 ~0U 29 29 }; 30 30 31 + int audit_classify_arch(int arch) 32 + { 33 + #ifdef CONFIG_IA32_SUPPORT 34 + if (arch == AUDIT_ARCH_I386) 35 + return 1; 36 + #endif 37 + return 0; 38 + } 39 + 31 40 int audit_classify_syscall(int abi, unsigned syscall) 32 41 { 33 42 #ifdef CONFIG_IA32_SUPPORT
+9
arch/powerpc/kernel/audit.c
··· 28 28 ~0U 29 29 }; 30 30 31 + int audit_classify_arch(int arch) 32 + { 33 + #ifdef CONFIG_PPC64 34 + if (arch == AUDIT_ARCH_PPC) 35 + return 1; 36 + #endif 37 + return 0; 38 + } 39 + 31 40 int audit_classify_syscall(int abi, unsigned syscall) 32 41 { 33 42 #ifdef CONFIG_PPC64
+9
arch/s390/kernel/audit.c
··· 28 28 ~0U 29 29 }; 30 30 31 + int audit_classify_arch(int arch) 32 + { 33 + #ifdef CONFIG_COMPAT 34 + if (arch == AUDIT_ARCH_S390) 35 + return 1; 36 + #endif 37 + return 0; 38 + } 39 + 31 40 int audit_classify_syscall(int abi, unsigned syscall) 32 41 { 33 42 #ifdef CONFIG_COMPAT
+9
arch/sparc64/kernel/audit.c
··· 28 28 ~0U 29 29 }; 30 30 31 + int audit_classify_arch(int arch) 32 + { 33 + #ifdef CONFIG_SPARC32_COMPAT 34 + if (arch == AUDIT_ARCH_SPARC) 35 + return 1; 36 + #endif 37 + return 0; 38 + } 39 + 31 40 int audit_classify_syscall(int abi, unsigned syscall) 32 41 { 33 42 #ifdef CONFIG_SPARC32_COMPAT
+9
arch/x86_64/kernel/audit.c
··· 28 28 ~0U 29 29 }; 30 30 31 + int audit_classify_arch(int arch) 32 + { 33 + #ifdef CONFIG_IA32_EMULATION 34 + if (arch == AUDIT_ARCH_I386) 35 + return 1; 36 + #endif 37 + return 0; 38 + } 39 + 31 40 int audit_classify_syscall(int abi, unsigned syscall) 32 41 { 33 42 #ifdef CONFIG_IA32_EMULATION
+3
include/linux/audit.h
··· 340 340 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) 341 341 extern int __init audit_register_class(int class, unsigned *list); 342 342 extern int audit_classify_syscall(int abi, unsigned syscall); 343 + extern int audit_classify_arch(int arch); 343 344 #ifdef CONFIG_AUDITSYSCALL 344 345 /* These are defined in auditsc.c */ 345 346 /* Public API */ ··· 459 458 return 0; 460 459 } 461 460 extern int audit_n_rules; 461 + extern int audit_signals; 462 462 #else 463 463 #define audit_alloc(t) ({ 0; }) 464 464 #define audit_free(t) do { ; } while (0) ··· 492 490 #define audit_mq_getsetattr(d,s) ({ 0; }) 493 491 #define audit_ptrace(t) ((void)0) 494 492 #define audit_n_rules 0 493 + #define audit_signals 0 495 494 #endif 496 495 497 496 #ifdef CONFIG_AUDIT
+8 -5
kernel/audit.h
··· 83 83 u32 field_count; 84 84 char *filterkey; /* ties events to rules */ 85 85 struct audit_field *fields; 86 + struct audit_field *arch_f; /* quick access to arch field */ 86 87 struct audit_field *inode_f; /* quick access to an inode field */ 87 88 struct audit_watch *watch; /* associated watch */ 88 89 struct list_head rlist; /* entry in audit_watch.rules list */ ··· 132 131 extern int selinux_audit_rule_update(void); 133 132 134 133 #ifdef CONFIG_AUDITSYSCALL 135 - extern void __audit_signal_info(int sig, struct task_struct *t); 136 - static inline void audit_signal_info(int sig, struct task_struct *t) 134 + extern int __audit_signal_info(int sig, struct task_struct *t); 135 + static inline int audit_signal_info(int sig, struct task_struct *t) 137 136 { 138 - if (unlikely(audit_pid && t->tgid == audit_pid)) 139 - __audit_signal_info(sig, t); 137 + if (unlikely((audit_pid && t->tgid == audit_pid) || 138 + (audit_signals && !audit_dummy_context()))) 139 + return __audit_signal_info(sig, t); 140 + return 0; 140 141 } 141 142 extern enum audit_state audit_filter_inodes(struct task_struct *, 142 143 struct audit_context *); 143 144 extern void audit_set_auditable(struct audit_context *); 144 145 #else 145 - #define audit_signal_info(s,t) 146 + #define audit_signal_info(s,t) AUDIT_DISABLED 146 147 #define audit_filter_inodes(t,c) AUDIT_DISABLED 147 148 #define audit_set_auditable(c) 148 149 #endif
+47 -1
kernel/auditfilter.c
··· 311 311 return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall); 312 312 } 313 313 314 + static inline int audit_match_class_bits(int class, u32 *mask) 315 + { 316 + int i; 317 + 318 + if (classes[class]) { 319 + for (i = 0; i < AUDIT_BITMASK_SIZE; i++) 320 + if (mask[i] & classes[class][i]) 321 + return 0; 322 + } 323 + return 1; 324 + } 325 + 326 + static int audit_match_signal(struct audit_entry *entry) 327 + { 328 + struct audit_field *arch = entry->rule.arch_f; 329 + 330 + if (!arch) { 331 + /* When arch is unspecified, we must check both masks on biarch 332 + * as syscall number alone is ambiguous. */ 333 + return (audit_match_class_bits(AUDIT_CLASS_SIGNAL, 334 + entry->rule.mask) && 335 + audit_match_class_bits(AUDIT_CLASS_SIGNAL_32, 336 + entry->rule.mask)); 337 + } 338 + 339 + switch(audit_classify_arch(arch->val)) { 340 + case 0: /* native */ 341 + return (audit_match_class_bits(AUDIT_CLASS_SIGNAL, 342 + entry->rule.mask)); 343 + case 1: /* 32bit on biarch */ 344 + return (audit_match_class_bits(AUDIT_CLASS_SIGNAL_32, 345 + entry->rule.mask)); 346 + default: 347 + return 1; 348 + } 349 + } 350 + 314 351 /* Common user-space to kernel rule translation. */ 315 352 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) 316 353 { ··· 466 429 err = -EINVAL; 467 430 goto exit_free; 468 431 } 432 + entry->rule.arch_f = f; 469 433 break; 470 434 case AUDIT_PERM: 471 435 if (f->val & ~15) ··· 557 519 case AUDIT_FSGID: 558 520 case AUDIT_LOGINUID: 559 521 case AUDIT_PERS: 560 - case AUDIT_ARCH: 561 522 case AUDIT_MSGTYPE: 562 523 case AUDIT_PPID: 563 524 case AUDIT_DEVMAJOR: ··· 567 530 case AUDIT_ARG1: 568 531 case AUDIT_ARG2: 569 532 case AUDIT_ARG3: 533 + break; 534 + case AUDIT_ARCH: 535 + entry->rule.arch_f = f; 570 536 break; 571 537 case AUDIT_SUBJ_USER: 572 538 case AUDIT_SUBJ_ROLE: ··· 1261 1221 #ifdef CONFIG_AUDITSYSCALL 1262 1222 if (!dont_count) 1263 1223 audit_n_rules++; 1224 + 1225 + if (!audit_match_signal(entry)) 1226 + audit_signals++; 1264 1227 #endif 1265 1228 mutex_unlock(&audit_filter_mutex); 1266 1229 ··· 1337 1294 #ifdef CONFIG_AUDITSYSCALL 1338 1295 if (!dont_count) 1339 1296 audit_n_rules--; 1297 + 1298 + if (!audit_match_signal(entry)) 1299 + audit_signals--; 1340 1300 #endif 1341 1301 mutex_unlock(&audit_filter_mutex); 1342 1302
+92 -19
kernel/auditsc.c
··· 89 89 /* number of audit rules */ 90 90 int audit_n_rules; 91 91 92 + /* determines whether we collect data for signals sent */ 93 + int audit_signals; 94 + 92 95 /* When fs/namei.c:getname() is called, we store the pointer in name and 93 96 * we don't let putname() free it (instead we free all of the saved 94 97 * pointers at syscall exit time). ··· 116 113 }; 117 114 118 115 #define AUDIT_AUX_IPCPERM 0 116 + 117 + /* Number of target pids per aux struct. */ 118 + #define AUDIT_AUX_PIDS 16 119 119 120 120 struct audit_aux_data_mq_open { 121 121 struct audit_aux_data d; ··· 187 181 struct vfsmount *mnt; 188 182 }; 189 183 184 + struct audit_aux_data_pids { 185 + struct audit_aux_data d; 186 + pid_t target_pid[AUDIT_AUX_PIDS]; 187 + u32 target_sid[AUDIT_AUX_PIDS]; 188 + int pid_count; 189 + }; 190 + 190 191 /* The per-task audit context. */ 191 192 struct audit_context { 192 193 int dummy; /* must be the first element */ ··· 214 201 struct vfsmount * pwdmnt; 215 202 struct audit_context *previous; /* For nested syscalls */ 216 203 struct audit_aux_data *aux; 204 + struct audit_aux_data *aux_pids; 217 205 218 206 /* Save things to print about task_struct */ 219 207 pid_t pid, ppid; ··· 671 657 context->aux = aux->next; 672 658 kfree(aux); 673 659 } 660 + while ((aux = context->aux_pids)) { 661 + context->aux_pids = aux->next; 662 + kfree(aux); 663 + } 674 664 } 675 665 676 666 static inline void audit_zero_context(struct audit_context *context, ··· 814 796 up_read(&mm->mmap_sem); 815 797 } 816 798 audit_log_task_context(ab); 799 + } 800 + 801 + static int audit_log_pid_context(struct audit_context *context, pid_t pid, 802 + u32 sid) 803 + { 804 + struct audit_buffer *ab; 805 + char *s = NULL; 806 + u32 len; 807 + int rc = 0; 808 + 809 + ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); 810 + if (!ab) 811 + return 1; 812 + 813 + if (selinux_sid_to_string(sid, &s, &len)) { 814 + audit_log_format(ab, "opid=%d obj=(none)", pid); 815 + rc = 1; 816 + } else 817 + audit_log_format(ab, "opid=%d obj=%s", pid, s); 818 + audit_log_end(ab); 819 + kfree(s); 820 + 821 + return rc; 817 822 } 818 823 819 824 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) ··· 1017 976 audit_log_end(ab); 1018 977 } 1019 978 1020 - if (context->target_pid) { 1021 - ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); 1022 - if (ab) { 1023 - char *s = NULL, *t; 1024 - u32 len; 1025 - if (selinux_sid_to_string(context->target_sid, 1026 - &s, &len)) 1027 - t = "(none)"; 1028 - else 1029 - t = s; 1030 - audit_log_format(ab, "opid=%d obj=%s", 1031 - context->target_pid, t); 1032 - audit_log_end(ab); 1033 - kfree(s); 1034 - } 979 + for (aux = context->aux_pids; aux; aux = aux->next) { 980 + struct audit_aux_data_pids *axs = (void *)aux; 981 + int i; 982 + 983 + for (i = 0; i < axs->pid_count; i++) 984 + if (audit_log_pid_context(context, axs->target_pid[i], 985 + axs->target_sid[i])) 986 + call_panic = 1; 1035 987 } 988 + 989 + if (context->target_pid && 990 + audit_log_pid_context(context, context->target_pid, 991 + context->target_sid)) 992 + call_panic = 1; 1036 993 1037 994 if (context->pwd && context->pwdmnt) { 1038 995 ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); ··· 1252 1213 } else { 1253 1214 audit_free_names(context); 1254 1215 audit_free_aux(context); 1216 + context->aux = NULL; 1217 + context->aux_pids = NULL; 1255 1218 context->target_pid = 0; 1219 + context->target_sid = 0; 1256 1220 kfree(context->filterkey); 1257 1221 context->filterkey = NULL; 1258 1222 tsk->audit_context = context; ··· 1989 1947 * If the audit subsystem is being terminated, record the task (pid) 1990 1948 * and uid that is doing that. 1991 1949 */ 1992 - void __audit_signal_info(int sig, struct task_struct *t) 1950 + int __audit_signal_info(int sig, struct task_struct *t) 1993 1951 { 1952 + struct audit_aux_data_pids *axp; 1953 + struct task_struct *tsk = current; 1954 + struct audit_context *ctx = tsk->audit_context; 1994 1955 extern pid_t audit_sig_pid; 1995 1956 extern uid_t audit_sig_uid; 1996 1957 extern u32 audit_sig_sid; 1997 1958 1998 - if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { 1999 - struct task_struct *tsk = current; 2000 - struct audit_context *ctx = tsk->audit_context; 1959 + if (audit_pid && t->tgid == audit_pid && 1960 + (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) { 2001 1961 audit_sig_pid = tsk->pid; 2002 1962 if (ctx) 2003 1963 audit_sig_uid = ctx->loginuid; ··· 2007 1963 audit_sig_uid = tsk->uid; 2008 1964 selinux_get_task_sid(tsk, &audit_sig_sid); 2009 1965 } 1966 + 1967 + if (!audit_signals) /* audit_context checked in wrapper */ 1968 + return 0; 1969 + 1970 + /* optimize the common case by putting first signal recipient directly 1971 + * in audit_context */ 1972 + if (!ctx->target_pid) { 1973 + ctx->target_pid = t->tgid; 1974 + selinux_get_task_sid(t, &ctx->target_sid); 1975 + return 0; 1976 + } 1977 + 1978 + axp = (void *)ctx->aux_pids; 1979 + if (!axp || axp->pid_count == AUDIT_AUX_PIDS) { 1980 + axp = kzalloc(sizeof(*axp), GFP_ATOMIC); 1981 + if (!axp) 1982 + return -ENOMEM; 1983 + 1984 + axp->d.type = AUDIT_OBJ_PID; 1985 + axp->d.next = ctx->aux_pids; 1986 + ctx->aux_pids = (void *)axp; 1987 + } 1988 + BUG_ON(axp->pid_count > AUDIT_AUX_PIDS); 1989 + 1990 + axp->target_pid[axp->pid_count] = t->tgid; 1991 + selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]); 1992 + axp->pid_count++; 1993 + 1994 + return 0; 2010 1995 }
+6 -4
kernel/signal.c
··· 497 497 int error = -EINVAL; 498 498 if (!valid_signal(sig)) 499 499 return error; 500 + 501 + error = audit_signal_info(sig, t); /* Let audit system see the signal */ 502 + if (error) 503 + return error; 504 + 500 505 error = -EPERM; 501 506 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) 502 507 && ((sig != SIGCONT) || ··· 511 506 && !capable(CAP_KILL)) 512 507 return error; 513 508 514 - error = security_task_kill(t, info, sig, 0); 515 - if (!error) 516 - audit_signal_info(sig, t); /* Let audit system see the signal */ 517 - return error; 509 + return security_task_kill(t, info, sig, 0); 518 510 } 519 511 520 512 /* forward decl */
+5
lib/audit.c
··· 28 28 ~0U 29 29 }; 30 30 31 + int audit_classify_arch(int arch) 32 + { 33 + return 0; 34 + } 35 + 31 36 int audit_classify_syscall(int abi, unsigned syscall) 32 37 { 33 38 switch(syscall) {