Skip to content

Commit 05d1a71

Browse files
author
Mimi Zohar
committed
ima: add support for creating files using the mknodat syscall
Commit 3034a14 "ima: pass 'opened' flag to identify newly created files" stopped identifying empty files as new files. However new empty files can be created using the mknodat syscall. On systems with IMA-appraisal enabled, these empty files are not labeled with security.ima extended attributes properly, preventing them from subsequently being opened in order to write the file data contents. This patch defines a new hook named ima_post_path_mknod() to mark these empty files, created using mknodat, as new in order to allow the file data contents to be written. In addition, files with security.ima xattrs containing a file signature are considered "immutable" and can not be modified. The file contents need to be written, before signing the file. This patch relaxes this requirement for new files, allowing the file signature to be written before the file contents. Changelog: - defer identifying files with signatures stored as security.ima (based on Dmitry Rozhkov's comments) - removing tests (eg. dentry, dentry->d_inode, inode->i_size == 0) (based on Al's review) Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Cc: Al Viro <<viro@zeniv.linux.org.uk> Tested-by: Dmitry Rozhkov <dmitry.rozhkov@linux.intel.com>
1 parent 42a4c60 commit 05d1a71

File tree

4 files changed

+37
-1
lines changed

4 files changed

+37
-1
lines changed

fs/namei.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3608,6 +3608,8 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
36083608
switch (mode & S_IFMT) {
36093609
case 0: case S_IFREG:
36103610
error = vfs_create(path.dentry->d_inode,dentry,mode,true);
3611+
if (!error)
3612+
ima_post_path_mknod(dentry);
36113613
break;
36123614
case S_IFCHR: case S_IFBLK:
36133615
error = vfs_mknod(path.dentry->d_inode,dentry,mode,

include/linux/ima.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extern int ima_file_mmap(struct file *file, unsigned long prot);
2121
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
2222
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
2323
enum kernel_read_file_id id);
24+
extern void ima_post_path_mknod(struct dentry *dentry);
2425

2526
#else
2627
static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -54,6 +55,11 @@ static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
5455
return 0;
5556
}
5657

58+
static inline void ima_post_path_mknod(struct dentry *dentry)
59+
{
60+
return;
61+
}
62+
5763
#endif /* CONFIG_IMA */
5864

5965
#ifdef CONFIG_IMA_APPRAISE

security/integrity/ima/ima_appraise.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,11 @@ int ima_appraise_measurement(enum ima_hooks func,
275275
xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
276276
if (!ima_fix_xattr(dentry, iint))
277277
status = INTEGRITY_PASS;
278+
} else if ((inode->i_size == 0) &&
279+
(iint->flags & IMA_NEW_FILE) &&
280+
(xattr_value &&
281+
xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
282+
status = INTEGRITY_PASS;
278283
}
279284
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
280285
op, cause, rc, 0);

security/integrity/ima/ima_main.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
246246
ima_audit_measurement(iint, pathname);
247247

248248
out_digsig:
249-
if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG))
249+
if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG) &&
250+
!(iint->flags & IMA_NEW_FILE))
250251
rc = -EACCES;
251252
kfree(xattr_value);
252253
out_free:
@@ -315,6 +316,28 @@ int ima_file_check(struct file *file, int mask, int opened)
315316
}
316317
EXPORT_SYMBOL_GPL(ima_file_check);
317318

319+
/**
320+
* ima_post_path_mknod - mark as a new inode
321+
* @dentry: newly created dentry
322+
*
323+
* Mark files created via the mknodat syscall as new, so that the
324+
* file data can be written later.
325+
*/
326+
void ima_post_path_mknod(struct dentry *dentry)
327+
{
328+
struct integrity_iint_cache *iint;
329+
struct inode *inode = dentry->d_inode;
330+
int must_appraise;
331+
332+
must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK);
333+
if (!must_appraise)
334+
return;
335+
336+
iint = integrity_inode_get(inode);
337+
if (iint)
338+
iint->flags |= IMA_NEW_FILE;
339+
}
340+
318341
/**
319342
* ima_read_file - pre-measure/appraise hook decision based on policy
320343
* @file: pointer to the file to be measured/appraised/audit

0 commit comments

Comments
 (0)