summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2018-09-27 15:00:03 -0700
committerShentubot <shentubot@google.com>2018-09-27 15:00:58 -0700
commit491faac03b2815ca1bc9b5425c1b3f6291468e20 (patch)
tree0a8f0c1ad99c3d8660f36802132ecd9386c54518 /pkg
parent68ac2ad1e1f16e65d9d1318d6827edf8487578d0 (diff)
Implement 'runsc kill --all'
In order to implement kill --all correctly, the Sentry needs to track all tasks that belong to a given container. This change introduces ContainerID to the task, that gets inherited by all children. 'kill --all' then iterates over all tasks comparing the ContainerID field to find all processes that need to be signalled. PiperOrigin-RevId: 214841768 Change-Id: I693b2374be8692d88cc441ef13a0ae34abf73ac6
Diffstat (limited to 'pkg')
-rw-r--r--pkg/sentry/control/proc.go14
-rw-r--r--pkg/sentry/kernel/kernel.go25
-rw-r--r--pkg/sentry/kernel/task.go12
-rw-r--r--pkg/sentry/kernel/task_clone.go1
-rw-r--r--pkg/sentry/kernel/task_start.go4
5 files changed, 53 insertions, 3 deletions
diff --git a/pkg/sentry/control/proc.go b/pkg/sentry/control/proc.go
index b120471cb..106055e86 100644
--- a/pkg/sentry/control/proc.go
+++ b/pkg/sentry/control/proc.go
@@ -83,6 +83,9 @@ type ExecArgs struct {
// FilePayload determines the files to give to the new process.
urpc.FilePayload
+
+ // ContainerID is the container for the process being executed.
+ ContainerID string
}
// Exec runs a new task.
@@ -133,6 +136,7 @@ func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadI
UTSNamespace: proc.Kernel.RootUTSNamespace(),
IPCNamespace: proc.Kernel.RootIPCNamespace(),
AbstractSocketNamespace: proc.Kernel.RootAbstractSocketNamespace(),
+ ContainerID: args.ContainerID,
}
if initArgs.Root != nil {
// initArgs must hold a reference on Root. This ref is dropped
@@ -182,7 +186,7 @@ type PsArgs struct {
// Ps provides a process listing for the running kernel.
func (proc *Proc) Ps(args *PsArgs, out *string) error {
var p []*Process
- if e := Processes(proc.Kernel, &p); e != nil {
+ if e := Processes(proc.Kernel, "", &p); e != nil {
return e
}
if !args.JSON {
@@ -258,8 +262,9 @@ func PrintPIDsJSON(pl []*Process) (string, error) {
return string(b), nil
}
-// Processes retrieves information about processes running in the sandbox.
-func Processes(k *kernel.Kernel, out *[]*Process) error {
+// Processes retrieves information about processes running in the sandbox with
+// the given container id. All processes are returned if 'containerID' is empty.
+func Processes(k *kernel.Kernel, containerID string, out *[]*Process) error {
ts := k.TaskSet()
now := k.RealtimeClock().Now()
for _, tg := range ts.Root.ThreadGroups() {
@@ -268,6 +273,9 @@ func Processes(k *kernel.Kernel, out *[]*Process) error {
if pid == 0 {
continue
}
+ if containerID != "" && containerID != tg.Leader().ContainerID() {
+ continue
+ }
ppid := kernel.ThreadID(0)
if tg.Leader().Parent() != nil {
diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go
index f71e32ac9..1ace0b501 100644
--- a/pkg/sentry/kernel/kernel.go
+++ b/pkg/sentry/kernel/kernel.go
@@ -524,6 +524,9 @@ type CreateProcessArgs struct {
// Anyone setting Root must donate a reference (i.e. increment it) to
// keep it alive until it is decremented by CreateProcess.
Root *fs.Dirent
+
+ // ContainerID is the container that the process belongs to.
+ ContainerID string
}
// NewContext returns a context.Context that represents the task that will be
@@ -660,6 +663,7 @@ func (k *Kernel) CreateProcess(args CreateProcessArgs) (*ThreadGroup, ThreadID,
UTSNamespace: args.UTSNamespace,
IPCNamespace: args.IPCNamespace,
AbstractSocketNamespace: args.AbstractSocketNamespace,
+ ContainerID: args.ContainerID,
}
t, err := k.tasks.NewTask(config)
if err != nil {
@@ -818,6 +822,27 @@ func (k *Kernel) SendExternalSignal(info *arch.SignalInfo, context string) {
k.sendExternalSignal(info, context)
}
+// SendContainerSignal sends the given signal to all processes inside the
+// namespace that match the given container ID.
+func (k *Kernel) SendContainerSignal(cid string, info *arch.SignalInfo) error {
+ k.extMu.Lock()
+ defer k.extMu.Unlock()
+ k.tasks.mu.RLock()
+ defer k.tasks.mu.RUnlock()
+
+ for t := range k.tasks.Root.tids {
+ if t == t.tg.leader && t.ContainerID() == cid {
+ t.tg.signalHandlers.mu.Lock()
+ defer t.tg.signalHandlers.mu.Unlock()
+ infoCopy := *info
+ if err := t.sendSignalLocked(&infoCopy, true /*group*/); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
// FeatureSet returns the FeatureSet.
func (k *Kernel) FeatureSet() *cpuid.FeatureSet {
return k.featureSet
diff --git a/pkg/sentry/kernel/task.go b/pkg/sentry/kernel/task.go
index 2f6f825ac..07ad1614c 100644
--- a/pkg/sentry/kernel/task.go
+++ b/pkg/sentry/kernel/task.go
@@ -205,6 +205,13 @@ type Task struct {
// k is the Kernel that this task belongs to. The k pointer is immutable.
k *Kernel
+ // containerID has no equivalent in Linux; it's used by runsc to track all
+ // tasks that belong to a given containers since cgroups aren't implemented.
+ // It's inherited by the children, is immutable, and may be empty.
+ //
+ // NOTE: cgroups can be used to track this when implemented.
+ containerID string
+
// mu protects some of the following fields.
mu sync.Mutex `state:"nosave"`
@@ -678,3 +685,8 @@ func (t *Task) MountNamespace() *fs.MountNamespace {
func (t *Task) AbstractSockets() *AbstractSocketNamespace {
return t.abstractSockets
}
+
+// ContainerID returns t's container ID.
+func (t *Task) ContainerID() string {
+ return t.containerID
+}
diff --git a/pkg/sentry/kernel/task_clone.go b/pkg/sentry/kernel/task_clone.go
index 46c688b20..130bd652b 100644
--- a/pkg/sentry/kernel/task_clone.go
+++ b/pkg/sentry/kernel/task_clone.go
@@ -258,6 +258,7 @@ func (t *Task) Clone(opts *CloneOptions) (ThreadID, *SyscallControl, error) {
UTSNamespace: utsns,
IPCNamespace: ipcns,
AbstractSocketNamespace: t.abstractSockets,
+ ContainerID: t.ContainerID(),
}
if opts.NewThreadGroup {
cfg.Parent = t
diff --git a/pkg/sentry/kernel/task_start.go b/pkg/sentry/kernel/task_start.go
index 6ce99d268..6c8d7d316 100644
--- a/pkg/sentry/kernel/task_start.go
+++ b/pkg/sentry/kernel/task_start.go
@@ -77,6 +77,9 @@ type TaskConfig struct {
// AbstractSocketNamespace is the AbstractSocketNamespace of the new task.
AbstractSocketNamespace *AbstractSocketNamespace
+
+ // ContainerID is the container the new task belongs to.
+ ContainerID string
}
// NewTask creates a new task defined by cfg.
@@ -124,6 +127,7 @@ func (ts *TaskSet) newTask(cfg *TaskConfig) (*Task, error) {
abstractSockets: cfg.AbstractSocketNamespace,
rseqCPU: -1,
futexWaiter: futex.NewWaiter(),
+ containerID: cfg.ContainerID,
}
t.endStopCond.L = &t.tg.signalHandlers.mu
t.ptraceTracer.Store((*Task)(nil))