github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/container-utils/cgroups/cgroups.go (about) 1 // Copyright 2019-2022 The Inspektor Gadget authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cgroups 16 17 import ( 18 "bufio" 19 "fmt" 20 "os" 21 "path/filepath" 22 "strings" 23 "unsafe" 24 25 "golang.org/x/sys/unix" 26 27 "github.com/inspektor-gadget/inspektor-gadget/pkg/utils/host" 28 ) 29 30 func CgroupPathV2AddMountpoint(path string) (string, error) { 31 pathWithMountpoint := filepath.Join("/sys/fs/cgroup/unified", path) 32 if _, err := os.Stat(pathWithMountpoint); os.IsNotExist(err) { 33 pathWithMountpoint = filepath.Join("/sys/fs/cgroup", path) 34 if _, err := os.Stat(pathWithMountpoint); os.IsNotExist(err) { 35 return "", fmt.Errorf("accessing cgroup %q: %w", path, err) 36 } 37 } 38 return pathWithMountpoint, nil 39 } 40 41 // GetCgroupID returns the cgroup2 ID of a path. 42 func GetCgroupID(pathWithMountpoint string) (uint64, error) { 43 hf, _, err := unix.NameToHandleAt(unix.AT_FDCWD, pathWithMountpoint, 0) 44 if err != nil { 45 return 0, fmt.Errorf("GetCgroupID on %q failed: %w", pathWithMountpoint, err) 46 } 47 if hf.Size() != 8 { 48 return 0, fmt.Errorf("GetCgroupID on %q failed: unexpected size", pathWithMountpoint) 49 } 50 ret := *(*uint64)(unsafe.Pointer(&hf.Bytes()[0])) 51 return ret, nil 52 } 53 54 // GetCgroupPaths returns the cgroup1 and cgroup2 paths of a process. 55 // It does not include the "/sys/fs/cgroup/{unified,systemd,}" prefix. 56 func GetCgroupPaths(pid int) (string, string, error) { 57 cgroupPathV1 := "" 58 cgroupPathV2 := "" 59 if cgroupFile, err := os.Open(filepath.Join(host.HostProcFs, fmt.Sprint(pid), "cgroup")); err == nil { 60 defer cgroupFile.Close() 61 reader := bufio.NewReader(cgroupFile) 62 for { 63 line, err := reader.ReadString('\n') 64 if err != nil { 65 break 66 } 67 if strings.HasPrefix(line, "1:name=systemd:") { 68 cgroupPathV1 = strings.TrimPrefix(line, "1:name=systemd:") 69 cgroupPathV1 = strings.TrimSuffix(cgroupPathV1, "\n") 70 continue 71 } 72 if strings.HasPrefix(line, "0::") { 73 cgroupPathV2 = strings.TrimPrefix(line, "0::") 74 cgroupPathV2 = strings.TrimSuffix(cgroupPathV2, "\n") 75 continue 76 } 77 } 78 } else { 79 return "", "", fmt.Errorf("parsing cgroup: %w", err) 80 } 81 82 if cgroupPathV1 == "/" { 83 cgroupPathV1 = "" 84 } 85 86 if cgroupPathV2 == "/" { 87 cgroupPathV2 = "" 88 } 89 90 if cgroupPathV2 == "" && cgroupPathV1 == "" { 91 return "", "", fmt.Errorf("cgroup path not found in /proc/PID/cgroup") 92 } 93 94 return cgroupPathV1, cgroupPathV2, nil 95 }