aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAmy Griffis <amy.griffis@hp.com>2007-03-29 18:01:04 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2007-05-11 05:38:25 -0400
commite54dc2431d740a79a6bd013babade99d71b1714f (patch)
tree16b0990d5c16946239a17b332f54b5918fb03305 /kernel
parent7f13da40e36c84d0d046b7adbd060af7d3717250 (diff)
[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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit.h13
-rw-r--r--kernel/auditfilter.c48
-rw-r--r--kernel/auditsc.c111
-rw-r--r--kernel/signal.c10
4 files changed, 153 insertions, 29 deletions
diff --git a/kernel/audit.h b/kernel/audit.h
index a3370232a390..815d6f5c04ee 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -83,6 +83,7 @@ struct audit_krule {
83 u32 field_count; 83 u32 field_count;
84 char *filterkey; /* ties events to rules */ 84 char *filterkey; /* ties events to rules */
85 struct audit_field *fields; 85 struct audit_field *fields;
86 struct audit_field *arch_f; /* quick access to arch field */
86 struct audit_field *inode_f; /* quick access to an inode field */ 87 struct audit_field *inode_f; /* quick access to an inode field */
87 struct audit_watch *watch; /* associated watch */ 88 struct audit_watch *watch; /* associated watch */
88 struct list_head rlist; /* entry in audit_watch.rules list */ 89 struct list_head rlist; /* entry in audit_watch.rules list */
@@ -131,17 +132,19 @@ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
131extern int selinux_audit_rule_update(void); 132extern int selinux_audit_rule_update(void);
132 133
133#ifdef CONFIG_AUDITSYSCALL 134#ifdef CONFIG_AUDITSYSCALL
134extern void __audit_signal_info(int sig, struct task_struct *t); 135extern int __audit_signal_info(int sig, struct task_struct *t);
135static inline void audit_signal_info(int sig, struct task_struct *t) 136static inline int audit_signal_info(int sig, struct task_struct *t)
136{ 137{
137 if (unlikely(audit_pid && t->tgid == audit_pid)) 138 if (unlikely((audit_pid && t->tgid == audit_pid) ||
138 __audit_signal_info(sig, t); 139 (audit_signals && !audit_dummy_context())))
140 return __audit_signal_info(sig, t);
141 return 0;
139} 142}
140extern enum audit_state audit_filter_inodes(struct task_struct *, 143extern enum audit_state audit_filter_inodes(struct task_struct *,
141 struct audit_context *); 144 struct audit_context *);
142extern void audit_set_auditable(struct audit_context *); 145extern void audit_set_auditable(struct audit_context *);
143#else 146#else
144#define audit_signal_info(s,t) 147#define audit_signal_info(s,t) AUDIT_DISABLED
145#define audit_filter_inodes(t,c) AUDIT_DISABLED 148#define audit_filter_inodes(t,c) AUDIT_DISABLED
146#define audit_set_auditable(c) 149#define audit_set_auditable(c)
147#endif 150#endif
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 3749193aed8c..6c61263ff96d 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -311,6 +311,43 @@ int audit_match_class(int class, unsigned syscall)
311 return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall); 311 return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);
312} 312}
313 313
314static 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
326static 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/* Common user-space to kernel rule translation. */ 351/* Common user-space to kernel rule translation. */
315static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) 352static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
316{ 353{
@@ -429,6 +466,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
429 err = -EINVAL; 466 err = -EINVAL;
430 goto exit_free; 467 goto exit_free;
431 } 468 }
469 entry->rule.arch_f = f;
432 break; 470 break;
433 case AUDIT_PERM: 471 case AUDIT_PERM:
434 if (f->val & ~15) 472 if (f->val & ~15)
@@ -519,7 +557,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
519 case AUDIT_FSGID: 557 case AUDIT_FSGID:
520 case AUDIT_LOGINUID: 558 case AUDIT_LOGINUID:
521 case AUDIT_PERS: 559 case AUDIT_PERS:
522 case AUDIT_ARCH:
523 case AUDIT_MSGTYPE: 560 case AUDIT_MSGTYPE:
524 case AUDIT_PPID: 561 case AUDIT_PPID:
525 case AUDIT_DEVMAJOR: 562 case AUDIT_DEVMAJOR:
@@ -531,6 +568,9 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
531 case AUDIT_ARG2: 568 case AUDIT_ARG2:
532 case AUDIT_ARG3: 569 case AUDIT_ARG3:
533 break; 570 break;
571 case AUDIT_ARCH:
572 entry->rule.arch_f = f;
573 break;
534 case AUDIT_SUBJ_USER: 574 case AUDIT_SUBJ_USER:
535 case AUDIT_SUBJ_ROLE: 575 case AUDIT_SUBJ_ROLE:
536 case AUDIT_SUBJ_TYPE: 576 case AUDIT_SUBJ_TYPE:
@@ -1221,6 +1261,9 @@ static inline int audit_add_rule(struct audit_entry *entry,
1221#ifdef CONFIG_AUDITSYSCALL 1261#ifdef CONFIG_AUDITSYSCALL
1222 if (!dont_count) 1262 if (!dont_count)
1223 audit_n_rules++; 1263 audit_n_rules++;
1264
1265 if (!audit_match_signal(entry))
1266 audit_signals++;
1224#endif 1267#endif
1225 mutex_unlock(&audit_filter_mutex); 1268 mutex_unlock(&audit_filter_mutex);
1226 1269
@@ -1294,6 +1337,9 @@ static inline int audit_del_rule(struct audit_entry *entry,
1294#ifdef CONFIG_AUDITSYSCALL 1337#ifdef CONFIG_AUDITSYSCALL
1295 if (!dont_count) 1338 if (!dont_count)
1296 audit_n_rules--; 1339 audit_n_rules--;
1340
1341 if (!audit_match_signal(entry))
1342 audit_signals--;
1297#endif 1343#endif
1298 mutex_unlock(&audit_filter_mutex); 1344 mutex_unlock(&audit_filter_mutex);
1299 1345
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2243c559bc03..6aff0df75568 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -89,6 +89,9 @@ extern int audit_enabled;
89/* number of audit rules */ 89/* number of audit rules */
90int audit_n_rules; 90int audit_n_rules;
91 91
92/* determines whether we collect data for signals sent */
93int audit_signals;
94
92/* When fs/namei.c:getname() is called, we store the pointer in name and 95/* When fs/namei.c:getname() is called, we store the pointer in name and
93 * we don't let putname() free it (instead we free all of the saved 96 * we don't let putname() free it (instead we free all of the saved
94 * pointers at syscall exit time). 97 * pointers at syscall exit time).
@@ -114,6 +117,9 @@ struct audit_aux_data {
114 117
115#define AUDIT_AUX_IPCPERM 0 118#define AUDIT_AUX_IPCPERM 0
116 119
120/* Number of target pids per aux struct. */
121#define AUDIT_AUX_PIDS 16
122
117struct audit_aux_data_mq_open { 123struct audit_aux_data_mq_open {
118 struct audit_aux_data d; 124 struct audit_aux_data d;
119 int oflag; 125 int oflag;
@@ -181,6 +187,13 @@ struct audit_aux_data_path {
181 struct vfsmount *mnt; 187 struct vfsmount *mnt;
182}; 188};
183 189
190struct audit_aux_data_pids {
191 struct audit_aux_data d;
192 pid_t target_pid[AUDIT_AUX_PIDS];
193 u32 target_sid[AUDIT_AUX_PIDS];
194 int pid_count;
195};
196
184/* The per-task audit context. */ 197/* The per-task audit context. */
185struct audit_context { 198struct audit_context {
186 int dummy; /* must be the first element */ 199 int dummy; /* must be the first element */
@@ -201,6 +214,7 @@ struct audit_context {
201 struct vfsmount * pwdmnt; 214 struct vfsmount * pwdmnt;
202 struct audit_context *previous; /* For nested syscalls */ 215 struct audit_context *previous; /* For nested syscalls */
203 struct audit_aux_data *aux; 216 struct audit_aux_data *aux;
217 struct audit_aux_data *aux_pids;
204 218
205 /* Save things to print about task_struct */ 219 /* Save things to print about task_struct */
206 pid_t pid, ppid; 220 pid_t pid, ppid;
@@ -657,6 +671,10 @@ static inline void audit_free_aux(struct audit_context *context)
657 context->aux = aux->next; 671 context->aux = aux->next;
658 kfree(aux); 672 kfree(aux);
659 } 673 }
674 while ((aux = context->aux_pids)) {
675 context->aux_pids = aux->next;
676 kfree(aux);
677 }
660} 678}
661 679
662static inline void audit_zero_context(struct audit_context *context, 680static inline void audit_zero_context(struct audit_context *context,
@@ -798,6 +816,29 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk
798 audit_log_task_context(ab); 816 audit_log_task_context(ab);
799} 817}
800 818
819static int audit_log_pid_context(struct audit_context *context, pid_t pid,
820 u32 sid)
821{
822 struct audit_buffer *ab;
823 char *s = NULL;
824 u32 len;
825 int rc = 0;
826
827 ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
828 if (!ab)
829 return 1;
830
831 if (selinux_sid_to_string(sid, &s, &len)) {
832 audit_log_format(ab, "opid=%d obj=(none)", pid);
833 rc = 1;
834 } else
835 audit_log_format(ab, "opid=%d obj=%s", pid, s);
836 audit_log_end(ab);
837 kfree(s);
838
839 return rc;
840}
841
801static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) 842static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
802{ 843{
803 int i, call_panic = 0; 844 int i, call_panic = 0;
@@ -976,23 +1017,21 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
976 audit_log_end(ab); 1017 audit_log_end(ab);
977 } 1018 }
978 1019
979 if (context->target_pid) { 1020 for (aux = context->aux_pids; aux; aux = aux->next) {
980 ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID); 1021 struct audit_aux_data_pids *axs = (void *)aux;
981 if (ab) { 1022 int i;
982 char *s = NULL, *t; 1023
983 u32 len; 1024 for (i = 0; i < axs->pid_count; i++)
984 if (selinux_sid_to_string(context->target_sid, 1025 if (audit_log_pid_context(context, axs->target_pid[i],
985 &s, &len)) 1026 axs->target_sid[i]))
986 t = "(none)"; 1027 call_panic = 1;
987 else
988 t = s;
989 audit_log_format(ab, "opid=%d obj=%s",
990 context->target_pid, t);
991 audit_log_end(ab);
992 kfree(s);
993 }
994 } 1028 }
995 1029
1030 if (context->target_pid &&
1031 audit_log_pid_context(context, context->target_pid,
1032 context->target_sid))
1033 call_panic = 1;
1034
996 if (context->pwd && context->pwdmnt) { 1035 if (context->pwd && context->pwdmnt) {
997 ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); 1036 ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
998 if (ab) { 1037 if (ab) {
@@ -1213,7 +1252,10 @@ void audit_syscall_exit(int valid, long return_code)
1213 } else { 1252 } else {
1214 audit_free_names(context); 1253 audit_free_names(context);
1215 audit_free_aux(context); 1254 audit_free_aux(context);
1255 context->aux = NULL;
1256 context->aux_pids = NULL;
1216 context->target_pid = 0; 1257 context->target_pid = 0;
1258 context->target_sid = 0;
1217 kfree(context->filterkey); 1259 kfree(context->filterkey);
1218 context->filterkey = NULL; 1260 context->filterkey = NULL;
1219 tsk->audit_context = context; 1261 tsk->audit_context = context;
@@ -1947,15 +1989,17 @@ int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
1947 * If the audit subsystem is being terminated, record the task (pid) 1989 * If the audit subsystem is being terminated, record the task (pid)
1948 * and uid that is doing that. 1990 * and uid that is doing that.
1949 */ 1991 */
1950void __audit_signal_info(int sig, struct task_struct *t) 1992int __audit_signal_info(int sig, struct task_struct *t)
1951{ 1993{
1994 struct audit_aux_data_pids *axp;
1995 struct task_struct *tsk = current;
1996 struct audit_context *ctx = tsk->audit_context;
1952 extern pid_t audit_sig_pid; 1997 extern pid_t audit_sig_pid;
1953 extern uid_t audit_sig_uid; 1998 extern uid_t audit_sig_uid;
1954 extern u32 audit_sig_sid; 1999 extern u32 audit_sig_sid;
1955 2000
1956 if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { 2001 if (audit_pid && t->tgid == audit_pid &&
1957 struct task_struct *tsk = current; 2002 (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) {
1958 struct audit_context *ctx = tsk->audit_context;
1959 audit_sig_pid = tsk->pid; 2003 audit_sig_pid = tsk->pid;
1960 if (ctx) 2004 if (ctx)
1961 audit_sig_uid = ctx->loginuid; 2005 audit_sig_uid = ctx->loginuid;
@@ -1963,4 +2007,33 @@ void __audit_signal_info(int sig, struct task_struct *t)
1963 audit_sig_uid = tsk->uid; 2007 audit_sig_uid = tsk->uid;
1964 selinux_get_task_sid(tsk, &audit_sig_sid); 2008 selinux_get_task_sid(tsk, &audit_sig_sid);
1965 } 2009 }
2010
2011 if (!audit_signals) /* audit_context checked in wrapper */
2012 return 0;
2013
2014 /* optimize the common case by putting first signal recipient directly
2015 * in audit_context */
2016 if (!ctx->target_pid) {
2017 ctx->target_pid = t->tgid;
2018 selinux_get_task_sid(t, &ctx->target_sid);
2019 return 0;
2020 }
2021
2022 axp = (void *)ctx->aux_pids;
2023 if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
2024 axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
2025 if (!axp)
2026 return -ENOMEM;
2027
2028 axp->d.type = AUDIT_OBJ_PID;
2029 axp->d.next = ctx->aux_pids;
2030 ctx->aux_pids = (void *)axp;
2031 }
2032 BUG_ON(axp->pid_count > AUDIT_AUX_PIDS);
2033
2034 axp->target_pid[axp->pid_count] = t->tgid;
2035 selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
2036 axp->pid_count++;
2037
2038 return 0;
1966} 2039}
diff --git a/kernel/signal.c b/kernel/signal.c
index 2ac3a668d9dd..c43a3f19d477 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -497,6 +497,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
497 int error = -EINVAL; 497 int error = -EINVAL;
498 if (!valid_signal(sig)) 498 if (!valid_signal(sig))
499 return error; 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 error = -EPERM; 505 error = -EPERM;
501 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) 506 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
502 && ((sig != SIGCONT) || 507 && ((sig != SIGCONT) ||
@@ -506,10 +511,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
506 && !capable(CAP_KILL)) 511 && !capable(CAP_KILL))
507 return error; 512 return error;
508 513
509 error = security_task_kill(t, info, sig, 0); 514 return security_task_kill(t, info, sig, 0);
510 if (!error)
511 audit_signal_info(sig, t); /* Let audit system see the signal */
512 return error;
513} 515}
514 516
515/* forward decl */ 517/* forward decl */