diff options
-rw-r--r-- | drivers/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/n_tty.c | 20 | ||||
-rw-r--r-- | drivers/char/tty_audit.c | 345 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 14 | ||||
-rw-r--r-- | include/linux/audit.h | 11 | ||||
-rw-r--r-- | include/linux/sched.h | 4 | ||||
-rw-r--r-- | include/linux/tty.h | 33 | ||||
-rw-r--r-- | kernel/audit.c | 96 | ||||
-rw-r--r-- | kernel/audit.h | 1 | ||||
-rw-r--r-- | kernel/auditsc.c | 3 | ||||
-rw-r--r-- | kernel/exit.c | 2 | ||||
-rw-r--r-- | kernel/fork.c | 3 | ||||
-rw-r--r-- | net/netlabel/netlabel_user.c | 4 | ||||
-rw-r--r-- | security/selinux/nlmsgtab.c | 2 |
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 | |||
15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ | 15 | obj-$(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 |
17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o |
18 | obj-$(CONFIG_AUDIT) += tty_audit.o | ||
18 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 19 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o |
19 | obj-$(CONFIG_ESPSERIAL) += esp.o | 20 | obj-$(CONFIG_ESPSERIAL) += esp.o |
20 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o | 21 | obj-$(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 | ||
83 | static 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 | |||
16 | struct 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 | |||
25 | static 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 | |||
47 | err_buf: | ||
48 | kfree(buf); | ||
49 | err: | ||
50 | return NULL; | ||
51 | } | ||
52 | |||
53 | static 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 | |||
63 | static 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 | */ | ||
75 | static 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 | */ | ||
106 | static 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 | */ | ||
118 | void tty_audit_exit(void) | ||
119 | { | ||
120 | struct tty_audit_buf *buf; | ||
121 | |||
122 | spin_lock_irq(¤t->sighand->siglock); | ||
123 | buf = current->signal->tty_audit_buf; | ||
124 | current->signal->tty_audit_buf = NULL; | ||
125 | spin_unlock_irq(¤t->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 | */ | ||
141 | void tty_audit_fork(struct signal_struct *sig) | ||
142 | { | ||
143 | spin_lock_irq(¤t->sighand->siglock); | ||
144 | sig->audit_tty = current->signal->audit_tty; | ||
145 | spin_unlock_irq(¤t->sighand->siglock); | ||
146 | sig->tty_audit_buf = NULL; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * tty_audit_push_task - Flush task's pending audit data | ||
151 | */ | ||
152 | void 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 | */ | ||
178 | static 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(¤t->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(¤t->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(¤t->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(¤t->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 | */ | ||
225 | void 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 | */ | ||
270 | void tty_audit_push(struct tty_struct *tty) | ||
271 | { | ||
272 | struct tty_audit_buf *buf; | ||
273 | |||
274 | spin_lock_irq(¤t->sighand->siglock); | ||
275 | if (likely(!current->signal->audit_tty)) { | ||
276 | spin_unlock_irq(¤t->sighand->siglock); | ||
277 | return; | ||
278 | } | ||
279 | buf = current->signal->tty_audit_buf; | ||
280 | if (buf) | ||
281 | atomic_inc(&buf->count); | ||
282 | spin_unlock_irq(¤t->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 | */ | ||
304 | void tty_audit_opening(void) | ||
305 | { | ||
306 | int disable; | ||
307 | |||
308 | disable = 1; | ||
309 | spin_lock_irq(¤t->sighand->siglock); | ||
310 | if (current->signal->audit_tty == 0) | ||
311 | disable = 0; | ||
312 | spin_unlock_irq(¤t->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(¤t->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(¤t->files->file_lock); | ||
337 | } | ||
338 | task_unlock(current); | ||
339 | if (!disable) | ||
340 | return; | ||
341 | |||
342 | spin_lock_irq(¤t->sighand->siglock); | ||
343 | current->signal->audit_tty = 0; | ||
344 | spin_unlock_irq(¤t->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 | ||
1504 | EXPORT_SYMBOL(tty_hung_up_p); | 1504 | EXPORT_SYMBOL(tty_hung_up_p); |
1505 | 1505 | ||
1506 | /** | ||
1507 | * is_tty - checker whether file is a TTY | ||
1508 | */ | ||
1509 | int 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 | |||
1506 | static void session_clear_tty(struct pid *session) | 1515 | static 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(¤t->sighand->siglock); | 2683 | spin_unlock_irq(¤t->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 | } | ||
2740 | out1: | 2752 | out1: |
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 | ||
296 | struct 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); |
526 | extern void audit_log_lost(const char *message); | ||
518 | /* Private API (for audit.c only) */ | 527 | /* Private API (for audit.c only) */ |
519 | extern int audit_filter_user(struct netlink_skb_parms *cb, int type); | 528 | extern int audit_filter_user(struct netlink_skb_parms *cb, int type); |
520 | extern int audit_filter_type(int type); | 529 | extern int audit_filter_type(int type); |
521 | extern int audit_receive_filter(int type, int pid, int uid, int seq, | 530 | extern 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); |
532 | extern 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 | ||
180 | struct device; | 180 | struct device; |
181 | struct 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); | |||
310 | extern void tty_vhangup(struct tty_struct * tty); | 311 | extern void tty_vhangup(struct tty_struct * tty); |
311 | extern void tty_unhangup(struct file *filp); | 312 | extern void tty_unhangup(struct file *filp); |
312 | extern int tty_hung_up_p(struct file * filp); | 313 | extern int tty_hung_up_p(struct file * filp); |
314 | extern int is_tty(struct file *filp); | ||
313 | extern void do_SAK(struct tty_struct *tty); | 315 | extern void do_SAK(struct tty_struct *tty); |
314 | extern void __do_SAK(struct tty_struct *tty); | 316 | extern void __do_SAK(struct tty_struct *tty); |
315 | extern void disassociate_ctty(int priv); | 317 | extern 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 */ |
348 | extern struct tty_ldisc tty_ldisc_N_TTY; | 350 | extern struct tty_ldisc tty_ldisc_N_TTY; |
349 | 351 | ||
352 | /* tty_audit.c */ | ||
353 | #ifdef CONFIG_AUDIT | ||
354 | extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | ||
355 | size_t size); | ||
356 | extern void tty_audit_exit(void); | ||
357 | extern void tty_audit_fork(struct signal_struct *sig); | ||
358 | extern void tty_audit_push(struct tty_struct *tty); | ||
359 | extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid); | ||
360 | extern void tty_audit_opening(void); | ||
361 | #else | ||
362 | static inline void tty_audit_add_data(struct tty_struct *tty, | ||
363 | unsigned char *data, size_t size) | ||
364 | { | ||
365 | } | ||
366 | static inline void tty_audit_exit(void) | ||
367 | { | ||
368 | } | ||
369 | static inline void tty_audit_fork(struct signal_struct *sig) | ||
370 | { | ||
371 | } | ||
372 | static inline void tty_audit_push(struct tty_struct *tty) | ||
373 | { | ||
374 | } | ||
375 | static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid) | ||
376 | { | ||
377 | } | ||
378 | static inline void tty_audit_opening(void) | ||
379 | { | ||
380 | } | ||
381 | #endif | ||
382 | |||
350 | /* tty_ioctl.c */ | 383 | /* tty_ioctl.c */ |
351 | extern int n_tty_ioctl(struct tty_struct * tty, struct file * file, | 384 | extern 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 | ||
427 | static 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); | ||
447 | out: | ||
448 | read_unlock(&tasklist_lock); | ||
449 | return err; | ||
450 | } | ||
451 | |||
426 | int audit_send_list(void *_dest) | 452 | int 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, | |||
1201 | const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | 1282 | const 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 | */ |
1225 | const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | 1305 | const 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, | |||
115 | extern void audit_send_reply(int pid, int seq, int type, | 115 | extern 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); |
118 | extern void audit_log_lost(const char *message); | ||
119 | extern void audit_panic(const char *message); | 118 | extern void audit_panic(const char *message); |
120 | 119 | ||
121 | struct audit_netlink_list { | 120 | struct 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 | ||
72 | extern struct list_head audit_filter_list[]; | 72 | extern struct list_head audit_filter_list[]; |
73 | 73 | ||
74 | /* No syscall auditing will take place unless audit_enabled != 0. */ | ||
75 | extern 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 */ | ||
51 | extern 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 | ||