1
0
Fork 0

bootloader: initrd can be generated from the /tmp

This fixes regression introduced by 74c3d35d7a.
Added safety check, that the custom directory from which the initrd is
generated has to owned by the same user who is running the TuneD.
Also dropped redundant "error:" prefix from some related error messages.

Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com>
This commit is contained in:
Jaroslav Škarvada 2026-05-06 22:52:38 +02:00
parent 5624a6168b
commit 5855a79eba
No known key found for this signature in database
GPG key ID: D8E1C00E076E840B
3 changed files with 34 additions and 7 deletions

View file

@ -26,6 +26,7 @@ PLUGIN_VARIABLES_UNIT_NAME = "variables"
MAGIC_HEADER_NAME = "this_is_some_magic_section_header_because_of_compatibility"
RECOMMEND_DIRECTORIES = ["/usr/lib/tuned/recommend.d", "/etc/tuned/recommend.d"]
TMP_DIR = "/tmp"
TMP_FILE_SUFFIX = ".tmp"
# max. number of consecutive errors to give up
ERROR_THRESHOLD = 3

View file

@ -213,11 +213,22 @@ class Plugin(object):
def _instance_post_static(self, instance, enabling):
pass
def _safe_script_path(self, path):
def _safe_script_path(self, path, tmp_allowed = False):
"""
Checks if the path is within profile directories or TMP directory.
TMP directory is configured in the consts.py.
:param path: the path to check
:param tmp_allowed: optional parameter, default False, True allows paths within TMP
:returns: True if the path is OK
"""
path = os.path.realpath(path)
# os.path.join() to add trailing slash
if tmp_allowed and path.startswith(os.path.join(consts.TMP_DIR, "")):
return True
profile_paths = self._global_cfg.get_list(consts.CFG_PROFILE_DIRS, consts.CFG_DEF_PROFILE_DIRS)
for p in profile_paths:
if path.startswith(p):
if path.startswith(os.path.join(p, "")):
return True
return False

View file

@ -134,7 +134,12 @@ class BootloaderPlugin(base.Plugin):
If the `DIR` directory name begins with '/', the absolute path
is used. Otherwise, the current profile directory is used as the
base directory for the `DIR`. For safety reasons, `DIR` has to be
a subdirectory within the defined profile directories.
a subdirectory within the defined profile directories or within the
`TMP` directory (`TMP` directory is configured in the consts.py)
and owned by the same user who is running the TuneD process.
If `TMP` directory is used be careful about possible security concerns,
because `TMP` is usually writeable by any user. See e.g. the
`cpu-partitioning` profile for inspiration how to handle it securely.
The [option]`initrd_dst_img=PATHNAME` sets the name and location of
the resulting initrd image. Typically, it is not necessary to use this
@ -594,16 +599,26 @@ class BootloaderPlugin(base.Plugin):
if src_dir == "":
return False
if not os.path.isdir(src_dir):
log.error("error: cannot create initrd image, source directory '%s' doesn't exist" % src_dir)
log.error("cannot create initrd image, source directory '%s' doesn't exist" % src_dir)
return False
if not self._safe_script_path(src_dir):
log.error("error: paths outside of the profile directories cannot be used: '%s'" % src_dir)
if not self._safe_script_path(src_dir, tmp_allowed = True):
log.error("paths outside of the profile directories or '%s' cannot be used, path: '%s'"
% (consts.TMP_DIR, src_dir))
return False
try:
euid = os.geteuid()
fuid = os.stat(src_dir).st_uid
if euid != fuid:
log.error("directory '%s' to be included in the initrd is owned by UID '%d' which is different "
"from the TuneD process EUID '%d', it is suspicious, initrd will not be created" % (src_dir, fuid, euid))
return False
except (FileNotFoundError, PermissionError) as e:
log.error("unable to stat directory '%s': '%s'" % (src_dir, e))
try:
os.chmod(src_dir, 0o755)
log.debug("setting permissions of directory '%s'" % src_dir)
except Exception as e:
log.error("error: failed to change permissions of directory '%s': %s" % (src_dir, e))
log.error("failed to change permissions of directory '%s': %s" % (src_dir, e))
return False
log.info("generating initrd image from directory '%s'" % src_dir)