diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit.c | 249 | ||||
| -rw-r--r-- | kernel/audit.h | 13 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 45 | ||||
| -rw-r--r-- | kernel/auditsc.c | 40 |
4 files changed, 235 insertions, 112 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index a7b16086d36f..b7d3709cc452 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -126,6 +126,8 @@ static int audit_freelist_count; | |||
| 126 | static LIST_HEAD(audit_freelist); | 126 | static LIST_HEAD(audit_freelist); |
| 127 | 127 | ||
| 128 | static struct sk_buff_head audit_skb_queue; | 128 | static struct sk_buff_head audit_skb_queue; |
| 129 | /* queue of skbs to send to auditd when/if it comes back */ | ||
| 130 | static struct sk_buff_head audit_skb_hold_queue; | ||
| 129 | static struct task_struct *kauditd_task; | 131 | static struct task_struct *kauditd_task; |
| 130 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | 132 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); |
| 131 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | 133 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); |
| @@ -154,6 +156,11 @@ struct audit_buffer { | |||
| 154 | gfp_t gfp_mask; | 156 | gfp_t gfp_mask; |
| 155 | }; | 157 | }; |
| 156 | 158 | ||
| 159 | struct audit_reply { | ||
| 160 | int pid; | ||
| 161 | struct sk_buff *skb; | ||
| 162 | }; | ||
| 163 | |||
| 157 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) | 164 | static void audit_set_pid(struct audit_buffer *ab, pid_t pid) |
| 158 | { | 165 | { |
| 159 | if (ab) { | 166 | if (ab) { |
| @@ -252,14 +259,15 @@ void audit_log_lost(const char *message) | |||
| 252 | } | 259 | } |
| 253 | 260 | ||
| 254 | static int audit_log_config_change(char *function_name, int new, int old, | 261 | static int audit_log_config_change(char *function_name, int new, int old, |
| 255 | uid_t loginuid, u32 sid, int allow_changes) | 262 | uid_t loginuid, u32 sessionid, u32 sid, |
| 263 | int allow_changes) | ||
| 256 | { | 264 | { |
| 257 | struct audit_buffer *ab; | 265 | struct audit_buffer *ab; |
| 258 | int rc = 0; | 266 | int rc = 0; |
| 259 | 267 | ||
| 260 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 268 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 261 | audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new, | 269 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, |
| 262 | old, loginuid); | 270 | old, loginuid, sessionid); |
| 263 | if (sid) { | 271 | if (sid) { |
| 264 | char *ctx = NULL; | 272 | char *ctx = NULL; |
| 265 | u32 len; | 273 | u32 len; |
| @@ -279,7 +287,8 @@ static int audit_log_config_change(char *function_name, int new, int old, | |||
| 279 | } | 287 | } |
| 280 | 288 | ||
| 281 | static int audit_do_config_change(char *function_name, int *to_change, | 289 | static int audit_do_config_change(char *function_name, int *to_change, |
| 282 | int new, uid_t loginuid, u32 sid) | 290 | int new, uid_t loginuid, u32 sessionid, |
| 291 | u32 sid) | ||
| 283 | { | 292 | { |
| 284 | int allow_changes, rc = 0, old = *to_change; | 293 | int allow_changes, rc = 0, old = *to_change; |
| 285 | 294 | ||
| @@ -290,8 +299,8 @@ static int audit_do_config_change(char *function_name, int *to_change, | |||
| 290 | allow_changes = 1; | 299 | allow_changes = 1; |
| 291 | 300 | ||
| 292 | if (audit_enabled != AUDIT_OFF) { | 301 | if (audit_enabled != AUDIT_OFF) { |
| 293 | rc = audit_log_config_change(function_name, new, old, | 302 | rc = audit_log_config_change(function_name, new, old, loginuid, |
| 294 | loginuid, sid, allow_changes); | 303 | sessionid, sid, allow_changes); |
| 295 | if (rc) | 304 | if (rc) |
| 296 | allow_changes = 0; | 305 | allow_changes = 0; |
| 297 | } | 306 | } |
| @@ -305,26 +314,28 @@ static int audit_do_config_change(char *function_name, int *to_change, | |||
| 305 | return rc; | 314 | return rc; |
| 306 | } | 315 | } |
| 307 | 316 | ||
| 308 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) | 317 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid, |
| 318 | u32 sid) | ||
| 309 | { | 319 | { |
| 310 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, | 320 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, |
| 311 | limit, loginuid, sid); | 321 | limit, loginuid, sessionid, sid); |
| 312 | } | 322 | } |
| 313 | 323 | ||
| 314 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) | 324 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid, |
| 325 | u32 sid) | ||
| 315 | { | 326 | { |
| 316 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, | 327 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, |
| 317 | limit, loginuid, sid); | 328 | limit, loginuid, sessionid, sid); |
| 318 | } | 329 | } |
| 319 | 330 | ||
| 320 | static int audit_set_enabled(int state, uid_t loginuid, u32 sid) | 331 | static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid) |
| 321 | { | 332 | { |
| 322 | int rc; | 333 | int rc; |
| 323 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) | 334 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) |
| 324 | return -EINVAL; | 335 | return -EINVAL; |
| 325 | 336 | ||
| 326 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state, | 337 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state, |
| 327 | loginuid, sid); | 338 | loginuid, sessionid, sid); |
| 328 | 339 | ||
| 329 | if (!rc) | 340 | if (!rc) |
| 330 | audit_ever_enabled |= !!state; | 341 | audit_ever_enabled |= !!state; |
| @@ -332,7 +343,7 @@ static int audit_set_enabled(int state, uid_t loginuid, u32 sid) | |||
| 332 | return rc; | 343 | return rc; |
| 333 | } | 344 | } |
| 334 | 345 | ||
| 335 | static int audit_set_failure(int state, uid_t loginuid, u32 sid) | 346 | static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid) |
| 336 | { | 347 | { |
| 337 | if (state != AUDIT_FAIL_SILENT | 348 | if (state != AUDIT_FAIL_SILENT |
| 338 | && state != AUDIT_FAIL_PRINTK | 349 | && state != AUDIT_FAIL_PRINTK |
| @@ -340,7 +351,43 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sid) | |||
| 340 | return -EINVAL; | 351 | return -EINVAL; |
| 341 | 352 | ||
| 342 | return audit_do_config_change("audit_failure", &audit_failure, state, | 353 | return audit_do_config_change("audit_failure", &audit_failure, state, |
| 343 | loginuid, sid); | 354 | loginuid, sessionid, sid); |
| 355 | } | ||
| 356 | |||
| 357 | /* | ||
| 358 | * Queue skbs to be sent to auditd when/if it comes back. These skbs should | ||
| 359 | * already have been sent via prink/syslog and so if these messages are dropped | ||
| 360 | * it is not a huge concern since we already passed the audit_log_lost() | ||
| 361 | * notification and stuff. This is just nice to get audit messages during | ||
| 362 | * boot before auditd is running or messages generated while auditd is stopped. | ||
| 363 | * This only holds messages is audit_default is set, aka booting with audit=1 | ||
| 364 | * or building your kernel that way. | ||
| 365 | */ | ||
| 366 | static void audit_hold_skb(struct sk_buff *skb) | ||
| 367 | { | ||
| 368 | if (audit_default && | ||
| 369 | skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit) | ||
| 370 | skb_queue_tail(&audit_skb_hold_queue, skb); | ||
| 371 | else | ||
| 372 | kfree_skb(skb); | ||
| 373 | } | ||
| 374 | |||
| 375 | static void kauditd_send_skb(struct sk_buff *skb) | ||
| 376 | { | ||
| 377 | int err; | ||
| 378 | /* take a reference in case we can't send it and we want to hold it */ | ||
| 379 | skb_get(skb); | ||
| 380 | err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0); | ||
| 381 | if (err < 0) { | ||
| 382 | BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */ | ||
| 383 | printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); | ||
| 384 | audit_log_lost("auditd dissapeared\n"); | ||
| 385 | audit_pid = 0; | ||
| 386 | /* we might get lucky and get this in the next auditd */ | ||
| 387 | audit_hold_skb(skb); | ||
| 388 | } else | ||
| 389 | /* drop the extra reference if sent ok */ | ||
| 390 | kfree_skb(skb); | ||
| 344 | } | 391 | } |
| 345 | 392 | ||
| 346 | static int kauditd_thread(void *dummy) | 393 | static int kauditd_thread(void *dummy) |
| @@ -349,24 +396,41 @@ static int kauditd_thread(void *dummy) | |||
| 349 | 396 | ||
| 350 | set_freezable(); | 397 | set_freezable(); |
| 351 | while (!kthread_should_stop()) { | 398 | while (!kthread_should_stop()) { |
| 399 | /* | ||
| 400 | * if auditd just started drain the queue of messages already | ||
| 401 | * sent to syslog/printk. remember loss here is ok. we already | ||
| 402 | * called audit_log_lost() if it didn't go out normally. so the | ||
| 403 | * race between the skb_dequeue and the next check for audit_pid | ||
| 404 | * doesn't matter. | ||
| 405 | * | ||
| 406 | * if you ever find kauditd to be too slow we can get a perf win | ||
| 407 | * by doing our own locking and keeping better track if there | ||
| 408 | * are messages in this queue. I don't see the need now, but | ||
| 409 | * in 5 years when I want to play with this again I'll see this | ||
| 410 | * note and still have no friggin idea what i'm thinking today. | ||
| 411 | */ | ||
| 412 | if (audit_default && audit_pid) { | ||
| 413 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 414 | if (unlikely(skb)) { | ||
| 415 | while (skb && audit_pid) { | ||
| 416 | kauditd_send_skb(skb); | ||
| 417 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 352 | skb = skb_dequeue(&audit_skb_queue); | 422 | skb = skb_dequeue(&audit_skb_queue); |
| 353 | wake_up(&audit_backlog_wait); | 423 | wake_up(&audit_backlog_wait); |
| 354 | if (skb) { | 424 | if (skb) { |
| 355 | if (audit_pid) { | 425 | if (audit_pid) |
| 356 | int err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0); | 426 | kauditd_send_skb(skb); |
| 357 | if (err < 0) { | 427 | else { |
| 358 | BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */ | ||
| 359 | printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); | ||
| 360 | audit_log_lost("auditd dissapeared\n"); | ||
| 361 | audit_pid = 0; | ||
| 362 | } | ||
| 363 | } else { | ||
| 364 | if (printk_ratelimit()) | 428 | if (printk_ratelimit()) |
| 365 | printk(KERN_NOTICE "%s\n", skb->data + | 429 | printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0)); |
| 366 | NLMSG_SPACE(0)); | ||
| 367 | else | 430 | else |
| 368 | audit_log_lost("printk limit exceeded\n"); | 431 | audit_log_lost("printk limit exceeded\n"); |
| 369 | kfree_skb(skb); | 432 | |
| 433 | audit_hold_skb(skb); | ||
| 370 | } | 434 | } |
| 371 | } else { | 435 | } else { |
| 372 | DECLARE_WAITQUEUE(wait, current); | 436 | DECLARE_WAITQUEUE(wait, current); |
| @@ -385,13 +449,13 @@ static int kauditd_thread(void *dummy) | |||
| 385 | return 0; | 449 | return 0; |
| 386 | } | 450 | } |
| 387 | 451 | ||
| 388 | static int audit_prepare_user_tty(pid_t pid, uid_t loginuid) | 452 | static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid) |
| 389 | { | 453 | { |
| 390 | struct task_struct *tsk; | 454 | struct task_struct *tsk; |
| 391 | int err; | 455 | int err; |
| 392 | 456 | ||
| 393 | read_lock(&tasklist_lock); | 457 | read_lock(&tasklist_lock); |
| 394 | tsk = find_task_by_pid(pid); | 458 | tsk = find_task_by_vpid(pid); |
| 395 | err = -ESRCH; | 459 | err = -ESRCH; |
| 396 | if (!tsk) | 460 | if (!tsk) |
| 397 | goto out; | 461 | goto out; |
| @@ -404,7 +468,7 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid) | |||
| 404 | if (err) | 468 | if (err) |
| 405 | goto out; | 469 | goto out; |
| 406 | 470 | ||
| 407 | tty_audit_push_task(tsk, loginuid); | 471 | tty_audit_push_task(tsk, loginuid, sessionid); |
| 408 | out: | 472 | out: |
| 409 | read_unlock(&tasklist_lock); | 473 | read_unlock(&tasklist_lock); |
| 410 | return err; | 474 | return err; |
| @@ -469,6 +533,19 @@ nlmsg_failure: /* Used by NLMSG_PUT */ | |||
| 469 | return NULL; | 533 | return NULL; |
| 470 | } | 534 | } |
| 471 | 535 | ||
| 536 | static int audit_send_reply_thread(void *arg) | ||
| 537 | { | ||
| 538 | struct audit_reply *reply = (struct audit_reply *)arg; | ||
| 539 | |||
| 540 | mutex_lock(&audit_cmd_mutex); | ||
| 541 | mutex_unlock(&audit_cmd_mutex); | ||
| 542 | |||
| 543 | /* Ignore failure. It'll only happen if the sender goes away, | ||
| 544 | because our timeout is set to infinite. */ | ||
| 545 | netlink_unicast(audit_sock, reply->skb, reply->pid, 0); | ||
| 546 | kfree(reply); | ||
| 547 | return 0; | ||
| 548 | } | ||
| 472 | /** | 549 | /** |
| 473 | * audit_send_reply - send an audit reply message via netlink | 550 | * audit_send_reply - send an audit reply message via netlink |
| 474 | * @pid: process id to send reply to | 551 | * @pid: process id to send reply to |
| @@ -485,14 +562,26 @@ nlmsg_failure: /* Used by NLMSG_PUT */ | |||
| 485 | void audit_send_reply(int pid, int seq, int type, int done, int multi, | 562 | void audit_send_reply(int pid, int seq, int type, int done, int multi, |
| 486 | void *payload, int size) | 563 | void *payload, int size) |
| 487 | { | 564 | { |
| 488 | struct sk_buff *skb; | 565 | struct sk_buff *skb; |
| 566 | struct task_struct *tsk; | ||
| 567 | struct audit_reply *reply = kmalloc(sizeof(struct audit_reply), | ||
| 568 | GFP_KERNEL); | ||
| 569 | |||
| 570 | if (!reply) | ||
| 571 | return; | ||
| 572 | |||
| 489 | skb = audit_make_reply(pid, seq, type, done, multi, payload, size); | 573 | skb = audit_make_reply(pid, seq, type, done, multi, payload, size); |
| 490 | if (!skb) | 574 | if (!skb) |
| 491 | return; | 575 | return; |
| 492 | /* Ignore failure. It'll only happen if the sender goes away, | 576 | |
| 493 | because our timeout is set to infinite. */ | 577 | reply->pid = pid; |
| 494 | netlink_unicast(audit_sock, skb, pid, 0); | 578 | reply->skb = skb; |
| 495 | return; | 579 | |
| 580 | tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); | ||
| 581 | if (IS_ERR(tsk)) { | ||
| 582 | kfree(reply); | ||
| 583 | kfree_skb(skb); | ||
| 584 | } | ||
| 496 | } | 585 | } |
| 497 | 586 | ||
| 498 | /* | 587 | /* |
| @@ -534,7 +623,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 534 | } | 623 | } |
| 535 | 624 | ||
| 536 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | 625 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, |
| 537 | u32 pid, u32 uid, uid_t auid, u32 sid) | 626 | u32 pid, u32 uid, uid_t auid, u32 ses, |
| 627 | u32 sid) | ||
| 538 | { | 628 | { |
| 539 | int rc = 0; | 629 | int rc = 0; |
| 540 | char *ctx = NULL; | 630 | char *ctx = NULL; |
| @@ -546,8 +636,8 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | |||
| 546 | } | 636 | } |
| 547 | 637 | ||
| 548 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 638 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
| 549 | audit_log_format(*ab, "user pid=%d uid=%u auid=%u", | 639 | audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u", |
| 550 | pid, uid, auid); | 640 | pid, uid, auid, ses); |
| 551 | if (sid) { | 641 | if (sid) { |
| 552 | rc = security_secid_to_secctx(sid, &ctx, &len); | 642 | rc = security_secid_to_secctx(sid, &ctx, &len); |
| 553 | if (rc) | 643 | if (rc) |
| @@ -570,6 +660,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 570 | struct audit_buffer *ab; | 660 | struct audit_buffer *ab; |
| 571 | u16 msg_type = nlh->nlmsg_type; | 661 | u16 msg_type = nlh->nlmsg_type; |
| 572 | uid_t loginuid; /* loginuid of sender */ | 662 | uid_t loginuid; /* loginuid of sender */ |
| 663 | u32 sessionid; | ||
| 573 | struct audit_sig_info *sig_data; | 664 | struct audit_sig_info *sig_data; |
| 574 | char *ctx = NULL; | 665 | char *ctx = NULL; |
| 575 | u32 len; | 666 | u32 len; |
| @@ -591,6 +682,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 591 | pid = NETLINK_CREDS(skb)->pid; | 682 | pid = NETLINK_CREDS(skb)->pid; |
| 592 | uid = NETLINK_CREDS(skb)->uid; | 683 | uid = NETLINK_CREDS(skb)->uid; |
| 593 | loginuid = NETLINK_CB(skb).loginuid; | 684 | loginuid = NETLINK_CB(skb).loginuid; |
| 685 | sessionid = NETLINK_CB(skb).sessionid; | ||
| 594 | sid = NETLINK_CB(skb).sid; | 686 | sid = NETLINK_CB(skb).sid; |
| 595 | seq = nlh->nlmsg_seq; | 687 | seq = nlh->nlmsg_seq; |
| 596 | data = NLMSG_DATA(nlh); | 688 | data = NLMSG_DATA(nlh); |
| @@ -613,12 +705,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 613 | status_get = (struct audit_status *)data; | 705 | status_get = (struct audit_status *)data; |
| 614 | if (status_get->mask & AUDIT_STATUS_ENABLED) { | 706 | if (status_get->mask & AUDIT_STATUS_ENABLED) { |
| 615 | err = audit_set_enabled(status_get->enabled, | 707 | err = audit_set_enabled(status_get->enabled, |
| 616 | loginuid, sid); | 708 | loginuid, sessionid, sid); |
| 617 | if (err < 0) return err; | 709 | if (err < 0) return err; |
| 618 | } | 710 | } |
| 619 | if (status_get->mask & AUDIT_STATUS_FAILURE) { | 711 | if (status_get->mask & AUDIT_STATUS_FAILURE) { |
| 620 | err = audit_set_failure(status_get->failure, | 712 | err = audit_set_failure(status_get->failure, |
| 621 | loginuid, sid); | 713 | loginuid, sessionid, sid); |
| 622 | if (err < 0) return err; | 714 | if (err < 0) return err; |
| 623 | } | 715 | } |
| 624 | if (status_get->mask & AUDIT_STATUS_PID) { | 716 | if (status_get->mask & AUDIT_STATUS_PID) { |
| @@ -627,17 +719,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 627 | if (audit_enabled != AUDIT_OFF) | 719 | if (audit_enabled != AUDIT_OFF) |
| 628 | audit_log_config_change("audit_pid", new_pid, | 720 | audit_log_config_change("audit_pid", new_pid, |
| 629 | audit_pid, loginuid, | 721 | audit_pid, loginuid, |
| 630 | sid, 1); | 722 | sessionid, sid, 1); |
| 631 | 723 | ||
| 632 | audit_pid = new_pid; | 724 | audit_pid = new_pid; |
| 633 | audit_nlk_pid = NETLINK_CB(skb).pid; | 725 | audit_nlk_pid = NETLINK_CB(skb).pid; |
| 634 | } | 726 | } |
| 635 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) | 727 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) |
| 636 | err = audit_set_rate_limit(status_get->rate_limit, | 728 | err = audit_set_rate_limit(status_get->rate_limit, |
| 637 | loginuid, sid); | 729 | loginuid, sessionid, sid); |
| 638 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 730 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
| 639 | err = audit_set_backlog_limit(status_get->backlog_limit, | 731 | err = audit_set_backlog_limit(status_get->backlog_limit, |
| 640 | loginuid, sid); | 732 | loginuid, sessionid, sid); |
| 641 | break; | 733 | break; |
| 642 | case AUDIT_USER: | 734 | case AUDIT_USER: |
| 643 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: | 735 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: |
| @@ -649,12 +741,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 649 | if (err == 1) { | 741 | if (err == 1) { |
| 650 | err = 0; | 742 | err = 0; |
| 651 | if (msg_type == AUDIT_USER_TTY) { | 743 | if (msg_type == AUDIT_USER_TTY) { |
| 652 | err = audit_prepare_user_tty(pid, loginuid); | 744 | err = audit_prepare_user_tty(pid, loginuid, |
| 745 | sessionid); | ||
| 653 | if (err) | 746 | if (err) |
| 654 | break; | 747 | break; |
| 655 | } | 748 | } |
| 656 | audit_log_common_recv_msg(&ab, msg_type, pid, uid, | 749 | audit_log_common_recv_msg(&ab, msg_type, pid, uid, |
| 657 | loginuid, sid); | 750 | loginuid, sessionid, sid); |
| 658 | 751 | ||
| 659 | if (msg_type != AUDIT_USER_TTY) | 752 | if (msg_type != AUDIT_USER_TTY) |
| 660 | audit_log_format(ab, " msg='%.1024s'", | 753 | audit_log_format(ab, " msg='%.1024s'", |
| @@ -664,8 +757,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 664 | 757 | ||
| 665 | audit_log_format(ab, " msg="); | 758 | audit_log_format(ab, " msg="); |
| 666 | size = nlmsg_len(nlh); | 759 | size = nlmsg_len(nlh); |
| 667 | audit_log_n_untrustedstring(ab, size, | 760 | audit_log_n_untrustedstring(ab, data, size); |
| 668 | data); | ||
| 669 | } | 761 | } |
| 670 | audit_set_pid(ab, pid); | 762 | audit_set_pid(ab, pid); |
| 671 | audit_log_end(ab); | 763 | audit_log_end(ab); |
| @@ -677,7 +769,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 677 | return -EINVAL; | 769 | return -EINVAL; |
| 678 | if (audit_enabled == AUDIT_LOCKED) { | 770 | if (audit_enabled == AUDIT_LOCKED) { |
| 679 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 771 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 680 | uid, loginuid, sid); | 772 | uid, loginuid, sessionid, sid); |
| 681 | 773 | ||
| 682 | audit_log_format(ab, " audit_enabled=%d res=0", | 774 | audit_log_format(ab, " audit_enabled=%d res=0", |
| 683 | audit_enabled); | 775 | audit_enabled); |
| @@ -688,7 +780,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 688 | case AUDIT_LIST: | 780 | case AUDIT_LIST: |
| 689 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, | 781 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, |
| 690 | uid, seq, data, nlmsg_len(nlh), | 782 | uid, seq, data, nlmsg_len(nlh), |
| 691 | loginuid, sid); | 783 | loginuid, sessionid, sid); |
| 692 | break; | 784 | break; |
| 693 | case AUDIT_ADD_RULE: | 785 | case AUDIT_ADD_RULE: |
| 694 | case AUDIT_DEL_RULE: | 786 | case AUDIT_DEL_RULE: |
| @@ -696,7 +788,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 696 | return -EINVAL; | 788 | return -EINVAL; |
| 697 | if (audit_enabled == AUDIT_LOCKED) { | 789 | if (audit_enabled == AUDIT_LOCKED) { |
| 698 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 790 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 699 | uid, loginuid, sid); | 791 | uid, loginuid, sessionid, sid); |
| 700 | 792 | ||
| 701 | audit_log_format(ab, " audit_enabled=%d res=0", | 793 | audit_log_format(ab, " audit_enabled=%d res=0", |
| 702 | audit_enabled); | 794 | audit_enabled); |
| @@ -707,13 +799,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 707 | case AUDIT_LIST_RULES: | 799 | case AUDIT_LIST_RULES: |
| 708 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, | 800 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, |
| 709 | uid, seq, data, nlmsg_len(nlh), | 801 | uid, seq, data, nlmsg_len(nlh), |
| 710 | loginuid, sid); | 802 | loginuid, sessionid, sid); |
| 711 | break; | 803 | break; |
| 712 | case AUDIT_TRIM: | 804 | case AUDIT_TRIM: |
| 713 | audit_trim_trees(); | 805 | audit_trim_trees(); |
| 714 | 806 | ||
| 715 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 807 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 716 | uid, loginuid, sid); | 808 | uid, loginuid, sessionid, sid); |
| 717 | 809 | ||
| 718 | audit_log_format(ab, " op=trim res=1"); | 810 | audit_log_format(ab, " op=trim res=1"); |
| 719 | audit_log_end(ab); | 811 | audit_log_end(ab); |
| @@ -721,21 +813,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 721 | case AUDIT_MAKE_EQUIV: { | 813 | case AUDIT_MAKE_EQUIV: { |
| 722 | void *bufp = data; | 814 | void *bufp = data; |
| 723 | u32 sizes[2]; | 815 | u32 sizes[2]; |
| 724 | size_t len = nlmsg_len(nlh); | 816 | size_t msglen = nlmsg_len(nlh); |
| 725 | char *old, *new; | 817 | char *old, *new; |
| 726 | 818 | ||
| 727 | err = -EINVAL; | 819 | err = -EINVAL; |
| 728 | if (len < 2 * sizeof(u32)) | 820 | if (msglen < 2 * sizeof(u32)) |
| 729 | break; | 821 | break; |
| 730 | memcpy(sizes, bufp, 2 * sizeof(u32)); | 822 | memcpy(sizes, bufp, 2 * sizeof(u32)); |
| 731 | bufp += 2 * sizeof(u32); | 823 | bufp += 2 * sizeof(u32); |
| 732 | len -= 2 * sizeof(u32); | 824 | msglen -= 2 * sizeof(u32); |
| 733 | old = audit_unpack_string(&bufp, &len, sizes[0]); | 825 | old = audit_unpack_string(&bufp, &msglen, sizes[0]); |
| 734 | if (IS_ERR(old)) { | 826 | if (IS_ERR(old)) { |
| 735 | err = PTR_ERR(old); | 827 | err = PTR_ERR(old); |
| 736 | break; | 828 | break; |
| 737 | } | 829 | } |
| 738 | new = audit_unpack_string(&bufp, &len, sizes[1]); | 830 | new = audit_unpack_string(&bufp, &msglen, sizes[1]); |
| 739 | if (IS_ERR(new)) { | 831 | if (IS_ERR(new)) { |
| 740 | err = PTR_ERR(new); | 832 | err = PTR_ERR(new); |
| 741 | kfree(old); | 833 | kfree(old); |
| @@ -745,7 +837,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 745 | err = audit_tag_tree(old, new); | 837 | err = audit_tag_tree(old, new); |
| 746 | 838 | ||
| 747 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, | 839 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, |
| 748 | uid, loginuid, sid); | 840 | uid, loginuid, sessionid, sid); |
| 749 | 841 | ||
| 750 | audit_log_format(ab, " op=make_equiv old="); | 842 | audit_log_format(ab, " op=make_equiv old="); |
| 751 | audit_log_untrustedstring(ab, old); | 843 | audit_log_untrustedstring(ab, old); |
| @@ -779,7 +871,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 779 | struct task_struct *tsk; | 871 | struct task_struct *tsk; |
| 780 | 872 | ||
| 781 | read_lock(&tasklist_lock); | 873 | read_lock(&tasklist_lock); |
| 782 | tsk = find_task_by_pid(pid); | 874 | tsk = find_task_by_vpid(pid); |
| 783 | if (!tsk) | 875 | if (!tsk) |
| 784 | err = -ESRCH; | 876 | err = -ESRCH; |
| 785 | else { | 877 | else { |
| @@ -802,7 +894,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 802 | if (s->enabled != 0 && s->enabled != 1) | 894 | if (s->enabled != 0 && s->enabled != 1) |
| 803 | return -EINVAL; | 895 | return -EINVAL; |
| 804 | read_lock(&tasklist_lock); | 896 | read_lock(&tasklist_lock); |
| 805 | tsk = find_task_by_pid(pid); | 897 | tsk = find_task_by_vpid(pid); |
| 806 | if (!tsk) | 898 | if (!tsk) |
| 807 | err = -ESRCH; | 899 | err = -ESRCH; |
| 808 | else { | 900 | else { |
| @@ -877,6 +969,7 @@ static int __init audit_init(void) | |||
| 877 | audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; | 969 | audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; |
| 878 | 970 | ||
| 879 | skb_queue_head_init(&audit_skb_queue); | 971 | skb_queue_head_init(&audit_skb_queue); |
| 972 | skb_queue_head_init(&audit_skb_hold_queue); | ||
| 880 | audit_initialized = 1; | 973 | audit_initialized = 1; |
| 881 | audit_enabled = audit_default; | 974 | audit_enabled = audit_default; |
| 882 | audit_ever_enabled |= !!audit_default; | 975 | audit_ever_enabled |= !!audit_default; |
| @@ -1199,7 +1292,7 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) | |||
| 1199 | * This function will take the passed buf and convert it into a string of | 1292 | * This function will take the passed buf and convert it into a string of |
| 1200 | * ascii hex digits. The new string is placed onto the skb. | 1293 | * ascii hex digits. The new string is placed onto the skb. |
| 1201 | */ | 1294 | */ |
| 1202 | void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, | 1295 | void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, |
| 1203 | size_t len) | 1296 | size_t len) |
| 1204 | { | 1297 | { |
| 1205 | int i, avail, new_len; | 1298 | int i, avail, new_len; |
| @@ -1235,8 +1328,8 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, | |||
| 1235 | * Format a string of no more than slen characters into the audit buffer, | 1328 | * Format a string of no more than slen characters into the audit buffer, |
| 1236 | * enclosed in quote marks. | 1329 | * enclosed in quote marks. |
| 1237 | */ | 1330 | */ |
| 1238 | static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | 1331 | void audit_log_n_string(struct audit_buffer *ab, const char *string, |
| 1239 | const char *string) | 1332 | size_t slen) |
| 1240 | { | 1333 | { |
| 1241 | int avail, new_len; | 1334 | int avail, new_len; |
| 1242 | unsigned char *ptr; | 1335 | unsigned char *ptr; |
| @@ -1292,13 +1385,13 @@ int audit_string_contains_control(const char *string, size_t len) | |||
| 1292 | * The caller specifies the number of characters in the string to log, which may | 1385 | * The caller specifies the number of characters in the string to log, which may |
| 1293 | * or may not be the entire string. | 1386 | * or may not be the entire string. |
| 1294 | */ | 1387 | */ |
| 1295 | void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | 1388 | void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string, |
| 1296 | const char *string) | 1389 | size_t len) |
| 1297 | { | 1390 | { |
| 1298 | if (audit_string_contains_control(string, len)) | 1391 | if (audit_string_contains_control(string, len)) |
| 1299 | audit_log_hex(ab, string, len); | 1392 | audit_log_n_hex(ab, string, len); |
| 1300 | else | 1393 | else |
| 1301 | audit_log_n_string(ab, len, string); | 1394 | audit_log_n_string(ab, string, len); |
| 1302 | } | 1395 | } |
| 1303 | 1396 | ||
| 1304 | /** | 1397 | /** |
| @@ -1311,7 +1404,7 @@ void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | |||
| 1311 | */ | 1404 | */ |
| 1312 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | 1405 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) |
| 1313 | { | 1406 | { |
| 1314 | audit_log_n_untrustedstring(ab, strlen(string), string); | 1407 | audit_log_n_untrustedstring(ab, string, strlen(string)); |
| 1315 | } | 1408 | } |
| 1316 | 1409 | ||
| 1317 | /* This is a helper-function to print the escaped d_path */ | 1410 | /* This is a helper-function to print the escaped d_path */ |
| @@ -1355,19 +1448,23 @@ void audit_log_end(struct audit_buffer *ab) | |||
| 1355 | audit_log_lost("rate limit exceeded"); | 1448 | audit_log_lost("rate limit exceeded"); |
| 1356 | } else { | 1449 | } else { |
| 1357 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); | 1450 | struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); |
| 1451 | nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0); | ||
| 1452 | |||
| 1358 | if (audit_pid) { | 1453 | if (audit_pid) { |
| 1359 | nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0); | ||
| 1360 | skb_queue_tail(&audit_skb_queue, ab->skb); | 1454 | skb_queue_tail(&audit_skb_queue, ab->skb); |
| 1361 | ab->skb = NULL; | ||
| 1362 | wake_up_interruptible(&kauditd_wait); | 1455 | wake_up_interruptible(&kauditd_wait); |
| 1363 | } else if (nlh->nlmsg_type != AUDIT_EOE) { | 1456 | } else { |
| 1364 | if (printk_ratelimit()) { | 1457 | if (nlh->nlmsg_type != AUDIT_EOE) { |
| 1365 | printk(KERN_NOTICE "type=%d %s\n", | 1458 | if (printk_ratelimit()) { |
| 1366 | nlh->nlmsg_type, | 1459 | printk(KERN_NOTICE "type=%d %s\n", |
| 1367 | ab->skb->data + NLMSG_SPACE(0)); | 1460 | nlh->nlmsg_type, |
| 1368 | } else | 1461 | ab->skb->data + NLMSG_SPACE(0)); |
| 1369 | audit_log_lost("printk limit exceeded\n"); | 1462 | } else |
| 1463 | audit_log_lost("printk limit exceeded\n"); | ||
| 1464 | } | ||
| 1465 | audit_hold_skb(ab->skb); | ||
| 1370 | } | 1466 | } |
| 1467 | ab->skb = NULL; | ||
| 1371 | } | 1468 | } |
| 1372 | audit_buffer_free(ab); | 1469 | audit_buffer_free(ab); |
| 1373 | } | 1470 | } |
diff --git a/kernel/audit.h b/kernel/audit.h index 3cfc54ee3e1f..9d6717412fec 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -74,6 +74,11 @@ struct audit_entry { | |||
| 74 | struct audit_krule rule; | 74 | struct audit_krule rule; |
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | #ifdef CONFIG_AUDIT | ||
| 78 | extern int audit_enabled; | ||
| 79 | extern int audit_ever_enabled; | ||
| 80 | #endif | ||
| 81 | |||
| 77 | extern int audit_pid; | 82 | extern int audit_pid; |
| 78 | 83 | ||
| 79 | #define AUDIT_INODE_BUCKETS 32 | 84 | #define AUDIT_INODE_BUCKETS 32 |
| @@ -104,6 +109,9 @@ struct audit_netlink_list { | |||
| 104 | int audit_send_list(void *); | 109 | int audit_send_list(void *); |
| 105 | 110 | ||
| 106 | struct inotify_watch; | 111 | struct inotify_watch; |
| 112 | /* Inotify handle */ | ||
| 113 | extern struct inotify_handle *audit_ih; | ||
| 114 | |||
| 107 | extern void audit_free_parent(struct inotify_watch *); | 115 | extern void audit_free_parent(struct inotify_watch *); |
| 108 | extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32, | 116 | extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32, |
| 109 | const char *, struct inode *); | 117 | const char *, struct inode *); |
| @@ -111,6 +119,7 @@ extern int selinux_audit_rule_update(void); | |||
| 111 | 119 | ||
| 112 | extern struct mutex audit_filter_mutex; | 120 | extern struct mutex audit_filter_mutex; |
| 113 | extern void audit_free_rule_rcu(struct rcu_head *); | 121 | extern void audit_free_rule_rcu(struct rcu_head *); |
| 122 | extern struct list_head audit_filter_list[]; | ||
| 114 | 123 | ||
| 115 | #ifdef CONFIG_AUDIT_TREE | 124 | #ifdef CONFIG_AUDIT_TREE |
| 116 | extern struct audit_chunk *audit_tree_lookup(const struct inode *); | 125 | extern struct audit_chunk *audit_tree_lookup(const struct inode *); |
| @@ -137,6 +146,10 @@ extern void audit_put_tree(struct audit_tree *); | |||
| 137 | 146 | ||
| 138 | extern char *audit_unpack_string(void **, size_t *, size_t); | 147 | extern char *audit_unpack_string(void **, size_t *, size_t); |
| 139 | 148 | ||
| 149 | extern pid_t audit_sig_pid; | ||
| 150 | extern uid_t audit_sig_uid; | ||
| 151 | extern u32 audit_sig_sid; | ||
| 152 | |||
| 140 | #ifdef CONFIG_AUDITSYSCALL | 153 | #ifdef CONFIG_AUDITSYSCALL |
| 141 | extern int __audit_signal_info(int sig, struct task_struct *t); | 154 | extern int __audit_signal_info(int sig, struct task_struct *t); |
| 142 | static inline int audit_signal_info(int sig, struct task_struct *t) | 155 | static inline int audit_signal_info(int sig, struct task_struct *t) |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 13430176b3c9..0e0bd27e6512 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -89,14 +89,9 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { | |||
| 89 | 89 | ||
| 90 | DEFINE_MUTEX(audit_filter_mutex); | 90 | DEFINE_MUTEX(audit_filter_mutex); |
| 91 | 91 | ||
| 92 | /* Inotify handle */ | ||
| 93 | extern struct inotify_handle *audit_ih; | ||
| 94 | |||
| 95 | /* Inotify events we care about. */ | 92 | /* Inotify events we care about. */ |
| 96 | #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF | 93 | #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF |
| 97 | 94 | ||
| 98 | extern int audit_enabled; | ||
| 99 | |||
| 100 | void audit_free_parent(struct inotify_watch *i_watch) | 95 | void audit_free_parent(struct inotify_watch *i_watch) |
| 101 | { | 96 | { |
| 102 | struct audit_parent *parent; | 97 | struct audit_parent *parent; |
| @@ -422,7 +417,7 @@ exit_err: | |||
| 422 | static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | 417 | static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) |
| 423 | { | 418 | { |
| 424 | struct audit_entry *entry; | 419 | struct audit_entry *entry; |
| 425 | struct audit_field *f; | 420 | struct audit_field *ino_f; |
| 426 | int err = 0; | 421 | int err = 0; |
| 427 | int i; | 422 | int i; |
| 428 | 423 | ||
| @@ -483,6 +478,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 483 | if (f->val & ~15) | 478 | if (f->val & ~15) |
| 484 | goto exit_free; | 479 | goto exit_free; |
| 485 | break; | 480 | break; |
| 481 | case AUDIT_FILETYPE: | ||
| 482 | if ((f->val & ~S_IFMT) > S_IFMT) | ||
| 483 | goto exit_free; | ||
| 484 | break; | ||
| 486 | case AUDIT_INODE: | 485 | case AUDIT_INODE: |
| 487 | err = audit_to_inode(&entry->rule, f); | 486 | err = audit_to_inode(&entry->rule, f); |
| 488 | if (err) | 487 | if (err) |
| @@ -504,9 +503,9 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 504 | } | 503 | } |
| 505 | } | 504 | } |
| 506 | 505 | ||
| 507 | f = entry->rule.inode_f; | 506 | ino_f = entry->rule.inode_f; |
| 508 | if (f) { | 507 | if (ino_f) { |
| 509 | switch(f->op) { | 508 | switch(ino_f->op) { |
| 510 | case AUDIT_NOT_EQUAL: | 509 | case AUDIT_NOT_EQUAL: |
| 511 | entry->rule.inode_f = NULL; | 510 | entry->rule.inode_f = NULL; |
| 512 | case AUDIT_EQUAL: | 511 | case AUDIT_EQUAL: |
| @@ -531,7 +530,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 531 | { | 530 | { |
| 532 | int err = 0; | 531 | int err = 0; |
| 533 | struct audit_entry *entry; | 532 | struct audit_entry *entry; |
| 534 | struct audit_field *f; | 533 | struct audit_field *ino_f; |
| 535 | void *bufp; | 534 | void *bufp; |
| 536 | size_t remain = datasz - sizeof(struct audit_rule_data); | 535 | size_t remain = datasz - sizeof(struct audit_rule_data); |
| 537 | int i; | 536 | int i; |
| @@ -654,14 +653,18 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 654 | if (f->val & ~15) | 653 | if (f->val & ~15) |
| 655 | goto exit_free; | 654 | goto exit_free; |
| 656 | break; | 655 | break; |
| 656 | case AUDIT_FILETYPE: | ||
| 657 | if ((f->val & ~S_IFMT) > S_IFMT) | ||
| 658 | goto exit_free; | ||
| 659 | break; | ||
| 657 | default: | 660 | default: |
| 658 | goto exit_free; | 661 | goto exit_free; |
| 659 | } | 662 | } |
| 660 | } | 663 | } |
| 661 | 664 | ||
| 662 | f = entry->rule.inode_f; | 665 | ino_f = entry->rule.inode_f; |
| 663 | if (f) { | 666 | if (ino_f) { |
| 664 | switch(f->op) { | 667 | switch(ino_f->op) { |
| 665 | case AUDIT_NOT_EQUAL: | 668 | case AUDIT_NOT_EQUAL: |
| 666 | entry->rule.inode_f = NULL; | 669 | entry->rule.inode_f = NULL; |
| 667 | case AUDIT_EQUAL: | 670 | case AUDIT_EQUAL: |
| @@ -1500,8 +1503,9 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | |||
| 1500 | } | 1503 | } |
| 1501 | 1504 | ||
| 1502 | /* Log rule additions and removals */ | 1505 | /* Log rule additions and removals */ |
| 1503 | static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, | 1506 | static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid, |
| 1504 | struct audit_krule *rule, int res) | 1507 | char *action, struct audit_krule *rule, |
| 1508 | int res) | ||
| 1505 | { | 1509 | { |
| 1506 | struct audit_buffer *ab; | 1510 | struct audit_buffer *ab; |
| 1507 | 1511 | ||
| @@ -1511,7 +1515,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, | |||
| 1511 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1515 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 1512 | if (!ab) | 1516 | if (!ab) |
| 1513 | return; | 1517 | return; |
| 1514 | audit_log_format(ab, "auid=%u", loginuid); | 1518 | audit_log_format(ab, "auid=%u ses=%u", loginuid, sessionid); |
| 1515 | if (sid) { | 1519 | if (sid) { |
| 1516 | char *ctx = NULL; | 1520 | char *ctx = NULL; |
| 1517 | u32 len; | 1521 | u32 len; |
| @@ -1543,7 +1547,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, | |||
| 1543 | * @sid: SE Linux Security ID of sender | 1547 | * @sid: SE Linux Security ID of sender |
| 1544 | */ | 1548 | */ |
| 1545 | int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | 1549 | int audit_receive_filter(int type, int pid, int uid, int seq, void *data, |
| 1546 | size_t datasz, uid_t loginuid, u32 sid) | 1550 | size_t datasz, uid_t loginuid, u32 sessionid, u32 sid) |
| 1547 | { | 1551 | { |
| 1548 | struct task_struct *tsk; | 1552 | struct task_struct *tsk; |
| 1549 | struct audit_netlink_list *dest; | 1553 | struct audit_netlink_list *dest; |
| @@ -1590,7 +1594,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
| 1590 | 1594 | ||
| 1591 | err = audit_add_rule(entry, | 1595 | err = audit_add_rule(entry, |
| 1592 | &audit_filter_list[entry->rule.listnr]); | 1596 | &audit_filter_list[entry->rule.listnr]); |
| 1593 | audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err); | 1597 | audit_log_rule_change(loginuid, sessionid, sid, "add", |
| 1598 | &entry->rule, !err); | ||
| 1594 | 1599 | ||
| 1595 | if (err) | 1600 | if (err) |
| 1596 | audit_free_rule(entry); | 1601 | audit_free_rule(entry); |
| @@ -1606,8 +1611,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, | |||
| 1606 | 1611 | ||
| 1607 | err = audit_del_rule(entry, | 1612 | err = audit_del_rule(entry, |
| 1608 | &audit_filter_list[entry->rule.listnr]); | 1613 | &audit_filter_list[entry->rule.listnr]); |
| 1609 | audit_log_rule_change(loginuid, sid, "remove", &entry->rule, | 1614 | audit_log_rule_change(loginuid, sessionid, sid, "remove", |
| 1610 | !err); | 1615 | &entry->rule, !err); |
| 1611 | 1616 | ||
| 1612 | audit_free_rule(entry); | 1617 | audit_free_rule(entry); |
| 1613 | break; | 1618 | break; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 56e56ed594a8..c10e7aae04d7 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -68,9 +68,6 @@ | |||
| 68 | 68 | ||
| 69 | #include "audit.h" | 69 | #include "audit.h" |
| 70 | 70 | ||
| 71 | extern struct list_head audit_filter_list[]; | ||
| 72 | extern int audit_ever_enabled; | ||
| 73 | |||
| 74 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | 71 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context |
| 75 | * for saving names from getname(). */ | 72 | * for saving names from getname(). */ |
| 76 | #define AUDIT_NAMES 20 | 73 | #define AUDIT_NAMES 20 |
| @@ -283,6 +280,19 @@ static int audit_match_perm(struct audit_context *ctx, int mask) | |||
| 283 | } | 280 | } |
| 284 | } | 281 | } |
| 285 | 282 | ||
| 283 | static int audit_match_filetype(struct audit_context *ctx, int which) | ||
| 284 | { | ||
| 285 | unsigned index = which & ~S_IFMT; | ||
| 286 | mode_t mode = which & S_IFMT; | ||
| 287 | if (index >= ctx->name_count) | ||
| 288 | return 0; | ||
| 289 | if (ctx->names[index].ino == -1) | ||
| 290 | return 0; | ||
| 291 | if ((ctx->names[index].mode ^ mode) & S_IFMT) | ||
| 292 | return 0; | ||
| 293 | return 1; | ||
| 294 | } | ||
| 295 | |||
| 286 | /* | 296 | /* |
| 287 | * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *; | 297 | * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *; |
| 288 | * ->first_trees points to its beginning, ->trees - to the current end of data. | 298 | * ->first_trees points to its beginning, ->trees - to the current end of data. |
| @@ -592,6 +602,9 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 592 | case AUDIT_PERM: | 602 | case AUDIT_PERM: |
| 593 | result = audit_match_perm(ctx, f->val); | 603 | result = audit_match_perm(ctx, f->val); |
| 594 | break; | 604 | break; |
| 605 | case AUDIT_FILETYPE: | ||
| 606 | result = audit_match_filetype(ctx, f->val); | ||
| 607 | break; | ||
| 595 | } | 608 | } |
| 596 | 609 | ||
| 597 | if (!result) | 610 | if (!result) |
| @@ -1095,7 +1108,7 @@ static int audit_log_single_execve_arg(struct audit_context *context, | |||
| 1095 | audit_log_format(*ab, "[%d]", i); | 1108 | audit_log_format(*ab, "[%d]", i); |
| 1096 | audit_log_format(*ab, "="); | 1109 | audit_log_format(*ab, "="); |
| 1097 | if (has_cntl) | 1110 | if (has_cntl) |
| 1098 | audit_log_hex(*ab, buf, to_send); | 1111 | audit_log_n_hex(*ab, buf, to_send); |
| 1099 | else | 1112 | else |
| 1100 | audit_log_format(*ab, "\"%s\"", buf); | 1113 | audit_log_format(*ab, "\"%s\"", buf); |
| 1101 | audit_log_format(*ab, "\n"); | 1114 | audit_log_format(*ab, "\n"); |
| @@ -1296,7 +1309,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1296 | break; } | 1309 | break; } |
| 1297 | 1310 | ||
| 1298 | case AUDIT_SOCKETCALL: { | 1311 | case AUDIT_SOCKETCALL: { |
| 1299 | int i; | ||
| 1300 | struct audit_aux_data_socketcall *axs = (void *)aux; | 1312 | struct audit_aux_data_socketcall *axs = (void *)aux; |
| 1301 | audit_log_format(ab, "nargs=%d", axs->nargs); | 1313 | audit_log_format(ab, "nargs=%d", axs->nargs); |
| 1302 | for (i=0; i<axs->nargs; i++) | 1314 | for (i=0; i<axs->nargs; i++) |
| @@ -1307,7 +1319,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1307 | struct audit_aux_data_sockaddr *axs = (void *)aux; | 1319 | struct audit_aux_data_sockaddr *axs = (void *)aux; |
| 1308 | 1320 | ||
| 1309 | audit_log_format(ab, "saddr="); | 1321 | audit_log_format(ab, "saddr="); |
| 1310 | audit_log_hex(ab, axs->a, axs->len); | 1322 | audit_log_n_hex(ab, axs->a, axs->len); |
| 1311 | break; } | 1323 | break; } |
| 1312 | 1324 | ||
| 1313 | case AUDIT_FD_PAIR: { | 1325 | case AUDIT_FD_PAIR: { |
| @@ -1321,7 +1333,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1321 | 1333 | ||
| 1322 | for (aux = context->aux_pids; aux; aux = aux->next) { | 1334 | for (aux = context->aux_pids; aux; aux = aux->next) { |
| 1323 | struct audit_aux_data_pids *axs = (void *)aux; | 1335 | struct audit_aux_data_pids *axs = (void *)aux; |
| 1324 | int i; | ||
| 1325 | 1336 | ||
| 1326 | for (i = 0; i < axs->pid_count; i++) | 1337 | for (i = 0; i < axs->pid_count; i++) |
| 1327 | if (audit_log_pid_context(context, axs->target_pid[i], | 1338 | if (audit_log_pid_context(context, axs->target_pid[i], |
| @@ -1371,8 +1382,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1371 | default: | 1382 | default: |
| 1372 | /* log the name's directory component */ | 1383 | /* log the name's directory component */ |
| 1373 | audit_log_format(ab, " name="); | 1384 | audit_log_format(ab, " name="); |
| 1374 | audit_log_n_untrustedstring(ab, n->name_len, | 1385 | audit_log_n_untrustedstring(ab, n->name, |
| 1375 | n->name); | 1386 | n->name_len); |
| 1376 | } | 1387 | } |
| 1377 | } else | 1388 | } else |
| 1378 | audit_log_format(ab, " name=(null)"); | 1389 | audit_log_format(ab, " name=(null)"); |
| @@ -1596,7 +1607,7 @@ static inline void handle_one(const struct inode *inode) | |||
| 1596 | if (likely(put_tree_ref(context, chunk))) | 1607 | if (likely(put_tree_ref(context, chunk))) |
| 1597 | return; | 1608 | return; |
| 1598 | if (unlikely(!grow_tree_refs(context))) { | 1609 | if (unlikely(!grow_tree_refs(context))) { |
| 1599 | printk(KERN_WARNING "out of memory, audit has lost a tree reference"); | 1610 | printk(KERN_WARNING "out of memory, audit has lost a tree reference\n"); |
| 1600 | audit_set_auditable(context); | 1611 | audit_set_auditable(context); |
| 1601 | audit_put_chunk(chunk); | 1612 | audit_put_chunk(chunk); |
| 1602 | unroll_tree_refs(context, p, count); | 1613 | unroll_tree_refs(context, p, count); |
| @@ -1656,7 +1667,7 @@ retry: | |||
| 1656 | } | 1667 | } |
| 1657 | /* too bad */ | 1668 | /* too bad */ |
| 1658 | printk(KERN_WARNING | 1669 | printk(KERN_WARNING |
| 1659 | "out of memory, audit has lost a tree reference"); | 1670 | "out of memory, audit has lost a tree reference\n"); |
| 1660 | unroll_tree_refs(context, p, count); | 1671 | unroll_tree_refs(context, p, count); |
| 1661 | audit_set_auditable(context); | 1672 | audit_set_auditable(context); |
| 1662 | return; | 1673 | return; |
| @@ -1752,13 +1763,13 @@ static int audit_inc_name_count(struct audit_context *context, | |||
| 1752 | if (context->name_count >= AUDIT_NAMES) { | 1763 | if (context->name_count >= AUDIT_NAMES) { |
| 1753 | if (inode) | 1764 | if (inode) |
| 1754 | printk(KERN_DEBUG "name_count maxed, losing inode data: " | 1765 | printk(KERN_DEBUG "name_count maxed, losing inode data: " |
| 1755 | "dev=%02x:%02x, inode=%lu", | 1766 | "dev=%02x:%02x, inode=%lu\n", |
| 1756 | MAJOR(inode->i_sb->s_dev), | 1767 | MAJOR(inode->i_sb->s_dev), |
| 1757 | MINOR(inode->i_sb->s_dev), | 1768 | MINOR(inode->i_sb->s_dev), |
| 1758 | inode->i_ino); | 1769 | inode->i_ino); |
| 1759 | 1770 | ||
| 1760 | else | 1771 | else |
| 1761 | printk(KERN_DEBUG "name_count maxed, losing inode data"); | 1772 | printk(KERN_DEBUG "name_count maxed, losing inode data\n"); |
| 1762 | return 1; | 1773 | return 1; |
| 1763 | } | 1774 | } |
| 1764 | context->name_count++; | 1775 | context->name_count++; |
| @@ -2361,9 +2372,6 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
| 2361 | struct audit_aux_data_pids *axp; | 2372 | struct audit_aux_data_pids *axp; |
| 2362 | struct task_struct *tsk = current; | 2373 | struct task_struct *tsk = current; |
| 2363 | struct audit_context *ctx = tsk->audit_context; | 2374 | struct audit_context *ctx = tsk->audit_context; |
| 2364 | extern pid_t audit_sig_pid; | ||
| 2365 | extern uid_t audit_sig_uid; | ||
| 2366 | extern u32 audit_sig_sid; | ||
| 2367 | 2375 | ||
| 2368 | if (audit_pid && t->tgid == audit_pid) { | 2376 | if (audit_pid && t->tgid == audit_pid) { |
| 2369 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { | 2377 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { |
