diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/Makefile | 3 | ||||
| -rw-r--r-- | security/inode.c | 11 | ||||
| -rw-r--r-- | security/integrity/ima/ima.h | 6 | ||||
| -rw-r--r-- | security/integrity/ima/ima_api.c | 4 | ||||
| -rw-r--r-- | security/integrity/ima/ima_iint.c | 85 | ||||
| -rw-r--r-- | security/integrity/ima/ima_main.c | 309 | ||||
| -rw-r--r-- | security/integrity/ima/ima_policy.c | 9 | ||||
| -rw-r--r-- | security/keys/gc.c | 3 | ||||
| -rw-r--r-- | security/keys/keyctl.c | 12 | ||||
| -rw-r--r-- | security/keys/keyring.c | 4 | ||||
| -rw-r--r-- | security/min_addr.c | 2 | ||||
| -rw-r--r-- | security/security.c | 2 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 2 | ||||
| -rw-r--r-- | security/selinux/netlabel.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/ebitmap.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 2 | ||||
| -rw-r--r-- | security/tomoyo/file.c | 1 | ||||
| -rw-r--r-- | security/tomoyo/tomoyo.c | 7 |
18 files changed, 187 insertions, 279 deletions
diff --git a/security/Makefile b/security/Makefile index bb44e350c618..da20a193c8dd 100644 --- a/security/Makefile +++ b/security/Makefile | |||
| @@ -8,7 +8,8 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack | |||
| 8 | subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo | 8 | subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo |
| 9 | 9 | ||
| 10 | # always enable default capabilities | 10 | # always enable default capabilities |
| 11 | obj-y += commoncap.o min_addr.o | 11 | obj-y += commoncap.o |
| 12 | obj-$(CONFIG_MMU) += min_addr.o | ||
| 12 | 13 | ||
| 13 | # Object file lists | 14 | # Object file lists |
| 14 | obj-$(CONFIG_SECURITY) += security.o capability.o | 15 | obj-$(CONFIG_SECURITY) += security.o capability.o |
diff --git a/security/inode.c b/security/inode.c index f7496c6a022b..c3a793881d04 100644 --- a/security/inode.c +++ b/security/inode.c | |||
| @@ -156,15 +156,8 @@ static int create_by_name(const char *name, mode_t mode, | |||
| 156 | * block. A pointer to that is in the struct vfsmount that we | 156 | * block. A pointer to that is in the struct vfsmount that we |
| 157 | * have around. | 157 | * have around. |
| 158 | */ | 158 | */ |
| 159 | if (!parent ) { | 159 | if (!parent) |
| 160 | if (mount && mount->mnt_sb) { | 160 | parent = mount->mnt_sb->s_root; |
| 161 | parent = mount->mnt_sb->s_root; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | if (!parent) { | ||
| 165 | pr_debug("securityfs: Ah! can not find a parent!\n"); | ||
| 166 | return -EFAULT; | ||
| 167 | } | ||
| 168 | 161 | ||
| 169 | mutex_lock(&parent->d_inode->i_mutex); | 162 | mutex_lock(&parent->d_inode->i_mutex); |
| 170 | *dentry = lookup_one_len(name, parent, strlen(name)); | 163 | *dentry = lookup_one_len(name, parent, strlen(name)); |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 165eb5397ea5..47fb65d1fcbd 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
| @@ -65,7 +65,6 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, | |||
| 65 | const char *cause, int result, int info); | 65 | const char *cause, int result, int info); |
| 66 | 66 | ||
| 67 | /* Internal IMA function definitions */ | 67 | /* Internal IMA function definitions */ |
| 68 | void ima_iintcache_init(void); | ||
| 69 | int ima_init(void); | 68 | int ima_init(void); |
| 70 | void ima_cleanup(void); | 69 | void ima_cleanup(void); |
| 71 | int ima_fs_init(void); | 70 | int ima_fs_init(void); |
| @@ -97,7 +96,6 @@ static inline unsigned long ima_hash_key(u8 *digest) | |||
| 97 | 96 | ||
| 98 | /* iint cache flags */ | 97 | /* iint cache flags */ |
| 99 | #define IMA_MEASURED 1 | 98 | #define IMA_MEASURED 1 |
| 100 | #define IMA_IINT_DUMP_STACK 512 | ||
| 101 | 99 | ||
| 102 | /* integrity data associated with an inode */ | 100 | /* integrity data associated with an inode */ |
| 103 | struct ima_iint_cache { | 101 | struct ima_iint_cache { |
| @@ -128,13 +126,11 @@ void ima_template_show(struct seq_file *m, void *e, | |||
| 128 | */ | 126 | */ |
| 129 | struct ima_iint_cache *ima_iint_insert(struct inode *inode); | 127 | struct ima_iint_cache *ima_iint_insert(struct inode *inode); |
| 130 | struct ima_iint_cache *ima_iint_find_get(struct inode *inode); | 128 | struct ima_iint_cache *ima_iint_find_get(struct inode *inode); |
| 131 | struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode); | ||
| 132 | void ima_iint_delete(struct inode *inode); | ||
| 133 | void iint_free(struct kref *kref); | 129 | void iint_free(struct kref *kref); |
| 134 | void iint_rcu_free(struct rcu_head *rcu); | 130 | void iint_rcu_free(struct rcu_head *rcu); |
| 135 | 131 | ||
| 136 | /* IMA policy related functions */ | 132 | /* IMA policy related functions */ |
| 137 | enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK }; | 133 | enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; |
| 138 | 134 | ||
| 139 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); | 135 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); |
| 140 | void ima_init_policy(void); | 136 | void ima_init_policy(void); |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 3cd58b60afd2..2a5e0bcf3887 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
| @@ -95,12 +95,12 @@ err_out: | |||
| 95 | * ima_must_measure - measure decision based on policy. | 95 | * ima_must_measure - measure decision based on policy. |
| 96 | * @inode: pointer to inode to measure | 96 | * @inode: pointer to inode to measure |
| 97 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) | 97 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) |
| 98 | * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP) | 98 | * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) |
| 99 | * | 99 | * |
| 100 | * The policy is defined in terms of keypairs: | 100 | * The policy is defined in terms of keypairs: |
| 101 | * subj=, obj=, type=, func=, mask=, fsmagic= | 101 | * subj=, obj=, type=, func=, mask=, fsmagic= |
| 102 | * subj,obj, and type: are LSM specific. | 102 | * subj,obj, and type: are LSM specific. |
| 103 | * func: PATH_CHECK | BPRM_CHECK | FILE_MMAP | 103 | * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP |
| 104 | * mask: contains the permission mask | 104 | * mask: contains the permission mask |
| 105 | * fsmagic: hex value | 105 | * fsmagic: hex value |
| 106 | * | 106 | * |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index a4e2b1dac943..2d4d05d92fda 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
| @@ -19,8 +19,6 @@ | |||
| 19 | #include <linux/radix-tree.h> | 19 | #include <linux/radix-tree.h> |
| 20 | #include "ima.h" | 20 | #include "ima.h" |
| 21 | 21 | ||
| 22 | #define ima_iint_delete ima_inode_free | ||
| 23 | |||
| 24 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); | 22 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); |
| 25 | DEFINE_SPINLOCK(ima_iint_lock); | 23 | DEFINE_SPINLOCK(ima_iint_lock); |
| 26 | 24 | ||
| @@ -45,22 +43,18 @@ out: | |||
| 45 | return iint; | 43 | return iint; |
| 46 | } | 44 | } |
| 47 | 45 | ||
| 48 | /* Allocate memory for the iint associated with the inode | 46 | /** |
| 49 | * from the iint_cache slab, initialize the iint, and | 47 | * ima_inode_alloc - allocate an iint associated with an inode |
| 50 | * insert it into the radix tree. | 48 | * @inode: pointer to the inode |
| 51 | * | ||
| 52 | * On success return a pointer to the iint; on failure return NULL. | ||
| 53 | */ | 49 | */ |
| 54 | struct ima_iint_cache *ima_iint_insert(struct inode *inode) | 50 | int ima_inode_alloc(struct inode *inode) |
| 55 | { | 51 | { |
| 56 | struct ima_iint_cache *iint = NULL; | 52 | struct ima_iint_cache *iint = NULL; |
| 57 | int rc = 0; | 53 | int rc = 0; |
| 58 | 54 | ||
| 59 | if (!ima_initialized) | ||
| 60 | return iint; | ||
| 61 | iint = kmem_cache_alloc(iint_cache, GFP_NOFS); | 55 | iint = kmem_cache_alloc(iint_cache, GFP_NOFS); |
| 62 | if (!iint) | 56 | if (!iint) |
| 63 | return iint; | 57 | return -ENOMEM; |
| 64 | 58 | ||
| 65 | rc = radix_tree_preload(GFP_NOFS); | 59 | rc = radix_tree_preload(GFP_NOFS); |
| 66 | if (rc < 0) | 60 | if (rc < 0) |
| @@ -69,67 +63,14 @@ struct ima_iint_cache *ima_iint_insert(struct inode *inode) | |||
| 69 | spin_lock(&ima_iint_lock); | 63 | spin_lock(&ima_iint_lock); |
| 70 | rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); | 64 | rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); |
| 71 | spin_unlock(&ima_iint_lock); | 65 | spin_unlock(&ima_iint_lock); |
| 66 | radix_tree_preload_end(); | ||
| 72 | out: | 67 | out: |
| 73 | if (rc < 0) { | 68 | if (rc < 0) |
| 74 | kmem_cache_free(iint_cache, iint); | 69 | kmem_cache_free(iint_cache, iint); |
| 75 | if (rc == -EEXIST) { | ||
| 76 | spin_lock(&ima_iint_lock); | ||
| 77 | iint = radix_tree_lookup(&ima_iint_store, | ||
| 78 | (unsigned long)inode); | ||
| 79 | spin_unlock(&ima_iint_lock); | ||
| 80 | } else | ||
| 81 | iint = NULL; | ||
| 82 | } | ||
| 83 | radix_tree_preload_end(); | ||
| 84 | return iint; | ||
| 85 | } | ||
| 86 | 70 | ||
| 87 | /** | 71 | return rc; |
| 88 | * ima_inode_alloc - allocate an iint associated with an inode | ||
| 89 | * @inode: pointer to the inode | ||
| 90 | * | ||
| 91 | * Return 0 on success, 1 on failure. | ||
| 92 | */ | ||
| 93 | int ima_inode_alloc(struct inode *inode) | ||
| 94 | { | ||
| 95 | struct ima_iint_cache *iint; | ||
| 96 | |||
| 97 | if (!ima_initialized) | ||
| 98 | return 0; | ||
| 99 | |||
| 100 | iint = ima_iint_insert(inode); | ||
| 101 | if (!iint) | ||
| 102 | return 1; | ||
| 103 | return 0; | ||
| 104 | } | 72 | } |
| 105 | 73 | ||
| 106 | /* ima_iint_find_insert_get - get the iint associated with an inode | ||
| 107 | * | ||
| 108 | * Most insertions are done at inode_alloc, except those allocated | ||
| 109 | * before late_initcall. When the iint does not exist, allocate it, | ||
| 110 | * initialize and insert it, and increment the iint refcount. | ||
| 111 | * | ||
| 112 | * (Can't initialize at security_initcall before any inodes are | ||
| 113 | * allocated, got to wait at least until proc_init.) | ||
| 114 | * | ||
| 115 | * Return the iint. | ||
| 116 | */ | ||
| 117 | struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode) | ||
| 118 | { | ||
| 119 | struct ima_iint_cache *iint = NULL; | ||
| 120 | |||
| 121 | iint = ima_iint_find_get(inode); | ||
| 122 | if (iint) | ||
| 123 | return iint; | ||
| 124 | |||
| 125 | iint = ima_iint_insert(inode); | ||
| 126 | if (iint) | ||
| 127 | kref_get(&iint->refcount); | ||
| 128 | |||
| 129 | return iint; | ||
| 130 | } | ||
| 131 | EXPORT_SYMBOL_GPL(ima_iint_find_insert_get); | ||
| 132 | |||
| 133 | /* iint_free - called when the iint refcount goes to zero */ | 74 | /* iint_free - called when the iint refcount goes to zero */ |
| 134 | void iint_free(struct kref *kref) | 75 | void iint_free(struct kref *kref) |
| 135 | { | 76 | { |
| @@ -164,17 +105,15 @@ void iint_rcu_free(struct rcu_head *rcu_head) | |||
| 164 | } | 105 | } |
| 165 | 106 | ||
| 166 | /** | 107 | /** |
| 167 | * ima_iint_delete - called on integrity_inode_free | 108 | * ima_inode_free - called on security_inode_free |
| 168 | * @inode: pointer to the inode | 109 | * @inode: pointer to the inode |
| 169 | * | 110 | * |
| 170 | * Free the integrity information(iint) associated with an inode. | 111 | * Free the integrity information(iint) associated with an inode. |
| 171 | */ | 112 | */ |
| 172 | void ima_iint_delete(struct inode *inode) | 113 | void ima_inode_free(struct inode *inode) |
| 173 | { | 114 | { |
| 174 | struct ima_iint_cache *iint; | 115 | struct ima_iint_cache *iint; |
| 175 | 116 | ||
| 176 | if (!ima_initialized) | ||
| 177 | return; | ||
| 178 | spin_lock(&ima_iint_lock); | 117 | spin_lock(&ima_iint_lock); |
| 179 | iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); | 118 | iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); |
| 180 | spin_unlock(&ima_iint_lock); | 119 | spin_unlock(&ima_iint_lock); |
| @@ -196,9 +135,11 @@ static void init_once(void *foo) | |||
| 196 | kref_set(&iint->refcount, 1); | 135 | kref_set(&iint->refcount, 1); |
| 197 | } | 136 | } |
| 198 | 137 | ||
| 199 | void __init ima_iintcache_init(void) | 138 | static int __init ima_iintcache_init(void) |
| 200 | { | 139 | { |
| 201 | iint_cache = | 140 | iint_cache = |
| 202 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, | 141 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, |
| 203 | SLAB_PANIC, init_once); | 142 | SLAB_PANIC, init_once); |
| 143 | return 0; | ||
| 204 | } | 144 | } |
| 145 | security_initcall(ima_iintcache_init); | ||
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b85e61bcf246..294b005d6520 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | * License. | 13 | * License. |
| 14 | * | 14 | * |
| 15 | * File: ima_main.c | 15 | * File: ima_main.c |
| 16 | * implements the IMA hooks: ima_bprm_check, ima_file_mmap, | 16 | * implements the IMA hooks: ima_bprm_check, ima_file_mmap, |
| 17 | * and ima_path_check. | 17 | * and ima_file_check. |
| 18 | */ | 18 | */ |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/file.h> | 20 | #include <linux/file.h> |
| @@ -35,50 +35,53 @@ static int __init hash_setup(char *str) | |||
| 35 | } | 35 | } |
| 36 | __setup("ima_hash=", hash_setup); | 36 | __setup("ima_hash=", hash_setup); |
| 37 | 37 | ||
| 38 | /** | 38 | struct ima_imbalance { |
| 39 | * ima_file_free - called on __fput() | 39 | struct hlist_node node; |
| 40 | * @file: pointer to file structure being freed | 40 | unsigned long fsmagic; |
| 41 | }; | ||
| 42 | |||
| 43 | /* | ||
| 44 | * ima_limit_imbalance - emit one imbalance message per filesystem type | ||
| 41 | * | 45 | * |
| 42 | * Flag files that changed, based on i_version; | 46 | * Maintain list of filesystem types that do not measure files properly. |
| 43 | * and decrement the iint readcount/writecount. | 47 | * Return false if unknown, true if known. |
| 44 | */ | 48 | */ |
| 45 | void ima_file_free(struct file *file) | 49 | static bool ima_limit_imbalance(struct file *file) |
| 46 | { | 50 | { |
| 47 | struct inode *inode = file->f_dentry->d_inode; | 51 | static DEFINE_SPINLOCK(ima_imbalance_lock); |
| 48 | struct ima_iint_cache *iint; | 52 | static HLIST_HEAD(ima_imbalance_list); |
| 49 | 53 | ||
| 50 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 54 | struct super_block *sb = file->f_dentry->d_sb; |
| 51 | return; | 55 | struct ima_imbalance *entry; |
| 52 | iint = ima_iint_find_get(inode); | 56 | struct hlist_node *node; |
| 53 | if (!iint) | 57 | bool found = false; |
| 54 | return; | 58 | |
| 55 | 59 | rcu_read_lock(); | |
| 56 | mutex_lock(&iint->mutex); | 60 | hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) { |
| 57 | if (iint->opencount <= 0) { | 61 | if (entry->fsmagic == sb->s_magic) { |
| 58 | printk(KERN_INFO | 62 | found = true; |
| 59 | "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n", | 63 | break; |
| 60 | __FUNCTION__, file->f_dentry->d_name.name, | ||
| 61 | iint->readcount, iint->writecount, | ||
| 62 | iint->opencount, atomic_long_read(&file->f_count)); | ||
| 63 | if (!(iint->flags & IMA_IINT_DUMP_STACK)) { | ||
| 64 | dump_stack(); | ||
| 65 | iint->flags |= IMA_IINT_DUMP_STACK; | ||
| 66 | } | 64 | } |
| 67 | } | 65 | } |
| 68 | iint->opencount--; | 66 | rcu_read_unlock(); |
| 69 | 67 | if (found) | |
| 70 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 68 | goto out; |
| 71 | iint->readcount--; | ||
| 72 | 69 | ||
| 73 | if (file->f_mode & FMODE_WRITE) { | 70 | entry = kmalloc(sizeof(*entry), GFP_NOFS); |
| 74 | iint->writecount--; | 71 | if (!entry) |
| 75 | if (iint->writecount == 0) { | 72 | goto out; |
| 76 | if (iint->version != inode->i_version) | 73 | entry->fsmagic = sb->s_magic; |
| 77 | iint->flags &= ~IMA_MEASURED; | 74 | spin_lock(&ima_imbalance_lock); |
| 78 | } | 75 | /* |
| 79 | } | 76 | * we could have raced and something else might have added this fs |
| 80 | mutex_unlock(&iint->mutex); | 77 | * to the list, but we don't really care |
| 81 | kref_put(&iint->refcount, iint_free); | 78 | */ |
| 79 | hlist_add_head_rcu(&entry->node, &ima_imbalance_list); | ||
| 80 | spin_unlock(&ima_imbalance_lock); | ||
| 81 | printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n", | ||
| 82 | entry->fsmagic); | ||
| 83 | out: | ||
| 84 | return found; | ||
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | /* ima_read_write_check - reflect possible reading/writing errors in the PCR. | 87 | /* ima_read_write_check - reflect possible reading/writing errors in the PCR. |
| @@ -111,196 +114,142 @@ static void ima_read_write_check(enum iint_pcr_error error, | |||
| 111 | } | 114 | } |
| 112 | } | 115 | } |
| 113 | 116 | ||
| 114 | static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | 117 | /* |
| 115 | const unsigned char *filename) | 118 | * Update the counts given an fmode_t |
| 119 | */ | ||
| 120 | static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode) | ||
| 116 | { | 121 | { |
| 117 | int rc = 0; | 122 | BUG_ON(!mutex_is_locked(&iint->mutex)); |
| 118 | |||
| 119 | iint->opencount++; | ||
| 120 | iint->readcount++; | ||
| 121 | |||
| 122 | rc = ima_collect_measurement(iint, file); | ||
| 123 | if (!rc) | ||
| 124 | ima_store_measurement(iint, file, filename); | ||
| 125 | return rc; | ||
| 126 | } | ||
| 127 | 123 | ||
| 128 | static void ima_update_counts(struct ima_iint_cache *iint, int mask) | ||
| 129 | { | ||
| 130 | iint->opencount++; | 124 | iint->opencount++; |
| 131 | if ((mask & MAY_WRITE) || (mask == 0)) | 125 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
| 132 | iint->writecount++; | ||
| 133 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
| 134 | iint->readcount++; | 126 | iint->readcount++; |
| 127 | if (mode & FMODE_WRITE) | ||
| 128 | iint->writecount++; | ||
| 135 | } | 129 | } |
| 136 | 130 | ||
| 137 | /** | 131 | /* |
| 138 | * ima_path_check - based on policy, collect/store measurement. | 132 | * ima_counts_get - increment file counts |
| 139 | * @path: contains a pointer to the path to be measured | ||
| 140 | * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE | ||
| 141 | * | ||
| 142 | * Measure the file being open for readonly, based on the | ||
| 143 | * ima_must_measure() policy decision. | ||
| 144 | * | 133 | * |
| 145 | * Keep read/write counters for all files, but only | 134 | * Maintain read/write counters for all files, but only |
| 146 | * invalidate the PCR for measured files: | 135 | * invalidate the PCR for measured files: |
| 147 | * - Opening a file for write when already open for read, | 136 | * - Opening a file for write when already open for read, |
| 148 | * results in a time of measure, time of use (ToMToU) error. | 137 | * results in a time of measure, time of use (ToMToU) error. |
| 149 | * - Opening a file for read when already open for write, | 138 | * - Opening a file for read when already open for write, |
| 150 | * could result in a file measurement error. | 139 | * could result in a file measurement error. |
| 151 | * | 140 | * |
| 152 | * Always return 0 and audit dentry_open failures. | ||
| 153 | * (Return code will be based upon measurement appraisal.) | ||
| 154 | */ | 141 | */ |
| 155 | int ima_path_check(struct path *path, int mask, int update_counts) | 142 | void ima_counts_get(struct file *file) |
| 156 | { | 143 | { |
| 157 | struct inode *inode = path->dentry->d_inode; | 144 | struct dentry *dentry = file->f_path.dentry; |
| 145 | struct inode *inode = dentry->d_inode; | ||
| 146 | fmode_t mode = file->f_mode; | ||
| 158 | struct ima_iint_cache *iint; | 147 | struct ima_iint_cache *iint; |
| 159 | struct file *file = NULL; | ||
| 160 | int rc; | 148 | int rc; |
| 161 | 149 | ||
| 162 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 150 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
| 163 | return 0; | 151 | return; |
| 164 | iint = ima_iint_find_insert_get(inode); | 152 | iint = ima_iint_find_get(inode); |
| 165 | if (!iint) | 153 | if (!iint) |
| 166 | return 0; | 154 | return; |
| 167 | |||
| 168 | mutex_lock(&iint->mutex); | 155 | mutex_lock(&iint->mutex); |
| 169 | if (update_counts) | 156 | rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); |
| 170 | ima_update_counts(iint, mask); | ||
| 171 | |||
| 172 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); | ||
| 173 | if (rc < 0) | 157 | if (rc < 0) |
| 174 | goto out; | 158 | goto out; |
| 175 | 159 | ||
| 176 | if ((mask & MAY_WRITE) || (mask == 0)) | 160 | if (mode & FMODE_WRITE) { |
| 177 | ima_read_write_check(TOMTOU, iint, inode, | 161 | ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name); |
| 178 | path->dentry->d_name.name); | ||
| 179 | |||
| 180 | if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ) | ||
| 181 | goto out; | 162 | goto out; |
| 182 | |||
| 183 | ima_read_write_check(OPEN_WRITERS, iint, inode, | ||
| 184 | path->dentry->d_name.name); | ||
| 185 | if (!(iint->flags & IMA_MEASURED)) { | ||
| 186 | struct dentry *dentry = dget(path->dentry); | ||
| 187 | struct vfsmount *mnt = mntget(path->mnt); | ||
| 188 | |||
| 189 | file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE, | ||
| 190 | current_cred()); | ||
| 191 | if (IS_ERR(file)) { | ||
| 192 | int audit_info = 0; | ||
| 193 | |||
| 194 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, | ||
| 195 | dentry->d_name.name, | ||
| 196 | "add_measurement", | ||
| 197 | "dentry_open failed", | ||
| 198 | 1, audit_info); | ||
| 199 | file = NULL; | ||
| 200 | goto out; | ||
| 201 | } | ||
| 202 | rc = get_path_measurement(iint, file, dentry->d_name.name); | ||
| 203 | } | 163 | } |
| 164 | ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name); | ||
| 204 | out: | 165 | out: |
| 166 | ima_inc_counts(iint, file->f_mode); | ||
| 205 | mutex_unlock(&iint->mutex); | 167 | mutex_unlock(&iint->mutex); |
| 206 | if (file) | 168 | |
| 207 | fput(file); | ||
| 208 | kref_put(&iint->refcount, iint_free); | 169 | kref_put(&iint->refcount, iint_free); |
| 209 | return 0; | ||
| 210 | } | 170 | } |
| 211 | EXPORT_SYMBOL_GPL(ima_path_check); | ||
| 212 | 171 | ||
| 213 | static int process_measurement(struct file *file, const unsigned char *filename, | 172 | /* |
| 214 | int mask, int function) | 173 | * Decrement ima counts |
| 174 | */ | ||
| 175 | static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, | ||
| 176 | struct file *file) | ||
| 215 | { | 177 | { |
| 216 | struct inode *inode = file->f_dentry->d_inode; | 178 | mode_t mode = file->f_mode; |
| 217 | struct ima_iint_cache *iint; | 179 | BUG_ON(!mutex_is_locked(&iint->mutex)); |
| 218 | int rc; | ||
| 219 | 180 | ||
| 220 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 181 | iint->opencount--; |
| 221 | return 0; | 182 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
| 222 | iint = ima_iint_find_insert_get(inode); | 183 | iint->readcount--; |
| 223 | if (!iint) | 184 | if (mode & FMODE_WRITE) { |
| 224 | return -ENOMEM; | 185 | iint->writecount--; |
| 225 | 186 | if (iint->writecount == 0) { | |
| 226 | mutex_lock(&iint->mutex); | 187 | if (iint->version != inode->i_version) |
| 227 | rc = ima_must_measure(iint, inode, mask, function); | 188 | iint->flags &= ~IMA_MEASURED; |
| 228 | if (rc != 0) | 189 | } |
| 229 | goto out; | 190 | } |
| 230 | 191 | ||
| 231 | rc = ima_collect_measurement(iint, file); | 192 | if (((iint->opencount < 0) || |
| 232 | if (!rc) | 193 | (iint->readcount < 0) || |
| 233 | ima_store_measurement(iint, file, filename); | 194 | (iint->writecount < 0)) && |
| 234 | out: | 195 | !ima_limit_imbalance(file)) { |
| 235 | mutex_unlock(&iint->mutex); | 196 | printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n", |
| 236 | kref_put(&iint->refcount, iint_free); | 197 | __FUNCTION__, iint->readcount, iint->writecount, |
| 237 | return rc; | 198 | iint->opencount); |
| 199 | dump_stack(); | ||
| 200 | } | ||
| 238 | } | 201 | } |
| 239 | 202 | ||
| 240 | /* | 203 | /** |
| 241 | * ima_counts_put - decrement file counts | 204 | * ima_file_free - called on __fput() |
| 205 | * @file: pointer to file structure being freed | ||
| 242 | * | 206 | * |
| 243 | * File counts are incremented in ima_path_check. On file open | 207 | * Flag files that changed, based on i_version; |
| 244 | * error, such as ETXTBSY, decrement the counts to prevent | 208 | * and decrement the iint readcount/writecount. |
| 245 | * unnecessary imbalance messages. | ||
| 246 | */ | 209 | */ |
| 247 | void ima_counts_put(struct path *path, int mask) | 210 | void ima_file_free(struct file *file) |
| 248 | { | 211 | { |
| 249 | struct inode *inode = path->dentry->d_inode; | 212 | struct inode *inode = file->f_dentry->d_inode; |
| 250 | struct ima_iint_cache *iint; | 213 | struct ima_iint_cache *iint; |
| 251 | 214 | ||
| 252 | /* The inode may already have been freed, freeing the iint | 215 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
| 253 | * with it. Verify the inode is not NULL before dereferencing | ||
| 254 | * it. | ||
| 255 | */ | ||
| 256 | if (!ima_initialized || !inode || !S_ISREG(inode->i_mode)) | ||
| 257 | return; | 216 | return; |
| 258 | iint = ima_iint_find_insert_get(inode); | 217 | iint = ima_iint_find_get(inode); |
| 259 | if (!iint) | 218 | if (!iint) |
| 260 | return; | 219 | return; |
| 261 | 220 | ||
| 262 | mutex_lock(&iint->mutex); | 221 | mutex_lock(&iint->mutex); |
| 263 | iint->opencount--; | 222 | ima_dec_counts(iint, inode, file); |
| 264 | if ((mask & MAY_WRITE) || (mask == 0)) | ||
| 265 | iint->writecount--; | ||
| 266 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
| 267 | iint->readcount--; | ||
| 268 | mutex_unlock(&iint->mutex); | 223 | mutex_unlock(&iint->mutex); |
| 269 | |||
| 270 | kref_put(&iint->refcount, iint_free); | 224 | kref_put(&iint->refcount, iint_free); |
| 271 | } | 225 | } |
| 272 | 226 | ||
| 273 | /* | 227 | static int process_measurement(struct file *file, const unsigned char *filename, |
| 274 | * ima_counts_get - increment file counts | 228 | int mask, int function) |
| 275 | * | ||
| 276 | * - for IPC shm and shmat file. | ||
| 277 | * - for nfsd exported files. | ||
| 278 | * | ||
| 279 | * Increment the counts for these files to prevent unnecessary | ||
| 280 | * imbalance messages. | ||
| 281 | */ | ||
| 282 | void ima_counts_get(struct file *file) | ||
| 283 | { | 229 | { |
| 284 | struct inode *inode = file->f_dentry->d_inode; | 230 | struct inode *inode = file->f_dentry->d_inode; |
| 285 | struct ima_iint_cache *iint; | 231 | struct ima_iint_cache *iint; |
| 232 | int rc; | ||
| 286 | 233 | ||
| 287 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 234 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
| 288 | return; | 235 | return 0; |
| 289 | iint = ima_iint_find_insert_get(inode); | 236 | iint = ima_iint_find_get(inode); |
| 290 | if (!iint) | 237 | if (!iint) |
| 291 | return; | 238 | return -ENOMEM; |
| 239 | |||
| 292 | mutex_lock(&iint->mutex); | 240 | mutex_lock(&iint->mutex); |
| 293 | iint->opencount++; | 241 | rc = ima_must_measure(iint, inode, mask, function); |
| 294 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 242 | if (rc != 0) |
| 295 | iint->readcount++; | 243 | goto out; |
| 296 | 244 | ||
| 297 | if (file->f_mode & FMODE_WRITE) | 245 | rc = ima_collect_measurement(iint, file); |
| 298 | iint->writecount++; | 246 | if (!rc) |
| 247 | ima_store_measurement(iint, file, filename); | ||
| 248 | out: | ||
| 299 | mutex_unlock(&iint->mutex); | 249 | mutex_unlock(&iint->mutex); |
| 300 | |||
| 301 | kref_put(&iint->refcount, iint_free); | 250 | kref_put(&iint->refcount, iint_free); |
| 251 | return rc; | ||
| 302 | } | 252 | } |
| 303 | EXPORT_SYMBOL_GPL(ima_counts_get); | ||
| 304 | 253 | ||
| 305 | /** | 254 | /** |
| 306 | * ima_file_mmap - based on policy, collect/store measurement. | 255 | * ima_file_mmap - based on policy, collect/store measurement. |
| @@ -347,11 +296,31 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
| 347 | return 0; | 296 | return 0; |
| 348 | } | 297 | } |
| 349 | 298 | ||
| 299 | /** | ||
| 300 | * ima_path_check - based on policy, collect/store measurement. | ||
| 301 | * @file: pointer to the file to be measured | ||
| 302 | * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE | ||
| 303 | * | ||
| 304 | * Measure files based on the ima_must_measure() policy decision. | ||
| 305 | * | ||
| 306 | * Always return 0 and audit dentry_open failures. | ||
| 307 | * (Return code will be based upon measurement appraisal.) | ||
| 308 | */ | ||
| 309 | int ima_file_check(struct file *file, int mask) | ||
| 310 | { | ||
| 311 | int rc; | ||
| 312 | |||
| 313 | rc = process_measurement(file, file->f_dentry->d_name.name, | ||
| 314 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | ||
| 315 | FILE_CHECK); | ||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | EXPORT_SYMBOL_GPL(ima_file_check); | ||
| 319 | |||
| 350 | static int __init init_ima(void) | 320 | static int __init init_ima(void) |
| 351 | { | 321 | { |
| 352 | int error; | 322 | int error; |
| 353 | 323 | ||
| 354 | ima_iintcache_init(); | ||
| 355 | error = ima_init(); | 324 | error = ima_init(); |
| 356 | ima_initialized = 1; | 325 | ima_initialized = 1; |
| 357 | return error; | 326 | return error; |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index e1278399b345..4759d0f99335 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
| @@ -67,7 +67,7 @@ static struct ima_measure_rule_entry default_rules[] = { | |||
| 67 | .flags = IMA_FUNC | IMA_MASK}, | 67 | .flags = IMA_FUNC | IMA_MASK}, |
| 68 | {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, | 68 | {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, |
| 69 | .flags = IMA_FUNC | IMA_MASK}, | 69 | .flags = IMA_FUNC | IMA_MASK}, |
| 70 | {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, | 70 | {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0, |
| 71 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | 71 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| @@ -282,8 +282,11 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | |||
| 282 | break; | 282 | break; |
| 283 | case Opt_func: | 283 | case Opt_func: |
| 284 | audit_log_format(ab, "func=%s ", args[0].from); | 284 | audit_log_format(ab, "func=%s ", args[0].from); |
| 285 | if (strcmp(args[0].from, "PATH_CHECK") == 0) | 285 | if (strcmp(args[0].from, "FILE_CHECK") == 0) |
| 286 | entry->func = PATH_CHECK; | 286 | entry->func = FILE_CHECK; |
| 287 | /* PATH_CHECK is for backwards compat */ | ||
| 288 | else if (strcmp(args[0].from, "PATH_CHECK") == 0) | ||
| 289 | entry->func = FILE_CHECK; | ||
| 287 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) | 290 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) |
| 288 | entry->func = FILE_MMAP; | 291 | entry->func = FILE_MMAP; |
| 289 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) | 292 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) |
diff --git a/security/keys/gc.c b/security/keys/gc.c index 4770be375ffe..19902319d097 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c | |||
| @@ -77,7 +77,8 @@ static bool key_gc_keyring(struct key *keyring, time_t limit) | |||
| 77 | goto dont_gc; | 77 | goto dont_gc; |
| 78 | 78 | ||
| 79 | /* scan the keyring looking for dead keys */ | 79 | /* scan the keyring looking for dead keys */ |
| 80 | klist = rcu_dereference(keyring->payload.subscriptions); | 80 | klist = rcu_dereference_check(keyring->payload.subscriptions, |
| 81 | lockdep_is_held(&key_serial_lock)); | ||
| 81 | if (!klist) | 82 | if (!klist) |
| 82 | goto dont_gc; | 83 | goto dont_gc; |
| 83 | 84 | ||
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 06ec722897be..e9c2e7c584d9 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
| @@ -1194,7 +1194,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
| 1194 | * have the authorisation token handy */ | 1194 | * have the authorisation token handy */ |
| 1195 | instkey = key_get_instantiation_authkey(keyid); | 1195 | instkey = key_get_instantiation_authkey(keyid); |
| 1196 | if (IS_ERR(instkey)) | 1196 | if (IS_ERR(instkey)) |
| 1197 | return PTR_ERR(key_ref); | 1197 | return PTR_ERR(instkey); |
| 1198 | key_put(instkey); | 1198 | key_put(instkey); |
| 1199 | 1199 | ||
| 1200 | key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0); | 1200 | key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0); |
| @@ -1236,6 +1236,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
| 1236 | */ | 1236 | */ |
| 1237 | long keyctl_session_to_parent(void) | 1237 | long keyctl_session_to_parent(void) |
| 1238 | { | 1238 | { |
| 1239 | #ifdef TIF_NOTIFY_RESUME | ||
| 1239 | struct task_struct *me, *parent; | 1240 | struct task_struct *me, *parent; |
| 1240 | const struct cred *mycred, *pcred; | 1241 | const struct cred *mycred, *pcred; |
| 1241 | struct cred *cred, *oldcred; | 1242 | struct cred *cred, *oldcred; |
| @@ -1326,6 +1327,15 @@ not_permitted: | |||
| 1326 | error_keyring: | 1327 | error_keyring: |
| 1327 | key_ref_put(keyring_r); | 1328 | key_ref_put(keyring_r); |
| 1328 | return ret; | 1329 | return ret; |
| 1330 | |||
| 1331 | #else /* !TIF_NOTIFY_RESUME */ | ||
| 1332 | /* | ||
| 1333 | * To be removed when TIF_NOTIFY_RESUME has been implemented on | ||
| 1334 | * m68k/xtensa | ||
| 1335 | */ | ||
| 1336 | #warning TIF_NOTIFY_RESUME not implemented | ||
| 1337 | return -EOPNOTSUPP; | ||
| 1338 | #endif /* !TIF_NOTIFY_RESUME */ | ||
| 1329 | } | 1339 | } |
| 1330 | 1340 | ||
| 1331 | /*****************************************************************************/ | 1341 | /*****************************************************************************/ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 8ec02746ca99..e814d2109f8e 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
| @@ -151,7 +151,9 @@ static void keyring_destroy(struct key *keyring) | |||
| 151 | write_unlock(&keyring_name_lock); | 151 | write_unlock(&keyring_name_lock); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | klist = rcu_dereference(keyring->payload.subscriptions); | 154 | klist = rcu_dereference_check(keyring->payload.subscriptions, |
| 155 | rcu_read_lock_held() || | ||
| 156 | atomic_read(&keyring->usage) == 0); | ||
| 155 | if (klist) { | 157 | if (klist) { |
| 156 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 158 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
| 157 | key_put(klist->keys[loop]); | 159 | key_put(klist->keys[loop]); |
diff --git a/security/min_addr.c b/security/min_addr.c index fc43c9d37084..e86f297522bf 100644 --- a/security/min_addr.c +++ b/security/min_addr.c | |||
| @@ -43,7 +43,7 @@ int mmap_min_addr_handler(struct ctl_table *table, int write, | |||
| 43 | return ret; | 43 | return ret; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | int __init init_mmap_min_addr(void) | 46 | static int __init init_mmap_min_addr(void) |
| 47 | { | 47 | { |
| 48 | update_mmap_min_addr(); | 48 | update_mmap_min_addr(); |
| 49 | 49 | ||
diff --git a/security/security.c b/security/security.c index 24e060be9fa5..122b748d0f4c 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -666,8 +666,6 @@ int security_file_alloc(struct file *file) | |||
| 666 | void security_file_free(struct file *file) | 666 | void security_file_free(struct file *file) |
| 667 | { | 667 | { |
| 668 | security_ops->file_free_security(file); | 668 | security_ops->file_free_security(file); |
| 669 | if (file->f_dentry) | ||
| 670 | ima_file_free(file); | ||
| 671 | } | 669 | } |
| 672 | 670 | ||
| 673 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 671 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7a374c2eb043..9a2ee845e9d4 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -2365,7 +2365,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
| 2365 | initrlim = init_task.signal->rlim + i; | 2365 | initrlim = init_task.signal->rlim + i; |
| 2366 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2366 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
| 2367 | } | 2367 | } |
| 2368 | update_rlimit_cpu(rlim->rlim_cur); | 2368 | update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur); |
| 2369 | } | 2369 | } |
| 2370 | } | 2370 | } |
| 2371 | 2371 | ||
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index e68823741ad5..2534400317c5 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
| @@ -204,7 +204,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | |||
| 204 | * | 204 | * |
| 205 | * Description | 205 | * Description |
| 206 | * Call the NetLabel mechanism to set the label of a packet using @sid. | 206 | * Call the NetLabel mechanism to set the label of a packet using @sid. |
| 207 | * Returns zero on auccess, negative values on failure. | 207 | * Returns zero on success, negative values on failure. |
| 208 | * | 208 | * |
| 209 | */ | 209 | */ |
| 210 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, | 210 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 68c7348d1acc..04b6145d767f 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
| @@ -128,7 +128,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, | |||
| 128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; | 128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; |
| 129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; | 129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; |
| 130 | c_iter->bitmap[cmap_idx] | 130 | c_iter->bitmap[cmap_idx] |
| 131 | |= e_iter->maps[cmap_idx] << cmap_sft; | 131 | |= e_iter->maps[i] << cmap_sft; |
| 132 | } | 132 | } |
| 133 | e_iter = e_iter->next; | 133 | e_iter = e_iter->next; |
| 134 | } | 134 | } |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index d6bb20cbad62..b3efae204ac7 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -836,7 +836,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
| 836 | goto out; | 836 | goto out; |
| 837 | } | 837 | } |
| 838 | 838 | ||
| 839 | /* type/domain unchaned */ | 839 | /* type/domain unchanged */ |
| 840 | if (old_context->type == new_context->type) { | 840 | if (old_context->type == new_context->type) { |
| 841 | rc = 0; | 841 | rc = 0; |
| 842 | goto out; | 842 | goto out; |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 8346938809b1..9a6c58881c0a 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include "common.h" | 12 | #include "common.h" |
| 13 | #include "tomoyo.h" | 13 | #include "tomoyo.h" |
| 14 | #include "realpath.h" | 14 | #include "realpath.h" |
| 15 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) | ||
| 16 | 15 | ||
| 17 | /* | 16 | /* |
| 18 | * tomoyo_globally_readable_file_entry is a structure which is used for holding | 17 | * tomoyo_globally_readable_file_entry is a structure which is used for holding |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 8a00ade85166..2aceebf5f354 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
| @@ -80,9 +80,8 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
| 80 | return tomoyo_find_next_domain(bprm); | 80 | return tomoyo_find_next_domain(bprm); |
| 81 | /* | 81 | /* |
| 82 | * Read permission is checked against interpreters using next domain. | 82 | * Read permission is checked against interpreters using next domain. |
| 83 | * '1' is the result of open_to_namei_flags(O_RDONLY). | ||
| 84 | */ | 83 | */ |
| 85 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1); | 84 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); |
| 86 | } | 85 | } |
| 87 | 86 | ||
| 88 | static int tomoyo_path_truncate(struct path *path, loff_t length, | 87 | static int tomoyo_path_truncate(struct path *path, loff_t length, |
| @@ -184,10 +183,6 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | |||
| 184 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | 183 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) |
| 185 | { | 184 | { |
| 186 | int flags = f->f_flags; | 185 | int flags = f->f_flags; |
| 187 | |||
| 188 | if ((flags + 1) & O_ACCMODE) | ||
| 189 | flags++; | ||
| 190 | flags |= f->f_flags & (O_APPEND | O_TRUNC); | ||
| 191 | /* Don't check read permission here if called from do_execve(). */ | 186 | /* Don't check read permission here if called from do_execve(). */ |
| 192 | if (current->in_execve) | 187 | if (current->in_execve) |
| 193 | return 0; | 188 | return 0; |
