[Xenial][SRU][PATCH 1/1] cap_inode_getsecurity: use d_find_any_alias() instead of d_find_alias()

Po-Hsu Lin po-hsu.lin at canonical.com
Wed Oct 24 06:54:49 UTC 2018

From: "Eddie.Horng" <eddie.horng at mediatek.com>

BugLink: https://bugs.launchpad.net/bugs/1786729

The code in cap_inode_getsecurity(), introduced by commit 8db6c34f1dbc
("Introduce v3 namespaced file capabilities"), should use
d_find_any_alias() instead of d_find_alias() do handle unhashed dentry
correctly. This is needed, for example, if execveat() is called with an
open but unlinked overlayfs file, because overlayfs unhashes dentry on
This is a regression of real life application, first reported at

Below reproducer and setup can reproduce the case.
  const char* exec="echo";
  const char *newargv[] = { "echo", "hello", NULL};
  const char *newenviron[] = { NULL };
  int fd, err;

  fd = open(exec, O_PATH);
  err = syscall(322/*SYS_execveat*/, fd, "", newargv, newenviron,
    fprintf(stderr, "execveat: %s\n", strerror(errno));

gcc compile into ~/test/a.out
mount -t overlay -orw,lowerdir=/mnt/l,upperdir=/mnt/u,workdir=/mnt/w
none /mnt/m
cd /mnt/m
cp /bin/echo .

Expected result:
Actually result:
execveat: Invalid argument
Invalid argument reading file caps for /dev/fd/3

The 2nd reproducer and setup emulates similar case but for
regular filesystem:
  const char* exec="echo";
  int fd, err;
  char buf[256];

  fd = open(exec, O_RDONLY);
  err = fgetxattr(fd, "security.capability", buf, 256);
    fprintf(stderr, "fgetxattr: %s\n", strerror(errno));

gcc compile into ~/test_fgetxattr

cd /tmp
cp /bin/echo .

fgetxattr: Invalid argument

On regular filesystem, for example, ext4 read xattr from
disk and return to execveat(), will not trigger this issue, however,
the overlay attr handler pass real dentry to vfs_getxattr() will.
This reproducer calls fgetxattr() with an unlinked fd, involkes
vfs_getxattr() then reproduced the case that d_find_alias() in
cap_inode_getsecurity() can't find the unlinked dentry.

Suggested-by: Amir Goldstein <amir73il at gmail.com>
Acked-by: Amir Goldstein <amir73il at gmail.com>
Acked-by: Serge E. Hallyn <serge at hallyn.com>
Fixes: 8db6c34f1dbc ("Introduce v3 namespaced file capabilities")
Cc: <stable at vger.kernel.org> # v4.14
Signed-off-by: Eddie Horng <eddie.horng at mediatek.com>
Signed-off-by: Eric W. Biederman <ebiederm at xmission.com>
(backported from commit 355139a8dba446cc11a424cddbf7afebc3041ba1)
Signed-off-by: Po-Hsu Lin <po-hsu.lin at canonical.com>
 security/commoncap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/commoncap.c b/security/commoncap.c
index 814324f..f2b35c7 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -399,7 +399,7 @@ int cap_inode_getsecurity(const struct inode *inode, const char *name,
 	if (strcmp(name, "capability") != 0)
 		return -EOPNOTSUPP;
-	dentry = d_find_alias((struct inode *)inode);
+	dentry = d_find_any_alias((struct inode *)inode);
 	if (!dentry)
 		return -EINVAL;

More information about the kernel-team mailing list