aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge C. Wilson <ltcgcw@us.ibm.com>2006-05-24 17:09:55 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2006-06-20 05:25:26 -0400
commit20ca73bc792be9625af184cbec36e1372611d1c3 (patch)
tree98a1232ad3c9baa14676b2b48fab79a3df4a20b0
parent8ba8e0fbe6321961f6ba04e2fd7215b37d935c83 (diff)
[PATCH] Audit of POSIX Message Queue Syscalls v.2
This patch adds audit support to POSIX message queues. It applies cleanly to the lspp.b15 branch of Al Viro's git tree. There are new auxiliary data structures, and collection and emission routines in kernel/auditsc.c. New hooks in ipc/mqueue.c collect arguments from the syscalls. I tested the patch by building the examples from the POSIX MQ library tarball. Build them -lrt, not against the old MQ library in the tarball. Here's the URL: http://www.geocities.com/wronski12/posix_ipc/libmqueue-4.41.tar.gz Do auditctl -a exit,always -S for mq_open, mq_timedsend, mq_timedreceive, mq_notify, mq_getsetattr. mq_unlink has no new hooks. Please see the corresponding userspace patch to get correct output from auditd for the new record types. [fixes folded] Signed-off-by: George Wilson <ltcgcw@us.ibm.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--include/linux/audit.h46
-rw-r--r--ipc/mqueue.c22
-rw-r--r--kernel/auditsc.c274
3 files changed, 341 insertions, 1 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 4b62743b2e6d..7c8780b150e6 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -85,6 +85,10 @@
85#define AUDIT_CWD 1307 /* Current working directory */ 85#define AUDIT_CWD 1307 /* Current working directory */
86#define AUDIT_EXECVE 1309 /* execve arguments */ 86#define AUDIT_EXECVE 1309 /* execve arguments */
87#define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */ 87#define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */
88#define AUDIT_MQ_OPEN 1312 /* POSIX MQ open record type */
89#define AUDIT_MQ_SENDRECV 1313 /* POSIX MQ send/receive record type */
90#define AUDIT_MQ_NOTIFY 1314 /* POSIX MQ notify record type */
91#define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */
88 92
89#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ 93#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
90#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ 94#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -287,6 +291,8 @@ struct audit_context;
287struct inode; 291struct inode;
288struct netlink_skb_parms; 292struct netlink_skb_parms;
289struct linux_binprm; 293struct linux_binprm;
294struct mq_attr;
295struct mqstat;
290 296
291#define AUDITSC_INVALID 0 297#define AUDITSC_INVALID 0
292#define AUDITSC_SUCCESS 1 298#define AUDITSC_SUCCESS 1
@@ -336,6 +342,11 @@ extern int audit_socketcall(int nargs, unsigned long *args);
336extern int audit_sockaddr(int len, void *addr); 342extern int audit_sockaddr(int len, void *addr);
337extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); 343extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
338extern int audit_set_macxattr(const char *name); 344extern int audit_set_macxattr(const char *name);
345extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
346extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout);
347extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
348extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification);
349extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
339 350
340static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp) 351static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
341{ 352{
@@ -349,6 +360,36 @@ static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid,
349 return __audit_ipc_set_perm(qbytes, uid, gid, mode); 360 return __audit_ipc_set_perm(qbytes, uid, gid, mode);
350 return 0; 361 return 0;
351} 362}
363static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
364{
365 if (unlikely(current->audit_context))
366 return __audit_mq_open(oflag, mode, u_attr);
367 return 0;
368}
369static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
370{
371 if (unlikely(current->audit_context))
372 return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
373 return 0;
374}
375static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
376{
377 if (unlikely(current->audit_context))
378 return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
379 return 0;
380}
381static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
382{
383 if (unlikely(current->audit_context))
384 return __audit_mq_notify(mqdes, u_notification);
385 return 0;
386}
387static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
388{
389 if (unlikely(current->audit_context))
390 return __audit_mq_getsetattr(mqdes, mqstat);
391 return 0;
392}
352#else 393#else
353#define audit_alloc(t) ({ 0; }) 394#define audit_alloc(t) ({ 0; })
354#define audit_free(t) do { ; } while (0) 395#define audit_free(t) do { ; } while (0)
@@ -369,6 +410,11 @@ static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid,
369#define audit_sockaddr(len, addr) ({ 0; }) 410#define audit_sockaddr(len, addr) ({ 0; })
370#define audit_avc_path(dentry, mnt) ({ 0; }) 411#define audit_avc_path(dentry, mnt) ({ 0; })
371#define audit_set_macxattr(n) do { ; } while (0) 412#define audit_set_macxattr(n) do { ; } while (0)
413#define audit_mq_open(o,m,a) ({ 0; })
414#define audit_mq_timedsend(d,l,p,t) ({ 0; })
415#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
416#define audit_mq_notify(d,n) ({ 0; })
417#define audit_mq_getsetattr(d,s) ({ 0; })
372#endif 418#endif
373 419
374#ifdef CONFIG_AUDIT 420#ifdef CONFIG_AUDIT
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 41ecbd440fed..1511714a9585 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -8,6 +8,8 @@
8 * Lockless receive & send, fd based notify: 8 * Lockless receive & send, fd based notify:
9 * Manfred Spraul (manfred@colorfullife.com) 9 * Manfred Spraul (manfred@colorfullife.com)
10 * 10 *
11 * Audit: George Wilson (ltcgcw@us.ibm.com)
12 *
11 * This file is released under the GPL. 13 * This file is released under the GPL.
12 */ 14 */
13 15
@@ -24,6 +26,7 @@
24#include <linux/skbuff.h> 26#include <linux/skbuff.h>
25#include <linux/netlink.h> 27#include <linux/netlink.h>
26#include <linux/syscalls.h> 28#include <linux/syscalls.h>
29#include <linux/audit.h>
27#include <linux/signal.h> 30#include <linux/signal.h>
28#include <linux/mutex.h> 31#include <linux/mutex.h>
29 32
@@ -657,6 +660,10 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
657 char *name; 660 char *name;
658 int fd, error; 661 int fd, error;
659 662
663 error = audit_mq_open(oflag, mode, u_attr);
664 if (error != 0)
665 return error;
666
660 if (IS_ERR(name = getname(u_name))) 667 if (IS_ERR(name = getname(u_name)))
661 return PTR_ERR(name); 668 return PTR_ERR(name);
662 669
@@ -814,6 +821,10 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
814 long timeout; 821 long timeout;
815 int ret; 822 int ret;
816 823
824 ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
825 if (ret != 0)
826 return ret;
827
817 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) 828 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
818 return -EINVAL; 829 return -EINVAL;
819 830
@@ -896,6 +907,10 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
896 struct mqueue_inode_info *info; 907 struct mqueue_inode_info *info;
897 struct ext_wait_queue wait; 908 struct ext_wait_queue wait;
898 909
910 ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
911 if (ret != 0)
912 return ret;
913
899 timeout = prepare_timeout(u_abs_timeout); 914 timeout = prepare_timeout(u_abs_timeout);
900 915
901 ret = -EBADF; 916 ret = -EBADF;
@@ -975,6 +990,10 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
975 struct mqueue_inode_info *info; 990 struct mqueue_inode_info *info;
976 struct sk_buff *nc; 991 struct sk_buff *nc;
977 992
993 ret = audit_mq_notify(mqdes, u_notification);
994 if (ret != 0)
995 return ret;
996
978 nc = NULL; 997 nc = NULL;
979 sock = NULL; 998 sock = NULL;
980 if (u_notification != NULL) { 999 if (u_notification != NULL) {
@@ -1115,6 +1134,9 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
1115 omqstat = info->attr; 1134 omqstat = info->attr;
1116 omqstat.mq_flags = filp->f_flags & O_NONBLOCK; 1135 omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
1117 if (u_mqstat) { 1136 if (u_mqstat) {
1137 ret = audit_mq_getsetattr(mqdes, &mqstat);
1138 if (ret != 0)
1139 goto out;
1118 if (mqstat.mq_flags & O_NONBLOCK) 1140 if (mqstat.mq_flags & O_NONBLOCK)
1119 filp->f_flags |= O_NONBLOCK; 1141 filp->f_flags |= O_NONBLOCK;
1120 else 1142 else
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 4503c4663cf8..14e295a4121b 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 4 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
5 * Copyright 2005 Hewlett-Packard Development Company, L.P. 5 * Copyright 2005 Hewlett-Packard Development Company, L.P.
6 * Copyright (C) 2005 IBM Corporation 6 * Copyright (C) 2005, 2006 IBM Corporation
7 * All Rights Reserved. 7 * All Rights Reserved.
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,9 @@
29 * this file -- see entry.S) is based on a GPL'd patch written by 29 * this file -- see entry.S) is based on a GPL'd patch written by
30 * okir@suse.de and Copyright 2003 SuSE Linux AG. 30 * okir@suse.de and Copyright 2003 SuSE Linux AG.
31 * 31 *
32 * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
33 * 2006.
34 *
32 * The support of additional filter rules compares (>, <, >=, <=) was 35 * The support of additional filter rules compares (>, <, >=, <=) was
33 * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005. 36 * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
34 * 37 *
@@ -49,6 +52,7 @@
49#include <linux/module.h> 52#include <linux/module.h>
50#include <linux/mount.h> 53#include <linux/mount.h>
51#include <linux/socket.h> 54#include <linux/socket.h>
55#include <linux/mqueue.h>
52#include <linux/audit.h> 56#include <linux/audit.h>
53#include <linux/personality.h> 57#include <linux/personality.h>
54#include <linux/time.h> 58#include <linux/time.h>
@@ -102,6 +106,33 @@ struct audit_aux_data {
102 106
103#define AUDIT_AUX_IPCPERM 0 107#define AUDIT_AUX_IPCPERM 0
104 108
109struct audit_aux_data_mq_open {
110 struct audit_aux_data d;
111 int oflag;
112 mode_t mode;
113 struct mq_attr attr;
114};
115
116struct audit_aux_data_mq_sendrecv {
117 struct audit_aux_data d;
118 mqd_t mqdes;
119 size_t msg_len;
120 unsigned int msg_prio;
121 struct timespec abs_timeout;
122};
123
124struct audit_aux_data_mq_notify {
125 struct audit_aux_data d;
126 mqd_t mqdes;
127 struct sigevent notification;
128};
129
130struct audit_aux_data_mq_getsetattr {
131 struct audit_aux_data d;
132 mqd_t mqdes;
133 struct mq_attr mqstat;
134};
135
105struct audit_aux_data_ipcctl { 136struct audit_aux_data_ipcctl {
106 struct audit_aux_data d; 137 struct audit_aux_data d;
107 struct ipc_perm p; 138 struct ipc_perm p;
@@ -644,6 +675,43 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
644 continue; /* audit_panic has been called */ 675 continue; /* audit_panic has been called */
645 676
646 switch (aux->type) { 677 switch (aux->type) {
678 case AUDIT_MQ_OPEN: {
679 struct audit_aux_data_mq_open *axi = (void *)aux;
680 audit_log_format(ab,
681 "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld "
682 "mq_msgsize=%ld mq_curmsgs=%ld",
683 axi->oflag, axi->mode, axi->attr.mq_flags,
684 axi->attr.mq_maxmsg, axi->attr.mq_msgsize,
685 axi->attr.mq_curmsgs);
686 break; }
687
688 case AUDIT_MQ_SENDRECV: {
689 struct audit_aux_data_mq_sendrecv *axi = (void *)aux;
690 audit_log_format(ab,
691 "mqdes=%d msg_len=%zd msg_prio=%u "
692 "abs_timeout_sec=%ld abs_timeout_nsec=%ld",
693 axi->mqdes, axi->msg_len, axi->msg_prio,
694 axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec);
695 break; }
696
697 case AUDIT_MQ_NOTIFY: {
698 struct audit_aux_data_mq_notify *axi = (void *)aux;
699 audit_log_format(ab,
700 "mqdes=%d sigev_signo=%d",
701 axi->mqdes,
702 axi->notification.sigev_signo);
703 break; }
704
705 case AUDIT_MQ_GETSETATTR: {
706 struct audit_aux_data_mq_getsetattr *axi = (void *)aux;
707 audit_log_format(ab,
708 "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
709 "mq_curmsgs=%ld ",
710 axi->mqdes,
711 axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg,
712 axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs);
713 break; }
714
647 case AUDIT_IPC: { 715 case AUDIT_IPC: {
648 struct audit_aux_data_ipcctl *axi = (void *)aux; 716 struct audit_aux_data_ipcctl *axi = (void *)aux;
649 audit_log_format(ab, 717 audit_log_format(ab,
@@ -1183,6 +1251,210 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
1183} 1251}
1184 1252
1185/** 1253/**
1254 * __audit_mq_open - record audit data for a POSIX MQ open
1255 * @oflag: open flag
1256 * @mode: mode bits
1257 * @u_attr: queue attributes
1258 *
1259 * Returns 0 for success or NULL context or < 0 on error.
1260 */
1261int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
1262{
1263 struct audit_aux_data_mq_open *ax;
1264 struct audit_context *context = current->audit_context;
1265
1266 if (!audit_enabled)
1267 return 0;
1268
1269 if (likely(!context))
1270 return 0;
1271
1272 ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
1273 if (!ax)
1274 return -ENOMEM;
1275
1276 if (u_attr != NULL) {
1277 if (copy_from_user(&ax->attr, u_attr, sizeof(ax->attr))) {
1278 kfree(ax);
1279 return -EFAULT;
1280 }
1281 } else
1282 memset(&ax->attr, 0, sizeof(ax->attr));
1283
1284 ax->oflag = oflag;
1285 ax->mode = mode;
1286
1287 ax->d.type = AUDIT_MQ_OPEN;
1288 ax->d.next = context->aux;
1289 context->aux = (void *)ax;
1290 return 0;
1291}
1292
1293/**
1294 * __audit_mq_timedsend - record audit data for a POSIX MQ timed send
1295 * @mqdes: MQ descriptor
1296 * @msg_len: Message length
1297 * @msg_prio: Message priority
1298 * @abs_timeout: Message timeout in absolute time
1299 *
1300 * Returns 0 for success or NULL context or < 0 on error.
1301 */
1302int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
1303 const struct timespec __user *u_abs_timeout)
1304{
1305 struct audit_aux_data_mq_sendrecv *ax;
1306 struct audit_context *context = current->audit_context;
1307
1308 if (!audit_enabled)
1309 return 0;
1310
1311 if (likely(!context))
1312 return 0;
1313
1314 ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
1315 if (!ax)
1316 return -ENOMEM;
1317
1318 if (u_abs_timeout != NULL) {
1319 if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
1320 kfree(ax);
1321 return -EFAULT;
1322 }
1323 } else
1324 memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
1325
1326 ax->mqdes = mqdes;
1327 ax->msg_len = msg_len;
1328 ax->msg_prio = msg_prio;
1329
1330 ax->d.type = AUDIT_MQ_SENDRECV;
1331 ax->d.next = context->aux;
1332 context->aux = (void *)ax;
1333 return 0;
1334}
1335
1336/**
1337 * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive
1338 * @mqdes: MQ descriptor
1339 * @msg_len: Message length
1340 * @msg_prio: Message priority
1341 * @abs_timeout: Message timeout in absolute time
1342 *
1343 * Returns 0 for success or NULL context or < 0 on error.
1344 */
1345int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len,
1346 unsigned int __user *u_msg_prio,
1347 const struct timespec __user *u_abs_timeout)
1348{
1349 struct audit_aux_data_mq_sendrecv *ax;
1350 struct audit_context *context = current->audit_context;
1351
1352 if (!audit_enabled)
1353 return 0;
1354
1355 if (likely(!context))
1356 return 0;
1357
1358 ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
1359 if (!ax)
1360 return -ENOMEM;
1361
1362 if (u_msg_prio != NULL) {
1363 if (get_user(ax->msg_prio, u_msg_prio)) {
1364 kfree(ax);
1365 return -EFAULT;
1366 }
1367 } else
1368 ax->msg_prio = 0;
1369
1370 if (u_abs_timeout != NULL) {
1371 if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
1372 kfree(ax);
1373 return -EFAULT;
1374 }
1375 } else
1376 memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
1377
1378 ax->mqdes = mqdes;
1379 ax->msg_len = msg_len;
1380
1381 ax->d.type = AUDIT_MQ_SENDRECV;
1382 ax->d.next = context->aux;
1383 context->aux = (void *)ax;
1384 return 0;
1385}
1386
1387/**
1388 * __audit_mq_notify - record audit data for a POSIX MQ notify
1389 * @mqdes: MQ descriptor
1390 * @u_notification: Notification event
1391 *
1392 * Returns 0 for success or NULL context or < 0 on error.
1393 */
1394
1395int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
1396{
1397 struct audit_aux_data_mq_notify *ax;
1398 struct audit_context *context = current->audit_context;
1399
1400 if (!audit_enabled)
1401 return 0;
1402
1403 if (likely(!context))
1404 return 0;
1405
1406 ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
1407 if (!ax)
1408 return -ENOMEM;
1409
1410 if (u_notification != NULL) {
1411 if (copy_from_user(&ax->notification, u_notification, sizeof(ax->notification))) {
1412 kfree(ax);
1413 return -EFAULT;
1414 }
1415 } else
1416 memset(&ax->notification, 0, sizeof(ax->notification));
1417
1418 ax->mqdes = mqdes;
1419
1420 ax->d.type = AUDIT_MQ_NOTIFY;
1421 ax->d.next = context->aux;
1422 context->aux = (void *)ax;
1423 return 0;
1424}
1425
1426/**
1427 * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
1428 * @mqdes: MQ descriptor
1429 * @mqstat: MQ flags
1430 *
1431 * Returns 0 for success or NULL context or < 0 on error.
1432 */
1433int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
1434{
1435 struct audit_aux_data_mq_getsetattr *ax;
1436 struct audit_context *context = current->audit_context;
1437
1438 if (!audit_enabled)
1439 return 0;
1440
1441 if (likely(!context))
1442 return 0;
1443
1444 ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
1445 if (!ax)
1446 return -ENOMEM;
1447
1448 ax->mqdes = mqdes;
1449 ax->mqstat = *mqstat;
1450
1451 ax->d.type = AUDIT_MQ_GETSETATTR;
1452 ax->d.next = context->aux;
1453 context->aux = (void *)ax;
1454 return 0;
1455}
1456
1457/**
1186 * audit_ipc_obj - record audit data for ipc object 1458 * audit_ipc_obj - record audit data for ipc object
1187 * @ipcp: ipc permissions 1459 * @ipcp: ipc permissions
1188 * 1460 *