[RFC][PATCH] overlayfs: Redirect xattr ops on security.evm to security.evm_overlayfs

Roberto Sassu roberto.sassu at huaweicloud.com
Tue Dec 12 10:24:50 UTC 2023


On 11.12.23 19:01, Christian Brauner wrote:
>> The second problem is that one security.evm is not enough. We need two,
>> to store the two different HMACs. And we need both at the same time,
>> since when overlayfs is mounted the lower/upper directories can be
>> still accessible.
> 
> "Changes to the underlying filesystems while part of a mounted overlay
> filesystem are not allowed. If the underlying filesystem is changed, the
> behavior of the overlay is undefined, though it will not result in a
> crash or deadlock."
> 
> https://docs.kernel.org/filesystems/overlayfs.html#changes-to-underlying-filesystems
> 
> So I don't know why this would be a problem.

+ Eric Snowberg

Ok, that would reduce the surface of attack. However, when looking at:

      ovl: Always reevaluate the file signature for IMA

      Commit db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the 
i_version")
      partially closed an IMA integrity issue when directly modifying a file
      on the lower filesystem.  If the overlay file is first opened by a 
user
      and later the lower backing file is modified by root, but the extended
      attribute is NOT updated, the signature validation succeeds with 
the old
      original signature.

Ok, so if the behavior of overlayfs is undefined if the lower backing 
file is modified by root, do we need to reevaluate? Or instead would be 
better to forbid the write from IMA (legitimate, I think, since the 
behavior is documented)? I just saw that we have d_real_inode(), we can 
use it to determine if the write should be denied.

>> In the example I described, IMA tries to update security.ima, but this
>> causes EVM to attempt updating security.evm twice (once after the upper
>> filesystem performed the setxattr requested by overlayfs, another after
>> overlayfs performed the setxattr requested by IMA; the latter fails
> 
> So I think phrasing it this way is confusiong. All that overlayfs does
> is to forward that setxattr request to the upper layer. So really the
> overlayfs layer here is irrelevant?

I guess you meant (s/?/./).

The problem is calling vfs_setxattr()/vfs_removexattr() which makes EVM 
verify those calls. If overlayfs should be irrelevant, then it should 
use calls that don't cause EVM to be invoked. Otherwise, from EVM 
perspective it is equal to do an xattr operation from user space.

>> since EVM does not allow the VFS to directly update the HMAC).
> 
> Callchains and details, please. I don't understand what you mean.

Originally I wanted to analyze the stacktraces together, then for sake 
of brevity and (I thought) clarity, I decided to not include them. So, 
let's go through them.

  #0  evm_update_evmxattr (dentry=dentry at entry=0x6b6b6ba0, 
xattr_name=xattr_name at entry=0x60b39cf0 "security.ima",
      xattr_value=xattr_value at entry=0x653a7742 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302o\322", 
'\314' <repeats 36 times>, "@x:e", 
xattr_value_len=xattr_value_len at entry=34) at 
security/integrity/evm/evm_crypto.c:358
  #1  0x00000000604f011a in evm_inode_post_setxattr 
(dentry=dentry at entry=0x6b6b6ba0, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima", xattr_value=xattr_value at entry=0x653a7742, 
xattr_value_len=xattr_value_len at entry=34) at 
security/integrity/evm/evm_main.c:753
  #2  0x00000000604a36ff in security_inode_post_setxattr 
(dentry=dentry at entry=0x6b6b6ba0, name=name at entry=0x60b39cf0 
"security.ima", value=value at entry=0x653a7742, size=size at entry=34, 
flags=flags at entry=0) at security/security.c:2286
  #3  0x0000000060232570 in __vfs_setxattr_noperm 
(idmap=idmap at entry=0x60ea0250 <nop_mnt_idmap>, 
dentry=dentry at entry=0x6b6b6ba0, name=name at entry=0x60b39cf0 
"security.ima", value=value at entry=0x653a7742, size=size at entry=34, 
flags=flags at entry=0) at fs/xattr.c:239
  #4  0x0000000060232778 in __vfs_setxattr_locked 
