[lxc-devel] [distrobuilder/master] Fix checksum check

monstermunchkin on Github lxc-bot at linuxcontainers.org
Tue May 19 09:48:29 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 310 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200519/5ef688bd/attachment.bin>
-------------- next part --------------
From 4a449714dae975dc49ebe1db2c34b76c15a047d4 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 19 May 2020 11:38:00 +0200
Subject: [PATCH 1/2] shared: Handle multiple checksums

Gentoo provides multiple hashes (BLAKE2B and SHA512) for the same file.
Instead of failing on the first mismatch, we need to check all
checksums.

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 shared/net.go  | 27 ++++++++++++++++++---------
 shared/util.go | 23 ++++++++++++++++++-----
 2 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/shared/net.go b/shared/net.go
index 408425e..8ac9081 100644
--- a/shared/net.go
+++ b/shared/net.go
@@ -20,6 +20,7 @@ import (
 func DownloadHash(def DefinitionImage, file, checksum string, hashFunc hash.Hash) (string, error) {
 	var (
 		client http.Client
+		hashes []string
 		hash   string
 		err    error
 	)
@@ -40,7 +41,7 @@ func DownloadHash(def DefinitionImage, file, checksum string, hashFunc hash.Hash
 			hashLen = hashFunc.Size() * 2
 		}
 
-		hash, err = downloadChecksum(targetDir, checksum, file, hashFunc, hashLen)
+		hashes, err = downloadChecksum(targetDir, checksum, file, hashFunc, hashLen)
 		if err != nil {
 			return "", errors.Wrap(err, "Error while downloading checksum")
 		}
@@ -67,8 +68,16 @@ func DownloadHash(def DefinitionImage, file, checksum string, hashFunc hash.Hash
 			}
 
 			result := fmt.Sprintf("%x", hashFunc.Sum(nil))
-			if result != hash {
-				return "", fmt.Errorf("Hash mismatch for %s: %s != %s", imagePath, result, hash)
+
+			for _, h := range hashes {
+				if result == h {
+					hash = h
+					break
+				}
+			}
+
+			if hash == "" {
+				return "", fmt.Errorf("Hash mismatch for %s: %s != %v", imagePath, result, hashes)
 			}
 		}
 
@@ -103,7 +112,7 @@ func DownloadHash(def DefinitionImage, file, checksum string, hashFunc hash.Hash
 
 // downloadChecksum downloads or opens URL, and matches fname against the
 // checksums inside of the downloaded or opened file.
-func downloadChecksum(targetDir string, URL string, fname string, hashFunc hash.Hash, hashLen int) (string, error) {
+func downloadChecksum(targetDir string, URL string, fname string, hashFunc hash.Hash, hashLen int) ([]string, error) {
 	var (
 		client   http.Client
 		tempFile *os.File
@@ -115,29 +124,29 @@ func downloadChecksum(targetDir string, URL string, fname string, hashFunc hash.
 	if err == nil && !fi.IsDir() {
 		tempFile, err = os.Open(filepath.Join(targetDir, URL))
 		if err != nil {
-			return "", err
+			return nil, err
 		}
 		defer os.Remove(tempFile.Name())
 	} else {
 		tempFile, err = ioutil.TempFile(targetDir, "hash.")
 		if err != nil {
-			return "", err
+			return nil, err
 		}
 		defer os.Remove(tempFile.Name())
 
 		_, err = lxd.DownloadFileHash(&client, "", nil, nil, "", URL, "", hashFunc, tempFile)
 		// ignore hash mismatch
 		if err != nil && !strings.HasPrefix(err.Error(), "Hash mismatch") {
-			return "", err
+			return nil, err
 		}
 	}
 
 	tempFile.Seek(0, 0)
 
 	checksum := getChecksum(filepath.Base(fname), hashLen, tempFile)
-	if checksum != "" {
+	if checksum != nil {
 		return checksum, nil
 	}
 
-	return "", fmt.Errorf("Could not find checksum")
+	return nil, fmt.Errorf("Could not find checksum")
 }
diff --git a/shared/util.go b/shared/util.go
index 2b66c9f..abaf4d0 100644
--- a/shared/util.go
+++ b/shared/util.go
@@ -368,10 +368,11 @@ func GetTargetDir(def DefinitionImage) string {
 	return targetDir
 }
 
-func getChecksum(fname string, hashLen int, r io.Reader) string {
+func getChecksum(fname string, hashLen int, r io.Reader) []string {
 	scanner := bufio.NewScanner(r)
 
 	var matches []string
+	var result []string
 
 	for scanner.Scan() {
 		if !strings.Contains(scanner.Text(), fname) {
@@ -395,19 +396,27 @@ func getChecksum(fname string, hashLen int, r io.Reader) string {
 		fields := strings.Split(m, " ")
 
 		if strings.TrimSpace(fields[len(fields)-1]) == fname {
-			return strings.TrimSpace(fields[0])
+			result = append(result, strings.TrimSpace(fields[0]))
 		}
 	}
 
+	if len(result) > 0 {
+		return result
+	}
+
 	// Check common checksum file (pattern: "<hash> <filename>") which contains the filename
 	for _, m := range matches {
 		fields := strings.Split(m, " ")
 
 		if strings.Contains(strings.TrimSpace(fields[len(fields)-1]), fname) {
-			return strings.TrimSpace(fields[0])
+			result = append(result, strings.TrimSpace(fields[0]))
 		}
 	}
 
+	if len(result) > 0 {
+		return result
+	}
+
 	// Special case: CentOS
 	for _, m := range matches {
 		for _, s := range strings.Split(m, " ") {
@@ -417,10 +426,14 @@ func getChecksum(fname string, hashLen int, r io.Reader) string {
 			}
 
 			if hashLen == 0 || hashLen == len(strings.TrimSpace(s)) {
-				return s
+				result = append(result, s)
 			}
 		}
 	}
 
-	return ""
+	if len(result) > 0 {
+		return result
+	}
+
+	return nil
 }

From 6547ece1aba4a264973e81e911ec9156984baec6 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 19 May 2020 11:47:27 +0200
Subject: [PATCH 2/2] shared/util_test: Update checksum test

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 shared/util_test.go | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/shared/util_test.go b/shared/util_test.go
index 635605d..1c4f7f3 100644
--- a/shared/util_test.go
+++ b/shared/util_test.go
@@ -225,7 +225,7 @@ func Test_getChecksum(t *testing.T) {
 	tests := []struct {
 		name string
 		args args
-		want string
+		want []string
 	}{
 		{
 			"openwrt-x86-64-rootfs.tar.gz",
@@ -243,7 +243,7 @@ d99669ef301129e6ba59417ff41814dd02b4bdbe7254e2c8535de5eae35801ad *openwrt-sdk-x8
 3b961a97e3105e02e07c1aba7671186efe559ce0ac078c370d5082a7a6999dbe *openwrt-x86-64-generic-squashfs-rootfs.img.gz
 76cc26429a61a516d348735a8d62bf3885d9d37489f20789a77c879dcf8a1025 *openwrt-x86-64-rootfs.tar.gz`),
 			},
-			"76cc26429a61a516d348735a8d62bf3885d9d37489f20789a77c879dcf8a1025",
+			[]string{"76cc26429a61a516d348735a8d62bf3885d9d37489f20789a77c879dcf8a1025"},
 		},
 		{
 			"stage3-ppc64le-20200414T103003Z.tar.xz",
@@ -259,7 +259,7 @@ e4b9cb10146502310cbedf14197afa9e94b75f7d59c1c6977bff23bac529e9114e3fddb155cfcad9
 # SHA512 HASH
 1047f97cbb209fb22d372dffe4461722b5eaf936fc73546a8f036dc52a5d20433921d367288b28b3de5154cad1253b40d32233104c2be45732ebfa413bd9b09b  stage3-ppc64le-20200414T103003Z.tar.xz.CONTENTS`),
 			},
-			"e4b9cb10146502310cbedf14197afa9e94b75f7d59c1c6977bff23bac529e9114e3fddb155cfcad9119e466a39f0fcd8d75354e5237da79c9289fe76ee77693d",
+			[]string{"e4b9cb10146502310cbedf14197afa9e94b75f7d59c1c6977bff23bac529e9114e3fddb155cfcad9119e466a39f0fcd8d75354e5237da79c9289fe76ee77693d"},
 		},
 		{
 			"CentOS-8-x86_64-1905-dvd1.iso",
@@ -291,7 +291,7 @@ RP3G/3Z1T3c=
 =HgZm
 -----END PGP SIGNATURE-----`),
 			},
-			"ea17ef71e0df3f6bf1d4bf1fc25bec1a76d1f211c115d39618fe688be34503e8",
+			[]string{"ea17ef71e0df3f6bf1d4bf1fc25bec1a76d1f211c115d39618fe688be34503e8"},
 		},
 
 		{
@@ -326,7 +326,26 @@ Z4iksZrx82g=
 =L746
 -----END PGP SIGNATURE-----`),
 			},
-			"9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d",
+			[]string{"9a2c47d97b9975452f7d582264e9fc16d108ed8252ac6816239a3b58cef5c53d"},
+		},
+		{
+			"stage3-ppc-20200518T100528Z.tar.xz",
+			args{
+				"stage3-ppc-20200518T100528Z.tar.xz",
+				128,
+				bytes.NewBufferString(`# BLAKE2B HASH
+				6298bdc913c83190f6aa5f7399f05f2f1a20b1997479f033a261fa2e8347fd7cee67900a761c47b7c1c8370127e58016dd90d58f2f37b7f0d5e16722ba0650d2  stage3-ppc-20200518T100528Z.tar.xz
+				# SHA512 HASH
+				2d0183b8151e4560c317c2903c330f9fbfe2cc37c02ee100a60c9f42253e3ac3ef6db341c177a5e7594131bdcbdebfabe73217c0d4dc86e4dc4d1ce59ad5fbe7  stage3-ppc-20200518T100528Z.tar.xz
+				# BLAKE2B HASH
+				f8aeda7504be4a1374cbd837703138880baf70f8b256ee9f1f2f90cea0b669de62b14112afd2302ff03b6b410cd84f7434a79af3cb197c896a8279ca3068cdfe  stage3-ppc-20200518T100528Z.tar.xz.CONTENTS.gz
+				# SHA512 HASH
+				3a7dede7bcb68a0a32310d1bfbdd8806a17a1720be30907a17673f5f303dee340f5ad9c99d25738fb6f65b5ec224786b7d6b3ecbd5f37185469fbf33ea4c8c92  stage3-ppc-20200518T100528Z.tar.xz.CONTENTS.gz`),
+			},
+			[]string{
+				"6298bdc913c83190f6aa5f7399f05f2f1a20b1997479f033a261fa2e8347fd7cee67900a761c47b7c1c8370127e58016dd90d58f2f37b7f0d5e16722ba0650d2",
+				"2d0183b8151e4560c317c2903c330f9fbfe2cc37c02ee100a60c9f42253e3ac3ef6db341c177a5e7594131bdcbdebfabe73217c0d4dc86e4dc4d1ce59ad5fbe7",
+			},
 		},
 	}
 


More information about the lxc-devel mailing list