summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2021-09-16 13:51:30 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-09-17 07:26:23 +0100
commit626e949292a4d21cc828fcc6c8d5f62a93622f61 (patch)
tree6fd99b86288728fe149b242da990aba50c5d8cea
parent6b520611235673c9223609676a70d3cf5f6d4744 (diff)
downloadpoky-626e949292a4d21cc828fcc6c8d5f62a93622f61.tar.gz
bitbake: fetch2/git: Avoid races over mirror tarball creation
There is a potential race over the mirror tarballs where a partial git repo could be extracted causing fetcher failures if the tarball is being rewritten whilst another build accesses it. Create the mirror tarball atomically to avoid this. [YOCTO #14441] (Bitbake rev: 3250bc950c56bd7dd2114df26e5a8e13b04ceac8) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/fetch2/git.py21
1 files changed, 19 insertions, 2 deletions
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
index 488f4c7414..3643a491d7 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -68,6 +68,7 @@ import subprocess
68import tempfile 68import tempfile
69import bb 69import bb
70import bb.progress 70import bb.progress
71from contextlib import contextmanager
71from bb.fetch2 import FetchMethod 72from bb.fetch2 import FetchMethod
72from bb.fetch2 import runfetchcmd 73from bb.fetch2 import runfetchcmd
73from bb.fetch2 import logger 74from bb.fetch2 import logger
@@ -418,6 +419,20 @@ class Git(FetchMethod):
418 bb.utils.remove(tmpdir, recurse=True) 419 bb.utils.remove(tmpdir, recurse=True)
419 420
420 def build_mirror_data(self, ud, d): 421 def build_mirror_data(self, ud, d):
422
423 # Create as a temp file and move atomically into position to avoid races
424 @contextmanager
425 def create_atomic(filename, d):
426 fd, tfile = tempfile.mkstemp(dir=os.path.dirname(filename))
427 try:
428 yield tfile
429 umask = os.umask(0o666)
430 os.umask(umask)
431 os.chmod(tfile, (0o666 & ~umask))
432 runfetchcmd("mv %s %s" % (tfile, filename), d)
433 finally:
434 os.close(fd)
435
421 if ud.shallow and ud.write_shallow_tarballs: 436 if ud.shallow and ud.write_shallow_tarballs:
422 if not os.path.exists(ud.fullshallow): 437 if not os.path.exists(ud.fullshallow):
423 if os.path.islink(ud.fullshallow): 438 if os.path.islink(ud.fullshallow):
@@ -428,7 +443,8 @@ class Git(FetchMethod):
428 self.clone_shallow_local(ud, shallowclone, d) 443 self.clone_shallow_local(ud, shallowclone, d)
429 444
430 logger.info("Creating tarball of git repository") 445 logger.info("Creating tarball of git repository")
431 runfetchcmd("tar -czf %s ." % ud.fullshallow, d, workdir=shallowclone) 446 with create_atomic(ud.fullshallow, d) as tfile:
447 runfetchcmd("tar -czf %s ." % tfile, d, workdir=shallowclone)
432 runfetchcmd("touch %s.done" % ud.fullshallow, d) 448 runfetchcmd("touch %s.done" % ud.fullshallow, d)
433 finally: 449 finally:
434 bb.utils.remove(tempdir, recurse=True) 450 bb.utils.remove(tempdir, recurse=True)
@@ -437,7 +453,8 @@ class Git(FetchMethod):
437 os.unlink(ud.fullmirror) 453 os.unlink(ud.fullmirror)
438 454
439 logger.info("Creating tarball of git repository") 455 logger.info("Creating tarball of git repository")
440 runfetchcmd("tar -czf %s ." % ud.fullmirror, d, workdir=ud.clonedir) 456 with create_atomic(ud.fullmirror, d) as tfile:
457 runfetchcmd("tar -czf %s ." % tfile, d, workdir=ud.clonedir)
441 runfetchcmd("touch %s.done" % ud.fullmirror, d) 458 runfetchcmd("touch %s.done" % ud.fullmirror, d)
442 459
443 def clone_shallow_local(self, ud, dest, d): 460 def clone_shallow_local(self, ud, dest, d):