bitbake: hashserv: validate unihash values

(Bitbake rev: a4daa14312d659333984aa1ae58ddfe0c96392f1)

Signed-off-by: Anders Heimer <anders.heimer@est.tech>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit f9b817d8017e5d5a1d22b9aa10a3c974bc7fa33d)
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
Anders Heimer
2026-06-05 06:58:26 +02:00
committed by Paul Barker
parent d47ac87fb6
commit d80ddd7b90
5 changed files with 115 additions and 6 deletions

View File

@@ -43,6 +43,10 @@ def check_siggen_version(siggen):
if siggen.find_siginfo_version < siggen.find_siginfo_minversion:
bb.fatal("Siggen from metadata (OE-Core?) is too old, please update it (%s vs %s)" % (siggen.find_siginfo_version, siggen.find_siginfo_minversion))
def check_hashserv_unihash(unihash):
if not hashserv.is_valid_unihash(unihash):
bb.fatal("Hash Equivalence Server returned invalid unihash")
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set) or isinstance(obj, frozenset):
@@ -753,6 +757,7 @@ class SignatureGeneratorUniHashMixIn(object):
# the unique hash.
taskhash = self.taskhash[tid]
if unihash:
check_hashserv_unihash(unihash)
# A unique hash equal to the taskhash is not very interesting,
# so it is reported it at debug level 2. If they differ, that
# is much more interesting, so it is reported at debug level 1
@@ -772,7 +777,7 @@ class SignatureGeneratorUniHashMixIn(object):
import importlib
taskhash = d.getVar('BB_TASKHASH')
unihash = d.getVar('BB_UNIHASH')
unihash = d.getVar('BB_UNIHASH', expand=False)
report_taskdata = d.getVar('SSTATE_HASHEQUIV_REPORT_TASKDATA') == '1'
tempdir = d.getVar('T')
mcfn = d.getVar('BB_FILENAME')
@@ -834,6 +839,7 @@ class SignatureGeneratorUniHashMixIn(object):
data = client.report_unihash(taskhash, method, outhash, unihash, extra_data)
new_unihash = data['unihash']
check_hashserv_unihash(new_unihash)
if new_unihash != unihash:
hashequiv_logger.debug('Task %s unihash changed %s -> %s by server %s' % (taskhash, unihash, new_unihash, self.server))
@@ -873,6 +879,7 @@ class SignatureGeneratorUniHashMixIn(object):
return False
finalunihash = data['unihash']
check_hashserv_unihash(finalunihash)
if finalunihash == current_unihash:
hashequiv_logger.verbose('Task %s unihash %s unchanged by server' % (tid, finalunihash))

View File

@@ -9,7 +9,9 @@
import unittest
import logging
import bb
import bb.data
import time
from contextlib import contextmanager
logger = logging.getLogger('BitBake.TestSiggen')
@@ -26,3 +28,49 @@ class SiggenTest(unittest.TestCase):
for t in tests:
self.assertEqual(bb.siggen.build_pnid(*t), tests[t])
def test_get_unihashes_rejects_invalid_hashserv_unihash(self):
class TestClient:
def get_unihash_batch(self, query):
list(query)
return ["${@os.system('true')}"]
class TestSiggen(bb.siggen.SignatureGeneratorUniHashMixIn):
def __init__(self):
self.server = "test-server"
self.method = "test-method"
self.extramethod = {}
self.taskhash = {"test.bb:do_compile": "a" * 64}
self.unihash = {}
self.unitaskhashes = {}
self.tidtopn = {}
self.setscenetasks = set()
self.max_parallel = 1
@contextmanager
def client(self):
yield TestClient()
siggen = TestSiggen()
with self.assertRaises(bb.BBHandledException):
siggen.get_unihashes(["test.bb:do_compile"])
self.assertEqual(siggen.unihash, {})
self.assertEqual(siggen.unitaskhashes, {})
def test_report_unihash_reads_bb_unihash_without_expansion(self):
class TestSiggen(bb.siggen.SignatureGeneratorUniHashMixIn):
def __init__(self):
self.setscenetasks = set()
self.taskhash = {"test.bb:do_compile": "b" * 64}
d = bb.data.init()
d.setVar("BB_TASKHASH", "a" * 64)
d.setVar("BB_UNIHASH", "${@d.setVar('EXPANDED_UNIHASH', '1') or 'bad'}")
d.setVar("SSTATE_HASHEQUIV_REPORT_TASKDATA", "0")
d.setVar("T", "/tmp")
d.setVar("BB_FILENAME", "test.bb")
TestSiggen().report_unihash(".", "compile", d)
self.assertIsNone(d.getVar("EXPANDED_UNIHASH"))