Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / security / selinux / selinuxfs.c
index f5d7836..00534c3 100644 (file)
@@ -9,7 +9,6 @@
  *     the Free Software Foundation, version 2.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
@@ -22,6 +21,7 @@
 #include <linux/major.h>
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
+#include <linux/audit.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
+#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+#define SELINUX_COMPAT_NET_VALUE 0
+#else
+#define SELINUX_COMPAT_NET_VALUE 1
+#endif
+
+int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
+
 static int __init checkreqprot_setup(char *str)
 {
        selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
@@ -44,6 +52,13 @@ static int __init checkreqprot_setup(char *str)
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
+static int __init selinux_compat_net_setup(char *str)
+{
+       selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
+       return 1;
+}
+__setup("selinux_compat_net=", selinux_compat_net_setup);
+
 
 static DEFINE_MUTEX(sel_mutex);
 
@@ -84,6 +99,7 @@ enum sel_inos {
        SEL_AVC,        /* AVC management directory */
        SEL_MEMBER,     /* compute polyinstantiation membership decision */
        SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
+       SEL_COMPAT_NET, /* whether to use old compat network packet controls */
 };
 
 #define TMPBUFLEN      12
@@ -127,6 +143,10 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
                length = task_has_security(current, SECURITY__SETENFORCE);
                if (length)
                        goto out;
+               audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+                       "enforcing=%d old_enforcing=%d auid=%u", new_value, 
+                       selinux_enforcing,
+                       audit_get_loginuid(current->audit_context));
                selinux_enforcing = new_value;
                if (selinux_enforcing)
                        avc_ss_reset(0);
@@ -177,6 +197,9 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
                length = selinux_disable();
                if (length < 0)
                        goto out;
+               audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
+                       "selinux=0 auid=%u",
+                       audit_get_loginuid(current->audit_context));
        }
 
        length = count;
@@ -262,6 +285,9 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
                length = ret;
        else
                length = count;
+       audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
+               "policy loaded auid=%u",
+               audit_get_loginuid(current->audit_context));
 out:
        mutex_unlock(&sel_mutex);
        vfree(data);
@@ -353,6 +379,55 @@ static struct file_operations sel_checkreqprot_ops = {
        .write          = sel_write_checkreqprot,
 };
 
+static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
+                                  size_t count, loff_t *ppos)
+{
+       char tmpbuf[TMPBUFLEN];
+       ssize_t length;
+
+       length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
+       return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
+                                   size_t count, loff_t *ppos)
+{
+       char *page;
+       ssize_t length;
+       int new_value;
+
+       length = task_has_security(current, SECURITY__LOAD_POLICY);
+       if (length)
+               return length;
+
+       if (count >= PAGE_SIZE)
+               return -ENOMEM;
+       if (*ppos != 0) {
+               /* No partial writes. */
+               return -EINVAL;
+       }
+       page = (char*)get_zeroed_page(GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
+       length = -EFAULT;
+       if (copy_from_user(page, buf, count))
+               goto out;
+
+       length = -EINVAL;
+       if (sscanf(page, "%d", &new_value) != 1)
+               goto out;
+
+       selinux_compat_net = new_value ? 1 : 0;
+       length = count;
+out:
+       free_page((unsigned long) page);
+       return length;
+}
+static struct file_operations sel_compat_net_ops = {
+       .read           = sel_read_compat_net,
+       .write          = sel_write_compat_net,
+};
+
 /*
  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
  */
@@ -1208,6 +1283,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
                [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
                [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
                [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
+               [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
                /* last one */ {""}
        };
        ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
@@ -1268,10 +1344,11 @@ err:
        goto out;
 }
 
-static struct super_block *sel_get_sb(struct file_system_type *fs_type,
-                                     int flags, const char *dev_name, void *data)
+static int sel_get_sb(struct file_system_type *fs_type,
+                     int flags, const char *dev_name, void *data,
+                     struct vfsmount *mnt)
 {
-       return get_sb_single(fs_type, flags, data, sel_fill_super);
+       return get_sb_single(fs_type, flags, data, sel_fill_super, mnt);
 }
 
 static struct file_system_type sel_fs_type = {