(idmap=idmap at entry=0x60ea0250 <nop_mnt_idmap>, 
dentry=dentry at entry=0x6b6b6ba0, name=name at entry=0x60b39cf0 
"security.ima", value=0x653a7742, size=size at entry=34, 
flags=flags at entry=0, delegated_inode=0xe1003b18) at fs/xattr.c:296
  #5  0x0000000060232829 in vfs_setxattr (idmap=0x60ea0250 
<nop_mnt_idmap>, dentry=dentry at entry=0x6b6b6ba0, 
name=name at entry=0x60b39cf0 "security.ima", value=<optimized out>, 
value at entry=0x653a7742, size=size at entry=34, flags=flags at entry=0) at 
fs/xattr.c:322
  #6  0x00000000603a4440 in ovl_do_setxattr (ofs=0x65366008, 
ofs=0x65366008, flags=0, size=34, value=0x653a7742, name=0x60b39cf0 
"security.ima", dentry=0x6b6b6ba0) at ./include/linux/mount.h:80
  #7  ovl_xattr_set (dentry=0x6b6b7dd8, inode=0x6367cbb8, 
name=0x60b39cf0 "security.ima", value=0x653a7742, size=size at entry=34, 
flags=flags at entry=0) at fs/overlayfs/xattrs.c:69
  #8  0x00000000603a4698 in ovl_other_xattr_set (handler=<optimized 
out>, idmap=<optimized out>, dentry=<optimized out>, inode=<optimized 
out>, name=<optimized out>, value=<optimized out>, size=34, flags=0) at 
fs/overlayfs/xattrs.c:233
  #9  0x0000000060231bd6 in __vfs_setxattr (idmap=idmap at entry=0x60ea0250 
<nop_mnt_idmap>, dentry=dentry at entry=0x6b6b7dd8, 
inode=inode at entry=0x6367cbb8, name=<optimized out>, 
name at entry=0x60b39cf0 "security.ima", value=value at entry=0x653a7742, 
size=size at entry=34, flags=0)
      at fs/xattr.c:201
  #10 0x000000006023246e in __vfs_setxattr_noperm (idmap=0x60ea0250 
<nop_mnt_idmap>, dentry=dentry at entry=0x6b6b7dd8, 
name=name at entry=0x60b39cf0 "security.ima", value=0x653a7742, size=34, 
flags=flags at entry=0) at fs/xattr.c:235
  #11 0x00000000604ed684 in ima_fix_xattr 
(dentry=dentry at entry=0x6b6b7dd8, iint=iint at entry=0x651d2008) at 
security/integrity/ima/ima_appraise.c:101
  #12 0x00000000604ee4c8 in ima_update_xattr 
(iint=iint at entry=0x651d2008, file=file at entry=0x6a3c76c0) at 
security/integrity/ima/ima_appraise.c:624
  #13 0x00000000604e32cc in ima_check_last_writer (iint=0x651d2008, 
inode=inode at entry=0x6367cbb8, file=file at entry=0x6a3c76c0) at 
security/integrity/ima/ima_main.c:180
  #14 0x00000000604e461c in ima_file_free (file=file at entry=0x6a3c76c0) 
at security/integrity/ima/ima_main.c:204
  #15 0x00000000601f3cd8 in __fput (file=0x6a3c76c0) at fs/file_table.c:388
  #16 0x00000000601f40c4 in ____fput (work=<optimized out>) at 
fs/file_table.c:422
  #17 0x000000006007d87c in task_work_run () at kernel/task_work.c:180
  #18 0x000000006002f294 in resume_user_mode_work (regs=<optimized out>) 
at ./include/linux/resume_user_mode.h:49
  #19 interrupt_end () at arch/um/kernel/process.c:108
  #20 0x0000000060049bf8 in userspace (regs=0x632b1360, 
aux_fp_regs=0xe1000020) at arch/um/os-Linux/skas/process.c:499
  #21 0x000000006002ee94 in new_thread_handler () at 
arch/um/kernel/process.c:136

