This commit is contained in:
2025-04-15 01:32:02 +03:00
parent fe3acf5b85
commit 240ee852c8
12 changed files with 201 additions and 131 deletions

View File

@ -18,6 +18,8 @@ package build
import (
"log/slog"
"sync"
"syscall"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
@ -25,28 +27,48 @@ import (
func NewMainBuilder(
cfg Config,
mgr manager.Manager,
repos PackageFinder,
) (*Builder, error) {
installerExecutor, err := GetSafeInstaller()
) (*Builder, func(), error) {
var err error
var safeInstallerClose, safeScriptExecutorClose func()
var cleanupOnce sync.Once
cleanup := func() {
cleanupOnce.Do(func() {
if safeScriptExecutorClose != nil {
safeScriptExecutorClose()
}
if safeInstallerClose != nil {
safeInstallerClose()
}
})
}
defer func() {
if err != nil {
slog.Debug("close executors")
cleanup()
}
}()
installerExecutor, safeInstallerClose, err := GetSafeInstaller()
if err != nil {
slog.Error("i will panic GetSafeInstaller", "err", err)
return nil, err
return nil, nil, err
}
// It is very important!
// See https://stackoverflow.com/questions/47296408/cannot-open-uid-map-for-writing-from-an-app-with-cap-setuid-capability-set
if err := utils.NoNewPrivs(); err != nil {
return nil, err
if err = utils.NoNewPrivs(); err != nil {
return nil, nil, err
}
s, err := GetSafeScriptExecutor()
s, safeScriptExecutorClose, err := GetSafeScriptExecutor()
if err != nil {
slog.Error("i will panic GetSafeScriptExecutor", "err", err)
return nil, err
return nil, nil, err
}
mgr := manager.Detect()
builder := &Builder{
scriptExecutor: s,
cacheExecutor: &Cache{
@ -68,5 +90,7 @@ func NewMainBuilder(
repos: repos,
}
return builder, nil
slog.Warn("uid", "uid", syscall.Getuid(), "gid", syscall.Getgid())
return builder, cleanup, nil
}

View File

@ -18,10 +18,12 @@ package build
import (
"context"
"fmt"
"log/slog"
"net/rpc"
"os"
"os/exec"
"sync"
"syscall"
"github.com/hashicorp/go-plugin"
@ -217,10 +219,12 @@ var pluginMap = map[string]plugin.Plugin{
"installer": &InstallerPlugin{},
}
func GetSafeScriptExecutor() (ScriptExecutor, error) {
func GetSafeScriptExecutor() (ScriptExecutor, func(), error) {
var err error
executable, err := os.Executable()
if err != nil {
return nil, err
return nil, nil, err
}
cmd := exec.Command(executable, "_internal-safe-script-executor")
@ -233,7 +237,7 @@ func GetSafeScriptExecutor() (ScriptExecutor, error) {
}
uid, gid, err := utils.GetUidGidAlrUser()
if err != nil {
return nil, err
return nil, nil, err
}
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
@ -254,14 +258,33 @@ func GetSafeScriptExecutor() (ScriptExecutor, error) {
})
rpcClient, err := client.Client()
if err != nil {
slog.Info("1")
return nil, err
return nil, nil, err
}
raw1, err := rpcClient.Dispense("script-executor")
var cleanupOnce sync.Once
cleanup := func() {
cleanupOnce.Do(func() {
client.Kill()
})
}
defer func() {
if err != nil {
slog.Debug("close script-executor")
cleanup()
}
}()
raw, err := rpcClient.Dispense("script-executor")
if err != nil {
return nil, err
return nil, nil, err
}
return raw1.(ScriptExecutor), nil
executor, ok := raw.(ScriptExecutor)
if !ok {
err = fmt.Errorf("dispensed object is not a ScriptExecutor (got %T)", raw)
return nil, nil, err
}
return executor, cleanup, nil
}

View File

@ -17,15 +17,18 @@
package build
import (
"fmt"
"log/slog"
"net/rpc"
"os"
"os/exec"
"sync"
"syscall"
"github.com/hashicorp/go-plugin"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/logger"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
)
type InstallerPlugin struct {
@ -80,10 +83,12 @@ func (p *InstallerPlugin) Server(*plugin.MuxBroker) (interface{}, error) {
return &InstallerRPCServer{Impl: p.Impl}, nil
}
func GetSafeInstaller() (InstallerExecutor, error) {
func GetSafeInstaller() (InstallerExecutor, func(), error) {
var err error
executable, err := os.Executable()
if err != nil {
return nil, err
return nil, nil, err
}
cmd := exec.Command(executable, "_internal-installer")
cmd.Env = append(os.Environ(),
@ -94,6 +99,16 @@ func GetSafeInstaller() (InstallerExecutor, error) {
"ALR_LOG_LEVEL=DEBUG",
"XDG_SESSION_CLASS=user",
)
uid, gid, err := utils.GetUidGidAlrUser()
if err != nil {
return nil, nil, err
}
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uint32(uid),
Gid: uint32(gid),
},
}
slog.Debug("safe installer setup", "uid", syscall.Getuid(), "gid", syscall.Getgid())
@ -110,13 +125,33 @@ func GetSafeInstaller() (InstallerExecutor, error) {
})
rpcClient, err := client.Client()
if err != nil {
return nil, err
return nil, nil, err
}
raw1, err := rpcClient.Dispense("installer")
var cleanupOnce sync.Once
cleanup := func() {
cleanupOnce.Do(func() {
client.Kill()
})
}
defer func() {
if err != nil {
slog.Debug("close installer")
cleanup()
}
}()
raw, err := rpcClient.Dispense("installer")
if err != nil {
return nil, err
return nil, nil, err
}
return raw1.(InstallerExecutor), nil
executor, ok := raw.(InstallerExecutor)
if !ok {
err = fmt.Errorf("dispensed object is not a ScriptExecutor (got %T)", raw)
return nil, nil, err
}
return executor, cleanup, nil
}