Add support for prlimit(RLIMIT_NOFILE) to trace procfs.

Updates #4805

PiperOrigin-RevId: 451029238
This commit is contained in:
Ayush Ranjan
2022-05-25 15:30:14 -07:00
committed by gVisor bot
parent 006bbe78ca
commit a3892a07b5
5 changed files with 36 additions and 2 deletions
+2 -2
View File
@@ -51,9 +51,9 @@ const Infinity = ^uint64(0)
// +stateify savable
type Limit struct {
// Cur specifies the current limit.
Cur uint64
Cur uint64 `json:"cur,omitempty"`
// Max specifies the maximum settable limit.
Max uint64
Max uint64 `json:"max,omitempty"`
}
// LimitSet represents the Limits that correspond to each LimitType.
+1
View File
@@ -11,6 +11,7 @@ go_library(
"//pkg/log",
"//pkg/sentry/fsimpl/proc",
"//pkg/sentry/kernel",
"//pkg/sentry/limits",
"//pkg/sentry/mm",
"//pkg/sentry/vfs",
],
+19
View File
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/proc"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/sentry/vfs"
)
@@ -57,6 +58,9 @@ type ProcessProcfsDump struct {
StartTime int64 `json:"clone_ts,omitempty"`
// Root is /proc/[pid]/root.
Root string `json:"root,omitempty"`
// Limits constains resource limits for this process. Currently only
// RLIMIT_NOFILE is supported.
Limits map[string]limits.Limit `json:"limits,omitempty"`
}
// getMM returns t's MemoryManager. On success, the MemoryManager's users count
@@ -170,6 +174,13 @@ func getRoot(t *kernel.Task, pid kernel.ThreadID) string {
return path
}
func getFDLimit(ctx context.Context, pid kernel.ThreadID) (limits.Limit, error) {
if limitSet := limits.FromContext(ctx); limitSet != nil {
return limitSet.Get(limits.NumberOfFiles), nil
}
return limits.Limit{}, fmt.Errorf("could not find limit set for pid %s", pid)
}
// Dump returns a procfs dump for process pid. t must be a task in process pid.
func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
ctx := t.AsyncContext()
@@ -180,6 +191,11 @@ func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
}
defer mm.DecUsers(ctx)
fdLimit, err := getFDLimit(ctx, pid)
if err != nil {
return ProcessProcfsDump{}, err
}
return ProcessProcfsDump{
PID: int32(pid),
Exe: getExecutablePath(ctx, pid, mm),
@@ -189,5 +205,8 @@ func Dump(t *kernel.Task, pid kernel.ThreadID) (ProcessProcfsDump, error) {
FDs: getFDs(ctx, t, pid),
StartTime: t.StartTime().Nanoseconds(),
Root: getRoot(t, pid),
Limits: map[string]limits.Limit{
"RLIMIT_NOFILE": fdLimit,
},
}, nil
}
+1
View File
@@ -70,6 +70,7 @@ go_test(
"//pkg/sentry/control",
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/limits",
"//pkg/sentry/platform",
"//pkg/sentry/seccheck",
"//pkg/sentry/seccheck/checkers/remote/test",
+13
View File
@@ -21,7 +21,9 @@ import (
"testing"
"time"
specs "github.com/opencontainers/runtime-spec/specs-go"
"google.golang.org/protobuf/proto"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/seccheck"
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/test"
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
@@ -295,6 +297,13 @@ func TestProcfsDump(t *testing.T) {
testEnv := "GVISOR_IS_GREAT=true"
spec.Process.Env = append(spec.Process.Env, testEnv)
spec.Process.Cwd = "/"
fdLimit := limits.Limit{
Cur: 10_000,
Max: 100_000,
}
spec.Process.Rlimits = []specs.POSIXRlimit{
{Type: "RLIMIT_NOFILE", Hard: fdLimit.Max, Soft: fdLimit.Cur},
}
_, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf)
if err != nil {
t.Fatalf("error setting up container: %v", err)
@@ -383,4 +392,8 @@ func TestProcfsDump(t *testing.T) {
if want := "/"; procfsDump[0].Root != "/" {
t.Errorf("expected root to be %q, but got %q", want, procfsDump[0].Root)
}
if got := procfsDump[0].Limits["RLIMIT_NOFILE"]; got != fdLimit {
t.Errorf("expected FD limit to be %+v, but got %+v", fdLimit, got)
}
}