Skip to content

Implement execve#3162

Merged
sporksmith merged 4 commits intoshadow:mainfrom
sporksmith:execve2
Sep 25, 2023
Merged

Implement execve#3162
sporksmith merged 4 commits intoshadow:mainfrom
sporksmith:execve2

Conversation

@sporksmith
Copy link
Copy Markdown
Contributor

@sporksmith sporksmith commented Sep 20, 2023

Fixes #2988 (split execveat into #3166)

@sporksmith sporksmith self-assigned this Sep 20, 2023
@github-actions github-actions bot added Component: Libraries Support functions like LD_PRELOAD and logging Component: Testing Unit and integration tests and frameworks Component: Main Composing the core Shadow executable Component: Build Build/install tools and dependencies labels Sep 20, 2023
@github-actions github-actions bot removed the Component: Build Build/install tools and dependencies label Sep 21, 2023
@sporksmith sporksmith changed the title Execve2 Implement execve Sep 21, 2023
@sporksmith sporksmith force-pushed the execve2 branch 2 times, most recently from e32261b to e48e11a Compare September 21, 2023 23:37
@sporksmith
Copy link
Copy Markdown
Contributor Author

sporksmith commented Sep 23, 2023

It occurred to me how to test whether pending signals are cleared during exec, so I did. Turns out they're not. Will add a fixup commit on Monday.

Here's the test program:

#define _GNU_SOURCE

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv) {
  printf("beginning of main\n");

  // create a sigset with just SIGINT.
  sigset_t sigint;
  sigemptyset(&sigint);
  sigaddset(&sigint, SIGINT);

  // unblock signal. if it's (still) pending, it should kill the process.
  sigprocmask(SIG_UNBLOCK, &sigint, NULL);

  printf("sig unblocked\n");

  // block it.
  sigprocmask(SIG_BLOCK, &sigint, NULL);
  printf("sig blocked\n");

  // raise it. The signal is blocked, so this will set the signal pending, but
  // not deliver it yet.
  raise(SIGINT);
  printf("sig raised\n");

  // re-exec ourselves
  execv(argv[0], argv);

  return 0;
}

If pending signals were cleared, this should loop forever re-execing itself. But it appears they're not, so it doesn't. Output:

$ ./a.out 
beginning of main
sig unblocked
sig blocked
sig raised
beginning of main

@github-actions github-actions bot added the Component: Build Build/install tools and dependencies label Sep 25, 2023
Previously when we forked a process, we'd dup the descriptors kept in
the shadow `Process` object into the new `Process`, and put the new
descriptor numbers in shared memory for the shim-side code of the new
managed process to use.

This is incorrect, though, since the dup'd descriptor doesn't exist in
the new native process.

The original descriptors are transferred between shadow and the managed
process when it's first spawn, using `posix_spawn` actions. It's
simplest to just use those in the new process as well, since the forked
process will also inherit them.
@github-actions github-actions bot removed the Component: Build Build/install tools and dependencies label Sep 25, 2023
@sporksmith sporksmith merged commit 540c626 into shadow:main Sep 25, 2023
@sporksmith sporksmith deleted the execve2 branch September 25, 2023 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component: Libraries Support functions like LD_PRELOAD and logging Component: Main Composing the core Shadow executable Component: Testing Unit and integration tests and frameworks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement execve

2 participants