Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
Linus Torvalds [Sat, 19 Apr 2008 01:18:30 +0000 (18:18 -0700)]
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
  security: fix up documentation for security_module_enable
  Security: Introduce security= boot parameter
  Audit: Final renamings and cleanup
  SELinux: use new audit hooks, remove redundant exports
  Audit: internally use the new LSM audit hooks
  LSM/Audit: Introduce generic Audit LSM hooks
  SELinux: remove redundant exports
  Netlink: Use generic LSM hook
  Audit: use new LSM hooks instead of SELinux exports
  SELinux: setup new inode/ipc getsecid hooks
  LSM: Introduce inode_getsecid and ipc_getsecid hooks

18 files changed:
Documentation/kernel-parameters.txt
include/linux/audit.h
include/linux/security.h
include/linux/selinux.h
kernel/audit.c
kernel/audit.h
kernel/auditfilter.c
kernel/auditsc.c
net/netlink/af_netlink.c
security/dummy.c
security/security.c
security/selinux/exports.c
security/selinux/hooks.c
security/selinux/include/audit.h [new file with mode: 0644]
security/selinux/ss/services.c
security/smack/smack.h
security/smack/smack_lsm.c
security/smack/smackfs.c

index 256a216..4b0f1ae 100644 (file)
@@ -366,6 +366,12 @@ and is between 256 and 4096 characters. It is defined in the file
                        possible to determine what the correct size should be.
                        This option provides an override for these situations.
 
+       security=       [SECURITY] Choose a security module to enable at boot.
+                       If this boot parameter is not specified, only the first
+                       security module asking for security registration will be
+                       loaded. An invalid security module name will be treated
+                       as if no module has been chosen.
+
        capability.disable=
                        [SECURITY] Disable capabilities.  This would normally
                        be used only if an alternative security model is to be
index 2af9ec0..4ccb048 100644 (file)
@@ -353,6 +353,33 @@ struct netlink_skb_parms;
 struct linux_binprm;
 struct mq_attr;
 struct mqstat;
+struct audit_watch;
+struct audit_tree;
+
+struct audit_krule {
+       int                     vers_ops;
+       u32                     flags;
+       u32                     listnr;
+       u32                     action;
+       u32                     mask[AUDIT_BITMASK_SIZE];
+       u32                     buflen; /* for data alloc on list rules */
+       u32                     field_count;
+       char                    *filterkey; /* ties events to rules */
+       struct audit_field      *fields;
+       struct audit_field      *arch_f; /* quick access to arch field */
+       struct audit_field      *inode_f; /* quick access to an inode field */
+       struct audit_watch      *watch; /* associated watch */
+       struct audit_tree       *tree;  /* associated watched tree */
+       struct list_head        rlist;  /* entry in audit_{watch,tree}.rules list */
+};
+
+struct audit_field {
+       u32                             type;
+       u32                             val;
+       u32                             op;
+       char                            *lsm_str;
+       void                            *lsm_rule;
+};
 
 #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
@@ -536,6 +563,8 @@ extern void             audit_log_d_path(struct audit_buffer *ab,
                                             const char *prefix,
                                             struct path *path);
 extern void                audit_log_lost(const char *message);
+extern int                 audit_update_lsm_rules(void);
+
                                /* Private API (for audit.c only) */
 extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
 extern int audit_filter_type(int type);
index f5eb9ff..fea1f4a 100644 (file)
 
 extern unsigned securebits;
 
+/* Maximum number of letters for an LSM name string */
+#define SECURITY_NAME_MAX      10
+
 struct ctl_table;
+struct audit_krule;
 
 /*
  * These functions are in security/capability.c and are used
@@ -136,6 +140,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
 /**
  * struct security_operations - main security structure
  *
+ * Security module identifier.
+ *
+ * @name:
+ *     A string that acts as a unique identifeir for the LSM with max number
+ *     of characters = SECURITY_NAME_MAX.
+ *
  * Security hooks for program execution operations.
  *
  * @bprm_alloc_security:
@@ -468,6 +478,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     @dentry is the dentry being changed.
  *     Return 0 on success.  If error is returned, then the operation
  *     causing setuid bit removal is failed.
+ * @inode_getsecid:
+ *     Get the secid associated with the node.
+ *     @inode contains a pointer to the inode.
+ *     @secid contains a pointer to the location where result will be saved.
+ *     In case of failure, @secid will be set to zero.
  *
  * Security hooks for file operations
  *
@@ -636,6 +651,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  * @task_getsecid:
  *     Retrieve the security identifier of the process @p.
  *     @p contains the task_struct for the process and place is into @secid.
+ *     In case of failure, @secid will be set to zero.
+ *
  * @task_setgroups:
  *     Check permission before setting the supplementary group set of the
  *     current process.
@@ -997,6 +1014,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     @ipcp contains the kernel IPC permission structure
  *     @flag contains the desired (requested) permission set
  *     Return 0 if permission is granted.
+ * @ipc_getsecid:
+ *     Get the secid associated with the ipc object.
+ *     @ipcp contains the kernel IPC permission structure.
+ *     @secid contains a pointer to the location where result will be saved.
+ *     In case of failure, @secid will be set to zero.
  *
  * Security hooks for individual messages held in System V IPC message queues
  * @msg_msg_alloc_security:
@@ -1223,9 +1245,42 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     @secdata contains the security context.
  *     @seclen contains the length of the security context.
  *
+ * Security hooks for Audit
+ *
+ * @audit_rule_init:
+ *     Allocate and initialize an LSM audit rule structure.
+ *     @field contains the required Audit action. Fields flags are defined in include/linux/audit.h
+ *     @op contains the operator the rule uses.
+ *     @rulestr contains the context where the rule will be applied to.
+ *     @lsmrule contains a pointer to receive the result.
+ *     Return 0 if @lsmrule has been successfully set,
+ *     -EINVAL in case of an invalid rule.
+ *
+ * @audit_rule_known:
+ *     Specifies whether given @rule contains any fields related to current LSM.
+ *     @rule contains the audit rule of interest.
+ *     Return 1 in case of relation found, 0 otherwise.
+ *
+ * @audit_rule_match:
+ *     Determine if given @secid matches a rule previously approved
+ *     by @audit_rule_known.
+ *     @secid contains the security id in question.
+ *     @field contains the field which relates to current LSM.
+ *     @op contains the operator that will be used for matching.
+ *     @rule points to the audit rule that will be checked against.
+ *     @actx points to the audit context associated with the check.
+ *     Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
+ *
+ * @audit_rule_free:
+ *     Deallocate the LSM audit rule structure previously allocated by
+ *     audit_rule_init.
+ *     @rule contains the allocated rule
+ *
  * This is the main security structure.
  */
 struct security_operations {
+       char name[SECURITY_NAME_MAX + 1];
+
        int (*ptrace) (struct task_struct * parent, struct task_struct * child);
        int (*capget) (struct task_struct * target,
                       kernel_cap_t * effective,
@@ -1317,6 +1372,7 @@ struct security_operations {
        int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
        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_getsecid)(const struct inode *inode, u32 *secid);
 
        int (*file_permission) (struct file * file, int mask);
        int (*file_alloc_security) (struct file * file);
@@ -1369,6 +1425,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);
+       void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid);
 
        int (*msg_msg_alloc_security) (struct msg_msg * msg);
        void (*msg_msg_free_security) (struct msg_msg * msg);
