public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Process killed by seccomp looks live by tracer
@ 2026-03-04 10:51 Max Ver
  2026-03-04 18:05 ` Kees Cook
  0 siblings, 1 reply; 8+ messages in thread
From: Max Ver @ 2026-03-04 10:51 UTC (permalink / raw)
  To: linux-kernel, bpf; +Cc: Kees Cook, Andy Lutomirski, Will Drewry, Oleg Nesterov

I was using ptrace to trace a tracee status, using
`PTRACE_GET_SYSCALL_INFO` and `PTRACE_SYSCALL`
to get its syscall arguments and results. When a tracee killed by its
seccomp, the tracer can't know immediately,
instead, the `PTRACE_GET_SYSCALL_INFO` tell tracer that tracee exit
with no error. The syscall wasn't actually
executed, it was captured by seccomp, even the tracee was killed by seccomp.

Here is a poc explaining what I said.
I was expecting to aware the death of tracee at the fourth
`PTRACE_GET_SYSCALL_INFO`,
at least `PTRACE_GET_SYSCALL_INFO` should tell that the syscall
failed, or get some different message from waitpid.
But the result are below. Tracer can only get the death of tracee at
the fifth loop.

---
Start tracing child
entry
exit ok
entry
exit ok
get_syscall_info: No such process
---
// poc file
#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <string.h>
#include <sys/ptrace.h>
#include <linux/ptrace.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <threads.h>
#include <unistd.h>

void
child ()
{
  if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
    {
      perror ("prctl");
      exit (1);
    }
  ptrace (PTRACE_TRACEME, 0, 0, 0);
  raise (SIGSTOP);

  struct sock_filter filter[] = {
    BPF_STMT (BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
  };

  struct sock_fprog prog = {
    .len = 1,
    .filter = filter,
  };

  if (syscall (SYS_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog))
    {
      perror ("seccomp");
      exit (1);
    }
  write (1, "a", 1);
}

void
get_child_info (pid_t pid)
{
  int status;

  struct ptrace_syscall_info info;
  memset (&info, 0, sizeof (info));
  ptrace (PTRACE_SYSCALL, pid, 0, 0);
  if ((waitpid (pid, &status, 0) == -1) || WIFEXITED (status))
    {
      puts ("child exit");
      exit (1);
    }
  if (ptrace (PTRACE_GET_SYSCALL_INFO, pid,
              sizeof (struct ptrace_syscall_info), &info)
      == -1)
    {
      perror ("get_syscall_info");
      exit (1);
    }

  if (info.op == PTRACE_SYSCALL_INFO_ENTRY)
    puts ("entry");
  else if (info.op == PTRACE_SYSCALL_INFO_EXIT)
    puts (info.exit.is_error ? "exit with err" : "exit ok");
  else if (info.op == PTRACE_SYSCALL_INFO_NONE)
    puts ("none");
  else if (info.op == PTRACE_SYSCALL_INFO_SECCOMP)
    puts ("seccomp");
  else
    printf ("%d\n", info.op);
}

void
parent (pid_t pid)
{
  int status;
  waitpid (pid, &status, 0);
  puts ("Start tracing child");

  if (ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == -1)
    exit (1);
  while (1)
    get_child_info (pid);
}

int
main ()
{
  pid_t pid = fork ();
  if (pid == 0)
    child ();
  else
    parent (pid);
}

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-03-22 13:40 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-04 10:51 Process killed by seccomp looks live by tracer Max Ver
2026-03-04 18:05 ` Kees Cook
2026-03-05  2:00   ` Max Ver
2026-03-05 14:49     ` Oleg Nesterov
2026-03-05 17:45       ` Oleg Nesterov
2026-03-06  2:55         ` Max Ver
2026-03-08 13:08           ` Oleg Nesterov
2026-03-22 13:40             ` Oleg Nesterov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox