Skip to content
Open
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
17 changes: 17 additions & 0 deletions gpustack_runtime/deployer/kubernetes.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,21 @@ def _resolve_runtime_class_name(
pod.spec.runtime_class_name = runtime_class_name


def _set_privilege_escalation(container: kubernetes.client.V1Container) -> None:
security = container.security_context or kubernetes.client.V1SecurityContext()
capabilities = security.capabilities
added_capabilities = {
capability.upper().removeprefix("CAP_")
for capability in (capabilities.add or [])
} if capabilities else set()
# Kubernetes cannot disable escalation for privileged containers, SYS_ADMIN, or ALL.
security.allow_privilege_escalation = bool(
security.privileged
or added_capabilities.intersection({"SYS_ADMIN", "ALL"}),
)
container.security_context = security
Comment on lines +695 to +707

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

在 Kubernetes 中,用房声明的 Capability 可能会带有 CAP_ 前缀(例如 CAP_SYS_ADMIN),或者使用 ALL / CAP_ALL 来启用所有权限。此外,这些字焦串可能是大小写不敏感的。

如果用户指定了 CAP_SYS_ADMIN、ALL 或 CAP_ALL,当前的检查 "SYS_ADMIN" in (capabilities.add or []) 将无法识别,从而导致 allow_privilege_escalation 被错误地设置为 False,这可能会导致容器因权限不足而无法正常运行。

建议对 Capability 进行不区分大小写的处理,并同时支持 CAP_SYS_ADMIN、ALL 和 CAP_ALL。

Suggested change
def _set_privilege_escalation(container: kubernetes.client.V1Container) -> None:
security = container.security_context or kubernetes.client.V1SecurityContext()
capabilities = security.capabilities
# Kubernetes cannot disable escalation for privileged containers or CAP_SYS_ADMIN.
security.allow_privilege_escalation = bool(
security.privileged
or (capabilities and "SYS_ADMIN" in (capabilities.add or [])),
)
container.security_context = security
def _set_privilege_escalation(container: kubernetes.client.V1Container) -> None:
security = container.security_context or kubernetes.client.V1SecurityContext()
capabilities = security.capabilities
# Kubernetes cannot disable escalation for privileged containers or CAP_SYS_ADMIN.
add_caps = {cap.upper() for cap in (capabilities.add or [])} if capabilities else set()
security.allow_privilege_escalation = bool(
security.privileged
or {"SYS_ADMIN", "CAP_SYS_ADMIN", "ALL", "CAP_ALL"}.intersection(add_caps),
)
container.security_context = security

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复。新增 capability 规范化:大小写不敏感,去除可选 CAP_ 前缀,并识别 SYS_ADMIN、CAP_SYS_ADMIN、ALL、CAP_ALL。其他 capability(如 IPC_LOCK)仍可显式关闭权限提升。新增 6 个覆盖前缀/大小写/ALL 的测试,连同既有特权测试共 23 项通过。未把不确定的 capability 字符串扩大为允许提权。提交已推送到 PR 分支。



def _resolve_privileged(container: Container, kdp: bool) -> bool:
"""
Resolve whether a container runs privileged.
Expand Down Expand Up @@ -1765,6 +1780,8 @@ def _create_pod(
),
)

_set_privilege_escalation(container)

# Append the container.
if c.profile == ContainerProfileEnum.INIT:
pod.spec.init_containers = pod.spec.init_containers or []
Expand Down
36 changes: 36 additions & 0 deletions tests/gpustack_runtime/deployer/test_privilege_escalation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from __future__ import annotations as __future_annotations__

import kubernetes
import pytest

from gpustack_runtime.deployer.kubernetes import _set_privilege_escalation


@pytest.mark.parametrize(
"security, expected",
[
(None, False),
(kubernetes.client.V1SecurityContext(privileged=False), False),
(kubernetes.client.V1SecurityContext(privileged=True), True),
*[
(kubernetes.client.V1SecurityContext(
capabilities=kubernetes.client.V1Capabilities(add=[value]),
), True)
for value in ["SYS_ADMIN", "CAP_SYS_ADMIN", "sys_admin", "cap_sys_admin", "ALL", "CAP_ALL"]
],
(
kubernetes.client.V1SecurityContext(
capabilities=kubernetes.client.V1Capabilities(add=["IPC_LOCK"]),
run_as_user=1000,
),
False,
),
],
)
def test_privilege_escalation_matches_final_security_context(security, expected):
container = kubernetes.client.V1Container(name="model", security_context=security)
_set_privilege_escalation(container)
assert container.security_context.allow_privilege_escalation is expected
if security is not None:
assert container.security_context is security
assert container.security_context.run_as_user == security.run_as_user