Skip to content

Commit db7d513

Browse files
manifests: set proper SELinux labels for '/boot/efi' and '/boot/lost+found'
Issue: osbuild/osbuild#1877 Co-authored-by: Dusty Mabe <[email protected]>
1 parent 6813e3f commit db7d513

10 files changed

+744
-47
lines changed

build.sh

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,12 @@ patch_osbuild() {
173173
mv /usr/bin/osbuild-mpp /usr/lib/osbuild/tools/
174174

175175
# Now all the software is under the /usr/lib/osbuild dir and we can patch
176-
cat /usr/lib/coreos-assembler/0001-hacks-for-coreos-selinux-issues.patch \
177-
/usr/lib/coreos-assembler/0001-org.osbuild.mkdir-support-creating-dirs-on-mounts.patch \
178-
| patch -d /usr/lib/osbuild -p1
176+
cat /usr/lib/coreos-assembler/0001-org.osbuild.mkdir-support-creating-dirs-on-mounts.patch \
177+
/usr/lib/coreos-assembler/0001-parsing-add-parse_location_into_parts.patch \
178+
/usr/lib/coreos-assembler/0002-parsing-treat-locations-without-scheme-as-belonging-.patch \
179+
/usr/lib/coreos-assembler/0003-org.osbuild.selinux-support-operating-on-mounts.patch \
180+
/usr/lib/coreos-assembler/0004-org.osbuild.selinux-support-for-specifying-where-fil.patch \
181+
| patch -d /usr/lib/osbuild -p1
179182

180183
# And then move the files back; supermin appliance creation will need it back
181184
# in the places delivered by the RPM.

src/0001-hacks-for-coreos-selinux-issues.patch

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
From 234d0776d9fa9a5f0f26e6ff8db290652e01f664 Mon Sep 17 00:00:00 2001
2+
From: Nikita Dubrovskii <[email protected]>
3+
Date: Fri, 18 Oct 2024 12:28:32 +0200
4+
Subject: [PATCH 1/4] parsing: add parse_location_into_parts
5+
6+
New fucntion returns tuple of 'root' and relative 'file path', which could be
7+
useful in contexts, where knowing 'root' is required, for example setting
8+
selinux labels.
9+
---
10+
osbuild/util/parsing.py | 25 +++++++++++++++++++------
11+
1 file changed, 19 insertions(+), 6 deletions(-)
12+
13+
diff --git a/osbuild/util/parsing.py b/osbuild/util/parsing.py
14+
index f8fb2768..f75ffd67 100644
15+
--- a/osbuild/util/parsing.py
16+
+++ b/osbuild/util/parsing.py
17+
@@ -2,7 +2,7 @@
18+
19+
import os
20+
import re
21+
-from typing import Dict, Union
22+
+from typing import Dict, Tuple, Union
23+
from urllib.parse import ParseResult, urlparse
24+
25+
26+
@@ -72,9 +72,9 @@ def parse_input(url: ParseResult, args: Dict) -> os.PathLike:
27+
return root
28+
29+
30+
-def parse_location(location: str, args: Dict) -> str:
31+
+def parse_location_into_parts(location: str, args: Dict) -> Tuple[str, str]:
32+
"""
33+
- Parses the location URL to derive the corresponding file path.
34+
+ Parses the location URL to derive the corresponding root and url path.
35+
36+
Parameters:
37+
- location (str): The location URL to be parsed.
38+
@@ -97,11 +97,24 @@ def parse_location(location: str, args: Dict) -> str:
39+
if not url.path.startswith("/"):
40+
raise ValueError(f"url.path from location must start with '/', got: {url.path}")
41+
42+
- path = os.path.relpath(url.path, "/")
43+
+ return root, url.path
44+
+
45+
+
46+
+def parse_location(location: str, args: Dict) -> str:
47+
+ """
48+
+ Parses the location URL to derive the corresponding file path.
49+
+
50+
+ Parameters:
51+
+ - location (str): The location URL to be parsed.
52+
+ - args (Dict): A dictionary containing arguments including mounts and
53+
+ path information as passed by osbuild.api.arguments()
54+
+ """
55+
+
56+
+ root, urlpath = parse_location_into_parts(location, args)
57+
+ path = os.path.relpath(urlpath, "/")
58+
path = os.path.join(root, path)
59+
path = os.path.normpath(path)
60+
-
61+
- if url.path.endswith("/"):
62+
+ if urlpath.endswith("/"):
63+
path = os.path.join(path, ".")
64+
65+
return path
66+
--
67+
2.47.0
68+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
From 779783e873aa7353bf3b8e27b6b81a9f48b3d225 Mon Sep 17 00:00:00 2001
2+
From: Nikita Dubrovskii <[email protected]>
3+
Date: Mon, 28 Oct 2024 11:20:23 +0100
4+
Subject: [PATCH 2/4] parsing: treat locations without scheme as belonging to
5+
'tree://'
6+
7+
---
8+
osbuild/util/parsing.py | 4 ++++
9+
stages/org.osbuild.mkdir | 9 +++------
10+
2 files changed, 7 insertions(+), 6 deletions(-)
11+
12+
diff --git a/osbuild/util/parsing.py b/osbuild/util/parsing.py
13+
index f75ffd67..0877abec 100644
14+
--- a/osbuild/util/parsing.py
15+
+++ b/osbuild/util/parsing.py
16+
@@ -82,6 +82,10 @@ def parse_location_into_parts(location: str, args: Dict) -> Tuple[str, str]:
17+
path information as passed by osbuild.api.arguments()
18+
"""
19+
20+
+ if "://" not in location:
21+
+ print("INFO: location has no scheme, assuming 'tree://'")
22+
+ location = f"tree://{location}"
23+
+
24+
url = urlparse(location)
25+
26+
scheme = url.scheme
27+
diff --git a/stages/org.osbuild.mkdir b/stages/org.osbuild.mkdir
28+
index d2d11a7a..01f5f431 100755
29+
--- a/stages/org.osbuild.mkdir
30+
+++ b/stages/org.osbuild.mkdir
31+
@@ -15,12 +15,9 @@ def main(args):
32+
parents = item.get("parents", False)
33+
exist_ok = item.get("exist_ok", False)
34+
35+
- if "://" not in path:
36+
- if not path.startswith("/"):
37+
- print("WARNING: relative path used, this is discouraged!")
38+
- path = f"tree:///{path}"
39+
- else:
40+
- path = f"tree://{path}"
41+
+ if "://" not in path and not path.startswith("/"):
42+
+ print("WARNING: relative path used, this is discouraged!")
43+
+ path = f"tree:///{path}"
44+
45+
target = parsing.parse_location(path, args)
46+
if parents:
47+
--
48+
2.47.0
49+
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
From e3454fe7de62f675fcfc3092689803416a457984 Mon Sep 17 00:00:00 2001
2+
From: Nikita Dubrovskii <[email protected]>
3+
Date: Thu, 17 Oct 2024 12:57:00 +0200
4+
Subject: [PATCH 3/4] org.osbuild.selinux: support operating on mounts
5+
6+
This adds support for specifying paths to operate on,
7+
rather than just the root of the target:
8+
```
9+
- type: org.osbuild.selinux
10+
options:
11+
file_contexts: etc/selinux/targeted/contexts/files/file_contexts
12+
target: mount://root/path/to/dir
13+
mounts:
14+
- name: root
15+
source: disk
16+
target: /
17+
```
18+
19+
or
20+
21+
```
22+
- type: org.osbuild.selinux
23+
options:
24+
labels:
25+
mount://root/path/to/file: system_u:object_r:boot_t:s0
26+
mount://root/path/to/other/file: system_u:object_r:var_t:s0
27+
mounts:
28+
- name: root
29+
source: disk
30+
target: /
31+
32+
```
33+
---
34+
stages/org.osbuild.selinux | 21 ++++++++++++---------
35+
stages/org.osbuild.selinux.meta.json | 17 ++++++++++++++++-
36+
2 files changed, 28 insertions(+), 10 deletions(-)
37+
38+
diff --git a/stages/org.osbuild.selinux b/stages/org.osbuild.selinux
39+
index 563d827b..40487599 100755
40+
--- a/stages/org.osbuild.selinux
41+
+++ b/stages/org.osbuild.selinux
42+
@@ -4,26 +4,30 @@ import pathlib
43+
import sys
44+
45+
import osbuild.api
46+
-from osbuild.util import selinux
47+
+from osbuild.util import parsing, selinux
48+
49+
50+
-def main(tree, options):
51+
+def main(args):
52+
+ # Get the path where the tree is
53+
+ options = args["options"]
54+
file_contexts = options.get("file_contexts")
55+
exclude_paths = options.get("exclude_paths")
56+
+ target = options.get("target", "tree:///")
57+
+ root, target = parsing.parse_location_into_parts(target, args)
58+
59+
if file_contexts:
60+
- file_contexts = os.path.join(f"{tree}", options["file_contexts"])
61+
+ file_contexts = os.path.join(args["tree"], options["file_contexts"])
62+
if exclude_paths:
63+
- exclude_paths = [os.path.join(tree, p.lstrip("/")) for p in exclude_paths]
64+
- selinux.setfiles(file_contexts, os.fspath(tree), "", exclude_paths=exclude_paths)
65+
+ exclude_paths = [os.path.normpath(f"{root}/{target}/{p}") for p in exclude_paths]
66+
+ selinux.setfiles(file_contexts, os.path.normpath(root), target, exclude_paths=exclude_paths)
67+
68+
labels = options.get("labels", {})
69+
for path, label in labels.items():
70+
- fullpath = os.path.join(tree, path.lstrip("/"))
71+
+ fullpath = parsing.parse_location(path, args)
72+
selinux.setfilecon(fullpath, label)
73+
74+
if options.get("force_autorelabel", False):
75+
- stamp = pathlib.Path(tree, ".autorelabel")
76+
+ stamp = pathlib.Path(root, ".autorelabel")
77+
# Creating just empty /.autorelabel resets only the type of files.
78+
# To ensure that the full context is reset, we write "-F" into the file.
79+
# This mimics the behavior of `fixfiles -F boot`. The "-F" option is
80+
@@ -34,6 +38,5 @@ def main(tree, options):
81+
82+
83+
if __name__ == '__main__':
84+
- args = osbuild.api.arguments()
85+
- r = main(args["tree"], args["options"])
86+
+ r = main(osbuild.api.arguments())
87+
sys.exit(r)
88+
diff --git a/stages/org.osbuild.selinux.meta.json b/stages/org.osbuild.selinux.meta.json
89+
index 30dbddae..87b13e59 100644
90+
--- a/stages/org.osbuild.selinux.meta.json
91+
+++ b/stages/org.osbuild.selinux.meta.json
92+
@@ -33,6 +33,21 @@
93+
}
94+
],
95+
"properties": {
96+
+ "target": {
97+
+ "oneOf": [
98+
+ {
99+
+ "type": "string",
100+
+ "description": "Target path, if a mount",
101+
+ "pattern": "^mount://.+"
102+
+ },
103+
+ {
104+
+ "type": "string",
105+
+ "description": "Target path, if a tree",
106+
+ "pattern": "^tree://.+"
107+
+ }
108+
+ ],
109+
+ "default": "tree:///"
110+
+ },
111+
"file_contexts": {
112+
"type": "string",
113+
"description": "Path to the active SELinux policy's `file_contexts`"
114+
@@ -53,7 +68,7 @@
115+
},
116+
"force_autorelabel": {
117+
"type": "boolean",
118+
- "description": "Do not use. Forces auto-relabelling on first boot.",
119+
+ "description": "Do not use. Forces auto-relabelling on first boot. Affects target's root or tree:/// by default",
120+
"default": false
121+
}
122+
}
123+
--
124+
2.47.0
125+

0 commit comments

Comments
 (0)