Here IMA is updating security.ima at file close after a write (frame 
#12). The overlayfs dentry is 0x6b6b7dd8, the upper dentry is 0x6b6b6ba0.

Issuing a setxattr operation to overlayfs causes the latter to call 
vfs_setxattr() (frame #5). From EVM perspective, this is just a setxattr 
operation on the upper filesystem, so it processes it normally (we are 
already past evm_inode_setxattr() which succeeded, now we are in the 
post method after the operation).

What evm_update_evmxattr() does is the following:

		rc = __vfs_setxattr_noperm(&nop_mnt_idmap, dentry,
					   XATTR_NAME_EVM,
					   &data.hdr.xattr.data[1],
					   SHA1_DIGEST_SIZE + 1, 0);

This is still done on the upper dentry:

  #0  __vfs_setxattr_noperm (idmap=idmap at entry=0x60ea0250 
<nop_mnt_idmap>, dentry=dentry at entry=0x6b6b6ba0, 
name=name at entry=0x60b39c34 "security.evm", value=value at entry=0xe1003923, 
size=size at entry=21, flags=flags at entry=0) at fs/xattr.c:226
  #1  0x00000000604f0e06 in evm_update_evmxattr 
(dentry=dentry at entry=0x6b6b6ba0, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima",
      xattr_value=xattr_value at entry=0x653a7742 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302o\322", 
'\314' <repeats 36 times>, "@x:e", 
xattr_value_len=xattr_value_len at entry=34) at 
security/integrity/evm/evm_crypto.c:378

Everything good until this point. EVM just set the HMAC on the upper 
dentry. Let's see the next call to evm_update_evmxattr():

  #0  evm_update_evmxattr (dentry=dentry at entry=0x6b6b7dd8, 
xattr_name=xattr_name at entry=0x60b39cf0 "security.ima",
      xattr_value=xattr_value at entry=0x653a7742 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302o\322", 
'\314' <repeats 36 times>, "@x:e", 
xattr_value_len=xattr_value_len at entry=34) at 
security/integrity/evm/evm_crypto.c:358
  #1  0x00000000604f011a in evm_inode_post_setxattr 
(dentry=dentry at entry=0x6b6b7dd8, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima", xattr_value=xattr_value at entry=0x653a7742, 
xattr_value_len=xattr_value_len at entry=34) at 
security/integrity/evm/evm_main.c:753
  #2  0x00000000604a36ff in security_inode_post_setxattr 
(dentry=dentry at entry=0x6b6b7dd8, name=name at entry=0x60b39cf0 
"security.ima", value=value at entry=0x653a7742, size=size at entry=34, 
flags=flags at entry=0) at security/security.c:2286
  #3  0x0000000060232570 in __vfs_setxattr_noperm (idmap=<optimized 
out>, dentry=dentry at entry=0x6b6b7dd8, name=name at entry=0x60b39cf0 
"security.ima", value=0x653a7742, size=34, flags=flags at entry=0) at 
fs/xattr.c:239
  #4  0x00000000604ed684 in ima_fix_xattr 
(dentry=dentry at entry=0x6b6b7dd8, iint=iint at entry=0x651d2008) at 
security/integrity/ima/ima_appraise.c:101
  #5  0x00000000604ee4c8 in ima_update_xattr 
(iint=iint at entry=0x651d2008, file=file at entry=0x6a3c76c0) at 
security/integrity/ima/ima_appraise.c:624
  #6  0x00000000604e32cc in ima_check_last_writer (iint=0x651d2008, 
inode=inode at entry=0x6367cbb8, file=file at entry=0x6a3c76c0) at 
security/integrity/ima/ima_main.c:180
  #7  0x00000000604e461c in ima_file_free (file=file at entry=0x6a3c76c0) 
at security/integrity/ima/ima_main.c:204
  #8  0x00000000601f3cd8 in __fput (file=0x6a3c76c0) at fs/file_table.c:388
  #9  0x00000000601f40c4 in ____fput (work=<optimized out>) at 
fs/file_table.c:422
  #10 0x000000006007d87c in task_work_run () at kernel/task_work.c:180
  #11 0x000000006002f294 in resume_user_mode_work (regs=<optimized out>) 
