This commit is contained in:
parent
2896ae2072
commit
f2d675fb55
@ -1,7 +1,9 @@
|
||||
package hooks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -43,10 +45,40 @@ func pluginRoot() (string, error) {
|
||||
if err != nil || len(data) == 0 {
|
||||
return "", errors.New("内置插件内容不可用")
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(root, entry.Name()), data, 0700); err != nil {
|
||||
if err := writeBundledPlugin(filepath.Join(root, entry.Name()), data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
bundledRoot = root
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func writeBundledPlugin(path string, data []byte) error {
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
remove := true
|
||||
defer func() {
|
||||
if remove {
|
||||
_ = os.Remove(path)
|
||||
}
|
||||
}()
|
||||
if _, err := io.Copy(file, bytes.NewReader(data)); err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
if err := file.Sync(); err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
if err := file.Chmod(0700); err != nil {
|
||||
_ = file.Close()
|
||||
return err
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
remove = false
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ func newPluginLaunchSpec(pluginPath, root, name, socketName string, env []string
|
||||
return nil, fmt.Errorf("create plugin sandbox: %w", err)
|
||||
}
|
||||
cleanup := func() { _ = os.RemoveAll(runtimeDir) }
|
||||
if err := os.Chmod(runtimeDir, 0700); err != nil {
|
||||
if err := unix.Chmod(runtimeDir, 0700); err != nil {
|
||||
cleanup()
|
||||
return nil, fmt.Errorf("secure plugin sandbox: %w", err)
|
||||
}
|
||||
@ -93,8 +93,12 @@ func newPluginLaunchSpec(pluginPath, root, name, socketName string, env []string
|
||||
listenerFile,
|
||||
},
|
||||
Sys: &syscall.SysProcAttr{
|
||||
Chroot: runtimeDir,
|
||||
Credential: &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid), NoSetGroups: true},
|
||||
Chroot: runtimeDir,
|
||||
Credential: &syscall.Credential{
|
||||
Uid: uint32(uid), // #nosec G115 -- pluginIdentity restricts both values to 1..65534.
|
||||
Gid: uint32(gid), // #nosec G115 -- pluginIdentity restricts both values to 1..65534.
|
||||
NoSetGroups: true,
|
||||
},
|
||||
Cloneflags: cloneFlags,
|
||||
Pdeathsig: syscall.SIGKILL,
|
||||
Setsid: true,
|
||||
@ -126,12 +130,12 @@ func copyPluginConfig(root, runtimeDir, name string, uid, gid int) error {
|
||||
}
|
||||
|
||||
func copyPluginFile(sourcePath, targetPath string, uid, gid int, mode os.FileMode) error {
|
||||
source, err := os.Open(sourcePath)
|
||||
source, err := openPluginSource(sourcePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open plugin configuration: %w", err)
|
||||
}
|
||||
defer source.Close()
|
||||
target, err := os.OpenFile(targetPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, mode)
|
||||
target, err := createPluginTarget(targetPath, mode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create sandbox plugin configuration: %w", err)
|
||||
}
|
||||
@ -149,15 +153,41 @@ func copyPluginFile(sourcePath, targetPath string, uid, gid int, mode os.FileMod
|
||||
_ = os.Remove(targetPath)
|
||||
return errors.New("plugin configuration exceeds the allowed size")
|
||||
}
|
||||
if err := os.Chmod(targetPath, mode); err != nil {
|
||||
if err := target.Chmod(mode); err != nil {
|
||||
return fmt.Errorf("secure sandbox plugin configuration: %w", err)
|
||||
}
|
||||
if err := os.Chown(targetPath, uid, gid); err != nil {
|
||||
if err := target.Chown(uid, gid); err != nil {
|
||||
return fmt.Errorf("assign sandbox plugin configuration identity: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func openPluginSource(path string) (*os.File, error) {
|
||||
fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC|unix.O_NOFOLLOW, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file := os.NewFile(uintptr(fd), path)
|
||||
if file == nil {
|
||||
_ = unix.Close(fd)
|
||||
return nil, errors.New("open plugin source returned an invalid file")
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func createPluginTarget(path string, mode os.FileMode) (*os.File, error) {
|
||||
fd, err := unix.Open(path, unix.O_WRONLY|unix.O_CREAT|unix.O_EXCL|unix.O_CLOEXEC|unix.O_NOFOLLOW, uint32(mode.Perm()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file := os.NewFile(uintptr(fd), path)
|
||||
if file == nil {
|
||||
_ = unix.Close(fd)
|
||||
return nil, errors.New("create plugin target returned an invalid file")
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func pluginIdentity(name string) (int, error) {
|
||||
value := os.Getenv(name)
|
||||
if value == "" {
|
||||
@ -171,13 +201,13 @@ func pluginIdentity(name string) (int, error) {
|
||||
}
|
||||
|
||||
func copyPluginExecutable(sourcePath, targetPath string, uid, gid int) error {
|
||||
source, err := os.Open(sourcePath)
|
||||
source, err := openPluginSource(sourcePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open plugin executable: %w", err)
|
||||
}
|
||||
defer source.Close()
|
||||
|
||||
target, err := os.OpenFile(targetPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0700)
|
||||
target, err := createPluginTarget(targetPath, 0700)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create sandbox plugin executable: %w", err)
|
||||
}
|
||||
@ -192,10 +222,10 @@ func copyPluginExecutable(sourcePath, targetPath string, uid, gid int) error {
|
||||
if err := target.Close(); err != nil {
|
||||
return fmt.Errorf("close sandbox plugin executable: %w", err)
|
||||
}
|
||||
if err := os.Chmod(targetPath, 0700); err != nil {
|
||||
if err := target.Chmod(0700); err != nil {
|
||||
return fmt.Errorf("secure sandbox plugin executable: %w", err)
|
||||
}
|
||||
if err := os.Chown(targetPath, uid, gid); err != nil {
|
||||
if err := target.Chown(uid, gid); err != nil {
|
||||
return fmt.Errorf("assign sandbox plugin identity: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
Loading…
Reference in New Issue
Block a user