From 5bc546919f7274c09c180df188aa7d12fdd3bfeb Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Wed, 26 Apr 2023 10:59:16 +0200 Subject: [PATCH 1/2] build_library/gen_tmpfiles.py: Add options for allowed users and groups This will generate tmpfiles config only for directories that are owned by an allowed user and group if such are passed. Not passing any allowed users or groups, allows any user or group. --- build_library/gen_tmpfiles.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/build_library/gen_tmpfiles.py b/build_library/gen_tmpfiles.py index a4b4134ba1..15958bedbf 100755 --- a/build_library/gen_tmpfiles.py +++ b/build_library/gen_tmpfiles.py @@ -21,8 +21,15 @@ def main(): parser.add_option('--output', help='Write output to the given file') parser.add_option('--ignore', action='append', default=[], help='Ignore one or more paths (use multiple times)') + parser.add_option('--allow-user', action='append', default=[], + help='Allow entries owned by this user only (use multiple times for multiple users)') + parser.add_option('--allow-group', action='append', default=[], + help='Allow entries owned by this group only (use multiple times for multiple groups)') opts, args = parser.parse_args() + allowed_users = set(opts.allow_user) + allowed_groups = set(opts.allow_group) + if opts.root: opts.root = os.path.abspath(opts.root) @@ -59,7 +66,7 @@ def main(): stripped = path if stripped in opts.ignore: - continue + continue info = os.stat(path) assert stat.S_ISDIR(info.st_mode) @@ -67,10 +74,14 @@ def main(): try: owner = pwd.getpwuid(info.st_uid).pw_name + if allowed_users and owner not in allowed_users: + continue except KeyError: owner = str(info.st_uid) try: group = grp.getgrgid(info.st_gid).gr_name + if allowed_groups and group not in allowed_groups: + continue except KeyError: group = str(info.st_gid) From 076e6940e2757a6d87e5fda2c62a397193adecd1 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Wed, 26 Apr 2023 11:01:03 +0200 Subject: [PATCH 2/2] build_library/build_image_util.sh: Split base_image_var.conf into two We used to create a base_image_var.conf tmpfiles config file that contained information about directories under /var that weren't covered by any other tmpfiles config file. Recently some package update started installing a directory under /var that belonged to a user/group not found directly in passwd/group file in /etc. This user/group was defined in passwd/group in /usr/share/baselayout, but at the early boot, these are not yet checked for user/group information, so systemd-tmpfiles running inside initrd failed when trying to create such an entry using the base_image_var.conf tmpfiles config file. Split the base_image_var.conf into two files - base_image_var.conf and base_image_var_late.conf. The former will only contain entries owned by user/group that are supposed to exist very early in the boot, while the latter will contain the rest of directories - those will be created later during the boot. --- build_library/build_image_util.sh | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh index d0ed76f318..bc0b6cc756 100755 --- a/build_library/build_image_util.sh +++ b/build_library/build_image_util.sh @@ -744,11 +744,34 @@ finish_image() { done # Record directories installed to the state partition. # Explicitly ignore entries covered by existing configs. - local tmp_ignore=$(awk '/^[dDfFL]/ {print "--ignore=" $2}' \ - "${root_fs_dir}"/usr/lib/tmpfiles.d/*.conf) + local ignores=() allowed_users=() allowed_groups=() + mapfile -t ignores < <(awk '/^[dDfFL]/ {print "--ignore=" $2}' \ + "${root_fs_dir}"/usr/lib/tmpfiles.d/*.conf) + # Also ignore directories owned by users/groups not in /etc/passwd + # or /etc/group. This is for setting up needed directories in very + # early boot phase (initrd-setup-root). Our source of truth for + # allowed users and groups are users and groups copied by the + # flatcar-tmpfiles script. + + # The grep, sed and tr below basically turn a line like: + # COPY_USERS="root|core" + # into: + # --allow-user=root + # --allow-user=core + mapfile -t allowed_users < <(grep '^COPY_USERS=' "${root_fs_dir}/sbin/flatcar-tmpfiles" | sed -e 's/.*="\([^"]*\)"/\1/' | tr '|' '\n' | sed -e 's/^/--allow-user=/') + mapfile -t allowed_users < <(grep '^COPY_GROUPS=' "${root_fs_dir}/sbin/flatcar-tmpfiles" | sed -e 's/.*="\([^"]*\)"/\1/' | tr '|' '\n' | sed -e 's/^/--allow-group=/') sudo "${BUILD_LIBRARY_DIR}/gen_tmpfiles.py" --root="${root_fs_dir}" \ --output="${root_fs_dir}/usr/lib/tmpfiles.d/base_image_var.conf" \ - ${tmp_ignore} "${root_fs_dir}/var" + "${ignores[@]}" "${allowed_users[@]}" "${allowed_groups[@]}" "${root_fs_dir}/var" + + # Now record the rest of the directories installed to the state + # partition. We go through tmpfiles again to also ignore the entries + # from the just generated base_image_var.conf. + mapfile -t ignores < <(awk '/^[dDfFL]/ {print "--ignore=" $2}' \ + "${root_fs_dir}"/usr/lib/tmpfiles.d/*.conf) + sudo "${BUILD_LIBRARY_DIR}/gen_tmpfiles.py" --root="${root_fs_dir}" \ + --output="${root_fs_dir}/usr/lib/tmpfiles.d/base_image_var_late.conf" \ + "${ignores[@]}" "${root_fs_dir}/var" # Only configure bootloaders if there is a boot partition if mountpoint -q "${root_fs_dir}"/boot; then