aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-03 15:35:32 +0900
committerOphestra <cat@gensokyo.uk>2025-08-03 17:46:14 +0900
commitff662963781c0b9e32c85c6cf725533b61af2bc7 (patch)
treecbdda7968c47629b2fe72daf92537d50ebab6f3b
parent347a79df721e37e09b19c206f43a48e17cb97463 (diff)
container/mount: mount data escape helper function
For formatting user-supplied path strings into overlayfs mount data. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--container/mount.go18
-rw-r--r--container/mount_test.go49
2 files changed, 67 insertions, 0 deletions
diff --git a/container/mount.go b/container/mount.go
index 7ee614b4..fc0e177f 100644
--- a/container/mount.go
+++ b/container/mount.go
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
+ "strings"
. "syscall"
"hakurei.app/container/vfs"
@@ -183,3 +184,20 @@ func parentPerm(perm os.FileMode) os.FileMode {
}
return os.FileMode(pperm)
}
+
+// escapeOverlayDataSegment escapes a string for formatting into the data argument of an overlay mount call.
+func escapeOverlayDataSegment(s string) string {
+ if s == zeroString {
+ return zeroString
+ }
+
+ if f := strings.SplitN(s, "\x00", 2); len(f) > 0 {
+ s = f[0]
+ }
+
+ return strings.NewReplacer(
+ `\`, `\\`,
+ `,`, `\,`,
+ `:`, `\:`,
+ ).Replace(s)
+}
diff --git a/container/mount_test.go b/container/mount_test.go
new file mode 100644
index 00000000..573f080b
--- /dev/null
+++ b/container/mount_test.go
@@ -0,0 +1,49 @@
+package container
+
+import (
+ "os"
+ "testing"
+)
+
+func TestParentPerm(t *testing.T) {
+ testCases := []struct {
+ perm os.FileMode
+ want os.FileMode
+ }{
+ {0755, 0755},
+ {0750, 0750},
+ {0705, 0705},
+ {0700, 0700},
+ {050, 0750},
+ {05, 0705},
+ {0, 0700},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.perm.String(), func(t *testing.T) {
+ if got := parentPerm(tc.perm); got != tc.want {
+ t.Errorf("parentPerm: %#o, want %#o", got, tc.want)
+ }
+ })
+ }
+}
+
+func TestEscapeOverlayDataSegment(t *testing.T) {
+ testCases := []struct {
+ name string
+ s string
+ want string
+ }{
+ {"zero", zeroString, zeroString},
+ {"multi", `\\\:,:,\\\`, `\\\\\\\:\,\:\,\\\\\\`},
+ {"bwrap", `/path :,\`, `/path \:\,\\`},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ if got := escapeOverlayDataSegment(tc.s); got != tc.want {
+ t.Errorf("escapeOverlayDataSegment: %s, want %s", got, tc.want)
+ }
+ })
+ }
+}