@@ -10,6 +10,7 @@ import (
1010 "github.com/aquasecurity/tracee/pkg/bucketscache"
1111 "github.com/aquasecurity/tracee/pkg/errfmt"
1212 "github.com/aquasecurity/tracee/pkg/logger"
13+ "github.com/aquasecurity/tracee/pkg/utils/proc"
1314)
1415
1516// ContainerPathResolver generates an accessible absolute path from the root
@@ -45,36 +46,57 @@ func (cPathRes *ContainerPathResolver) GetHostAbsPath(mountNSAbsolutePath string
4546 pids := cPathRes .mountNSPIDsCache .GetBucket (uint32 (mountNS ))
4647
4748 for _ , pid := range pids {
48- // cap.SYS_PTRACE is needed here. Instead of raising privileges, since
49- // this is called too frequently, if the needed event is being traced,
50- // the needed capabilities are added to the Base ring and are always set
51- // as effective.
52- //
53- // (Note: To change this behavior we need a privileged process/server)
54-
55- procRootPath := fmt .Sprintf ("/proc/%d/root" , int (pid ))
56-
57- // fs.FS interface requires relative paths, so the '/' prefix should be trimmed.
58- entries , err := fs .ReadDir (cPathRes .fs , strings .TrimPrefix (procRootPath , "/" ))
49+ procRoot , err := cPathRes .getProcessFSRoot (uint (pid ))
5950 if err != nil {
60- // This process is either not alive or we don't have permissions to access.
6151 // Try next pid in mount ns to find accessible path to mount ns files.
62- logger .Debugw (
63- "Finding mount NS path" ,
64- "Unreachable proc root path" , procRootPath ,
65- "error" , err .Error (),
66- )
52+ logger .Debugw ("Could not access process FS" , "pid" , pid , "error" , err )
6753 continue
6854 }
69- if len (entries ) == 0 {
70- return "" , errfmt .Errorf ("empty directory" )
71- }
72- if err == nil {
73- return fmt .Sprintf ("%s%s" , procRootPath , mountNSAbsolutePath ), nil
74- }
55+
56+ return fmt .Sprintf ("%s%s" , procRoot , mountNSAbsolutePath ), nil
57+ }
58+
59+ // No PIDs registered in this namespace, or couldn't access FS root of any of the PIDs found.
60+ // Try finding one in procfs.
61+ pid , err := proc .GetAnyProcessInNS ("mnt" , mountNS )
62+ if err != nil {
63+ // Couldn't find a process in this namespace using procfs
64+ return "" , ErrContainerFSUnreachable
65+ }
66+
67+ procRoot , err := cPathRes .getProcessFSRoot (pid )
68+ if err != nil {
69+ logger .Debugw ("Could not access process FS" , "pid" , pid , "error" , err )
70+ return "" , ErrContainerFSUnreachable
71+ }
72+
73+ // Register this process in the mount namespace
74+ cPathRes .mountNSPIDsCache .AddBucketItem (uint32 (mountNS ), uint32 (pid ))
75+
76+ return fmt .Sprintf ("%s%s" , procRoot , mountNSAbsolutePath ), nil
77+ }
78+
79+ func (cPathRes * ContainerPathResolver ) getProcessFSRoot (pid uint ) (string , error ) {
80+ // cap.SYS_PTRACE is needed here. Instead of raising privileges, since
81+ // this is called too frequently, if the needed event is being traced,
82+ // the needed capabilities are added to the Base ring and are always set
83+ // as effective.
84+ //
85+ // (Note: To change this behavior we need a privileged process/server)
86+
87+ procRootPath := fmt .Sprintf ("/proc/%d/root" , pid )
88+
89+ // fs.FS interface requires relative paths, so the '/' prefix should be trimmed.
90+ entries , err := fs .ReadDir (cPathRes .fs , strings .TrimPrefix (procRootPath , "/" ))
91+ if err != nil {
92+ // This process is either not alive or we don't have permissions to access.
93+ return "" , errfmt .Errorf ("failed accessing process FS root %s: %v" , procRootPath , err )
94+ }
95+ if len (entries ) == 0 {
96+ return "" , errfmt .Errorf ("process FS root (%s) is empty" , procRootPath )
7597 }
7698
77- return "" , ErrContainerFSUnreachable
99+ return procRootPath , nil
78100}
79101
80102var (
0 commit comments