On Mon, 2025-09-08 at 18:58 +0800, Coiby Xu wrote: > 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 sets security.selinux for a file.
The problem description should be generic. -> and then writes some other security xattr for the file. Start a new paragraph here for the example. > For example, on > Fedora, after booting the kernel with "ima_appraise=fix evm=fix > ima_policy=appraise_tcb" and installing rpm-plugin-ima, 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 selinux.selinux, the IMA_DIGSIG flag > that had been set early was cleared. As a result, IMA hash is generated > when the file is closed. Start a new paragraph here, adding a sentence describing the solution to the problem. For example, 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, > > #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 <c...@redhat.com> Thanks, Coiby. The updated patch looks good. Have you looked at the other calls to ima_reset_appraise_flags() to make sure they don't need to be adjusted? thanks, Mimi > --- > security/integrity/ima/ima_appraise.c | 15 +++++++++++++-- > 1 file changed, 13 insertions(+), 2 deletions(-) > > diff --git a/security/integrity/ima/ima_appraise.c > b/security/integrity/ima/ima_appraise.c > index f435eff4667f..4e4750ea41ad 100644 > --- a/security/integrity/ima/ima_appraise.c > +++ b/security/integrity/ima/ima_appraise.c > @@ -694,6 +694,15 @@ static int ima_protect_xattr(struct dentry *dentry, > const char *xattr_name, > return 0; > } > > +/* > + * ima_reset_appraise_flags - reset ima_iint_cache flags > + * > + * @digsig: whether to clear/set IMA_DIGSIG flag, tristate values > + * 0: clear IMA_DIGSIG > + * 1: set IMA_DIGSIG > + * -1: don't change IMA_DIGSIG > + * > + */ > static void ima_reset_appraise_flags(struct inode *inode, int digsig) > { > struct ima_iint_cache *iint; > @@ -706,9 +715,9 @@ static void ima_reset_appraise_flags(struct inode *inode, > int digsig) > return; > iint->measured_pcrs = 0; > set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags); > - if (digsig) > + if (digsig == 1) > set_bit(IMA_DIGSIG, &iint->atomic_flags); > - else > + else if (digsig == 0) > clear_bit(IMA_DIGSIG, &iint->atomic_flags); > } > > @@ -794,6 +803,8 @@ static int ima_inode_setxattr(struct mnt_idmap *idmap, > struct dentry *dentry, > digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG); > } else if (!strcmp(xattr_name, XATTR_NAME_EVM) && xattr_value_len > 0) { > digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG); > + } else { > + digsig = -1; > } > if (result == 1 || evm_revalidate_status(xattr_name)) { > ima_reset_appraise_flags(d_backing_inode(dentry), digsig);