diff options
-rw-r--r-- | fs/inode.c | 1 | ||||
-rw-r--r-- | include/linux/fs.h | 4 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 3 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_iint.c | 11 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 35 |
6 files changed, 22 insertions, 34 deletions
diff --git a/fs/inode.c b/fs/inode.c index 86464332e590..56d909d69bc8 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/mount.h> | 24 | #include <linux/mount.h> |
25 | #include <linux/async.h> | 25 | #include <linux/async.h> |
26 | #include <linux/posix_acl.h> | 26 | #include <linux/posix_acl.h> |
27 | #include <linux/ima.h> | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * This is needed for the following functions: | 30 | * This is needed for the following functions: |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 63d069bd80b7..01e3a0047fed 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -776,6 +776,10 @@ struct inode { | |||
776 | 776 | ||
777 | unsigned int i_flags; | 777 | unsigned int i_flags; |
778 | 778 | ||
779 | #ifdef CONFIG_IMA | ||
780 | /* protected by i_lock */ | ||
781 | unsigned int i_readcount; /* struct files open RO */ | ||
782 | #endif | ||
779 | atomic_t i_writecount; | 783 | atomic_t i_writecount; |
780 | #ifdef CONFIG_SECURITY | 784 | #ifdef CONFIG_SECURITY |
781 | void *i_security; | 785 | void *i_security; |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index b546b90f5fa8..27849e1656dc 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -70,6 +70,7 @@ int ima_init(void); | |||
70 | void ima_cleanup(void); | 70 | void ima_cleanup(void); |
71 | int ima_fs_init(void); | 71 | int ima_fs_init(void); |
72 | void ima_fs_cleanup(void); | 72 | void ima_fs_cleanup(void); |
73 | int ima_inode_alloc(struct inode *inode); | ||
73 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, | 74 | int ima_add_template_entry(struct ima_template_entry *entry, int violation, |
74 | const char *op, struct inode *inode); | 75 | const char *op, struct inode *inode); |
75 | int ima_calc_hash(struct file *file, char *digest); | 76 | int ima_calc_hash(struct file *file, char *digest); |
@@ -106,8 +107,6 @@ struct ima_iint_cache { | |||
106 | unsigned char flags; | 107 | unsigned char flags; |
107 | u8 digest[IMA_DIGEST_SIZE]; | 108 | u8 digest[IMA_DIGEST_SIZE]; |
108 | struct mutex mutex; /* protects: version, flags, digest */ | 109 | struct mutex mutex; /* protects: version, flags, digest */ |
109 | /* protected by inode->i_lock */ | ||
110 | unsigned int readcount; /* measured files readcount */ | ||
111 | struct kref refcount; /* ima_iint_cache reference count */ | 110 | struct kref refcount; /* ima_iint_cache reference count */ |
112 | }; | 111 | }; |
113 | 112 | ||
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 52015d098fdf..d3963de6003d 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -116,7 +116,7 @@ int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode, | |||
116 | { | 116 | { |
117 | int must_measure; | 117 | int must_measure; |
118 | 118 | ||
119 | if (iint->flags & IMA_MEASURED) | 119 | if (iint && iint->flags & IMA_MEASURED) |
120 | return 1; | 120 | return 1; |
121 | 121 | ||
122 | must_measure = ima_match_policy(inode, function, mask); | 122 | must_measure = ima_match_policy(inode, function, mask); |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index e68891f8d55a..0936a7197e47 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
@@ -124,11 +124,6 @@ void iint_free(struct kref *kref) | |||
124 | refcount); | 124 | refcount); |
125 | iint->version = 0; | 125 | iint->version = 0; |
126 | iint->flags = 0UL; | 126 | iint->flags = 0UL; |
127 | if (iint->readcount != 0) { | ||
128 | printk(KERN_INFO "%s: readcount: %u\n", __func__, | ||
129 | iint->readcount); | ||
130 | iint->readcount = 0; | ||
131 | } | ||
132 | kref_init(&iint->refcount); | 127 | kref_init(&iint->refcount); |
133 | kmem_cache_free(iint_cache, iint); | 128 | kmem_cache_free(iint_cache, iint); |
134 | } | 129 | } |
@@ -143,6 +138,11 @@ void ima_inode_free(struct inode *inode) | |||
143 | { | 138 | { |
144 | struct ima_iint_cache *iint; | 139 | struct ima_iint_cache *iint; |
145 | 140 | ||
141 | if (inode->i_readcount) | ||
142 | printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount); | ||
143 | |||
144 | inode->i_readcount = 0; | ||
145 | |||
146 | spin_lock(&ima_iint_lock); | 146 | spin_lock(&ima_iint_lock); |
147 | iint = __ima_iint_find(inode); | 147 | iint = __ima_iint_find(inode); |
148 | if (iint) | 148 | if (iint) |
@@ -160,7 +160,6 @@ static void init_once(void *foo) | |||
160 | iint->version = 0; | 160 | iint->version = 0; |
161 | iint->flags = 0UL; | 161 | iint->flags = 0UL; |
162 | mutex_init(&iint->mutex); | 162 | mutex_init(&iint->mutex); |
163 | iint->readcount = 0; | ||
164 | kref_init(&iint->refcount); | 163 | kref_init(&iint->refcount); |
165 | } | 164 | } |
166 | 165 | ||
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 24660bf3f82a..2a77b14fee27 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -86,17 +86,6 @@ out: | |||
86 | } | 86 | } |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * Update the counts given an fmode_t | ||
90 | */ | ||
91 | static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode) | ||
92 | { | ||
93 | assert_spin_locked(&iint->inode->i_lock); | ||
94 | |||
95 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
96 | iint->readcount++; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * ima_counts_get - increment file counts | 89 | * ima_counts_get - increment file counts |
101 | * | 90 | * |
102 | * Maintain read/write counters for all files, but only | 91 | * Maintain read/write counters for all files, but only |
@@ -112,27 +101,23 @@ void ima_counts_get(struct file *file) | |||
112 | struct dentry *dentry = file->f_path.dentry; | 101 | struct dentry *dentry = file->f_path.dentry; |
113 | struct inode *inode = dentry->d_inode; | 102 | struct inode *inode = dentry->d_inode; |
114 | fmode_t mode = file->f_mode; | 103 | fmode_t mode = file->f_mode; |
115 | struct ima_iint_cache *iint; | ||
116 | int rc; | 104 | int rc; |
117 | bool send_tomtou = false, send_writers = false; | 105 | bool send_tomtou = false, send_writers = false; |
118 | 106 | ||
119 | if (!iint_initialized || !S_ISREG(inode->i_mode)) | 107 | if (!S_ISREG(inode->i_mode)) |
120 | return; | 108 | return; |
121 | iint = ima_iint_find_get(inode); | 109 | |
122 | if (!iint) | ||
123 | return; | ||
124 | mutex_lock(&iint->mutex); | ||
125 | spin_lock(&inode->i_lock); | 110 | spin_lock(&inode->i_lock); |
126 | 111 | ||
127 | if (!ima_initialized) | 112 | if (!ima_initialized) |
128 | goto out; | 113 | goto out; |
129 | 114 | ||
130 | rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); | 115 | rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK); |
131 | if (rc < 0) | 116 | if (rc < 0) |
132 | goto out; | 117 | goto out; |
133 | 118 | ||
134 | if (mode & FMODE_WRITE) { | 119 | if (mode & FMODE_WRITE) { |
135 | if (iint->readcount) | 120 | if (inode->i_readcount) |
136 | send_tomtou = true; | 121 | send_tomtou = true; |
137 | goto out; | 122 | goto out; |
138 | } | 123 | } |
@@ -140,10 +125,10 @@ void ima_counts_get(struct file *file) | |||
140 | if (atomic_read(&inode->i_writecount) > 0) | 125 | if (atomic_read(&inode->i_writecount) > 0) |
141 | send_writers = true; | 126 | send_writers = true; |
142 | out: | 127 | out: |
143 | ima_inc_counts(iint, file->f_mode); | 128 | /* remember the vfs deals with i_writecount */ |
129 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
130 | inode->i_readcount++; | ||
144 | spin_unlock(&inode->i_lock); | 131 | spin_unlock(&inode->i_lock); |
145 | mutex_unlock(&iint->mutex); | ||
146 | kref_put(&iint->refcount, iint_free); | ||
147 | 132 | ||
148 | if (send_tomtou) | 133 | if (send_tomtou) |
149 | ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", | 134 | ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", |
@@ -166,9 +151,9 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, | |||
166 | assert_spin_locked(&inode->i_lock); | 151 | assert_spin_locked(&inode->i_lock); |
167 | 152 | ||
168 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { | 153 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { |
169 | if (unlikely(iint->readcount == 0)) | 154 | if (unlikely(inode->i_readcount == 0)) |
170 | dump = true; | 155 | dump = true; |
171 | iint->readcount--; | 156 | inode->i_readcount--; |
172 | } | 157 | } |
173 | if (mode & FMODE_WRITE) { | 158 | if (mode & FMODE_WRITE) { |
174 | if (atomic_read(&inode->i_writecount) <= 0) | 159 | if (atomic_read(&inode->i_writecount) <= 0) |
@@ -180,7 +165,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, | |||
180 | 165 | ||
181 | if (dump && !ima_limit_imbalance(file)) { | 166 | if (dump && !ima_limit_imbalance(file)) { |
182 | printk(KERN_INFO "%s: open/free imbalance (r:%u)\n", | 167 | printk(KERN_INFO "%s: open/free imbalance (r:%u)\n", |
183 | __func__, iint->readcount); | 168 | __func__, inode->i_readcount); |
184 | dump_stack(); | 169 | dump_stack(); |
185 | } | 170 | } |
186 | } | 171 | } |