[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [RFC] linux-2.6.10-auditfs-tc1.patch



Serge Hallyn wrote:
Perhaps we should print out current->cap_effective?  Or is that
overkill?  Or perhaps an actual "security_identify_process(task, buf,
len)" hook would be useful, where commoncap could print out the
capabilities, and selinux could print out the context.  Maybe that's
closer to debug info...


This hook, and a similar security_identify_inode(...), hook will be necessary for an LSM to go through a LSPP evaluation. The label information is required to be included in the audit record for all subjects/objects/information involved in the event. I have a quick-and-dirty patch that implemented this functionality. Note that this patch uses pre-allocated 1K buffers (limits info and sucks up a lot of memory). A proper memory allocation scheme needs to be worked up and the patch probably needs to be rebased to newer code. I planned on getting back to this in the near future. If someone else is working on this functionality, please let me know, otherwise I can bump this up on my TODO list.


This patch also includes uid/gid/mode for filesystem objects. I felt that this was a needed addition to determine the cause of filesystem related denials. Do others agree with this addition to the records, and is there anything else that we could possibly want?

--

Darrel
Index: fs/namei.c
===================================================================
RCS file: /source/cvsroots/fedora-cd/fedora-cd/src/linux-2.6/fs/namei.c,v
retrieving revision 1.22
diff -u -p -r1.22 namei.c
--- fs/namei.c	11 Jan 2005 19:10:14 -0000	1.22
+++ fs/namei.c	12 Jan 2005 19:48:37 -0000
@@ -1047,9 +1047,7 @@ int fastcall path_lookup(const char *nam
 	retval = link_path_walk(name, nd);
 	if (unlikely(current->audit_context
 		     && nd && nd->dentry && nd->dentry->d_inode))
-		audit_inode(name,
-			    nd->dentry->d_inode->i_ino,
-			    nd->dentry->d_inode->i_rdev);
+		audit_inode(name, nd->dentry->d_inode);
 	return retval;
 }
 
Index: include/linux/audit.h
===================================================================
RCS file: /source/cvsroots/fedora-cd/fedora-cd/src/linux-2.6/include/linux/audit.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 audit.h
--- include/linux/audit.h	26 May 2004 18:05:58 -0000	1.1.1.1
+++ include/linux/audit.h	12 Jan 2005 19:48:40 -0000
@@ -147,7 +147,9 @@ extern void audit_syscall_entry(struct t
 extern void audit_syscall_exit(struct task_struct *task, int return_code);
 extern void audit_getname(const char *name);
 extern void audit_putname(const char *name);
-extern void audit_inode(const char *name, unsigned long ino, dev_t rdev);
+
+struct inode;
+extern void audit_inode(const char *name, struct inode *inode);
 
 				/* Private API (for audit.c only) */
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
@@ -162,7 +164,7 @@ extern int  audit_set_loginuid(struct au
 #define audit_syscall_exit(t,r) do { ; } while (0)
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
-#define audit_inode(n,i,d) do { ; } while (0)
+#define audit_inode(n,i) do { ; } while (0)
 #endif
 
 #ifdef CONFIG_AUDIT
Index: include/linux/security.h
===================================================================
RCS file: /source/cvsroots/fedora-cd/fedora-cd/src/linux-2.6/include/linux/security.h,v
retrieving revision 1.35
diff -u -p -r1.35 security.h
--- include/linux/security.h	11 Jan 2005 19:10:15 -0000	1.35
+++ include/linux/security.h	12 Jan 2005 19:48:40 -0000
@@ -413,6 +413,11 @@ struct open_request;
  *	is specified by @buffer_size.  @buffer may be NULL to request
  *	the size of the buffer required.
  *	Returns number of bytes used/required on success.
+ * @inode_audit_augment:
+ *	Copy a NULL terminated string representing @inode's security relevant
+ *	data into @buffer.  @buffer_size is the size of buffer that is being
+ *	written to.  You only have this much space and this call can not return
+ *	an error, so manage the space wisely...
  *
  * Security hooks for file operations
  *
@@ -632,6 +637,11 @@ struct open_request;
  * 	security attributes, e.g. for /proc/pid inodes.
  *	@p contains the task_struct for the task.
  *	@inode contains the inode structure for the inode.
+ * @task_audit_augment:
+ *	Copy a NULL terminated string representing @p's security relevant
+ *	data into @buffer.  @buffer_size is the size of buffer that is being
+ *	written to.  You only have this much space and this call can not return
+ *	an error, so manage the space wisely...
  *
  * Security hooks for Netlink messaging.
  *
@@ -1127,6 +1137,8 @@ struct security_operations {
   	int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size);
   	int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
   	int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
+	void (*inode_audit_augment)(struct inode *inode, char *buffer,
+	                            size_t buffer_size);
 
 	int (*file_permission) (struct file * file, int mask);
 	int (*file_alloc_security) (struct file * file);
@@ -1168,6 +1180,8 @@ struct security_operations {
 			   unsigned long arg5);
 	void (*task_reparent_to_init) (struct task_struct * p);
 	void (*task_to_inode)(struct task_struct *p, struct inode *inode);
+	void (*task_audit_augment)(struct task_struct *p, char *buffer,
+	                           size_t buffer_size);
 
 	int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
 
@@ -1680,6 +1694,13 @@ static inline int security_inode_listsec
 	return security_ops->inode_listsecurity(inode, buffer, buffer_size);
 }
 
+static inline void security_inode_audit_augment(struct inode *inode,
+                                                char *buffer,
+                                                size_t buffer_size)
+{
+	security_ops->inode_audit_augment(inode, buffer, buffer_size);
+}
+
 static inline int security_file_permission (struct file *file, int mask)
 {
 	return security_ops->file_permission (file, mask);
@@ -1846,6 +1867,12 @@ static inline void security_task_to_inod
 	security_ops->task_to_inode(p, inode);
 }
 
+static inline void security_task_audit_augment(struct task_struct *p,
+                                               char *buffer, size_t buffer_size)
+{
+	security_ops->task_audit_augment(p, buffer, buffer_size);
+}
+
 static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
 					   short flag)
 {
@@ -2347,6 +2374,11 @@ static inline int security_inode_listsec
 	return 0;
 }
 
+static inline void security_inode_audit_augment(struct inode *inode,
+                                                char *buffer,
+                                                size_t buffer_size)
+{ }
+
 static inline int security_file_permission (struct file *file, int mask)
 {
 	return 0;
@@ -2505,6 +2537,10 @@ static inline void security_task_reparen
 }
 
 static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
+{ }
+
+static inline void security_task_audit_augment(struct task_struct *p,
+                                               char *buffer, size_t buffer_size)
 { }
 
 static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
Index: kernel/auditsc.c
===================================================================
RCS file: /source/cvsroots/fedora-cd/fedora-cd/src/linux-2.6/kernel/auditsc.c,v
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.3 auditsc.c
--- kernel/auditsc.c	14 Dec 2004 19:04:21 -0000	1.1.1.3
+++ kernel/auditsc.c	12 Jan 2005 19:48:40 -0000
@@ -39,6 +39,7 @@
 #include <linux/personality.h>
 #include <linux/time.h>
 #include <asm/unistd.h>
+#include <linux/security.h>
 
 /* 0 = no checking
    1 = put_count checking
@@ -58,6 +59,10 @@ extern int audit_enabled;
  * path_lookup. */
 #define AUDIT_NAMES_RESERVED 7
 
+/* AUDIT_SECURITY_STRING_LEN is the length of the string that we will allow
+ * security modules to add to the audit record. */
+#define AUDIT_SECURITY_STRING_LEN 1024
+
 /* At task start time, the audit_state is set in the audit_context using
    a per-task filter.  At syscall entry, the audit_state is augmented by
    the syscall filter. */
@@ -90,6 +95,11 @@ struct audit_names {
 	const char	*name;
 	unsigned long	ino;
 	dev_t		rdev;
+	int		initialized;
+	uid_t		uid;
+	gid_t		gid;
+	umode_t		mode;
+	char		security_string[AUDIT_SECURITY_STRING_LEN + 1];
 };
 
 /* The per-task audit context. */
