Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[pandora-kernel.git] / security / selinux / hooks.c
index 9a2ee84..5c9f25b 100644 (file)
@@ -76,6 +76,7 @@
 #include <linux/selinux.h>
 #include <linux/mutex.h>
 #include <linux/posix-timers.h>
+#include <linux/syslog.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -125,18 +126,6 @@ __setup("selinux=", selinux_enabled_setup);
 int selinux_enabled = 1;
 #endif
 
-
-/*
- * Minimal support for a secondary security module,
- * just to allow the use of the capability module.
- */
-static struct security_operations *secondary_ops;
-
-/* Lists of inode and superblock security structures initialized
-   before the policy was loaded. */
-static LIST_HEAD(superblock_security_head);
-static DEFINE_SPINLOCK(sb_security_lock);
-
 static struct kmem_cache *sel_inode_cache;
 
 /**
@@ -272,7 +261,6 @@ static int superblock_alloc_security(struct super_block *sb)
                return -ENOMEM;
 
        mutex_init(&sbsec->lock);
-       INIT_LIST_HEAD(&sbsec->list);
        INIT_LIST_HEAD(&sbsec->isec_head);
        spin_lock_init(&sbsec->isec_lock);
        sbsec->sb = sb;
@@ -287,40 +275,34 @@ static int superblock_alloc_security(struct super_block *sb)
 static void superblock_free_security(struct super_block *sb)
 {
        struct superblock_security_struct *sbsec = sb->s_security;
-
-       spin_lock(&sb_security_lock);
-       if (!list_empty(&sbsec->list))
-               list_del_init(&sbsec->list);
-       spin_unlock(&sb_security_lock);
-
        sb->s_security = NULL;
        kfree(sbsec);
 }
 
 static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
 {
-       struct sk_security_struct *ssec;
+       struct sk_security_struct *sksec;
 
-       ssec = kzalloc(sizeof(*ssec), priority);
-       if (!ssec)
+       sksec = kzalloc(sizeof(*sksec), priority);
+       if (!sksec)
                return -ENOMEM;
 
-       ssec->peer_sid = SECINITSID_UNLABELED;
-       ssec->sid = SECINITSID_UNLABELED;
-       sk->sk_security = ssec;
+       sksec->peer_sid = SECINITSID_UNLABELED;
+       sksec->sid = SECINITSID_UNLABELED;
+       sk->sk_security = sksec;
 
-       selinux_netlbl_sk_security_reset(ssec);
+       selinux_netlbl_sk_security_reset(sksec);
 
        return 0;
 }
 
 static void sk_free_security(struct sock *sk)
 {
-       struct sk_security_struct *ssec = sk->sk_security;
+       struct sk_security_struct *sksec = sk->sk_security;
 
        sk->sk_security = NULL;
-       selinux_netlbl_sk_security_free(ssec);
-       kfree(ssec);
+       selinux_netlbl_sk_security_free(sksec);
+       kfree(sksec);
 }
 
 /* The security server must be initialized before
@@ -329,7 +311,7 @@ extern int ss_initialized;
 
 /* The file system's label must be initialized prior to use. */
 
-static char *labeling_behaviors[6] = {
+static const char *labeling_behaviors[6] = {
        "uses xattr",
        "uses transition SIDs",
        "uses task SIDs",
@@ -618,10 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                        /* Defer initialization until selinux_complete_init,
                           after the initial policy is loaded and the security
                           server is ready to handle calls. */
-                       spin_lock(&sb_security_lock);
-                       if (list_empty(&sbsec->list))
-                               list_add(&sbsec->list, &superblock_security_head);
-                       spin_unlock(&sb_security_lock);
                        goto out;
                }
                rc = -EINVAL;
@@ -812,16 +790,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 
        /*
         * if the parent was able to be mounted it clearly had no special lsm
-        * mount options.  thus we can safely put this sb on the list and deal
-        * with it later
+        * mount options.  thus we can safely deal with this superblock later
         */
-       if (!ss_initialized) {
-               spin_lock(&sb_security_lock);
-               if (list_empty(&newsbsec->list))
-                       list_add(&newsbsec->list, &superblock_security_head);
-               spin_unlock(&sb_security_lock);
+       if (!ss_initialized)
                return;
-       }
 
        /* how can we clone if the old one wasn't set up?? */
        BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
@@ -2049,29 +2021,30 @@ static int selinux_quota_on(struct dentry *dentry)
        return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
 }
 
