diff options
author | Eli Schwartz <eschwartz@archlinux.org> | 2023-02-07 21:24:55 -0500 |
---|---|---|
committer | Eli Schwartz <eschwartz@archlinux.org> | 2023-02-20 22:33:46 -0500 |
commit | ecb32bf457ed27b75c9b4386ca1acfbd4b63869e (patch) | |
tree | bd1399cfde6eaec22c56d03ffd2cf016acdc9777 /mesonbuild/minstall.py | |
parent | a878c38476dbe886bf26bc7bafb07bd4f20f763e (diff) | |
download | meson-ecb32bf457ed27b75c9b4386ca1acfbd4b63869e.zip meson-ecb32bf457ed27b75c9b4386ca1acfbd4b63869e.tar.gz meson-ecb32bf457ed27b75c9b4386ca1acfbd4b63869e.tar.bz2 |
minstall: drop privileges before running rebuild_all
If the user runs `sudo meson install` this may run ninja to build
everything that gets installed. This naturally happens as root also, by
default, which is bad. Instead, detect root elevation tools and drop the
uid/gid of the child ninja process back to the original invoking user
before doing anything.
Diffstat (limited to 'mesonbuild/minstall.py')
-rw-r--r-- | mesonbuild/minstall.py | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index ab797b5..a645960 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -42,7 +42,7 @@ if T.TYPE_CHECKING: ExecutableSerialisation, InstallDataBase, InstallEmptyDir, InstallSymlinkData, TargetInstallData ) - from .mesonlib import FileMode + from .mesonlib import FileMode, EnvironOrDict try: from typing import Protocol @@ -753,7 +753,41 @@ def rebuild_all(wd: str) -> bool: print("Can't find ninja, can't rebuild test.") return False - ret = subprocess.run(ninja + ['-C', wd]).returncode + def drop_privileges() -> T.Tuple[T.Optional[EnvironOrDict], T.Optional[T.Callable[[], None]]]: + if not is_windows() and os.geteuid() == 0: + import pwd + env = os.environ.copy() + + if os.environ.get('SUDO_USER') is not None: + orig_user = env.pop('SUDO_USER') + orig_uid = env.pop('SUDO_UID', 0) + orig_gid = env.pop('SUDO_GID', 0) + homedir = pwd.getpwuid(int(orig_uid)).pw_dir + elif os.environ.get('DOAS_USER') is not None: + orig_user = env.pop('DOAS_USER') + pwdata = pwd.getpwnam(orig_user) + orig_uid = pwdata.pw_uid + orig_gid = pwdata.pw_gid + homedir = pwdata.pw_dir + else: + return None, None + + env['USER'] = orig_user + env['HOME'] = homedir + + def wrapped() -> None: + print(f'Dropping privileges to {orig_user!r} before running ninja...') + if orig_gid is not None: + os.setgid(int(orig_gid)) + if orig_uid is not None: + os.setuid(int(orig_uid)) + + return env, wrapped + else: + return None, None + + env, preexec_fn = drop_privileges() + ret = subprocess.run(ninja + ['-C', wd], env=env, preexec_fn=preexec_fn).returncode if ret != 0: print(f'Could not rebuild {wd}') return False |