aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/n_tty.c20
-rw-r--r--drivers/char/tty_audit.c345
-rw-r--r--drivers/char/tty_io.c14
-rw-r--r--include/linux/audit.h11
-rw-r--r--include/linux/sched.h4
-rw-r--r--include/linux/tty.h33
-rw-r--r--kernel/audit.c96
-rw-r--r--kernel/audit.h1
-rw-r--r--kernel/auditsc.c3
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c3
-rw-r--r--net/netlabel/netlabel_user.c4
-rw-r--r--security/selinux/nlmsgtab.c2
14 files changed, 518 insertions, 21 deletions
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 2f56ecc035aa..f2996a95eb07 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -15,6 +15,7 @@ obj-y += misc.o
15obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ 15obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \
16 consolemap_deftbl.o selection.o keyboard.o 16 consolemap_deftbl.o selection.o keyboard.o
17obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o 17obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
18obj-$(CONFIG_AUDIT) += tty_audit.o
18obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o 19obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
19obj-$(CONFIG_ESPSERIAL) += esp.o 20obj-$(CONFIG_ESPSERIAL) += esp.o
20obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o 21obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 371631f4bfb9..038056911934 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -45,6 +45,8 @@
45#include <linux/slab.h> 45#include <linux/slab.h>
46#include <linux/poll.h> 46#include <linux/poll.h>
47#include <linux/bitops.h> 47#include <linux/bitops.h>
48#include <linux/audit.h>
49#include <linux/file.h>
48 50
49#include <asm/uaccess.h> 51#include <asm/uaccess.h>
50#include <asm/system.h> 52#include <asm/system.h>
@@ -78,6 +80,13 @@ static inline void free_buf(unsigned char *buf)
78 free_page((unsigned long) buf); 80 free_page((unsigned long) buf);
79} 81}
80 82
83static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
84 unsigned char __user *ptr)
85{
86 tty_audit_add_data(tty, &x, 1);
87 return put_user(x, ptr);
88}
89
81/** 90/**
82 * n_tty_set__room - receive space 91 * n_tty_set__room - receive space
83 * @tty: terminal 92 * @tty: terminal
@@ -1153,6 +1162,7 @@ static int copy_from_read_buf(struct tty_struct *tty,
1153 if (n) { 1162 if (n) {
1154 retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n); 1163 retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
1155 n -= retval; 1164 n -= retval;
1165 tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
1156 spin_lock_irqsave(&tty->read_lock, flags); 1166 spin_lock_irqsave(&tty->read_lock, flags);
1157 tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); 1167 tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
1158 tty->read_cnt -= n; 1168 tty->read_cnt -= n;
@@ -1279,7 +1289,7 @@ do_it_again:
1279 break; 1289 break;
1280 cs = tty->link->ctrl_status; 1290 cs = tty->link->ctrl_status;
1281 tty->link->ctrl_status = 0; 1291 tty->link->ctrl_status = 0;
1282 if (put_user(cs, b++)) { 1292 if (tty_put_user(tty, cs, b++)) {
1283 retval = -EFAULT; 1293 retval = -EFAULT;
1284 b--; 1294 b--;
1285 break; 1295 break;
@@ -1321,7 +1331,7 @@ do_it_again:
1321 1331
1322 /* Deal with packet mode. */ 1332 /* Deal with packet mode. */
1323 if (tty->packet && b == buf) { 1333 if (tty->packet && b == buf) {
1324 if (put_user(TIOCPKT_DATA, b++)) { 1334 if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
1325 retval = -EFAULT; 1335 retval = -EFAULT;
1326 b--; 1336 b--;
1327 break; 1337 break;
@@ -1352,15 +1362,17 @@ do_it_again:
1352 spin_unlock_irqrestore(&tty->read_lock, flags); 1362 spin_unlock_irqrestore(&tty->read_lock, flags);
1353 1363
1354 if (!eol || (c != __DISABLED_CHAR)) { 1364 if (!eol || (c != __DISABLED_CHAR)) {
1355 if (put_user(c, b++)) { 1365 if (tty_put_user(tty, c, b++)) {
1356 retval = -EFAULT; 1366 retval = -EFAULT;
1357 b--; 1367 b--;
1358 break; 1368 break;
1359 } 1369 }
1360 nr--; 1370 nr--;
1361 } 1371 }
1362 if (eol) 1372 if (eol) {
1373 tty_audit_push(tty);
1363 break; 1374 break;
1375 }
1364 } 1376 }
1365 if (retval) 1377 if (retval)
1366 break; 1378 break;
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
new file mode 100644
index 000000000000..d222012c1b0c
--- /dev/null
+++ b/drivers/char/tty_audit.c
@@ -0,0 +1,345 @@
1/*
2 * Creating audit events from TTY input.
3 *
4 * Copyright (C) 2007 Red Hat, Inc. All rights reserved. This copyrighted
5 * material is made available to anyone wishing to use, modify, copy, or
6 * redistribute it subject to the terms and conditions of the GNU General
7 * Public License v.2.
8 *
9 * Authors: Miloslav Trmac <mitr@redhat.com>
10 */
11
12#include <linux/audit.h>
13#include <linux/file.h>
14#include <linux/tty.h>
15
16struct tty_audit_buf {
17 atomic_t count;
18 struct mutex mutex; /* Protects all data below */
19 int major, minor; /* The TTY which the data is from */
20 unsigned icanon:1;
21 size_t valid;
22 unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */
23};
24
25static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
26 int icanon)
27{
28 struct tty_audit_buf *buf;
29
30 buf = kmalloc(sizeof (*buf), GFP_KERNEL);
31 if (!buf)
32 goto err;
33 if (PAGE_SIZE != N_TTY_BUF_SIZE)
34 buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
35 else
36 buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
37 if (!buf->data)
38 goto err_buf;
39 atomic_set(&buf->count, 1);
40 mutex_init(&buf->mutex);
41 buf->major = major;
42 buf->minor = minor;
43 buf->icanon = icanon;
44 buf->valid = 0;
45 return buf;
46
47err_buf:
48 kfree(buf);
49err:
50 return NULL;
51}
52
53static void tty_audit_buf_free(struct tty_audit_buf *buf)
54{
55 WARN_ON(buf->valid != 0);
56 if (PAGE_SIZE != N_TTY_BUF_SIZE)
57 kfree(buf->data);
58 else
59 free_page((unsigned long)buf->data);
60 kfree(buf);
61}
62
63static void tty_audit_buf_put(struct tty_audit_buf *buf)
64{
65 if (atomic_dec_and_test(&buf->count))
66 tty_audit_buf_free(buf);
67}
68
69/**
70 * tty_audit_buf_push - Push buffered data out
71 *
72 * Generate an audit message from the contents of @buf, which is owned by
73 * @tsk with @loginuid. @buf->mutex must be locked.
74 */
75static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
76 struct tty_audit_buf *buf)
77{
78 struct audit_buffer *ab;
79
80 if (buf->valid == 0)
81 return;
82 if (audit_enabled == 0)
83 return;
84 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
85 if (ab) {
86 char name[sizeof(tsk->comm)];
87
88 audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
89 "minor=%d comm=", tsk->pid, tsk->uid,
90 loginuid, buf->major, buf->minor);
91 get_task_comm(name, tsk);
92 audit_log_untrustedstring(ab, name);
93 audit_log_format(ab, " data=");
94 audit_log_n_untrustedstring(ab, buf->valid, buf->data);
95 audit_log_end(ab);
96 }
97 buf->valid = 0;
98}
99
100/**
101 * tty_audit_buf_push_current - Push buffered data out
102 *
103 * Generate an audit message from the contents of @buf, which is owned by
104 * the current task. @buf->mutex must be locked.
105 */
106static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
107{
108 tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
109 buf);
110}
111
112/**
113 * tty_audit_exit - Handle a task exit
114 *
115 * Make sure all buffered data is written out and deallocate the buffer.
116 * Only needs to be called if current->signal->tty_audit_buf != %NULL.
117 */
118void tty_audit_exit(void)
119{
120 struct tty_audit_buf *buf;
121
122 spin_lock_irq(&current->sighand->siglock);
123 buf = current->signal->tty_audit_buf;
124 current->signal->tty_audit_buf = NULL;
125 spin_unlock_irq(&current->sighand->siglock);
126 if (!buf)
127 return;
128
129 mutex_lock(&buf->mutex);
130 tty_audit_buf_push_current(buf);
131 mutex_unlock(&buf->mutex);
132
133 tty_audit_buf_put(buf);
134}
135
136/**
137 * tty_audit_fork - Copy TTY audit state for a new task
138 *
139 * Set up TTY audit state in @sig from current. @sig needs no locking.
140 */
141void tty_audit_fork(struct signal_struct *sig)
142{
143 spin_lock_irq(&current->sighand->siglock);
144 sig->audit_tty = current->signal->audit_tty;
145 spin_unlock_irq(&current->sighand->siglock);
146 sig->tty_audit_buf = NULL;
147}
148
149/**
150 * tty_audit_push_task - Flush task's pending audit data
151 */
152void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
153{
154 struct tty_audit_buf *buf;
155
156 spin_lock_irq(&tsk->sighand->siglock);
157 buf = tsk->signal->tty_audit_buf;
158 if (buf)
159 atomic_inc(&buf->count);
160 spin_unlock_irq(&tsk->sighand->siglock);
161 if (!buf)
162 return;
163
164 mutex_lock(&buf->mutex);
165 tty_audit_buf_push(tsk, loginuid, buf);
166 mutex_unlock(&buf->mutex);
167
168 tty_audit_buf_put(buf);
169}
170
171/**
172 * tty_audit_buf_get - Get an audit buffer.
173 *
174 * Get an audit buffer for @tty, allocate it if necessary. Return %NULL
175 * if TTY auditing is disabled or out of memory. Otherwise, return a new
176 * reference to the buffer.
177 */
178static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
179{
180 struct tty_audit_buf *buf, *buf2;
181
182 buf = NULL;
183 buf2 = NULL;
184 spin_lock_irq(&current->sighand->siglock);
185 if (likely(!current->signal->audit_tty))
186 goto out;
187 buf = current->signal->tty_audit_buf;
188 if (buf) {
189 atomic_inc(&buf->count);
190 goto out;
191 }
192 spin_unlock_irq(&current->sighand->siglock);
193
194 buf2 = tty_audit_buf_alloc(tty->driver->major,
195 tty->driver->minor_start + tty->index,
196 tty->icanon);
197 if (buf2 == NULL) {
198 audit_log_lost("out of memory in TTY auditing");
199 return NULL;
200 }
201
202 spin_lock_irq(&current->sighand->siglock);
203 if (!current->signal->audit_tty)
204 goto out;
205 buf = current->signal->tty_audit_buf;
206 if (!buf) {
207 current->signal->tty_audit_buf = buf2;
208 buf = buf2;
209 buf2 = NULL;
210 }
211 atomic_inc(&buf->count);
212 /* Fall through */
213 out:
214 spin_unlock_irq(&current->sighand->siglock);
215 if (buf2)
216 tty_audit_buf_free(buf2);
217 return buf;
218}
219
220/**
221 * tty_audit_add_data - Add data for TTY auditing.
222 *
223 * Audit @data of @size from @tty, if necessary.
224 */
225void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
226 size_t size)
227{
228 struct tty_audit_buf *buf;
229 int major, minor;
230
231 if (unlikely(size == 0))
232 return;
233
234 buf = tty_audit_buf_get(tty);
235 if (!buf)
236 return;
237
238 mutex_lock(&buf->mutex);
239 major = tty->driver->major;
240 minor = tty->driver->minor_start + tty->index;
241 if (buf->major != major || buf->minor != minor
242 || buf->icanon != tty->icanon) {
243 tty_audit_buf_push_current(buf);
244 buf->major = major;
245 buf->minor = minor;
246 buf->icanon = tty->icanon;
247 }
248 do {
249 size_t run;
250
251 run = N_TTY_BUF_SIZE - buf->valid;
252 if (run > size)
253 run = size;
254 memcpy(buf->data + buf->valid, data, run);
255 buf->valid += run;
256 data += run;
257 size -= run;
258 if (buf->valid == N_TTY_BUF_SIZE)
259 tty_audit_buf_push_current(buf);
260 } while (size != 0);
261 mutex_unlock(&buf->mutex);
262 tty_audit_buf_put(buf);
263}
264
265/**
266 * tty_audit_push - Push buffered data out
267 *
268 * Make sure no audit data is pending for @tty on the current process.
269 */
270void tty_audit_push(struct tty_struct *tty)
271{
272 struct tty_audit_buf *buf;
273
274 spin_lock_irq(&current->sighand->siglock);
275 if (likely(!current->signal->audit_tty)) {
276 spin_unlock_irq(&current->sighand->siglock);
277 return;
278 }
279 buf = current->signal->tty_audit_buf;
280 if (buf)
281 atomic_inc(&buf->count);
282 spin_unlock_irq(&current->sighand->siglock);
283
284 if (buf) {
285 int major, minor;
286
287 major = tty->driver->major;
288 minor = tty->driver->minor_start + tty->index;
289 mutex_lock(&buf->mutex);
290 if (buf->major == major && buf->minor == minor)
291 tty_audit_buf_push_current(buf);
292 mutex_unlock(&buf->mutex);
293 tty_audit_buf_put(buf);
294 }
295}
296
297/**
298 * tty_audit_opening - A TTY is being opened.
299 *
300 * As a special hack, tasks that close all their TTYs and open new ones
301 * are assumed to be system daemons (e.g. getty) and auditing is
302 * automatically disabled for them.
303 */
304void tty_audit_opening(void)
305{
306 int disable;
307
308 disable = 1;
309 spin_lock_irq(&current->sighand->siglock);
310 if (current->signal->audit_tty == 0)
311 disable = 0;
312 spin_unlock_irq(&current->sighand->siglock);
313 if (!disable)
314 return;
315
316 task_lock(current);
317 if (current->files) {
318 struct fdtable *fdt;
319 unsigned i;
320
321 /*
322 * We don't take a ref to the file, so we must hold ->file_lock
323 * instead.
324 */
325 spin_lock(&current->files->file_lock);
326 fdt = files_fdtable(current->files);
327 for (i = 0; i < fdt->max_fds; i++) {
328 struct file *filp;
329
330 filp = fcheck_files(current->files, i);
331 if (filp && is_tty(filp)) {
332 disable = 0;
333 break;
334 }
335 }
336 spin_unlock(&current->files->file_lock);
337 }
338 task_unlock(current);
339 if (!disable)
340 return;
341
342 spin_lock_irq(&current->sighand->siglock);
343 current->signal->audit_tty = 0;
344 spin_unlock_irq(&current->sighand->siglock);
345}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index fde69e589ca7..de37ebc3a4cf 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1503,6 +1503,15 @@ int tty_hung_up_p(struct file * filp)
1503 1503
1504EXPORT_SYMBOL(tty_hung_up_p); 1504EXPORT_SYMBOL(tty_hung_up_p);
1505 1505
1506/**
1507 * is_tty - checker whether file is a TTY
1508 */
1509int is_tty(struct file *filp)
1510{
1511 return filp->f_op->read == tty_read
1512 || filp->f_op->read == hung_up_tty_read;
1513}
1514
1506static void session_clear_tty(struct pid *session) 1515static void session_clear_tty(struct pid *session)
1507{ 1516{
1508 struct task_struct *p; 1517 struct task_struct *p;
@@ -2673,6 +2682,7 @@ got_driver:
2673 __proc_set_tty(current, tty); 2682 __proc_set_tty(current, tty);
2674 spin_unlock_irq(&current->sighand->siglock); 2683 spin_unlock_irq(&current->sighand->siglock);
2675 mutex_unlock(&tty_mutex); 2684 mutex_unlock(&tty_mutex);
2685 tty_audit_opening();
2676 return 0; 2686 return 0;
2677} 2687}
2678 2688
@@ -2735,8 +2745,10 @@ static int ptmx_open(struct inode * inode, struct file * filp)
2735 2745
2736 check_tty_count(tty, "tty_open"); 2746 check_tty_count(tty, "tty_open");
2737 retval = ptm_driver->open(tty, filp); 2747 retval = ptm_driver->open(tty, filp);
2738 if (!retval) 2748 if (!retval) {
2749 tty_audit_opening();
2739 return 0; 2750 return 0;
2751 }
2740out1: 2752out1:
2741 release_dev(filp); 2753 release_dev(filp);
2742 return retval; 2754 return retval;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index fccc6e50298a..8ca7ca0b47f0 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -63,9 +63,12 @@
63#define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */ 63#define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */
64#define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */ 64#define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */
65#define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */ 65#define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */
66#define AUDIT_TTY_GET 1014 /* Get TTY auditing status */
67#define AUDIT_TTY_SET 1015 /* Set TTY auditing status */
66 68
67#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ 69#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
68#define AUDIT_USER_AVC 1107 /* We filter this differently */ 70#define AUDIT_USER_AVC 1107 /* We filter this differently */
71#define AUDIT_USER_TTY 1124 /* Non-ICANON TTY input meaning */
69#define AUDIT_LAST_USER_MSG 1199 72#define AUDIT_LAST_USER_MSG 1199
70#define AUDIT_FIRST_USER_MSG2 2100 /* More user space messages */ 73#define AUDIT_FIRST_USER_MSG2 2100 /* More user space messages */
71#define AUDIT_LAST_USER_MSG2 2999 74#define AUDIT_LAST_USER_MSG2 2999
@@ -92,6 +95,7 @@
92#define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ 95#define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */
93#define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ 96#define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */
94#define AUDIT_OBJ_PID 1318 /* ptrace target */ 97#define AUDIT_OBJ_PID 1318 /* ptrace target */
98#define AUDIT_TTY 1319 /* Input on an administrative TTY */
95 99
96#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ 100#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
97#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ 101#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -289,6 +293,10 @@ struct audit_status {
289 __u32 backlog; /* messages waiting in queue */ 293 __u32 backlog; /* messages waiting in queue */
290}; 294};
291 295
296struct audit_tty_status {
297 __u32 enabled; /* 1 = enabled, 0 = disabled */
298};
299
292/* audit_rule_data supports filter rules with both integer and string 300/* audit_rule_data supports filter rules with both integer and string
293 * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and 301 * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
294 * AUDIT_LIST_RULES requests. 302 * AUDIT_LIST_RULES requests.
@@ -515,11 +523,13 @@ extern void audit_log_d_path(struct audit_buffer *ab,
515 const char *prefix, 523 const char *prefix,
516 struct dentry *dentry, 524 struct dentry *dentry,
517 struct vfsmount *vfsmnt); 525 struct vfsmount *vfsmnt);
526extern void audit_log_lost(const char *message);
518 /* Private API (for audit.c only) */ 527 /* Private API (for audit.c only) */
519extern int audit_filter_user(struct netlink_skb_parms *cb, int type); 528extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
520extern int audit_filter_type(int type); 529extern int audit_filter_type(int type);
521extern int audit_receive_filter(int type, int pid, int uid, int seq, 530extern int audit_receive_filter(int type, int pid, int uid, int seq,
522 void *data, size_t datasz, uid_t loginuid, u32 sid); 531 void *data, size_t datasz, uid_t loginuid, u32 sid);
532extern int audit_enabled;
523#else 533#else
524#define audit_log(c,g,t,f,...) do { ; } while (0) 534#define audit_log(c,g,t,f,...) do { ; } while (0)
525#define audit_log_start(c,g,t) ({ NULL; }) 535#define audit_log_start(c,g,t) ({ NULL; })
@@ -530,6 +540,7 @@ extern int audit_receive_filter(int type, int pid, int uid, int seq,
530#define audit_log_untrustedstring(a,s) do { ; } while (0) 540#define audit_log_untrustedstring(a,s) do { ; } while (0)
531#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0) 541#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
532#define audit_log_d_path(b,p,d,v) do { ; } while (0) 542#define audit_log_d_path(b,p,d,v) do { ; } while (0)
543#define audit_enabled 0
533#endif 544#endif
534#endif 545#endif
535#endif 546#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 3cffc1204663..b579624477f4 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -529,6 +529,10 @@ struct signal_struct {
529#ifdef CONFIG_TASKSTATS 529#ifdef CONFIG_TASKSTATS
530 struct taskstats *stats; 530 struct taskstats *stats;
531#endif 531#endif
532#ifdef CONFIG_AUDIT
533 unsigned audit_tty;
534 struct tty_audit_buf *tty_audit_buf;
535#endif
532}; 536};
533 537
534/* Context switch must be unlocked if interrupts are to be enabled */ 538/* Context switch must be unlocked if interrupts are to be enabled */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index deaba9ec5004..691a1748d9d2 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -178,6 +178,7 @@ struct tty_bufhead {
178#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN) 178#define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN)
179 179
180struct device; 180struct device;
181struct signal_struct;
181/* 182/*
182 * Where all of the state associated with a tty is kept while the tty 183 * Where all of the state associated with a tty is kept while the tty
183 * is open. Since the termios state should be kept even if the tty 184 * is open. Since the termios state should be kept even if the tty
@@ -310,6 +311,7 @@ extern void tty_hangup(struct tty_struct * tty);
310extern void tty_vhangup(struct tty_struct * tty); 311extern void tty_vhangup(struct tty_struct * tty);
311extern void tty_unhangup(struct file *filp); 312extern void tty_unhangup(struct file *filp);
312extern int tty_hung_up_p(struct file * filp); 313extern int tty_hung_up_p(struct file * filp);
314extern int is_tty(struct file *filp);
313extern void do_SAK(struct tty_struct *tty); 315extern void do_SAK(struct tty_struct *tty);
314extern void __do_SAK(struct tty_struct *tty); 316extern void __do_SAK(struct tty_struct *tty);
315extern void disassociate_ctty(int priv); 317extern void disassociate_ctty(int priv);
@@ -347,6 +349,37 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay);
347/* n_tty.c */ 349/* n_tty.c */
348extern struct tty_ldisc tty_ldisc_N_TTY; 350extern struct tty_ldisc tty_ldisc_N_TTY;
349 351
352/* tty_audit.c */
353#ifdef CONFIG_AUDIT
354extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
355 size_t size);
356extern void tty_audit_exit(void);
357extern void tty_audit_fork(struct signal_struct *sig);
358extern void tty_audit_push(struct tty_struct *tty);
359extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid);
360extern void tty_audit_opening(void);
361#else
362static inline void tty_audit_add_data(struct tty_struct *tty,
363 unsigned char *data, size_t size)
364{
365}
366static inline void tty_audit_exit(void)
367{
368}
369static inline void tty_audit_fork(struct signal_struct *sig)
370{
371}
372static inline void tty_audit_push(struct tty_struct *tty)
373{
374}
375static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
376{
377}
378static inline void tty_audit_opening(void)
379{
380}
381#endif
382
350/* tty_ioctl.c */ 383/* tty_ioctl.c */
351extern int n_tty_ioctl(struct tty_struct * tty, struct file * file, 384extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
352 unsigned int cmd, unsigned long arg); 385 unsigned int cmd, unsigned long arg);
diff --git a/kernel/audit.c b/kernel/audit.c
index d13276d41410..5ce8851facf7 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -58,6 +58,7 @@
58#include <linux/selinux.h> 58#include <linux/selinux.h>
59#include <linux/inotify.h> 59#include <linux/inotify.h>
60#include <linux/freezer.h> 60#include <linux/freezer.h>
61#include <linux/tty.h>
61 62
62#include "audit.h" 63#include "audit.h"
63 64
@@ -423,6 +424,31 @@ static int kauditd_thread(void *dummy)
423 return 0; 424 return 0;
424} 425}
425 426
427static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
428{
429 struct task_struct *tsk;
430 int err;
431
432 read_lock(&tasklist_lock);
433 tsk = find_task_by_pid(pid);
434 err = -ESRCH;
435 if (!tsk)
436 goto out;
437 err = 0;
438
439 spin_lock_irq(&tsk->sighand->siglock);
440 if (!tsk->signal->audit_tty)
441 err = -EPERM;
442 spin_unlock_irq(&tsk->sighand->siglock);
443 if (err)
444 goto out;
445
446 tty_audit_push_task(tsk, loginuid);
447out:
448 read_unlock(&tasklist_lock);
449 return err;
450}
451
426int audit_send_list(void *_dest) 452int audit_send_list(void *_dest)
427{ 453{
428 struct audit_netlink_list *dest = _dest; 454 struct audit_netlink_list *dest = _dest;
@@ -511,6 +537,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
511 case AUDIT_DEL: 537 case AUDIT_DEL:
512 case AUDIT_DEL_RULE: 538 case AUDIT_DEL_RULE:
513 case AUDIT_SIGNAL_INFO: 539 case AUDIT_SIGNAL_INFO:
540 case AUDIT_TTY_GET:
541 case AUDIT_TTY_SET:
514 if (security_netlink_recv(skb, CAP_AUDIT_CONTROL)) 542 if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
515 err = -EPERM; 543 err = -EPERM;
516 break; 544 break;
@@ -622,6 +650,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
622 err = audit_filter_user(&NETLINK_CB(skb), msg_type); 650 err = audit_filter_user(&NETLINK_CB(skb), msg_type);
623 if (err == 1) { 651 if (err == 1) {
624 err = 0; 652 err = 0;
653 if (msg_type == AUDIT_USER_TTY) {
654 err = audit_prepare_user_tty(pid, loginuid);
655 if (err)
656 break;
657 }
625 ab = audit_log_start(NULL, GFP_KERNEL, msg_type); 658 ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
626 if (ab) { 659 if (ab) {
627 audit_log_format(ab, 660 audit_log_format(ab,
@@ -638,8 +671,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
638 " subj=%s", ctx); 671 " subj=%s", ctx);
639 kfree(ctx); 672 kfree(ctx);
640 } 673 }
641 audit_log_format(ab, " msg='%.1024s'", 674 if (msg_type != AUDIT_USER_TTY)
642 (char *)data); 675 audit_log_format(ab, " msg='%.1024s'",
676 (char *)data);
677 else {
678 int size;
679
680 audit_log_format(ab, " msg=");
681 size = nlmsg_len(nlh);
682 audit_log_n_untrustedstring(ab, size,
683 data);
684 }
643 audit_set_pid(ab, pid); 685 audit_set_pid(ab, pid);
644 audit_log_end(ab); 686 audit_log_end(ab);
645 } 687 }
@@ -730,6 +772,45 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
730 0, 0, sig_data, sizeof(*sig_data) + len); 772 0, 0, sig_data, sizeof(*sig_data) + len);
731 kfree(sig_data); 773 kfree(sig_data);
732 break; 774 break;
775 case AUDIT_TTY_GET: {
776 struct audit_tty_status s;
777 struct task_struct *tsk;
778
779 read_lock(&tasklist_lock);
780 tsk = find_task_by_pid(pid);
781 if (!tsk)
782 err = -ESRCH;
783 else {
784 spin_lock_irq(&tsk->sighand->siglock);
785 s.enabled = tsk->signal->audit_tty != 0;
786 spin_unlock_irq(&tsk->sighand->siglock);
787 }
788 read_unlock(&tasklist_lock);
789 audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0,
790 &s, sizeof(s));
791 break;
792 }
793 case AUDIT_TTY_SET: {
794 struct audit_tty_status *s;
795 struct task_struct *tsk;
796
797 if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
798 return -EINVAL;
799 s = data;
800 if (s->enabled != 0 && s->enabled != 1)
801 return -EINVAL;
802 read_lock(&tasklist_lock);
803 tsk = find_task_by_pid(pid);
804 if (!tsk)
805 err = -ESRCH;
806 else {
807 spin_lock_irq(&tsk->sighand->siglock);
808 tsk->signal->audit_tty = s->enabled != 0;
809 spin_unlock_irq(&tsk->sighand->siglock);
810 }
811 read_unlock(&tasklist_lock);
812 break;
813 }
733 default: 814 default:
734 err = -EINVAL; 815 err = -EINVAL;
735 break; 816 break;
@@ -1185,7 +1266,7 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
1185} 1266}
1186 1267
1187/** 1268/**
1188 * audit_log_n_unstrustedstring - log a string that may contain random characters 1269 * audit_log_n_untrustedstring - log a string that may contain random characters
1189 * @ab: audit_buffer 1270 * @ab: audit_buffer
1190 * @len: lenth of string (not including trailing null) 1271 * @len: lenth of string (not including trailing null)
1191 * @string: string to be logged 1272 * @string: string to be logged
@@ -1201,25 +1282,24 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
1201const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, 1282const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
1202 const char *string) 1283 const char *string)
1203{ 1284{
1204 const unsigned char *p = string; 1285 const unsigned char *p;
1205 1286
1206 while (*p) { 1287 for (p = string; p < (const unsigned char *)string + len && *p; p++) {
1207 if (*p == '"' || *p < 0x21 || *p > 0x7f) { 1288 if (*p == '"' || *p < 0x21 || *p > 0x7f) {
1208 audit_log_hex(ab, string, len); 1289 audit_log_hex(ab, string, len);
1209 return string + len + 1; 1290 return string + len + 1;
1210 } 1291 }
1211 p++;
1212 } 1292 }
1213 audit_log_n_string(ab, len, string); 1293 audit_log_n_string(ab, len, string);
1214 return p + 1; 1294 return p + 1;
1215} 1295}
1216 1296
1217/** 1297/**
1218 * audit_log_unstrustedstring - log a string that may contain random characters 1298 * audit_log_untrustedstring - log a string that may contain random characters
1219 * @ab: audit_buffer 1299 * @ab: audit_buffer
1220 * @string: string to be logged 1300 * @string: string to be logged
1221 * 1301 *
1222 * Same as audit_log_n_unstrustedstring(), except that strlen is used to 1302 * Same as audit_log_n_untrustedstring(), except that strlen is used to
1223 * determine string length. 1303 * determine string length.
1224 */ 1304 */
1225const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) 1305const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
diff --git a/kernel/audit.h b/kernel/audit.h
index 815d6f5c04ee..95877435c347 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -115,7 +115,6 @@ extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
115extern void audit_send_reply(int pid, int seq, int type, 115extern void audit_send_reply(int pid, int seq, int type,
116 int done, int multi, 116 int done, int multi,
117 void *payload, int size); 117 void *payload, int size);
118extern void audit_log_lost(const char *message);
119extern void audit_panic(const char *message); 118extern void audit_panic(const char *message);
120 119
121struct audit_netlink_list { 120struct audit_netlink_list {
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e36481ed61b4..7ccc3da30a91 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -71,9 +71,6 @@
71 71
72extern struct list_head audit_filter_list[]; 72extern struct list_head audit_filter_list[];
73 73
74/* No syscall auditing will take place unless audit_enabled != 0. */
75extern int audit_enabled;
76
77/* AUDIT_NAMES is the number of slots we reserve in the audit_context 74/* AUDIT_NAMES is the number of slots we reserve in the audit_context
78 * for saving names from getname(). */ 75 * for saving names from getname(). */
79#define AUDIT_NAMES 20 76#define AUDIT_NAMES 20
diff --git a/kernel/exit.c b/kernel/exit.c
index 64a5263c8c7b..57626692cd90 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -965,6 +965,8 @@ fastcall NORET_TYPE void do_exit(long code)
965 if (unlikely(tsk->compat_robust_list)) 965 if (unlikely(tsk->compat_robust_list))
966 compat_exit_robust_list(tsk); 966 compat_exit_robust_list(tsk);
967#endif 967#endif
968 if (group_dead)
969 tty_audit_exit();
968 if (unlikely(tsk->audit_context)) 970 if (unlikely(tsk->audit_context))
969 audit_free(tsk); 971 audit_free(tsk);
970 972
diff --git a/kernel/fork.c b/kernel/fork.c
index 344d693fdc78..4015912aaac2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -49,6 +49,7 @@
49#include <linux/delayacct.h> 49#include <linux/delayacct.h>
50#include <linux/taskstats_kern.h> 50#include <linux/taskstats_kern.h>
51#include <linux/random.h> 51#include <linux/random.h>
52#include <linux/tty.h>
52 53
53#include <asm/pgtable.h> 54#include <asm/pgtable.h>
54#include <asm/pgalloc.h> 55#include <asm/pgalloc.h>
@@ -897,6 +898,8 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
897 } 898 }
898 acct_init_pacct(&sig->pacct); 899 acct_init_pacct(&sig->pacct);
899 900
901 tty_audit_fork(sig);
902
900 return 0; 903 return 0;
901} 904}
902 905
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 42f12bd65964..89dcc485653b 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -46,10 +46,6 @@
46#include "netlabel_cipso_v4.h" 46#include "netlabel_cipso_v4.h"
47#include "netlabel_user.h" 47#include "netlabel_user.h"
48 48
49/* do not do any auditing if audit_enabled == 0, see kernel/audit.c for
50 * details */
51extern int audit_enabled;
52
53/* 49/*
54 * NetLabel NETLINK Setup Functions 50 * NetLabel NETLINK Setup Functions
55 */ 51 */
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index ccfe8755735e..eddc7b420109 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -110,6 +110,8 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
110 { AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, 110 { AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
111 { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY }, 111 { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY },
112 { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ }, 112 { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
113 { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ },
114 { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
113}; 115};
114 116
115 117