at ./include/linux/resume_user_mode.h:49
  #12 interrupt_end () at arch/um/kernel/process.c:108
  #13 0x0000000060049bf8 in userspace (regs=0x632b1360, 
aux_fp_regs=0xe1000020) at arch/um/os-Linux/skas/process.c:499
  #14 0x000000006002ee94 in new_thread_handler () at 
arch/um/kernel/process.c:136
  #15 0x0000000000000000 in ?? ()

This is the relationship between the two stacktraces:

  int __vfs_setxattr_noperm(struct mnt_idmap *idmap,
  			  struct dentry *dentry, const char *name,
  			  const void *value, size_t size, int flags)
  {
  	struct inode *inode = dentry->d_inode;
  	int error = -EAGAIN;
  	int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
  				   XATTR_SECURITY_PREFIX_LEN);

  	if (issec)
  		inode->i_flags &= ~S_NOSEC;
  	if (inode->i_opflags & IOP_XATTR) {
  		error = __vfs_setxattr(idmap, dentry, inode, name, value, ====> 
first stacktrace (frame #9)
  				       size, flags);
  		if (!error) {
  			fsnotify_xattr(dentry);
  			security_inode_post_setxattr(dentry, name, value, ====> second 
stacktrace (frame #2)
  						     size, flags);
  		}

Now we are back in the post method after the setxattr call issued to 
overlayfs. EVM treats it no differently from the first setxattr 
operation on the upper filesystem, and again tries to set security.evm, 
this time on overlayfs:

  Breakpoint 2, __vfs_setxattr_noperm (idmap=idmap at entry=0x60ea0250 
<nop_mnt_idmap>, dentry=dentry at entry=0x6b6b7dd8, 
name=name at entry=0x60b39c34 "security.evm", value=value at entry=0xe1003b63, 
size=size at entry=21, flags=flags at entry=0) at fs/xattr.c:226
  226	{

If we were in the upper filesystem, there would not have been any 
problem, __vfs_setxattr() does not call evm_inode_setxattr() which fails 
for security.evm and an HMAC as value.

However, we are in the overlayfs, so we pass the setxattr operation through:

  #0  evm_inode_setxattr (idmap=idmap at entry=0x60ea0250 <nop_mnt_idmap>, 
dentry=dentry at entry=0x6b6b6ba0, xattr_name=xattr_name at entry=0x60b39c34 
"security.evm", xattr_value=xattr_value at entry=0xe1003b63, 
xattr_value_len=xattr_value_len at entry=21) at 
security/integrity/evm/evm_main.c:571
  #1  0x00000000604a344f in security_inode_setxattr 
(idmap=idmap at entry=0x60ea0250 <nop_mnt_idmap>, 
dentry=dentry at entry=0x6b6b6ba0, name=name at entry=0x60b39c34 
"security.evm", value=value at entry=0xe1003b63, size=size at entry=21, 
flags=flags at entry=0) at security/security.c:2191
  #2  0x00000000602326e8 in __vfs_setxattr_locked 
(idmap=idmap at entry=0x60ea0250 <nop_mnt_idmap>, 
dentry=dentry at entry=0x6b6b6ba0, name=name at entry=0x60b39c34 
"security.evm", value=0xe1003b63, size=size at entry=21, 
flags=flags at entry=0, delegated_inode=0xe1003988) at fs/xattr.c:287
  #3  0x0000000060232829 in vfs_setxattr (idmap=0x60ea0250 
<nop_mnt_idmap>, dentry=dentry at entry=0x6b6b6ba0, 
name=name at entry=0x60b39c34 "security.evm", value=<optimized out>, 
value at entry=0xe1003b63, size=size at entry=21, flags=flags at entry=0) at 
fs/xattr.c:322
  #4  0x00000000603a4440 in ovl_do_setxattr (ofs=0x65366008, 
ofs=0x65366008, flags=0, size=21, value=0xe1003b63, name=0x60b39c34 
"security.evm", dentry=0x6b6b6ba0) at ./include/linux/mount.h:80
  #5  ovl_xattr_set (dentry=0x6b6b7dd8, inode=0x6367cbb8, 
name=0x60b39c34 "security.evm", value=0xe1003b63, size=size at entry=21, 
flags=flags at entry=0) at fs/overlayfs/xattrs.c:69
  #6  0x00000000603a4698 in ovl_other_xattr_set (handler=<optimized 
