aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tty_audit.c38
-rw-r--r--include/asm-generic/audit_change_attr.h4
-rw-r--r--include/linux/audit.h9
-rw-r--r--include/linux/tty.h9
-rw-r--r--kernel/audit.c67
-rw-r--r--kernel/audit.h5
-rw-r--r--kernel/audit_tree.c9
-rw-r--r--kernel/audit_watch.c4
-rw-r--r--kernel/auditfilter.c12
-rw-r--r--kernel/auditsc.c16
-rw-r--r--mm/mmap.c2
-rw-r--r--mm/nommu.c2
12 files changed, 118 insertions, 59 deletions
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
index 1b8ee590b4ca..f64582b0f623 100644
--- a/drivers/char/tty_audit.c
+++ b/drivers/char/tty_audit.c
@@ -188,25 +188,43 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
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 */
193void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid) 200int 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); 205 if (!lock_task_sighand(tsk, &flags))
198 buf = tsk->signal->tty_audit_buf; 206 return -ESRCH;
199 if (buf) 207
200 atomic_inc(&buf->count); 208 if (tsk->signal->audit_tty) {
201 spin_unlock_irq(&tsk->sighand->siglock); 209 buf = tsk->signal->tty_audit_buf;
202 if (!buf) 210 if (buf)
203 return; 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 mutex_lock(&buf->mutex); 222 mutex_lock(&buf->mutex);
206 tty_audit_buf_push(tsk, loginuid, sessionid, buf); 223 tty_audit_buf_push(tsk, loginuid, sessionid, buf);
207 mutex_unlock(&buf->mutex); 224 mutex_unlock(&buf->mutex);
208 225
209 tty_audit_buf_put(buf); 226 tty_audit_buf_put(buf);
227 return 0;
210} 228}
211 229
212/** 230/**
diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h
index 50764550a60c..bcbab3e4a3be 100644
--- a/include/asm-generic/audit_change_attr.h
+++ b/include/asm-generic/audit_change_attr.h
@@ -20,3 +20,7 @@ __NR_chown32,
20__NR_fchown32, 20__NR_fchown32,
21__NR_lchown32, 21__NR_lchown32,
22#endif 22#endif
23__NR_link,
24#ifdef __NR_linkat
25__NR_linkat,
26#endif
diff --git a/include/linux/audit.h b/include/linux/audit.h
index e24afabc548f..8b5c0620abf9 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -102,6 +102,7 @@
102#define AUDIT_EOE 1320 /* End of multi-record event */ 102#define AUDIT_EOE 1320 /* End of multi-record event */
103#define AUDIT_BPRM_FCAPS 1321 /* Information about fcaps increasing perms */ 103#define AUDIT_BPRM_FCAPS 1321 /* Information about fcaps increasing perms */
104#define AUDIT_CAPSET 1322 /* Record showing argument to sys_capset */ 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#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ 107#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
107#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ 108#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -478,6 +479,7 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
478 const struct cred *new, 479 const struct cred *new,
479 const struct cred *old); 480 const struct cred *old);
480extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old); 481extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);
482extern void __audit_mmap_fd(int fd, int flags);
481 483
482static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) 484static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
483{ 485{
@@ -531,6 +533,12 @@ static inline void audit_log_capset(pid_t pid, const struct cred *new,
531 __audit_log_capset(pid, new, old); 533 __audit_log_capset(pid, new, old);
532} 534}
533 535
536static inline void audit_mmap_fd(int fd, int flags)
537{
538 if (unlikely(!audit_dummy_context()))
539 __audit_mmap_fd(fd, flags);
540}
541
534extern int audit_n_rules; 542extern int audit_n_rules;
535extern int audit_signals; 543extern int audit_signals;
536#else 544#else
@@ -564,6 +572,7 @@ extern int audit_signals;
564#define audit_mq_getsetattr(d,s) ((void)0) 572#define audit_mq_getsetattr(d,s) ((void)0)
565#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; }) 573#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
566#define audit_log_capset(pid, ncr, ocr) ((void)0) 574#define audit_log_capset(pid, ncr, ocr) ((void)0)
575#define audit_mmap_fd(fd, flags) ((void)0)
567#define audit_ptrace(t) ((void)0) 576#define audit_ptrace(t) ((void)0)
568#define audit_n_rules 0 577#define audit_n_rules 0
569#define audit_signals 0 578#define audit_signals 0
diff --git a/include/linux/tty.h b/include/linux/tty.h
index e500171c745f..2a754748dd5f 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -541,8 +541,8 @@ extern void tty_audit_exit(void);
541extern void tty_audit_fork(struct signal_struct *sig); 541extern void tty_audit_fork(struct signal_struct *sig);
542extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); 542extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
543extern void tty_audit_push(struct tty_struct *tty); 543extern void tty_audit_push(struct tty_struct *tty);
544extern void tty_audit_push_task(struct task_struct *tsk, 544extern int tty_audit_push_task(struct task_struct *tsk,
545 uid_t loginuid, u32 sessionid); 545 uid_t loginuid, u32 sessionid);
546#else 546#else
547static inline void tty_audit_add_data(struct tty_struct *tty, 547static inline void tty_audit_add_data(struct tty_struct *tty,
548 unsigned char *data, size_t size) 548 unsigned char *data, size_t size)
@@ -560,9 +560,10 @@ static inline void tty_audit_fork(struct signal_struct *sig)
560static inline void tty_audit_push(struct tty_struct *tty) 560static inline void tty_audit_push(struct tty_struct *tty)
561{ 561{
562} 562}
563static inline void tty_audit_push_task(struct task_struct *tsk, 563static inline int tty_audit_push_task(struct task_struct *tsk,
564 uid_t loginuid, u32 sessionid) 564 uid_t loginuid, u32 sessionid)
565{ 565{
566 return 0;
566} 567}
567#endif 568#endif
568 569
diff --git a/kernel/audit.c b/kernel/audit.c
index d96045789b54..77770a034d59 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -467,23 +467,16 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid)
467 struct task_struct *tsk; 467 struct task_struct *tsk;
468 int err; 468 int err;
469 469
470 read_lock(&tasklist_lock); 470 rcu_read_lock();
471 tsk = find_task_by_vpid(pid); 471 tsk = find_task_by_vpid(pid);
472 err = -ESRCH; 472 if (!tsk) {
473 if (!tsk) 473 rcu_read_unlock();
474 goto out; 474 return -ESRCH;
475 err = 0; 475 }
476 476 get_task_struct(tsk);
477 spin_lock_irq(&tsk->sighand->siglock); 477 rcu_read_unlock();
478 if (!tsk->signal->audit_tty) 478 err = tty_audit_push_task(tsk, loginuid, sessionid);
479 err = -EPERM; 479 put_task_struct(tsk);
480 spin_unlock_irq(&tsk->sighand->siglock);
481 if (err)
482 goto out;
483
484 tty_audit_push_task(tsk, loginuid, sessionid);
485out:
486 read_unlock(&tasklist_lock);
487 return err; 480 return err;
488} 481}
489 482
@@ -506,7 +499,7 @@ int audit_send_list(void *_dest)
506} 499}
507 500
508struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, 501struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
509 int multi, void *payload, int size) 502 int multi, const void *payload, int size)
510{ 503{
511 struct sk_buff *skb; 504 struct sk_buff *skb;
512 struct nlmsghdr *nlh; 505 struct nlmsghdr *nlh;
@@ -555,8 +548,8 @@ static int audit_send_reply_thread(void *arg)
555 * Allocates an skb, builds the netlink message, and sends it to the pid. 548 * Allocates an skb, builds the netlink message, and sends it to the pid.
556 * No failure notifications. 549 * No failure notifications.
557 */ 550 */
558void audit_send_reply(int pid, int seq, int type, int done, int multi, 551static void audit_send_reply(int pid, int seq, int type, int done, int multi,
559 void *payload, int size) 552 const void *payload, int size)
560{ 553{
561 struct sk_buff *skb; 554 struct sk_buff *skb;
562 struct task_struct *tsk; 555 struct task_struct *tsk;
@@ -880,40 +873,40 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
880 case AUDIT_TTY_GET: { 873 case AUDIT_TTY_GET: {
881 struct audit_tty_status s; 874 struct audit_tty_status s;
882 struct task_struct *tsk; 875 struct task_struct *tsk;
876 unsigned long flags;
883 877
884 read_lock(&tasklist_lock); 878 rcu_read_lock();
885 tsk = find_task_by_vpid(pid); 879 tsk = find_task_by_vpid(pid);
886 if (!tsk) 880 if (tsk && lock_task_sighand(tsk, &flags)) {
887 err = -ESRCH;
888 else {
889 spin_lock_irq(&tsk->sighand->siglock);
890 s.enabled = tsk->signal->audit_tty != 0; 881 s.enabled = tsk->signal->audit_tty != 0;
891 spin_unlock_irq(&tsk->sighand->siglock); 882 unlock_task_sighand(tsk, &flags);
892 } 883 } else
893 read_unlock(&tasklist_lock); 884 err = -ESRCH;
894 audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0, 885 rcu_read_unlock();
895 &s, sizeof(s)); 886
887 if (!err)
888 audit_send_reply(NETLINK_CB(skb).pid, seq,
889 AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
896 break; 890 break;
897 } 891 }
898 case AUDIT_TTY_SET: { 892 case AUDIT_TTY_SET: {
899 struct audit_tty_status *s; 893 struct audit_tty_status *s;
900 struct task_struct *tsk; 894 struct task_struct *tsk;
895 unsigned long flags;
901 896
902 if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) 897 if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
903 return -EINVAL; 898 return -EINVAL;
904 s = data; 899 s = data;
905 if (s->enabled != 0 && s->enabled != 1) 900 if (s->enabled != 0 && s->enabled != 1)
906 return -EINVAL; 901 return -EINVAL;
907 read_lock(&tasklist_lock); 902 rcu_read_lock();
908 tsk = find_task_by_vpid(pid); 903 tsk = find_task_by_vpid(pid);
909 if (!tsk) 904 if (tsk && lock_task_sighand(tsk, &flags)) {
910 err = -ESRCH;
911 else {
912 spin_lock_irq(&tsk->sighand->siglock);
913 tsk->signal->audit_tty = s->enabled != 0; 905 tsk->signal->audit_tty = s->enabled != 0;
914 spin_unlock_irq(&tsk->sighand->siglock); 906 unlock_task_sighand(tsk, &flags);
915 } 907 } else
916 read_unlock(&tasklist_lock); 908 err = -ESRCH;
909 rcu_read_unlock();
917 break; 910 break;
918 } 911 }
919 default: 912 default:
diff --git a/kernel/audit.h b/kernel/audit.h
index f7206db4e13d..91e7071c4d2c 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -84,10 +84,7 @@ extern int audit_compare_dname_path(const char *dname, const char *path,
84 int *dirlen); 84 int *dirlen);
85extern struct sk_buff * audit_make_reply(int pid, int seq, int type, 85extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
86 int done, int multi, 86 int done, int multi,
87 void *payload, int size); 87 const void *payload, int size);
88extern void audit_send_reply(int pid, int seq, int type,
89 int done, int multi,
90 void *payload, int size);
91extern void audit_panic(const char *message); 88extern void audit_panic(const char *message);
92 89
93struct audit_netlink_list { 90struct audit_netlink_list {
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 7f18d3a4527e..37b2bea170c8 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -223,7 +223,7 @@ static void untag_chunk(struct node *p)
223{ 223{
224 struct audit_chunk *chunk = find_chunk(p); 224 struct audit_chunk *chunk = find_chunk(p);
225 struct fsnotify_mark *entry = &chunk->mark; 225 struct fsnotify_mark *entry = &chunk->mark;
226 struct audit_chunk *new; 226 struct audit_chunk *new = NULL;
227 struct audit_tree *owner; 227 struct audit_tree *owner;
228 int size = chunk->count - 1; 228 int size = chunk->count - 1;
229 int i, j; 229 int i, j;
@@ -232,9 +232,14 @@ static void untag_chunk(struct node *p)
232 232
233 spin_unlock(&hash_lock); 233 spin_unlock(&hash_lock);
234 234
235 if (size)
236 new = alloc_chunk(size);
237
235 spin_lock(&entry->lock); 238 spin_lock(&entry->lock);
236 if (chunk->dead || !entry->i.inode) { 239 if (chunk->dead || !entry->i.inode) {
237 spin_unlock(&entry->lock); 240 spin_unlock(&entry->lock);
241 if (new)
242 free_chunk(new);
238 goto out; 243 goto out;
239 } 244 }
240 245
@@ -255,9 +260,9 @@ static void untag_chunk(struct node *p)
255 goto out; 260 goto out;
256 } 261 }
257 262
258 new = alloc_chunk(size);
259 if (!new) 263 if (!new)
260 goto Fallback; 264 goto Fallback;
265
261 fsnotify_duplicate_mark(&new->mark, entry); 266 fsnotify_duplicate_mark(&new->mark, entry);
262 if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { 267 if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) {
263 free_chunk(new); 268 free_chunk(new);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index f0c9b2e7542d..d2e3c7866460 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -60,7 +60,7 @@ struct audit_parent {
60}; 60};
61 61
62/* fsnotify handle. */ 62/* fsnotify handle. */
63struct fsnotify_group *audit_watch_group; 63static struct fsnotify_group *audit_watch_group;
64 64
65/* fsnotify events we care about. */ 65/* fsnotify events we care about. */
66#define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\ 66#define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\
@@ -123,7 +123,7 @@ void audit_put_watch(struct audit_watch *watch)
123 } 123 }
124} 124}
125 125
126void audit_remove_watch(struct audit_watch *watch) 126static void audit_remove_watch(struct audit_watch *watch)
127{ 127{
128 list_del(&watch->wlist); 128 list_del(&watch->wlist);
129 audit_put_parent(watch->parent); 129 audit_put_parent(watch->parent);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index eb7675499fb5..add2819af71b 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1252,6 +1252,18 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb,
1252 case AUDIT_LOGINUID: 1252 case AUDIT_LOGINUID:
1253 result = audit_comparator(cb->loginuid, f->op, f->val); 1253 result = audit_comparator(cb->loginuid, f->op, f->val);
1254 break; 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 if (!result) 1269 if (!result)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 1b31c130d034..f49a0318c2ed 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -241,6 +241,10 @@ struct audit_context {
241 pid_t pid; 241 pid_t pid;
242 struct audit_cap_data cap; 242 struct audit_cap_data cap;
243 } capset; 243 } capset;
244 struct {
245 int fd;
246 int flags;
247 } mmap;
244 }; 248 };
245 int fds[2]; 249 int fds[2];
246 250
@@ -1305,6 +1309,10 @@ static void show_special(struct audit_context *context, int *call_panic)
1305 audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted); 1309 audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
1306 audit_log_cap(ab, "cap_pe", &context->capset.cap.effective); 1310 audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
1307 break; } 1311 break; }
1312 case AUDIT_MMAP: {
1313 audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
1314 context->mmap.flags);
1315 break; }
1308 } 1316 }
1309 audit_log_end(ab); 1317 audit_log_end(ab);
1310} 1318}
@@ -2476,6 +2484,14 @@ void __audit_log_capset(pid_t pid,
2476 context->type = AUDIT_CAPSET; 2484 context->type = AUDIT_CAPSET;
2477} 2485}
2478 2486
2487void __audit_mmap_fd(int fd, int flags)
2488{
2489 struct audit_context *context = current->audit_context;
2490 context->mmap.fd = fd;
2491 context->mmap.flags = flags;
2492 context->type = AUDIT_MMAP;
2493}
2494
2479/** 2495/**
2480 * audit_core_dumps - record information about processes that end abnormally 2496 * audit_core_dumps - record information about processes that end abnormally
2481 * @signr: signal value 2497 * @signr: signal value
diff --git a/mm/mmap.c b/mm/mmap.c
index 00161a48a451..b179abb1474a 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -28,6 +28,7 @@
28#include <linux/rmap.h> 28#include <linux/rmap.h>
29#include <linux/mmu_notifier.h> 29#include <linux/mmu_notifier.h>
30#include <linux/perf_event.h> 30#include <linux/perf_event.h>
31#include <linux/audit.h>
31 32
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33#include <asm/cacheflush.h> 34#include <asm/cacheflush.h>
@@ -1108,6 +1109,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
1108 unsigned long retval = -EBADF; 1109 unsigned long retval = -EBADF;
1109 1110
1110 if (!(flags & MAP_ANONYMOUS)) { 1111 if (!(flags & MAP_ANONYMOUS)) {
1112 audit_mmap_fd(fd, flags);
1111 if (unlikely(flags & MAP_HUGETLB)) 1113 if (unlikely(flags & MAP_HUGETLB))
1112 return -EINVAL; 1114 return -EINVAL;
1113 file = fget(fd); 1115 file = fget(fd);
diff --git a/mm/nommu.c b/mm/nommu.c
index 30b5c20eec15..3613517c7592 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -29,6 +29,7 @@
29#include <linux/personality.h> 29#include <linux/personality.h>
30#include <linux/security.h> 30#include <linux/security.h>
31#include <linux/syscalls.h> 31#include <linux/syscalls.h>
32#include <linux/audit.h>
32 33
33#include <asm/uaccess.h> 34#include <asm/uaccess.h>
34#include <asm/tlb.h> 35#include <asm/tlb.h>
@@ -1458,6 +1459,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
1458 struct file *file = NULL; 1459 struct file *file = NULL;
1459 unsigned long retval = -EBADF; 1460 unsigned long retval = -EBADF;
1460 1461
1462 audit_mmap_fd(fd, flags);
1461 if (!(flags & MAP_ANONYMOUS)) { 1463 if (!(flags & MAP_ANONYMOUS)) {
1462 file = fget(fd); 1464 file = fget(fd);
1463 if (!file) 1465 if (!file)