iSulad/0062-verify-name-and-digest-consistency.patch
zhongtao c36bc934aa !638 upgrade from upstream
* upgrade from upstream
2023-12-21 02:03:18 +00:00

320 lines
9.5 KiB
Diff

From 950dc3c56f192061383de4d19229ace243eae503 Mon Sep 17 00:00:00 2001
From: zhongtao <zhongtao17@huawei.com>
Date: Mon, 18 Dec 2023 15:54:37 +0800
Subject: [PATCH 62/64] verify name and digest consistency
Signed-off-by: zhongtao <zhongtao17@huawei.com>
---
.../oci/storage/image_store/image_store.c | 265 +++++++++++-------
1 file changed, 162 insertions(+), 103 deletions(-)
diff --git a/src/daemon/modules/image/oci/storage/image_store/image_store.c b/src/daemon/modules/image/oci/storage/image_store/image_store.c
index 58baa47a..1b482504 100644
--- a/src/daemon/modules/image/oci/storage/image_store/image_store.c
+++ b/src/daemon/modules/image/oci/storage/image_store/image_store.c
@@ -22,6 +22,7 @@
#include <isula_libutils/storage_image.h>
#include <isula_libutils/imagetool_images_list.h>
#include <isula_libutils/json_common.h>
+#include <isula_libutils/auto_cleanup.h>
#include <limits.h>
#include <pthread.h>
#include <stdlib.h>
@@ -444,11 +445,161 @@ out:
return value;
}
+static int resort_image_names(const char **names, size_t names_len, char **first_name, char ***image_tags,
+ char ***image_digests)
+{
+ int ret = 0;
+ size_t i;
+ char *prefix = NULL;
+
+ for (i = 0; i < names_len; i++) {
+ size_t len = strlen(names[i]);
+ if (strlen(names[i]) > MAX_IMAGE_NAME_LENGTH) {
+ prefix = util_sub_string(names[i], len - MAX_IMAGE_NAME_LENGTH,
+ MAX_IMAGE_NAME_LENGTH - MAX_IMAGE_DIGEST_LENGTH);
+ }
+
+ // TODO: maybe should support other digest
+ if (prefix != NULL && strcmp(prefix, DIGEST_PREFIX) == 0) {
+ if (util_array_append(image_digests, names[i]) != 0) {
+ ERROR("Failed to append image to digest: %s", names[i]);
+ ret = -1;
+ goto out;
+ }
+ } else {
+ if (util_array_append(image_tags, names[i]) != 0) {
+ ERROR("Failed to append image to tags: %s", names[i]);
+ ret = -1;
+ goto out;
+ }
+ }
+ }
+
+ if (first_name == NULL) {
+ goto out;
+ }
+
+ if (util_array_len((const char **)(*image_digests)) > 0) {
+ free(*first_name);
+ *first_name = util_strdup_s((*image_digests)[0]);
+ }
+
+ if (util_array_len((const char **)(*image_tags)) > 0) {
+ free(*first_name);
+ *first_name = util_strdup_s((*image_tags)[0]);
+ }
+
+out:
+ if (ret != 0) {
+ util_free_array(*image_digests);
+ util_free_array(*image_tags);
+ free(*first_name);
+ }
+ free(prefix);
+ return ret;
+}
+
+// Validate checks that the contents is a valid digest
+static bool validate_digest(const char *digest)
+{
+ bool ret = true;
+ const char *sha256_encode_patten = "^[a-f0-9]{64}$";
+ char *value = util_strdup_s(digest);
+ char *index = strchr(value, ':');
+ char *alg = NULL;
+ char *encode = NULL;
+
+ // contains ':' and is not the last character
+ if (index == NULL || index - value + 1 == strlen(value)) {
+ INFO("Invalid checksum digest format");
+ ret = false;
+ goto out;
+ }
+
+ *index++ = '\0';
+
+ alg = value;
+ encode = index;
+ // Currently only support SHA256 algorithm
+ if (strcmp(alg, "sha256") != 0) {
+ DEBUG("Unsupported digest algorithm: %s", alg);
+ ret = false;
+ goto out;
+ }
+
+ ret = util_reg_match(sha256_encode_patten, encode) == 0;
+
+out:
+ free(value);
+ return ret;
+}
+
+// Parsing a reference string as a possible identifier, full digest, or familiar name.
+static char *parse_digest_reference(const char *ref)
+{
+ char *indentfier_patten = "^[a-f0-9]{64}$";
+
+ if (util_reg_match(indentfier_patten, ref) == 0) {
+ return util_string_append(ref, "sha256:");
+ }
+
+ if (validate_digest(ref)) {
+ return util_strdup_s(ref);
+ }
+
+ return oci_normalize_image_name(ref);
+}
+
+static int is_name_digest_consistent(const char *name, char **names, size_t names_len, const char *digest)
+{
+ size_t i;
+ int ret = -1;
+ int nret = 0;
+ char *tag_pos = NULL;
+ char **tags = NULL;
+ char **digests = NULL;
+
+ if (resort_image_names((const char **)names, names_len, NULL, &tags, &digests) != 0) {
+ ERROR("Failed to resort image names");
+ goto out;
+ }
+
+ for (i = 0; i < util_array_len((const char **)tags); i++) {
+ __isula_auto_free char *ref = NULL;
+ __isula_auto_free char *tmp_repo_digests = NULL;
+ ref = parse_digest_reference(tags[i]);
+ if (ref == NULL) {
+ continue;
+ }
+ tag_pos = util_tag_pos(ref);
+ if (tag_pos == NULL) {
+ ERROR("invalid ref %s", ref);
+ continue;
+ }
+ *tag_pos = '\0';
+
+ nret = asprintf(&tmp_repo_digests, "%s@%s", ref, digest);
+ if (nret < 0) {
+ ERROR("Failed to receive repo digest");
+ goto out;
+ }
+ if (strcmp(name, tmp_repo_digests) == 0) {
+ ret = 0;
+ goto out;
+ }
+ }
+out:
+ util_free_array(tags);
+ util_free_array(digests);
+ return ret;
+}
+
// by_digest returns the image which matches the specified name.
static image_t *by_digest(const char *name)
{
digest_image_t *digest_filter_images = NULL;
char *digest = NULL;
+ image_t *tmp_ret = NULL;
// split digest for image name with digest
digest = strrchr(name, '@');
@@ -457,12 +608,21 @@ static image_t *by_digest(const char *name)
}
digest++;
digest_filter_images = (digest_image_t *)map_search(g_image_store->bydigest, (void *)digest);
- if (digest_filter_images == NULL) {
+ if (digest_filter_images == NULL || linked_list_empty(&(digest_filter_images->images_list))) {
return NULL;
}
// currently, a digest corresponds to an image, directly returning the first element
- return linked_list_first_elem(&(digest_filter_images->images_list));
+ tmp_ret = linked_list_first_elem(&(digest_filter_images->images_list));
+
+ // verify name and digest consistency to ensure we are not matching images to different repositories,
+ // even if the digests match.
+ // For example, ubuntu@sha256:abc......, shouldn't match test@sha256:abc......
+ if (is_name_digest_consistent(name, tmp_ret->simage->names, tmp_ret->simage->names_len, digest) != 0) {
+ return NULL;
+ }
+
+ return tmp_ret;
}
static image_t *lookup(const char *id)
@@ -2001,107 +2161,6 @@ out:
return ret;
}
-static int resort_image_names(const char **names, size_t names_len, char **first_name, char ***image_tags,
- char ***image_digests)
-{
- int ret = 0;
- size_t i;
- char *prefix = NULL;
-
- for (i = 0; i < names_len; i++) {
- size_t len = strlen(names[i]);
- if (strlen(names[i]) > MAX_IMAGE_NAME_LENGTH) {
- prefix = util_sub_string(names[i], len - MAX_IMAGE_NAME_LENGTH,
- MAX_IMAGE_NAME_LENGTH - MAX_IMAGE_DIGEST_LENGTH);
- }
-
- // TODO: maybe should support other digest
- if (prefix != NULL && strcmp(prefix, DIGEST_PREFIX) == 0) {
- if (util_array_append(image_digests, names[i]) != 0) {
- ERROR("Failed to append image to digest: %s", names[i]);
- ret = -1;
- goto out;
- }
- } else {
- if (util_array_append(image_tags, names[i]) != 0) {
- ERROR("Failed to append image to tags: %s", names[i]);
- ret = -1;
- goto out;
- }
- }
- }
-
- if (util_array_len((const char **)(*image_digests)) > 0) {
- free(*first_name);
- *first_name = util_strdup_s((*image_digests)[0]);
- }
-
- if (util_array_len((const char **)(*image_tags)) > 0) {
- free(*first_name);
- *first_name = util_strdup_s((*image_tags)[0]);
- }
-
-out:
- if (ret != 0) {
- util_free_array(*image_digests);
- util_free_array(*image_tags);
- free(*first_name);
- }
- free(prefix);
- return ret;
-}
-
-// Validate checks that the contents is a valid digest
-static bool validate_digest(const char *digest)
-{
- bool ret = true;
- const char *sha256_encode_patten = "^[a-f0-9]{64}$";
- char *value = util_strdup_s(digest);
- char *index = strchr(value, ':');
- char *alg = NULL;
- char *encode = NULL;
-
- // contains ':' and is not the last character
- if (index == NULL || index - value + 1 == strlen(value)) {
- INFO("Invalid checksum digest format");
- ret = false;
- goto out;
- }
-
- *index++ = '\0';
-
- alg = value;
- encode = index;
- // Currently only support SHA256 algorithm
- if (strcmp(alg, "sha256") != 0) {
- DEBUG("Unsupported digest algorithm: %s", alg);
- ret = false;
- goto out;
- }
-
- ret = util_reg_match(sha256_encode_patten, encode) == 0;
-
-out:
- free(value);
- return ret;
-}
-
-// Parsing a reference string as a possible identifier, full digest, or familiar name.
-static char *parse_digest_reference(const char *ref)
-{
- char *indentfier_patten = "^[a-f0-9]{64}$";
-
- if (util_reg_match(indentfier_patten, ref) == 0) {
- return util_string_append(ref, "sha256:");
- }
-
- if (validate_digest(ref)) {
- return util_strdup_s(ref);
- }
-
- return oci_normalize_image_name(ref);
-}
-
static int pack_repo_digest(char ***old_repo_digests, const char **image_tags, const char *digest, char ***repo_digests)
{
int ret = 0;
--
2.42.0