Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASAN and TSAN introduce unwanted shell execution in posix_spawn on glibc Linux #59326

Open
ridiculousfish opened this issue Dec 3, 2022 · 1 comment
Labels

Comments

@ridiculousfish
Copy link
Contributor

ridiculousfish commented Dec 3, 2022

When using posix_spawn under ASAN or TSAN, files that fail to execute will be retried as scripts using /bin/sh, on glibc Linux. The expected behavior is that posix_spawn fails with ENOEXEC.

posix_spawn in glibc used to have a feature such that, if the child-side exec call fails with ENOEXEC, it would "retry" by passing the argument to /bin/sh. This feature was removed as default in 2011 (see here), now requiring the explicit flag SPAWN_XFLAGS_TRY_SHELL. However both ASAN and TSAN somehow set that flag, causing this unwanted /bin/sh execution.

The most likely reason is that the interceptor is calling the compatibility version of posix_spawn instead of the modern one.

To reproduce, on GNU Linux (I used Ubuntu Jammy):

  1. Create a "shebangless script":

     echo 'echo I should not run' > ./file
     chmod a+x ./file
    
  2. Compile and run the following C code as clang spawn.c:

     #include <spawn.h>
     #include <stdio.h>
     #include <errno.h>
    
     extern char **environ;
    
     int main(int argc, char *argv[]) {
       pid_t pid = 0;
       char arg[] = "./file";
       char *const args[] = {arg, NULL};
       int ret = posix_spawn(&pid, arg, NULL, NULL, args, environ);
       if (ret == 0) {
             printf("Got pid: %d\n", pid);
       } else {
             perror("posix_spawn");
       }
       return 0;
     }
    

This prints posix_spawn: Exec format error as expected, as the script does not have a shebang.

Now retry with ASAN: clang -fsanitize=address spawn.c, and the script will run. It should not run.

I bisected this to e124074, and confirmed the bug is still present on main (059a23c).

@krobelus
Copy link
Member

krobelus commented Dec 3, 2022

The most likely reason is that the interceptor is calling the compatibility version of posix_spawn instead of the modern one.

ad294e5 ([sanitizers] Fix interception of GLibc regexec, 2021-03-08) fixed a similar issue.
Probably we need to request a posix_spawn from glibc>=2.15 since that's the lower bound of the non-compat version.

@EugeneZelenko EugeneZelenko added compiler-rt:asan Address sanitizer compiler-rt:tsan Thread sanitizer platform:linux and removed new issue labels Dec 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants