summaryrefslogtreecommitdiffstats
path: root/meta/classes-global
diff options
context:
space:
mode:
authorTobias Hagelborn <tobias.hagelborn@axis.com>2024-02-05 15:03:34 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-02-18 07:34:42 +0000
commitf909d235c95d89bd44a7d3fc719adfc82cdc1d98 (patch)
treeab24c1d29bcae1bb5c98ff565077131061b22dcc /meta/classes-global
parenta277d1f7a0dc716b497fd855f20cbd6a7d488f8b (diff)
downloadpoky-f909d235c95d89bd44a7d3fc719adfc82cdc1d98.tar.gz
sstate.bbclass: Only sign packages at the time of their creation
The purpose of the change is to never sign a package not created by the build itself. sstate_create_package is refactored into Python and re-designed to handle signing inside the function. Thus, the signing should never apply to existing sstate packages. The function is therefore renamed into sstate_create_and_sign_package. The creation of the archive remains in a separate shellscript function. Co-authored-by: Peter Kjellerstedt <peter.kjellerstedt@axis.com> (From OE-Core rev: ba223f8fff19ea59440d56cf3fe46200f3f71e22) Signed-off-by: Tobias Hagelborn <tobias.hagelborn@axis.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes-global')
-rw-r--r--meta/classes-global/sstate.bbclass140
1 files changed, 94 insertions, 46 deletions
diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
index efe7f69775..96655ff24f 100644
--- a/meta/classes-global/sstate.bbclass
+++ b/meta/classes-global/sstate.bbclass
@@ -703,9 +703,7 @@ def sstate_package(ss, d):
703 if d.getVar('SSTATE_SKIP_CREATION') == '1': 703 if d.getVar('SSTATE_SKIP_CREATION') == '1':
704 return 704 return
705 705
706 sstate_create_package = ['sstate_report_unihash', 'sstate_create_pkgdirs', 'sstate_create_package'] 706 sstate_create_package = ['sstate_report_unihash', 'sstate_create_and_sign_package']
707 if d.getVar('SSTATE_SIG_KEY'):
708 sstate_create_package.append('sstate_sign_package')
709 707
710 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \ 708 for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \
711 sstate_create_package + \ 709 sstate_create_package + \
@@ -810,26 +808,100 @@ python sstate_task_postfunc () {
810} 808}
811sstate_task_postfunc[dirs] = "${WORKDIR}" 809sstate_task_postfunc[dirs] = "${WORKDIR}"
812 810
813python sstate_create_pkgdirs () { 811# Create a sstate package
814 # report_unihash can change SSTATE_PKG and mkdir -p in shell doesn't own intermediate directories 812# If enabled, sign the package.
815 # correctly so do this in an intermediate python task 813# Package and signature are created in a sub-directory
816 with bb.utils.umask(0o002): 814# and renamed in place once created.
817 bb.utils.mkdirhier(os.path.dirname(d.getVar('SSTATE_PKG'))) 815python sstate_create_and_sign_package () {
816 from pathlib import Path
817
818 # Best effort touch
819 def touch(file):
820 try:
821 file.touch()
822 except:
823 pass
824
825 def update_file(src, dst, force=False):
826 if dst.is_symlink() and not dst.exists():
827 force=True
828 try:
829 # This relies on that src is a temporary file that can be renamed
830 # or left as is.
831 if force:
832 src.rename(dst)
833 else:
834 os.link(src, dst)
835 return True
836 except:
837 pass
838
839 if dst.exists():
840 touch(dst)
841
842 return False
843
844 sign_pkg = (
845 bb.utils.to_boolean(d.getVar("SSTATE_VERIFY_SIG")) and
846 bool(d.getVar("SSTATE_SIG_KEY"))
847 )
848
849 sstate_pkg = Path(d.getVar("SSTATE_PKG"))
850 sstate_pkg_sig = Path(str(sstate_pkg) + ".sig")
851 if sign_pkg:
852 if sstate_pkg.exists() and sstate_pkg_sig.exists():
853 touch(sstate_pkg)
854 touch(sstate_pkg_sig)
855 return
856 else:
857 if sstate_pkg.exists():
858 touch(sstate_pkg)
859 return
860
861 # Create the required sstate directory if it is not present.
862 if not sstate_pkg.parent.is_dir():
863 with bb.utils.umask(0o002):
864 bb.utils.mkdirhier(str(sstate_pkg.parent))
865
866 if sign_pkg:
867 from tempfile import TemporaryDirectory
868 with TemporaryDirectory(dir=sstate_pkg.parent) as tmp_dir:
869 tmp_pkg = Path(tmp_dir) / sstate_pkg.name
870 d.setVar("TMP_SSTATE_PKG", str(tmp_pkg))
871 bb.build.exec_func('sstate_archive_package', d)
872
873 from oe.gpg_sign import get_signer
874 signer = get_signer(d, 'local')
875 signer.detach_sign(str(tmp_pkg), d.getVar('SSTATE_SIG_KEY'), None,
876 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
877
878 tmp_pkg_sig = Path(tmp_dir) / sstate_pkg_sig.name
879 if not update_file(tmp_pkg_sig, sstate_pkg_sig):
880 # If the created signature file could not be copied into place,
881 # then we should not use the sstate package either.
882 return
883
884 # If the .sig file was updated, then the sstate package must also
885 # be updated.
886 update_file(tmp_pkg, sstate_pkg, force=True)
887 else:
888 from tempfile import NamedTemporaryFile
889 with NamedTemporaryFile(prefix=sstate_pkg.name, dir=sstate_pkg.parent) as tmp_pkg_fd:
890 tmp_pkg = tmp_pkg_fd.name
891 d.setVar("TMP_SSTATE_PKG", str(tmp_pkg))
892 bb.build.exec_func('sstate_archive_package',d)
893 update_file(tmp_pkg, sstate_pkg)
894 # update_file() may have renamed tmp_pkg, which must exist when the
895 # NamedTemporaryFile() context handler ends.
896 touch(Path(tmp_pkg))
897
818} 898}
819 899
820#
821# Shell function to generate a sstate package from a directory 900# Shell function to generate a sstate package from a directory
822# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR. 901# set as SSTATE_BUILDDIR. Will be run from within SSTATE_BUILDDIR.
823# 902# The calling function handles moving the sstate package into the final
824sstate_create_package () { 903# destination.
825 # Exit early if it already exists 904sstate_archive_package () {
826 if [ -e ${SSTATE_PKG} ]; then
827 touch ${SSTATE_PKG} 2>/dev/null || true
828 return
829 fi
830
831 TFILE=`mktemp ${SSTATE_PKG}.XXXXXXXX`
832
833 OPT="-cS" 905 OPT="-cS"
834 ZSTD="zstd -${SSTATE_ZSTD_CLEVEL} -T${ZSTD_THREADS}" 906 ZSTD="zstd -${SSTATE_ZSTD_CLEVEL} -T${ZSTD_THREADS}"
835 # Use pzstd if available 907 # Use pzstd if available
@@ -840,42 +912,18 @@ sstate_create_package () {
840 # Need to handle empty directories 912 # Need to handle empty directories
841 if [ "$(ls -A)" ]; then 913 if [ "$(ls -A)" ]; then
842 set +e 914 set +e
843 tar -I "$ZSTD" $OPT -f $TFILE * 915 tar -I "$ZSTD" $OPT -f ${TMP_SSTATE_PKG} *
844 ret=$? 916 ret=$?
845 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then 917 if [ $ret -ne 0 ] && [ $ret -ne 1 ]; then
846 exit 1 918 exit 1
847 fi 919 fi
848 set -e 920 set -e
849 else 921 else
850 tar -I "$ZSTD" $OPT --file=$TFILE --files-from=/dev/null 922 tar -I "$ZSTD" $OPT --file=${TMP_SSTATE_PKG} --files-from=/dev/null
851 fi
852 chmod 0664 $TFILE
853 # Skip if it was already created by some other process
854 if [ -h ${SSTATE_PKG} ] && [ ! -e ${SSTATE_PKG} ]; then
855 # There is a symbolic link, but it links to nothing.
856 # Forcefully replace it with the new file.
857 ln -f $TFILE ${SSTATE_PKG} || true
858 elif [ ! -e ${SSTATE_PKG} ]; then
859 # Move into place using ln to attempt an atomic op.
860 # Abort if it already exists
861 ln $TFILE ${SSTATE_PKG} || true
862 else
863 touch ${SSTATE_PKG} 2>/dev/null || true
864 fi 923 fi
865 rm $TFILE 924 chmod 0664 ${TMP_SSTATE_PKG}
866} 925}
867 926
868python sstate_sign_package () {
869 from oe.gpg_sign import get_signer
870
871
872 signer = get_signer(d, 'local')
873 sstate_pkg = d.getVar('SSTATE_PKG')
874 if os.path.exists(sstate_pkg + '.sig'):
875 os.unlink(sstate_pkg + '.sig')
876 signer.detach_sign(sstate_pkg, d.getVar('SSTATE_SIG_KEY', False), None,
877 d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False)
878}
879 927
880python sstate_report_unihash() { 928python sstate_report_unihash() {
881 report_unihash = getattr(bb.parse.siggen, 'report_unihash', None) 929 report_unihash = getattr(bb.parse.siggen, 'report_unihash', None)