summaryrefslogtreecommitdiff
path: root/0011-update-common-submodule.patch
blob: 01696ec174b63fdbb1adeb47363c2047f091eeaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
From 194a48aef32367c45c555a4d93fb1a3375b0dead Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
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 <lersek@redhat.com>
Message-Id: <20230519140849.310774-2-lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
(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);