Skip to content

setpgid() lets a session leader join another process group #15566

Description

@dany74q

A session leader can join another process group of its session with setpgid(), where Linux returns EPERM (JoinProcessGroup in pkg/sentry/kernel/sessions.go has no session leader check). After the move its process group has another leader, so pidfd_send_signal() with PIDFD_SIGNAL_PROCESS_GROUP on its pidfd fails with EINVAL.

Reproducer
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void) {
  pid_t leader = fork();
  if (leader == 0) {
    setsid();
    pid_t child = fork();
    if (child == 0) {
      pause();
      _exit(0);
    }
    setpgid(child, child);
    int ret = setpgid(0, child);
    printf("setpgid(0, child) = %d (%s)\n", ret, ret == 0 ? "ok" : strerror(errno));
    printf("leader pgid == sid: %s\n", getpgid(0) == getsid(0) ? "yes" : "no");
    kill(child, SIGKILL);
    return 0;
  }
  waitpid(leader, NULL, 0);
  return 0;
}

Linux prints setpgid(0, child) = -1 (Operation not permitted). runsc prints setpgid(0, child) = 0 (ok).

Proposed fix in #15567.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions