On Wednesday 29 March 2006 14:01, Stephen Smalley wrote:
Not that I disagree with this change in approach, but I think that
when
it has come up in the past, there has been concern expressed about the
fact that we could end up not being able to generate the context from
the SID when the audit record is being emitted (due to OOM condition),
OK, attached below is a patch that I think addresses all your comments.
In testing this version, I noticed that I now have a 30% performace hit.
Somewhere between the two patches I lost 19% of the performance.
I'm reviewing the differences to see what caused that.
There is one last loose end to this patch. I am adding a function,
selinux_ctxid_to_string. Is there an official SE Linux kernel API that
provides this? I'll fix Tim's patch to use the same API.
-Steve
diff -urp linux-2.6.16.x86_64.orig/include/linux/selinux.h
linux-2.6.16.x86_64/include/linux/selinux.h
--- linux-2.6.16.x86_64.orig/include/linux/selinux.h 2006-03-29 18:08:04.000000000 -0500
+++ linux-2.6.16.x86_64/include/linux/selinux.h 2006-03-29 20:29:32.000000000 -0500
@@ -15,6 +15,7 @@
struct selinux_audit_rule;
struct audit_context;
+struct inode;
#ifdef CONFIG_SECURITY_SELINUX
@@ -76,6 +77,28 @@ void selinux_audit_set_callback(int (*ca
*/
void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid);
+/**
+ * selinux_ctxid_to_string - map a security context ID to a string
+ * @ctxid: security context ID to be converted.
+ * @ctx: address of context string to be returned
+ * @ctxlen: length of returned context string.
+ * @gfp_mask: memory type mask
+ *
+ * Returns 0 if successful, -errno if not. On success, the context
+ * string will be allocated internally, and the caller must call
+ * kfree() on it after use.
+ */
+int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen, gfp_t gfp_mask);
+
+/**
+ * selinux_get_inode_sid - get the inode's security context ID
+ * @inode: inode structure to get the sid from.
+ * @sid: security context ID returned.
+ *
+ * Returns nothing
+ */
+void selinux_get_inode_sid(const struct inode *inode, u32 *sid);
+
#else
static inline int selinux_audit_rule_init(u32 field, u32 op,
@@ -107,6 +130,18 @@ static inline void selinux_task_ctxid(st
*ctxid = 0;
}
+static inline void selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen, gfp_t
gfp_mask)
+{
+ *ctx = NULL;
+ *ctxlen = 0;
+ return 0;
+}
+
+static inline void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+{
+ *sid = 0;
+}
+
#endif /* CONFIG_SECURITY_SELINUX */
#endif /* _LINUX_SELINUX_H */
diff -urp linux-2.6.16.x86_64.orig/kernel/auditsc.c linux-2.6.16.x86_64/kernel/auditsc.c
--- linux-2.6.16.x86_64.orig/kernel/auditsc.c 2006-03-29 18:08:07.000000000 -0500
+++ linux-2.6.16.x86_64/kernel/auditsc.c 2006-03-29 20:17:41.000000000 -0500
@@ -90,7 +90,7 @@ struct audit_names {
uid_t uid;
gid_t gid;
dev_t rdev;
- char *ctx;
+ u32 osid;
};
struct audit_aux_data {
@@ -435,9 +435,6 @@ static inline void audit_free_names(stru
#endif
for (i = 0; i < context->name_count; i++) {
- char *p = context->names[i].ctx;
- context->names[i].ctx = NULL;
- kfree(p);
if (context->names[i].name)
__putname(context->names[i].name);
}
@@ -729,9 +726,16 @@ 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].ctx) {
- audit_log_format(ab, " obj=%s",
- context->names[i].ctx);
+ if (context->names[i].osid != 0) {
+ char *ctx;
+ int len;
+ if (selinux_ctxid_to_string(
+ context->names[i].osid, &ctx, &len, gfp_mask)){
+ audit_log_format(ab, " obj=%u",
+ context->names[i].osid);
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
}
audit_log_end(ab);
@@ -983,37 +987,10 @@ void audit_putname(const char *name)
void audit_inode_context(int idx, const struct inode *inode)
{
struct audit_context *context = current->audit_context;
- const char *suffix = security_inode_xattr_getsuffix();
- char *ctx = NULL;
- int len = 0;
-
- if (!suffix)
- goto ret;
-
- len = security_inode_getsecurity(inode, suffix, NULL, 0, 0);
- if (len == -EOPNOTSUPP)
- goto ret;
- if (len < 0)
- goto error_path;
-
- ctx = kmalloc(len, GFP_KERNEL);
- if (!ctx)
- goto error_path;
-
- len = security_inode_getsecurity(inode, suffix, ctx, len, 0);
- if (len < 0)
- goto error_path;
-
- kfree(context->names[idx].ctx);
- context->names[idx].ctx = ctx;
- goto ret;
-
-error_path:
- if (ctx)
- kfree(ctx);
- audit_panic("error in audit_inode_context");
-ret:
- return;
+ if (security_inode_xattr_getsuffix())
+ selinux_get_inode_sid(inode, &context->names[idx].osid);
+ else
+ context->names[idx].osid = 0;
}
diff -urp linux-2.6.16.x86_64.orig/security/selinux/exports.c
linux-2.6.16.x86_64/security/selinux/exports.c
--- linux-2.6.16.x86_64.orig/security/selinux/exports.c 2006-03-29 18:08:08.000000000
-0500
+++ linux-2.6.16.x86_64/security/selinux/exports.c 2006-03-29 20:24:55.000000000 -0500
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/selinux.h>
+#include <linux/fs.h>
#include "security.h"
#include "objsec.h"
@@ -26,3 +27,27 @@ void selinux_task_ctxid(struct task_stru
else
*ctxid = 0;
}
+
+extern int ss_initialized;
+
+int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen, gfp_t gfp_mask)
+{
+ if (ss_initialized)
+ return security_sid_to_context(ctxid, ctx, ctxlen);
+ else {
+ *ctx = NULL;
+ *ctxlen = 0;
+ }
+
+ return 0;
+}
+
+void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+{
+ if (selinux_enabled) {
+ struct inode_security_struct *isec = inode->i_security;
+ *sid = isec->sid;
+ } else
+ *sid = 0;
+}
+