@@ -1480,10 +1537,18 @@ struct security_operations {
 
 #endif /* CONFIG_KEYS */
 
+#ifdef CONFIG_AUDIT
+       int (*audit_rule_init)(u32 field, u32 op, char *rulestr, void **lsmrule);
+       int (*audit_rule_known)(struct audit_krule *krule);
+       int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule,
+                               struct audit_context *actx);
+       void (*audit_rule_free)(void *lsmrule);
+#endif /* CONFIG_AUDIT */
 };
 
 /* prototypes */
 extern int security_init       (void);
+extern int security_module_enable(struct security_operations *ops);
 extern int register_security   (struct security_operations *ops);
 extern int mod_reg_security    (const char *name, struct security_operations *ops);
 extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
@@ -1578,6 +1643,7 @@ int security_inode_killpriv(struct dentry *dentry);
 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
+void security_inode_getsecid(const struct inode *inode, u32 *secid);
 int security_file_permission(struct file *file, int mask);
 int security_file_alloc(struct file *file);
 void security_file_free(struct file *file);
@@ -1622,6 +1688,7 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 void security_task_reparent_to_init(struct task_struct *p);
 void security_task_to_inode(struct task_struct *p, struct inode *inode);
 int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
+void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
 int security_msg_msg_alloc(struct msg_msg *msg);
 void security_msg_msg_free(struct msg_msg *msg);
 int security_msg_queue_alloc(struct msg_queue *msq);
@@ -2022,6 +2089,11 @@ static inline int security_inode_listsecurity(struct inode *inode, char *buffer,
        return 0;
 }
 
+static inline void security_inode_getsecid(const struct inode *inode, u32 *secid)
+{
+       *secid = 0;
+}
+
 static inline int security_file_permission (struct file *file, int mask)
 {
        return 0;
@@ -2137,7 +2209,9 @@ static inline int security_task_getsid (struct task_struct *p)
 }
 
 static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
-{ }
+{
+       *secid = 0;
+}
 
 static inline int security_task_setgroups (struct group_info *group_info)
 {
@@ -2216,6 +2290,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
        return 0;
 }
 
+static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+{
+       *secid = 0;
+}
+
 static inline int security_msg_msg_alloc (struct msg_msg * msg)
 {
        return 0;
@@ -2672,5 +2751,38 @@ static inline int security_key_permission(key_ref_t key_ref,
 #endif
 #endif /* CONFIG_KEYS */
 
+#ifdef CONFIG_AUDIT
+#ifdef CONFIG_SECURITY
+int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
+int security_audit_rule_known(struct audit_krule *krule);
+int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
+                             struct audit_context *actx);
+void security_audit_rule_free(void *lsmrule);
+
+#else
+
+static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr,
+                                          void **lsmrule)
+{
+       return 0;
+}
+
+static inline int security_audit_rule_known(struct audit_krule *krule)
+{
+       return 0;
+}
+
+static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
+                                  void *lsmrule, struct audit_context *actx)
+{
+       return 0;
+}
+
+static inline void security_audit_rule_free(void *lsmrule)
+{ }
+
+#endif /* CONFIG_SECURITY */
+#endif /* CONFIG_AUDIT */
+
 #endif /* ! __LINUX_SECURITY_H */
 
index 8c2cc4c..20f965d 100644 (file)
 
 struct selinux_audit_rule;
 struct audit_context;
