Skip to content

Commit 371eddf

Browse files
DaanDeMeyerbehrmann
authored andcommitted
Check for CAP_SYS_ADMIN instead of root
Even if we're running as root, we might not have CAP_SYS_ADMIN, so let's always check for CAP_SYS_ADMIN.
1 parent 64495fd commit 371eddf

File tree

2 files changed

+28
-27
lines changed

2 files changed

+28
-27
lines changed

mkosi/__init__.py

+27-26
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
workdir,
115115
)
116116
from mkosi.sandbox import (
117+
CAP_SYS_ADMIN,
117118
CLONE_NEWNS,
118119
MOUNT_ATTR_NODEV,
119120
MOUNT_ATTR_NOEXEC,
@@ -123,6 +124,7 @@
123124
MS_SLAVE,
124125
__version__,
125126
acquire_privileges,
127+
have_effective_cap,
126128
join_new_session_keyring,
127129
mount,
128130
mount_rbind,
@@ -4888,39 +4890,38 @@ def run_build(
48884890
metadata_dir: Path,
48894891
package_dir: Optional[Path] = None,
48904892
) -> None:
4891-
if os.getuid() != 0:
4893+
if not have_effective_cap(CAP_SYS_ADMIN):
48924894
acquire_privileges()
4893-
4894-
unshare(CLONE_NEWNS)
4895-
4896-
if os.getuid() == 0:
4895+
unshare(CLONE_NEWNS)
4896+
else:
4897+
unshare(CLONE_NEWNS)
48974898
mount("", "/", "", MS_SLAVE | MS_REC, "")
48984899

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

4904-
for d in remount:
4905-
if not Path(d).exists():
4906-
continue
4905+
for d in remount:
4906+
if not Path(d).exists():
4907+
continue
49074908

4908-
if any(
4909-
p and p.is_relative_to(d)
4910-
for p in (
4911-
config.workspace_dir_or_default(),
4912-
config.package_cache_dir_or_default(),
4913-
config.cache_dir,
4914-
config.output_dir_or_cwd(),
4915-
)
4916-
):
4917-
continue
4909+
if any(
4910+
p and p.is_relative_to(d)
4911+
for p in (
4912+
config.workspace_dir_or_default(),
4913+
config.package_cache_dir_or_default(),
4914+
config.cache_dir,
4915+
config.output_dir_or_cwd(),
4916+
)
4917+
):
4918+
continue
49184919

4919-
attrs = MOUNT_ATTR_RDONLY
4920-
if d in ("/boot", "/efi"):
4921-
attrs |= MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | MOUNT_ATTR_NOEXEC
4920+
attrs = MOUNT_ATTR_RDONLY
4921+
if d in ("/boot", "/efi"):
4922+
attrs |= MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | MOUNT_ATTR_NOEXEC
49224923

4923-
mount_rbind(d, d, attrs)
4924+
mount_rbind(d, d, attrs)
49244925

49254926
with (
49264927
complete_step(f"Building {config.image} image"),

mkosi/sandbox.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ def become_user(uid: int, gid: int) -> None:
452452

453453

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

458458
if become_root:

0 commit comments

Comments
 (0)