Skip to content

Commit 4787322

Browse files
Mimi Zohargregkh
Mimi Zohar
authored andcommitted
ima: audit log files opened with O_DIRECT flag
commit f9b2a73 upstream. Files are measured or appraised based on the IMA policy. When a file, in policy, is opened with the O_DIRECT flag, a deadlock occurs. The first attempt at resolving this lockdep temporarily removed the O_DIRECT flag and restored it, after calculating the hash. The second attempt introduced the O_DIRECT_HAVELOCK flag. Based on this flag, do_blockdev_direct_IO() would skip taking the i_mutex a second time. The third attempt, by Dmitry Kasatkin, resolves the i_mutex locking issue, by re-introducing the IMA mutex, but uncovered another problem. Reading a file with O_DIRECT flag set, writes directly to userspace pages. A second patch allocates a user-space like memory. This works for all IMA hooks, except ima_file_free(), which is called on __fput() to recalculate the file hash. Until this last issue is addressed, do not 'collect' the measurement for measuring, appraising, or auditing files opened with the O_DIRECT flag set. Based on policy, permit or deny file access. This patch defines a new IMA policy rule option named 'permit_directio'. Policy rules could be defined, based on LSM or other criteria, to permit specific applications to open files with the O_DIRECT flag set. Changelog v1: - permit or deny file access based IMA policy rules Signed-off-by: Mimi Zohar <[email protected]> Acked-by: Dmitry Kasatkin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 50db1fe commit 4787322

File tree

5 files changed

+20
-4
lines changed

5 files changed

+20
-4
lines changed

Documentation/ABI/testing/ima_policy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Description:
2323
[fowner]]
2424
lsm: [[subj_user=] [subj_role=] [subj_type=]
2525
[obj_user=] [obj_role=] [obj_type=]]
26-
option: [[appraise_type=]]
26+
option: [[appraise_type=]] [permit_directio]
2727

2828
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
2929
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]

security/integrity/ima/ima_api.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
199199
struct evm_ima_xattr_data **xattr_value,
200200
int *xattr_len)
201201
{
202+
const char *audit_cause = "failed";
202203
struct inode *inode = file_inode(file);
203204
const char *filename = file->f_dentry->d_name.name;
204205
int result = 0;
@@ -213,6 +214,12 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
213214
if (!(iint->flags & IMA_COLLECTED)) {
214215
u64 i_version = file_inode(file)->i_version;
215216

217+
if (file->f_flags & O_DIRECT) {
218+
audit_cause = "failed(directio)";
219+
result = -EACCES;
220+
goto out;
221+
}
222+
216223
/* use default hash algorithm */
217224
hash.hdr.algo = ima_hash_algo;
218225

@@ -233,9 +240,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
233240
result = -ENOMEM;
234241
}
235242
}
243+
out:
236244
if (result)
237245
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
238-
filename, "collect_data", "failed",
246+
filename, "collect_data", audit_cause,
239247
result, 0);
240248
return result;
241249
}

security/integrity/ima/ima_main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,11 @@ static int process_measurement(struct file *file, const char *filename,
214214
xattr_ptr = &xattr_value;
215215

216216
rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
217-
if (rc != 0)
217+
if (rc != 0) {
218+
if (file->f_flags & O_DIRECT)
219+
rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
218220
goto out_digsig;
221+
}
219222

220223
pathname = filename ?: ima_d_path(&file->f_path, &pathbuf);
221224

security/integrity/ima/ima_policy.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ enum {
353353
Opt_obj_user, Opt_obj_role, Opt_obj_type,
354354
Opt_subj_user, Opt_subj_role, Opt_subj_type,
355355
Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
356-
Opt_appraise_type, Opt_fsuuid
356+
Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
357357
};
358358

359359
static match_table_t policy_tokens = {
@@ -375,6 +375,7 @@ static match_table_t policy_tokens = {
375375
{Opt_uid, "uid=%s"},
376376
{Opt_fowner, "fowner=%s"},
377377
{Opt_appraise_type, "appraise_type=%s"},
378+
{Opt_permit_directio, "permit_directio"},
378379
{Opt_err, NULL}
379380
};
380381

@@ -622,6 +623,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
622623
else
623624
result = -EINVAL;
624625
break;
626+
case Opt_permit_directio:
627+
entry->flags |= IMA_PERMIT_DIRECTIO;
628+
break;
625629
case Opt_err:
626630
ima_log_string(ab, "UNKNOWN", p);
627631
result = -EINVAL;

security/integrity/integrity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define IMA_ACTION_FLAGS 0xff000000
3131
#define IMA_DIGSIG 0x01000000
3232
#define IMA_DIGSIG_REQUIRED 0x02000000
33+
#define IMA_PERMIT_DIRECTIO 0x04000000
3334

3435
#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
3536
IMA_APPRAISE_SUBMASK)

0 commit comments

Comments
 (0)