Skip to content

Commit a408e4a

Browse files
Goldwyn Rodriguesmimizohar
authored andcommitted
ima: open a new file instance if no read permissions
Open a new file instance as opposed to changing file->f_mode when the file is not readable. This is done to accomodate overlayfs stacked file operations change. The real struct file is hidden behind the overlays struct file. So, any file->f_mode manipulations are not reflected on the real struct file. Open the file again in read mode if original file cannot be read, read and calculate the hash. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Cc: stable@vger.kernel.org (linux-4.19) Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
1 parent 1e4c8da commit a408e4a

File tree

1 file changed

+34
-20
lines changed

1 file changed

+34
-20
lines changed

security/integrity/ima/ima_crypto.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ static int ima_calc_file_hash_atfm(struct file *file,
210210
{
211211
loff_t i_size, offset;
212212
char *rbuf[2] = { NULL, };
213-
int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0;
213+
int rc, rbuf_len, active = 0, ahash_rc = 0;
214214
struct ahash_request *req;
215215
struct scatterlist sg[1];
216216
struct crypto_wait wait;
@@ -257,11 +257,6 @@ static int ima_calc_file_hash_atfm(struct file *file,
257257
&rbuf_size[1], 0);
258258
}
259259

260-
if (!(file->f_mode & FMODE_READ)) {
261-
file->f_mode |= FMODE_READ;
262-
read = 1;
263-
}
264-
265260
for (offset = 0; offset < i_size; offset += rbuf_len) {
266261
if (!rbuf[1] && offset) {
267262
/* Not using two buffers, and it is not the first
@@ -300,8 +295,6 @@ static int ima_calc_file_hash_atfm(struct file *file,
300295
/* wait for the last update request to complete */
301296
rc = ahash_wait(ahash_rc, &wait);
302297
out3:
303-
if (read)
304-
file->f_mode &= ~FMODE_READ;
305298
ima_free_pages(rbuf[0], rbuf_size[0]);
306299
ima_free_pages(rbuf[1], rbuf_size[1]);
307300
out2:
@@ -336,7 +329,7 @@ static int ima_calc_file_hash_tfm(struct file *file,
336329
{
337330
loff_t i_size, offset = 0;
338331
char *rbuf;
339-
int rc, read = 0;
332+
int rc;
340333
SHASH_DESC_ON_STACK(shash, tfm);
341334

342335
shash->tfm = tfm;
@@ -357,11 +350,6 @@ static int ima_calc_file_hash_tfm(struct file *file,
357350
if (!rbuf)
358351
return -ENOMEM;
359352

360-
if (!(file->f_mode & FMODE_READ)) {
361-
file->f_mode |= FMODE_READ;
362-
read = 1;
363-
}
364-
365353
while (offset < i_size) {
366354
int rbuf_len;
367355

@@ -378,8 +366,6 @@ static int ima_calc_file_hash_tfm(struct file *file,
378366
if (rc)
379367
break;
380368
}
381-
if (read)
382-
file->f_mode &= ~FMODE_READ;
383369
kfree(rbuf);
384370
out:
385371
if (!rc)
@@ -420,6 +406,8 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
420406
{
421407
loff_t i_size;
422408
int rc;
409+
struct file *f = file;
410+
bool new_file_instance = false, modified_flags = false;
423411

424412
/*
425413
* For consistency, fail file's opened with the O_DIRECT flag on
@@ -431,15 +419,41 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
431419
return -EINVAL;
432420
}
433421

434-
i_size = i_size_read(file_inode(file));
422+
/* Open a new file instance in O_RDONLY if we cannot read */
423+
if (!(file->f_mode & FMODE_READ)) {
424+
int flags = file->f_flags & ~(O_WRONLY | O_APPEND |
425+
O_TRUNC | O_CREAT | O_NOCTTY | O_EXCL);
426+
flags |= O_RDONLY;
427+
f = dentry_open(&file->f_path, flags, file->f_cred);
428+
if (IS_ERR(f)) {
429+
/*
430+
* Cannot open the file again, lets modify f_flags
431+
* of original and continue
432+
*/
433+
pr_info_ratelimited("Unable to reopen file for reading.\n");
434+
f = file;
435+
f->f_flags |= FMODE_READ;
436+
modified_flags = true;
437+
} else {
438+
new_file_instance = true;
439+
}
440+
}
441+
442+
i_size = i_size_read(file_inode(f));
435443

436444
if (ima_ahash_minsize && i_size >= ima_ahash_minsize) {
437-
rc = ima_calc_file_ahash(file, hash);
445+
rc = ima_calc_file_ahash(f, hash);
438446
if (!rc)
439-
return 0;
447+
goto out;
440448
}
441449

442-
return ima_calc_file_shash(file, hash);
450+
rc = ima_calc_file_shash(f, hash);
451+
out:
452+
if (new_file_instance)
453+
fput(f);
454+
else if (modified_flags)
455+
f->f_flags &= ~FMODE_READ;
456+
return rc;
443457
}
444458

445459
/*

0 commit comments

Comments
 (0)