-struct inode;
 struct kern_ipc_perm;
 
 #ifdef CONFIG_SECURITY_SELINUX
 
 /**
- *     selinux_audit_rule_init - alloc/init an selinux audit rule structure.
- *     @field: the field this rule refers to
- *     @op: the operater the rule uses
- *     @rulestr: the text "target" of the rule
- *     @rule: pointer to the new rule structure returned via this
- *
- *     Returns 0 if successful, -errno if not.  On success, the rule structure
- *     will be allocated internally.  The caller must free this structure with
- *     selinux_audit_rule_free() after use.
- */
-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
-                            struct selinux_audit_rule **rule);
-
-/**
- *     selinux_audit_rule_free - free an selinux audit rule structure.
- *     @rule: pointer to the audit rule to be freed
- *
- *     This will free all memory associated with the given rule.
- *     If @rule is NULL, no operation is performed.
- */
-void selinux_audit_rule_free(struct selinux_audit_rule *rule);
-
-/**
- *     selinux_audit_rule_match - determine if a context ID matches a rule.
- *     @sid: the context ID to check
- *     @field: the field this rule refers to
- *     @op: the operater the rule uses
- *     @rule: pointer to the audit rule to check against
- *     @actx: the audit context (can be NULL) associated with the check
- *
- *     Returns 1 if the context id matches the rule, 0 if it does not, and
- *     -errno on failure.
- */
-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
-                             struct selinux_audit_rule *rule,
-                             struct audit_context *actx);
-
-/**
- *     selinux_audit_set_callback - set the callback for policy reloads.
- *     @callback: the function to call when the policy is reloaded
- *
- *     This sets the function callback function that will update the rules
- *     upon policy reloads.  This callback should rebuild all existing rules
- *     using selinux_audit_rule_init().
- */
-void selinux_audit_set_callback(int (*callback)(void));
-
-/**
- *     selinux_sid_to_string - map a security context ID to a string
- *     @sid: security context ID to be converted.
- *     @ctx: address of context string to be returned
- *     @ctxlen: length of returned context string.
- *
- *     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_sid_to_string(u32 sid, char **ctx, u32 *ctxlen);
-
-/**
- *     selinux_get_inode_sid - get the inode's security context ID
- *     @inode: inode structure to get the sid from.
- *     @sid: pointer to security context ID to be filled in.
- *
- *     Returns nothing
- */
-void selinux_get_inode_sid(const struct inode *inode, u32 *sid);
-
-/**
- *     selinux_get_ipc_sid - get the ipc security context ID
- *     @ipcp: ipc structure to get the sid from.
- *     @sid: pointer to security context ID to be filled in.
- *
- *     Returns nothing
- */
-void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
-
-/**
- *     selinux_get_task_sid - return the SID of task
- *     @tsk: the task whose SID will be returned
- *     @sid: pointer to security context ID to be filled in.
- *
- *     Returns nothing
- */
-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
-
-/**
  *     selinux_string_to_sid - map a security context string to a security ID
  *     @str: the security context string to be mapped
  *     @sid: ID value returned via this.
@@ -151,52 +63,6 @@ void selinux_secmark_refcount_inc(void);
 void selinux_secmark_refcount_dec(void);
 #else
 
-static inline int selinux_audit_rule_init(u32 field, u32 op,
-                                          char *rulestr,
-                                          struct selinux_audit_rule **rule)
-{
-       return -EOPNOTSUPP;
-}
-
-static inline void selinux_audit_rule_free(struct selinux_audit_rule *rule)
-{
-       return;
-}
-
-static inline int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
-                                           struct selinux_audit_rule *rule,
-                                           struct audit_context *actx)
-{
-       return 0;
-}
-
-static inline void selinux_audit_set_callback(int (*callback)(void))
-{
-       return;
-}
-
-static inline int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
-{
-       *ctx = NULL;
-       *ctxlen = 0;
-       return 0;
-}
-
-static inline void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
-{
-       *sid = 0;
-}
-
-static inline void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
-{
-       *sid = 0;
-}
-
-static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
-{
-       *sid = 0;
-}
-
 static inline int selinux_string_to_sid(const char *str, u32 *sid)
 {
        *sid = 0;
index b782b04..a7b1608 100644 (file)
@@ -21,7 +21,7 @@
  *
  * Written by Rickard E. (Rik) Faith <faith@redhat.com>
  *
- * Goals: 1) Integrate fully with SELinux.
+ * Goals: 1) Integrate fully with Security Modules.
  *       2) Minimal run-time overhead:
  *          a) Minimal when syscall auditing is disabled (audit_enable=0).
  *          b) Small when syscall auditing is enabled and no audit record
@@ -55,7 +55,6 @@
 #include <net/netlink.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
-#include <linux/selinux.h>
 #include <linux/inotify.h>
 #include <linux/freezer.h>
 #include <linux/tty.h>
@@ -265,13 +264,13 @@ static int audit_log_config_change(char *function_name, int new, int old,
                char *ctx = NULL;
                u32 len;
 
-               rc = selinux_sid_to_string(sid, &ctx, &len);
+               rc = security_secid_to_secctx(sid, &ctx, &len);
                if (rc) {
                        audit_log_format(ab, " sid=%u", sid);
                        allow_changes = 0; /* Something weird, deny request */
                } else {
                        audit_log_format(ab, " subj=%s", ctx);
-                       kfree(ctx);
+                       security_release_secctx(ctx, len);
                }
        }
        audit_log_format(ab, " res=%d", allow_changes);
@@ -550,12 +549,13 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
        audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
                         pid, uid, auid);
        if (sid) {
-               rc = selinux_sid_to_string(sid, &ctx, &len);
+               rc = security_secid_to_secctx(sid, &ctx, &len);
                if (rc)
                        audit_log_format(*ab, " ssid=%u", sid);
-               else
+               else {
                        audit_log_format(*ab, " subj=%s", ctx);
-               kfree(ctx);
+                       security_release_secctx(ctx, len);
+               }
        }
 
        return rc;
@@ -758,18 +758,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                break;
        }
        case AUDIT_SIGNAL_INFO:
-               err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
+               err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);
                if (err)
                        return err;
                sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
                if (!sig_data) {
-                       kfree(ctx);
+                       security_release_secctx(ctx, len);
                        return -ENOMEM;
                }
                sig_data->uid = audit_sig_uid;
                sig_data->pid = audit_sig_pid;
                memcpy(sig_data->ctx, ctx, len);
-               kfree(ctx);
+               security_release_secctx(ctx, len);
                audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
                                0, 0, sig_data, sizeof(*sig_data) + len);
                kfree(sig_data);
@@ -881,10 +881,6 @@ static int __init audit_init(void)
        audit_enabled = audit_default;
        audit_ever_enabled |= !!audit_default;
 
-       /* Register the callback with selinux.  This callback will be invoked
-        * when a new policy is loaded. */
-       selinux_audit_set_callback(&selinux_audit_rule_update);
-
        audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
 
 #ifdef CONFIG_AUDITSYSCALL
index 2554bd5..3cfc54e 100644 (file)
@@ -65,34 +65,9 @@ struct audit_watch {
        struct list_head        rules;  /* associated rules */
 };
 
-struct audit_field {
-       u32                             type;
-       u32                             val;
-       u32                             op;
-       char                            *se_str;
-       struct selinux_audit_rule       *se_rule;
-};
-
 struct audit_tree;
 struct audit_chunk;
 