out>, idmap=<optimized out>, dentry=<optimized out>, inode=<optimized 
out>, name=<optimized out>, value=<optimized out>, size=21, flags=0) at 
fs/overlayfs/xattrs.c:233
  #7  0x0000000060231bd6 in __vfs_setxattr (idmap=idmap at entry=0x60ea0250 
<nop_mnt_idmap>, dentry=dentry at entry=0x6b6b7dd8, 
inode=inode at entry=0x6367cbb8, name=<optimized out>, 
name at entry=0x60b39c34 "security.evm", value=value at entry=0xe1003b63, 
size=size at entry=21, flags=0)
      at fs/xattr.c:201
  #8  0x000000006023246e in __vfs_setxattr_noperm 
(idmap=idmap at entry=0x60ea0250 <nop_mnt_idmap>, 
dentry=dentry at entry=0x6b6b7dd8, name=name at entry=0x60b39c34 
"security.evm", value=value at entry=0xe1003b63, size=size at entry=21, 
flags=flags at entry=0) at fs/xattr.c:235
  #9  0x00000000604f0e06 in evm_update_evmxattr 
(dentry=dentry at entry=0x6b6b7dd8, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima",
      xattr_value=xattr_value at entry=0x653a7742 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302o\322", 
'\314' <repeats 36 times>, "@x:e", 
xattr_value_len=xattr_value_len at entry=34) at 
security/integrity/evm/evm_crypto.c:378
  #10 0x00000000604f011a in evm_inode_post_setxattr 
(dentry=dentry at entry=0x6b6b7dd8, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima", xattr_value=xattr_value at entry=0x653a7742, 
xattr_value_len=xattr_value_len at entry=34) at 
security/integrity/evm/evm_main.c:753
  #11 0x00000000604a36ff in security_inode_post_setxattr 
(dentry=dentry at entry=0x6b6b7dd8, name=name at entry=0x60b39cf0 
"security.ima", value=value at entry=0x653a7742, size=size at entry=34, 
flags=flags at entry=0) at security/security.c:2286
  #12 0x0000000060232570 in __vfs_setxattr_noperm (idmap=<optimized 
out>, dentry=dentry at entry=0x6b6b7dd8, name=name at entry=0x60b39cf0 
"security.ima", value=0x653a7742, size=34, flags=flags at entry=0) at 
fs/xattr.c:239
  #13 0x00000000604ed684 in ima_fix_xattr 
(dentry=dentry at entry=0x6b6b7dd8, iint=iint at entry=0x651d2008) at 
security/integrity/ima/ima_appraise.c:101
  #14 0x00000000604ee4c8 in ima_update_xattr 
(iint=iint at entry=0x651d2008, file=file at entry=0x6a3c76c0) at 
security/integrity/ima/ima_appraise.c:624
  #15 0x00000000604e32cc in ima_check_last_writer (iint=0x651d2008, 
inode=inode at entry=0x6367cbb8, file=file at entry=0x6a3c76c0) at 
security/integrity/ima/ima_main.c:180
  #16 0x00000000604e461c in ima_file_free (file=file at entry=0x6a3c76c0) 
at security/integrity/ima/ima_main.c:204
  #17 0x00000000601f3cd8 in __fput (file=0x6a3c76c0) at fs/file_table.c:388
  #18 0x00000000601f40c4 in ____fput (work=<optimized out>) at 
fs/file_table.c:422
  #19 0x000000006007d87c in task_work_run () at kernel/task_work.c:180
  #20 0x000000006002f294 in resume_user_mode_work (regs=<optimized out>) 
