-
Notifications
You must be signed in to change notification settings - Fork 519
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Arnaldo Garcia Rincon <[email protected]>
- Loading branch information
1 parent
6e3d6ed
commit 1a3f35b
Showing
10 changed files
with
1,389 additions
and
0 deletions.
There are no files selected for viewing
66 changes: 66 additions & 0 deletions
66
packages/hotdog/0001-poststart-hook-silently-exit-under-certain-condition.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
From 6ce5ac28431bfb18a0ba0233636e238fc18082d6 Mon Sep 17 00:00:00 2001 | ||
From: Arnaldo Garcia Rincon <[email protected]> | ||
Date: Wed, 23 Feb 2022 19:55:25 +0000 | ||
Subject: [PATCH 1/9] poststart-hook: silently exit under certain conditions | ||
|
||
Since hotdog patches java processes on a best-effort basis, the hotdog | ||
poststart hook won't exit with a non-zero error code if: | ||
|
||
- The process fails to constrain itself | ||
- An error occurred while reading the container's capabilities | ||
- An error occurred while the hotpatch was applied | ||
|
||
Signed-off-by: Arnaldo Garcia Rincon <[email protected]> | ||
Reviewed-by: Ben Cressey <[email protected]> | ||
Reviewed-by: Samuel Karp <[email protected]> | ||
--- | ||
cmd/hotdog-poststart-hook/main.go | 14 +++++++++++--- | ||
1 file changed, 11 insertions(+), 3 deletions(-) | ||
|
||
diff --git a/cmd/hotdog-poststart-hook/main.go b/cmd/hotdog-poststart-hook/main.go | ||
index 49b3606..2e559d4 100644 | ||
--- a/cmd/hotdog-poststart-hook/main.go | ||
+++ b/cmd/hotdog-poststart-hook/main.go | ||
@@ -20,6 +20,7 @@ func main() { | ||
} | ||
|
||
func _main() error { | ||
+ // Fail if an error occurs while the container's state or config are retrieved | ||
state, err := hook.State() | ||
if err != nil { | ||
return err | ||
@@ -28,21 +29,28 @@ func _main() error { | ||
if err != nil { | ||
return err | ||
} | ||
+ // Silently exit if: | ||
+ // - The process fails to constrain itself | ||
+ // - An error occurred while reading the container's capabilities | ||
+ // - An error occurred while the hotpatch was applied | ||
+ // We don't send these errors to the STDOUT because the runtime | ||
+ // only reads it when the hook errors out | ||
if spec.Process.SelinuxLabel != "" { | ||
runtime.LockOSThread() | ||
defer runtime.UnlockOSThread() | ||
if err := selinux.SetExecLabel(spec.Process.SelinuxLabel); err != nil { | ||
- return err | ||
+ return nil | ||
} | ||
} | ||
capJSON, err := json.Marshal(spec.Process.Capabilities) | ||
if err != nil { | ||
- return err | ||
+ return nil | ||
} | ||
hotpatch := exec.Command("nsenter", | ||
"-t", strconv.Itoa(state.Pid), | ||
"-m", "-n", "-i", "-u", "-p", | ||
filepath.Join(hotdog.ContainerDir, hotdog.HotpatchBinary)) | ||
hotpatch.Env = []string{hotdog.EnvCapability + "=" + string(capJSON)} | ||
- return hotpatch.Start() | ||
+ hotpatch.Start() | ||
+ return nil | ||
} | ||
-- | ||
2.33.1 | ||
|
168 changes: 168 additions & 0 deletions
168
packages/hotdog/0002-poststart-hook-enter-container-s-cgroups.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
From 84a8080e1a8754d605bad861fc528d61d7792ff9 Mon Sep 17 00:00:00 2001 | ||
From: Arnaldo Garcia Rincon <[email protected]> | ||
Date: Thu, 27 Jan 2022 22:29:30 +0000 | ||
Subject: [PATCH 2/9] poststart-hook: enter container's cgroups | ||
|
||
The poststart-hooks processes have to be bound to the resource limits | ||
set to the container to prevent them from consuming all the host's | ||
resources. | ||
|
||
Signed-off-by: Arnaldo Garcia Rincon <[email protected]> | ||
Reviewed-by: Ben Cressey <[email protected]> | ||
Reviewed-by: Samuel Karp <[email protected]> | ||
--- | ||
cgroups/utils.go | 74 +++++++++++++++++++++++++++++++ | ||
cmd/hotdog-poststart-hook/main.go | 32 +++++++++---- | ||
2 files changed, 98 insertions(+), 8 deletions(-) | ||
create mode 100644 cgroups/utils.go | ||
|
||
diff --git a/cgroups/utils.go b/cgroups/utils.go | ||
new file mode 100644 | ||
index 0000000..fc321d0 | ||
--- /dev/null | ||
+++ b/cgroups/utils.go | ||
@@ -0,0 +1,74 @@ | ||
+package cgroups | ||
+ | ||
+import ( | ||
+ "bufio" | ||
+ "fmt" | ||
+ "os" | ||
+ "path/filepath" | ||
+ "strconv" | ||
+ "strings" | ||
+) | ||
+ | ||
+// EnterCgroups writes the current process into the cgroups of | ||
+// the target process | ||
+func EnterCgroups(targetPID string) error { | ||
+ cgroups, err := parseCgroupFile(filepath.Join("/proc", targetPID, "/cgroup")) | ||
+ if err != nil { | ||
+ return nil | ||
+ } | ||
+ pid := os.Getpid() | ||
+ | ||
+ for sub, path := range cgroups { | ||
+ if err := os.WriteFile(filepath.Join("/sys/fs/cgroup/", sub, path, "tasks"), []byte(strconv.Itoa(pid)), 0); err != nil { | ||
+ return err | ||
+ } | ||
+ } | ||
+ return nil | ||
+} | ||
+ | ||
+// parseCgroupFile returns a map of strings, with the keys being the names of the cgroups | ||
+// controllers, and the values the path name of the control group in the hierarchy | ||
+// to which the process belongs. | ||
+func parseCgroupFile(path string) (map[string]string, error) { | ||
+ f, err := os.Open(path) | ||
+ if err != nil { | ||
+ return nil, err | ||
+ } | ||
+ defer f.Close() | ||
+ | ||
+ s := bufio.NewScanner(f) | ||
+ cgroups := make(map[string]string) | ||
+ | ||
+ for s.Scan() { | ||
+ text := s.Text() | ||
+ // from cgroups(7): | ||
+ // /proc/[pid]/cgroup | ||
+ // ... | ||
+ // For each cgroup hierarchy ... there is one entry | ||
+ // containing three colon-separated fields of the form: | ||
+ // hierarchy-ID:subsystem-list:cgroup-path | ||
+ parts := strings.SplitN(text, ":", 3) | ||
+ if len(parts) < 3 { | ||
+ return nil, fmt.Errorf("invalid cgroup entry: must contain at least two colons: %v", text) | ||
+ } | ||
+ subsystem := parts[1] | ||
+ path := parts[2] | ||
+ // The `cgroup` file contains lines with empty subsystems | ||
+ if subsystem == "" { | ||
+ continue | ||
+ } | ||
+ // There are subsystems with the form `name=<sub>` | ||
+ if strings.Contains(subsystem, "=") { | ||
+ subParts := strings.SplitN(subsystem, "=", 2) | ||
+ if len(subParts) < 2 { | ||
+ return nil, fmt.Errorf("invalid subsystem format, must have subsystem name: %s", parts[1]) | ||
+ } | ||
+ subsystem = subParts[1] | ||
+ } | ||
+ cgroups[subsystem] = path | ||
+ } | ||
+ if err := s.Err(); err != nil { | ||
+ return nil, err | ||
+ } | ||
+ return cgroups, nil | ||
+} | ||
diff --git a/cmd/hotdog-poststart-hook/main.go b/cmd/hotdog-poststart-hook/main.go | ||
index 2e559d4..fc5d9d1 100644 | ||
--- a/cmd/hotdog-poststart-hook/main.go | ||
+++ b/cmd/hotdog-poststart-hook/main.go | ||
@@ -8,9 +8,11 @@ import ( | ||
"strconv" | ||
|
||
"github.com/bottlerocket/hotdog" | ||
+ "github.com/bottlerocket/hotdog/cgroups" | ||
"github.com/bottlerocket/hotdog/hook" | ||
|
||
- selinux "github.com/opencontainers/selinux/go-selinux" | ||
+ "github.com/opencontainers/runtime-spec/specs-go" | ||
+ "github.com/opencontainers/selinux/go-selinux" | ||
) | ||
|
||
func main() { | ||
@@ -29,28 +31,42 @@ func _main() error { | ||
if err != nil { | ||
return err | ||
} | ||
+ targetPID := strconv.Itoa(state.Pid) | ||
+ runtime.LockOSThread() | ||
+ defer runtime.UnlockOSThread() | ||
+ | ||
// Silently exit if: | ||
// - The process fails to constrain itself | ||
// - An error occurred while reading the container's capabilities | ||
// - An error occurred while the hotpatch was applied | ||
// We don't send these errors to the STDOUT because the runtime | ||
// only reads it when the hook errors out | ||
- if spec.Process.SelinuxLabel != "" { | ||
- runtime.LockOSThread() | ||
- defer runtime.UnlockOSThread() | ||
- if err := selinux.SetExecLabel(spec.Process.SelinuxLabel); err != nil { | ||
- return nil | ||
- } | ||
+ if err := constrainProcess(spec, targetPID); err != nil { | ||
+ return nil | ||
} | ||
capJSON, err := json.Marshal(spec.Process.Capabilities) | ||
if err != nil { | ||
return nil | ||
} | ||
hotpatch := exec.Command("nsenter", | ||
- "-t", strconv.Itoa(state.Pid), | ||
+ "-t", targetPID, | ||
"-m", "-n", "-i", "-u", "-p", | ||
filepath.Join(hotdog.ContainerDir, hotdog.HotpatchBinary)) | ||
hotpatch.Env = []string{hotdog.EnvCapability + "=" + string(capJSON)} | ||
hotpatch.Start() | ||
return nil | ||
} | ||
+ | ||
+// constrainProcess sets the SELinux label of the running process, and changes | ||
+// its cgroups to be the same as the target container. | ||
+func constrainProcess(spec specs.Spec, targetPID string) error { | ||
+ if err := cgroups.EnterCgroups(targetPID); err != nil { | ||
+ return err | ||
+ } | ||
+ if spec.Process.SelinuxLabel != "" { | ||
+ if err := selinux.SetExecLabel(spec.Process.SelinuxLabel); err != nil { | ||
+ return err | ||
+ } | ||
+ } | ||
+ return nil | ||
+} | ||
-- | ||
2.33.1 | ||
|
52 changes: 52 additions & 0 deletions
52
packages/hotdog/0003-poststart-hook-set-NO_NEW_PRIVS-in-poststart-process.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
From 71ac992149a17862a495552f38e747a6d297fb43 Mon Sep 17 00:00:00 2001 | ||
From: Arnaldo Garcia Rincon <[email protected]> | ||
Date: Thu, 3 Feb 2022 22:55:40 +0000 | ||
Subject: [PATCH 3/9] poststart-hook: set `NO_NEW_PRIVS` in poststart process | ||
|
||
The `NO_NEW_PRIVS` flag will prevent the poststart process and its | ||
children from getting more privileges than what they were granted. | ||
|
||
Signed-off-by: Arnaldo Garcia Rincon <[email protected]> | ||
Reviewed-by: Ben Cressey <[email protected]> | ||
Reviewed-by: Samuel Karp <[email protected]> | ||
--- | ||
cmd/hotdog-poststart-hook/main.go | 10 ++++++++-- | ||
1 file changed, 8 insertions(+), 2 deletions(-) | ||
|
||
diff --git a/cmd/hotdog-poststart-hook/main.go b/cmd/hotdog-poststart-hook/main.go | ||
index fc5d9d1..ac9d33c 100644 | ||
--- a/cmd/hotdog-poststart-hook/main.go | ||
+++ b/cmd/hotdog-poststart-hook/main.go | ||
@@ -13,6 +13,7 @@ import ( | ||
|
||
"github.com/opencontainers/runtime-spec/specs-go" | ||
"github.com/opencontainers/selinux/go-selinux" | ||
+ "golang.org/x/sys/unix" | ||
) | ||
|
||
func main() { | ||
@@ -57,8 +58,10 @@ func _main() error { | ||
return nil | ||
} | ||
|
||
-// constrainProcess sets the SELinux label of the running process, and changes | ||
-// its cgroups to be the same as the target container. | ||
+// constrainProcess sets the SELinux label of the running process, changes | ||
+// its cgroups to be the same as the target container, and sets the | ||
+// `NO_NEW_PRIVS` flags to prevent the current process to get more | ||
+// privileges. | ||
func constrainProcess(spec specs.Spec, targetPID string) error { | ||
if err := cgroups.EnterCgroups(targetPID); err != nil { | ||
return err | ||
@@ -68,5 +71,8 @@ func constrainProcess(spec specs.Spec, targetPID string) error { | ||
return err | ||
} | ||
} | ||
+ if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { | ||
+ return err | ||
+ } | ||
return nil | ||
} | ||
-- | ||
2.33.1 | ||
|
Oops, something went wrong.