-struct audit_krule {
-       int                     vers_ops;
-       u32                     flags;
-       u32                     listnr;
-       u32                     action;
-       u32                     mask[AUDIT_BITMASK_SIZE];
-       u32                     buflen; /* for data alloc on list rules */
-       u32                     field_count;
-       char                    *filterkey; /* ties events to rules */
-       struct audit_field      *fields;
-       struct audit_field      *arch_f; /* quick access to arch field */
-       struct audit_field      *inode_f; /* quick access to an inode field */
-       struct audit_watch      *watch; /* associated watch */
-       struct audit_tree       *tree;  /* associated watched tree */
-       struct list_head        rlist;  /* entry in audit_{watch,tree}.rules list */
-};
-
 struct audit_entry {
        struct list_head        list;
        struct rcu_head         rcu;
index 2f2914b..28fef6b 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/netlink.h>
 #include <linux/sched.h>
 #include <linux/inotify.h>
-#include <linux/selinux.h>
+#include <linux/security.h>
 #include "audit.h"
 
 /*
@@ -38,7 +38,7 @@
  *             Synchronizes writes and blocking reads of audit's filterlist
  *             data.  Rcu is used to traverse the filterlist and access
  *             contents of structs audit_entry, audit_watch and opaque
- *             selinux rules during filtering.  If modified, these structures
+ *             LSM rules during filtering.  If modified, these structures
  *             must be copied and replace their counterparts in the filterlist.
  *             An audit_parent struct is not accessed during filtering, so may
  *             be written directly provided audit_filter_mutex is held.
@@ -139,8 +139,8 @@ static inline void audit_free_rule(struct audit_entry *e)
        if (e->rule.fields)
                for (i = 0; i < e->rule.field_count; i++) {
                        struct audit_field *f = &e->rule.fields[i];
-                       kfree(f->se_str);
-                       selinux_audit_rule_free(f->se_rule);
+                       kfree(f->lsm_str);
+                       security_audit_rule_free(f->lsm_rule);
                }
        kfree(e->rule.fields);
        kfree(e->rule.filterkey);
@@ -554,8 +554,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                f->op = data->fieldflags[i] & AUDIT_OPERATORS;
                f->type = data->fields[i];
                f->val = data->values[i];
-               f->se_str = NULL;
-               f->se_rule = NULL;
+               f->lsm_str = NULL;
+               f->lsm_rule = NULL;
                switch(f->type) {
                case AUDIT_PID:
                case AUDIT_UID:
@@ -597,12 +597,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                                goto exit_free;
                        entry->rule.buflen += f->val;
 
-                       err = selinux_audit_rule_init(f->type, f->op, str,
-                                                     &f->se_rule);
+                       err = security_audit_rule_init(f->type, f->op, str,
+                                                      (void **)&f->lsm_rule);
                        /* Keep currently invalid fields around in case they
                         * become valid after a policy reload. */
                        if (err == -EINVAL) {
-                               printk(KERN_WARNING "audit rule for selinux "
+                               printk(KERN_WARNING "audit rule for LSM "
                                       "\'%s\' is invalid\n",  str);
                                err = 0;
                        }
@@ -610,7 +610,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                                kfree(str);
                                goto exit_free;
                        } else
-                               f->se_str = str;
+                               f->lsm_str = str;
                        break;
                case AUDIT_WATCH:
                        str = audit_unpack_string(&bufp, &remain, f->val);
@@ -754,7 +754,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
                case AUDIT_OBJ_LEV_LOW:
                case AUDIT_OBJ_LEV_HIGH:
                        data->buflen += data->values[i] =
-                               audit_pack_string(&bufp, f->se_str);
+                               audit_pack_string(&bufp, f->lsm_str);
                        break;
                case AUDIT_WATCH:
                        data->buflen += data->values[i] =
@@ -806,7 +806,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
                case AUDIT_OBJ_TYPE:
                case AUDIT_OBJ_LEV_LOW:
                case AUDIT_OBJ_LEV_HIGH:
-                       if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
+                       if (strcmp(a->fields[i].lsm_str, b->fields[i].lsm_str))
                                return 1;
                        break;
                case AUDIT_WATCH:
@@ -862,28 +862,28 @@ out:
        return new;
 }
 
-/* Duplicate selinux field information.  The se_rule is opaque, so must be
+/* Duplicate LSM field information.  The lsm_rule is opaque, so must be
  * re-initialized. */
