use new SYS_faccessat2 syscall to implement faccessat with flags
authorRich Felker <dalias@aerifal.cx>
Thu, 10 Sep 2020 01:55:11 +0000 (21:55 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 10 Sep 2020 01:55:11 +0000 (21:55 -0400)
commit 0a05eace163cee9b08571d2ff9d90f5e82d9c228 implemented AT_EACCESS
for faccessat with a horrible hack, creating a child process to change
switch uid/gid and perform the access probe without making potentially
irreversible changes to the caller's credentials. this was due to the
syscall lacking a flags argument.

linux 5.8 introduced a new syscall, SYS_faccessat2, fixing this
deficiency. use it if any flags are passed, and fallback to the old
strategy on ENOSYS. continue using the old syscall when there are no
flags.

src/unistd/faccessat.c

index 76bbd4c..557503e 100644 (file)
@@ -25,12 +25,17 @@ static int checker(void *p)
 
 int faccessat(int fd, const char *filename, int amode, int flag)
 {
-       if (!flag || (flag==AT_EACCESS && getuid()==geteuid() && getgid()==getegid()))
-               return syscall(SYS_faccessat, fd, filename, amode, flag);
+       if (flag) {
+               int ret = __syscall(SYS_faccessat2, fd, filename, amode, flag);
+               if (ret != -ENOSYS) return __syscall_ret(ret);
+       }
 
-       if (flag != AT_EACCESS)
+       if (flag & ~AT_EACCESS)
                return __syscall_ret(-EINVAL);
 
+       if (!flag || (getuid()==geteuid() && getgid()==getegid()))
+               return syscall(SYS_faccessat, fd, filename, amode);
+
        char stack[1024];
        sigset_t set;
        pid_t pid;