Skip to content

Commit 15873a0

Browse files
coibyopsiff
authored andcommitted
ima: don't clear IMA_DIGSIG flag when setting or removing non-IMA xattr
[ Upstream commit 88b4cbc ] Currently when both IMA and EVM are in fix mode, the IMA signature will be reset to IMA hash if a program first stores IMA signature in security.ima and then writes/removes some other security xattr for the file. For example, on Fedora, after booting the kernel with "ima_appraise=fix evm=fix ima_policy=appraise_tcb" and installing rpm-plugin-ima, installing/reinstalling a package will not make good reference IMA signature generated. Instead IMA hash is generated, # getfattr -m - -d -e hex /usr/bin/bash # file: usr/bin/bash security.ima=0x0404... This happens because when setting security.selinux, the IMA_DIGSIG flag that had been set early was cleared. As a result, IMA hash is generated when the file is closed. Similarly, IMA signature can be cleared on file close after removing security xattr like security.evm or setting/removing ACL. Prevent replacing the IMA file signature with a file hash, by preventing the IMA_DIGSIG flag from being reset. Here's a minimal C reproducer which sets security.selinux as the last step which can also replaced by removing security.evm or setting ACL, #include <stdio.h> #include <sys/xattr.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <stdlib.h> int main() { const char* file_path = "/usr/sbin/test_binary"; const char* hex_string = "030204d33204490066306402304"; int length = strlen(hex_string); char* ima_attr_value; int fd; fd = open(file_path, O_WRONLY|O_CREAT|O_EXCL, 0644); if (fd == -1) { perror("Error opening file"); return 1; } ima_attr_value = (char*)malloc(length / 2 ); for (int i = 0, j = 0; i < length; i += 2, j++) { sscanf(hex_string + i, "%2hhx", &ima_attr_value[j]); } if (fsetxattr(fd, "security.ima", ima_attr_value, length/2, 0) == -1) { perror("Error setting extended attribute"); close(fd); return 1; } const char* selinux_value= "system_u:object_r:bin_t:s0"; if (fsetxattr(fd, "security.selinux", selinux_value, strlen(selinux_value), 0) == -1) { perror("Error setting extended attribute"); close(fd); return 1; } close(fd); return 0; } Signed-off-by: Coiby Xu <[email protected]> Signed-off-by: Mimi Zohar <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit d2993a7e98eb70c737c6f5365a190e79c72b8407) Signed-off-by: Wentao Guan <[email protected]>
1 parent d35b091 commit 15873a0

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

security/integrity/ima/ima_appraise.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,15 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
671671
return 0;
672672
}
673673

674+
/*
675+
* ima_reset_appraise_flags - reset ima_iint_cache flags
676+
*
677+
* @digsig: whether to clear/set IMA_DIGSIG flag, tristate values
678+
* 0: clear IMA_DIGSIG
679+
* 1: set IMA_DIGSIG
680+
* -1: don't change IMA_DIGSIG
681+
*
682+
*/
674683
static void ima_reset_appraise_flags(struct inode *inode, int digsig)
675684
{
676685
struct integrity_iint_cache *iint;
@@ -683,9 +692,9 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig)
683692
return;
684693
iint->measured_pcrs = 0;
685694
set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags);
686-
if (digsig)
695+
if (digsig == 1)
687696
set_bit(IMA_DIGSIG, &iint->atomic_flags);
688-
else
697+
else if (digsig == 0)
689698
clear_bit(IMA_DIGSIG, &iint->atomic_flags);
690699
}
691700

@@ -770,6 +779,8 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
770779
digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
771780
} else if (!strcmp(xattr_name, XATTR_NAME_EVM) && xattr_value_len > 0) {
772781
digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
782+
} else {
783+
digsig = -1;
773784
}
774785
if (result == 1 || evm_revalidate_status(xattr_name)) {
775786
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
@@ -783,18 +794,20 @@ int ima_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
783794
const char *acl_name, struct posix_acl *kacl)
784795
{
785796
if (evm_revalidate_status(acl_name))
786-
ima_reset_appraise_flags(d_backing_inode(dentry), 0);
797+
ima_reset_appraise_flags(d_backing_inode(dentry), -1);
787798

788799
return 0;
789800
}
790801

791802
int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
792803
{
793-
int result;
804+
int result, digsig = -1;
794805

795806
result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
796807
if (result == 1 || evm_revalidate_status(xattr_name)) {
797-
ima_reset_appraise_flags(d_backing_inode(dentry), 0);
808+
if (!strcmp(xattr_name, XATTR_NAME_IMA))
809+
digsig = 0;
810+
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
798811
if (result == 1)
799812
result = 0;
800813
}

0 commit comments

Comments
 (0)