image-info: mount partitions in correct order when analysing image

image-info's code which analysed image with multiple partitions was not
correctly working with more than two partitions, which had to be the
root '/' and EFI partition '/boot/efi'. The consequence was that SELinux
labels on paths which were mounted incorrectly could have been reported
as incorrect.

Modify `append_partitions()` to first read the fstab entries and then
mount all partitions using their UUID in the correct order. Only then
analyze the image filesystem tree.

Regenerate affected image test cases.

Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
Tomas Hozza 2021-08-02 16:35:09 +02:00 committed by Ondřej Budai
parent 972515ad84
commit aed3bf785c
3 changed files with 36 additions and 75 deletions

View file

@ -10795,7 +10795,6 @@
},
"rpm-verify": {
"changed": {
"/boot": ".M.......",
"/etc/chrony.conf": "S.5....T.",
"/etc/dnf/plugins/product-id.conf": "..5....T.",
"/etc/dnf/plugins/subscription-manager.conf": "..5....T.",
@ -10814,34 +10813,9 @@
"/var/spool/anacron/cron.monthly": ".M.......",
"/var/spool/anacron/cron.weekly": ".M......."
},
"missing": [
"/boot/efi",
"/boot/efi/EFI",
"/boot/efi/EFI/BOOT",
"/boot/efi/EFI/BOOT/BOOTAA64.EFI",
"/boot/efi/EFI/BOOT/fbaa64.efi",
"/boot/efi/EFI/redhat",
"/boot/efi/EFI/redhat",
"/boot/efi/EFI/redhat/BOOTAA64.CSV",
"/boot/efi/EFI/redhat/fonts",
"/boot/efi/EFI/redhat/grubaa64.efi",
"/boot/efi/EFI/redhat/mmaa64.efi",
"/boot/efi/EFI/redhat/shim.efi",
"/boot/efi/EFI/redhat/shimaa64-redhat.efi",
"/boot/efi/EFI/redhat/shimaa64.efi",
"/boot/grub2",
"/boot/grub2/grubenv",
"/boot/loader/entries"
]
"missing": []
},
"selinux": {
"context-mismatch": [
{
"actual": "unconfined_u:object_r:unlabeled_t:s0",
"expected": "system_u:object_r:boot_t:s0",
"filename": "/boot"
}
],
"policy": {
"SELINUX": "enforcing",
"SELINUXTYPE": "targeted"

View file

@ -10835,7 +10835,6 @@
},
"rpm-verify": {
"changed": {
"/boot": ".M.......",
"/etc/chrony.conf": "S.5....T.",
"/etc/dnf/plugins/product-id.conf": "..5....T.",
"/etc/dnf/plugins/subscription-manager.conf": "..5....T.",
@ -10857,34 +10856,10 @@
"/var/spool/anacron/cron.weekly": ".M......."
},
"missing": [
"/boot/efi",
"/boot/efi/EFI",
"/boot/efi/EFI/BOOT",
"/boot/efi/EFI/BOOT/BOOTAA64.EFI",
"/boot/efi/EFI/BOOT/fbaa64.efi",
"/boot/efi/EFI/redhat",
"/boot/efi/EFI/redhat",
"/boot/efi/EFI/redhat/BOOTAA64.CSV",
"/boot/efi/EFI/redhat/fonts",
"/boot/efi/EFI/redhat/grubaa64.efi",
"/boot/efi/EFI/redhat/mmaa64.efi",
"/boot/efi/EFI/redhat/shim.efi",
"/boot/efi/EFI/redhat/shimaa64-redhat.efi",
"/boot/efi/EFI/redhat/shimaa64.efi",
"/boot/grub2",
"/boot/grub2/grubenv",
"/boot/loader/entries",
"/etc/yum.repos.d/redhat-rhui.repo"
]
},
"selinux": {
"context-mismatch": [
{
"actual": "unconfined_u:object_r:unlabeled_t:s0",
"expected": "system_u:object_r:boot_t:s0",
"filename": "/boot"
}
],
"policy": {
"SELINUX": "enforcing",
"SELINUXTYPE": "targeted"

View file

@ -7,6 +7,7 @@ import errno
import functools
import glob
import mimetypes
import operator
import json
import os
import platform
@ -1812,44 +1813,55 @@ def append_filesystem(report, tree, *, is_ostree=False):
print("EFI partition", file=sys.stderr)
def partition_is_esp(partition):
return partition["type"] == "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
def find_esp(partitions):
for i, p in enumerate(partitions):
if partition_is_esp(p):
return p, i
return None, 0
def append_partitions(report, device, loctl):
partitions = report["partitions"]
esp, esp_id = find_esp(partitions)
with contextlib.ExitStack() as cm:
# open each partition as a loop device
devices = {}
device_idx_by_part_uuid = {}
for n, part in enumerate(partitions):
start, size = part["start"], part["size"]
dev = cm.enter_context(loop_open(loctl, device, offset=start, size=size))
devices[n] = dev
read_partition(dev, part)
if part["uuid"]:
device_idx_by_part_uuid[part["uuid"].upper()] = n
# find partition with fstab and read it
fstab = []
for n, part in enumerate(partitions):
if not part["fstype"]:
continue
with mount(devices[n]) as tree:
if esp and os.path.exists(f"{tree}/boot/efi"):
with mount_at(devices[esp_id], f"{tree}/boot/efi", options=['umask=077']):
append_filesystem(report, tree)
# situation when /boot is on a separate partition
elif esp and os.path.exists(f"{tree}/efi"):
with mount_at(devices[esp_id], f"{tree}/efi", options=['umask=077']):
append_filesystem(report, tree)
else:
append_filesystem(report, tree)
if os.path.exists(f"{tree}/etc/fstab"):
fstab.extend(read_fstab(tree))
break
# sort the fstab entries by the mountpoint
fstab = sorted(fstab, key=operator.itemgetter(1))
# mount all partitions to ther respective mount points
root_tree = ""
for n, fstab_entry in enumerate(fstab):
part_uuid = fstab_entry[0].split("=")[1].upper()
part_device = devices[device_idx_by_part_uuid[part_uuid]]
part_mountpoint = fstab_entry[1]
part_fstype = fstab_entry[2]
part_options = fstab_entry[3].split(",")
# the first mount point should be root
if n == 0:
if part_mountpoint != "/":
raise RuntimeError("The first mountpoint in sorted fstab entries is not '/'")
root_tree = cm.enter_context(mount(part_device))
continue
cm.enter_context(mount_at(part_device, f"{root_tree}{part_mountpoint}", options=part_options, extra=["-t", part_fstype]))
if not root_tree:
raise RuntimeError("The root filesystem tree is not mounted")
append_filesystem(report, root_tree)
def analyse_image(image):