diff options
-rw-r--r-- | security/integrity/ima/ima_main.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2191b36ad1da..03bb52ecf490 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -77,21 +77,19 @@ __setup("ima_hash=", hash_setup); | |||
77 | * could result in a file measurement error. | 77 | * could result in a file measurement error. |
78 | * | 78 | * |
79 | */ | 79 | */ |
80 | static void ima_rdwr_violation_check(struct file *file) | 80 | static void ima_rdwr_violation_check(struct file *file, |
81 | struct integrity_iint_cache *iint, | ||
82 | char **pathbuf, | ||
83 | const char **pathname) | ||
81 | { | 84 | { |
82 | struct inode *inode = file_inode(file); | 85 | struct inode *inode = file_inode(file); |
83 | fmode_t mode = file->f_mode; | 86 | fmode_t mode = file->f_mode; |
84 | bool send_tomtou = false, send_writers = false; | 87 | bool send_tomtou = false, send_writers = false; |
85 | char *pathbuf = NULL; | ||
86 | const char *pathname; | ||
87 | |||
88 | if (!S_ISREG(inode->i_mode) || !(ima_policy_flag & IMA_MEASURE)) | ||
89 | return; | ||
90 | 88 | ||
91 | if (mode & FMODE_WRITE) { | 89 | if (mode & FMODE_WRITE) { |
92 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { | 90 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { |
93 | struct integrity_iint_cache *iint; | 91 | if (!iint) |
94 | iint = integrity_iint_find(inode); | 92 | iint = integrity_iint_find(inode); |
95 | /* IMA_MEASURE is set from reader side */ | 93 | /* IMA_MEASURE is set from reader side */ |
96 | if (iint && (iint->flags & IMA_MEASURE)) | 94 | if (iint && (iint->flags & IMA_MEASURE)) |
97 | send_tomtou = true; | 95 | send_tomtou = true; |
@@ -105,14 +103,13 @@ static void ima_rdwr_violation_check(struct file *file) | |||
105 | if (!send_tomtou && !send_writers) | 103 | if (!send_tomtou && !send_writers) |
106 | return; | 104 | return; |
107 | 105 | ||
108 | pathname = ima_d_path(&file->f_path, &pathbuf); | 106 | *pathname = ima_d_path(&file->f_path, pathbuf); |
109 | 107 | ||
110 | if (send_tomtou) | 108 | if (send_tomtou) |
111 | ima_add_violation(file, pathname, "invalid_pcr", "ToMToU"); | 109 | ima_add_violation(file, *pathname, "invalid_pcr", "ToMToU"); |
112 | if (send_writers) | 110 | if (send_writers) |
113 | ima_add_violation(file, pathname, | 111 | ima_add_violation(file, *pathname, |
114 | "invalid_pcr", "open_writers"); | 112 | "invalid_pcr", "open_writers"); |
115 | kfree(pathbuf); | ||
116 | } | 113 | } |
117 | 114 | ||
118 | static void ima_check_last_writer(struct integrity_iint_cache *iint, | 115 | static void ima_check_last_writer(struct integrity_iint_cache *iint, |
@@ -160,13 +157,14 @@ static int process_measurement(struct file *file, int mask, int function, | |||
160 | int opened) | 157 | int opened) |
161 | { | 158 | { |
162 | struct inode *inode = file_inode(file); | 159 | struct inode *inode = file_inode(file); |
163 | struct integrity_iint_cache *iint; | 160 | struct integrity_iint_cache *iint = NULL; |
164 | struct ima_template_desc *template_desc; | 161 | struct ima_template_desc *template_desc; |
165 | char *pathbuf = NULL; | 162 | char *pathbuf = NULL; |
166 | const char *pathname = NULL; | 163 | const char *pathname = NULL; |
167 | int rc = -ENOMEM, action, must_appraise; | 164 | int rc = -ENOMEM, action, must_appraise; |
168 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; | 165 | struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; |
169 | int xattr_len = 0; | 166 | int xattr_len = 0; |
167 | bool violation_check; | ||
170 | 168 | ||
171 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) | 169 | if (!ima_policy_flag || !S_ISREG(inode->i_mode)) |
172 | return 0; | 170 | return 0; |
@@ -176,7 +174,9 @@ static int process_measurement(struct file *file, int mask, int function, | |||
176 | * Included is the appraise submask. | 174 | * Included is the appraise submask. |
177 | */ | 175 | */ |
178 | action = ima_get_action(inode, mask, function); | 176 | action = ima_get_action(inode, mask, function); |
179 | if (!action) | 177 | violation_check = (function == FILE_CHECK && |
178 | (ima_policy_flag & IMA_MEASURE)); | ||
179 | if (!action && !violation_check) | ||
180 | return 0; | 180 | return 0; |
181 | 181 | ||
182 | must_appraise = action & IMA_APPRAISE; | 182 | must_appraise = action & IMA_APPRAISE; |
@@ -187,9 +187,19 @@ static int process_measurement(struct file *file, int mask, int function, | |||
187 | 187 | ||
188 | mutex_lock(&inode->i_mutex); | 188 | mutex_lock(&inode->i_mutex); |
189 | 189 | ||
190 | iint = integrity_inode_get(inode); | 190 | if (action) { |
191 | if (!iint) | 191 | iint = integrity_inode_get(inode); |
192 | goto out; | 192 | if (!iint) |
193 | goto out; | ||
194 | } | ||
195 | |||
196 | if (violation_check) { | ||
197 | ima_rdwr_violation_check(file, iint, &pathbuf, &pathname); | ||
198 | if (!action) { | ||
199 | rc = 0; | ||
200 | goto out_free; | ||
201 | } | ||
202 | } | ||
193 | 203 | ||
194 | /* Determine if already appraised/measured based on bitmask | 204 | /* Determine if already appraised/measured based on bitmask |
195 | * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, | 205 | * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED, |
@@ -218,7 +228,8 @@ static int process_measurement(struct file *file, int mask, int function, | |||
218 | goto out_digsig; | 228 | goto out_digsig; |
219 | } | 229 | } |
220 | 230 | ||
221 | pathname = ima_d_path(&file->f_path, &pathbuf); | 231 | if (!pathname) /* ima_rdwr_violation possibly pre-fetched */ |
232 | pathname = ima_d_path(&file->f_path, &pathbuf); | ||
222 | 233 | ||
223 | if (action & IMA_MEASURE) | 234 | if (action & IMA_MEASURE) |
224 | ima_store_measurement(iint, file, pathname, | 235 | ima_store_measurement(iint, file, pathname, |
@@ -228,13 +239,15 @@ static int process_measurement(struct file *file, int mask, int function, | |||
228 | xattr_value, xattr_len, opened); | 239 | xattr_value, xattr_len, opened); |
229 | if (action & IMA_AUDIT) | 240 | if (action & IMA_AUDIT) |
230 | ima_audit_measurement(iint, pathname); | 241 | ima_audit_measurement(iint, pathname); |
231 | kfree(pathbuf); | 242 | |
232 | out_digsig: | 243 | out_digsig: |
233 | if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG)) | 244 | if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG)) |
234 | rc = -EACCES; | 245 | rc = -EACCES; |
246 | kfree(xattr_value); | ||
247 | out_free: | ||
248 | kfree(pathbuf); | ||
235 | out: | 249 | out: |
236 | mutex_unlock(&inode->i_mutex); | 250 | mutex_unlock(&inode->i_mutex); |
237 | kfree(xattr_value); | ||
238 | if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) | 251 | if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) |
239 | return -EACCES; | 252 | return -EACCES; |
240 | return 0; | 253 | return 0; |
@@ -288,7 +301,6 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
288 | */ | 301 | */ |
289 | int ima_file_check(struct file *file, int mask, int opened) | 302 | int ima_file_check(struct file *file, int mask, int opened) |
290 | { | 303 | { |
291 | ima_rdwr_violation_check(file); | ||
292 | return process_measurement(file, | 304 | return process_measurement(file, |
293 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | 305 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
294 | FILE_CHECK, opened); | 306 | FILE_CHECK, opened); |