diff options
| author | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-28 08:29:59 -0400 |
|---|---|---|
| committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-28 08:29:59 -0400 |
| commit | 185a257f2f73bcd89050ad02da5bedbc28fc43fa (patch) | |
| tree | 5e32586114534ed3f2165614cba3d578f5d87307 /security | |
| parent | 3f1a9aaeffd8d1cbc5ab9776c45cbd66af1c9699 (diff) | |
| parent | a77c64c1a641950626181b4857abb701d8f38ccc (diff) | |
Merge branch 'master' into gfs2
Diffstat (limited to 'security')
| -rw-r--r-- | security/inode.c | 9 | ||||
| -rw-r--r-- | security/selinux/Kconfig | 37 | ||||
| -rw-r--r-- | security/selinux/exports.c | 13 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 69 | ||||
| -rw-r--r-- | security/selinux/include/objsec.h | 4 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 7 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 1 | ||||
| -rw-r--r-- | security/selinux/ss/mls.c | 21 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.c | 27 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.h | 7 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 30 |
11 files changed, 133 insertions, 92 deletions
diff --git a/security/inode.c b/security/inode.c index 47eb63480dac..49ee51529396 100644 --- a/security/inode.c +++ b/security/inode.c | |||
| @@ -44,8 +44,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf, | |||
| 44 | 44 | ||
| 45 | static int default_open(struct inode *inode, struct file *file) | 45 | static int default_open(struct inode *inode, struct file *file) |
| 46 | { | 46 | { |
| 47 | if (inode->u.generic_ip) | 47 | if (inode->i_private) |
| 48 | file->private_data = inode->u.generic_ip; | 48 | file->private_data = inode->i_private; |
| 49 | 49 | ||
| 50 | return 0; | 50 | return 0; |
| 51 | } | 51 | } |
| @@ -64,7 +64,6 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev) | |||
| 64 | inode->i_mode = mode; | 64 | inode->i_mode = mode; |
| 65 | inode->i_uid = 0; | 65 | inode->i_uid = 0; |
| 66 | inode->i_gid = 0; | 66 | inode->i_gid = 0; |
| 67 | inode->i_blksize = PAGE_CACHE_SIZE; | ||
| 68 | inode->i_blocks = 0; | 67 | inode->i_blocks = 0; |
| 69 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 68 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
| 70 | switch (mode & S_IFMT) { | 69 | switch (mode & S_IFMT) { |
| @@ -194,7 +193,7 @@ static int create_by_name(const char *name, mode_t mode, | |||
| 194 | * directory dentry if set. If this paramater is NULL, then the | 193 | * directory dentry if set. If this paramater is NULL, then the |
| 195 | * file will be created in the root of the securityfs filesystem. | 194 | * file will be created in the root of the securityfs filesystem. |
| 196 | * @data: a pointer to something that the caller will want to get to later | 195 | * @data: a pointer to something that the caller will want to get to later |
| 197 | * on. The inode.u.generic_ip pointer will point to this value on | 196 | * on. The inode.i_private pointer will point to this value on |
| 198 | * the open() call. | 197 | * the open() call. |
| 199 | * @fops: a pointer to a struct file_operations that should be used for | 198 | * @fops: a pointer to a struct file_operations that should be used for |
| 200 | * this file. | 199 | * this file. |
| @@ -240,7 +239,7 @@ struct dentry *securityfs_create_file(const char *name, mode_t mode, | |||
| 240 | if (fops) | 239 | if (fops) |
| 241 | dentry->d_inode->i_fop = fops; | 240 | dentry->d_inode->i_fop = fops; |
| 242 | if (data) | 241 | if (data) |
| 243 | dentry->d_inode->u.generic_ip = data; | 242 | dentry->d_inode->i_private = data; |
| 244 | } | 243 | } |
| 245 | exit: | 244 | exit: |
| 246 | return dentry; | 245 | return dentry; |
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 814ddc42f1f4..293dbd6246c1 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig | |||
| @@ -124,3 +124,40 @@ config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT | |||
| 124 | 124 | ||
| 125 | If you are unsure what do do here, select N. | 125 | If you are unsure what do do here, select N. |
| 126 | 126 | ||
| 127 | config SECURITY_SELINUX_POLICYDB_VERSION_MAX | ||
| 128 | bool "NSA SELinux maximum supported policy format version" | ||
| 129 | depends on SECURITY_SELINUX | ||
| 130 | default n | ||
| 131 | help | ||
| 132 | This option enables the maximum policy format version supported | ||
| 133 | by SELinux to be set to a particular value. This value is reported | ||
| 134 | to userspace via /selinux/policyvers and used at policy load time. | ||
| 135 | It can be adjusted downward to support legacy userland (init) that | ||
| 136 | does not correctly handle kernels that support newer policy versions. | ||
| 137 | |||
| 138 | Examples: | ||
| 139 | For the Fedora Core 3 or 4 Linux distributions, enable this option | ||
| 140 | and set the value via the next option. For Fedore Core 5 and later, | ||
| 141 | do not enable this option. | ||
| 142 | |||
| 143 | If you are unsure how to answer this question, answer N. | ||
| 144 | |||
| 145 | config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | ||
| 146 | int "NSA SELinux maximum supported policy format version value" | ||
| 147 | depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX | ||
| 148 | range 15 21 | ||
| 149 | default 19 | ||
| 150 | help | ||
| 151 | This option sets the value for the maximum policy format version | ||
| 152 | supported by SELinux. | ||
| 153 | |||
| 154 | Examples: | ||
| 155 | For Fedora Core 3, use 18. | ||
| 156 | For Fedora Core 4, use 19. | ||
| 157 | |||
| 158 | If you are unsure how to answer this question, look for the | ||
| 159 | policy format version supported by your policy toolchain, by | ||
| 160 | running 'checkpolicy -V'. Or look at what policy you have | ||
| 161 | installed under /etc/selinux/$SELINUXTYPE/policy, where | ||
| 162 | SELINUXTYPE is defined in your /etc/selinux/config. | ||
| 163 | |||
diff --git a/security/selinux/exports.c b/security/selinux/exports.c index 9d7737db5e51..b6f96943be1f 100644 --- a/security/selinux/exports.c +++ b/security/selinux/exports.c | |||
| @@ -21,19 +21,10 @@ | |||
| 21 | #include "security.h" | 21 | #include "security.h" |
| 22 | #include "objsec.h" | 22 | #include "objsec.h" |
| 23 | 23 | ||
| 24 | void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid) | 24 | int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen) |
| 25 | { | 25 | { |
| 26 | struct task_security_struct *tsec = tsk->security; | ||
| 27 | if (selinux_enabled) | 26 | if (selinux_enabled) |
| 28 | *ctxid = tsec->sid; | 27 | return security_sid_to_context(sid, ctx, ctxlen); |
| 29 | else | ||
| 30 | *ctxid = 0; | ||
| 31 | } | ||
| 32 | |||
| 33 | int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen) | ||
| 34 | { | ||
| 35 | if (selinux_enabled) | ||
| 36 | return security_sid_to_context(ctxid, ctx, ctxlen); | ||
| 37 | else { | 28 | else { |
| 38 | *ctx = NULL; | 29 | *ctx = NULL; |
| 39 | *ctxlen = 0; | 30 | *ctxlen = 0; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5a66c4c09f7a..e4d81a42fca4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -51,7 +51,6 @@ | |||
| 51 | #include <net/ip.h> /* for sysctl_local_port_range[] */ | 51 | #include <net/ip.h> /* for sysctl_local_port_range[] */ |
| 52 | #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 */ |
| 53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
| 54 | #include <asm/semaphore.h> | ||
| 55 | #include <asm/ioctls.h> | 54 | #include <asm/ioctls.h> |
| 56 | #include <linux/bitops.h> | 55 | #include <linux/bitops.h> |
| 57 | #include <linux/interrupt.h> | 56 | #include <linux/interrupt.h> |
| @@ -71,6 +70,7 @@ | |||
| 71 | #include <linux/audit.h> | 70 | #include <linux/audit.h> |
| 72 | #include <linux/string.h> | 71 | #include <linux/string.h> |
| 73 | #include <linux/selinux.h> | 72 | #include <linux/selinux.h> |
| 73 | #include <linux/mutex.h> | ||
| 74 | 74 | ||
| 75 | #include "avc.h" | 75 | #include "avc.h" |
| 76 | #include "objsec.h" | 76 | #include "objsec.h" |
| @@ -185,7 +185,7 @@ static int inode_alloc_security(struct inode *inode) | |||
| 185 | return -ENOMEM; | 185 | return -ENOMEM; |
| 186 | 186 | ||
| 187 | memset(isec, 0, sizeof(*isec)); | 187 | memset(isec, 0, sizeof(*isec)); |
| 188 | init_MUTEX(&isec->sem); | 188 | mutex_init(&isec->lock); |
| 189 | INIT_LIST_HEAD(&isec->list); | 189 | INIT_LIST_HEAD(&isec->list); |
| 190 | isec->inode = inode; | 190 | isec->inode = inode; |
| 191 | isec->sid = SECINITSID_UNLABELED; | 191 | isec->sid = SECINITSID_UNLABELED; |
| @@ -242,7 +242,7 @@ static int superblock_alloc_security(struct super_block *sb) | |||
| 242 | if (!sbsec) | 242 | if (!sbsec) |
| 243 | return -ENOMEM; | 243 | return -ENOMEM; |
| 244 | 244 | ||
| 245 | init_MUTEX(&sbsec->sem); | 245 | mutex_init(&sbsec->lock); |
| 246 | INIT_LIST_HEAD(&sbsec->list); | 246 | INIT_LIST_HEAD(&sbsec->list); |
| 247 | INIT_LIST_HEAD(&sbsec->isec_head); | 247 | INIT_LIST_HEAD(&sbsec->isec_head); |
| 248 | spin_lock_init(&sbsec->isec_lock); | 248 | spin_lock_init(&sbsec->isec_lock); |
| @@ -594,7 +594,7 @@ static int superblock_doinit(struct super_block *sb, void *data) | |||
| 594 | struct inode *inode = root->d_inode; | 594 | struct inode *inode = root->d_inode; |
| 595 | int rc = 0; | 595 | int rc = 0; |
| 596 | 596 | ||
| 597 | down(&sbsec->sem); | 597 | mutex_lock(&sbsec->lock); |
| 598 | if (sbsec->initialized) | 598 | if (sbsec->initialized) |
| 599 | goto out; | 599 | goto out; |
| 600 | 600 | ||
| @@ -689,7 +689,7 @@ next_inode: | |||
| 689 | } | 689 | } |
| 690 | spin_unlock(&sbsec->isec_lock); | 690 | spin_unlock(&sbsec->isec_lock); |
| 691 | out: | 691 | out: |
| 692 | up(&sbsec->sem); | 692 | mutex_unlock(&sbsec->lock); |
| 693 | return rc; | 693 | return rc; |
| 694 | } | 694 | } |
| 695 | 695 | ||
| @@ -843,15 +843,13 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 843 | char *context = NULL; | 843 | char *context = NULL; |
| 844 | unsigned len = 0; | 844 | unsigned len = 0; |
| 845 | int rc = 0; | 845 | int rc = 0; |
| 846 | int hold_sem = 0; | ||
| 847 | 846 | ||
| 848 | if (isec->initialized) | 847 | if (isec->initialized) |
| 849 | goto out; | 848 | goto out; |
| 850 | 849 | ||
| 851 | down(&isec->sem); | 850 | mutex_lock(&isec->lock); |
| 852 | hold_sem = 1; | ||
| 853 | if (isec->initialized) | 851 | if (isec->initialized) |
| 854 | goto out; | 852 | goto out_unlock; |
| 855 | 853 | ||
| 856 | sbsec = inode->i_sb->s_security; | 854 | sbsec = inode->i_sb->s_security; |
| 857 | if (!sbsec->initialized) { | 855 | if (!sbsec->initialized) { |
| @@ -862,7 +860,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 862 | if (list_empty(&isec->list)) | 860 | if (list_empty(&isec->list)) |
| 863 | list_add(&isec->list, &sbsec->isec_head); | 861 | list_add(&isec->list, &sbsec->isec_head); |
| 864 | spin_unlock(&sbsec->isec_lock); | 862 | spin_unlock(&sbsec->isec_lock); |
| 865 | goto out; | 863 | goto out_unlock; |
| 866 | } | 864 | } |
| 867 | 865 | ||
| 868 | switch (sbsec->behavior) { | 866 | switch (sbsec->behavior) { |
| @@ -885,7 +883,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 885 | printk(KERN_WARNING "%s: no dentry for dev=%s " | 883 | printk(KERN_WARNING "%s: no dentry for dev=%s " |
| 886 | "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id, | 884 | "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id, |
| 887 | inode->i_ino); | 885 | inode->i_ino); |
| 888 | goto out; | 886 | goto out_unlock; |
| 889 | } | 887 | } |
| 890 | 888 | ||
| 891 | len = INITCONTEXTLEN; | 889 | len = INITCONTEXTLEN; |
| @@ -893,7 +891,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 893 | if (!context) { | 891 | if (!context) { |
| 894 | rc = -ENOMEM; | 892 | rc = -ENOMEM; |
| 895 | dput(dentry); | 893 | dput(dentry); |
| 896 | goto out; | 894 | goto out_unlock; |
| 897 | } | 895 | } |
| 898 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, | 896 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, |
| 899 | context, len); | 897 | context, len); |
| @@ -903,7 +901,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 903 | NULL, 0); | 901 | NULL, 0); |
| 904 | if (rc < 0) { | 902 | if (rc < 0) { |
| 905 | dput(dentry); | 903 | dput(dentry); |
| 906 | goto out; | 904 | goto out_unlock; |
| 907 | } | 905 | } |
| 908 | kfree(context); | 906 | kfree(context); |
| 909 | len = rc; | 907 | len = rc; |
| @@ -911,7 +909,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 911 | if (!context) { | 909 | if (!context) { |
| 912 | rc = -ENOMEM; | 910 | rc = -ENOMEM; |
| 913 | dput(dentry); | 911 | dput(dentry); |
| 914 | goto out; | 912 | goto out_unlock; |
| 915 | } | 913 | } |
| 916 | rc = inode->i_op->getxattr(dentry, | 914 | rc = inode->i_op->getxattr(dentry, |
| 917 | XATTR_NAME_SELINUX, | 915 | XATTR_NAME_SELINUX, |
| @@ -924,7 +922,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 924 | "%d for dev=%s ino=%ld\n", __FUNCTION__, | 922 | "%d for dev=%s ino=%ld\n", __FUNCTION__, |
| 925 | -rc, inode->i_sb->s_id, inode->i_ino); | 923 | -rc, inode->i_sb->s_id, inode->i_ino); |
| 926 | kfree(context); | 924 | kfree(context); |
| 927 | goto out; | 925 | goto out_unlock; |
| 928 | } | 926 | } |
| 929 | /* Map ENODATA to the default file SID */ | 927 | /* Map ENODATA to the default file SID */ |
| 930 | sid = sbsec->def_sid; | 928 | sid = sbsec->def_sid; |
| @@ -960,7 +958,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 960 | isec->sclass, | 958 | isec->sclass, |
| 961 | &sid); | 959 | &sid); |
| 962 | if (rc) | 960 | if (rc) |
| 963 | goto out; | 961 | goto out_unlock; |
| 964 | isec->sid = sid; | 962 | isec->sid = sid; |
| 965 | break; | 963 | break; |
| 966 | case SECURITY_FS_USE_MNTPOINT: | 964 | case SECURITY_FS_USE_MNTPOINT: |
| @@ -978,7 +976,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 978 | isec->sclass, | 976 | isec->sclass, |
| 979 | &sid); | 977 | &sid); |
| 980 | if (rc) | 978 | if (rc) |
| 981 | goto out; | 979 | goto out_unlock; |
| 982 | isec->sid = sid; | 980 | isec->sid = sid; |
| 983 | } | 981 | } |
| 984 | } | 982 | } |
| @@ -987,12 +985,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 987 | 985 | ||
| 988 | isec->initialized = 1; | 986 | isec->initialized = 1; |
| 989 | 987 | ||
| 988 | out_unlock: | ||
| 989 | mutex_unlock(&isec->lock); | ||
| 990 | out: | 990 | out: |
| 991 | if (isec->sclass == SECCLASS_FILE) | 991 | if (isec->sclass == SECCLASS_FILE) |
| 992 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 992 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
| 993 | |||
| 994 | if (hold_sem) | ||
| 995 | up(&isec->sem); | ||
| 996 | return rc; | 993 | return rc; |
| 997 | } | 994 | } |
| 998 | 995 | ||
| @@ -1364,25 +1361,6 @@ static inline u32 file_to_av(struct file *file) | |||
| 1364 | return av; | 1361 | return av; |
| 1365 | } | 1362 | } |
| 1366 | 1363 | ||
| 1367 | /* Set an inode's SID to a specified value. */ | ||
| 1368 | static int inode_security_set_sid(struct inode *inode, u32 sid) | ||
| 1369 | { | ||
| 1370 | struct inode_security_struct *isec = inode->i_security; | ||
| 1371 | struct superblock_security_struct *sbsec = inode->i_sb->s_security; | ||
| 1372 | |||
| 1373 | if (!sbsec->initialized) { | ||
| 1374 | /* Defer initialization to selinux_complete_init. */ | ||
| 1375 | return 0; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | down(&isec->sem); | ||
| 1379 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
| 1380 | isec->sid = sid; | ||
| 1381 | isec->initialized = 1; | ||
| 1382 | up(&isec->sem); | ||
| 1383 | return 0; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | /* Hook functions begin here. */ | 1364 | /* Hook functions begin here. */ |
| 1387 | 1365 | ||
| 1388 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) | 1366 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) |
| @@ -1711,10 +1689,12 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
| 1711 | { | 1689 | { |
| 1712 | struct avc_audit_data ad; | 1690 | struct avc_audit_data ad; |
| 1713 | struct file *file, *devnull = NULL; | 1691 | struct file *file, *devnull = NULL; |
| 1714 | struct tty_struct *tty = current->signal->tty; | 1692 | struct tty_struct *tty; |
| 1715 | struct fdtable *fdt; | 1693 | struct fdtable *fdt; |
| 1716 | long j = -1; | 1694 | long j = -1; |
| 1717 | 1695 | ||
| 1696 | mutex_lock(&tty_mutex); | ||
| 1697 | tty = current->signal->tty; | ||
| 1718 | if (tty) { | 1698 | if (tty) { |
| 1719 | file_list_lock(); | 1699 | file_list_lock(); |
| 1720 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); | 1700 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); |
| @@ -1734,6 +1714,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
| 1734 | } | 1714 | } |
| 1735 | file_list_unlock(); | 1715 | file_list_unlock(); |
| 1736 | } | 1716 | } |
| 1717 | mutex_unlock(&tty_mutex); | ||
| 1737 | 1718 | ||
| 1738 | /* Revalidate access to inherited open files. */ | 1719 | /* Revalidate access to inherited open files. */ |
| 1739 | 1720 | ||
| @@ -2091,7 +2072,13 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2091 | } | 2072 | } |
| 2092 | } | 2073 | } |
| 2093 | 2074 | ||
| 2094 | inode_security_set_sid(inode, newsid); | 2075 | /* Possibly defer initialization to selinux_complete_init. */ |
| 2076 | if (sbsec->initialized) { | ||
| 2077 | struct inode_security_struct *isec = inode->i_security; | ||
| 2078 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
| 2079 | isec->sid = newsid; | ||
| 2080 | isec->initialized = 1; | ||
| 2081 | } | ||
| 2095 | 2082 | ||
| 2096 | if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) | 2083 | if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) |
| 2097 | return -EOPNOTSUPP; | 2084 | return -EOPNOTSUPP; |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 0a39bfd1319f..ef2267fea8bd 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -44,7 +44,7 @@ struct inode_security_struct { | |||
| 44 | u32 sid; /* SID of this object */ | 44 | u32 sid; /* SID of this object */ |
| 45 | u16 sclass; /* security class of this object */ | 45 | u16 sclass; /* security class of this object */ |
| 46 | unsigned char initialized; /* initialization flag */ | 46 | unsigned char initialized; /* initialization flag */ |
| 47 | struct semaphore sem; | 47 | struct mutex lock; |
| 48 | unsigned char inherit; /* inherit SID from parent entry */ | 48 | unsigned char inherit; /* inherit SID from parent entry */ |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| @@ -63,7 +63,7 @@ struct superblock_security_struct { | |||
| 63 | unsigned int behavior; /* labeling behavior */ | 63 | unsigned int behavior; /* labeling behavior */ |
| 64 | unsigned char initialized; /* initialization flag */ | 64 | unsigned char initialized; /* initialization flag */ |
| 65 | unsigned char proc; /* proc fs */ | 65 | unsigned char proc; /* proc fs */ |
| 66 | struct semaphore sem; | 66 | struct mutex lock; |
| 67 | struct list_head isec_head; | 67 | struct list_head isec_head; |
| 68 | spinlock_t isec_lock; | 68 | spinlock_t isec_lock; |
| 69 | }; | 69 | }; |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 911954a692fa..1ef79172cc8c 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
| @@ -24,10 +24,15 @@ | |||
| 24 | #define POLICYDB_VERSION_VALIDATETRANS 19 | 24 | #define POLICYDB_VERSION_VALIDATETRANS 19 |
| 25 | #define POLICYDB_VERSION_MLS 19 | 25 | #define POLICYDB_VERSION_MLS 19 |
| 26 | #define POLICYDB_VERSION_AVTAB 20 | 26 | #define POLICYDB_VERSION_AVTAB 20 |
| 27 | #define POLICYDB_VERSION_RANGETRANS 21 | ||
| 27 | 28 | ||
| 28 | /* Range of policy versions we understand*/ | 29 | /* Range of policy versions we understand*/ |
| 29 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 30 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
| 30 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB | 31 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
| 32 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | ||
| 33 | #else | ||
| 34 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS | ||
| 35 | #endif | ||
| 31 | 36 | ||
| 32 | extern int selinux_enabled; | 37 | extern int selinux_enabled; |
| 33 | extern int selinux_mls_enabled; | 38 | extern int selinux_mls_enabled; |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 00534c302ba2..bab7b386cb8d 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -771,7 +771,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode) | |||
| 771 | if (ret) { | 771 | if (ret) { |
| 772 | ret->i_mode = mode; | 772 | ret->i_mode = mode; |
| 773 | ret->i_uid = ret->i_gid = 0; | 773 | ret->i_uid = ret->i_gid = 0; |
| 774 | ret->i_blksize = PAGE_CACHE_SIZE; | ||
| 775 | ret->i_blocks = 0; | 774 | ret->i_blocks = 0; |
| 776 | ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; | 775 | ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; |
| 777 | } | 776 | } |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 119bd6078ba1..c713af23250a 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
| @@ -530,22 +530,21 @@ int mls_compute_sid(struct context *scontext, | |||
| 530 | u32 specified, | 530 | u32 specified, |
| 531 | struct context *newcontext) | 531 | struct context *newcontext) |
| 532 | { | 532 | { |
| 533 | struct range_trans *rtr; | ||
| 534 | |||
| 533 | if (!selinux_mls_enabled) | 535 | if (!selinux_mls_enabled) |
| 534 | return 0; | 536 | return 0; |
| 535 | 537 | ||
| 536 | switch (specified) { | 538 | switch (specified) { |
| 537 | case AVTAB_TRANSITION: | 539 | case AVTAB_TRANSITION: |
| 538 | if (tclass == SECCLASS_PROCESS) { | 540 | /* Look for a range transition rule. */ |
| 539 | struct range_trans *rangetr; | 541 | for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { |
| 540 | /* Look for a range transition rule. */ | 542 | if (rtr->source_type == scontext->type && |
| 541 | for (rangetr = policydb.range_tr; rangetr; | 543 | rtr->target_type == tcontext->type && |
| 542 | rangetr = rangetr->next) { | 544 | rtr->target_class == tclass) { |
| 543 | if (rangetr->dom == scontext->type && | 545 | /* Set the range from the rule */ |
| 544 | rangetr->type == tcontext->type) { | 546 | return mls_range_set(newcontext, |
| 545 | /* Set the range from the rule */ | 547 | &rtr->target_range); |
| 546 | return mls_range_set(newcontext, | ||
| 547 | &rangetr->range); | ||
| 548 | } | ||
| 549 | } | 548 | } |
| 550 | } | 549 | } |
| 551 | /* Fallthrough */ | 550 | /* Fallthrough */ |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index f03960e697ce..b18895302555 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
| @@ -96,6 +96,11 @@ static struct policydb_compat_info policydb_compat[] = { | |||
| 96 | .sym_num = SYM_NUM, | 96 | .sym_num = SYM_NUM, |
| 97 | .ocon_num = OCON_NUM, | 97 | .ocon_num = OCON_NUM, |
| 98 | }, | 98 | }, |
| 99 | { | ||
| 100 | .version = POLICYDB_VERSION_RANGETRANS, | ||
| 101 | .sym_num = SYM_NUM, | ||
| 102 | .ocon_num = OCON_NUM, | ||
| 103 | }, | ||
| 99 | }; | 104 | }; |
| 100 | 105 | ||
| 101 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 106 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
| @@ -645,15 +650,15 @@ void policydb_destroy(struct policydb *p) | |||
| 645 | 650 | ||
| 646 | for (rt = p->range_tr; rt; rt = rt -> next) { | 651 | for (rt = p->range_tr; rt; rt = rt -> next) { |
| 647 | if (lrt) { | 652 | if (lrt) { |
| 648 | ebitmap_destroy(&lrt->range.level[0].cat); | 653 | ebitmap_destroy(&lrt->target_range.level[0].cat); |
| 649 | ebitmap_destroy(&lrt->range.level[1].cat); | 654 | ebitmap_destroy(&lrt->target_range.level[1].cat); |
| 650 | kfree(lrt); | 655 | kfree(lrt); |
| 651 | } | 656 | } |
| 652 | lrt = rt; | 657 | lrt = rt; |
| 653 | } | 658 | } |
| 654 | if (lrt) { | 659 | if (lrt) { |
| 655 | ebitmap_destroy(&lrt->range.level[0].cat); | 660 | ebitmap_destroy(&lrt->target_range.level[0].cat); |
| 656 | ebitmap_destroy(&lrt->range.level[1].cat); | 661 | ebitmap_destroy(&lrt->target_range.level[1].cat); |
| 657 | kfree(lrt); | 662 | kfree(lrt); |
| 658 | } | 663 | } |
| 659 | 664 | ||
| @@ -1829,6 +1834,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1829 | } | 1834 | } |
| 1830 | 1835 | ||
| 1831 | if (p->policyvers >= POLICYDB_VERSION_MLS) { | 1836 | if (p->policyvers >= POLICYDB_VERSION_MLS) { |
| 1837 | int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; | ||
| 1832 | rc = next_entry(buf, fp, sizeof(u32)); | 1838 | rc = next_entry(buf, fp, sizeof(u32)); |
| 1833 | if (rc < 0) | 1839 | if (rc < 0) |
| 1834 | goto bad; | 1840 | goto bad; |
| @@ -1847,9 +1853,16 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1847 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | 1853 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); |
| 1848 | if (rc < 0) | 1854 | if (rc < 0) |
| 1849 | goto bad; | 1855 | goto bad; |
| 1850 | rt->dom = le32_to_cpu(buf[0]); | 1856 | rt->source_type = le32_to_cpu(buf[0]); |
| 1851 | rt->type = le32_to_cpu(buf[1]); | 1857 | rt->target_type = le32_to_cpu(buf[1]); |
| 1852 | rc = mls_read_range_helper(&rt->range, fp); | 1858 | if (new_rangetr) { |
| 1859 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 1860 | if (rc < 0) | ||
| 1861 | goto bad; | ||
| 1862 | rt->target_class = le32_to_cpu(buf[0]); | ||
| 1863 | } else | ||
| 1864 | rt->target_class = SECCLASS_PROCESS; | ||
| 1865 | rc = mls_read_range_helper(&rt->target_range, fp); | ||
| 1853 | if (rc) | 1866 | if (rc) |
| 1854 | goto bad; | 1867 | goto bad; |
| 1855 | lrt = rt; | 1868 | lrt = rt; |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index b1340711f721..8319d5ff5944 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
| @@ -106,9 +106,10 @@ struct cat_datum { | |||
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | struct range_trans { | 108 | struct range_trans { |
| 109 | u32 dom; /* current process domain */ | 109 | u32 source_type; |
| 110 | u32 type; /* program executable type */ | 110 | u32 target_type; |
| 111 | struct mls_range range; /* new range */ | 111 | u32 target_class; |
| 112 | struct mls_range target_range; | ||
| 112 | struct range_trans *next; | 113 | struct range_trans *next; |
| 113 | }; | 114 | }; |
| 114 | 115 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 7eb69a602d8f..0c219a1b3243 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -2003,7 +2003,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | |||
| 2003 | return rc; | 2003 | return rc; |
| 2004 | } | 2004 | } |
| 2005 | 2005 | ||
| 2006 | int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | 2006 | int selinux_audit_rule_match(u32 sid, u32 field, u32 op, |
| 2007 | struct selinux_audit_rule *rule, | 2007 | struct selinux_audit_rule *rule, |
| 2008 | struct audit_context *actx) | 2008 | struct audit_context *actx) |
| 2009 | { | 2009 | { |
| @@ -2026,11 +2026,11 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | |||
| 2026 | goto out; | 2026 | goto out; |
| 2027 | } | 2027 | } |
| 2028 | 2028 | ||
| 2029 | ctxt = sidtab_search(&sidtab, ctxid); | 2029 | ctxt = sidtab_search(&sidtab, sid); |
| 2030 | if (!ctxt) { | 2030 | if (!ctxt) { |
| 2031 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 2031 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
| 2032 | "selinux_audit_rule_match: unrecognized SID %d\n", | 2032 | "selinux_audit_rule_match: unrecognized SID %d\n", |
| 2033 | ctxid); | 2033 | sid); |
| 2034 | match = -ENOENT; | 2034 | match = -ENOENT; |
| 2035 | goto out; | 2035 | goto out; |
| 2036 | } | 2036 | } |
| @@ -2502,14 +2502,24 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) | |||
| 2502 | { | 2502 | { |
| 2503 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | 2503 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
| 2504 | struct sk_security_struct *sksec = sk->sk_security; | 2504 | struct sk_security_struct *sksec = sk->sk_security; |
| 2505 | struct netlbl_lsm_secattr secattr; | ||
| 2506 | u32 nlbl_peer_sid; | ||
| 2505 | 2507 | ||
| 2506 | sksec->sclass = isec->sclass; | 2508 | sksec->sclass = isec->sclass; |
| 2507 | 2509 | ||
| 2508 | if (sk->sk_family != PF_INET) | 2510 | if (sk->sk_family != PF_INET) |
| 2509 | return; | 2511 | return; |
| 2510 | 2512 | ||
| 2513 | netlbl_secattr_init(&secattr); | ||
| 2514 | if (netlbl_sock_getattr(sk, &secattr) == 0 && | ||
| 2515 | selinux_netlbl_secattr_to_sid(NULL, | ||
| 2516 | &secattr, | ||
| 2517 | sksec->sid, | ||
| 2518 | &nlbl_peer_sid) == 0) | ||
| 2519 | sksec->peer_sid = nlbl_peer_sid; | ||
| 2520 | netlbl_secattr_destroy(&secattr, 0); | ||
| 2521 | |||
| 2511 | sksec->nlbl_state = NLBL_REQUIRE; | 2522 | sksec->nlbl_state = NLBL_REQUIRE; |
| 2512 | sksec->peer_sid = sksec->sid; | ||
| 2513 | 2523 | ||
| 2514 | /* Try to set the NetLabel on the socket to save time later, if we fail | 2524 | /* Try to set the NetLabel on the socket to save time later, if we fail |
| 2515 | * here we will pick up the pieces in later calls to | 2525 | * here we will pick up the pieces in later calls to |
| @@ -2568,7 +2578,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) | |||
| 2568 | sock = SOCKET_I(inode); | 2578 | sock = SOCKET_I(inode); |
| 2569 | isec = inode->i_security; | 2579 | isec = inode->i_security; |
| 2570 | sksec = sock->sk->sk_security; | 2580 | sksec = sock->sk->sk_security; |
| 2571 | down(&isec->sem); | 2581 | mutex_lock(&isec->lock); |
| 2572 | if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && | 2582 | if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && |
| 2573 | (mask & (MAY_WRITE | MAY_APPEND)))) { | 2583 | (mask & (MAY_WRITE | MAY_APPEND)))) { |
| 2574 | lock_sock(sock->sk); | 2584 | lock_sock(sock->sk); |
| @@ -2576,7 +2586,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) | |||
| 2576 | release_sock(sock->sk); | 2586 | release_sock(sock->sk); |
| 2577 | } else | 2587 | } else |
| 2578 | rc = 0; | 2588 | rc = 0; |
| 2579 | up(&isec->sem); | 2589 | mutex_unlock(&isec->lock); |
| 2580 | 2590 | ||
| 2581 | return rc; | 2591 | return rc; |
| 2582 | } | 2592 | } |
| @@ -2601,7 +2611,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
| 2601 | u32 netlbl_sid; | 2611 | u32 netlbl_sid; |
| 2602 | u32 recv_perm; | 2612 | u32 recv_perm; |
| 2603 | 2613 | ||
| 2604 | rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid); | 2614 | rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid); |
| 2605 | if (rc != 0) | 2615 | if (rc != 0) |
| 2606 | return rc; | 2616 | return rc; |
| 2607 | 2617 | ||
| @@ -2610,13 +2620,13 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
| 2610 | 2620 | ||
| 2611 | switch (sksec->sclass) { | 2621 | switch (sksec->sclass) { |
| 2612 | case SECCLASS_UDP_SOCKET: | 2622 | case SECCLASS_UDP_SOCKET: |
| 2613 | recv_perm = UDP_SOCKET__RECV_MSG; | 2623 | recv_perm = UDP_SOCKET__RECVFROM; |
| 2614 | break; | 2624 | break; |
| 2615 | case SECCLASS_TCP_SOCKET: | 2625 | case SECCLASS_TCP_SOCKET: |
| 2616 | recv_perm = TCP_SOCKET__RECV_MSG; | 2626 | recv_perm = TCP_SOCKET__RECVFROM; |
| 2617 | break; | 2627 | break; |
| 2618 | default: | 2628 | default: |
| 2619 | recv_perm = RAWIP_SOCKET__RECV_MSG; | 2629 | recv_perm = RAWIP_SOCKET__RECVFROM; |
| 2620 | } | 2630 | } |
| 2621 | 2631 | ||
| 2622 | rc = avc_has_perm(sksec->sid, | 2632 | rc = avc_has_perm(sksec->sid, |
