Files
Shailend ChandandgVisor bot 329cdabbf5 Implement pidfds
This patch introduces pidfd support roughly up to Linux 6.8. Linux selftests
at this version pass, and are now run as an //image_test target. Some features,
like PIDFD_THREAD, that occur later than 6.8 in Linux, are included.

It includes:
- These new syscalls:
  - pidfd_open()
  - pidfd_getfd()
  - pidfd_send_signal()
- New aspects to these existing syscalls:
  - waitid() in its support of P_PIDFD
  - clone()/clone3() in their support of CLONE_PIDFD
  - poll()/epoll()/select() in their support for pidfds
  - setns() in its support for pidfds
  - pid introspection via /proc/[pid]/fdinfo/[pidfd]

It excludes:
- pidfdfs: pidfds are backed by the anon inode right now
- ioctls to retrieve namespace fds using a pidfd
- process_madvise()

Updates #5839.

PiperOrigin-RevId: 908341658
2026-04-30 13:22:58 -07:00

119 lines
3.2 KiB
Go

// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kernel
import (
"context"
"gvisor.dev/gvisor/pkg/tcpip"
)
// afterLoad is invoked by stateify.
func (ts *TaskSet) afterLoad(_ context.Context) {
ts.zeroLiveTasksCond.L = &ts.mu
}
// saveDanglingEndpoints is invoked by stateify.
func (k *Kernel) saveDanglingEndpoints() []tcpip.Endpoint {
return tcpip.GetDanglingEndpoints()
}
// loadDanglingEndpoints is invoked by stateify.
func (k *Kernel) loadDanglingEndpoints(_ context.Context, es []tcpip.Endpoint) {
for _, e := range es {
tcpip.AddDanglingEndpoint(e)
}
}
// saveVforkParent is invoked by stateify.
func (t *Task) saveVforkParent() *Task {
return t.vforkParent.Load()
}
// loadVforkParent is invoked by stateify.
func (t *Task) loadVforkParent(_ context.Context, vforkParent *Task) {
t.vforkParent.Store(vforkParent)
}
// savePtraceTracer is invoked by stateify.
func (t *Task) savePtraceTracer() *Task {
return t.ptraceTracer.Load()
}
// loadPtraceTracer is invoked by stateify.
func (t *Task) loadPtraceTracer(_ context.Context, tracer *Task) {
t.ptraceTracer.Store(tracer)
}
// saveSeccomp is invoked by stateify.
func (t *Task) saveSeccomp() *taskSeccomp {
return t.seccomp.Load()
}
// loadSeccomp is invoked by stateify.
func (t *Task) loadSeccomp(_ context.Context, seccompData *taskSeccomp) {
t.seccomp.Store(seccompData)
}
// saveFsContext is invoked by stateify.
func (t *Task) saveFsContext() *FSContext {
return t.fsContext.Load()
}
// loadFsContext is invoked by stateify.
func (t *Task) loadFsContext(_ context.Context, fsContext *FSContext) {
t.fsContext.Store(fsContext)
}
// saveAppCPUClockLast is invoked by stateify.
func (tg *ThreadGroup) saveAppCPUClockLast() *Task {
return tg.appCPUClockLast.Load()
}
// loadAppCPUClockLast is invoked by stateify.
func (tg *ThreadGroup) loadAppCPUClockLast(_ context.Context, task *Task) {
tg.appCPUClockLast.Store(task)
}
// saveAppSysCPUClockLast is invoked by stateify.
func (tg *ThreadGroup) saveAppSysCPUClockLast() *Task {
return tg.appSysCPUClockLast.Load()
}
// loadAppSysCPUClockLast is invoked by stateify.
func (tg *ThreadGroup) loadAppSysCPUClockLast(_ context.Context, task *Task) {
tg.appSysCPUClockLast.Store(task)
}
// saveOldRSeqCritical is invoked by stateify.
func (tg *ThreadGroup) saveOldRSeqCritical() *OldRSeqCriticalRegion {
return tg.oldRSeqCritical.Load()
}
// loadOldRSeqCritical is invoked by stateify.
func (tg *ThreadGroup) loadOldRSeqCritical(_ context.Context, r *OldRSeqCriticalRegion) {
tg.oldRSeqCritical.Store(r)
}
// saveT is invoked by stateify.
func (p *pid) saveT() *Task {
return p.t.Load()
}
// loadT is invoked by stateify.
func (p *pid) loadT(_ context.Context, t *Task) {
p.t.Store(t)
}