From 194a48aef32367c45c555a4d93fb1a3375b0dead Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Fri, 19 May 2023 16:08:47 +0200 Subject: [PATCH] update common submodule Laszlo Ersek (2): options/keys: key_store_import_key(): un-constify "key" parameter options/keys: introduce unescape_device_mapper_lvm() Richard W.M. Jones (1): mlcustomize/SELinux_relabel.ml: Use Array.mem Roman Kagan (1): mlcustomize: skip SELinux relabeling if it's disabled Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2168506 Signed-off-by: Laszlo Ersek Message-Id: <20230519140849.310774-2-lersek@redhat.com> Reviewed-by: Richard W.M. Jones (cherry picked from commit 83afd6d3d2c82ee3a8f22079ba12ef7eac38ac34) --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Submodule common 70c10a07..b636c3f2: diff --git a/common/mlcustomize/SELinux_relabel.ml b/common/mlcustomize/SELinux_relabel.ml index 5ecf7bd7..2f3a09bf 100644 --- a/common/mlcustomize/SELinux_relabel.ml +++ b/common/mlcustomize/SELinux_relabel.ml @@ -24,10 +24,6 @@ open Printf module G = Guestfs -(* Simple reimplementation of Array.mem, available only with OCaml >= 4.03. *) -let array_find a l = - List.mem a (Array.to_list l) - let rec relabel (g : G.guestfs) = (* Is the guest using SELinux? (Otherwise this is a no-op). *) if is_selinux_guest g then ( @@ -59,14 +55,24 @@ and use_setfiles g = g#aug_load (); debug_augeas_errors g; + let config_path = "/files/etc/selinux/config" in + let config_keys = g#aug_ls config_path in + (* SELinux may be disabled via a setting in config file *) + let selinux_disabled = + let selinuxmode_path = config_path ^ "/SELINUX" in + if Array.mem selinuxmode_path config_keys then + g#aug_get selinuxmode_path = "disabled" + else + false in + if selinux_disabled then + failwith "selinux disabled"; + (* Get the SELinux policy name, eg. "targeted", "minimum". * Use "targeted" if not specified, just like libselinux does. *) let policy = - let config_path = "/files/etc/selinux/config" in let selinuxtype_path = config_path ^ "/SELINUXTYPE" in - let keys = g#aug_ls config_path in - if array_find selinuxtype_path keys then + if Array.mem selinuxtype_path config_keys then g#aug_get selinuxtype_path else "targeted" in diff --git a/common/options/keys.c b/common/options/keys.c index 48f1bc7c..52b27369 100644 --- a/common/options/keys.c +++ b/common/options/keys.c @@ -260,8 +260,107 @@ key_store_add_from_selector (struct key_store *ks, const char *selector) return key_store_import_key (ks, &key); } +/* Turn /dev/mapper/VG-LV into /dev/VG/LV, in-place. */ +static void +unescape_device_mapper_lvm (char *id) +{ + static const char dev[] = "/dev/", dev_mapper[] = "/dev/mapper/"; + const char *input_start; + char *output; + enum { M_SCAN, M_FILL, M_DONE } mode; + + if (!STRPREFIX (id, dev_mapper)) + return; + + /* Start parsing "VG-LV" from "id" after "/dev/mapper/". */ + input_start = id + (sizeof dev_mapper - 1); + + /* Start writing the unescaped "VG/LV" output after "/dev/". */ + output = id + (sizeof dev - 1); + + for (mode = M_SCAN; mode < M_DONE; ++mode) { + char c; + const char *input = input_start; + const char *hyphen_buffered = NULL; + bool single_hyphen_seen = false; + + do { + c = *input; + + switch (c) { + case '-': + if (hyphen_buffered == NULL) + /* This hyphen may start an escaped hyphen, or it could be the + * separator in VG-LV. + */ + hyphen_buffered = input; + else { + /* This hyphen completes an escaped hyphen; unescape it. */ + if (mode == M_FILL) + *output++ = '-'; + hyphen_buffered = NULL; + } + break; + + case '/': + /* Slash characters are forbidden in VG-LV anywhere. If there's any, + * we'll find it in the first (i.e., scanning) phase, before we output + * anything back to "id". + */ + assert (mode == M_SCAN); + return; + + default: + /* Encountered a non-slash, non-hyphen character -- which also may be + * the terminating NUL. + */ + if (hyphen_buffered != NULL) { + /* The non-hyphen character comes after a buffered hyphen, so the + * buffered hyphen is supposed to be the single hyphen that separates + * VG from LV in VG-LV. There are three requirements for this + * separator: (a) it must be unique (we must not have seen another + * such separator earlier), (b) it must not be at the start of VG-LV + * (because VG would be empty that way), (c) it must not be at the end + * of VG-LV (because LV would be empty that way). Should any of these + * be violated, we'll catch that during the first (i.e., scanning) + * phase, before modifying "id". + */ + if (single_hyphen_seen || hyphen_buffered == input_start || + c == '\0') { + assert (mode == M_SCAN); + return; + } + + /* Translate the separator hyphen to a slash character. */ + if (mode == M_FILL) + *output++ = '/'; + hyphen_buffered = NULL; + single_hyphen_seen = true; + } + + /* Output the non-hyphen character (including the terminating NUL) + * regardless of whether there was a buffered hyphen separator (which, + * by now, we'll have attempted to translate and flush). + */ + if (mode == M_FILL) + *output++ = c; + } + + ++input; + } while (c != '\0'); + + /* We must have seen the VG-LV separator. If that's not the case, we'll + * catch it before modifying "id". + */ + if (!single_hyphen_seen) { + assert (mode == M_SCAN); + return; + } + } +} + struct key_store * -key_store_import_key (struct key_store *ks, const struct key_store_key *key) +key_store_import_key (struct key_store *ks, struct key_store_key *key) { struct key_store_key *new_keys; @@ -278,6 +377,7 @@ key_store_import_key (struct key_store *ks, const struct key_store_key *key) error (EXIT_FAILURE, errno, "realloc"); ks->keys = new_keys; + unescape_device_mapper_lvm (key->id); ks->keys[ks->nr_keys] = *key; ++ks->nr_keys; diff --git a/common/options/options.h b/common/options/options.h index 94573ee0..94e8b9ee 100644 --- a/common/options/options.h +++ b/common/options/options.h @@ -169,7 +169,8 @@ extern struct matching_key *get_keys (struct key_store *ks, const char *device, const char *uuid, size_t *nr_matches); extern void free_keys (struct matching_key *keys, size_t nr_matches); extern struct key_store *key_store_add_from_selector (struct key_store *ks, const char *selector); -extern struct key_store *key_store_import_key (struct key_store *ks, const struct key_store_key *key); +extern struct key_store *key_store_import_key (struct key_store *ks, + struct key_store_key *key); extern bool key_store_requires_network (const struct key_store *ks); extern void free_key_store (struct key_store *ks);