aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-19 14:35:50 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-06-19 14:35:50 -0400
commit0f45aa18e65cf3d768082d7d86054a0d2a20bb18 (patch)
tree6e94dfcd813061f5a710b5621e1b2f5a01a95533
parent0107b3cf3225aed6ddde4fa8dbcd4ed643b34f4d (diff)
AUDIT: Allow filtering of user messages
Turn the field from a bitmask to an enumeration and add a list to allow filtering of messages generated by userspace. We also define a list for file system watches in anticipation of that feature. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--include/linux/audit.h15
-rw-r--r--kernel/audit.c36
-rw-r--r--kernel/auditsc.c92
3 files changed, 85 insertions, 58 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index bf2ad3ba72eb..b5bda24f7365 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -75,10 +75,15 @@
75#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */ 75#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
76 76
77/* Rule flags */ 77/* Rule flags */
78#define AUDIT_PER_TASK 0x01 /* Apply rule at task creation (not syscall) */ 78#define AUDIT_FILTER_USER 0x00 /* Apply rule to user-generated messages */
79#define AUDIT_AT_ENTRY 0x02 /* Apply rule at syscall entry */ 79#define AUDIT_FILTER_TASK 0x01 /* Apply rule at task creation (not syscall) */
80#define AUDIT_AT_EXIT 0x04 /* Apply rule at syscall exit */ 80#define AUDIT_FILTER_ENTRY 0x02 /* Apply rule at syscall entry */
81#define AUDIT_PREPEND 0x10 /* Prepend to front of list */ 81#define AUDIT_FILTER_WATCH 0x03 /* Apply rule to file system watches */
82#define AUDIT_FILTER_EXIT 0x04 /* Apply rule at syscall exit */
83
84#define AUDIT_NR_FILTERS 5
85
86#define AUDIT_FILTER_PREPEND 0x10 /* Prepend to front of list */
82 87
83/* Rule actions */ 88/* Rule actions */
84#define AUDIT_NEVER 0 /* Do not build context if rule matches */ 89#define AUDIT_NEVER 0 /* Do not build context if rule matches */
@@ -230,6 +235,7 @@ extern int audit_socketcall(int nargs, unsigned long *args);
230extern int audit_sockaddr(int len, void *addr); 235extern int audit_sockaddr(int len, void *addr);
231extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); 236extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
232extern void audit_signal_info(int sig, struct task_struct *t); 237extern void audit_signal_info(int sig, struct task_struct *t);
238extern int audit_filter_user(struct task_struct *tsk, int type);
233#else 239#else
234#define audit_alloc(t) ({ 0; }) 240#define audit_alloc(t) ({ 0; })
235#define audit_free(t) do { ; } while (0) 241#define audit_free(t) do { ; } while (0)
@@ -246,6 +252,7 @@ extern void audit_signal_info(int sig, struct task_struct *t);
246#define audit_sockaddr(len, addr) ({ 0; }) 252#define audit_sockaddr(len, addr) ({ 0; })
247#define audit_avc_path(dentry, mnt) ({ 0; }) 253#define audit_avc_path(dentry, mnt) ({ 0; })
248#define audit_signal_info(s,t) do { ; } while (0) 254#define audit_signal_info(s,t) do { ; } while (0)
255#define audit_filter_user(struct ({ 1; })
249#endif 256#endif
250 257
251#ifdef CONFIG_AUDIT 258#ifdef CONFIG_AUDIT
diff --git a/kernel/audit.c b/kernel/audit.c
index ef35166fdc29..f0bbfe073136 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -107,13 +107,6 @@ static struct sk_buff_head audit_skb_queue;
107static struct task_struct *kauditd_task; 107static struct task_struct *kauditd_task;
108static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); 108static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
109 109
110/* There are three lists of rules -- one to search at task creation
111 * time, one to search at syscall entry time, and another to search at
112 * syscall exit time. */
113static LIST_HEAD(audit_tsklist);
114static LIST_HEAD(audit_entlist);
115static LIST_HEAD(audit_extlist);
116
117/* The netlink socket is only to be read by 1 CPU, which lets us assume 110/* The netlink socket is only to be read by 1 CPU, which lets us assume
118 * that list additions and deletions never happen simultaneously in 111 * that list additions and deletions never happen simultaneously in
119 * auditsc.c */ 112 * auditsc.c */
@@ -376,6 +369,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
376 u16 msg_type = nlh->nlmsg_type; 369 u16 msg_type = nlh->nlmsg_type;
377 uid_t loginuid; /* loginuid of sender */ 370 uid_t loginuid; /* loginuid of sender */
378 struct audit_sig_info sig_data; 371 struct audit_sig_info sig_data;
372 struct task_struct *tsk;
379 373
380 err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); 374 err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
381 if (err) 375 if (err)
@@ -435,15 +429,25 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
435 break; 429 break;
436 case AUDIT_USER: 430 case AUDIT_USER:
437 case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: 431 case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
438 ab = audit_log_start(NULL, msg_type); 432 read_lock(&tasklist_lock);
439 if (!ab) 433 tsk = find_task_by_pid(pid);
440 break; /* audit_panic has been called */ 434 if (tsk)
441 audit_log_format(ab, 435 get_task_struct(tsk);
442 "user pid=%d uid=%u auid=%u" 436 read_unlock(&tasklist_lock);
443 " msg='%.1024s'", 437 if (!tsk)
444 pid, uid, loginuid, (char *)data); 438 return -ESRCH;
445 audit_set_pid(ab, pid); 439
446 audit_log_end(ab); 440 if (audit_filter_user(tsk, msg_type)) {
441 ab = audit_log_start(NULL, msg_type);
442 if (ab) {
443 audit_log_format(ab,
444 "user pid=%d uid=%u auid=%u msg='%.1024s'",
445 pid, uid, loginuid, (char *)data);
446 audit_set_pid(ab, pid);
447 audit_log_end(ab);
448 }
449 }
450 put_task_struct(tsk);
447 break; 451 break;
448 case AUDIT_ADD: 452 case AUDIT_ADD:
449 case AUDIT_DEL: 453 case AUDIT_DEL:
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e75f84e1a1a0..6b4fbb1c0129 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -167,9 +167,16 @@ struct audit_context {
167/* There are three lists of rules -- one to search at task creation 167/* There are three lists of rules -- one to search at task creation
168 * time, one to search at syscall entry time, and another to search at 168 * time, one to search at syscall entry time, and another to search at
169 * syscall exit time. */ 169 * syscall exit time. */
170static LIST_HEAD(audit_tsklist); 170static struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
171static LIST_HEAD(audit_entlist); 171 LIST_HEAD_INIT(audit_filter_list[0]),
172static LIST_HEAD(audit_extlist); 172 LIST_HEAD_INIT(audit_filter_list[1]),
173 LIST_HEAD_INIT(audit_filter_list[2]),
174 LIST_HEAD_INIT(audit_filter_list[3]),
175 LIST_HEAD_INIT(audit_filter_list[4]),
176#if AUDIT_NR_FILTERS != 5
177#error Fix audit_filter_list initialiser
178#endif
179};
173 180
174struct audit_entry { 181struct audit_entry {
175 struct list_head list; 182 struct list_head list;
@@ -210,16 +217,15 @@ static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
210/* Note that audit_add_rule and audit_del_rule are called via 217/* Note that audit_add_rule and audit_del_rule are called via
211 * audit_receive() in audit.c, and are protected by 218 * audit_receive() in audit.c, and are protected by
212 * audit_netlink_sem. */ 219 * audit_netlink_sem. */
213static inline int audit_add_rule(struct audit_entry *entry, 220static inline void audit_add_rule(struct audit_entry *entry,
214 struct list_head *list) 221 struct list_head *list)
215{ 222{
216 if (entry->rule.flags & AUDIT_PREPEND) { 223 if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
217 entry->rule.flags &= ~AUDIT_PREPEND; 224 entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
218 list_add_rcu(&entry->list, list); 225 list_add_rcu(&entry->list, list);
219 } else { 226 } else {
220 list_add_tail_rcu(&entry->list, list); 227 list_add_tail_rcu(&entry->list, list);
221 } 228 }
222 return 0;
223} 229}
224 230
225static void audit_free_rule(struct rcu_head *head) 231static void audit_free_rule(struct rcu_head *head)
@@ -245,7 +251,7 @@ static inline int audit_del_rule(struct audit_rule *rule,
245 return 0; 251 return 0;
246 } 252 }
247 } 253 }
248 return -EFAULT; /* No matching rule */ 254 return -ENOENT; /* No matching rule */
249} 255}
250 256
251/* Copy rule from user-space to kernel-space. Called during 257/* Copy rule from user-space to kernel-space. Called during
@@ -260,6 +266,8 @@ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
260 return -1; 266 return -1;
261 if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS) 267 if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
262 return -1; 268 return -1;
269 if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
270 return -1;
263 271
264 d->flags = s->flags; 272 d->flags = s->flags;
265 d->action = s->action; 273 d->action = s->action;
@@ -275,23 +283,20 @@ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
275int audit_receive_filter(int type, int pid, int uid, int seq, void *data, 283int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
276 uid_t loginuid) 284 uid_t loginuid)
277{ 285{
278 u32 flags;
279 struct audit_entry *entry; 286 struct audit_entry *entry;
280 int err = 0; 287 int err = 0;
288 int i;
289 unsigned listnr;
281 290
282 switch (type) { 291 switch (type) {
283 case AUDIT_LIST: 292 case AUDIT_LIST:
284 /* The *_rcu iterators not needed here because we are 293 /* The *_rcu iterators not needed here because we are
285 always called with audit_netlink_sem held. */ 294 always called with audit_netlink_sem held. */
286 list_for_each_entry(entry, &audit_tsklist, list) 295 for (i=0; i<AUDIT_NR_FILTERS; i++) {
287 audit_send_reply(pid, seq, AUDIT_LIST, 0, 1, 296 list_for_each_entry(entry, &audit_filter_list[i], list)
288 &entry->rule, sizeof(entry->rule)); 297 audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
289 list_for_each_entry(entry, &audit_entlist, list) 298 &entry->rule, sizeof(entry->rule));
290 audit_send_reply(pid, seq, AUDIT_LIST, 0, 1, 299 }
291 &entry->rule, sizeof(entry->rule));
292 list_for_each_entry(entry, &audit_extlist, list)
293 audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
294 &entry->rule, sizeof(entry->rule));
295 audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0); 300 audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
296 break; 301 break;
297 case AUDIT_ADD: 302 case AUDIT_ADD:
@@ -301,26 +306,20 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
301 kfree(entry); 306 kfree(entry);
302 return -EINVAL; 307 return -EINVAL;
303 } 308 }
304 flags = entry->rule.flags; 309 listnr = entry->rule.flags & ~AUDIT_FILTER_PREPEND;
305 if (!err && (flags & AUDIT_PER_TASK)) 310 audit_add_rule(entry, &audit_filter_list[listnr]);
306 err = audit_add_rule(entry, &audit_tsklist);
307 if (!err && (flags & AUDIT_AT_ENTRY))
308 err = audit_add_rule(entry, &audit_entlist);
309 if (!err && (flags & AUDIT_AT_EXIT))
310 err = audit_add_rule(entry, &audit_extlist);
311 audit_log(NULL, AUDIT_CONFIG_CHANGE, 311 audit_log(NULL, AUDIT_CONFIG_CHANGE,
312 "auid=%u added an audit rule\n", loginuid); 312 "auid=%u added an audit rule\n", loginuid);
313 break; 313 break;
314 case AUDIT_DEL: 314 case AUDIT_DEL:
315 flags =((struct audit_rule *)data)->flags; 315 listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
316 if (!err && (flags & AUDIT_PER_TASK)) 316 if (listnr >= AUDIT_NR_FILTERS)
317 err = audit_del_rule(data, &audit_tsklist); 317 return -EINVAL;
318 if (!err && (flags & AUDIT_AT_ENTRY)) 318
319 err = audit_del_rule(data, &audit_entlist); 319 err = audit_del_rule(data, &audit_filter_list[listnr]);
320 if (!err && (flags & AUDIT_AT_EXIT)) 320 if (!err)
321 err = audit_del_rule(data, &audit_extlist); 321 audit_log(NULL, AUDIT_CONFIG_CHANGE,
322 audit_log(NULL, AUDIT_CONFIG_CHANGE, 322 "auid=%u removed an audit rule\n", loginuid);
323 "auid=%u removed an audit rule\n", loginuid);
324 break; 323 break;
325 default: 324 default:
326 return -EINVAL; 325 return -EINVAL;
@@ -454,7 +453,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
454 enum audit_state state; 453 enum audit_state state;
455 454
456 rcu_read_lock(); 455 rcu_read_lock();
457 list_for_each_entry_rcu(e, &audit_tsklist, list) { 456 list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
458 if (audit_filter_rules(tsk, &e->rule, NULL, &state)) { 457 if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
459 rcu_read_unlock(); 458 rcu_read_unlock();
460 return state; 459 return state;
@@ -490,6 +489,23 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
490 return AUDIT_BUILD_CONTEXT; 489 return AUDIT_BUILD_CONTEXT;
491} 490}
492 491
492int audit_filter_user(struct task_struct *tsk, int type)
493{
494 struct audit_entry *e;
495 enum audit_state state;
496
497 rcu_read_lock();
498 list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
499 if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
500 rcu_read_unlock();
501 return state != AUDIT_DISABLED;
502 }
503 }
504 rcu_read_unlock();
505 return 1; /* Audit by default */
506
507}
508
493/* This should be called with task_lock() held. */ 509/* This should be called with task_lock() held. */
494static inline struct audit_context *audit_get_context(struct task_struct *tsk, 510static inline struct audit_context *audit_get_context(struct task_struct *tsk,
495 int return_valid, 511 int return_valid,
@@ -504,7 +520,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
504 520
505 if (context->in_syscall && !context->auditable) { 521 if (context->in_syscall && !context->auditable) {
506 enum audit_state state; 522 enum audit_state state;
507 state = audit_filter_syscall(tsk, context, &audit_extlist); 523 state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
508 if (state == AUDIT_RECORD_CONTEXT) 524 if (state == AUDIT_RECORD_CONTEXT)
509 context->auditable = 1; 525 context->auditable = 1;
510 } 526 }
@@ -876,7 +892,7 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
876 892
877 state = context->state; 893 state = context->state;
878 if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT) 894 if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)
879 state = audit_filter_syscall(tsk, context, &audit_entlist); 895 state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
880 if (likely(state == AUDIT_DISABLED)) 896 if (likely(state == AUDIT_DISABLED))
881 return; 897 return;
882 898