@@ -113,6 +123,7 @@ struct audit_context {
 	uid_t		    uid, euid, suid, fsuid;
 	gid_t		    gid, egid, sgid, fsgid;
 	unsigned long	    personality;
+	char		    security_string[AUDIT_SECURITY_STRING_LEN + 1];
 
 #if AUDIT_DEBUG
 	int		    put_count;
@@ -469,6 +480,10 @@ static inline struct audit_context *audi
 	context->sgid = tsk->sgid;
 	context->fsgid = tsk->fsgid;
 	context->personality = tsk->personality;
+	context->security_string[0] = '\0';
+	security_task_audit_augment(tsk, context->security_string,
+	                            AUDIT_SECURITY_STRING_LEN);
+	context->security_string[AUDIT_SECURITY_STRING_LEN] = '\0';
 	tsk->audit_context = NULL;
 	return context;
 }
@@ -608,6 +623,8 @@ static void audit_log_exit(struct audit_
 		  context->gid,
 		  context->euid, context->suid, context->fsuid,
 		  context->egid, context->sgid, context->fsgid);
+	if (context->security_string[0] != '\0')
+		audit_log_format(ab, " security=%s", context->security_string);
 	audit_log_end(ab);
 	for (i = 0; i < context->name_count; i++) {
 		ab = audit_log_start(context);
@@ -617,15 +634,21 @@ static void audit_log_exit(struct audit_
 		if (context->names[i].name)
 			audit_log_format(ab, " name=%s",
 					 context->names[i].name);
-		if (context->names[i].ino != (unsigned long)-1)
-			audit_log_format(ab, " inode=%lu",
-					 context->names[i].ino);
 		/* FIXME: should use format_dev_t, but ab structure is
 		 * opaque. */
-		if (context->names[i].rdev != -1)
-			audit_log_format(ab, " dev=%02x:%02x",
+		if (context->names[i].initialized) {
+			audit_log_format(ab, " inode=%lu dev=%02x:%02x uid=%d"
+			                 " gid=%d mode=%04o",
+					 context->names[i].ino,
 					 MAJOR(context->names[i].rdev),
-					 MINOR(context->names[i].rdev));
+					 MINOR(context->names[i].rdev),
+			                 context->names[i].uid,
+		                         context->names[i].gid,
+			                 context->names[i].mode);
+			if (context->security_string[0] != '\0')
+				audit_log_format(ab, " security=%s",
+				             context->names[i].security_string);
+		}
 		audit_log_end(ab);
 	}
 }
@@ -815,6 +838,11 @@ void audit_getname(const char *name)
 	context->names[context->name_count].name = name;
 	context->names[context->name_count].ino  = (unsigned long)-1;
 	context->names[context->name_count].rdev = -1;
+	context->names[context->name_count].initialized = 0;
+	context->names[context->name_count].uid = -1;
+	context->names[context->name_count].gid = -1;
+	context->names[context->name_count].mode = -1;
+	context->names[context->name_count].security_string[0] = '\0';
 	++context->name_count;
 }
 
@@ -861,7 +889,7 @@ EXPORT_SYMBOL(audit_putname);
 
 /* Store the inode and device from a lookup.  Called from
  * fs/namei.c:path_lookup(). */
