Freeing multiple contexts message
by Steve Grubb
Hi,
I think we need to change the message in audit_free_context(). It currently
says:
"audit(:%d): major=%d name_count=%d: freeing multiple contexts (%d)\n"
This does not really indicate to the casual user that they've encountered a
bug that needs to be reported. Is there a common method to flag kernel bugs
that gets a user's attention? BUG_ON? WARN_ON?
Also, does this message contain enough information for troubleshooting if
someone reports it? Should it contain the syscall number, task name, or is
anything else needed?
-Steve
19 years, 1 month
[PATCH] LSPP audit enablement: storing selinux ocontext and scontext
by Dustin Kirkland
The attached patch contains functionality specified by the labeled
security protection profile--basically appending object context and
subject context labels to audit records.
This code was originally written by Dan Jones against a 2.6.9 kernel
tree. I have ported it forward to the 2.6.13-rc3-mm1 tree and tested
it.
I expect at least one section of this code to generate some animated
discussion. This code utilizes "static inline" function definitions
rather than "#define" macros, as per Documentation/SubmittingPatches
lines 328-372 and Documentation/CodingStyle line 358. This is
inconsistent with the rest of the code in include/linux/audit.h, so I
suspect someone will have to give, in the interest of consistency.
Please advise.
Additionally, we've arbitrarily defined AUDIT_SECURITY_CONTEXT = 1350.
We expect this to change to whatever the appropriate value might be.
Signed-off-by: Dustin Kirkland <dustin.kirkland(a)us.ibm.com>
diff -uprN linux-2.6.13-rc3-mm1/include/linux/audit.h
linux-2.6.13-rc3-mm1-lspp_audit/include/linux/audit.h
--- linux-2.6.13-rc3-mm1/include/linux/audit.h 2005-07-18 15:20:34.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/include/linux/audit.h 2005-07-19 11:33:37.000000000 -0500
@@ -68,6 +68,7 @@
#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */
#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */
#define AUDIT_CWD 1307 /* Current working directory */
+#define AUDIT_SECURITY_CONTEXT 1350 /* security context */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -238,6 +239,8 @@ extern int audit_sockaddr(int len, void
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
extern void audit_signal_info(int sig, struct task_struct *t);
extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+extern int audit_ipc_security_context(struct kern_ipc_perm *ipcp);
+extern int audit_set_macxattr(const char *name);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -255,6 +258,14 @@ extern int audit_filter_user(struct netl
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_signal_info(s,t) do { ; } while (0)
#define audit_filter_user(cb,t) ({ 1; })
+static inline int audit_ipc_security_context(struct kern_ipc_perm *ipcp)
+{
+ return 0;
+}
+static inline int audit_set_macxattr(const char *name)
+{
+ return 0;
+}
#endif
#ifdef CONFIG_AUDIT
@@ -283,6 +294,7 @@ extern void audit_send_reply(int pi
int done, int multi,
void *payload, int size);
extern void audit_log_lost(const char *message);
+extern void audit_panic(const char *message);
extern struct semaphore audit_netlink_sem;
#else
#define audit_log(c,g,t,f,...) do { ; } while (0)
@@ -293,6 +305,10 @@ extern struct semaphore audit_netlink_se
#define audit_log_hex(a,b,l) do { ; } while (0)
#define audit_log_untrustedstring(a,s) do { ; } while (0)
#define audit_log_d_path(b,p,d,v) do { ; } while (0)
+static inline void audit_panic(const char *message)
+{
+ return;
+}
#endif
#endif
#endif
diff -uprN linux-2.6.13-rc3-mm1/include/linux/security.h linux-2.6.13-rc3-mm1-lspp_audit/include/linux/security.h
--- linux-2.6.13-rc3-mm1/include/linux/security.h 2005-07-18 15:20:35.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/include/linux/security.h 2005-07-18 16:35:02.000000000 -0500
@@ -792,6 +792,11 @@ struct swap_info_struct;
* @ipcp contains the kernel IPC permission structure
* @flag contains the desired (requested) permission set
* Return 0 if permission is granted.
+ * @ipc_getsecurity:
+ * Copy the security label associated with the ipc object into
+ * @buffer. @buffer may be NULL to request the size of the buffer
+ * required. @size indicates the size of @buffer in bytes. Return
+ * number of bytes used/required on success.
*
* Security hooks for individual messages held in System V IPC message queues
* @msg_msg_alloc_security:
@@ -1140,6 +1145,7 @@ struct security_operations {
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
+ int (*ipc_getsecurity)(struct kern_ipc_perm *ipcp, void *buffer, size_t size);
int (*msg_msg_alloc_security) (struct msg_msg * msg);
void (*msg_msg_free_security) (struct msg_msg * msg);
@@ -1775,6 +1781,11 @@ static inline int security_ipc_permissio
return security_ops->ipc_permission (ipcp, flag);
}
+static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ return security_ops->ipc_getsecurity(ipcp, buffer, size);
+}
+
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return security_ops->msg_msg_alloc_security (msg);
@@ -2405,6 +2416,11 @@ static inline int security_ipc_permissio
return 0;
}
+static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return 0;
diff -uprN linux-2.6.13-rc3-mm1/ipc/msg.c linux-2.6.13-rc3-mm1-lspp_audit/ipc/msg.c
--- linux-2.6.13-rc3-mm1/ipc/msg.c 2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/ipc/msg.c 2005-07-18 16:35:02.000000000 -0500
@@ -441,6 +441,13 @@ asmlinkage long sys_msgctl (int msqid, i
if (msq == NULL)
goto out_up;
+ ipcp = &msq->q_perm;
+
+ if (cmd == IPC_SET) {
+ if ((err = audit_ipc_security_context(ipcp)))
+ goto out_unlock_up;
+ }
+
err = -EIDRM;
if (msg_checkid(msq,msqid))
goto out_unlock_up;
diff -uprN linux-2.6.13-rc3-mm1/ipc/sem.c linux-2.6.13-rc3-mm1-lspp_audit/ipc/sem.c
--- linux-2.6.13-rc3-mm1/ipc/sem.c 2005-07-18 15:20:05.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/ipc/sem.c 2005-07-18 16:35:02.000000000 -0500
@@ -811,12 +811,18 @@ static int semctl_down(int semid, int se
if(sma==NULL)
return -EINVAL;
+ ipcp = &sma->sem_perm;
+
+ if(cmd == IPC_SET) {
+ if ((err = audit_ipc_security_context(ipcp)))
+ goto out_unlock;
+ }
+
if (sem_checkid(sma,semid)) {
err=-EIDRM;
goto out_unlock;
}
- ipcp = &sma->sem_perm;
-
+
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
err=-EPERM;
diff -uprN linux-2.6.13-rc3-mm1/ipc/shm.c linux-2.6.13-rc3-mm1-lspp_audit/ipc/shm.c
--- linux-2.6.13-rc3-mm1/ipc/shm.c 2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/ipc/shm.c 2005-07-18 16:35:02.000000000 -0500
@@ -610,6 +610,9 @@ asmlinkage long sys_shmctl (int shmid, i
err=-EINVAL;
if(shp==NULL)
goto out_up;
+ err = audit_ipc_security_context(&(shp->shm_perm));
+ if(err)
+ goto out_unlock_up;
err = shm_checkid(shp,shmid);
if(err)
goto out_unlock_up;
diff -uprN linux-2.6.13-rc3-mm1/ipc/util.c linux-2.6.13-rc3-mm1-lspp_audit/ipc/util.c
--- linux-2.6.13-rc3-mm1/ipc/util.c 2005-06-17 14:48:29.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/ipc/util.c 2005-07-18 16:35:02.000000000 -0500
@@ -24,6 +24,7 @@
#include <linux/security.h>
#include <linux/rcupdate.h>
#include <linux/workqueue.h>
+#include <linux/audit.h>
#include <asm/unistd.h>
@@ -420,6 +421,8 @@ int ipcperms (struct kern_ipc_perm *ipcp
{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
int requested_mode, granted_mode;
+ audit_ipc_security_context(ipcp);
+
requested_mode = (flag >> 6) | (flag >> 3) | flag;
granted_mode = ipcp->mode;
if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
diff -uprN linux-2.6.13-rc3-mm1/kernel/audit.c linux-2.6.13-rc3-mm1-lspp_audit/kernel/audit.c
--- linux-2.6.13-rc3-mm1/kernel/audit.c 2005-07-18 15:20:35.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/kernel/audit.c 2005-07-18 16:35:02.000000000 -0500
@@ -147,7 +147,7 @@ struct audit_entry {
struct audit_rule rule;
};
-static void audit_panic(const char *message)
+void audit_panic(const char *message)
{
switch (audit_failure)
{
@@ -896,3 +896,4 @@ void audit_log(struct audit_context *ctx
audit_log_end(ab);
}
}
+
diff -uprN linux-2.6.13-rc3-mm1/kernel/auditsc.c linux-2.6.13-rc3-mm1-lspp_audit/kernel/auditsc.c
--- linux-2.6.13-rc3-mm1/kernel/auditsc.c 2005-07-18 15:20:35.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/kernel/auditsc.c 2005-07-19 11:50:15.000000000 -0500
@@ -43,6 +43,7 @@
#include <linux/netlink.h>
#include <linux/compiler.h>
#include <asm/unistd.h>
+#include <linux/security.h>
/* 0 = no checking
1 = put_count checking
@@ -99,6 +100,7 @@ struct audit_names {
gid_t gid;
dev_t rdev;
unsigned flags;
+ char *security_context;
};
struct audit_aux_data {
@@ -108,6 +110,12 @@ struct audit_aux_data {
#define AUDIT_AUX_IPCPERM 0
+struct audit_aux_data_security_context {
+ struct audit_aux_data d;
+ char *security_context;
+ size_t security_context_len;
+};
+
struct audit_aux_data_ipcctl {
struct audit_aux_data d;
struct ipc_perm p;
@@ -167,6 +175,8 @@ struct audit_context {
#endif
};
+static const char *audit_macxattr;
+
/* Public API */
/* There are three lists of rules -- one to search at task creation
* time, one to search at syscall entry time, and another to search at
@@ -650,9 +660,11 @@ static inline void audit_free_names(stru
context->ino_count = 0;
#endif
- for (i = 0; i < context->name_count; i++)
+ for (i = 0; i < context->name_count; i++) {
if (context->names[i].name)
__putname(context->names[i].name);
+ kfree(context->names[i].security_context);
+ }
context->name_count = 0;
if (context->pwd)
dput(context->pwd);
@@ -751,6 +763,37 @@ static inline void audit_free_context(st
printk(KERN_ERR "audit: freed %d contexts\n", count);
}
+static void audit_log_task_security_context(struct audit_buffer *ab)
+{
+ char *security_context;
+ ssize_t len = 0;
+
+ len = security_getprocattr(current, "current", NULL, 0);
+ if (len < 0) {
+ if (len != -EINVAL)
+ audit_panic("security_getprocattr error in audit_log_task_security_context");
+ return;
+ }
+
+ security_context = kmalloc(len, GFP_KERNEL);
+ if (!security_context) {
+ audit_panic("memory allocation error in audit_log_task_security_context");
+ return;
+ }
+
+ len = security_getprocattr(current, "current", security_context, len);
+ if (len < 0 ) {
+ audit_panic("security_getprocattr error in audit_log_task_security_context");
+ goto out;
+ }
+
+ audit_log_format(ab, " scontext=%s", security_context);
+
+out:
+ kfree(security_context);
+ return;
+}
+
static void audit_log_task_info(struct audit_buffer *ab)
{
char name[sizeof(current->comm)];
@@ -777,6 +820,7 @@ static void audit_log_task_info(struct a
vma = vma->vm_next;
}
up_read(&mm->mmap_sem);
+ audit_log_task_security_context(ab);
}
static void audit_log_exit(struct audit_context *context, unsigned int gfp_mask)
@@ -848,6 +892,11 @@ static void audit_log_exit(struct audit_
struct audit_aux_data_path *axi = (void *)aux;
audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
break; }
+ case AUDIT_SECURITY_CONTEXT: {
+ struct audit_aux_data_security_context *axi = (void *)aux;
+ audit_log_format(ab, " ocontext=%s", axi->security_context);
+ kfree(axi->security_context);
+ break; }
}
audit_log_end(ab);
@@ -883,6 +932,10 @@ static void audit_log_exit(struct audit_
context->names[i].gid,
MAJOR(context->names[i].rdev),
MINOR(context->names[i].rdev));
+ if (context->names[i].security_context) {
+ audit_log_format(ab, " ocontext=%s",
+ context->names[i].security_context);
+ }
audit_log_end(ab);
}
}
@@ -1098,6 +1151,37 @@ void audit_putname(const char *name)
#endif
}
+void audit_inode_security_context(int idx, const struct inode *inode)
+{
+ struct audit_context *context = current->audit_context;
+ int len = 0;
+
+ if (!audit_macxattr)
+ return;
+
+ len = security_inode_getsecurity((struct inode *)inode, audit_macxattr, NULL, 0);
+ if (len < 0) {
+ if (len != -EOPNOTSUPP)
+ audit_panic("security_inode_getsecurity error in audit_inode_security_context");
+ return;
+ }
+
+ context->names[idx].security_context = kmalloc(len, GFP_KERNEL);
+ if (!(context->names[idx].security_context)) {
+ audit_panic("memory allocation error in audit_inode_security_context");
+ return;
+ }
+
+ len = security_inode_getsecurity((struct inode *)inode, audit_macxattr,
+ context->names[idx].security_context, len);
+ if (len < 0) {
+ kfree(context->names[idx].security_context);
+ audit_panic("security_inode_getsecurity error in audit_inode_security_context");
+ }
+
+ return;
+}
+
/* Store the inode and device from a lookup. Called from
* fs/namei.c:path_lookup(). */
void audit_inode(const char *name, const struct inode *inode, unsigned flags)
@@ -1133,6 +1217,8 @@ void audit_inode(const char *name, const
context->names[idx].uid = inode->i_uid;
context->names[idx].gid = inode->i_gid;
context->names[idx].rdev = inode->i_rdev;
+
+ audit_inode_security_context(idx, inode);
}
void auditsc_get_stamp(struct audit_context *ctx,
@@ -1270,3 +1356,63 @@ void audit_signal_info(int sig, struct t
}
}
+int audit_ipc_security_context(struct kern_ipc_perm *ipcp)
+{
+ struct audit_aux_data_security_context *ax;
+ struct audit_context *context = current->audit_context;
+ int len = 0;
+
+ if (likely(!context))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+ if (!ax) {
+ audit_panic("memory allocation error in audit_ipc_security_context");
+ return -ENOMEM;
+ }
+
+ len = security_ipc_getsecurity(ipcp, NULL, 0);
+ if (len < 0) {
+ if (len != -EOPNOTSUPP)
+ audit_panic("security_ipc_getsecurity error in audit_ipc_security_context");
+ return len;
+ }
+
+ ax->security_context = kmalloc(len, GFP_ATOMIC);
+ if (!ax->security_context) {
+ audit_panic("memory allocation error in audit_ipc_security_context");
+ kfree(ax);
+ return -ENOMEM;
+ }
+
+ len = security_ipc_getsecurity(ipcp, ax->security_context, len);
+ if (len < 0) {
+ audit_panic("security_ipc_getsecurity error in audit_ipc_security_context");
+ kfree(ax->security_context);
+ kfree(ax);
+ return len;
+ }
+
+ ax->security_context_len = len;
+
+ ax->d.type = AUDIT_SECURITY_CONTEXT;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
+}
+
+/* Set the security XATTR name. This is needed for audit functions
+ * to obtain the security context of file system objects. */
+int audit_set_macxattr(const char *name)
+{
+ size_t len = strlen(name)+1;
+
+ if (audit_macxattr)
+ return -EINVAL;
+
+ audit_macxattr = kmalloc(len, GFP_KERNEL);
+ if (!audit_macxattr)
+ return -ENOMEM;
+ memcpy((void *)audit_macxattr, (const void *)name, len);
+ return 0;
+}
diff -uprN linux-2.6.13-rc3-mm1/security/dummy.c linux-2.6.13-rc3-mm1-lspp_audit/security/dummy.c
--- linux-2.6.13-rc3-mm1/security/dummy.c 2005-07-18 15:20:36.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/security/dummy.c 2005-07-18 16:35:02.000000000 -0500
@@ -557,6 +557,11 @@ static int dummy_ipc_permission (struct
return 0;
}
+static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ return -EOPNOTSUPP;
+}
+
static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
{
return 0;
@@ -907,6 +912,7 @@ void security_fixup_ops (struct security
set_to_dummy_if_null(ops, task_reparent_to_init);
set_to_dummy_if_null(ops, task_to_inode);
set_to_dummy_if_null(ops, ipc_permission);
+ set_to_dummy_if_null(ops, ipc_getsecurity);
set_to_dummy_if_null(ops, msg_msg_alloc_security);
set_to_dummy_if_null(ops, msg_msg_free_security);
set_to_dummy_if_null(ops, msg_queue_alloc_security);
diff -uprN linux-2.6.13-rc3-mm1/security/selinux/hooks.c linux-2.6.13-rc3-mm1-lspp_audit/security/selinux/hooks.c
--- linux-2.6.13-rc3-mm1/security/selinux/hooks.c 2005-07-18 15:20:36.000000000 -0500
+++ linux-2.6.13-rc3-mm1-lspp_audit/security/selinux/hooks.c 2005-07-19 10:56:44.000000000 -0500
@@ -116,6 +116,35 @@ static struct security_operations *secon
static LIST_HEAD(superblock_security_head);
static DEFINE_SPINLOCK(sb_security_lock);
+/* Return security context for a given sid or just the context
+ length if the buffer is null or length is 0 */
+static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
+{
+ char *context;
+ unsigned len;
+ int rc;
+
+ if (buffer && !size)
+ return -ERANGE;
+
+ rc = security_sid_to_context(sid, &context, &len);
+ if (rc)
+ return rc;
+
+ if (!buffer || !size)
+ goto getsecurity_exit;
+
+ if (size < len) {
+ kfree(context);
+ return -ERANGE;
+ }
+ memcpy(buffer, context, len);
+
+getsecurity_exit:
+ kfree(context);
+ return len;
+}
+
/* Allocate and free functions for each kind of security blob. */
static int task_alloc_security(struct task_struct *task)
@@ -2232,30 +2261,13 @@ static int selinux_inode_removexattr (st
static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
{
struct inode_security_struct *isec = inode->i_security;
- char *context;
- unsigned len;
- int rc;
/* Permission check handled by selinux_inode_getxattr hook.*/
if (strcmp(name, XATTR_SELINUX_SUFFIX))
return -EOPNOTSUPP;
- rc = security_sid_to_context(isec->sid, &context, &len);
- if (rc)
- return rc;
-
- if (!buffer || !size) {
- kfree(context);
- return len;
- }
- if (size < len) {
- kfree(context);
- return -ERANGE;
- }
- memcpy(buffer, context, len);
- kfree(context);
- return len;
+ return(selinux_getsecurity(isec->sid, buffer, size));
}
static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -3360,6 +3372,13 @@ out:
return err;
}
+static int selinux_socket_getsecurity(struct socket *sock, void *buffer, size_t size)
+{
+ struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
+
+ return(selinux_getsecurity(isec->sid, buffer, size));
+}
+
static int selinux_sk_alloc_security(struct sock *sk, int family, int priority)
{
return sk_alloc_security(sk, family, priority);
@@ -4025,6 +4044,13 @@ static int selinux_ipc_permission(struct
return ipc_has_perm(ipcp, av);
}
+static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
+{
+ struct ipc_security_struct *isec = ipcp->security;
+
+ return(selinux_getsecurity(isec->sid, buffer, size));
+}
+
/* module stacking operations */
static int selinux_register_security (const char *name, struct security_operations *ops)
{
@@ -4066,8 +4092,7 @@ static int selinux_getprocattr(struct ta
char *name, void *value, size_t size)
{
struct task_security_struct *tsec;
- u32 sid, len;
- char *context;
+ u32 sid;
int error;
if (current != p) {
@@ -4076,9 +4101,6 @@ static int selinux_getprocattr(struct ta
return error;
}
- if (!size)
- return -ERANGE;
-
tsec = p->security;
if (!strcmp(name, "current"))
@@ -4095,16 +4117,7 @@ static int selinux_getprocattr(struct ta
if (!sid)
return 0;
- error = security_sid_to_context(sid, &context, &len);
- if (error)
- return error;
- if (len > size) {
- kfree(context);
- return -ERANGE;
- }
- memcpy(value, context, len);
- kfree(context);
- return len;
+ return(selinux_getsecurity(sid, value, size));
}
static int selinux_setprocattr(struct task_struct *p,
@@ -4299,6 +4312,7 @@ static struct security_operations selinu
.task_to_inode = selinux_task_to_inode,
.ipc_permission = selinux_ipc_permission,
+ .ipc_getsecurity = selinux_ipc_getsecurity,
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
.msg_msg_free_security = selinux_msg_msg_free_security,
@@ -4379,6 +4393,10 @@ static __init int selinux_init(void)
if (register_security (&selinux_ops))
panic("SELinux: Unable to register with kernel.\n");
+ if (audit_set_macxattr(XATTR_SELINUX_SUFFIX)) {
+ printk(KERN_WARNING "SELinux: Unable to register xattr name with audit.\n");
+ }
+
if (selinux_enforcing) {
printk(KERN_INFO "SELinux: Starting in enforcing mode\n");
} else {
19 years, 1 month
Selective Audit; filtering on message type; integration of operators
by Dustin Kirkland
RBACPP FAU_SEL.1 Selective Audit
The TSF shall be able to include or exclude auditable events from the
set of audited events based on the following attributes:
(a) Object identity, user identity, subject identity, host identity, and
***event type***
I'm currently working on a design for a patch to the audit userspace and
kernel subsystem that provides this functionality. Additionally, I'm
conducting this work in conjunction with trying to provide extended
support for operators (such as > and <), as these would be useful in
this context.
To give credit where due, Steve Grubb and I have discussed a some of
these items in off hand conversations recently. I'm collecting those
thoughts and others here for review.
--
USER_SPACE
From a user-experience perspective, we're trying to enable a user to
exclude messages of a certain type (or ranges of messages of particular
types). If you're unclear what types of messages are currently defined,
see include/linux/audit.h. Given extended support for ranges and
comparative operators, this should be extensible to other audit record
keys, such the user, subject, etc.
I'm suggesting the ability to add new rules via auditctl to a new list,
perhaps called "exclude". The proposed interface would look like:
Exclude messages of a specific type:
auditctl -a exclude,always -F "type=AUDIT_IPC"
Exclude messages within range:
auditctl -a exclude,always -F "type=AUDIT_SYSCALL..AUDIT_CWD"
Exclude messages using auditctl helper terms (ALL_DAEMON interpreted by
auditctl to be a range of 1200-1299 as specified in the audit.h header):
auditctl -a exclude,always -F "type=ALL_DAEMON"
Use multiple rules to exclude audit system command messages:
auditctl -a exclude,always -F "type<1100"
Also, the same form should be usable for other parameters as well, such
as uid, pid, etc.
auditctl -a exclude,always -F "uid<500"
auditctl -a exclude,always -F "pid=464"
I have written the code necessary to create an ordered, compressed list
of ranges of numbers that the kernel could very efficiently filter on.
Given some arbitrary number of ranges (as small as a singularity and as
large as the enumerated space), the code creates a list of upper and
lower bounds, however few are necessary to properly express the list of
ranges. For instance, given the user input ranges:
10-20, 5, 15-25, 23, 50
The algorithm will produce an optimized list:
5,5
10,25
50,50
This is a key, inexpensive operation to perform in user space that is
potentially a valuable gain kernel space. Memory requirements are
minimized, matches are found quickly, and the traversal is aborted as
soon as a range greater than the current value is encountered.
Note that I've also written the code necessary to remove individual
elements or ranges from an existing range, such that given our previous
range: (5, 10-25, 50), one chooses to remove 7, 13, 40-60 would result
in: (5, 10-12, 14-25). This is needed for the user's ability to prune
and modify existing rules.
--
KERNEL_SPACE
The kernel piece of this is pretty straightforward, actually... Near
the very top of audit_log_start(), we basically do something like:
if (unlikely(audit_exclude_type(type)))
return NULL;
Where audit_exclude_type() traverses our list of ranges looking for a
match, returning 1 if is to be excluded, 0 if no matches found.
Remember, this is ordered such that we can end the traversal as soon as
possible.
--
NETLINK
I'm nearly ready to post a patch, but I'm waiting on some consensus on
Steve's previous thread (New operators for rules). As of this posting,
there's no consensus yet on how we go about passing these values to/from
the kernel/userspace.
I'm trying to work within struct audit_rule.
struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
uint32_t flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
uint32_t action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
uint32_t field_count;
uint32_t mask[AUDIT_BITMASK_SIZE];
uint32_t fields[AUDIT_MAX_FIELDS];
uint32_t values[AUDIT_MAX_FIELDS];
};
There have been several propositions so far (utilize upper bits of
flags; utilize matching fields[]/values[] entries; hack in a zero-sized
array). If you have opinions on the conveyance of said operators,
please post to aforementioned thread.
Other comments on the design here proposed?
:-Dustin
19 years, 2 months
New operators for rules
by Steve Grubb
Hello,
Dustin and I were talking about how to represent some new operators for
writing audit rules. I am interested in seeing >, <, and range added at a
minimum. The question came up as to how to fit this into the existing
audit_rule structure. This is what we currently have:
struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
__u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
__u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
__u32 field_count;
__u32 mask[AUDIT_BITMASK_SIZE];
__u32 fields[AUDIT_MAX_FIELDS];
__u32 values[AUDIT_MAX_FIELDS];
};
The fields member currently uses the msb to determine whether its = or !=.
#define AUDIT_NEGATE 0x80000000
I was wondering if we should go ahead and map the other operators into the
other high bits. We are currently only using the lower 4 bits of the u32 word
so we have plenty of room. We have to do this in a way that is backward
compatible for old kernels. Any ideas? Any preferred bit patterns?
Also, we have the issue of needing to send 2 values for a range operator. How
should we make the kernel understand this? Or should we create a new message
type for adding, listing, and deleting rules that we can expand the idea of
operators for and use the current one for legacy compatibility?
Need some ideas from the kernel hackers....
-Steve
19 years, 2 months
API design for library to be used by testcases and ausearch
by Debora Velarde
Some of us at IBM have been discussing the possibility of having an API
which can be used by testcases and tools, such as ausearch, to get
information form the audit subsystem.
I'm attaching our proposal for what the API structures would look like as
well as prototypes for functions that testcases and ausearch would need in
order to get the data they need.
Note the structures are based on the current audit records and will need
to be updated as record types and fields are modified.
Please look them over and send us any feedback.
Thanks,
debbie
The following was designed by Loulwa Salem, Michael Thompson, and myself
with some feedback from Tim Chavez.
19 years, 2 months
Re: New operators for rules
by Dustin Kirkland
On 9/28/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> Need some ideas from the kernel hackers....
Not calling myself a kernel hacker, but I'll throw out a few thoughts.
> struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
> __u32 flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
> __u32 action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
> __u32 field_count;
> __u32 mask[AUDIT_BITMASK_SIZE];
> __u32 fields[AUDIT_MAX_FIELDS];
> __u32 values[AUDIT_MAX_FIELDS];
> };
>
> I was wondering if we should go ahead and map the other operators into the
> other high bits. We are currently only using the lower 4 bits of the u32 word
> so we have plenty of room. We have to do this in a way that is backward
> compatible for old kernels. Any ideas? Any preferred bit patterns?
>
> Also, we have the issue of needing to send 2 values for a range operator. How
> should we make the kernel understand this? Or should we create a new message
> type for adding, listing, and deleting rules that we can expand the idea of
> operators for and use the current one for legacy compatibility?
I think we ought to be able to get decent mileage out of field_count, fields[], and values[].
For the range stuff I've been working on, how about...
field[0] = OPERATOR
field[1] = BOUNDARY
field[2] = BOUNDARY
...
value[0] = AUDIT_RANGE
value[1] = 1300
value[2] = 1399
and
field[0] = AUDIT_OPERATOR
field[1] = AUDIT_BOUNDARY
...
value[0] = AUDIT_LESS_THAN
value[1] = 1500
and
field[0] = AUDIT_OPERATOR
field[1] = AUDIT_BOUNDARY
...
value[0] = AUDIT_GREATER_THAN
value[1] = 1066
Obviously, we create #define's for
AUDIT_[RANGE,OPERATOR,BOUNDARY,LESS_THAN,GREATER_THAN]. I suggest more
magic numbers, as opposed to bitmasks, but that's just me. The
field/value arrays certainly have room for storing the operator in
there. And I think it gives us considerably more room to grow the
operators list (to include perhaps AUDIT_GREATER_THAN_OR_EQUAL, etc).
Thoughts?
:-Dustin
19 years, 2 months
Re: [PATCH] LSPP audit enablement: storing selinux ocontext and scontext
by Dustin Kirkland
On 9/26/05, Steve Grubb <sgrubb(a)redhat.com> wrote:
> On Monday 26 September 2005 15:00, Steve Grubb wrote:
> > Lets use the following audit message number ranges for the next
round of
> > development:
>
> On second thought, maybe better to group the messages between kernel &
> userspace better
>
> 1500 - 1599 kernel LSPP events
> 1700 - 1799 kernel crypto events
> 1800 - 1999 future kernel use (maybe integrity labels and related
events)
> 2001 - 2099 unused (kernel)
> 2100 - 2199 user space anomaly records
> 2200 - 2299 user space actions taken in response to anomalies
> 2300 - 2399 user space generated LSPP events
> 2400 - 2499 user space crypto events
> 2500 - 2999 future user space (maybe integrity labels and related
events)
>
> This would allow us to cover more numbers in a case statement where we
are
> trying to just relay messages through the kernel back to userspace.
What about 1600-1699? Perhaps crypto -> 1600-1699, and save 1700-1999
for future use?
2000+ for user space seems sensible to me.
:-Dustin
19 years, 2 months
splitting up auditctl
by Timothy R. Chavez
Hi,
It was suggested to me that perhaps splitting out auditctl's functionality
logically into separate tools, might be something to consider. For instance,
adding and removing rules could be done by the 'aurule' command, leaving
'auditctl' to handle things like backlog, rate limits, enabling and disabling
of the audit subsystem, etc. I have to admit, I quite like the idea.
I'm not a big fan of all-in-wonder tools and that if we could, we should split
auditctl up before it turns into a menagerie of ideas that are linked simply
by the fact they interact or utilize the audit subsystem in some way, shape,
or form.
-tim
19 years, 2 months
audit 1.0.4 released
by Steve Grubb
Hello,
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit It will also be in rawhide
tomorrow. The Changelog is:
- Make rate & backlog 32 bit unsigned int in auditctl
- In auditctl, if -F arch is given with -t option, don't require list
- Update auditd man page
- Add size check to audit_send
- Update message for audit_open failure when kernel doesn't support audit
This is a bug fix release. The size check added to audit_send is an extra
precaution to make sure nothing bad happens.
Please let me know if there are any problems with this release.
-Steve
19 years, 2 months
auditfs.c
by Timothy R. Chavez
Hi,
kernel/auditfs.c --> fs/audit.c ?
Any other [less] confusing suggestions. Or are people happy with this? To
ease the pain of getting this upstream, eliminating confusion where possible
seems to make sense.
-tim
19 years, 2 months