Merge branch 'audit.b64' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current

* 'audit.b64' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current:
audit mmap
audit: make link()/linkat() match "attribute change" predicate
audit: Use rcu for task lookup protection
audit: Do not send uninitialized data for AUDIT_TTY_GET
audit: Call tty_audit_push_task() outside preempt disabled
in untag_chunk() we need to do alloc_chunk() a bit earlier
audit: make functions static
Audit: add support to match lsm labels on user audit messages

+118 -59
+28 -10
drivers/char/tty_audit.c
··· 188 188 } 189 189 190 190 /** 191 - * tty_audit_push_task - Flush task's pending audit data 191 + * tty_audit_push_task - Flush task's pending audit data 192 + * @tsk: task pointer 193 + * @loginuid: sender login uid 194 + * @sessionid: sender session id 195 + * 196 + * Called with a ref on @tsk held. Try to lock sighand and get a 197 + * reference to the tty audit buffer if available. 198 + * Flush the buffer or return an appropriate error code. 192 199 */ 193 - void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid) 200 + int tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid) 194 201 { 195 - struct tty_audit_buf *buf; 202 + struct tty_audit_buf *buf = ERR_PTR(-EPERM); 203 + unsigned long flags; 196 204 197 - spin_lock_irq(&tsk->sighand->siglock); 198 - buf = tsk->signal->tty_audit_buf; 199 - if (buf) 200 - atomic_inc(&buf->count); 201 - spin_unlock_irq(&tsk->sighand->siglock); 202 - if (!buf) 203 - return; 205 + if (!lock_task_sighand(tsk, &flags)) 206 + return -ESRCH; 207 + 208 + if (tsk->signal->audit_tty) { 209 + buf = tsk->signal->tty_audit_buf; 210 + if (buf) 211 + atomic_inc(&buf->count); 212 + } 213 + unlock_task_sighand(tsk, &flags); 214 + 215 + /* 216 + * Return 0 when signal->audit_tty set 217 + * but tsk->signal->tty_audit_buf == NULL. 218 + */ 219 + if (!buf || IS_ERR(buf)) 220 + return PTR_ERR(buf); 204 221 205 222 mutex_lock(&buf->mutex); 206 223 tty_audit_buf_push(tsk, loginuid, sessionid, buf); 207 224 mutex_unlock(&buf->mutex); 208 225 209 226 tty_audit_buf_put(buf); 227 + return 0; 210 228 } 211 229 212 230 /**
+4
include/asm-generic/audit_change_attr.h
··· 20 20 __NR_fchown32, 21 21 __NR_lchown32, 22 22 #endif 23 + __NR_link, 24 + #ifdef __NR_linkat 25 + __NR_linkat, 26 + #endif
+9
include/linux/audit.h
··· 102 102 #define AUDIT_EOE 1320 /* End of multi-record event */ 103 103 #define AUDIT_BPRM_FCAPS 1321 /* Information about fcaps increasing perms */ 104 104 #define AUDIT_CAPSET 1322 /* Record showing argument to sys_capset */ 105 + #define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */ 105 106 106 107 #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ 107 108 #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ ··· 479 478 const struct cred *new, 480 479 const struct cred *old); 481 480 extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old); 481 + extern void __audit_mmap_fd(int fd, int flags); 482 482 483 483 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) 484 484 { ··· 533 531 __audit_log_capset(pid, new, old); 534 532 } 535 533 534 + static inline void audit_mmap_fd(int fd, int flags) 535 + { 536 + if (unlikely(!audit_dummy_context())) 537 + __audit_mmap_fd(fd, flags); 538 + } 539 + 536 540 extern int audit_n_rules; 537 541 extern int audit_signals; 538 542 #else ··· 572 564 #define audit_mq_getsetattr(d,s) ((void)0) 573 565 #define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; }) 574 566 #define audit_log_capset(pid, ncr, ocr) ((void)0) 567 + #define audit_mmap_fd(fd, flags) ((void)0) 575 568 #define audit_ptrace(t) ((void)0) 576 569 #define audit_n_rules 0 577 570 #define audit_signals 0
+5 -4
include/linux/tty.h
··· 541 541 extern void tty_audit_fork(struct signal_struct *sig); 542 542 extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); 543 543 extern void tty_audit_push(struct tty_struct *tty); 544 - extern void tty_audit_push_task(struct task_struct *tsk, 545 - uid_t loginuid, u32 sessionid); 544 + extern int tty_audit_push_task(struct task_struct *tsk, 545 + uid_t loginuid, u32 sessionid); 546 546 #else 547 547 static inline void tty_audit_add_data(struct tty_struct *tty, 548 548 unsigned char *data, size_t size) ··· 560 560 static inline void tty_audit_push(struct tty_struct *tty) 561 561 { 562 562 } 563 - static inline void tty_audit_push_task(struct task_struct *tsk, 564 - uid_t loginuid, u32 sessionid) 563 + static inline int tty_audit_push_task(struct task_struct *tsk, 564 + uid_t loginuid, u32 sessionid) 565 565 { 566 + return 0; 566 567 } 567 568 #endif 568 569
+30 -37
kernel/audit.c
··· 467 467 struct task_struct *tsk; 468 468 int err; 469 469 470 - read_lock(&tasklist_lock); 470 + rcu_read_lock(); 471 471 tsk = find_task_by_vpid(pid); 472 - err = -ESRCH; 473 - if (!tsk) 474 - goto out; 475 - err = 0; 476 - 477 - spin_lock_irq(&tsk->sighand->siglock); 478 - if (!tsk->signal->audit_tty) 479 - err = -EPERM; 480 - spin_unlock_irq(&tsk->sighand->siglock); 481 - if (err) 482 - goto out; 483 - 484 - tty_audit_push_task(tsk, loginuid, sessionid); 485 - out: 486 - read_unlock(&tasklist_lock); 472 + if (!tsk) { 473 + rcu_read_unlock(); 474 + return -ESRCH; 475 + } 476 + get_task_struct(tsk); 477 + rcu_read_unlock(); 478 + err = tty_audit_push_task(tsk, loginuid, sessionid); 479 + put_task_struct(tsk); 487 480 return err; 488 481 } 489 482 ··· 499 506 } 500 507 501 508 struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, 502 - int multi, void *payload, int size) 509 + int multi, const void *payload, int size) 503 510 { 504 511 struct sk_buff *skb; 505 512 struct nlmsghdr *nlh; ··· 548 555 * Allocates an skb, builds the netlink message, and sends it to the pid. 549 556 * No failure notifications. 550 557 */ 551 - void audit_send_reply(int pid, int seq, int type, int done, int multi, 552 - void *payload, int size) 558 + static void audit_send_reply(int pid, int seq, int type, int done, int multi, 559 + const void *payload, int size) 553 560 { 554 561 struct sk_buff *skb; 555 562 struct task_struct *tsk; ··· 873 880 case AUDIT_TTY_GET: { 874 881 struct audit_tty_status s; 875 882 struct task_struct *tsk; 883 + unsigned long flags; 876 884 877 - read_lock(&tasklist_lock); 885 + rcu_read_lock(); 878 886 tsk = find_task_by_vpid(pid); 879 - if (!tsk) 880 - err = -ESRCH; 881 - else { 882 - spin_lock_irq(&tsk->sighand->siglock); 887 + if (tsk && lock_task_sighand(tsk, &flags)) { 883 888 s.enabled = tsk->signal->audit_tty != 0; 884 - spin_unlock_irq(&tsk->sighand->siglock); 885 - } 886 - read_unlock(&tasklist_lock); 887 - audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0, 888 - &s, sizeof(s)); 889 + unlock_task_sighand(tsk, &flags); 890 + } else 891 + err = -ESRCH; 892 + rcu_read_unlock(); 893 + 894 + if (!err) 895 + audit_send_reply(NETLINK_CB(skb).pid, seq, 896 + AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); 889 897 break; 890 898 } 891 899 case AUDIT_TTY_SET: { 892 900 struct audit_tty_status *s; 893 901 struct task_struct *tsk; 902 + unsigned long flags; 894 903 895 904 if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) 896 905 return -EINVAL; 897 906 s = data; 898 907 if (s->enabled != 0 && s->enabled != 1) 899 908 return -EINVAL; 900 - read_lock(&tasklist_lock); 909 + rcu_read_lock(); 901 910 tsk = find_task_by_vpid(pid); 902 - if (!tsk) 903 - err = -ESRCH; 904 - else { 905 - spin_lock_irq(&tsk->sighand->siglock); 911 + if (tsk && lock_task_sighand(tsk, &flags)) { 906 912 tsk->signal->audit_tty = s->enabled != 0; 907 - spin_unlock_irq(&tsk->sighand->siglock); 908 - } 909 - read_unlock(&tasklist_lock); 913 + unlock_task_sighand(tsk, &flags); 914 + } else 915 + err = -ESRCH; 916 + rcu_read_unlock(); 910 917 break; 911 918 } 912 919 default:
+1 -4
kernel/audit.h
··· 84 84 int *dirlen); 85 85 extern struct sk_buff * audit_make_reply(int pid, int seq, int type, 86 86 int done, int multi, 87 - void *payload, int size); 88 - extern void audit_send_reply(int pid, int seq, int type, 89 - int done, int multi, 90 - void *payload, int size); 87 + const void *payload, int size); 91 88 extern void audit_panic(const char *message); 92 89 93 90 struct audit_netlink_list {
+7 -2
kernel/audit_tree.c
··· 223 223 { 224 224 struct audit_chunk *chunk = find_chunk(p); 225 225 struct fsnotify_mark *entry = &chunk->mark; 226 - struct audit_chunk *new; 226 + struct audit_chunk *new = NULL; 227 227 struct audit_tree *owner; 228 228 int size = chunk->count - 1; 229 229 int i, j; ··· 232 232 233 233 spin_unlock(&hash_lock); 234 234 235 + if (size) 236 + new = alloc_chunk(size); 237 + 235 238 spin_lock(&entry->lock); 236 239 if (chunk->dead || !entry->i.inode) { 237 240 spin_unlock(&entry->lock); 241 + if (new) 242 + free_chunk(new); 238 243 goto out; 239 244 } 240 245 ··· 260 255 goto out; 261 256 } 262 257 263 - new = alloc_chunk(size); 264 258 if (!new) 265 259 goto Fallback; 260 + 266 261 fsnotify_duplicate_mark(&new->mark, entry); 267 262 if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { 268 263 free_chunk(new);
+2 -2
kernel/audit_watch.c
··· 60 60 }; 61 61 62 62 /* fsnotify handle. */ 63 - struct fsnotify_group *audit_watch_group; 63 + static struct fsnotify_group *audit_watch_group; 64 64 65 65 /* fsnotify events we care about. */ 66 66 #define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\ ··· 123 123 } 124 124 } 125 125 126 - void audit_remove_watch(struct audit_watch *watch) 126 + static void audit_remove_watch(struct audit_watch *watch) 127 127 { 128 128 list_del(&watch->wlist); 129 129 audit_put_parent(watch->parent);
+12
kernel/auditfilter.c
··· 1252 1252 case AUDIT_LOGINUID: 1253 1253 result = audit_comparator(cb->loginuid, f->op, f->val); 1254 1254 break; 1255 + case AUDIT_SUBJ_USER: 1256 + case AUDIT_SUBJ_ROLE: 1257 + case AUDIT_SUBJ_TYPE: 1258 + case AUDIT_SUBJ_SEN: 1259 + case AUDIT_SUBJ_CLR: 1260 + if (f->lsm_rule) 1261 + result = security_audit_rule_match(cb->sid, 1262 + f->type, 1263 + f->op, 1264 + f->lsm_rule, 1265 + NULL); 1266 + break; 1255 1267 } 1256 1268 1257 1269 if (!result)
+16
kernel/auditsc.c
··· 241 241 pid_t pid; 242 242 struct audit_cap_data cap; 243 243 } capset; 244 + struct { 245 + int fd; 246 + int flags; 247 + } mmap; 244 248 }; 245 249 int fds[2]; 246 250 ··· 1308 1304 audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable); 1309 1305 audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted); 1310 1306 audit_log_cap(ab, "cap_pe", &context->capset.cap.effective); 1307 + break; } 1308 + case AUDIT_MMAP: { 1309 + audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, 1310 + context->mmap.flags); 1311 1311 break; } 1312 1312 } 1313 1313 audit_log_end(ab); ··· 2482 2474 context->capset.cap.inheritable = new->cap_effective; 2483 2475 context->capset.cap.permitted = new->cap_permitted; 2484 2476 context->type = AUDIT_CAPSET; 2477 + } 2478 + 2479 + void __audit_mmap_fd(int fd, int flags) 2480 + { 2481 + struct audit_context *context = current->audit_context; 2482 + context->mmap.fd = fd; 2483 + context->mmap.flags = flags; 2484 + context->type = AUDIT_MMAP; 2485 2485 } 2486 2486 2487 2487 /**
+2
mm/mmap.c
··· 28 28 #include <linux/rmap.h> 29 29 #include <linux/mmu_notifier.h> 30 30 #include <linux/perf_event.h> 31 + #include <linux/audit.h> 31 32 32 33 #include <asm/uaccess.h> 33 34 #include <asm/cacheflush.h> ··· 1109 1108 unsigned long retval = -EBADF; 1110 1109 1111 1110 if (!(flags & MAP_ANONYMOUS)) { 1111 + audit_mmap_fd(fd, flags); 1112 1112 if (unlikely(flags & MAP_HUGETLB)) 1113 1113 return -EINVAL; 1114 1114 file = fget(fd);
+2
mm/nommu.c
··· 29 29 #include <linux/personality.h> 30 30 #include <linux/security.h> 31 31 #include <linux/syscalls.h> 32 + #include <linux/audit.h> 32 33 33 34 #include <asm/uaccess.h> 34 35 #include <asm/tlb.h> ··· 1459 1458 struct file *file = NULL; 1460 1459 unsigned long retval = -EBADF; 1461 1460 1461 + audit_mmap_fd(fd, flags); 1462 1462 if (!(flags & MAP_ANONYMOUS)) { 1463 1463 file = fget(fd); 1464 1464 if (!file)