at ./include/linux/resume_user_mode.h:49
  #21 interrupt_end () at arch/um/kernel/process.c:108
  #22 0x0000000060049bf8 in userspace (regs=0x632b1360, 
aux_fp_regs=0xe1000020) at arch/um/os-Linux/skas/process.c:499
  #23 0x000000006002ee94 in new_thread_handler () at 
arch/um/kernel/process.c:136
  #24 0x0000000000000000 in ?? ()

This is the stacktrace before failing. It should be clear now what is 
happening. vfs_setxattr() (frame #3) calls security_inode_setxattr() 
(frame #1), which calls evm_inode_setxattr() (frame #0).

Again, the final result is that the written file has a security.evm set 
by the upper filesystem with the HMAC calculated on the upper inode 
metadata (setting security.evm from overlayfs failed).

So, next time we try to read the file and EVM attempts to verify inode 
metadata (frame #5), we have:

  Breakpoint 5, vfs_getxattr (idmap=0x60ea0250 <nop_mnt_idmap>, 
dentry=0x6b6b6ba0, name=name at entry=0x60b39c34 "security.evm", 
value=value at entry=0x0, size=size at entry=0) at fs/xattr.c:431
  431	{
  (gdb) bt
  #0  vfs_getxattr (idmap=0x60ea0250 <nop_mnt_idmap>, dentry=0x6b6b6ba0, 
name=name at entry=0x60b39c34 "security.evm", value=value at entry=0x0, 
size=size at entry=0) at fs/xattr.c:431
  #1  0x00000000603a479a in ovl_xattr_get (size=0, value=0x0, 
name=0x60b39c34 "security.evm", inode=<optimized out>, dentry=<optimized 
out>) at ./include/linux/mount.h:80
  #2  ovl_other_xattr_get (handler=<optimized out>, dentry=<optimized 
out>, inode=<optimized out>, name=0x60b39c34 "security.evm", buffer=0x0, 
size=0) at fs/overlayfs/xattrs.c:224
  #3  0x00000000602329f3 in vfs_getxattr_alloc (idmap=<optimized out>, 
dentry=dentry at entry=0x6b6b7dd8, name=<optimized out>, 
name at entry=0x60b39c34 "security.evm", 
xattr_value=xattr_value at entry=0xe1003858, xattr_size=xattr_size at entry=0, 
flags=flags at entry=3136) at fs/xattr.c:394
  #4  0x00000000604ef2d0 in evm_verify_hmac 
(dentry=dentry at entry=0x6b6b7dd8, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima",
      xattr_value=xattr_value at entry=0x653a7840 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302", 
<incomplete sequence \322>, xattr_value_len=xattr_value_len at entry=34, 
iint=iint at entry=0x651d2008) at security/integrity/evm/evm_main.c:187
  #5  0x00000000604ef77a in evm_verifyxattr 
(dentry=dentry at entry=0x6b6b7dd8, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima", xattr_value=xattr_value at entry=0x653a7840, 
xattr_value_len=xattr_value_len at entry=34, iint=iint at entry=0x651d2008)
      at security/integrity/evm/evm_main.c:416
  #6  0x00000000604ee3f5 in ima_appraise_measurement 
(func=func at entry=FILE_CHECK, iint=iint at entry=0x651d2008, 
file=file at entry=0x6a3c6cc0, filename=<optimized out>, 
xattr_value=0x653a7840, xattr_len=xattr_len at entry=34, modsig=0x0) at 
security/integrity/ima/ima_appraise.c:522
  #7  0x00000000604e410e in process_measurement 
(file=file at entry=0x6a3c6cc0, cred=<optimized out>, secid=secid at entry=1, 
buf=buf at entry=0x0, size=size at entry=0, mask=mask at entry=10, 
func=<optimized out>) at security/integrity/ima/ima_main.c:374
  #8  0x00000000604e458d in ima_file_check (file=file at entry=0x6a3c6cc0, 
mask=<optimized out>) at security/integrity/ima/ima_main.c:557
  #9  0x00000000602050ba in do_open (nd=nd at entry=0xe1003c90, 