-static int selinux_syslog(int type)
+static int selinux_syslog(int type, bool from_file)
 {
        int rc;
 
-       rc = cap_syslog(type);
+       rc = cap_syslog(type, from_file);
        if (rc)
                return rc;
 
        switch (type) {
-       case 3:         /* Read last kernel messages */
-       case 10:        /* Return size of the log buffer */
+       case SYSLOG_ACTION_READ_ALL:    /* Read last kernel messages */
+       case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
                rc = task_has_system(current, SYSTEM__SYSLOG_READ);
                break;
-       case 6:         /* Disable logging to console */
-       case 7:         /* Enable logging to console */
-       case 8:         /* Set level of messages printed to console */
+       case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
+       case SYSLOG_ACTION_CONSOLE_ON:  /* Enable logging to console */
+       /* Set level of messages printed to console */
+       case SYSLOG_ACTION_CONSOLE_LEVEL:
                rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
                break;
-       case 0:         /* Close log */
-       case 1:         /* Open log */
-       case 2:         /* Read from log */
-       case 4:         /* Read/clear last kernel messages */
-       case 5:         /* Clear ring buffer */
+       case SYSLOG_ACTION_CLOSE:       /* Close log */
+       case SYSLOG_ACTION_OPEN:        /* Open log */
+       case SYSLOG_ACTION_READ:        /* Read from log */
+       case SYSLOG_ACTION_READ_CLEAR:  /* Read/clear last kernel messages */
+       case SYSLOG_ACTION_CLEAR:       /* Clear ring buffer */
        default:
                rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
                break;
@@ -3004,13 +2977,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
        return file_has_perm(cred, file, av);
 }
 
+static int default_noexec;
+
 static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
 {
        const struct cred *cred = current_cred();
        int rc = 0;
 
-#ifndef CONFIG_PPC32
-       if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
+       if (default_noexec &&
+           (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
                /*
                 * We are making executable an anonymous mapping or a
                 * private file mapping that will also be writable.
@@ -3020,7 +2995,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
                if (rc)
                        goto error;
        }
-#endif
 
        if (file) {
                /* read access is always possible with a mapping */
@@ -3081,8 +3055,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
        if (selinux_checkreqprot)
                prot = reqprot;
 
-#ifndef CONFIG_PPC32
-       if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
+       if (default_noexec &&
+           (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
                int rc = 0;
                if (vma->vm_start >= vma->vm_mm->start_brk &&
                    vma->vm_end <= vma->vm_mm->brk) {
@@ -3104,7 +3078,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
                if (rc)
                        return rc;
        }
-#endif
 
        return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
 }
@@ -3334,7 +3307,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
 
        if (ret == 0)
                tsec->create_sid = isec->sid;
-       return 0;
+       return ret;
 }
 
 static int selinux_kernel_module_request(char *kmod_name)
@@ -4007,7 +3980,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
                                              struct socket *other,
                                              struct sock *newsk)
 {
-       struct sk_security_struct *ssec;
+       struct sk_security_struct *sksec;
        struct inode_security_struct *isec;
        struct inode_security_struct *other_isec;
        struct common_audit_data ad;
@@ -4026,13 +3999,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
                return err;
 
        /* connecting socket */
-       ssec = sock->sk->sk_security;
-       ssec->peer_sid = other_isec->sid;
+       sksec = sock->sk->sk_security;
+       sksec->peer_sid = other_isec->sid;
 
        /* server child socket */
-       ssec = newsk->sk_security;
-       ssec->peer_sid = isec->sid;
-       err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
+       sksec = newsk->sk_security;
+       sksec->peer_sid = isec->sid;
+       err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid);
 
        return err;
 }
@@ -4195,7 +4168,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
        int err = 0;
        char *scontext;
        u32 scontext_len;
-       struct sk_security_struct *ssec;
+       struct sk_security_struct *sksec;
        struct inode_security_struct *isec;
        u32 peer_sid = SECSID_NULL;
 
@@ -4203,8 +4176,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
 
        if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
            isec->sclass == SECCLASS_TCP_SOCKET) {
-               ssec = sock->sk->sk_security;
-               peer_sid = ssec->peer_sid;
+               sksec = sock->sk->sk_security;
+               peer_sid = sksec->peer_sid;
        }
        if (peer_sid == SECSID_NULL) {
                err = -ENOPROTOOPT;
@@ -4271,14 +4244,14 @@ static void selinux_sk_free_security(struct sock *sk)
 
 static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
 {
-       struct sk_security_struct *ssec = sk->sk_security;
-       struct sk_security_struct *newssec = newsk->sk_security;
+       struct sk_security_struct *sksec = sk->sk_security;
+       struct sk_security_struct *newsksec = newsk->sk_security;
 
-       newssec->sid = ssec->sid;
-       newssec->peer_sid = ssec->peer_sid;
-       newssec->sclass = ssec->sclass;
+       newsksec->sid = sksec->sid;
+       newsksec->peer_sid = sksec->peer_sid;
+       newsksec->sclass = sksec->sclass;
 
-       selinux_netlbl_sk_security_reset(newssec);
+       selinux_netlbl_sk_security_reset(newsksec);
 }
 
 static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -5667,14 +5640,13 @@ static __init int selinux_init(void)
        /* Set the security state for the initial task. */
        cred_init_security();
 
+       default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
+
        sel_inode_cache = kmem_cache_create("selinux_inode_security",
                                            sizeof(struct inode_security_struct),
                                            0, SLAB_PANIC, NULL);
        avc_init();
 
-       secondary_ops = security_ops;
-       if (!secondary_ops)
-               panic("SELinux: No initial security operations\n");
        if (register_security(&selinux_ops))
                panic("SELinux: Unable to register with kernel.\n");
 
@@ -5686,35 +5658,18 @@ static __init int selinux_init(void)
        return 0;
 }
 
+static void delayed_superblock_init(struct super_block *sb, void *unused)
+{
+       superblock_doinit(sb, NULL);
+}
+
 void selinux_complete_init(void)
 {
        printk(KERN_DEBUG "SELinux:  Completing initialization.\n");
 
        /* Set up any superblocks initialized prior to the policy load. */
        printk(KERN_DEBUG "SELinux:  Setting up existing superblocks.\n");
-       spin_lock(&sb_lock);
-       spin_lock(&sb_security_lock);
-next_sb:
-       if (!list_empty(&superblock_security_head)) {
-               struct superblock_security_struct *sbsec =
-                               list_entry(superblock_security_head.next,
-                                          struct superblock_security_struct,
-                                          list);
-               struct super_block *sb = sbsec->sb;
-               sb->s_count++;
-               spin_unlock(&sb_security_lock);
-               spin_unlock(&sb_lock);
-               down_read(&sb->s_umount);
-               if (sb->s_root)
-                       superblock_doinit(sb, NULL);
-               drop_super(sb);
-               spin_lock(&sb_lock);
-               spin_lock(&sb_security_lock);
-               list_del_init(&sbsec->list);
-               goto next_sb;
-       }
-       spin_unlock(&sb_security_lock);
-       spin_unlock(&sb_lock);
+       iterate_supers(delayed_superblock_init, NULL);
 }
 
 /* SELinux requires early initialization in order to label
@@ -5835,8 +5790,7 @@ int selinux_disable(void)
        selinux_disabled = 1;
        selinux_enabled = 0;
 
-       /* Reset security_ops to the secondary module, dummy or capability. */
-       security_ops = secondary_ops;
+       reset_security_ops();
 
        /* Try to destroy the avc node cache */
        avc_disable();