-static inline int audit_dupe_selinux_field(struct audit_field *df,
+static inline int audit_dupe_lsm_field(struct audit_field *df,
                                           struct audit_field *sf)
 {
        int ret = 0;
-       char *se_str;
+       char *lsm_str;
 
-       /* our own copy of se_str */
-       se_str = kstrdup(sf->se_str, GFP_KERNEL);
-       if (unlikely(!se_str))
+       /* our own copy of lsm_str */
+       lsm_str = kstrdup(sf->lsm_str, GFP_KERNEL);
+       if (unlikely(!lsm_str))
                return -ENOMEM;
-       df->se_str = se_str;
+       df->lsm_str = lsm_str;
 
-       /* our own (refreshed) copy of se_rule */
-       ret = selinux_audit_rule_init(df->type, df->op, df->se_str,
-                                     &df->se_rule);
+       /* our own (refreshed) copy of lsm_rule */
+       ret = security_audit_rule_init(df->type, df->op, df->lsm_str,
+                                      (void **)&df->lsm_rule);
        /* Keep currently invalid fields around in case they
         * become valid after a policy reload. */
        if (ret == -EINVAL) {
-               printk(KERN_WARNING "audit rule for selinux \'%s\' is "
-                      "invalid\n", df->se_str);
+               printk(KERN_WARNING "audit rule for LSM \'%s\' is "
+                      "invalid\n", df->lsm_str);
                ret = 0;
        }
 
@@ -891,7 +891,7 @@ static inline int audit_dupe_selinux_field(struct audit_field *df,
 }
 
 /* Duplicate an audit rule.  This will be a deep copy with the exception
- * of the watch - that pointer is carried over.  The selinux specific fields
+ * of the watch - that pointer is carried over.  The LSM specific fields
  * will be updated in the copy.  The point is to be able to replace the old
  * rule with the new rule in the filterlist, then free the old rule.
  * The rlist element is undefined; list manipulations are handled apart from
@@ -930,7 +930,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
        new->tree = old->tree;
        memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
 
-       /* deep copy this information, updating the se_rule fields, because
+       /* deep copy this information, updating the lsm_rule fields, because
         * the originals will all be freed when the old rule is freed. */
        for (i = 0; i < fcount; i++) {
                switch (new->fields[i].type) {
@@ -944,7 +944,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
                case AUDIT_OBJ_TYPE:
                case AUDIT_OBJ_LEV_LOW:
                case AUDIT_OBJ_LEV_HIGH:
-                       err = audit_dupe_selinux_field(&new->fields[i],
+                       err = audit_dupe_lsm_field(&new->fields[i],
                                                       &old->fields[i]);
                        break;
                case AUDIT_FILTERKEY:
@@ -1515,11 +1515,12 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
        if (sid) {
                char *ctx = NULL;
                u32 len;
-               if (selinux_sid_to_string(sid, &ctx, &len))
+               if (security_secid_to_secctx(sid, &ctx, &len))
                        audit_log_format(ab, " ssid=%u", sid);
-               else
+               else {
                        audit_log_format(ab, " subj=%s", ctx);
-               kfree(ctx);
+                       security_release_secctx(ctx, len);
+               }
        }
        audit_log_format(ab, " op=%s rule key=", action);
        if (rule->filterkey)
@@ -1761,38 +1762,12 @@ unlock_and_return:
        return result;
 }
 
-/* Check to see if the rule contains any selinux fields.  Returns 1 if there
-   are selinux fields specified in the rule, 0 otherwise. */
-static inline int audit_rule_has_selinux(struct audit_krule *rule)
-{
-       int i;
-
-       for (i = 0; i < rule->field_count; i++) {
-               struct audit_field *f = &rule->fields[i];
-               switch (f->type) {
-               case AUDIT_SUBJ_USER:
-               case AUDIT_SUBJ_ROLE:
-               case AUDIT_SUBJ_TYPE:
-               case AUDIT_SUBJ_SEN:
-               case AUDIT_SUBJ_CLR:
-               case AUDIT_OBJ_USER:
-               case AUDIT_OBJ_ROLE:
-               case AUDIT_OBJ_TYPE:
-               case AUDIT_OBJ_LEV_LOW:
-               case AUDIT_OBJ_LEV_HIGH:
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-/* This function will re-initialize the se_rule field of all applicable rules.
- * It will traverse the filter lists serarching for rules that contain selinux
+/* This function will re-initialize the lsm_rule field of all applicable rules.
+ * It will traverse the filter lists serarching for rules that contain LSM
  * specific filter fields.  When such a rule is found, it is copied, the
- * selinux field is re-initialized, and the old rule is replaced with the
+ * LSM field is re-initialized, and the old rule is replaced with the
  * updated rule. */
-int selinux_audit_rule_update(void)
+int audit_update_lsm_rules(void)
 {
        struct audit_entry *entry, *n, *nentry;
        struct audit_watch *watch;
@@ -1804,7 +1779,7 @@ int selinux_audit_rule_update(void)
 
        for (i = 0; i < AUDIT_NR_FILTERS; i++) {
                list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
-                       if (!audit_rule_has_selinux(&entry->rule))
+                       if (!security_audit_rule_known(&entry->rule))
                                continue;
 
                        watch = entry->rule.watch;
@@ -1815,7 +1790,7 @@ int selinux_audit_rule_update(void)
                                 * return value */
                                if (!err)
                                        err = PTR_ERR(nentry);
-                               audit_panic("error updating selinux filters");
+                               audit_panic("error updating LSM filters");
                                if (watch)
                                        list_del(&entry->rule.rlist);
                                list_del_rcu(&entry->list);
index 782262e..56e56ed 100644 (file)
@@ -61,7 +61,6 @@
 #include <linux/security.h>
 #include <linux/list.h>
 #include <linux/tty.h>
-#include <linux/selinux.h>
 #include <linux/binfmts.h>
 #include <linux/highmem.h>
 #include <linux/syscalls.h>
@@ -528,14 +527,14 @@ static int audit_filter_rules(struct task_struct *tsk,
                           match for now to avoid losing information that
                           may be wanted.   An error message will also be
                           logged upon error */
-                       if (f->se_rule) {
+                       if (f->lsm_rule) {
                                if (need_sid) {
-                                       selinux_get_task_sid(tsk, &sid);
+                                       security_task_getsecid(tsk, &sid);
                                        need_sid = 0;
                                }
-                               result = selinux_audit_rule_match(sid, f->type,
+                               result = security_audit_rule_match(sid, f->type,
                                                                  f->op,
-                                                                 f->se_rule,
+                                                                 f->lsm_rule,
                                                                  ctx);
                        }
                        break;
@@ -546,18 +545,18 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_OBJ_LEV_HIGH:
                        /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
                           also applies here */
-                       if (f->se_rule) {
+                       if (f->lsm_rule) {
                                /* Find files that match */
                                if (name) {
-                                       result = selinux_audit_rule_match(
+                                       result = security_audit_rule_match(
                                                   name->osid, f->type, f->op,
-                                                  f->se_rule, ctx);
+                                                  f->lsm_rule, ctx);
                                } else if (ctx) {
                                        for (j = 0; j < ctx->name_count; j++) {
-                                               if (selinux_audit_rule_match(
+                                               if (security_audit_rule_match(
                                                      ctx->names[j].osid,
                                                      f->type, f->op,
-                                                     f->se_rule, ctx)) {
+                                                     f->lsm_rule, ctx)) {
                                                        ++result;
                                                        break;
                                                }
@@ -570,7 +569,7 @@ static int audit_filter_rules(struct task_struct *tsk,
                                             aux = aux->next) {
                                                if (aux->type == AUDIT_IPC) {
                                                        struct audit_aux_data_ipcctl *axi = (void *)aux;
-                                                       if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) {
+                                                       if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) {
                                                                ++result;
                                                                break;
                                                        }
@@ -885,11 +884,11 @@ void audit_log_task_context(struct audit_buffer *ab)
        int error;
        u32 sid;
 
-       selinux_get_task_sid(current, &sid);
+       security_task_getsecid(current, &sid);
        if (!sid)
                return;
 
-       error = selinux_sid_to_string(sid, &ctx, &len);
+       error = security_secid_to_secctx(sid, &ctx, &len);
        if (error) {
                if (error != -EINVAL)
                        goto error_path;
@@ -897,7 +896,7 @@ void audit_log_task_context(struct audit_buffer *ab)
        }
 
        audit_log_format(ab, " subj=%s", ctx);
-       kfree(ctx);
+       security_release_secctx(ctx, len);
        return;
 
 error_path:
@@ -941,7 +940,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
                                 u32 sid, char *comm)
 {
        struct audit_buffer *ab;
-       char *s = NULL;
+       char *ctx = NULL;
        u32 len;
        int rc = 0;
 
@@ -951,15 +950,16 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
 
        audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid,
                         uid, sessionid);
-       if (selinux_sid_to_string(sid, &s, &len)) {
+       if (security_secid_to_secctx(sid, &ctx, &len)) {
                audit_log_format(ab, " obj=(none)");
                rc = 1;
-       } else
-               audit_log_format(ab, " obj=%s", s);
+       } else {
+               audit_log_format(ab, " obj=%s", ctx);
+               security_release_secctx(ctx, len);
+       }
        audit_log_format(ab, " ocomm=");
        audit_log_untrustedstring(ab, comm);
        audit_log_end(ab);
-       kfree(s);
 
        return rc;
 }
@@ -1271,14 +1271,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        if (axi->osid != 0) {
                                char *ctx = NULL;
                                u32 len;
-                               if (selinux_sid_to_string(
+                               if (security_secid_to_secctx(
                                                axi->osid, &ctx, &len)) {
                                        audit_log_format(ab, " osid=%u",
                                                        axi->osid);
                                        call_panic = 1;
-                               } else
+                               } else {
                                        audit_log_format(ab, " obj=%s", ctx);
-                               kfree(ctx);
+                                       security_release_secctx(ctx, len);
+                               }
                        }
                        break; }
 
@@ -1392,13 +1393,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                if (n->osid != 0) {
                        char *ctx = NULL;
                        u32 len;
-                       if (selinux_sid_to_string(
+                       if (security_secid_to_secctx(
                                n->osid, &ctx, &len)) {
                                audit_log_format(ab, " osid=%u", n->osid);
                                call_panic = 2;
-                       } else
+                       } else {
                                audit_log_format(ab, " obj=%s", ctx);
-                       kfree(ctx);
+                               security_release_secctx(ctx, len);
+                       }
                }
 
                audit_log_end(ab);
@@ -1775,7 +1777,7 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
        name->uid   = inode->i_uid;
        name->gid   = inode->i_gid;
        name->rdev  = inode->i_rdev;
-       selinux_get_inode_sid(inode, &name->osid);
+       security_inode_getsecid(inode, &name->osid);
 }
 
 /**
@@ -2190,8 +2192,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
        ax->uid = ipcp->uid;
        ax->gid = ipcp->gid;
        ax->mode = ipcp->mode;
-       selinux_get_ipc_sid(ipcp, &ax->osid);
-
+       security_ipc_getsecid(ipcp, &ax->osid);
        ax->d.type = AUDIT_IPC;
        ax->d.next = context->aux;
        context->aux = (void *)ax;
@@ -2343,7 +2344,7 @@ void __audit_ptrace(struct task_struct *t)
        context->target_auid = audit_get_loginuid(t);
        context->target_uid = t->uid;
        context->target_sessionid = audit_get_sessionid(t);
-       selinux_get_task_sid(t, &context->target_sid);
+       security_task_getsecid(t, &context->target_sid);
        memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
 }
 
@@ -2371,7 +2372,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
                                audit_sig_uid = tsk->loginuid;
                        else
                                audit_sig_uid = tsk->uid;
-                       selinux_get_task_sid(tsk, &audit_sig_sid);
+                       security_task_getsecid(tsk, &audit_sig_sid);
                }
                if (!audit_signals || audit_dummy_context())
                        return 0;
@@ -2384,7 +2385,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
                ctx->target_auid = audit_get_loginuid(t);
                ctx->target_uid = t->uid;
                ctx->target_sessionid = audit_get_sessionid(t);
-               selinux_get_task_sid(t, &ctx->target_sid);
+               security_task_getsecid(t, &ctx->target_sid);
                memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
                return 0;
        }
@@ -2405,7 +2406,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
        axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
        axp->target_uid[axp->pid_count] = t->uid;
        axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
-       selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
+       security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
        memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
        axp->pid_count++;
 
@@ -2435,16 +2436,17 @@ void audit_core_dumps(long signr)
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
        audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
                        auid, current->uid, current->gid, sessionid);
-       selinux_get_task_sid(current, &sid);
+       security_task_getsecid(current, &sid);
        if (sid) {
                char *ctx = NULL;
                u32 len;
 
-               if (selinux_sid_to_string(sid, &ctx, &len))
+               if (security_secid_to_secctx(sid, &ctx, &len))
                        audit_log_format(ab, " ssid=%u", sid);
-               else
+               else {
                        audit_log_format(ab, " subj=%s", ctx);
-               kfree(ctx);
+                       security_release_secctx(ctx, len);
+               }
        }
        audit_log_format(ab, " pid=%d comm=", current->pid);
        audit_log_untrustedstring(ab, current->comm);
index 36f75d8..46f3e44 100644 (file)
@@ -54,7 +54,6 @@
 #include <linux/mm.h>
 #include <linux/types.h>
 #include <linux/audit.h>
-#include <linux/selinux.h>
 #include <linux/mutex.h>
 
 #include <net/net_namespace.h>
@@ -1249,7 +1248,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
        NETLINK_CB(skb).pid     = nlk->pid;
        NETLINK_CB(skb).dst_group = dst_group;
        NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
-       selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
+       security_task_getsecid(current, &(NETLINK_CB(skb).sid));
        memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
        /* What can I do? Netlink is asynchronous, so that
index 480366f..98d5f96 100644 (file)
@@ -424,6 +424,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
        return 0;
 }
 
+static void dummy_inode_getsecid(const struct inode *inode, u32 *secid)
+{
+       *secid = 0;
+}
+
 static int dummy_file_permission (struct file *file, int mask)
 {
        return 0;
@@ -542,7 +547,9 @@ static int dummy_task_getsid (struct task_struct *p)
 }
 
 static void dummy_task_getsecid (struct task_struct *p, u32 *secid)
-{ }
+{
+       *secid = 0;
+}
 
 static int dummy_task_setgroups (struct group_info *group_info)
 {
@@ -616,6 +623,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
        return 0;
 }
 
+static void dummy_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+{
+       *secid = 0;
+}
+
 static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
 {
        return 0;
@@ -983,7 +995,33 @@ static inline int dummy_key_permission(key_ref_t key_ref,
 }
 #endif /* CONFIG_KEYS */
 
-struct security_operations dummy_security_ops;
+#ifdef CONFIG_AUDIT
+static inline int dummy_audit_rule_init(u32 field, u32 op, char *rulestr,
+                                       void **lsmrule)
+{
+       return 0;
+}
+
+static inline int dummy_audit_rule_known(struct audit_krule *krule)
+{
+       return 0;
+}
+
+static inline int dummy_audit_rule_match(u32 secid, u32 field, u32 op,
+                                        void *lsmrule,
+                                        struct audit_context *actx)
+{
+       return 0;
+}
+
+static inline void dummy_audit_rule_free(void *lsmrule)
+{ }
+
+#endif /* CONFIG_AUDIT */
+
+struct security_operations dummy_security_ops = {
+       .name = "dummy",
+};
 
 #define set_to_dummy_if_null(ops, function)                            \
        do {                                                            \
@@ -1060,6 +1098,7 @@ void security_fixup_ops (struct security_operations *ops)
        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_getsecid);
        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);
@@ -1096,6 +1135,7 @@ void security_fixup_ops (struct security_operations *ops)
        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_getsecid);
        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);
@@ -1170,6 +1210,11 @@ void security_fixup_ops (struct security_operations *ops)
        set_to_dummy_if_null(ops, key_free);
        set_to_dummy_if_null(ops, key_permission);
 #endif /* CONFIG_KEYS */
-
+#ifdef CONFIG_AUDIT
+       set_to_dummy_if_null(ops, audit_rule_init);
+       set_to_dummy_if_null(ops, audit_rule_known);
+       set_to_dummy_if_null(ops, audit_rule_match);
+       set_to_dummy_if_null(ops, audit_rule_free);
+#endif
 }
 
index 54affd0..2e250c7 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/kernel.h>
 #include <linux/security.h>
 
+/* Boot-time LSM user choice */
+static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
 
 /* things that live in dummy.c */
 extern struct security_operations dummy_security_ops;
@@ -67,13 +69,47 @@ int __init security_init(void)
        return 0;
 }
 
+/* Save user chosen LSM */
+static int __init choose_lsm(char *str)
+{
+       strncpy(chosen_lsm, str, SECURITY_NAME_MAX);
+       return 1;
+}
+__setup("security=", choose_lsm);
+
+/**
+ * security_module_enable - Load given security module on boot ?
+ * @ops: a pointer to the struct security_operations that is to be checked.
+ *
+ * Each LSM must pass this method before registering its own operations
+ * to avoid security registration races. This method may also be used
+ * to check if your LSM is currently loaded during kernel initialization.
+ *
+ * Return true if:
+ *     -The passed LSM is the one chosen by user at boot time,
+ *     -or user didsn't specify a specific LSM and we're the first to ask
+ *      for registeration permissoin,
+ *     -or the passed LSM is currently loaded.
+ * Otherwise, return false.
+ */
+int __init security_module_enable(struct security_operations *ops)
+{
+       if (!*chosen_lsm)
+               strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX);
+       else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX))
+               return 0;
+
+       return 1;
+}
+
 /**
  * register_security - registers a security framework with the kernel
  * @ops: a pointer to the struct security_options that is to be registered
  *
  * This function is to allow a security module to register itself with the
  * kernel security subsystem.  Some rudimentary checking is done on the @ops
- * value passed to this function.
+ * value passed to this function. You'll need to check first if your LSM
+ * is allowed to register its @ops by calling security_module_enable(@ops).
  *
  * If there is already a security module registered with the kernel,
  * an error will be returned.  Otherwise 0 is returned on success.
@@ -523,6 +559,11 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
        return security_ops->inode_listsecurity(inode, buffer, buffer_size);
 }
 
+void security_inode_getsecid(const struct inode *inode, u32 *secid)
+{
+       security_ops->inode_getsecid(inode, secid);
+}
+
 int security_file_permission(struct file *file, int mask)
 {
        return security_ops->file_permission(file, mask);
@@ -712,6 +753,11 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
        return security_ops->ipc_permission(ipcp, flag);
 }
 
+void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+{
+       security_ops->ipc_getsecid(ipcp, secid);
+}
+
 int security_msg_msg_alloc(struct msg_msg *msg)
 {
        return security_ops->msg_msg_alloc_security(msg);
@@ -1111,3 +1157,28 @@ int security_key_permission(key_ref_t key_ref,
 }
 
 #endif /* CONFIG_KEYS */
+
+#ifdef CONFIG_AUDIT
+
+int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
+{
+       return security_ops->audit_rule_init(field, op, rulestr, lsmrule);
+}
+
+int security_audit_rule_known(struct audit_krule *krule)
+{
+       return security_ops->audit_rule_known(krule);
+}
+
+void security_audit_rule_free(void *lsmrule)
+{
+       security_ops->audit_rule_free(lsmrule);
+}
+
+int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
+                             struct audit_context *actx)
+{
+       return security_ops->audit_rule_match(secid, field, op, lsmrule, actx);
+}
+
+#endif /* CONFIG_AUDIT */
index 87d2bb3..64af2d3 100644 (file)
 /* SECMARK reference count */
 extern atomic_t selinux_secmark_refcount;
 
-int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
-{
-       if (selinux_enabled)
-               return security_sid_to_context(sid, 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;
-               return;
-       }
-       *sid = 0;
-}
-
-void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
-{
-       if (selinux_enabled) {
-               struct ipc_security_struct *isec = ipcp->security;
-               *sid = isec->sid;
-               return;
-       }
-       *sid = 0;
-}
-
-void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
-{
-       if (selinux_enabled) {
-               struct task_security_struct *tsec = tsk->security;
-               *sid = tsec->sid;
-               return;
-       }
-       *sid = 0;
-}
-
 int selinux_string_to_sid(char *str, u32 *sid)
 {
        if (selinux_enabled)
index 34f2d46..f9927f0 100644 (file)
@@ -83,6 +83,7 @@
 #include "netport.h"
 #include "xfrm.h"
 #include "netlabel.h"
+#include "audit.h"
 
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
@@ -2792,6 +2793,12 @@ static int selinux_inode_killpriv(struct dentry *dentry)
        return secondary_ops->inode_killpriv(dentry);
 }
 
+static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
+{
+       struct inode_security_struct *isec = inode->i_security;
+       *secid = isec->sid;
+}
+
 /* file security operations */
 
 static int selinux_revalidate_file_permission(struct file *file, int mask)
@@ -3183,7 +3190,8 @@ static int selinux_task_getsid(struct task_struct *p)
 
 static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
 {
-       selinux_get_task_sid(p, secid);
+       struct task_security_struct *tsec = p->security;
+       *secid = tsec->sid;
 }
 
 static int selinux_task_setgroups(struct group_info *group_info)
@@ -4149,7 +4157,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
                goto out;
 
        if (sock && family == PF_UNIX)
-               selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
+               selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
        else if (skb)
                selinux_skb_peerlbl_sid(skb, family, &peer_secid);
 
@@ -5026,6 +5034,12 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
        return ipc_has_perm(ipcp, av);
 }
 
+static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+{
+       struct ipc_security_struct *isec = ipcp->security;
+       *secid = isec->sid;
+}
+
 /* module stacking operations */
 static int selinux_register_security (const char *name, struct security_operations *ops)
 {
@@ -5281,6 +5295,8 @@ static int selinux_key_permission(key_ref_t key_ref,
 #endif
 
 static struct security_operations selinux_ops = {
+       .name =                         "selinux",
+
        .ptrace =                       selinux_ptrace,
        .capget =                       selinux_capget,
        .capset_check =                 selinux_capset_check,
@@ -5342,6 +5358,7 @@ static struct security_operations selinux_ops = {
        .inode_listsecurity =           selinux_inode_listsecurity,
        .inode_need_killpriv =          selinux_inode_need_killpriv,
        .inode_killpriv =               selinux_inode_killpriv,
+       .inode_getsecid =               selinux_inode_getsecid,
 
        .file_permission =              selinux_file_permission,
        .file_alloc_security =          selinux_file_alloc_security,
@@ -5382,6 +5399,7 @@ static struct security_operations selinux_ops = {
        .task_to_inode =                selinux_task_to_inode,
 
        .ipc_permission =               selinux_ipc_permission,
+       .ipc_getsecid =                 selinux_ipc_getsecid,
 
        .msg_msg_alloc_security =       selinux_msg_msg_alloc_security,
        .msg_msg_free_security =        selinux_msg_msg_free_security,
@@ -5463,12 +5481,24 @@ static struct security_operations selinux_ops = {
        .key_free =                     selinux_key_free,
        .key_permission =               selinux_key_permission,
 #endif
+
+#ifdef CONFIG_AUDIT
+       .audit_rule_init =              selinux_audit_rule_init,
+       .audit_rule_known =             selinux_audit_rule_known,
+       .audit_rule_match =             selinux_audit_rule_match,
+       .audit_rule_free =              selinux_audit_rule_free,
+#endif
 };
 
 static __init int selinux_init(void)
 {
        struct task_security_struct *tsec;
 
+       if (!security_module_enable(&selinux_ops)) {
+               selinux_enabled = 0;
+               return 0;
+       }
+
        if (!selinux_enabled) {
                printk(KERN_INFO "SELinux:  Disabled at boot.\n");
                return 0;
diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h
new file mode 100644 (file)
index 0000000..6c8b9ef
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SELinux support for the Audit LSM hooks
+ *
+ * Most of below header was moved from include/linux/selinux.h which 
+ * is released under below copyrights:
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef _SELINUX_AUDIT_H
+#define _SELINUX_AUDIT_H
+
+/**
+ *     selinux_audit_rule_init - alloc/init an selinux audit rule structure.
+ *     @field: the field this rule refers to
+ *     @op: the operater the rule uses
+ *     @rulestr: the text "target" of the rule
+ *     @rule: pointer to the new rule structure returned via this
+ *
+ *     Returns 0 if successful, -errno if not.  On success, the rule structure
+ *     will be allocated internally.  The caller must free this structure with
+ *     selinux_audit_rule_free() after use.
+ */
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule);
+
+/**
+ *     selinux_audit_rule_free - free an selinux audit rule structure.
+ *     @rule: pointer to the audit rule to be freed
+ *
+ *     This will free all memory associated with the given rule.
+ *     If @rule is NULL, no operation is performed.
+ */
+void selinux_audit_rule_free(void *rule);
+
+/**
+ *     selinux_audit_rule_match - determine if a context ID matches a rule.
+ *     @sid: the context ID to check
+ *     @field: the field this rule refers to
+ *     @op: the operater the rule uses
+ *     @rule: pointer to the audit rule to check against
+ *     @actx: the audit context (can be NULL) associated with the check
+ *
+ *     Returns 1 if the context id matches the rule, 0 if it does not, and
+ *     -errno on failure.
+ */
+int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
+                             struct audit_context *actx);
+
+/**
+ *     selinux_audit_rule_known - check to see if rule contains selinux fields.
+ *     @rule: rule to be checked
+ *     Returns 1 if there are selinux fields specified in the rule, 0 otherwise.
+ */
+int selinux_audit_rule_known(struct audit_krule *krule);
+
+#endif /* _SELINUX_AUDIT_H */
+
index 33425b1..b341b8f 100644 (file)
@@ -57,6 +57,7 @@
 #include "netlabel.h"
 #include "xfrm.h"
 #include "ebitmap.h"
+#include "audit.h"
 
 extern void selnl_notify_policyload(u32 seqno);
 unsigned int policydb_loaded_version;
@@ -2296,21 +2297,23 @@ struct selinux_audit_rule {
        struct context au_ctxt;
 };
 
-void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+void selinux_audit_rule_free(void *vrule)
 {
+       struct selinux_audit_rule *rule = vrule;
+
        if (rule) {
                context_destroy(&rule->au_ctxt);
                kfree(rule);
        }
 }
 
-int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
-                            struct selinux_audit_rule **rule)
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 {
        struct selinux_audit_rule *tmprule;
        struct role_datum *roledatum;
        struct type_datum *typedatum;
        struct user_datum *userdatum;
+       struct selinux_audit_rule **rule = (struct selinux_audit_rule **)vrule;
        int rc = 0;
 
        *rule = NULL;
@@ -2397,12 +2400,37 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
        return rc;
 }
 
-int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
-                             struct selinux_audit_rule *rule,
+/* Check to see if the rule contains any selinux fields */
+int selinux_audit_rule_known(struct audit_krule *rule)
+{
+       int i;
+
+       for (i = 0; i < rule->field_count; i++) {
+               struct audit_field *f = &rule->fields[i];
+               switch (f->type) {
+               case AUDIT_SUBJ_USER:
+               case AUDIT_SUBJ_ROLE:
+               case AUDIT_SUBJ_TYPE:
+               case AUDIT_SUBJ_SEN:
+               case AUDIT_SUBJ_CLR:
+               case AUDIT_OBJ_USER:
+               case AUDIT_OBJ_ROLE:
+               case AUDIT_OBJ_TYPE:
+               case AUDIT_OBJ_LEV_LOW:
+               case AUDIT_OBJ_LEV_HIGH:
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
                              struct audit_context *actx)
 {
        struct context *ctxt;
        struct mls_level *level;
+       struct selinux_audit_rule *rule = vrule;
        int match = 0;
 
        if (!rule) {
@@ -2509,7 +2537,7 @@ out:
        return match;
 }
 
-static int (*aurule_callback)(void) = NULL;
+static int (*aurule_callback)(void) = audit_update_lsm_rules;
 
 static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
                                u16 class, u32 perms, u32 *retained)
@@ -2534,11 +2562,6 @@ static int __init aurule_init(void)
 }
 __initcall(aurule_init);
 
-void selinux_audit_set_callback(int (*callback)(void))
-{
-       aurule_callback = callback;
-}
-
 #ifdef CONFIG_NETLABEL
 /**
  * security_netlbl_cache_add - Add an entry to the NetLabel cache
index 62c1e98..4a4477f 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/capability.h>
 #include <linux/spinlock.h>
+#include <linux/security.h>
 #include <net/netlabel.h>
 
 /*
@@ -187,6 +188,7 @@ extern struct smack_known smack_known_star;
 extern struct smack_known smack_known_unset;
 
 extern struct smk_list_entry *smack_list;
+extern struct security_operations smack_ops;
 
 /*
  * Stricly for CIPSO level manipulation.
index e2d6f7c..93f5b0c 100644 (file)
@@ -2424,7 +2424,9 @@ static void smack_release_secctx(char *secdata, u32 seclen)
 {
 }
 
-static struct security_operations smack_ops = {
+struct security_operations smack_ops = {
+       .name =                         "smack",
+
        .ptrace =                       smack_ptrace,
        .capget =                       cap_capget,
        .capset_check =                 cap_capset_check,
@@ -2557,6 +2559,9 @@ static struct security_operations smack_ops = {
  */
 static __init int smack_init(void)
 {
+       if (!security_module_enable(&smack_ops))
+               return 0;
+
        printk(KERN_INFO "Smack:  Initializing.\n");
 
        /*
index cfae8af..6ba2837 100644 (file)
@@ -965,12 +965,21 @@ static struct vfsmount *smackfs_mount;
  *
  * register the smackfs
  *
- * Returns 0 unless the registration fails.
+ * Do not register smackfs if Smack wasn't enabled
+ * on boot. We can not put this method normally under the
+ * smack_init() code path since the security subsystem get
+ * initialized before the vfs caches.
+ *
+ * Returns true if we were not chosen on boot or if
+ * we were chosen and filesystem registration succeeded.
  */
 static int __init init_smk_fs(void)
 {
        int err;
 
+       if (!security_module_enable(&smack_ops))
+               return 0;
+
        err = register_filesystem(&smk_fs_type);
        if (!err) {
                smackfs_mount = kern_mount(&smk_fs_type);