file=file at entry=0x6a3c6cc0, op=op at entry=0xe1003dd0) at fs/namei.c:3624
  #10 0x000000006020b0e5 in path_openat (nd=nd at entry=0xe1003c90, 
op=op at entry=0xe1003dd0, flags=flags at entry=65) at fs/namei.c:3779
  #11 0x000000006020be8a in do_filp_open (dfd=dfd at entry=-100, 
pathname=pathname at entry=0x63321100, op=op at entry=0xe1003dd0) at 
fs/namei.c:3809
  #12 0x00000000601eea16 in do_sys_openat2 (dfd=-100, 
filename=<optimized out>, how=how at entry=0xe1003e20) at fs/open.c:1440
  #13 0x00000000601eed8e in do_sys_open (mode=<optimized out>, 
flags=<optimized out>, filename=<optimized out>, dfd=<optimized out>) at 
fs/open.c:1455
  #14 __do_sys_openat (mode=<optimized out>, flags=<optimized out>, 
filename=<optimized out>, dfd=<optimized out>) at fs/open.c:1471
  #15 __se_sys_openat (dfd=<optimized out>, filename=<optimized out>, 
flags=<optimized out>, mode=<optimized out>) at fs/open.c:1466
  #16 0x0000000060032da0 in handle_syscall (r=r at entry=0x632b1360) at 
arch/um/kernel/skas/syscall.c:45
  #17 0x00000000600494a9 in handle_trap (pid=pid at entry=2974892, 
regs=regs at entry=0x632b1360, 
local_using_sysemu=local_using_sysemu at entry=2) at 
arch/um/os-Linux/skas/process.c:222
  #18 0x0000000060049bdf in userspace (regs=0x632b1360, 
aux_fp_regs=0xe1000020) at arch/um/os-Linux/skas/process.c:477
  #19 0x000000006002ee94 in new_thread_handler () at 
arch/um/kernel/process.c:136
  #20 0x0000000000000000 in ?? ()

Overlayfs is getting security.evm from the upper filesystem (frame #2), 
but that HMAC was calculated with the upper inode metadata, so when EVM 
tries to calculate the HMAC on the overlayfs inode metadata, it fails:

  #0  evm_calc_hmac_or_hash (dentry=dentry at entry=0x6b6b7dd8, 
req_xattr_name=req_xattr_name at entry=0x60b39cf0 "security.ima",
      req_xattr_value=req_xattr_value at entry=0x653a7840 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302", 
<incomplete sequence \322>, 
req_xattr_value_len=req_xattr_value_len at entry=34, type=type at entry=2 '\002',
      data=data at entry=0xe1003860) at security/integrity/evm/evm_crypto.c:225
  #1  0x00000000604f0cad in evm_calc_hmac 
(dentry=dentry at entry=0x6b6b7dd8, 
req_xattr_name=req_xattr_name at entry=0x60b39cf0 "security.ima",
      req_xattr_value=req_xattr_value at entry=0x653a7840 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302", 
<incomplete sequence \322>, 
req_xattr_value_len=req_xattr_value_len at entry=34, 
data=data at entry=0xe1003860)
      at security/integrity/evm/evm_crypto.c:310
  #2  0x00000000604ef40e in evm_verify_hmac 
(dentry=dentry at entry=0x6b6b7dd8, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima",
      xattr_value=xattr_value at entry=0x653a7840 
"\004\004\362\312\033\266\307\351\a\320m\257\344h~W\237\316v\263~N\223\267`P\"\332R\346\314\302", 
<incomplete sequence \322>, xattr_value_len=xattr_value_len at entry=34, 
iint=iint at entry=0x651d2008) at security/integrity/evm/evm_main.c:214
  #3  0x00000000604ef77a in evm_verifyxattr 
(dentry=dentry at entry=0x6b6b7dd8, xattr_name=xattr_name at entry=0x60b39cf0 
"security.ima", xattr_value=xattr_value at entry=0x653a7840, 
xattr_value_len=xattr_value_len at entry=34, iint=iint at entry=0x651d2008)
      at security/integrity/evm/evm_main.c:416
  #4  0x00000000604ee3f5 in ima_appraise_measurement 
