Skip to content

Commit

Permalink
Do not crash when creating thread group with already-exceeded soft CP…
Browse files Browse the repository at this point in the history
…U limit.

Reported-by: [email protected]
PiperOrigin-RevId: 699425946
  • Loading branch information
EtiennePerot authored and gvisor-bot committed Nov 23, 2024
1 parent d118c2b commit 2b55090
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
13 changes: 12 additions & 1 deletion pkg/sentry/kernel/task_start.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,17 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
}
}

// If the task was the first to be added to the thread group, check if
// it needs to be notified of CPU limits being exceeded.
// We use a defer here because we need to do this without holding the
// TaskSet or signalHandlers lock.
var isFirstTask bool
defer func() {
if isFirstTask {
tg.notifyRlimitCPUUpdated(t)
}
}()

// Make the new task (and possibly thread group) visible to the rest of
// the system atomically.
ts.mu.Lock()
Expand Down Expand Up @@ -259,7 +270,7 @@ func (ts *TaskSet) newTask(ctx context.Context, cfg *TaskConfig) (*Task, error)
t.EnterInitialCgroups(srcT, cfg.InitialCgroups)
committed = true

if tg.leader == nil {
if isFirstTask = tg.leader == nil; isFirstTask {
// New thread group.
tg.leader = t
if parentPG := tg.parentPG(); parentPG == nil {
Expand Down
1 change: 0 additions & 1 deletion pkg/sentry/kernel/thread_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ func (k *Kernel) NewThreadGroup(pidns *PIDNamespace, sh *SignalHandlers, termina
tg.rlimitCPUSoftListener.tg = tg
tg.rlimitCPUHardTimer.Init(&tg.appSysCPUClock, &tg.rlimitCPUHardListener)
tg.rlimitCPUHardListener.tg = tg
tg.notifyRlimitCPUUpdated(nil)
tg.oldRSeqCritical.Store(&OldRSeqCriticalRegion{})
return tg
}
Expand Down
13 changes: 8 additions & 5 deletions test/syscalls/linux/timers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,18 @@ TEST(TimerTest, RlimitCpuInheritedAcrossFork) {
sigemptyset(&new_action.sa_mask);
TEST_PCHECK(sigaction(SIGXCPU, &new_action, nullptr) == 0);

// Set both soft and hard limits to expire a short time from now. (Since we
// may not be able to raise RLIMIT_CPU again, this must happen in a
// disposable child of the test process.)
constexpr int kDelaySeconds = 2;
struct timespec ts;
TEST_PCHECK(clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == 0);
struct rlimit cpu_limits;
// Set soft limit to 0 to expire immediately. This should cause
// a SIGXCPU to be sent to the grandchild immediately on fork.
cpu_limits.rlim_cur = 0;
// Set hard limit to expire a short time from now. (Since we
// may not be able to raise RLIMIT_CPU again, this must happen in a
// disposable child of the test process.)
// +1 to round up, presuming that ts.tv_nsec > 0.
cpu_limits.rlim_cur = cpu_limits.rlim_max = ts.tv_sec + kDelaySeconds + 1;
cpu_limits.rlim_max = ts.tv_sec + kDelaySeconds + 1;
TEST_PCHECK(setrlimit(RLIMIT_CPU, &cpu_limits) == 0);
MaybeSave();

Expand All @@ -271,7 +274,7 @@ TEST(TimerTest, RlimitCpuInheritedAcrossFork) {
// block in waitid().
// TODO: b/315388929 - remove this
if (x % 16384 == 0) {
TEST_PCHECK(ppoll(&pfd, 1, &timeout, nullptr) == 0);
TEST_PCHECK(RetryEINTR(ppoll)(&pfd, 1, &timeout, nullptr) == 0);
}
}
}
Expand Down

0 comments on commit 2b55090

Please sign in to comment.