forked from security/hakurei
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>
This commit is contained in:
@@ -10,8 +10,7 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"hakurei.app/container/check"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -100,7 +99,6 @@ func (e DisallowedTypeflagError) Error() string {
|
|||||||
|
|
||||||
// Cure cures the [Artifact], producing a directory located at work.
|
// Cure cures the [Artifact], producing a directory located at work.
|
||||||
func (a *tarArtifact) Cure(t *TContext) (err error) {
|
func (a *tarArtifact) Cure(t *TContext) (err error) {
|
||||||
temp := t.GetTempDir()
|
|
||||||
var tr io.ReadCloser
|
var tr io.ReadCloser
|
||||||
if tr, err = t.Open(a.f); err != nil {
|
if tr, err = t.Open(a.f); err != nil {
|
||||||
return
|
return
|
||||||
@@ -137,14 +135,24 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type dirTargetPerm struct {
|
type dirTargetPerm struct {
|
||||||
path *check.Absolute
|
path string
|
||||||
mode fs.FileMode
|
mode fs.FileMode
|
||||||
}
|
}
|
||||||
var madeDirectories []dirTargetPerm
|
var madeDirectories []dirTargetPerm
|
||||||
|
|
||||||
if err = os.MkdirAll(temp.String(), 0700); err != nil {
|
if err = os.MkdirAll(t.GetTempDir().String(), 0700); err != nil {
|
||||||
return
|
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
|
var header *tar.Header
|
||||||
r := tar.NewReader(tr)
|
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 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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,8 +175,8 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
|
|||||||
switch typeflag {
|
switch typeflag {
|
||||||
case tar.TypeReg:
|
case tar.TypeReg:
|
||||||
var f *os.File
|
var f *os.File
|
||||||
if f, err = os.OpenFile(
|
if f, err = root.OpenFile(
|
||||||
pathname.String(),
|
header.Name,
|
||||||
os.O_CREATE|os.O_EXCL|os.O_WRONLY,
|
os.O_CREATE|os.O_EXCL|os.O_WRONLY,
|
||||||
header.FileInfo().Mode()&0500,
|
header.FileInfo().Mode()&0500,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
@@ -184,26 +191,29 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
|
|||||||
break
|
break
|
||||||
|
|
||||||
case tar.TypeLink:
|
case tar.TypeLink:
|
||||||
if err = os.Link(
|
if err = root.Link(
|
||||||
temp.Append(header.Linkname).String(),
|
header.Linkname,
|
||||||
pathname.String(),
|
header.Name,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
case tar.TypeSymlink:
|
case tar.TypeSymlink:
|
||||||
if err = os.Symlink(header.Linkname, pathname.String()); err != nil {
|
if err = root.Symlink(
|
||||||
|
header.Linkname,
|
||||||
|
header.Name,
|
||||||
|
); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
case tar.TypeDir:
|
case tar.TypeDir:
|
||||||
madeDirectories = append(madeDirectories, dirTargetPerm{
|
madeDirectories = append(madeDirectories, dirTargetPerm{
|
||||||
path: pathname,
|
path: header.Name,
|
||||||
mode: header.FileInfo().Mode(),
|
mode: header.FileInfo().Mode(),
|
||||||
})
|
})
|
||||||
if err = os.MkdirAll(pathname.String(), 0700); err != nil {
|
if err = root.MkdirAll(header.Name, 0700); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@@ -220,7 +230,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
|
|||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for _, e := range madeDirectories {
|
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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,6 +238,7 @@ func (a *tarArtifact) Cure(t *TContext) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
temp := t.GetTempDir()
|
||||||
if err = os.Chmod(temp.String(), 0700); err != nil {
|
if err = os.Chmod(temp.String(), 0700); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user