(func=func at entry=FILE_CHECK, iint=iint at entry=0x651d2008, 
file=file at entry=0x6a3c6cc0, filename=<optimized out>, 
xattr_value=0x653a7840, xattr_len=xattr_len at entry=34, modsig=0x0) at 
security/integrity/ima/ima_appraise.c:522
  #5  0x00000000604e410e in process_measurement 
(file=file at entry=0x6a3c6cc0, cred=<optimized out>, secid=secid at entry=1, 
buf=buf at entry=0x0, size=size at entry=0, mask=mask at entry=10, 
func=<optimized out>) at security/integrity/ima/ima_main.c:374
  #6  0x00000000604e458d in ima_file_check (file=file at entry=0x6a3c6cc0, 
mask=<optimized out>) at security/integrity/ima/ima_main.c:557
  #7  0x00000000602050ba in do_open (nd=nd at entry=0xe1003c90, 
file=file at entry=0x6a3c6cc0, op=op at entry=0xe1003dd0) at fs/namei.c:3624
  #8  0x000000006020b0e5 in path_openat (nd=nd at entry=0xe1003c90, 
op=op at entry=0xe1003dd0, flags=flags at entry=65) at fs/namei.c:3779
  #9  0x000000006020be8a in do_filp_open (dfd=dfd at entry=-100, 
pathname=pathname at entry=0x63321100, op=op at entry=0xe1003dd0) at 
fs/namei.c:3809
  #10 0x00000000601eea16 in do_sys_openat2 (dfd=-100, 
filename=<optimized out>, how=how at entry=0xe1003e20) at fs/open.c:1440
  #11 0x00000000601eed8e in do_sys_open (mode=<optimized out>, 
flags=<optimized out>, filename=<optimized out>, dfd=<optimized out>) at 
fs/open.c:1455
  #12 __do_sys_openat (mode=<optimized out>, flags=<optimized out>, 
filename=<optimized out>, dfd=<optimized out>) at fs/open.c:1471
  #13 __se_sys_openat (dfd=<optimized out>, filename=<optimized out>, 
flags=<optimized out>, mode=<optimized out>) at fs/open.c:1466
  #14 0x0000000060032da0 in handle_syscall (r=r at entry=0x632b1360) at 
arch/um/kernel/skas/syscall.c:45
  #15 0x00000000600494a9 in handle_trap (pid=pid at entry=2974892, 
regs=regs at entry=0x632b1360, 
local_using_sysemu=local_using_sysemu at entry=2) at 
arch/um/os-Linux/skas/process.c:222
  #16 0x0000000060049bdf in userspace (regs=0x632b1360, 
aux_fp_regs=0xe1000020) at arch/um/os-Linux/skas/process.c:477
  #17 0x000000006002ee94 in new_thread_handler () at 
arch/um/kernel/process.c:136
  #18 0x0000000000000000 in ?? ()


  275			iint->evm_status = evm_status;
  (gdb) p evm_status
  $4 = INTEGRITY_FAIL

>>
>> Remapping security.evm to security.evm_overlayfs (now
>> trusted.overlay.evm) allows us to store both HMACs separately and to
>> know which one to use.
>>
>> I just realized that the new xattr name should be public, because EVM
>> rejects HMAC updates, so we should reject HMAC updates based on the new
>> xattr name too.
> 
> I won't support any of this going in unless there's a comprehensive
> description of where this is all supposed to go and there's a
> comprehensive and coherent story of what EVM and IMA want to achieve for
> overlayfs or stacking filesystems in general. The past months we've seen
> a bunch of ductape to taper over this pretty basic question and there's
> no end in sight apparently.
> 
> Really, we need a comprehensive solution for both IMA and EVM it seems.
> And before that is solved we'll not be merging anything of this sort and
> won't make any impactful uapi changes such as exposing a new security.*
> xattr.

Fair enough, I'm going to answer to Amir about if we need EVM for 
overlayfs...

Roberto




More information about the Linux-security-module-archive mailing list