Skip to content

Commit 8ac66c1

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 10e397b commit 8ac66c1

10 files changed

+724
-45
lines changed

build.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ 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-
patch -d /usr/lib/osbuild -p1 < /usr/lib/coreos-assembler/0001-hacks-for-coreos-selinux-issues.patch
176+
cat /usr/lib/coreos-assembler/0001-parsing-add-parse_location_into_parts.patch \
177+
/usr/lib/coreos-assembler/0002-parsing-treat-locations-without-scheme-as-belonging-.patch \
178+
/usr/lib/coreos-assembler/0003-org.osbuild.selinux-support-operating-on-mounts.patch \
179+
/usr/lib/coreos-assembler/0004-org.osbuild.selinux-support-for-specifying-where-fil.patch \
180+
| patch -d /usr/lib/osbuild -p1
177181

178182
# And then move the files back; supermin appliance creation will need it back
179183
# 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 077244e3b9f4a3ba46244a1b3e056cb70609e265 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: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
From 6a59e740e4ccb761f9d87c2c6f837fa748908a90 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 | 6 +++++-
9+
stages/org.osbuild.mkdir | 9 +++------
10+
2 files changed, 8 insertions(+), 7 deletions(-)
11+
12+
diff --git a/osbuild/util/parsing.py b/osbuild/util/parsing.py
13+
index f75ffd67..d6d16f22 100644
14+
--- a/osbuild/util/parsing.py
15+
+++ b/osbuild/util/parsing.py
16+
@@ -77,11 +77,15 @@ def parse_location_into_parts(location: str, args: Dict) -> Tuple[str, str]:
17+
Parses the location URL to derive the corresponding root and url path.
18+
19+
Parameters:
20+
- - location (str): The location URL to be parsed.
21+
+ - location (str): The location URL to be parsed. If the URL has no scheme,
22+
+ then 'tree://' is implied
23+
- args (Dict): A dictionary containing arguments including mounts and
24+
path information as passed by osbuild.api.arguments()
25+
"""
26+
27+
+ if "://" not in location:
28+
+ location = f"tree://{location}"
29+
+
30+
url = urlparse(location)
31+
32+
scheme = url.scheme
33+
diff --git a/stages/org.osbuild.mkdir b/stages/org.osbuild.mkdir
34+
index d2d11a7a..01f5f431 100755
35+
--- a/stages/org.osbuild.mkdir
36+
+++ b/stages/org.osbuild.mkdir
37+
@@ -15,12 +15,9 @@ def main(args):
38+
parents = item.get("parents", False)
39+
exist_ok = item.get("exist_ok", False)
40+
41+
- if "://" not in path:
42+
- if not path.startswith("/"):
43+
- print("WARNING: relative path used, this is discouraged!")
44+
- path = f"tree:///{path}"
45+
- else:
46+
- path = f"tree://{path}"
47+
+ if "://" not in path and not path.startswith("/"):
48+
+ print("WARNING: relative path used, this is discouraged!")
49+
+ path = f"tree:///{path}"
50+
51+
target = parsing.parse_location(path, args)
52+
if parents:
53+
--
54+
2.47.0
55+
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
From 84d4de577057f66e1ad1c8e91631c441c0294532 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 | 8 +++++++-
36+
2 files changed, 19 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..e536cead 100644
90+
--- a/stages/org.osbuild.selinux.meta.json
91+
+++ b/stages/org.osbuild.selinux.meta.json
92+
@@ -33,6 +33,12 @@
93+
}
94+
],
95+
"properties": {
96+
+ "target": {
97+
+ "type": "string",
98+
+ "description": "Target path in the tree or on a mount",
99+
+ "pattern": "^mount://[^/]+/|^tree:///",
100+
+ "default": "tree:///"
101+
+ },
102+
"file_contexts": {
103+
"type": "string",
104+
"description": "Path to the active SELinux policy's `file_contexts`"
105+
@@ -53,7 +59,7 @@
106+
},
107+
"force_autorelabel": {
108+
"type": "boolean",
109+
- "description": "Do not use. Forces auto-relabelling on first boot.",
110+
+ "description": "Do not use. Forces auto-relabelling on first boot. Affects target's root or tree:/// by default",
111+
"default": false
112+
}
113+
}
114+
--
115+
2.47.0
116+
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
From a8e8ebde4400e94036df35f72b08708f00bd4ffe Mon Sep 17 00:00:00 2001
2+
From: Nikita Dubrovskii <[email protected]>
3+
Date: Fri, 18 Oct 2024 17:04:07 +0200
4+
Subject: [PATCH 4/4] org.osbuild.selinux: support for specifying where
5+
file_contexts comes from
6+
7+
file_context now can come from
8+
- tree (current default)
9+
- mount
10+
- input
11+
12+
Example:
13+
```
14+
- type: org.osbuild.selinux
15+
inputs:
16+
tree:
17+
type: org.osbuild.tree
18+
origin: org.osbuild.pipeline
19+
references:
20+
- name:tree
21+
options:
22+
file_contexts: input://tree/etc/selinux/targeted/contexts/files/file_contexts
23+
```
24+
---
25+
stages/org.osbuild.selinux | 6 +++++-
26+
stages/org.osbuild.selinux.meta.json | 12 ++++++++----
27+
2 files changed, 13 insertions(+), 5 deletions(-)
28+
29+
diff --git a/stages/org.osbuild.selinux b/stages/org.osbuild.selinux
30+
index 40487599..8e25a281 100755
31+
--- a/stages/org.osbuild.selinux
32+
+++ b/stages/org.osbuild.selinux
33+
@@ -9,6 +9,7 @@ from osbuild.util import parsing, selinux
34+
35+
def main(args):
36+
# Get the path where the tree is
37+
+ tree = args["tree"]
38+
options = args["options"]
39+
file_contexts = options.get("file_contexts")
40+
exclude_paths = options.get("exclude_paths")
41+
@@ -16,7 +17,10 @@ def main(args):
42+
root, target = parsing.parse_location_into_parts(target, args)
43+
44+
if file_contexts:
45+
- file_contexts = os.path.join(args["tree"], options["file_contexts"])
46+
+ if "://" not in file_contexts:
47+
+ file_contexts = os.path.normpath(f"{tree}/{file_contexts}")
48+
+ else:
49+
+ file_contexts = parsing.parse_location(file_contexts, args)
50+
if exclude_paths:
51+
exclude_paths = [os.path.normpath(f"{root}/{target}/{p}") for p in exclude_paths]
52+
selinux.setfiles(file_contexts, os.path.normpath(root), target, exclude_paths=exclude_paths)
53+
diff --git a/stages/org.osbuild.selinux.meta.json b/stages/org.osbuild.selinux.meta.json
54+
index e536cead..9a9d7bb1 100644
55+
--- a/stages/org.osbuild.selinux.meta.json
56+
+++ b/stages/org.osbuild.selinux.meta.json
57+
@@ -1,8 +1,8 @@
58+
{
59+
"summary": "Set SELinux file contexts",
60+
"description": [
61+
- "Sets correct SELinux labels for every file in the tree, according to the",
62+
- "SELinux policy installed inside the tree.",
63+
+ "Sets correct SELinux labels for every file in the tree or on mount, according to",
64+
+ "the SELinux policy.",
65+
"Uses the host's `setfiles` program and the tree's `file_contexts`, usually",
66+
" /etc/selinux/<SELINUXTYPE>/contexts/files/file_contexts",
67+
"where <SELINUXTYPE> is the value set in /etc/selinux/config (usually \"targeted\"",
68+
@@ -40,8 +40,8 @@
69+
"default": "tree:///"
70+
},
71+
"file_contexts": {
72+
- "type": "string",
73+
- "description": "Path to the active SELinux policy's `file_contexts`"
74+
+ "description": "Path to the active SELinux policy's `file_contexts`. Supports `tree://`, `mount://`, and `input://` schemes. Plain paths imply `tree://`.",
75+
+ "type": "string"
76+
},
77+
"exclude_paths": {
78+
"type": "array",
79+
@@ -70,6 +70,10 @@
80+
},
81+
"mounts": {
82+
"type": "array"
83+
+ },
84+
+ "inputs": {
85+
+ "type": "object",
86+
+ "additionalProperties": true
87+
}
88+
}
89+
}
90+
--
91+
2.47.0
92+

0 commit comments

Comments
 (0)