@@ -100,7 +100,14 @@ def _write(self, file_name: Union[Path, str], contents: list[str], chmod_mask=0o
100100 self .logger .debug ("[%s] Set file permissions: %s" % (file_path , chmod_mask ))
101101
102102 def _copy (self , source : Union [Path , str ], dest = None ) -> None :
103- """Copies a file into the initramfs build directory."""
103+ """Copies a file into the initramfs build directory.
104+ If a destination is not provided, the source is used, under the build directory.
105+
106+ If the destination parent is a symlink, the symlink is resolved.
107+ Crates parent directories if they do not exist
108+
109+ Raises a RuntimeError if the destination path is not within the build directory.
110+ """
104111 from shutil import copy2
105112
106113 if not isinstance (source , Path ):
@@ -111,10 +118,12 @@ def _copy(self, source: Union[Path, str], dest=None) -> None:
111118 dest = source
112119
113120 dest_path = self ._get_build_path (dest )
121+ build_base = self ._get_build_path ("/" )
114122
115123 while dest_path .parent .is_symlink ():
116- self .logger .debug ("Resolving symlink: %s" % dest_path .parent )
117- dest_path = self ._get_build_path (dest_path .parent .resolve () / dest_path .name )
124+ resolved_path = dest_path .parent .resolve () / dest_path .name
125+ self .logger .debug ("Resolved symlink: %s -> %s" % (dest_path .parent , resolved_path ))
126+ dest_path = self ._get_build_path (resolved_path )
118127
119128 if not dest_path .parent .is_dir ():
120129 self .logger .debug ("Parent directory for '%s' does not exist: %s" % (dest_path .name , dest_path .parent ))
@@ -126,6 +135,11 @@ def _copy(self, source: Union[Path, str], dest=None) -> None:
126135 self .logger .debug ("Destination is a directory, adding source filename: %s" % source .name )
127136 dest_path = dest_path / source .name
128137
138+ try : # Ensure the target is in the build directory
139+ dest_path .relative_to (build_base )
140+ except ValueError as e :
141+ raise RuntimeError ("Destination path is not within the build directory: %s" % dest_path ) from e
142+
129143 self .logger .log (self ["_build_log_level" ], "Copying '%s' to '%s'" % (source , dest_path ))
130144 copy2 (source , dest_path )
131145
@@ -144,7 +158,7 @@ def _symlink(self, source: Union[Path, str], target: Union[Path, str]) -> None:
144158 target = self ._get_build_path (target )
145159
146160 while target .parent .is_symlink ():
147- self .logger .debug ("Resolving target symlink: %s" % target .parent )
161+ self .logger .debug ("Resolving target parent symlink: %s" % target .parent )
148162 target = self ._get_build_path (target .parent .resolve () / target .name )
149163
150164 if not target .parent .is_dir ():
@@ -153,9 +167,9 @@ def _symlink(self, source: Union[Path, str], target: Union[Path, str]) -> None:
153167
154168 build_source = self ._get_build_path (source )
155169 while build_source .parent .is_symlink ():
156- self .logger .debug ("Resolving source symlink: %s" % build_source .parent )
170+ self .logger .debug ("Resolving source parent symlink: %s" % build_source .parent )
157171 build_source = self ._get_build_path (build_source .parent .resolve () / build_source .name )
158- source = build_source .relative_to (self ._get_build_path ("/" ))
172+ source = build_source .relative_to (self ._get_build_path ("/" ))
159173
160174 if target .is_symlink ():
161175 if target .resolve () == source :
0 commit comments