podman-build/pkg/domain/infra/abi/play_utils.go
2025-10-11 12:30:35 +09:00

56 lines
1.8 KiB
Go

//go:build !remote
package abi
import (
"fmt"
"os"
"strings"
"github.com/containers/podman/v5/libpod/define"
"golang.org/x/sys/unix"
)
// getSdNotifyMode returns the `sdNotifyAnnotation/$name` for the specified
// name. If name is empty, it'll only look for `sdNotifyAnnotation`.
func getSdNotifyMode(annotations map[string]string, name string) (string, error) {
var mode string
switch len(name) {
case 0:
mode = annotations[sdNotifyAnnotation]
default:
mode = annotations[sdNotifyAnnotation+"/"+name]
}
return mode, define.ValidateSdNotifyMode(mode)
}
// openPathSafely opens the given name under the trusted root path, the unsafeName
// must be a single path component and not contain "/".
// The resulting path will be opened or created if it does not exists.
// Following of symlink is done within staying under root, escapes outsides
// of root are not allowed and prevent.
//
// This custom function is needed because securejoin.SecureJoin() is not race safe
// and the volume might be mounted in another container that could swap in a symlink
// after the function ahs run. securejoin.OpenInRoot() doesn't work either because
// it cannot create files and doesn't work on freebsd.
func openPathSafely(root, unsafeName string) (*os.File, error) {
if strings.Contains(unsafeName, "/") {
return nil, fmt.Errorf("name %q must not contain path separator", unsafeName)
}
fdDir, err := os.OpenFile(root, unix.O_RDONLY, 0)
if err != nil {
return nil, err
}
defer fdDir.Close()
flags := unix.O_CREAT | unix.O_WRONLY | unix.O_TRUNC | unix.O_CLOEXEC
fd, err := unix.Openat(int(fdDir.Fd()), unsafeName, flags|unix.O_NOFOLLOW, 0o644)
if err == nil {
return os.NewFile(uintptr(fd), unsafeName), nil
}
if err == unix.ELOOP {
return openSymlinkPath(fdDir, unsafeName, flags)
}
return nil, &os.PathError{Op: "openat", Path: unsafeName, Err: err}
}