Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/linters/urunc-dict.txt
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ unikontainer
unikontainers
unikraft
urandom
userns
urfave
urunc
urunc's
Expand Down
12 changes: 12 additions & 0 deletions cmd/urunc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ func main() {
// stateCommand,
},
Before: func(_ context.Context, cmd *cli.Command) (context.Context, error) {
if !cmd.IsSet("root") {
xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR")
if xdgRuntimeDir != "" && ShouldHonorXDGRuntimeDir() {
root := xdgRuntimeDir + "/urunc"
if err := prepareXDGRuntimeDir(root); err != nil {
return nil, err
}
if err := cmd.Set("root", root); err != nil {
return nil, err
}
}
}
if err := reviseRootDir(cmd); err != nil {
return nil, err
}
Expand Down
30 changes: 30 additions & 0 deletions cmd/urunc/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"os/exec"
"syscall"

"github.com/moby/sys/userns"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v3"
"github.com/urunc-dev/urunc/pkg/unikontainers"
Expand Down Expand Up @@ -130,3 +131,32 @@ func fatalWithCode(err error, ret int) {
}
os.Exit(ret)
}

// ShouldHonorXDGRuntimeDir reports whether the runtime should use XDG_RUNTIME_DIR
// for the default root directory (e.g. /run/user/UID/urunc instead of /run/urunc).
// It returns true for non-root processes and for root inside a user namespace
// when not running as the "root" user (e.g. rootless Podman).
func ShouldHonorXDGRuntimeDir() bool {
if os.Geteuid() != 0 {
return true
}
if !userns.RunningInUserNS() {
// euid == 0 in the initial ns (real root): use /run/urunc for backward compatibility.
return false
}
// euid == 0 inside a user namespace (rootless): honor XDG_RUNTIME_DIR unless USER=root.
u, ok := os.LookupEnv("USER")
return !ok || u != "root"
}

// prepareXDGRuntimeDir prepares the XDG_RUNTIME_DIR directory according to the XDG specification.
// It creates the directory with proper permissions and sets the sticky bit to prevent auto-pruning.
func prepareXDGRuntimeDir(root string) error {
if err := os.MkdirAll(root, 0o700); err != nil {
return fmt.Errorf("the path in $XDG_RUNTIME_DIR must be writable by the user: %w", err)
}
if err := os.Chmod(root, os.FileMode(0o700)|os.ModeSticky); err != nil {
return fmt.Errorf("you should check permission of the path in $XDG_RUNTIME_DIR: %w", err)
}
return nil
}
Loading