aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-02-11 00:40:54 +0900
committerOphestra <cat@gensokyo.uk>2026-02-11 00:40:54 +0900
commit05a828c47453dc36c8f333b18588299067c34fc7 (patch)
tree9cf3bb1b684bd03fd9e79ee734d2a4a8505fe605 /internal/pkg
parent0061d11f939157e181a908f50b0ffb4c991e0375 (diff)
internal/pkg: validate tar pathnames
TContext no longer validates FileArtifact ahead of time, validation outcome is instead determined after consuming the reader to EOF. All data must therefore be treated as untrusted input until the reader is closed. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg')
-rw-r--r--internal/pkg/tar.go43
1 files changed, 27 insertions, 16 deletions
diff --git a/internal/pkg/tar.go b/internal/pkg/tar.go
index 1215adbd..77e4ee27 100644
--- a/internal/pkg/tar.go
+++ b/internal/pkg/tar.go
@@ -10,8 +10,7 @@ import (
"io/fs"
"net/http"
"os"
-
- "hakurei.app/container/check"
+ "path"
)
const (
@@ -100,7 +99,6 @@ func (e DisallowedTypeflagError) Error() string {
// Cure cures the [Artifact], producing a directory located at work.
func (a *tarArtifact) Cure(t *TContext) (err error) {
- temp := t.GetTempDir()
var tr io.ReadCloser
if tr, err = t.Open(a.f); err != nil {
return
@@ -137,14 +135,24 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
}
type dirTargetPerm struct {
- path *check.Absolute
+ path string
mode fs.FileMode
}
var madeDirectories []dirTargetPerm
- if err = os.MkdirAll(temp.String(), 0700); err != nil {
+ if err = os.MkdirAll(t.GetTempDir().String(), 0700); err != nil {
return
}
+ var root *os.Root
+ if root, err = os.OpenRoot(t.GetTempDir().String()); err != nil {
+ return
+ }
+ defer func() {
+ closeErr := root.Close()
+ if err == nil {
+ err = closeErr
+ }
+ }()
var header *tar.Header
r := tar.NewReader(tr)
@@ -158,9 +166,8 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
}
}
- pathname := temp.Append(header.Name)
if typeflag >= '0' && typeflag <= '9' && typeflag != tar.TypeDir {
- if err = os.MkdirAll(pathname.Dir().String(), 0700); err != nil {
+ if err = root.MkdirAll(path.Dir(header.Name), 0700); err != nil {
return
}
}
@@ -168,8 +175,8 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
switch typeflag {
case tar.TypeReg:
var f *os.File
- if f, err = os.OpenFile(
- pathname.String(),
+ if f, err = root.OpenFile(
+ header.Name,
os.O_CREATE|os.O_EXCL|os.O_WRONLY,
header.FileInfo().Mode()&0500,
); err != nil {
@@ -184,26 +191,29 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
break
case tar.TypeLink:
- if err = os.Link(
- temp.Append(header.Linkname).String(),
- pathname.String(),
+ if err = root.Link(
+ header.Linkname,
+ header.Name,
); err != nil {
return
}
break
case tar.TypeSymlink:
- if err = os.Symlink(header.Linkname, pathname.String()); err != nil {
+ if err = root.Symlink(
+ header.Linkname,
+ header.Name,
+ ); err != nil {
return
}
break
case tar.TypeDir:
madeDirectories = append(madeDirectories, dirTargetPerm{
- path: pathname,
+ path: header.Name,
mode: header.FileInfo().Mode(),
})
- if err = os.MkdirAll(pathname.String(), 0700); err != nil {
+ if err = root.MkdirAll(header.Name, 0700); err != nil {
return
}
break
@@ -220,7 +230,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
}
if err == nil {
for _, e := range madeDirectories {
- if err = os.Chmod(e.path.String(), e.mode&0500); err != nil {
+ if err = root.Chmod(e.path, e.mode&0500); err != nil {
return
}
}
@@ -228,6 +238,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
return
}
+ temp := t.GetTempDir()
if err = os.Chmod(temp.String(), 0700); err != nil {
return
}