1- // Copyright (c) 2018-2022 , Sylabs Inc. All rights reserved.
1+ // Copyright (c) 2018-2024 , Sylabs Inc. All rights reserved.
22// This software is licensed under a 3-clause BSD license. Please consult the
33// LICENSE.md file distributed with the sources of this project regarding your
44// rights to use or distribute this software.
@@ -13,9 +13,11 @@ import (
1313 "os"
1414 "path"
1515 "path/filepath"
16+ "syscall"
1617 "time"
1718
1819 securejoin "github.com/cyphar/filepath-securejoin"
20+ "github.com/sylabs/singularity/v4/internal/pkg/cgroups"
1921 "github.com/sylabs/singularity/v4/internal/pkg/util/bin"
2022 "github.com/sylabs/singularity/v4/internal/pkg/util/fs"
2123 "github.com/sylabs/singularity/v4/internal/pkg/util/rootless"
@@ -58,10 +60,52 @@ func runtimeStateDir() (path string, err error) {
5860 if err != nil {
5961 return "" , err
6062 }
63+
64+ // Root - use our own /run directory
6165 if u .Uid == "0" {
6266 return "/run/singularity-oci" , nil
6367 }
64- return fmt .Sprintf ("/run/user/%s/singularity-oci" , u .Uid ), nil
68+
69+ // Prefer XDG_RUNTIME_DIR for non-root, if set and usable.
70+ if ok , _ := cgroups .HasXDGRuntimeDir (); ok {
71+ d := filepath .Join (os .Getenv ("XDG_RUNTIME_DIR" ), "singularity-oci" )
72+ sylog .Debugf ("Using XDG_RUNTIME_DIR for runtime state (%s)" , d )
73+ return d , nil
74+ }
75+
76+ // If no XDG_RUNTIME_DIR, then try standard user session directory location.
77+ runDir := fmt .Sprintf ("/run/user/%s/" , u .Uid )
78+ if fs .IsDir (runDir ) {
79+ d := filepath .Join (runDir , "singularity-oci" )
80+ sylog .Debugf ("Using /run/user default for runtime state (%s)" , d )
81+ return d , nil
82+ }
83+
84+ // If standard user session directory not available, use TMPDIR as a last resort.
85+ runDir = filepath .Join (os .TempDir (), "singularity-oci-" + u .Uid )
86+ sylog .Infof ("No /run/user session directory for user. Using %q for runtime state." , runDir )
87+
88+ // Create if not present
89+ st , err := os .Stat (runDir )
90+ if os .IsNotExist (err ) {
91+ return runDir , os .Mkdir (runDir , 0o700 )
92+ }
93+ if err != nil {
94+ return "" , err
95+ }
96+
97+ // If it exists, verify it's a directory with correct ownership, perms.
98+ if ! st .IsDir () {
99+ return "" , fmt .Errorf ("%s exists, but is not a directory" , runDir )
100+ }
101+ if st .Sys ().(* syscall.Stat_t ).Uid != uint32 (os .Geteuid ()) { //nolint:forcetypeassert
102+ return "" , fmt .Errorf ("%s exists, but is not owned by correct user" , runDir )
103+ }
104+ if st .Mode ().Perm () != 0o700 {
105+ return "" , fmt .Errorf ("%s exists, but does not have correct permissions (700)" , runDir )
106+ }
107+
108+ return runDir , nil
65109}
66110
67111// stateDir returns the path to container state handled by conmon/singularity
0 commit comments