Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: check cap privileges instead of Geteuid during starting the agent #242

Merged
merged 14 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 55 additions & 28 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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


Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
7 changes: 5 additions & 2 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
24 changes: 24 additions & 0 deletions agent/common/permission.go
Original file line number Diff line number Diff line change
@@ -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 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
)

Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
28 changes: 28 additions & 0 deletions testdata/run_cap_bpf_test.sh
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions testdata/test_add_cap_bpf.sh
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions testdata/test_not_add_cap_bpf.sh
Original file line number Diff line number Diff line change
@@ -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"
Loading