Skip to content

Commit

Permalink
Check for CAP_SYS_ADMIN instead of root
Browse files Browse the repository at this point in the history
Even if we're running as root, we might not have CAP_SYS_ADMIN, so
let's always check for CAP_SYS_ADMIN.
  • Loading branch information
DaanDeMeyer authored and behrmann committed Mar 11, 2025
1 parent 64495fd commit 371eddf
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 27 deletions.
53 changes: 27 additions & 26 deletions mkosi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
workdir,
)
from mkosi.sandbox import (
CAP_SYS_ADMIN,
CLONE_NEWNS,
MOUNT_ATTR_NODEV,
MOUNT_ATTR_NOEXEC,
Expand All @@ -123,6 +124,7 @@
MS_SLAVE,
__version__,
acquire_privileges,
have_effective_cap,
join_new_session_keyring,
mount,
mount_rbind,
Expand Down Expand Up @@ -4888,39 +4890,38 @@ def run_build(
metadata_dir: Path,
package_dir: Optional[Path] = None,
) -> None:
if os.getuid() != 0:
if not have_effective_cap(CAP_SYS_ADMIN):
acquire_privileges()

unshare(CLONE_NEWNS)

if os.getuid() == 0:
unshare(CLONE_NEWNS)
else:
unshare(CLONE_NEWNS)
mount("", "/", "", MS_SLAVE | MS_REC, "")

# For extra safety when running as root, remount a bunch of directories read-only unless the output
# directory is located in it.
if os.getuid() == 0:
remount = ["/etc", "/opt", "/boot", "/efi", "/media", "/usr"]
# For extra safety when running as root with CAP_SYS_ADMIN, remount a bunch of directories read-only
# unless the output directory is located in it.
if os.getuid() == 0:
remount = ["/etc", "/opt", "/boot", "/efi", "/media", "/usr"]

for d in remount:
if not Path(d).exists():
continue
for d in remount:
if not Path(d).exists():
continue

if any(
p and p.is_relative_to(d)
for p in (
config.workspace_dir_or_default(),
config.package_cache_dir_or_default(),
config.cache_dir,
config.output_dir_or_cwd(),
)
):
continue
if any(
p and p.is_relative_to(d)
for p in (
config.workspace_dir_or_default(),
config.package_cache_dir_or_default(),
config.cache_dir,
config.output_dir_or_cwd(),
)
):
continue

attrs = MOUNT_ATTR_RDONLY
if d in ("/boot", "/efi"):
attrs |= MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | MOUNT_ATTR_NOEXEC
attrs = MOUNT_ATTR_RDONLY
if d in ("/boot", "/efi"):
attrs |= MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | MOUNT_ATTR_NOEXEC

mount_rbind(d, d, attrs)
mount_rbind(d, d, attrs)

with (
complete_step(f"Building {config.image} image"),
Expand Down
2 changes: 1 addition & 1 deletion mkosi/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ def become_user(uid: int, gid: int) -> None:


def acquire_privileges(*, become_root: bool = False) -> bool:
if os.getuid() == 0 or (not become_root and have_effective_cap(CAP_SYS_ADMIN)):
if have_effective_cap(CAP_SYS_ADMIN) and (os.getuid() == 0 or not become_root):
return False

if become_root:
Expand Down

0 comments on commit 371eddf

Please sign in to comment.