|
@@ -210,7 +210,7 @@ static int ima_calc_file_hash_atfm(struct file *file,
|
|
|
{
|
|
|
loff_t i_size, offset;
|
|
|
char *rbuf[2] = { NULL, };
|
|
|
- int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0;
|
|
|
+ int rc, rbuf_len, active = 0, ahash_rc = 0;
|
|
|
struct ahash_request *req;
|
|
|
struct scatterlist sg[1];
|
|
|
struct crypto_wait wait;
|
|
@@ -257,11 +257,6 @@ static int ima_calc_file_hash_atfm(struct file *file,
|
|
|
&rbuf_size[1], 0);
|
|
|
}
|
|
|
|
|
|
- if (!(file->f_mode & FMODE_READ)) {
|
|
|
- file->f_mode |= FMODE_READ;
|
|
|
- read = 1;
|
|
|
- }
|
|
|
-
|
|
|
for (offset = 0; offset < i_size; offset += rbuf_len) {
|
|
|
if (!rbuf[1] && offset) {
|
|
|
/* Not using two buffers, and it is not the first
|
|
@@ -300,8 +295,6 @@ static int ima_calc_file_hash_atfm(struct file *file,
|
|
|
/* wait for the last update request to complete */
|
|
|
rc = ahash_wait(ahash_rc, &wait);
|
|
|
out3:
|
|
|
- if (read)
|
|
|
- file->f_mode &= ~FMODE_READ;
|
|
|
ima_free_pages(rbuf[0], rbuf_size[0]);
|
|
|
ima_free_pages(rbuf[1], rbuf_size[1]);
|
|
|
out2:
|
|
@@ -336,7 +329,7 @@ static int ima_calc_file_hash_tfm(struct file *file,
|
|
|
{
|
|
|
loff_t i_size, offset = 0;
|
|
|
char *rbuf;
|
|
|
- int rc, read = 0;
|
|
|
+ int rc;
|
|
|
SHASH_DESC_ON_STACK(shash, tfm);
|
|
|
|
|
|
shash->tfm = tfm;
|
|
@@ -357,11 +350,6 @@ static int ima_calc_file_hash_tfm(struct file *file,
|
|
|
if (!rbuf)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- if (!(file->f_mode & FMODE_READ)) {
|
|
|
- file->f_mode |= FMODE_READ;
|
|
|
- read = 1;
|
|
|
- }
|
|
|
-
|
|
|
while (offset < i_size) {
|
|
|
int rbuf_len;
|
|
|
|
|
@@ -378,8 +366,6 @@ static int ima_calc_file_hash_tfm(struct file *file,
|
|
|
if (rc)
|
|
|
break;
|
|
|
}
|
|
|
- if (read)
|
|
|
- file->f_mode &= ~FMODE_READ;
|
|
|
kfree(rbuf);
|
|
|
out:
|
|
|
if (!rc)
|
|
@@ -420,6 +406,8 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
|
|
|
{
|
|
|
loff_t i_size;
|
|
|
int rc;
|
|
|
+ struct file *f = file;
|
|
|
+ bool new_file_instance = false, modified_flags = false;
|
|
|
|
|
|
/*
|
|
|
* 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)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- i_size = i_size_read(file_inode(file));
|
|
|
+ /* Open a new file instance in O_RDONLY if we cannot read */
|
|
|
+ if (!(file->f_mode & FMODE_READ)) {
|
|
|
+ int flags = file->f_flags & ~(O_WRONLY | O_APPEND |
|
|
|
+ O_TRUNC | O_CREAT | O_NOCTTY | O_EXCL);
|
|
|
+ flags |= O_RDONLY;
|
|
|
+ f = dentry_open(&file->f_path, flags, file->f_cred);
|
|
|
+ if (IS_ERR(f)) {
|
|
|
+ /*
|
|
|
+ * Cannot open the file again, lets modify f_flags
|
|
|
+ * of original and continue
|
|
|
+ */
|
|
|
+ pr_info_ratelimited("Unable to reopen file for reading.\n");
|
|
|
+ f = file;
|
|
|
+ f->f_flags |= FMODE_READ;
|
|
|
+ modified_flags = true;
|
|
|
+ } else {
|
|
|
+ new_file_instance = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ i_size = i_size_read(file_inode(f));
|
|
|
|
|
|
if (ima_ahash_minsize && i_size >= ima_ahash_minsize) {
|
|
|
- rc = ima_calc_file_ahash(file, hash);
|
|
|
+ rc = ima_calc_file_ahash(f, hash);
|
|
|
if (!rc)
|
|
|
- return 0;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
- return ima_calc_file_shash(file, hash);
|
|
|
+ rc = ima_calc_file_shash(f, hash);
|
|
|
+out:
|
|
|
+ if (new_file_instance)
|
|
|
+ fput(f);
|
|
|
+ else if (modified_flags)
|
|
|
+ f->f_flags &= ~FMODE_READ;
|
|
|
+ return rc;
|
|
|
}
|
|
|
|
|
|
/*
|