diff --git a/pkg/sentry/kernel/sessions.go b/pkg/sentry/kernel/sessions.go index 72e1cbf49..abc3fec46 100644 --- a/pkg/sentry/kernel/sessions.go +++ b/pkg/sentry/kernel/sessions.go @@ -256,7 +256,7 @@ func (pg *ProcessGroup) SendSignal(info *linux.SignalInfo) error { // // EPERM may be returned if either the given ThreadGroup is already a Session // leader, or a ProcessGroup already exists for the ThreadGroup's ID. -func (tg *ThreadGroup) CreateSession() error { +func (tg *ThreadGroup) CreateSession() (SessionID, error) { tg.pidns.owner.mu.Lock() defer tg.pidns.owner.mu.Unlock() tg.signalHandlers.mu.Lock() @@ -267,7 +267,7 @@ func (tg *ThreadGroup) CreateSession() error { // createSession creates a new session for a threadgroup. // // Precondition: callers must hold TaskSet.mu and the signal mutex for writing. -func (tg *ThreadGroup) createSession() error { +func (tg *ThreadGroup) createSession() (SessionID, error) { // Get the ID for this thread in the current namespace. id := tg.pidns.tgids[tg] @@ -278,21 +278,22 @@ func (tg *ThreadGroup) createSession() error { continue } if s.leader == tg { - return linuxerr.EPERM + return -1, linuxerr.EPERM } if s.id == SessionID(id) { - return linuxerr.EPERM + return -1, linuxerr.EPERM } for pg := s.processGroups.Front(); pg != nil; pg = pg.Next() { if pg.id == ProcessGroupID(id) { - return linuxerr.EPERM + return -1, linuxerr.EPERM } } } // Create a new Session, with a single reference. + sid := SessionID(id) s := &Session{ - id: SessionID(id), + id: sid, leader: tg, } s.InitRefs() @@ -356,7 +357,7 @@ func (tg *ThreadGroup) createSession() error { // Disconnect from the controlling terminal. tg.tty = nil - return nil + return sid, nil } // CreateProcessGroup creates a new process group. diff --git a/pkg/sentry/syscalls/linux/sys_thread.go b/pkg/sentry/syscalls/linux/sys_thread.go index 6aa73290c..a523b38b0 100644 --- a/pkg/sentry/syscalls/linux/sys_thread.go +++ b/pkg/sentry/syscalls/linux/sys_thread.go @@ -670,7 +670,11 @@ func Getpgid(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr // Setsid implements the linux syscall setsid(2). func Setsid(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { - return 0, nil, t.ThreadGroup().CreateSession() + sid, err := t.ThreadGroup().CreateSession() + if err != nil { + return 0, nil, err + } + return uintptr(sid), nil, nil } // Getsid implements the linux syscall getsid(2). diff --git a/test/syscalls/linux/pty.cc b/test/syscalls/linux/pty.cc index b7e8494c4..a94b557c2 100644 --- a/test/syscalls/linux/pty.cc +++ b/test/syscalls/linux/pty.cc @@ -1915,6 +1915,16 @@ TEST_F(JobControlTest, SetForegroundProcessGroupDifferentSession) { ASSERT_NO_ERRNO(ret); } +TEST_F(JobControlTest, SetGetSession) { + auto res = RunInChild([=]() { + pid_t sid = setsid(); + TEST_PCHECK(sid >= 0); + TEST_PCHECK(getsid(0) == sid); + TEST_PCHECK(getpid() == sid); + }); + ASSERT_NO_ERRNO(res); +} + // Verify that we don't hang when creating a new session from an orphaned // process group (b/139968068). Calling setsid() creates an orphaned process // group, as process groups that contain the session's leading process are