aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c244
-rw-r--r--security/selinux/include/audit.h4
-rw-r--r--security/selinux/include/avc.h15
-rw-r--r--security/selinux/include/objsec.h1
-rw-r--r--security/selinux/include/security.h7
-rw-r--r--security/selinux/netnode.c1
-rw-r--r--security/selinux/netport.c3
-rw-r--r--security/selinux/selinuxfs.c15
-rw-r--r--security/selinux/ss/avtab.c2
-rw-r--r--security/selinux/ss/context.h27
-rw-r--r--security/selinux/ss/mls.c19
-rw-r--r--security/selinux/ss/mls.h3
-rw-r--r--security/selinux/ss/policydb.c15
-rw-r--r--security/selinux/ss/services.c450
-rw-r--r--security/selinux/ss/sidtab.c76
-rw-r--r--security/selinux/ss/sidtab.h7
16 files changed, 530 insertions, 359 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1c864c0efe2b..91200feb3f9c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -9,7 +9,8 @@
9 * James Morris <jmorris@redhat.com> 9 * James Morris <jmorris@redhat.com>
10 * 10 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc. 11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 12 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 14 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com> 15 * <dgoeddel@trustedcs.com>
15 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. 16 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
@@ -42,9 +43,7 @@
42#include <linux/fdtable.h> 43#include <linux/fdtable.h>
43#include <linux/namei.h> 44#include <linux/namei.h>
44#include <linux/mount.h> 45#include <linux/mount.h>
45#include <linux/ext2_fs.h>
46#include <linux/proc_fs.h> 46#include <linux/proc_fs.h>
47#include <linux/kd.h>
48#include <linux/netfilter_ipv4.h> 47#include <linux/netfilter_ipv4.h>
49#include <linux/netfilter_ipv6.h> 48#include <linux/netfilter_ipv6.h>
50#include <linux/tty.h> 49#include <linux/tty.h>
@@ -53,7 +52,7 @@
53#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ 52#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
54#include <net/net_namespace.h> 53#include <net/net_namespace.h>
55#include <net/netlabel.h> 54#include <net/netlabel.h>
56#include <asm/uaccess.h> 55#include <linux/uaccess.h>
57#include <asm/ioctls.h> 56#include <asm/ioctls.h>
58#include <asm/atomic.h> 57#include <asm/atomic.h>
59#include <linux/bitops.h> 58#include <linux/bitops.h>
@@ -104,7 +103,9 @@ int selinux_enforcing;
104 103
105static int __init enforcing_setup(char *str) 104static int __init enforcing_setup(char *str)
106{ 105{
107 selinux_enforcing = simple_strtol(str, NULL, 0); 106 unsigned long enforcing;
107 if (!strict_strtoul(str, 0, &enforcing))
108 selinux_enforcing = enforcing ? 1 : 0;
108 return 1; 109 return 1;
109} 110}
110__setup("enforcing=", enforcing_setup); 111__setup("enforcing=", enforcing_setup);
@@ -115,7 +116,9 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
115 116
116static int __init selinux_enabled_setup(char *str) 117static int __init selinux_enabled_setup(char *str)
117{ 118{
118 selinux_enabled = simple_strtol(str, NULL, 0); 119 unsigned long enabled;
120 if (!strict_strtoul(str, 0, &enabled))
121 selinux_enabled = enabled ? 1 : 0;
119 return 1; 122 return 1;
120} 123}
121__setup("selinux=", selinux_enabled_setup); 124__setup("selinux=", selinux_enabled_setup);
@@ -123,13 +126,11 @@ __setup("selinux=", selinux_enabled_setup);
123int selinux_enabled = 1; 126int selinux_enabled = 1;
124#endif 127#endif
125 128
126/* Original (dummy) security module. */
127static struct security_operations *original_ops;
128 129
129/* Minimal support for a secondary security module, 130/*
130 just to allow the use of the dummy or capability modules. 131 * Minimal support for a secondary security module,
131 The owlsm module can alternatively be used as a secondary 132 * just to allow the use of the capability module.
132 module as long as CONFIG_OWLSM_FD is not enabled. */ 133 */
133static struct security_operations *secondary_ops; 134static struct security_operations *secondary_ops;
134 135
135/* Lists of inode and superblock security structures initialized 136/* Lists of inode and superblock security structures initialized
@@ -554,13 +555,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
554 struct task_security_struct *tsec = current->security; 555 struct task_security_struct *tsec = current->security;
555 struct superblock_security_struct *sbsec = sb->s_security; 556 struct superblock_security_struct *sbsec = sb->s_security;
556 const char *name = sb->s_type->name; 557 const char *name = sb->s_type->name;
557 struct inode *inode = sbsec->sb->s_root->d_inode; 558 struct dentry *root = sb->s_root;
558 struct inode_security_struct *root_isec = inode->i_security; 559 struct inode *root_inode = root->d_inode;
560 struct inode_security_struct *root_isec = root_inode->i_security;
559 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 561 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
560 u32 defcontext_sid = 0; 562 u32 defcontext_sid = 0;
561 char **mount_options = opts->mnt_opts; 563 char **mount_options = opts->mnt_opts;
562 int *flags = opts->mnt_opts_flags; 564 int *flags = opts->mnt_opts_flags;
563 int num_opts = opts->num_mnt_opts; 565 int num_opts = opts->num_mnt_opts;
566 bool can_xattr = false;
564 567
565 mutex_lock(&sbsec->lock); 568 mutex_lock(&sbsec->lock);
566 569
@@ -594,7 +597,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
594 */ 597 */
595 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) 598 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
596 && (num_opts == 0)) 599 && (num_opts == 0))
597 goto out; 600 goto out;
598 601
599 /* 602 /*
600 * parse the mount options, check if they are valid sids. 603 * parse the mount options, check if they are valid sids.
@@ -664,14 +667,24 @@ static int selinux_set_mnt_opts(struct super_block *sb,
664 goto out; 667 goto out;
665 } 668 }
666 669
667 if (strcmp(sb->s_type->name, "proc") == 0) 670 if (strcmp(name, "proc") == 0)
668 sbsec->proc = 1; 671 sbsec->proc = 1;
669 672
673 /*
674 * test if the fs supports xattrs, fs_use might make use of this if the
675 * fs has no definition in policy.
676 */
677 if (root_inode->i_op->getxattr) {
678 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
679 if (rc >= 0 || rc == -ENODATA)
680 can_xattr = true;
681 }
682
670 /* Determine the labeling behavior to use for this filesystem type. */ 683 /* Determine the labeling behavior to use for this filesystem type. */
671 rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid); 684 rc = security_fs_use(name, &sbsec->behavior, &sbsec->sid, can_xattr);
672 if (rc) { 685 if (rc) {
673 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", 686 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
674 __func__, sb->s_type->name, rc); 687 __func__, name, rc);
675 goto out; 688 goto out;
676 } 689 }
677 690
@@ -956,6 +969,57 @@ out_err:
956 return rc; 969 return rc;
957} 970}
958 971
972void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts)
973{
974 int i;
975 char *prefix;
976
977 for (i = 0; i < opts->num_mnt_opts; i++) {
978 char *has_comma = strchr(opts->mnt_opts[i], ',');
979
980 switch (opts->mnt_opts_flags[i]) {
981 case CONTEXT_MNT:
982 prefix = CONTEXT_STR;
983 break;
984 case FSCONTEXT_MNT:
985 prefix = FSCONTEXT_STR;
986 break;
987 case ROOTCONTEXT_MNT:
988 prefix = ROOTCONTEXT_STR;
989 break;
990 case DEFCONTEXT_MNT:
991 prefix = DEFCONTEXT_STR;
992 break;
993 default:
994 BUG();
995 };
996 /* we need a comma before each option */
997 seq_putc(m, ',');
998 seq_puts(m, prefix);
999 if (has_comma)
1000 seq_putc(m, '\"');
1001 seq_puts(m, opts->mnt_opts[i]);
1002 if (has_comma)
1003 seq_putc(m, '\"');
1004 }
1005}
1006
1007static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1008{
1009 struct security_mnt_opts opts;
1010 int rc;
1011
1012 rc = selinux_get_mnt_opts(sb, &opts);
1013 if (rc)
1014 return rc;
1015
1016 selinux_write_opts(m, &opts);
1017
1018 security_free_mnt_opts(&opts);
1019
1020 return rc;
1021}
1022
959static inline u16 inode_mode_to_security_class(umode_t mode) 1023static inline u16 inode_mode_to_security_class(umode_t mode)
960{ 1024{
961 switch (mode & S_IFMT) { 1025 switch (mode & S_IFMT) {
@@ -1682,14 +1746,23 @@ static inline u32 file_to_av(struct file *file)
1682 1746
1683/* Hook functions begin here. */ 1747/* Hook functions begin here. */
1684 1748
1685static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) 1749static int selinux_ptrace(struct task_struct *parent,
1750 struct task_struct *child,
1751 unsigned int mode)
1686{ 1752{
1687 int rc; 1753 int rc;
1688 1754
1689 rc = secondary_ops->ptrace(parent, child); 1755 rc = secondary_ops->ptrace(parent, child, mode);
1690 if (rc) 1756 if (rc)
1691 return rc; 1757 return rc;
1692 1758
1759 if (mode == PTRACE_MODE_READ) {
1760 struct task_security_struct *tsec = parent->security;
1761 struct task_security_struct *csec = child->security;
1762 return avc_has_perm(tsec->sid, csec->sid,
1763 SECCLASS_FILE, FILE__READ, NULL);
1764 }
1765
1693 return task_has_perm(parent, child, PROCESS__PTRACE); 1766 return task_has_perm(parent, child, PROCESS__PTRACE);
1694} 1767}
1695 1768
@@ -2495,7 +2568,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2495 } 2568 }
2496 2569
2497 if (value && len) { 2570 if (value && len) {
2498 rc = security_sid_to_context(newsid, &context, &clen); 2571 rc = security_sid_to_context_force(newsid, &context, &clen);
2499 if (rc) { 2572 if (rc) {
2500 kfree(namep); 2573 kfree(namep);
2501 return rc; 2574 return rc;
@@ -2669,6 +2742,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2669 return rc; 2742 return rc;
2670 2743
2671 rc = security_context_to_sid(value, size, &newsid); 2744 rc = security_context_to_sid(value, size, &newsid);
2745 if (rc == -EINVAL) {
2746 if (!capable(CAP_MAC_ADMIN))
2747 return rc;
2748 rc = security_context_to_sid_force(value, size, &newsid);
2749 }
2672 if (rc) 2750 if (rc)
2673 return rc; 2751 return rc;
2674 2752
@@ -2690,7 +2768,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2690} 2768}
2691 2769
2692static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, 2770static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
2693 const void *value, size_t size, 2771 const void *value, size_t size,
2694 int flags) 2772 int flags)
2695{ 2773{
2696 struct inode *inode = dentry->d_inode; 2774 struct inode *inode = dentry->d_inode;
@@ -2703,10 +2781,11 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
2703 return; 2781 return;
2704 } 2782 }
2705 2783
2706 rc = security_context_to_sid(value, size, &newsid); 2784 rc = security_context_to_sid_force(value, size, &newsid);
2707 if (rc) { 2785 if (rc) {
2708 printk(KERN_WARNING "%s: unable to obtain SID for context " 2786 printk(KERN_ERR "SELinux: unable to map context to SID"
2709 "%s, rc=%d\n", __func__, (char *)value, -rc); 2787 "for (%s, %lu), rc=%d\n",
2788 inode->i_sb->s_id, inode->i_ino, -rc);
2710 return; 2789 return;
2711 } 2790 }
2712 2791
@@ -2735,9 +2814,7 @@ static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
2735} 2814}
2736 2815
2737/* 2816/*
2738 * Copy the in-core inode security context value to the user. If the 2817 * Copy the inode security context value to the user.
2739 * getxattr() prior to this succeeded, check to see if we need to
2740 * canonicalize the value to be finally returned to the user.
2741 * 2818 *
2742 * Permission check is handled by selinux_inode_getxattr hook. 2819 * Permission check is handled by selinux_inode_getxattr hook.
2743 */ 2820 */
@@ -2746,12 +2823,33 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
2746 u32 size; 2823 u32 size;
2747 int error; 2824 int error;
2748 char *context = NULL; 2825 char *context = NULL;
2826 struct task_security_struct *tsec = current->security;
2749 struct inode_security_struct *isec = inode->i_security; 2827 struct inode_security_struct *isec = inode->i_security;
2750 2828
2751 if (strcmp(name, XATTR_SELINUX_SUFFIX)) 2829 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2752 return -EOPNOTSUPP; 2830 return -EOPNOTSUPP;
2753 2831
2754 error = security_sid_to_context(isec->sid, &context, &size); 2832 /*
2833 * If the caller has CAP_MAC_ADMIN, then get the raw context
2834 * value even if it is not defined by current policy; otherwise,
2835 * use the in-core value under current policy.
2836 * Use the non-auditing forms of the permission checks since
2837 * getxattr may be called by unprivileged processes commonly
2838 * and lack of permission just means that we fall back to the
2839 * in-core context value, not a denial.
2840 */
2841 error = secondary_ops->capable(current, CAP_MAC_ADMIN);
2842 if (!error)
2843 error = avc_has_perm_noaudit(tsec->sid, tsec->sid,
2844 SECCLASS_CAPABILITY2,
2845 CAPABILITY2__MAC_ADMIN,
2846 0,
2847 NULL);
2848 if (!error)
2849 error = security_sid_to_context_force(isec->sid, &context,
2850 &size);
2851 else
2852 error = security_sid_to_context(isec->sid, &context, &size);
2755 if (error) 2853 if (error)
2756 return error; 2854 return error;
2757 error = size; 2855 error = size;
@@ -2865,46 +2963,16 @@ static void selinux_file_free_security(struct file *file)
2865static int selinux_file_ioctl(struct file *file, unsigned int cmd, 2963static int selinux_file_ioctl(struct file *file, unsigned int cmd,
2866 unsigned long arg) 2964 unsigned long arg)
2867{ 2965{
2868 int error = 0; 2966 u32 av = 0;
2869
2870 switch (cmd) {
2871 case FIONREAD:
2872 /* fall through */
2873 case FIBMAP:
2874 /* fall through */
2875 case FIGETBSZ:
2876 /* fall through */
2877 case EXT2_IOC_GETFLAGS:
2878 /* fall through */
2879 case EXT2_IOC_GETVERSION:
2880 error = file_has_perm(current, file, FILE__GETATTR);
2881 break;
2882
2883 case EXT2_IOC_SETFLAGS:
2884 /* fall through */
2885 case EXT2_IOC_SETVERSION:
2886 error = file_has_perm(current, file, FILE__SETATTR);
2887 break;
2888
2889 /* sys_ioctl() checks */
2890 case FIONBIO:
2891 /* fall through */
2892 case FIOASYNC:
2893 error = file_has_perm(current, file, 0);
2894 break;
2895 2967
2896 case KDSKBENT: 2968 if (_IOC_DIR(cmd) & _IOC_WRITE)
2897 case KDSKBSENT: 2969 av |= FILE__WRITE;
2898 error = task_has_capability(current, CAP_SYS_TTY_CONFIG); 2970 if (_IOC_DIR(cmd) & _IOC_READ)
2899 break; 2971 av |= FILE__READ;
2972 if (!av)
2973 av = FILE__IOCTL;
2900 2974
2901 /* default case assumes that the command will go 2975 return file_has_perm(current, file, av);
2902 * to the file's ioctl() function.
2903 */
2904 default:
2905 error = file_has_perm(current, file, FILE__IOCTL);
2906 }
2907 return error;
2908} 2976}
2909 2977
2910static int file_map_prot_check(struct file *file, unsigned long prot, int shared) 2978static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
@@ -3663,7 +3731,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3663 struct sockaddr_in6 *addr6 = NULL; 3731 struct sockaddr_in6 *addr6 = NULL;
3664 unsigned short snum; 3732 unsigned short snum;
3665 struct sock *sk = sock->sk; 3733 struct sock *sk = sock->sk;
3666 u32 sid, node_perm, addrlen; 3734 u32 sid, node_perm;
3667 3735
3668 tsec = current->security; 3736 tsec = current->security;
3669 isec = SOCK_INODE(sock)->i_security; 3737 isec = SOCK_INODE(sock)->i_security;
@@ -3671,12 +3739,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3671 if (family == PF_INET) { 3739 if (family == PF_INET) {
3672 addr4 = (struct sockaddr_in *)address; 3740 addr4 = (struct sockaddr_in *)address;
3673 snum = ntohs(addr4->sin_port); 3741 snum = ntohs(addr4->sin_port);
3674 addrlen = sizeof(addr4->sin_addr.s_addr);
3675 addrp = (char *)&addr4->sin_addr.s_addr; 3742 addrp = (char *)&addr4->sin_addr.s_addr;
3676 } else { 3743 } else {
3677 addr6 = (struct sockaddr_in6 *)address; 3744 addr6 = (struct sockaddr_in6 *)address;
3678 snum = ntohs(addr6->sin6_port); 3745 snum = ntohs(addr6->sin6_port);
3679 addrlen = sizeof(addr6->sin6_addr.s6_addr);
3680 addrp = (char *)&addr6->sin6_addr.s6_addr; 3746 addrp = (char *)&addr6->sin6_addr.s6_addr;
3681 } 3747 }
3682 3748
@@ -5047,24 +5113,6 @@ static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5047 *secid = isec->sid; 5113 *secid = isec->sid;
5048} 5114}
5049 5115
5050/* module stacking operations */
5051static int selinux_register_security(const char *name, struct security_operations *ops)
5052{
5053 if (secondary_ops != original_ops) {
5054 printk(KERN_ERR "%s: There is already a secondary security "
5055 "module registered.\n", __func__);
5056 return -EINVAL;
5057 }
5058
5059 secondary_ops = ops;
5060
5061 printk(KERN_INFO "%s: Registering secondary module %s\n",
5062 __func__,
5063 name);
5064
5065 return 0;
5066}
5067
5068static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode) 5116static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
5069{ 5117{
5070 if (inode) 5118 if (inode)
@@ -5153,6 +5201,12 @@ static int selinux_setprocattr(struct task_struct *p,
5153 size--; 5201 size--;
5154 } 5202 }
5155 error = security_context_to_sid(value, size, &sid); 5203 error = security_context_to_sid(value, size, &sid);
5204 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5205 if (!capable(CAP_MAC_ADMIN))
5206 return error;
5207 error = security_context_to_sid_force(value, size,
5208 &sid);
5209 }
5156 if (error) 5210 if (error)
5157 return error; 5211 return error;
5158 } 5212 }
@@ -5186,12 +5240,12 @@ static int selinux_setprocattr(struct task_struct *p,
5186 struct task_struct *g, *t; 5240 struct task_struct *g, *t;
5187 struct mm_struct *mm = p->mm; 5241 struct mm_struct *mm = p->mm;
5188 read_lock(&tasklist_lock); 5242 read_lock(&tasklist_lock);
5189 do_each_thread(g, t) 5243 do_each_thread(g, t) {
5190 if (t->mm == mm && t != p) { 5244 if (t->mm == mm && t != p) {
5191 read_unlock(&tasklist_lock); 5245 read_unlock(&tasklist_lock);
5192 return -EPERM; 5246 return -EPERM;
5193 } 5247 }
5194 while_each_thread(g, t); 5248 } while_each_thread(g, t);
5195 read_unlock(&tasklist_lock); 5249 read_unlock(&tasklist_lock);
5196 } 5250 }
5197 5251
@@ -5343,10 +5397,10 @@ static struct security_operations selinux_ops = {
5343 .sb_free_security = selinux_sb_free_security, 5397 .sb_free_security = selinux_sb_free_security,
5344 .sb_copy_data = selinux_sb_copy_data, 5398 .sb_copy_data = selinux_sb_copy_data,
5345 .sb_kern_mount = selinux_sb_kern_mount, 5399 .sb_kern_mount = selinux_sb_kern_mount,
5400 .sb_show_options = selinux_sb_show_options,
5346 .sb_statfs = selinux_sb_statfs, 5401 .sb_statfs = selinux_sb_statfs,
5347 .sb_mount = selinux_mount, 5402 .sb_mount = selinux_mount,
5348 .sb_umount = selinux_umount, 5403 .sb_umount = selinux_umount,
5349 .sb_get_mnt_opts = selinux_get_mnt_opts,
5350 .sb_set_mnt_opts = selinux_set_mnt_opts, 5404 .sb_set_mnt_opts = selinux_set_mnt_opts,
5351 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, 5405 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
5352 .sb_parse_opts_str = selinux_parse_opts_str, 5406 .sb_parse_opts_str = selinux_parse_opts_str,
@@ -5378,7 +5432,7 @@ static struct security_operations selinux_ops = {
5378 .inode_listsecurity = selinux_inode_listsecurity, 5432 .inode_listsecurity = selinux_inode_listsecurity,
5379 .inode_need_killpriv = selinux_inode_need_killpriv, 5433 .inode_need_killpriv = selinux_inode_need_killpriv,
5380 .inode_killpriv = selinux_inode_killpriv, 5434 .inode_killpriv = selinux_inode_killpriv,
5381 .inode_getsecid = selinux_inode_getsecid, 5435 .inode_getsecid = selinux_inode_getsecid,
5382 5436
5383 .file_permission = selinux_file_permission, 5437 .file_permission = selinux_file_permission,
5384 .file_alloc_security = selinux_file_alloc_security, 5438 .file_alloc_security = selinux_file_alloc_security,
@@ -5419,7 +5473,7 @@ static struct security_operations selinux_ops = {
5419 .task_to_inode = selinux_task_to_inode, 5473 .task_to_inode = selinux_task_to_inode,
5420 5474
5421 .ipc_permission = selinux_ipc_permission, 5475 .ipc_permission = selinux_ipc_permission,
5422 .ipc_getsecid = selinux_ipc_getsecid, 5476 .ipc_getsecid = selinux_ipc_getsecid,
5423 5477
5424 .msg_msg_alloc_security = selinux_msg_msg_alloc_security, 5478 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5425 .msg_msg_free_security = selinux_msg_msg_free_security, 5479 .msg_msg_free_security = selinux_msg_msg_free_security,
@@ -5443,8 +5497,6 @@ static struct security_operations selinux_ops = {
5443 .sem_semctl = selinux_sem_semctl, 5497 .sem_semctl = selinux_sem_semctl,
5444 .sem_semop = selinux_sem_semop, 5498 .sem_semop = selinux_sem_semop,
5445 5499
5446 .register_security = selinux_register_security,
5447
5448 .d_instantiate = selinux_d_instantiate, 5500 .d_instantiate = selinux_d_instantiate,
5449 5501
5450 .getprocattr = selinux_getprocattr, 5502 .getprocattr = selinux_getprocattr,
@@ -5538,7 +5590,7 @@ static __init int selinux_init(void)
5538 0, SLAB_PANIC, NULL); 5590 0, SLAB_PANIC, NULL);
5539 avc_init(); 5591 avc_init();
5540 5592
5541 original_ops = secondary_ops = security_ops; 5593 secondary_ops = security_ops;
5542 if (!secondary_ops) 5594 if (!secondary_ops)
5543 panic("SELinux: No initial security operations\n"); 5595 panic("SELinux: No initial security operations\n");
5544 if (register_security(&selinux_ops)) 5596 if (register_security(&selinux_ops))
diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h
index 6c8b9ef15579..1bdf973433cc 100644
--- a/security/selinux/include/audit.h
+++ b/security/selinux/include/audit.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * SELinux support for the Audit LSM hooks 2 * SELinux support for the Audit LSM hooks
3 * 3 *
4 * Most of below header was moved from include/linux/selinux.h which 4 * Most of below header was moved from include/linux/selinux.h which
5 * is released under below copyrights: 5 * is released under below copyrights:
6 * 6 *
7 * Author: James Morris <jmorris@redhat.com> 7 * Author: James Morris <jmorris@redhat.com>
@@ -52,7 +52,7 @@ void selinux_audit_rule_free(void *rule);
52 * -errno on failure. 52 * -errno on failure.
53 */ 53 */
54int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule, 54int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
55 struct audit_context *actx); 55 struct audit_context *actx);
56 56
57/** 57/**
58 * selinux_audit_rule_known - check to see if rule contains selinux fields. 58 * selinux_audit_rule_known - check to see if rule contains selinux fields.
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 8e23d7a873a4..7b9769f5e775 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -75,13 +75,12 @@ struct avc_audit_data {
75 75
76/* Initialize an AVC audit data structure. */ 76/* Initialize an AVC audit data structure. */
77#define AVC_AUDIT_DATA_INIT(_d,_t) \ 77#define AVC_AUDIT_DATA_INIT(_d,_t) \
78 { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; } 78 { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
79 79
80/* 80/*
81 * AVC statistics 81 * AVC statistics
82 */ 82 */
83struct avc_cache_stats 83struct avc_cache_stats {
84{
85 unsigned int lookups; 84 unsigned int lookups;
86 unsigned int hits; 85 unsigned int hits;
87 unsigned int misses; 86 unsigned int misses;
@@ -97,8 +96,8 @@ struct avc_cache_stats
97void __init avc_init(void); 96void __init avc_init(void);
98 97
99void avc_audit(u32 ssid, u32 tsid, 98void avc_audit(u32 ssid, u32 tsid,
100 u16 tclass, u32 requested, 99 u16 tclass, u32 requested,
101 struct av_decision *avd, int result, struct avc_audit_data *auditdata); 100 struct av_decision *avd, int result, struct avc_audit_data *auditdata);
102 101
103#define AVC_STRICT 1 /* Ignore permissive mode. */ 102#define AVC_STRICT 1 /* Ignore permissive mode. */
104int avc_has_perm_noaudit(u32 ssid, u32 tsid, 103int avc_has_perm_noaudit(u32 ssid, u32 tsid,
@@ -107,8 +106,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
107 struct av_decision *avd); 106 struct av_decision *avd);
108 107
109int avc_has_perm(u32 ssid, u32 tsid, 108int avc_has_perm(u32 ssid, u32 tsid,
110 u16 tclass, u32 requested, 109 u16 tclass, u32 requested,
111 struct avc_audit_data *auditdata); 110 struct avc_audit_data *auditdata);
112 111
113u32 avc_policy_seqno(void); 112u32 avc_policy_seqno(void);
114 113
@@ -122,7 +121,7 @@ u32 avc_policy_seqno(void);
122#define AVC_CALLBACK_AUDITDENY_DISABLE 128 121#define AVC_CALLBACK_AUDITDENY_DISABLE 128
123 122
124int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, 123int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
125 u16 tclass, u32 perms, 124 u16 tclass, u32 perms,
126 u32 *out_retained), 125 u32 *out_retained),
127 u32 events, u32 ssid, u32 tsid, 126 u32 events, u32 ssid, u32 tsid,
128 u16 tclass, u32 perms); 127 u16 tclass, u32 perms);
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 032c2357dad1..91070ab874ce 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -44,7 +44,6 @@ struct inode_security_struct {
44 u16 sclass; /* security class of this object */ 44 u16 sclass; /* security class of this object */
45 unsigned char initialized; /* initialization flag */ 45 unsigned char initialized; /* initialization flag */
46 struct mutex lock; 46 struct mutex lock;
47 unsigned char inherit; /* inherit SID from parent entry */
48}; 47};
49 48
50struct file_security_struct { 49struct file_security_struct {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index ad30ac4273d6..44cba2e21dcf 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -93,12 +93,17 @@ int security_change_sid(u32 ssid, u32 tsid,
93int security_sid_to_context(u32 sid, char **scontext, 93int security_sid_to_context(u32 sid, char **scontext,
94 u32 *scontext_len); 94 u32 *scontext_len);
95 95
96int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
97
96int security_context_to_sid(const char *scontext, u32 scontext_len, 98int security_context_to_sid(const char *scontext, u32 scontext_len,
97 u32 *out_sid); 99 u32 *out_sid);
98 100
99int security_context_to_sid_default(const char *scontext, u32 scontext_len, 101int security_context_to_sid_default(const char *scontext, u32 scontext_len,
100 u32 *out_sid, u32 def_sid, gfp_t gfp_flags); 102 u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
101 103
104int security_context_to_sid_force(const char *scontext, u32 scontext_len,
105 u32 *sid);
106
102int security_get_user_sids(u32 callsid, char *username, 107int security_get_user_sids(u32 callsid, char *username,
103 u32 **sids, u32 *nel); 108 u32 **sids, u32 *nel);
104 109
@@ -131,7 +136,7 @@ int security_get_allow_unknown(void);
131#define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */ 136#define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */
132 137
133int security_fs_use(const char *fstype, unsigned int *behavior, 138int security_fs_use(const char *fstype, unsigned int *behavior,
134 u32 *sid); 139 u32 *sid, bool can_xattr);
135 140
136int security_genfs_sid(const char *fstype, char *name, u16 sclass, 141int security_genfs_sid(const char *fstype, char *name, u16 sclass,
137 u32 *sid); 142 u32 *sid);
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index b6ccd09379f1..7100072bb1b0 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -38,7 +38,6 @@
38#include <linux/ipv6.h> 38#include <linux/ipv6.h>
39#include <net/ip.h> 39#include <net/ip.h>
40#include <net/ipv6.h> 40#include <net/ipv6.h>
41#include <asm/bug.h>
42 41
43#include "netnode.h" 42#include "netnode.h"
44#include "objsec.h" 43#include "objsec.h"
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index 90b4cff7c350..fe7fba67f19f 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -37,7 +37,6 @@
37#include <linux/ipv6.h> 37#include <linux/ipv6.h>
38#include <net/ip.h> 38#include <net/ip.h>
39#include <net/ipv6.h> 39#include <net/ipv6.h>
40#include <asm/bug.h>
41 40
42#include "netport.h" 41#include "netport.h"
43#include "objsec.h" 42#include "objsec.h"
@@ -272,7 +271,7 @@ static __init int sel_netport_init(void)
272 } 271 }
273 272
274 ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET, 273 ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
275 SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); 274 SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
276 if (ret != 0) 275 if (ret != 0)
277 panic("avc_add_callback() failed, error %d\n", ret); 276 panic("avc_add_callback() failed, error %d\n", ret);
278 277
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index ac1ccc13a704..69c9dccc8cf0 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -27,7 +27,7 @@
27#include <linux/seq_file.h> 27#include <linux/seq_file.h>
28#include <linux/percpu.h> 28#include <linux/percpu.h>
29#include <linux/audit.h> 29#include <linux/audit.h>
30#include <asm/uaccess.h> 30#include <linux/uaccess.h>
31 31
32/* selinuxfs pseudo filesystem for exporting the security policy API. 32/* selinuxfs pseudo filesystem for exporting the security policy API.
33 Based on the proc code and the fs/nfsd/nfsctl.c code. */ 33 Based on the proc code and the fs/nfsd/nfsctl.c code. */
@@ -57,14 +57,18 @@ int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
57 57
58static int __init checkreqprot_setup(char *str) 58static int __init checkreqprot_setup(char *str)
59{ 59{
60 selinux_checkreqprot = simple_strtoul(str, NULL, 0) ? 1 : 0; 60 unsigned long checkreqprot;
61 if (!strict_strtoul(str, 0, &checkreqprot))
62 selinux_checkreqprot = checkreqprot ? 1 : 0;
61 return 1; 63 return 1;
62} 64}
63__setup("checkreqprot=", checkreqprot_setup); 65__setup("checkreqprot=", checkreqprot_setup);
64 66
65static int __init selinux_compat_net_setup(char *str) 67static int __init selinux_compat_net_setup(char *str)
66{ 68{
67 selinux_compat_net = simple_strtoul(str, NULL, 0) ? 1 : 0; 69 unsigned long compat_net;
70 if (!strict_strtoul(str, 0, &compat_net))
71 selinux_compat_net = compat_net ? 1 : 0;
68 return 1; 72 return 1;
69} 73}
70__setup("selinux_compat_net=", selinux_compat_net_setup); 74__setup("selinux_compat_net=", selinux_compat_net_setup);
@@ -352,11 +356,6 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
352 length = count; 356 length = count;
353 357
354out1: 358out1:
355
356 printk(KERN_INFO "SELinux: policy loaded with handle_unknown=%s\n",
357 (security_get_reject_unknown() ? "reject" :
358 (security_get_allow_unknown() ? "allow" : "deny")));
359
360 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, 359 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
361 "policy loaded auid=%u ses=%u", 360 "policy loaded auid=%u ses=%u",
362 audit_get_loginuid(current), 361 audit_get_loginuid(current),
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 9e6626362bfd..a1be97f8beea 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -311,7 +311,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
311 } 311 }
312 312
313 printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, " 313 printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
314 "longest chain length %d sum of chain length^2 %Lu\n", 314 "longest chain length %d sum of chain length^2 %llu\n",
315 tag, h->nel, slots_used, h->nslot, max_chain_len, 315 tag, h->nel, slots_used, h->nslot, max_chain_len,
316 chain2_len_sum); 316 chain2_len_sum);
317} 317}
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index b9a6f7fc62fc..658c2bd17da8 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -28,6 +28,8 @@ struct context {
28 u32 role; 28 u32 role;
29 u32 type; 29 u32 type;
30 struct mls_range range; 30 struct mls_range range;
31 char *str; /* string representation if context cannot be mapped. */
32 u32 len; /* length of string in bytes */
31}; 33};
32 34
33static inline void mls_context_init(struct context *c) 35static inline void mls_context_init(struct context *c)
@@ -106,20 +108,43 @@ static inline void context_init(struct context *c)
106 108
107static inline int context_cpy(struct context *dst, struct context *src) 109static inline int context_cpy(struct context *dst, struct context *src)
108{ 110{
111 int rc;
112
109 dst->user = src->user; 113 dst->user = src->user;
110 dst->role = src->role; 114 dst->role = src->role;
111 dst->type = src->type; 115 dst->type = src->type;
112 return mls_context_cpy(dst, src); 116 if (src->str) {
117 dst->str = kstrdup(src->str, GFP_ATOMIC);
118 if (!dst->str)
119 return -ENOMEM;
120 dst->len = src->len;
121 } else {
122 dst->str = NULL;
123 dst->len = 0;
124 }
125 rc = mls_context_cpy(dst, src);
126 if (rc) {
127 kfree(dst->str);
128 return rc;
129 }
130 return 0;
113} 131}
114 132
115static inline void context_destroy(struct context *c) 133static inline void context_destroy(struct context *c)
116{ 134{
117 c->user = c->role = c->type = 0; 135 c->user = c->role = c->type = 0;
136 kfree(c->str);
137 c->str = NULL;
138 c->len = 0;
118 mls_context_destroy(c); 139 mls_context_destroy(c);
119} 140}
120 141
121static inline int context_cmp(struct context *c1, struct context *c2) 142static inline int context_cmp(struct context *c1, struct context *c2)
122{ 143{
144 if (c1->len && c2->len)
145 return (c1->len == c2->len && !strcmp(c1->str, c2->str));
146 if (c1->len || c2->len)
147 return 0;
123 return ((c1->user == c2->user) && 148 return ((c1->user == c2->user) &&
124 (c1->role == c2->role) && 149 (c1->role == c2->role) &&
125 (c1->type == c2->type) && 150 (c1->type == c2->type) &&
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 8b1706b7b3cc..77d745da48bb 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -239,7 +239,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
239 * Policy read-lock must be held for sidtab lookup. 239 * Policy read-lock must be held for sidtab lookup.
240 * 240 *
241 */ 241 */
242int mls_context_to_sid(char oldc, 242int mls_context_to_sid(struct policydb *pol,
243 char oldc,
243 char **scontext, 244 char **scontext,
244 struct context *context, 245 struct context *context,
245 struct sidtab *s, 246 struct sidtab *s,
@@ -286,7 +287,7 @@ int mls_context_to_sid(char oldc,
286 *p++ = 0; 287 *p++ = 0;
287 288
288 for (l = 0; l < 2; l++) { 289 for (l = 0; l < 2; l++) {
289 levdatum = hashtab_search(policydb.p_levels.table, scontextp); 290 levdatum = hashtab_search(pol->p_levels.table, scontextp);
290 if (!levdatum) { 291 if (!levdatum) {
291 rc = -EINVAL; 292 rc = -EINVAL;
292 goto out; 293 goto out;
@@ -311,7 +312,7 @@ int mls_context_to_sid(char oldc,
311 *rngptr++ = 0; 312 *rngptr++ = 0;
312 } 313 }
313 314
314 catdatum = hashtab_search(policydb.p_cats.table, 315 catdatum = hashtab_search(pol->p_cats.table,
315 scontextp); 316 scontextp);
316 if (!catdatum) { 317 if (!catdatum) {
317 rc = -EINVAL; 318 rc = -EINVAL;
@@ -327,7 +328,7 @@ int mls_context_to_sid(char oldc,
327 if (rngptr) { 328 if (rngptr) {
328 int i; 329 int i;
329 330
330 rngdatum = hashtab_search(policydb.p_cats.table, rngptr); 331 rngdatum = hashtab_search(pol->p_cats.table, rngptr);
331 if (!rngdatum) { 332 if (!rngdatum) {
332 rc = -EINVAL; 333 rc = -EINVAL;
333 goto out; 334 goto out;
@@ -395,7 +396,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
395 if (!tmpstr) { 396 if (!tmpstr) {
396 rc = -ENOMEM; 397 rc = -ENOMEM;
397 } else { 398 } else {
398 rc = mls_context_to_sid(':', &tmpstr, context, 399 rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
399 NULL, SECSID_NULL); 400 NULL, SECSID_NULL);
400 kfree(freestr); 401 kfree(freestr);
401 } 402 }
@@ -436,13 +437,13 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
436 struct mls_level *usercon_clr = &(usercon->range.level[1]); 437 struct mls_level *usercon_clr = &(usercon->range.level[1]);
437 438
438 /* Honor the user's default level if we can */ 439 /* Honor the user's default level if we can */
439 if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) { 440 if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
440 *usercon_sen = *user_def; 441 *usercon_sen = *user_def;
441 } else if (mls_level_between(fromcon_sen, user_def, user_clr)) { 442 else if (mls_level_between(fromcon_sen, user_def, user_clr))
442 *usercon_sen = *fromcon_sen; 443 *usercon_sen = *fromcon_sen;
443 } else if (mls_level_between(fromcon_clr, user_low, user_def)) { 444 else if (mls_level_between(fromcon_clr, user_low, user_def))
444 *usercon_sen = *user_low; 445 *usercon_sen = *user_low;
445 } else 446 else
446 return -EINVAL; 447 return -EINVAL;
447 448
448 /* Lower the clearance of available contexts 449 /* Lower the clearance of available contexts
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 0fdf6257ef64..1276715aaa8b 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -30,7 +30,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c);
30int mls_range_isvalid(struct policydb *p, struct mls_range *r); 30int mls_range_isvalid(struct policydb *p, struct mls_range *r);
31int mls_level_isvalid(struct policydb *p, struct mls_level *l); 31int mls_level_isvalid(struct policydb *p, struct mls_level *l);
32 32
33int mls_context_to_sid(char oldc, 33int mls_context_to_sid(struct policydb *p,
34 char oldc,
34 char **scontext, 35 char **scontext,
35 struct context *context, 36 struct context *context,
36 struct sidtab *s, 37 struct sidtab *s,
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 84f8cc73c7db..2391761ae422 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -1478,7 +1478,8 @@ int policydb_read(struct policydb *p, void *fp)
1478 struct ocontext *l, *c, *newc; 1478 struct ocontext *l, *c, *newc;
1479 struct genfs *genfs_p, *genfs, *newgenfs; 1479 struct genfs *genfs_p, *genfs, *newgenfs;
1480 int i, j, rc; 1480 int i, j, rc;
1481 __le32 buf[8]; 1481 __le32 buf[4];
1482 u32 nodebuf[8];
1482 u32 len, len2, config, nprim, nel, nel2; 1483 u32 len, len2, config, nprim, nel, nel2;
1483 char *policydb_str; 1484 char *policydb_str;
1484 struct policydb_compat_info *info; 1485 struct policydb_compat_info *info;
@@ -1749,11 +1750,11 @@ int policydb_read(struct policydb *p, void *fp)
1749 goto bad; 1750 goto bad;
1750 break; 1751 break;
1751 case OCON_NODE: 1752 case OCON_NODE:
1752 rc = next_entry(buf, fp, sizeof(u32) * 2); 1753 rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
1753 if (rc < 0) 1754 if (rc < 0)
1754 goto bad; 1755 goto bad;
1755 c->u.node.addr = le32_to_cpu(buf[0]); 1756 c->u.node.addr = nodebuf[0]; /* network order */
1756 c->u.node.mask = le32_to_cpu(buf[1]); 1757 c->u.node.mask = nodebuf[1]; /* network order */
1757 rc = context_read_and_validate(&c->context[0], p, fp); 1758 rc = context_read_and_validate(&c->context[0], p, fp);
1758 if (rc) 1759 if (rc)
1759 goto bad; 1760 goto bad;
@@ -1782,13 +1783,13 @@ int policydb_read(struct policydb *p, void *fp)
1782 case OCON_NODE6: { 1783 case OCON_NODE6: {
1783 int k; 1784 int k;
1784 1785
1785 rc = next_entry(buf, fp, sizeof(u32) * 8); 1786 rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
1786 if (rc < 0) 1787 if (rc < 0)
1787 goto bad; 1788 goto bad;
1788 for (k = 0; k < 4; k++) 1789 for (k = 0; k < 4; k++)
1789 c->u.node6.addr[k] = le32_to_cpu(buf[k]); 1790 c->u.node6.addr[k] = nodebuf[k];
1790 for (k = 0; k < 4; k++) 1791 for (k = 0; k < 4; k++)
1791 c->u.node6.mask[k] = le32_to_cpu(buf[k+4]); 1792 c->u.node6.mask[k] = nodebuf[k+4];
1792 if (context_read_and_validate(&c->context[0], p, fp)) 1793 if (context_read_and_validate(&c->context[0], p, fp))
1793 goto bad; 1794 goto bad;
1794 break; 1795 break;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index dcc2e1c4fd83..8e42da120101 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -71,14 +71,6 @@ int selinux_policycap_openperm;
71extern const struct selinux_class_perm selinux_class_perm; 71extern const struct selinux_class_perm selinux_class_perm;
72 72
73static DEFINE_RWLOCK(policy_rwlock); 73static DEFINE_RWLOCK(policy_rwlock);
74#define POLICY_RDLOCK read_lock(&policy_rwlock)
75#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
76#define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
77#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock)
78
79static DEFINE_MUTEX(load_mutex);
80#define LOAD_LOCK mutex_lock(&load_mutex)
81#define LOAD_UNLOCK mutex_unlock(&load_mutex)
82 74
83static struct sidtab sidtab; 75static struct sidtab sidtab;
84struct policydb policydb; 76struct policydb policydb;
@@ -332,7 +324,7 @@ static int context_struct_compute_av(struct context *scontext,
332 goto inval_class; 324 goto inval_class;
333 if (unlikely(tclass > policydb.p_classes.nprim)) 325 if (unlikely(tclass > policydb.p_classes.nprim))
334 if (tclass > kdefs->cts_len || 326 if (tclass > kdefs->cts_len ||
335 !kdefs->class_to_string[tclass - 1] || 327 !kdefs->class_to_string[tclass] ||
336 !policydb.allow_unknown) 328 !policydb.allow_unknown)
337 goto inval_class; 329 goto inval_class;
338 330
@@ -415,9 +407,19 @@ static int context_struct_compute_av(struct context *scontext,
415 return 0; 407 return 0;
416 408
417inval_class: 409inval_class:
418 printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", __func__, 410 if (!tclass || tclass > kdefs->cts_len ||
419 tclass); 411 !kdefs->class_to_string[tclass]) {
420 return -EINVAL; 412 if (printk_ratelimit())
413 printk(KERN_ERR "SELinux: %s: unrecognized class %d\n",
414 __func__, tclass);
415 return -EINVAL;
416 }
417
418 /*
419 * Known to the kernel, but not to the policy.
420 * Handle as a denial (allowed is 0).
421 */
422 return 0;
421} 423}
422 424
423/* 425/*
@@ -429,7 +431,7 @@ int security_permissive_sid(u32 sid)
429 u32 type; 431 u32 type;
430 int rc; 432 int rc;
431 433
432 POLICY_RDLOCK; 434 read_lock(&policy_rwlock);
433 435
434 context = sidtab_search(&sidtab, sid); 436 context = sidtab_search(&sidtab, sid);
435 BUG_ON(!context); 437 BUG_ON(!context);
@@ -441,7 +443,7 @@ int security_permissive_sid(u32 sid)
441 */ 443 */
442 rc = ebitmap_get_bit(&policydb.permissive_map, type); 444 rc = ebitmap_get_bit(&policydb.permissive_map, type);
443 445
444 POLICY_RDUNLOCK; 446 read_unlock(&policy_rwlock);
445 return rc; 447 return rc;
446} 448}
447 449
@@ -486,7 +488,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
486 if (!ss_initialized) 488 if (!ss_initialized)
487 return 0; 489 return 0;
488 490
489 POLICY_RDLOCK; 491 read_lock(&policy_rwlock);
490 492
491 /* 493 /*
492 * Remap extended Netlink classes for old policy versions. 494 * Remap extended Netlink classes for old policy versions.
@@ -543,7 +545,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
543 } 545 }
544 546
545out: 547out:
546 POLICY_RDUNLOCK; 548 read_unlock(&policy_rwlock);
547 return rc; 549 return rc;
548} 550}
549 551
@@ -578,7 +580,7 @@ int security_compute_av(u32 ssid,
578 return 0; 580 return 0;
579 } 581 }
580 582
581 POLICY_RDLOCK; 583 read_lock(&policy_rwlock);
582 584
583 scontext = sidtab_search(&sidtab, ssid); 585 scontext = sidtab_search(&sidtab, ssid);
584 if (!scontext) { 586 if (!scontext) {
@@ -598,7 +600,7 @@ int security_compute_av(u32 ssid,
598 rc = context_struct_compute_av(scontext, tcontext, tclass, 600 rc = context_struct_compute_av(scontext, tcontext, tclass,
599 requested, avd); 601 requested, avd);
600out: 602out:
601 POLICY_RDUNLOCK; 603 read_unlock(&policy_rwlock);
602 return rc; 604 return rc;
603} 605}
604 606
@@ -616,6 +618,14 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
616 *scontext = NULL; 618 *scontext = NULL;
617 *scontext_len = 0; 619 *scontext_len = 0;
618 620
621 if (context->len) {
622 *scontext_len = context->len;
623 *scontext = kstrdup(context->str, GFP_ATOMIC);
624 if (!(*scontext))
625 return -ENOMEM;
626 return 0;
627 }
628
619 /* Compute the size of the context. */ 629 /* Compute the size of the context. */
620 *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1; 630 *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
621 *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1; 631 *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
@@ -655,17 +665,8 @@ const char *security_get_initial_sid_context(u32 sid)
655 return initial_sid_to_string[sid]; 665 return initial_sid_to_string[sid];
656} 666}
657 667
658/** 668static int security_sid_to_context_core(u32 sid, char **scontext,
659 * security_sid_to_context - Obtain a context for a given SID. 669 u32 *scontext_len, int force)
660 * @sid: security identifier, SID
661 * @scontext: security context
662 * @scontext_len: length in bytes
663 *
664 * Write the string representation of the context associated with @sid
665 * into a dynamically allocated string of the correct size. Set @scontext
666 * to point to this string and set @scontext_len to the length of the string.
667 */
668int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
669{ 670{
670 struct context *context; 671 struct context *context;
671 int rc = 0; 672 int rc = 0;
@@ -692,8 +693,11 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
692 rc = -EINVAL; 693 rc = -EINVAL;
693 goto out; 694 goto out;
694 } 695 }
695 POLICY_RDLOCK; 696 read_lock(&policy_rwlock);
696 context = sidtab_search(&sidtab, sid); 697 if (force)
698 context = sidtab_search_force(&sidtab, sid);
699 else
700 context = sidtab_search(&sidtab, sid);
697 if (!context) { 701 if (!context) {
698 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", 702 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
699 __func__, sid); 703 __func__, sid);
@@ -702,59 +706,54 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
702 } 706 }
703 rc = context_struct_to_string(context, scontext, scontext_len); 707 rc = context_struct_to_string(context, scontext, scontext_len);
704out_unlock: 708out_unlock:
705 POLICY_RDUNLOCK; 709 read_unlock(&policy_rwlock);
706out: 710out:
707 return rc; 711 return rc;
708 712
709} 713}
710 714
711static int security_context_to_sid_core(const char *scontext, u32 scontext_len, 715/**
712 u32 *sid, u32 def_sid, gfp_t gfp_flags) 716 * security_sid_to_context - Obtain a context for a given SID.
717 * @sid: security identifier, SID
718 * @scontext: security context
719 * @scontext_len: length in bytes
720 *
721 * Write the string representation of the context associated with @sid
722 * into a dynamically allocated string of the correct size. Set @scontext
723 * to point to this string and set @scontext_len to the length of the string.
724 */
725int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
726{
727 return security_sid_to_context_core(sid, scontext, scontext_len, 0);
728}
729
730int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len)
731{
732 return security_sid_to_context_core(sid, scontext, scontext_len, 1);
733}
734
735/*
736 * Caveat: Mutates scontext.
737 */
738static int string_to_context_struct(struct policydb *pol,
739 struct sidtab *sidtabp,
740 char *scontext,
741 u32 scontext_len,
742 struct context *ctx,
743 u32 def_sid)
713{ 744{
714 char *scontext2;
715 struct context context;
716 struct role_datum *role; 745 struct role_datum *role;
717 struct type_datum *typdatum; 746 struct type_datum *typdatum;
718 struct user_datum *usrdatum; 747 struct user_datum *usrdatum;
719 char *scontextp, *p, oldc; 748 char *scontextp, *p, oldc;
720 int rc = 0; 749 int rc = 0;
721 750
722 if (!ss_initialized) { 751 context_init(ctx);
723 int i;
724
725 for (i = 1; i < SECINITSID_NUM; i++) {
726 if (!strcmp(initial_sid_to_string[i], scontext)) {
727 *sid = i;
728 goto out;
729 }
730 }
731 *sid = SECINITSID_KERNEL;
732 goto out;
733 }
734 *sid = SECSID_NULL;
735
736 /* Copy the string so that we can modify the copy as we parse it.
737 The string should already by null terminated, but we append a
738 null suffix to the copy to avoid problems with the existing
739 attr package, which doesn't view the null terminator as part
740 of the attribute value. */
741 scontext2 = kmalloc(scontext_len+1, gfp_flags);
742 if (!scontext2) {
743 rc = -ENOMEM;
744 goto out;
745 }
746 memcpy(scontext2, scontext, scontext_len);
747 scontext2[scontext_len] = 0;
748
749 context_init(&context);
750 *sid = SECSID_NULL;
751
752 POLICY_RDLOCK;
753 752
754 /* Parse the security context. */ 753 /* Parse the security context. */
755 754
756 rc = -EINVAL; 755 rc = -EINVAL;
757 scontextp = (char *) scontext2; 756 scontextp = (char *) scontext;
758 757
759 /* Extract the user. */ 758 /* Extract the user. */
760 p = scontextp; 759 p = scontextp;
@@ -762,15 +761,15 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
762 p++; 761 p++;
763 762
764 if (*p == 0) 763 if (*p == 0)
765 goto out_unlock; 764 goto out;
766 765
767 *p++ = 0; 766 *p++ = 0;
768 767
769 usrdatum = hashtab_search(policydb.p_users.table, scontextp); 768 usrdatum = hashtab_search(pol->p_users.table, scontextp);
770 if (!usrdatum) 769 if (!usrdatum)
771 goto out_unlock; 770 goto out;
772 771
773 context.user = usrdatum->value; 772 ctx->user = usrdatum->value;
774 773
775 /* Extract role. */ 774 /* Extract role. */
776 scontextp = p; 775 scontextp = p;
@@ -778,14 +777,14 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
778 p++; 777 p++;
779 778
780 if (*p == 0) 779 if (*p == 0)
781 goto out_unlock; 780 goto out;
782 781
783 *p++ = 0; 782 *p++ = 0;
784 783
785 role = hashtab_search(policydb.p_roles.table, scontextp); 784 role = hashtab_search(pol->p_roles.table, scontextp);
786 if (!role) 785 if (!role)
787 goto out_unlock; 786 goto out;
788 context.role = role->value; 787 ctx->role = role->value;
789 788
790 /* Extract type. */ 789 /* Extract type. */
791 scontextp = p; 790 scontextp = p;
@@ -794,33 +793,87 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
794 oldc = *p; 793 oldc = *p;
795 *p++ = 0; 794 *p++ = 0;
796 795
797 typdatum = hashtab_search(policydb.p_types.table, scontextp); 796 typdatum = hashtab_search(pol->p_types.table, scontextp);
798 if (!typdatum) 797 if (!typdatum)
799 goto out_unlock; 798 goto out;
800 799
801 context.type = typdatum->value; 800 ctx->type = typdatum->value;
802 801
803 rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid); 802 rc = mls_context_to_sid(pol, oldc, &p, ctx, sidtabp, def_sid);
804 if (rc) 803 if (rc)
805 goto out_unlock; 804 goto out;
806 805
807 if ((p - scontext2) < scontext_len) { 806 if ((p - scontext) < scontext_len) {
808 rc = -EINVAL; 807 rc = -EINVAL;
809 goto out_unlock; 808 goto out;
810 } 809 }
811 810
812 /* Check the validity of the new context. */ 811 /* Check the validity of the new context. */
813 if (!policydb_context_isvalid(&policydb, &context)) { 812 if (!policydb_context_isvalid(pol, ctx)) {
814 rc = -EINVAL; 813 rc = -EINVAL;
815 goto out_unlock; 814 context_destroy(ctx);
815 goto out;
816 } 816 }
817 /* Obtain the new sid. */ 817 rc = 0;
818out:
819 return rc;
820}
821
822static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
823 u32 *sid, u32 def_sid, gfp_t gfp_flags,
824 int force)
825{
826 char *scontext2, *str = NULL;
827 struct context context;
828 int rc = 0;
829
830 if (!ss_initialized) {
831 int i;
832
833 for (i = 1; i < SECINITSID_NUM; i++) {
834 if (!strcmp(initial_sid_to_string[i], scontext)) {
835 *sid = i;
836 return 0;
837 }
838 }
839 *sid = SECINITSID_KERNEL;
840 return 0;
841 }
842 *sid = SECSID_NULL;
843
844 /* Copy the string so that we can modify the copy as we parse it. */
845 scontext2 = kmalloc(scontext_len+1, gfp_flags);
846 if (!scontext2)
847 return -ENOMEM;
848 memcpy(scontext2, scontext, scontext_len);
849 scontext2[scontext_len] = 0;
850
851 if (force) {
852 /* Save another copy for storing in uninterpreted form */
853 str = kstrdup(scontext2, gfp_flags);
854 if (!str) {
855 kfree(scontext2);
856 return -ENOMEM;
857 }
858 }
859
860 read_lock(&policy_rwlock);
861 rc = string_to_context_struct(&policydb, &sidtab,
862 scontext2, scontext_len,
863 &context, def_sid);
864 if (rc == -EINVAL && force) {
865 context.str = str;
866 context.len = scontext_len;
867 str = NULL;
868 } else if (rc)
869 goto out;
818 rc = sidtab_context_to_sid(&sidtab, &context, sid); 870 rc = sidtab_context_to_sid(&sidtab, &context, sid);
819out_unlock: 871 if (rc)
820 POLICY_RDUNLOCK; 872 context_destroy(&context);
821 context_destroy(&context);
822 kfree(scontext2);
823out: 873out:
874 read_unlock(&policy_rwlock);
875 kfree(scontext2);
876 kfree(str);
824 return rc; 877 return rc;
825} 878}
826 879
@@ -838,7 +891,7 @@ out:
838int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid) 891int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
839{ 892{
840 return security_context_to_sid_core(scontext, scontext_len, 893 return security_context_to_sid_core(scontext, scontext_len,
841 sid, SECSID_NULL, GFP_KERNEL); 894 sid, SECSID_NULL, GFP_KERNEL, 0);
842} 895}
843 896
844/** 897/**
@@ -855,6 +908,7 @@ int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
855 * The default SID is passed to the MLS layer to be used to allow 908 * The default SID is passed to the MLS layer to be used to allow
856 * kernel labeling of the MLS field if the MLS field is not present 909 * kernel labeling of the MLS field if the MLS field is not present
857 * (for upgrading to MLS without full relabel). 910 * (for upgrading to MLS without full relabel).
911 * Implicitly forces adding of the context even if it cannot be mapped yet.
858 * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient 912 * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
859 * memory is available, or 0 on success. 913 * memory is available, or 0 on success.
860 */ 914 */
@@ -862,7 +916,14 @@ int security_context_to_sid_default(const char *scontext, u32 scontext_len,
862 u32 *sid, u32 def_sid, gfp_t gfp_flags) 916 u32 *sid, u32 def_sid, gfp_t gfp_flags)
863{ 917{
864 return security_context_to_sid_core(scontext, scontext_len, 918 return security_context_to_sid_core(scontext, scontext_len,
865 sid, def_sid, gfp_flags); 919 sid, def_sid, gfp_flags, 1);
920}
921
922int security_context_to_sid_force(const char *scontext, u32 scontext_len,
923 u32 *sid)
924{
925 return security_context_to_sid_core(scontext, scontext_len,
926 sid, SECSID_NULL, GFP_KERNEL, 1);
866} 927}
867 928
868static int compute_sid_handle_invalid_context( 929static int compute_sid_handle_invalid_context(
@@ -922,7 +983,7 @@ static int security_compute_sid(u32 ssid,
922 983
923 context_init(&newcontext); 984 context_init(&newcontext);
924 985
925 POLICY_RDLOCK; 986 read_lock(&policy_rwlock);
926 987
927 scontext = sidtab_search(&sidtab, ssid); 988 scontext = sidtab_search(&sidtab, ssid);
928 if (!scontext) { 989 if (!scontext) {
@@ -1027,7 +1088,7 @@ static int security_compute_sid(u32 ssid,
1027 /* Obtain the sid for the context. */ 1088 /* Obtain the sid for the context. */
1028 rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid); 1089 rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
1029out_unlock: 1090out_unlock:
1030 POLICY_RDUNLOCK; 1091 read_unlock(&policy_rwlock);
1031 context_destroy(&newcontext); 1092 context_destroy(&newcontext);
1032out: 1093out:
1033 return rc; 1094 return rc;
@@ -1110,6 +1171,7 @@ static int validate_classes(struct policydb *p)
1110 const struct selinux_class_perm *kdefs = &selinux_class_perm; 1171 const struct selinux_class_perm *kdefs = &selinux_class_perm;
1111 const char *def_class, *def_perm, *pol_class; 1172 const char *def_class, *def_perm, *pol_class;
1112 struct symtab *perms; 1173 struct symtab *perms;
1174 bool print_unknown_handle = 0;
1113 1175
1114 if (p->allow_unknown) { 1176 if (p->allow_unknown) {
1115 u32 num_classes = kdefs->cts_len; 1177 u32 num_classes = kdefs->cts_len;
@@ -1130,6 +1192,7 @@ static int validate_classes(struct policydb *p)
1130 return -EINVAL; 1192 return -EINVAL;
1131 if (p->allow_unknown) 1193 if (p->allow_unknown)
1132 p->undefined_perms[i-1] = ~0U; 1194 p->undefined_perms[i-1] = ~0U;
1195 print_unknown_handle = 1;
1133 continue; 1196 continue;
1134 } 1197 }
1135 pol_class = p->p_class_val_to_name[i-1]; 1198 pol_class = p->p_class_val_to_name[i-1];
@@ -1159,6 +1222,7 @@ static int validate_classes(struct policydb *p)
1159 return -EINVAL; 1222 return -EINVAL;
1160 if (p->allow_unknown) 1223 if (p->allow_unknown)
1161 p->undefined_perms[class_val-1] |= perm_val; 1224 p->undefined_perms[class_val-1] |= perm_val;
1225 print_unknown_handle = 1;
1162 continue; 1226 continue;
1163 } 1227 }
1164 perdatum = hashtab_search(perms->table, def_perm); 1228 perdatum = hashtab_search(perms->table, def_perm);
@@ -1206,6 +1270,7 @@ static int validate_classes(struct policydb *p)
1206 return -EINVAL; 1270 return -EINVAL;
1207 if (p->allow_unknown) 1271 if (p->allow_unknown)
1208 p->undefined_perms[class_val-1] |= (1 << j); 1272 p->undefined_perms[class_val-1] |= (1 << j);
1273 print_unknown_handle = 1;
1209 continue; 1274 continue;
1210 } 1275 }
1211 perdatum = hashtab_search(perms->table, def_perm); 1276 perdatum = hashtab_search(perms->table, def_perm);
@@ -1223,6 +1288,9 @@ static int validate_classes(struct policydb *p)
1223 } 1288 }
1224 } 1289 }
1225 } 1290 }
1291 if (print_unknown_handle)
1292 printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n",
1293 (security_get_allow_unknown() ? "allowed" : "denied"));
1226 return 0; 1294 return 0;
1227} 1295}
1228 1296
@@ -1246,9 +1314,12 @@ static inline int convert_context_handle_invalid_context(struct context *context
1246 char *s; 1314 char *s;
1247 u32 len; 1315 u32 len;
1248 1316
1249 context_struct_to_string(context, &s, &len); 1317 if (!context_struct_to_string(context, &s, &len)) {
1250 printk(KERN_ERR "SELinux: context %s is invalid\n", s); 1318 printk(KERN_WARNING
1251 kfree(s); 1319 "SELinux: Context %s would be invalid if enforcing\n",
1320 s);
1321 kfree(s);
1322 }
1252 } 1323 }
1253 return rc; 1324 return rc;
1254} 1325}
@@ -1280,6 +1351,37 @@ static int convert_context(u32 key,
1280 1351
1281 args = p; 1352 args = p;
1282 1353
1354 if (c->str) {
1355 struct context ctx;
1356 s = kstrdup(c->str, GFP_KERNEL);
1357 if (!s) {
1358 rc = -ENOMEM;
1359 goto out;
1360 }
1361 rc = string_to_context_struct(args->newp, NULL, s,
1362 c->len, &ctx, SECSID_NULL);
1363 kfree(s);
1364 if (!rc) {
1365 printk(KERN_INFO
1366 "SELinux: Context %s became valid (mapped).\n",
1367 c->str);
1368 /* Replace string with mapped representation. */
1369 kfree(c->str);
1370 memcpy(c, &ctx, sizeof(*c));
1371 goto out;
1372 } else if (rc == -EINVAL) {
1373 /* Retain string representation for later mapping. */
1374 rc = 0;
1375 goto out;
1376 } else {
1377 /* Other error condition, e.g. ENOMEM. */
1378 printk(KERN_ERR
1379 "SELinux: Unable to map context %s, rc = %d.\n",
1380 c->str, -rc);
1381 goto out;
1382 }
1383 }
1384
1283 rc = context_cpy(&oldc, c); 1385 rc = context_cpy(&oldc, c);
1284 if (rc) 1386 if (rc)
1285 goto out; 1387 goto out;
@@ -1319,13 +1421,21 @@ static int convert_context(u32 key,
1319 } 1421 }
1320 1422
1321 context_destroy(&oldc); 1423 context_destroy(&oldc);
1424 rc = 0;
1322out: 1425out:
1323 return rc; 1426 return rc;
1324bad: 1427bad:
1325 context_struct_to_string(&oldc, &s, &len); 1428 /* Map old representation to string and save it. */
1429 if (context_struct_to_string(&oldc, &s, &len))
1430 return -ENOMEM;
1326 context_destroy(&oldc); 1431 context_destroy(&oldc);
1327 printk(KERN_ERR "SELinux: invalidating context %s\n", s); 1432 context_destroy(c);
1328 kfree(s); 1433 c->str = s;
1434 c->len = len;
1435 printk(KERN_INFO
1436 "SELinux: Context %s became invalid (unmapped).\n",
1437 c->str);
1438 rc = 0;
1329 goto out; 1439 goto out;
1330} 1440}
1331 1441
@@ -1359,17 +1469,13 @@ int security_load_policy(void *data, size_t len)
1359 int rc = 0; 1469 int rc = 0;
1360 struct policy_file file = { data, len }, *fp = &file; 1470 struct policy_file file = { data, len }, *fp = &file;
1361 1471
1362 LOAD_LOCK;
1363
1364 if (!ss_initialized) { 1472 if (!ss_initialized) {
1365 avtab_cache_init(); 1473 avtab_cache_init();
1366 if (policydb_read(&policydb, fp)) { 1474 if (policydb_read(&policydb, fp)) {
1367 LOAD_UNLOCK;
1368 avtab_cache_destroy(); 1475 avtab_cache_destroy();
1369 return -EINVAL; 1476 return -EINVAL;
1370 } 1477 }
1371 if (policydb_load_isids(&policydb, &sidtab)) { 1478 if (policydb_load_isids(&policydb, &sidtab)) {
1372 LOAD_UNLOCK;
1373 policydb_destroy(&policydb); 1479 policydb_destroy(&policydb);
1374 avtab_cache_destroy(); 1480 avtab_cache_destroy();
1375 return -EINVAL; 1481 return -EINVAL;
@@ -1378,7 +1484,6 @@ int security_load_policy(void *data, size_t len)
1378 if (validate_classes(&policydb)) { 1484 if (validate_classes(&policydb)) {
1379 printk(KERN_ERR 1485 printk(KERN_ERR
1380 "SELinux: the definition of a class is incorrect\n"); 1486 "SELinux: the definition of a class is incorrect\n");
1381 LOAD_UNLOCK;
1382 sidtab_destroy(&sidtab); 1487 sidtab_destroy(&sidtab);
1383 policydb_destroy(&policydb); 1488 policydb_destroy(&policydb);
1384 avtab_cache_destroy(); 1489 avtab_cache_destroy();
@@ -1388,7 +1493,6 @@ int security_load_policy(void *data, size_t len)
1388 policydb_loaded_version = policydb.policyvers; 1493 policydb_loaded_version = policydb.policyvers;
1389 ss_initialized = 1; 1494 ss_initialized = 1;
1390 seqno = ++latest_granting; 1495 seqno = ++latest_granting;
1391 LOAD_UNLOCK;
1392 selinux_complete_init(); 1496 selinux_complete_init();
1393 avc_ss_reset(seqno); 1497 avc_ss_reset(seqno);
1394 selnl_notify_policyload(seqno); 1498 selnl_notify_policyload(seqno);
@@ -1401,12 +1505,13 @@ int security_load_policy(void *data, size_t len)
1401 sidtab_hash_eval(&sidtab, "sids"); 1505 sidtab_hash_eval(&sidtab, "sids");
1402#endif 1506#endif
1403 1507
1404 if (policydb_read(&newpolicydb, fp)) { 1508 if (policydb_read(&newpolicydb, fp))
1405 LOAD_UNLOCK;
1406 return -EINVAL; 1509 return -EINVAL;
1407 }
1408 1510
1409 sidtab_init(&newsidtab); 1511 if (sidtab_init(&newsidtab)) {
1512 policydb_destroy(&newpolicydb);
1513 return -ENOMEM;
1514 }
1410 1515
1411 /* Verify that the kernel defined classes are correct. */ 1516 /* Verify that the kernel defined classes are correct. */
1412 if (validate_classes(&newpolicydb)) { 1517 if (validate_classes(&newpolicydb)) {
@@ -1429,25 +1534,28 @@ int security_load_policy(void *data, size_t len)
1429 goto err; 1534 goto err;
1430 } 1535 }
1431 1536
1432 /* Convert the internal representations of contexts 1537 /*
1433 in the new SID table and remove invalid SIDs. */ 1538 * Convert the internal representations of contexts
1539 * in the new SID table.
1540 */
1434 args.oldp = &policydb; 1541 args.oldp = &policydb;
1435 args.newp = &newpolicydb; 1542 args.newp = &newpolicydb;
1436 sidtab_map_remove_on_error(&newsidtab, convert_context, &args); 1543 rc = sidtab_map(&newsidtab, convert_context, &args);
1544 if (rc)
1545 goto err;
1437 1546
1438 /* Save the old policydb and SID table to free later. */ 1547 /* Save the old policydb and SID table to free later. */
1439 memcpy(&oldpolicydb, &policydb, sizeof policydb); 1548 memcpy(&oldpolicydb, &policydb, sizeof policydb);
1440 sidtab_set(&oldsidtab, &sidtab); 1549 sidtab_set(&oldsidtab, &sidtab);
1441 1550
1442 /* Install the new policydb and SID table. */ 1551 /* Install the new policydb and SID table. */
1443 POLICY_WRLOCK; 1552 write_lock_irq(&policy_rwlock);
1444 memcpy(&policydb, &newpolicydb, sizeof policydb); 1553 memcpy(&policydb, &newpolicydb, sizeof policydb);
1445 sidtab_set(&sidtab, &newsidtab); 1554 sidtab_set(&sidtab, &newsidtab);
1446 security_load_policycaps(); 1555 security_load_policycaps();
1447 seqno = ++latest_granting; 1556 seqno = ++latest_granting;
1448 policydb_loaded_version = policydb.policyvers; 1557 policydb_loaded_version = policydb.policyvers;
1449 POLICY_WRUNLOCK; 1558 write_unlock_irq(&policy_rwlock);
1450 LOAD_UNLOCK;
1451 1559
1452 /* Free the old policydb and SID table. */ 1560 /* Free the old policydb and SID table. */
1453 policydb_destroy(&oldpolicydb); 1561 policydb_destroy(&oldpolicydb);
@@ -1461,7 +1569,6 @@ int security_load_policy(void *data, size_t len)
1461 return 0; 1569 return 0;
1462 1570
1463err: 1571err:
1464 LOAD_UNLOCK;
1465 sidtab_destroy(&newsidtab); 1572 sidtab_destroy(&newsidtab);
1466 policydb_destroy(&newpolicydb); 1573 policydb_destroy(&newpolicydb);
1467 return rc; 1574 return rc;
@@ -1479,7 +1586,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
1479 struct ocontext *c; 1586 struct ocontext *c;
1480 int rc = 0; 1587 int rc = 0;
1481 1588
1482 POLICY_RDLOCK; 1589 read_lock(&policy_rwlock);
1483 1590
1484 c = policydb.ocontexts[OCON_PORT]; 1591 c = policydb.ocontexts[OCON_PORT];
1485 while (c) { 1592 while (c) {
@@ -1504,7 +1611,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
1504 } 1611 }
1505 1612
1506out: 1613out:
1507 POLICY_RDUNLOCK; 1614 read_unlock(&policy_rwlock);
1508 return rc; 1615 return rc;
1509} 1616}
1510 1617
@@ -1518,7 +1625,7 @@ int security_netif_sid(char *name, u32 *if_sid)
1518 int rc = 0; 1625 int rc = 0;
1519 struct ocontext *c; 1626 struct ocontext *c;
1520 1627
1521 POLICY_RDLOCK; 1628 read_lock(&policy_rwlock);
1522 1629
1523 c = policydb.ocontexts[OCON_NETIF]; 1630 c = policydb.ocontexts[OCON_NETIF];
1524 while (c) { 1631 while (c) {
@@ -1545,7 +1652,7 @@ int security_netif_sid(char *name, u32 *if_sid)
1545 *if_sid = SECINITSID_NETIF; 1652 *if_sid = SECINITSID_NETIF;
1546 1653
1547out: 1654out:
1548 POLICY_RDUNLOCK; 1655 read_unlock(&policy_rwlock);
1549 return rc; 1656 return rc;
1550} 1657}
1551 1658
@@ -1577,7 +1684,7 @@ int security_node_sid(u16 domain,
1577 int rc = 0; 1684 int rc = 0;
1578 struct ocontext *c; 1685 struct ocontext *c;
1579 1686
1580 POLICY_RDLOCK; 1687 read_lock(&policy_rwlock);
1581 1688
1582 switch (domain) { 1689 switch (domain) {
1583 case AF_INET: { 1690 case AF_INET: {
@@ -1632,7 +1739,7 @@ int security_node_sid(u16 domain,
1632 } 1739 }
1633 1740
1634out: 1741out:
1635 POLICY_RDUNLOCK; 1742 read_unlock(&policy_rwlock);
1636 return rc; 1743 return rc;
1637} 1744}
1638 1745
@@ -1671,7 +1778,9 @@ int security_get_user_sids(u32 fromsid,
1671 if (!ss_initialized) 1778 if (!ss_initialized)
1672 goto out; 1779 goto out;
1673 1780
1674 POLICY_RDLOCK; 1781 read_lock(&policy_rwlock);
1782
1783 context_init(&usercon);
1675 1784
1676 fromcon = sidtab_search(&sidtab, fromsid); 1785 fromcon = sidtab_search(&sidtab, fromsid);
1677 if (!fromcon) { 1786 if (!fromcon) {
@@ -1722,7 +1831,7 @@ int security_get_user_sids(u32 fromsid,
1722 } 1831 }
1723 1832
1724out_unlock: 1833out_unlock:
1725 POLICY_RDUNLOCK; 1834 read_unlock(&policy_rwlock);
1726 if (rc || !mynel) { 1835 if (rc || !mynel) {
1727 kfree(mysids); 1836 kfree(mysids);
1728 goto out; 1837 goto out;
@@ -1775,7 +1884,7 @@ int security_genfs_sid(const char *fstype,
1775 while (path[0] == '/' && path[1] == '/') 1884 while (path[0] == '/' && path[1] == '/')
1776 path++; 1885 path++;
1777 1886
1778 POLICY_RDLOCK; 1887 read_lock(&policy_rwlock);
1779 1888
1780 for (genfs = policydb.genfs; genfs; genfs = genfs->next) { 1889 for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
1781 cmp = strcmp(fstype, genfs->fstype); 1890 cmp = strcmp(fstype, genfs->fstype);
@@ -1812,7 +1921,7 @@ int security_genfs_sid(const char *fstype,
1812 1921
1813 *sid = c->sid[0]; 1922 *sid = c->sid[0];
1814out: 1923out:
1815 POLICY_RDUNLOCK; 1924 read_unlock(&policy_rwlock);
1816 return rc; 1925 return rc;
1817} 1926}
1818 1927
@@ -1825,12 +1934,13 @@ out:
1825int security_fs_use( 1934int security_fs_use(
1826 const char *fstype, 1935 const char *fstype,
1827 unsigned int *behavior, 1936 unsigned int *behavior,
1828 u32 *sid) 1937 u32 *sid,
1938 bool can_xattr)
1829{ 1939{
1830 int rc = 0; 1940 int rc = 0;
1831 struct ocontext *c; 1941 struct ocontext *c;
1832 1942
1833 POLICY_RDLOCK; 1943 read_lock(&policy_rwlock);
1834 1944
1835 c = policydb.ocontexts[OCON_FSUSE]; 1945 c = policydb.ocontexts[OCON_FSUSE];
1836 while (c) { 1946 while (c) {
@@ -1839,6 +1949,7 @@ int security_fs_use(
1839 c = c->next; 1949 c = c->next;
1840 } 1950 }
1841 1951
1952 /* look for labeling behavior defined in policy */
1842 if (c) { 1953 if (c) {
1843 *behavior = c->v.behavior; 1954 *behavior = c->v.behavior;
1844 if (!c->sid[0]) { 1955 if (!c->sid[0]) {
@@ -1849,18 +1960,27 @@ int security_fs_use(
1849 goto out; 1960 goto out;
1850 } 1961 }
1851 *sid = c->sid[0]; 1962 *sid = c->sid[0];
1963 goto out;
1964 }
1965
1966 /* labeling behavior not in policy, use xattrs if possible */
1967 if (can_xattr) {
1968 *behavior = SECURITY_FS_USE_XATTR;
1969 *sid = SECINITSID_FS;
1970 goto out;
1971 }
1972
1973 /* no behavior in policy and can't use xattrs, try GENFS */
1974 rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
1975 if (rc) {
1976 *behavior = SECURITY_FS_USE_NONE;
1977 rc = 0;
1852 } else { 1978 } else {
1853 rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid); 1979 *behavior = SECURITY_FS_USE_GENFS;
1854 if (rc) {
1855 *behavior = SECURITY_FS_USE_NONE;
1856 rc = 0;
1857 } else {
1858 *behavior = SECURITY_FS_USE_GENFS;
1859 }
1860 } 1980 }
1861 1981
1862out: 1982out:
1863 POLICY_RDUNLOCK; 1983 read_unlock(&policy_rwlock);
1864 return rc; 1984 return rc;
1865} 1985}
1866 1986
@@ -1868,7 +1988,7 @@ int security_get_bools(int *len, char ***names, int **values)
1868{ 1988{
1869 int i, rc = -ENOMEM; 1989 int i, rc = -ENOMEM;
1870 1990
1871 POLICY_RDLOCK; 1991 read_lock(&policy_rwlock);
1872 *names = NULL; 1992 *names = NULL;
1873 *values = NULL; 1993 *values = NULL;
1874 1994
@@ -1898,7 +2018,7 @@ int security_get_bools(int *len, char ***names, int **values)
1898 } 2018 }
1899 rc = 0; 2019 rc = 0;
1900out: 2020out:
1901 POLICY_RDUNLOCK; 2021 read_unlock(&policy_rwlock);
1902 return rc; 2022 return rc;
1903err: 2023err:
1904 if (*names) { 2024 if (*names) {
@@ -1916,7 +2036,7 @@ int security_set_bools(int len, int *values)
1916 int lenp, seqno = 0; 2036 int lenp, seqno = 0;
1917 struct cond_node *cur; 2037 struct cond_node *cur;
1918 2038
1919 POLICY_WRLOCK; 2039 write_lock_irq(&policy_rwlock);
1920 2040
1921 lenp = policydb.p_bools.nprim; 2041 lenp = policydb.p_bools.nprim;
1922 if (len != lenp) { 2042 if (len != lenp) {
@@ -1950,7 +2070,7 @@ int security_set_bools(int len, int *values)
1950 seqno = ++latest_granting; 2070 seqno = ++latest_granting;
1951 2071
1952out: 2072out:
1953 POLICY_WRUNLOCK; 2073 write_unlock_irq(&policy_rwlock);
1954 if (!rc) { 2074 if (!rc) {
1955 avc_ss_reset(seqno); 2075 avc_ss_reset(seqno);
1956 selnl_notify_policyload(seqno); 2076 selnl_notify_policyload(seqno);
@@ -1964,7 +2084,7 @@ int security_get_bool_value(int bool)
1964 int rc = 0; 2084 int rc = 0;
1965 int len; 2085 int len;
1966 2086
1967 POLICY_RDLOCK; 2087 read_lock(&policy_rwlock);
1968 2088
1969 len = policydb.p_bools.nprim; 2089 len = policydb.p_bools.nprim;
1970 if (bool >= len) { 2090 if (bool >= len) {
@@ -1974,7 +2094,7 @@ int security_get_bool_value(int bool)
1974 2094
1975 rc = policydb.bool_val_to_struct[bool]->state; 2095 rc = policydb.bool_val_to_struct[bool]->state;
1976out: 2096out:
1977 POLICY_RDUNLOCK; 2097 read_unlock(&policy_rwlock);
1978 return rc; 2098 return rc;
1979} 2099}
1980 2100
@@ -2029,7 +2149,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
2029 2149
2030 context_init(&newcon); 2150 context_init(&newcon);
2031 2151
2032 POLICY_RDLOCK; 2152 read_lock(&policy_rwlock);
2033 context1 = sidtab_search(&sidtab, sid); 2153 context1 = sidtab_search(&sidtab, sid);
2034 if (!context1) { 2154 if (!context1) {
2035 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", 2155 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
@@ -2071,7 +2191,7 @@ bad:
2071 } 2191 }
2072 2192
2073out_unlock: 2193out_unlock:
2074 POLICY_RDUNLOCK; 2194 read_unlock(&policy_rwlock);
2075 context_destroy(&newcon); 2195 context_destroy(&newcon);
2076out: 2196out:
2077 return rc; 2197 return rc;
@@ -2128,7 +2248,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
2128 return 0; 2248 return 0;
2129 } 2249 }
2130 2250
2131 POLICY_RDLOCK; 2251 read_lock(&policy_rwlock);
2132 2252
2133 nlbl_ctx = sidtab_search(&sidtab, nlbl_sid); 2253 nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
2134 if (!nlbl_ctx) { 2254 if (!nlbl_ctx) {
@@ -2147,7 +2267,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
2147 rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES); 2267 rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
2148 2268
2149out_slowpath: 2269out_slowpath:
2150 POLICY_RDUNLOCK; 2270 read_unlock(&policy_rwlock);
2151 if (rc == 0) 2271 if (rc == 0)
2152 /* at present NetLabel SIDs/labels really only carry MLS 2272 /* at present NetLabel SIDs/labels really only carry MLS
2153 * information so if the MLS portion of the NetLabel SID 2273 * information so if the MLS portion of the NetLabel SID
@@ -2177,7 +2297,7 @@ int security_get_classes(char ***classes, int *nclasses)
2177{ 2297{
2178 int rc = -ENOMEM; 2298 int rc = -ENOMEM;
2179 2299
2180 POLICY_RDLOCK; 2300 read_lock(&policy_rwlock);
2181 2301
2182 *nclasses = policydb.p_classes.nprim; 2302 *nclasses = policydb.p_classes.nprim;
2183 *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); 2303 *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
@@ -2194,7 +2314,7 @@ int security_get_classes(char ***classes, int *nclasses)
2194 } 2314 }
2195 2315
2196out: 2316out:
2197 POLICY_RDUNLOCK; 2317 read_unlock(&policy_rwlock);
2198 return rc; 2318 return rc;
2199} 2319}
2200 2320
@@ -2216,7 +2336,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
2216 int rc = -ENOMEM, i; 2336 int rc = -ENOMEM, i;
2217 struct class_datum *match; 2337 struct class_datum *match;
2218 2338
2219 POLICY_RDLOCK; 2339 read_lock(&policy_rwlock);
2220 2340
2221 match = hashtab_search(policydb.p_classes.table, class); 2341 match = hashtab_search(policydb.p_classes.table, class);
2222 if (!match) { 2342 if (!match) {
@@ -2244,11 +2364,11 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
2244 goto err; 2364 goto err;
2245 2365
2246out: 2366out:
2247 POLICY_RDUNLOCK; 2367 read_unlock(&policy_rwlock);
2248 return rc; 2368 return rc;
2249 2369
2250err: 2370err:
2251 POLICY_RDUNLOCK; 2371 read_unlock(&policy_rwlock);
2252 for (i = 0; i < *nperms; i++) 2372 for (i = 0; i < *nperms; i++)
2253 kfree((*perms)[i]); 2373 kfree((*perms)[i]);
2254 kfree(*perms); 2374 kfree(*perms);
@@ -2279,9 +2399,9 @@ int security_policycap_supported(unsigned int req_cap)
2279{ 2399{
2280 int rc; 2400 int rc;
2281 2401
2282 POLICY_RDLOCK; 2402 read_lock(&policy_rwlock);
2283 rc = ebitmap_get_bit(&policydb.policycaps, req_cap); 2403 rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
2284 POLICY_RDUNLOCK; 2404 read_unlock(&policy_rwlock);
2285 2405
2286 return rc; 2406 return rc;
2287} 2407}
@@ -2345,7 +2465,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
2345 2465
2346 context_init(&tmprule->au_ctxt); 2466 context_init(&tmprule->au_ctxt);
2347 2467
2348 POLICY_RDLOCK; 2468 read_lock(&policy_rwlock);
2349 2469
2350 tmprule->au_seqno = latest_granting; 2470 tmprule->au_seqno = latest_granting;
2351 2471
@@ -2382,7 +2502,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
2382 break; 2502 break;
2383 } 2503 }
2384 2504
2385 POLICY_RDUNLOCK; 2505 read_unlock(&policy_rwlock);
2386 2506
2387 if (rc) { 2507 if (rc) {
2388 selinux_audit_rule_free(tmprule); 2508 selinux_audit_rule_free(tmprule);
@@ -2420,7 +2540,7 @@ int selinux_audit_rule_known(struct audit_krule *rule)
2420} 2540}
2421 2541
2422int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, 2542int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
2423 struct audit_context *actx) 2543 struct audit_context *actx)
2424{ 2544{
2425 struct context *ctxt; 2545 struct context *ctxt;
2426 struct mls_level *level; 2546 struct mls_level *level;
@@ -2433,7 +2553,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
2433 return -ENOENT; 2553 return -ENOENT;
2434 } 2554 }
2435 2555
2436 POLICY_RDLOCK; 2556 read_lock(&policy_rwlock);
2437 2557
2438 if (rule->au_seqno < latest_granting) { 2558 if (rule->au_seqno < latest_granting) {
2439 audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, 2559 audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
@@ -2527,14 +2647,14 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
2527 } 2647 }
2528 2648
2529out: 2649out:
2530 POLICY_RDUNLOCK; 2650 read_unlock(&policy_rwlock);
2531 return match; 2651 return match;
2532} 2652}
2533 2653
2534static int (*aurule_callback)(void) = audit_update_lsm_rules; 2654static int (*aurule_callback)(void) = audit_update_lsm_rules;
2535 2655
2536static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, 2656static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
2537 u16 class, u32 perms, u32 *retained) 2657 u16 class, u32 perms, u32 *retained)
2538{ 2658{
2539 int err = 0; 2659 int err = 0;
2540 2660
@@ -2615,7 +2735,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2615 return 0; 2735 return 0;
2616 } 2736 }
2617 2737
2618 POLICY_RDLOCK; 2738 read_lock(&policy_rwlock);
2619 2739
2620 if (secattr->flags & NETLBL_SECATTR_CACHE) { 2740 if (secattr->flags & NETLBL_SECATTR_CACHE) {
2621 *sid = *(u32 *)secattr->cache->data; 2741 *sid = *(u32 *)secattr->cache->data;
@@ -2660,7 +2780,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2660 } 2780 }
2661 2781
2662netlbl_secattr_to_sid_return: 2782netlbl_secattr_to_sid_return:
2663 POLICY_RDUNLOCK; 2783 read_unlock(&policy_rwlock);
2664 return rc; 2784 return rc;
2665netlbl_secattr_to_sid_return_cleanup: 2785netlbl_secattr_to_sid_return_cleanup:
2666 ebitmap_destroy(&ctx_new.range.level[0].cat); 2786 ebitmap_destroy(&ctx_new.range.level[0].cat);
@@ -2685,7 +2805,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2685 if (!ss_initialized) 2805 if (!ss_initialized)
2686 return 0; 2806 return 0;
2687 2807
2688 POLICY_RDLOCK; 2808 read_lock(&policy_rwlock);
2689 ctx = sidtab_search(&sidtab, sid); 2809 ctx = sidtab_search(&sidtab, sid);
2690 if (ctx == NULL) 2810 if (ctx == NULL)
2691 goto netlbl_sid_to_secattr_failure; 2811 goto netlbl_sid_to_secattr_failure;
@@ -2696,12 +2816,12 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2696 rc = mls_export_netlbl_cat(ctx, secattr); 2816 rc = mls_export_netlbl_cat(ctx, secattr);
2697 if (rc != 0) 2817 if (rc != 0)
2698 goto netlbl_sid_to_secattr_failure; 2818 goto netlbl_sid_to_secattr_failure;
2699 POLICY_RDUNLOCK; 2819 read_unlock(&policy_rwlock);
2700 2820
2701 return 0; 2821 return 0;
2702 2822
2703netlbl_sid_to_secattr_failure: 2823netlbl_sid_to_secattr_failure:
2704 POLICY_RDUNLOCK; 2824 read_unlock(&policy_rwlock);
2705 return rc; 2825 return rc;
2706} 2826}
2707#endif /* CONFIG_NETLABEL */ 2827#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index 4a516ff4bcde..a81ded104129 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -14,10 +14,6 @@
14#define SIDTAB_HASH(sid) \ 14#define SIDTAB_HASH(sid) \
15(sid & SIDTAB_HASH_MASK) 15(sid & SIDTAB_HASH_MASK)
16 16
17#define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)
18#define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)
19#define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)
20
21int sidtab_init(struct sidtab *s) 17int sidtab_init(struct sidtab *s)
22{ 18{
23 int i; 19 int i;
@@ -30,7 +26,7 @@ int sidtab_init(struct sidtab *s)
30 s->nel = 0; 26 s->nel = 0;
31 s->next_sid = 1; 27 s->next_sid = 1;
32 s->shutdown = 0; 28 s->shutdown = 0;
33 INIT_SIDTAB_LOCK(s); 29 spin_lock_init(&s->lock);
34 return 0; 30 return 0;
35} 31}
36 32
@@ -86,7 +82,7 @@ out:
86 return rc; 82 return rc;
87} 83}
88 84
89struct context *sidtab_search(struct sidtab *s, u32 sid) 85static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
90{ 86{
91 int hvalue; 87 int hvalue;
92 struct sidtab_node *cur; 88 struct sidtab_node *cur;
@@ -99,7 +95,10 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
99 while (cur != NULL && sid > cur->sid) 95 while (cur != NULL && sid > cur->sid)
100 cur = cur->next; 96 cur = cur->next;
101 97
102 if (cur == NULL || sid != cur->sid) { 98 if (force && cur && sid == cur->sid && cur->context.len)
99 return &cur->context;
100
101 if (cur == NULL || sid != cur->sid || cur->context.len) {
103 /* Remap invalid SIDs to the unlabeled SID. */ 102 /* Remap invalid SIDs to the unlabeled SID. */
104 sid = SECINITSID_UNLABELED; 103 sid = SECINITSID_UNLABELED;
105 hvalue = SIDTAB_HASH(sid); 104 hvalue = SIDTAB_HASH(sid);
@@ -113,6 +112,16 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
113 return &cur->context; 112 return &cur->context;
114} 113}
115 114
115struct context *sidtab_search(struct sidtab *s, u32 sid)
116{
117 return sidtab_search_core(s, sid, 0);
118}
119
120struct context *sidtab_search_force(struct sidtab *s, u32 sid)
121{
122 return sidtab_search_core(s, sid, 1);
123}
124
116int sidtab_map(struct sidtab *s, 125int sidtab_map(struct sidtab *s,
117 int (*apply) (u32 sid, 126 int (*apply) (u32 sid,
118 struct context *context, 127 struct context *context,
@@ -138,43 +147,6 @@ out:
138 return rc; 147 return rc;
139} 148}
140 149
141void sidtab_map_remove_on_error(struct sidtab *s,
142 int (*apply) (u32 sid,
143 struct context *context,
144 void *args),
145 void *args)
146{
147 int i, ret;
148 struct sidtab_node *last, *cur, *temp;
149
150 if (!s)
151 return;
152
153 for (i = 0; i < SIDTAB_SIZE; i++) {
154 last = NULL;
155 cur = s->htable[i];
156 while (cur != NULL) {
157 ret = apply(cur->sid, &cur->context, args);
158 if (ret) {
159 if (last)
160 last->next = cur->next;
161 else
162 s->htable[i] = cur->next;
163 temp = cur;
164 cur = cur->next;
165 context_destroy(&temp->context);
166 kfree(temp);
167 s->nel--;
168 } else {
169 last = cur;
170 cur = cur->next;
171 }
172 }
173 }
174
175 return;
176}
177
178static inline u32 sidtab_search_context(struct sidtab *s, 150static inline u32 sidtab_search_context(struct sidtab *s,
179 struct context *context) 151 struct context *context)
180{ 152{
@@ -204,7 +176,7 @@ int sidtab_context_to_sid(struct sidtab *s,
204 176
205 sid = sidtab_search_context(s, context); 177 sid = sidtab_search_context(s, context);
206 if (!sid) { 178 if (!sid) {
207 SIDTAB_LOCK(s, flags); 179 spin_lock_irqsave(&s->lock, flags);
208 /* Rescan now that we hold the lock. */ 180 /* Rescan now that we hold the lock. */
209 sid = sidtab_search_context(s, context); 181 sid = sidtab_search_context(s, context);
210 if (sid) 182 if (sid)
@@ -215,11 +187,15 @@ int sidtab_context_to_sid(struct sidtab *s,
215 goto unlock_out; 187 goto unlock_out;
216 } 188 }
217 sid = s->next_sid++; 189 sid = s->next_sid++;
190 if (context->len)
191 printk(KERN_INFO
192 "SELinux: Context %s is not valid (left unmapped).\n",
193 context->str);
218 ret = sidtab_insert(s, sid, context); 194 ret = sidtab_insert(s, sid, context);
219 if (ret) 195 if (ret)
220 s->next_sid--; 196 s->next_sid--;
221unlock_out: 197unlock_out:
222 SIDTAB_UNLOCK(s, flags); 198 spin_unlock_irqrestore(&s->lock, flags);
223 } 199 }
224 200
225 if (ret) 201 if (ret)
@@ -284,19 +260,19 @@ void sidtab_set(struct sidtab *dst, struct sidtab *src)
284{ 260{
285 unsigned long flags; 261 unsigned long flags;
286 262
287 SIDTAB_LOCK(src, flags); 263 spin_lock_irqsave(&src->lock, flags);
288 dst->htable = src->htable; 264 dst->htable = src->htable;
289 dst->nel = src->nel; 265 dst->nel = src->nel;
290 dst->next_sid = src->next_sid; 266 dst->next_sid = src->next_sid;
291 dst->shutdown = 0; 267 dst->shutdown = 0;
292 SIDTAB_UNLOCK(src, flags); 268 spin_unlock_irqrestore(&src->lock, flags);
293} 269}
294 270
295void sidtab_shutdown(struct sidtab *s) 271void sidtab_shutdown(struct sidtab *s)
296{ 272{
297 unsigned long flags; 273 unsigned long flags;
298 274
299 SIDTAB_LOCK(s, flags); 275 spin_lock_irqsave(&s->lock, flags);
300 s->shutdown = 1; 276 s->shutdown = 1;
301 SIDTAB_UNLOCK(s, flags); 277 spin_unlock_irqrestore(&s->lock, flags);
302} 278}
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h
index 2fe9dfa3eb3a..64ea5b1cdea4 100644
--- a/security/selinux/ss/sidtab.h
+++ b/security/selinux/ss/sidtab.h
@@ -32,6 +32,7 @@ struct sidtab {
32int sidtab_init(struct sidtab *s); 32int sidtab_init(struct sidtab *s);
33int sidtab_insert(struct sidtab *s, u32 sid, struct context *context); 33int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);
34struct context *sidtab_search(struct sidtab *s, u32 sid); 34struct context *sidtab_search(struct sidtab *s, u32 sid);
35struct context *sidtab_search_force(struct sidtab *s, u32 sid);
35 36
36int sidtab_map(struct sidtab *s, 37int sidtab_map(struct sidtab *s,
37 int (*apply) (u32 sid, 38 int (*apply) (u32 sid,
@@ -39,12 +40,6 @@ int sidtab_map(struct sidtab *s,
39 void *args), 40 void *args),
40 void *args); 41 void *args);
41 42
42void sidtab_map_remove_on_error(struct sidtab *s,
43 int (*apply) (u32 sid,
44 struct context *context,
45 void *args),
46 void *args);
47
48int sidtab_context_to_sid(struct sidtab *s, 43int sidtab_context_to_sid(struct sidtab *s,
49 struct context *context, 44 struct context *context,
50 u32 *sid); 45 u32 *sid);