-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
cgroup.go
95 lines (81 loc) · 2.5 KB
/
cgroup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
//go:build linux
// Package utils holds utils related files
package utils
import (
"bufio"
"bytes"
"crypto/sha256"
"os"
"strconv"
"strings"
"github.com/DataDog/datadog-agent/pkg/security/common/containerutils"
)
// ContainerID is the type holding the container ID
type ContainerID string
// Bytes returns the container ID as a byte array
func (c ContainerID) Bytes() []byte {
buff := make([]byte, ContainerIDLen)
if len(c) == ContainerIDLen {
copy(buff[:], c)
}
return buff
}
// ContainerIDLen is the length of a container ID is the length of the hex representation of a sha256 hash
const ContainerIDLen = sha256.Size * 2
// ControlGroup describes the cgroup membership of a process
type ControlGroup struct {
// ID unique hierarchy ID
ID int
// Controllers are the list of cgroup controllers bound to the hierarchy
Controllers []string
// Path is the pathname of the control group to which the process
// belongs. It is relative to the mountpoint of the hierarchy.
Path string
}
// GetContainerID returns the container id extracted from the path of the control group
func (cg ControlGroup) GetContainerID() ContainerID {
return ContainerID(containerutils.FindContainerID(cg.Path))
}
// GetProcControlGroups returns the cgroup membership of the specified task.
func GetProcControlGroups(tgid, pid uint32) ([]ControlGroup, error) {
data, err := os.ReadFile(CgroupTaskPath(tgid, pid))
if err != nil {
return nil, err
}
var cgroups []ControlGroup
scanner := bufio.NewScanner(bytes.NewReader(data))
for scanner.Scan() {
t := scanner.Text()
parts := strings.Split(t, ":")
var ID int
ID, err = strconv.Atoi(parts[0])
if err != nil {
continue
}
c := ControlGroup{
ID: ID,
Controllers: strings.Split(parts[1], ","),
Path: parts[2],
}
cgroups = append(cgroups, c)
}
return cgroups, nil
}
// GetProcContainerID returns the container ID which the process belongs to. Returns "" if the process does not belong
// to a container.
func GetProcContainerID(tgid, pid uint32) (ContainerID, error) {
cgroups, err := GetProcControlGroups(tgid, pid)
if err != nil {
return "", err
}
for _, cgroup := range cgroups {
if containerID := cgroup.GetContainerID(); containerID != "" {
return containerID, nil
}
}
return "", nil
}