-void audit_inode(const char *name, unsigned long ino, dev_t rdev)
+void audit_inode(const char *name, struct inode *inode)
 {
 	int idx;
 	struct audit_context *context = current->audit_context;
@@ -887,8 +915,16 @@ void audit_inode(const char *name, unsig
 		++context->ino_count;
 #endif
 	}
-	context->names[idx].ino  = ino;
-	context->names[idx].rdev = rdev;
+	context->names[idx].initialized = 1;
+	context->names[idx].ino = inode->i_ino;
+	context->names[idx].rdev = inode->i_rdev;
+	context->names[idx].uid = inode->i_uid;
+	context->names[idx].gid = inode->i_gid;
+	context->names[idx].mode = (inode->i_mode & S_IALLUGO);
+	context->names[idx].security_string[0] = '\0';
+	security_inode_audit_augment(inode, context->names[idx].security_string,
+	                             AUDIT_SECURITY_STRING_LEN);
+	context->names[idx].security_string[AUDIT_SECURITY_STRING_LEN] = '\0';
 }
 
 void audit_get_stamp(struct audit_context *ctx,
Index: security/dummy.c
===================================================================
RCS file: /source/cvsroots/fedora-cd/fedora-cd/src/linux-2.6/security/dummy.c,v
retrieving revision 1.26
diff -u -p -r1.26 dummy.c
--- security/dummy.c	11 Jan 2005 19:10:20 -0000	1.26
+++ security/dummy.c	12 Jan 2005 19:48:40 -0000
@@ -498,6 +498,10 @@ static int dummy_inode_listsecurity(stru
 	return 0;
 }
 
+static void dummy_inode_audit_augment(struct inode *inode, char *buffer,
+                                      size_t buffer_size)
+{ }
+
 static int dummy_file_permission (struct file *file, int mask)
 {
 	return 0;
@@ -654,6 +658,10 @@ static void dummy_task_reparent_to_init 
 static void dummy_task_to_inode(struct task_struct *p, struct inode *inode)
 { }
 
+static void dummy_task_audit_augment(struct task_struct *p, char *buffer,
+                                     size_t buffer_size)
+{ }
+
 static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
 {
 	return 0;
@@ -1117,6 +1125,7 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, inode_getsecurity);
 	set_to_dummy_if_null(ops, inode_setsecurity);
 	set_to_dummy_if_null(ops, inode_listsecurity);
+ 	set_to_dummy_if_null(ops, inode_audit_augment);
 	set_to_dummy_if_null(ops, file_permission);
 	set_to_dummy_if_null(ops, file_alloc_security);
 	set_to_dummy_if_null(ops, file_free_security);
@@ -1147,6 +1156,7 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, task_prctl);
 	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, task_audit_augment);
 	set_to_dummy_if_null(ops, ipc_permission);
 	set_to_dummy_if_null(ops, msg_msg_alloc_security);
 	set_to_dummy_if_null(ops, msg_msg_free_security);
Index: security/selinux/hooks.c
===================================================================
RCS file: /source/cvsroots/fedora-cd/fedora-cd/src/linux-2.6/security/selinux/hooks.c,v
retrieving revision 1.94
diff -u -p -r1.94 hooks.c
--- security/selinux/hooks.c	11 Jan 2005 19:10:20 -0000	1.94
+++ security/selinux/hooks.c	12 Jan 2005 19:48:40 -0000
@@ -2717,6 +2717,28 @@ static int selinux_inode_listsecurity(st
 	return len;
 }
 
+static void selinux_inode_audit_augment(struct inode *inode, char *buffer,
+                                        size_t buffer_size)
+{
+	struct inode_security_struct *isec = inode->i_security;
+	char *context;
+	unsigned len;
+
+	if (!buffer || !buffer_size)
+		return;
+
+	if (security_sid_to_context(isec->sid, &context, &len))
+		return;
+
+	if (buffer_size < len)
+		len = buffer_size;
+
+	memcpy(buffer, context, len);
+	kfree(context);
+
+	return;
+}
+
 /* file security operations */
 
 static int selinux_file_permission(struct file *file, int mask)
@@ -3139,6 +3161,28 @@ static void selinux_task_to_inode(struct
 	return;
 }
 
+static void selinux_task_audit_augment(struct task_struct *p, char *buffer,
+                                       size_t buffer_size)
+{
+	struct task_security_struct *tsec = p->security;
+	char *context;
+	unsigned len;
+
+	if (!buffer || !buffer_size)
+		return;
+
+	if (security_sid_to_context(tsec->sid, &context, &len))
+		return;
+
+	if (buffer_size < len)
+		len = buffer_size;
+
+	memcpy(buffer, context, len);
+	kfree(context);
+
+	return;
+}
+
 #ifdef CONFIG_SECURITY_NETWORK
 
 /* Returns error only if unable to parse addresses */
@@ -6024,6 +6068,7 @@ struct security_operations selinux_ops =
 	.inode_getsecurity =            selinux_inode_getsecurity,
 	.inode_setsecurity =            selinux_inode_setsecurity,
 	.inode_listsecurity =           selinux_inode_listsecurity,
+ 	.inode_audit_augment =		selinux_inode_audit_augment,
 
 	.file_permission =		selinux_file_permission,
 	.file_alloc_security =		selinux_file_alloc_security,
@@ -6056,6 +6101,7 @@ struct security_operations selinux_ops =
 	.task_prctl =			selinux_task_prctl,
 	.task_reparent_to_init =	selinux_task_reparent_to_init,
 	.task_to_inode =                selinux_task_to_inode,
+ 	.task_audit_augment =		selinux_task_audit_augment,
 
 	.ipc_permission =		selinux_ipc_permission,
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]