mirror of
https://github.com/hengyoush/kyanos.git
synced 2025-12-20 01:03:46 +08:00
feat: check cap privileges instead of Geteuid during starting the agent (#242)
* feat: Introduce github.com/containerd/containerd/pkg/cap to check whether process has CAP_BPF privilege Signed-off-by: spencercjh <spencercjh@gmail.com> * fix: better logs * fix: adapt to e2e test env * style: go mod tidy * fix: make tests pass * fix: DO NOT use containerd cap package * test: introduce tests to verify agent/common/permission.go * fix: correct implementation refer to https://man7.org/linux/man-pages/man2/capset.2.html * test: test test_add_cap_bpf first * test: cap-add difference capability for different kernal * test: load btf file to container and run kyanos with --btf flag * test: add missing capability CAP_SYS_RESOURCE * test: try to use --privileged instead of cap-add --------- Signed-off-by: spencercjh <spencercjh@gmail.com>
This commit is contained in:
83
.github/workflows/test.yml
vendored
83
.github/workflows/test.yml
vendored
@@ -155,6 +155,33 @@ jobs:
|
||||
#install python pip
|
||||
sudo apt install -y python3 python3-pip pipx
|
||||
|
||||
- name: Test CAP_BPF privilege check
|
||||
uses: cilium/little-vm-helper@97c89f004bd0ab4caeacfe92ebc956e13e362e6b # v0.0.19
|
||||
if: ${{ !contains(fromJSON('["4.19-20240912.022020", "5.4-20240912.022020"]'), matrix.kernel) }}
|
||||
with:
|
||||
provision: 'false'
|
||||
cmd: |
|
||||
set -euxo pipefail
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
pushd /host
|
||||
bash /host/testdata/run_cap_bpf_test.sh "" "CAP_BPF"
|
||||
popd
|
||||
|
||||
|
||||
- name: Test CAP_SYS_ADMIN privilege check
|
||||
uses: cilium/little-vm-helper@97c89f004bd0ab4caeacfe92ebc956e13e362e6b # v0.0.19
|
||||
if: contains(fromJSON('["4.19-20240912.022020", "5.4-20240912.022020"]'), matrix.kernel)
|
||||
with:
|
||||
provision: 'false'
|
||||
cmd: |
|
||||
set -euxo pipefail
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
pushd /host
|
||||
bash /host/testdata/run_cap_bpf_test.sh "" "CAP_SYS_ADMIN"
|
||||
popd
|
||||
|
||||
- name: Test filter by comm
|
||||
uses: cilium/little-vm-helper@97c89f004bd0ab4caeacfe92ebc956e13e362e6b # v0.0.19
|
||||
with:
|
||||
@@ -165,9 +192,9 @@ jobs:
|
||||
cat /etc/issue
|
||||
pushd /host
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_filter_by_comm.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_filter_by_comm.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_filter_by_comm.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_filter_by_comm.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
popd
|
||||
|
||||
@@ -181,9 +208,9 @@ jobs:
|
||||
cat /etc/issue
|
||||
pushd /host
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_gotls.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_gotls.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_gotls.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_gotls.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
popd
|
||||
|
||||
@@ -197,9 +224,9 @@ jobs:
|
||||
cat /etc/issue
|
||||
pushd /host
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_https.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_https.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_https.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_https.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
popd
|
||||
|
||||
@@ -213,9 +240,9 @@ jobs:
|
||||
cat /etc/issue
|
||||
pushd /host
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_side.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_side.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_side.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_side.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
popd
|
||||
|
||||
@@ -229,9 +256,9 @@ jobs:
|
||||
cat /etc/issue
|
||||
pushd /host
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_mysql.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_mysql.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_mysql.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_mysql.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
popd
|
||||
|
||||
@@ -244,9 +271,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_base.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_base.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_base.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_base.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
|
||||
@@ -259,9 +286,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_filter_by_l4.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_filter_by_l4.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_filter_by_l4.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_filter_by_l4.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test kern evt
|
||||
@@ -273,9 +300,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_kern_evt.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_kern_evt.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_kern_evt.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_kern_evt.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test test docker filter by container id
|
||||
@@ -287,9 +314,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_docker_filter_by_container_id.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_docker_filter_by_container_id.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_docker_filter_by_container_id.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_docker_filter_by_container_id.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test test docker filter by container name
|
||||
@@ -301,9 +328,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_docker_filter_by_container_name.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_docker_filter_by_container_name.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_docker_filter_by_container_name.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_docker_filter_by_container_name.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test filter by pid
|
||||
@@ -315,9 +342,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_docker_filter_by_pid.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_docker_filter_by_pid.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_docker_filter_by_pid.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_docker_filter_by_pid.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test test containerd filter by container name
|
||||
@@ -329,9 +356,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_containerd_filter_by_container_name.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_containerd_filter_by_container_name.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_containerd_filter_by_container_name.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_containerd_filter_by_container_name.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test test containerd filter by container id
|
||||
@@ -343,9 +370,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_containerd_filter_by_container_id.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_containerd_filter_by_container_id.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_containerd_filter_by_container_id.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_containerd_filter_by_container_id.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test redis
|
||||
@@ -357,9 +384,9 @@ jobs:
|
||||
uname -a
|
||||
cat /etc/issue
|
||||
if [ -f "/var/lib/kyanos/btf/current.btf" ]; then
|
||||
bash /host/testdata/test_redis.sh '/host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
bash /host/testdata/test_redis.sh 'sudo /host/kyanos/kyanos $kyanos_log_option --btf /var/lib/kyanos/btf/current.btf'
|
||||
else
|
||||
bash /host/testdata/test_redis.sh '/host/kyanos/kyanos $kyanos_log_option'
|
||||
bash /host/testdata/test_redis.sh 'sudo /host/kyanos/kyanos $kyanos_log_option'
|
||||
fi
|
||||
|
||||
- name: Test k8s
|
||||
|
||||
@@ -35,8 +35,11 @@ func SetupAgent(options ac.AgentOptions) {
|
||||
return
|
||||
}
|
||||
|
||||
if os.Geteuid() != 0 {
|
||||
common.AgentLog.Error("Kyanos requires root privileges to run. Please run kyanos with sudo.")
|
||||
if ok, err := ac.HasPermission(); err != nil {
|
||||
common.AgentLog.Error("check capabilities failed: ", err)
|
||||
return
|
||||
} else if !ok {
|
||||
common.AgentLog.Error("Kyanos requires CAP_BPF to run. Please run kyanos with sudo or run container in privilege mode.")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
24
agent/common/permission.go
Normal file
24
agent/common/permission.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// capBpf 0000 0000 0000 0000 0000 0000 1000 0000
|
||||
capBpf = 1 << (unix.CAP_BPF - 32)
|
||||
// capSysAdmin 0000 0000 0010 0000 0000 0000 0000 0000
|
||||
capSysAdmin = 1 << unix.CAP_SYS_ADMIN
|
||||
)
|
||||
|
||||
// HasPermission reference: https://man7.org/linux/man-pages/man2/capset.2.html
|
||||
func HasPermission() (bool, error) {
|
||||
hdr := unix.CapUserHeader{Version: unix.LINUX_CAPABILITY_VERSION_3}
|
||||
var data [2]unix.CapUserData
|
||||
if err := unix.Capget(&hdr, &data[0]); err != nil {
|
||||
return false, err
|
||||
}
|
||||
// Note that the CAP_* values are bit indexes and need to be bit-shifted before ORing into the bit fields.
|
||||
// Note that 64-bit capabilities use datap[0] and datap[1], whereas 32-bit capabilities use only datap[0].
|
||||
return data[1].Permitted&capBpf != 0 || data[0].Permitted&capSysAdmin != 0, nil
|
||||
}
|
||||
2
go.mod
2
go.mod
@@ -34,6 +34,7 @@ require (
|
||||
k8s.io/cri-api v0.31.0
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/kubernetes v1.24.17
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -138,7 +139,6 @@ require (
|
||||
k8s.io/apimachinery v0.31.1 // indirect
|
||||
k8s.io/apiserver v0.31.1 // indirect
|
||||
k8s.io/component-base v0.31.1 // indirect
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||
rsc.io/binaryregexp v0.2.0 // indirect
|
||||
)
|
||||
|
||||
|
||||
2
go.sum
2
go.sum
@@ -31,8 +31,6 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||
github.com/charmbracelet/bubbletea v1.2.2 h1:EMz//Ky/aFS2uLcKqpCst5UOE6z5CFDGRsUpyXz0chs=
|
||||
github.com/charmbracelet/bubbletea v1.2.2/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
|
||||
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
|
||||
github.com/charmbracelet/bubbletea v1.2.4/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM=
|
||||
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
|
||||
|
||||
28
testdata/run_cap_bpf_test.sh
vendored
Normal file
28
testdata/run_cap_bpf_test.sh
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
|
||||
DOCKER_REGISTRY="$1"
|
||||
if [ -n "$DOCKER_REGISTRY" ]; then
|
||||
# 检查是否以 / 结尾
|
||||
if [[ "$DOCKER_REGISTRY" != */ ]]; then
|
||||
DOCKER_REGISTRY="${DOCKER_REGISTRY}/"
|
||||
fi
|
||||
else
|
||||
echo "DOCKER_REGISTRY is missing."
|
||||
fi
|
||||
|
||||
# CAP_SYS_RESOURCE reference: https://docs.ebpf.io/linux/concepts/resource-limit/
|
||||
sudo docker run -d --ulimit memlock=100000000000:100000000000 --cap-add=CAP_SYS_RESOURCE --name alpine $DOCKER_REGISTRY'alpine' sh -c 'sleep 120' || true
|
||||
sudo docker cp /host/kyanos/kyanos alpine:/
|
||||
sudo docker cp ./testdata/test_not_add_cap_bpf.sh alpine:/
|
||||
sudo docker cp /var/lib/kyanos/btf/current.btf alpine:/
|
||||
sudo docker exec alpine sh -c 'sh /test_not_add_cap_bpf.sh "/kyanos --btf /current.btf"'
|
||||
sudo docker stop alpine && sudo docker rm alpine
|
||||
|
||||
# mount sys reference: https://stackoverflow.com/questions/75808955/error-mounting-sys-kernel-debug-tracing-to-rootfs
|
||||
sudo docker run -d -v /sys/:/sys/ --privileged --name alpine $DOCKER_REGISTRY'alpine' sh -c 'sleep 120' || true
|
||||
sudo docker cp /host/kyanos/kyanos alpine:/
|
||||
sudo docker cp ./testdata/test_add_cap_bpf.sh alpine:/
|
||||
sudo docker cp /var/lib/kyanos/btf/current.btf alpine:/
|
||||
sudo docker exec alpine sh -c 'sh /test_add_cap_bpf.sh "/kyanos --btf /current.btf"'
|
||||
sudo docker stop alpine && sudo docker rm alpine
|
||||
12
testdata/test_add_cap_bpf.sh
vendored
Normal file
12
testdata/test_add_cap_bpf.sh
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
set -x
|
||||
|
||||
CMD="$1"
|
||||
FILE_PREFIX="/tmp/kyanos"
|
||||
LNAME="${FILE_PREFIX}_test_add_cap_bpf_before.log"
|
||||
|
||||
timeout 30 ${CMD} watch http --debug-output 2>&1 | tee "${LNAME}" &
|
||||
wait
|
||||
|
||||
cat "${LNAME}"
|
||||
cat "${LNAME}" | grep -v "requires CAP_BPF"
|
||||
12
testdata/test_not_add_cap_bpf.sh
vendored
Normal file
12
testdata/test_not_add_cap_bpf.sh
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env sh
|
||||
set -x
|
||||
|
||||
CMD="$1"
|
||||
FILE_PREFIX="/tmp/kyanos"
|
||||
LNAME="${FILE_PREFIX}_test_not_add_cap_bpf_before.log"
|
||||
|
||||
timeout 30 ${CMD} watch http --debug-output 2>&1 | tee "${LNAME}" &
|
||||
wait
|
||||
|
||||
cat "${LNAME}"
|
||||
cat "${LNAME}" | grep "requires CAP_BPF"
|
||||
Reference in New Issue
Block a user