CVE-2021-27138 (C, published 2021-02-17T23:15Z)
Description: value: The boot loader in Das U-Boot before 2021.04-rc2 mishandles use of unit addresses in a FIT.
Severity: MEDIUM (CVSS v3 base score: 7.8)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/u-boot/u-boot
Files changed:
common/image-fit-sig.c
common/image-fit.c
test/py/tests/test_fit.py
test/py/tests/vboot_forge.py
Commit message: fit: Don't allow verification of images with @ nodes

When searching for a node called 'fred', any unit address appended to the
name is ignored by libfdt, meaning that 'fred' can match 'fred@1'. This
means that we cannot be sure that the node originally intended is the one
that is used.

Disallow use of nodes with unit addresses.

Update the forge test also, since it uses @ addresses.

CVE-2021-27138

Signed-off-by: Simon Glass <sjg@chromium.org>
Reported-by: Bruce Monroe <bruce.monroe@intel.com>
Reported-by: Arie Haenel <arie.haenel@intel.com>
Reported-by: Julien Lenoir <julien.lenoir@intel.com>


Vulnerable code:
int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
				    const void *sig_blob)
	int		noffset = 0;
		printf("error!\n%s for '%s' hash node in '%s' image node\n",
		       err_msg, fit_get_name(fit, noffset, NULL),
		       fit_get_name(fit, image_noffset, NULL));
		return 0;
                kernel@1 {
                kernel@2 {
                fdt@1 {
                        signature@1 {
                ramdisk@1 {
                ramdisk@2 {
                default = "conf@1";
                conf@1 {
                        kernel = "kernel@1";
                        fdt = "fdt@1";
            params['ramdisk_config'] = 'ramdisk = "ramdisk@1";'
            params['loadables_config'] = 'loadables = "kernel@2", "ramdisk@2";'
    # locate /images/kernel@1 (frankly, it just expects it to be the first one)
    fake_kernel.name = b'kernel@2'
    root[1].props[0].value = b'conf@2\x00'
    fake_conf.name = b'conf@2'
    fake_conf.props[0].value = b'kernel@2\x00'
    fake_conf.props[1].value = b'fdt@1\x00'

Fixed code:
		/*
		 * We don't support this since libfdt considers names with the
		 * name root but different @ suffix to be equal
		 */
		if (strchr(name, '@')) {
			err_msg = "Node name contains @";
			goto error;
		}
static int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
					   const void *sig_blob)
	const char *name = fit_get_name(fit, conf_noffset, NULL);
	/*
	 * We don't support this since libfdt considers names with the
	 * name root but different @ suffix to be equal
	 */
	if (strchr(name, '@')) {
		printf("Configuration node '%s' contains '@'\n", name);
		return -EPERM;
	}

	const char *name = fit_get_name(fit, image_noffset, NULL);
	if (strchr(name, '@')) {
		/*
		 * We don't support this since libfdt considers names with the
		 * name root but different @ suffix to be equal
		 */
		err_msg = "Node name contains @";
		goto err;
	}
		goto err;

err:
	printf("error!\n%s in '%s' image node\n", err_msg,
	       fit_get_name(fit, image_noffset, NULL));
	return 0;
                kernel-1 {
                kernel-2 {
                fdt-1 {
                        signature-1 {
                ramdisk-1 {
                ramdisk-2 {
                default = "conf-1";
                conf-1 {
                        kernel = "kernel-1";
                        fdt = "fdt-1";
            params['ramdisk_config'] = 'ramdisk = "ramdisk-1";'
            params['loadables_config'] = 'loadables = "kernel-2", "ramdisk-2";'
    # locate /images/kernel-1 (frankly, it just expects it to be the first one)
    fake_kernel.name = b'kernel-2'
    root[1].props[0].value = b'conf-2\x00'
    fake_conf.name = b'conf-2'
    fake_conf.props[0].value = b'kernel-2\x00'
    fake_conf.props[1].value = b'fdt-1\x00'