Changeset View
Standalone View
lib/libsecureboot/verify_file.c
Show First 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | add_verify_status(struct stat *stp, int status) | ||||
vsp = malloc(sizeof(struct verify_status)); | vsp = malloc(sizeof(struct verify_status)); | ||||
vsp->vs_next = verified_files; | vsp->vs_next = verified_files; | ||||
vsp->vs_dev = stp->st_dev; | vsp->vs_dev = stp->st_dev; | ||||
vsp->vs_ino = stp->st_ino; | vsp->vs_ino = stp->st_ino; | ||||
vsp->vs_status = status; | vsp->vs_status = status; | ||||
verified_files = vsp; | verified_files = vsp; | ||||
} | } | ||||
/** | /** | ||||
* @brief | * @brief | ||||
* load specified manifest if verified | * load specified manifest if verified | ||||
*/ | */ | ||||
int | int | ||||
load_manifest(const char *name, const char *prefix, | load_manifest(const char *name, const char *prefix, | ||||
const char *skip, struct stat *stp) | const char *skip, struct stat *stp) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | find_manifest(const char *name) | ||||
rc = VE_FINGERPRINT_NONE; | rc = VE_FINGERPRINT_NONE; | ||||
for (tp = manifest_names; *tp; tp++) { | for (tp = manifest_names; *tp; tp++) { | ||||
snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp); | snprintf(buf, sizeof(buf), "%s/%s", prefix, *tp); | ||||
DEBUG_PRINTF(5, ("looking for %s\n", buf)); | DEBUG_PRINTF(5, ("looking for %s\n", buf)); | ||||
if (stat(buf, &st) == 0 && st.st_size > 0) { | if (stat(buf, &st) == 0 && st.st_size > 0) { | ||||
#ifdef MANIFEST_SKIP_ALWAYS | #ifdef MANIFEST_SKIP_ALWAYS | ||||
skip = MANIFEST_SKIP_ALWAYS; | skip = MANIFEST_SKIP_ALWAYS; | ||||
#else | #else | ||||
if (*tp[0] == '.') { | if (!strncmp("../", *tp, 3)) { | ||||
#ifdef MANIFEST_SKIP | #ifdef MANIFEST_SKIP | ||||
skip = MANIFEST_SKIP; | skip = MANIFEST_SKIP; | ||||
#else | #else | ||||
if ((skip = strrchr(prefix, '/'))) | if ((skip = strrchr(prefix, '/'))) { | ||||
skip++; | *skip = '\0'; | ||||
sjg: skip is const char *, not supposed to touch it. | |||||
skip = NULL; | |||||
sjgUnsubmitted Not Done Inline ActionsThis would defeat the point of skip. sjg: This would defeat the point of skip.
Perhaps you want a MANIFEST_SKIP_NEVER ? | |||||
kdAuthorUnsubmitted Not Done Inline ActionsAs for the skip, I'm not sure if I understand its purpose and if its working as intended. For example lets say that the manifest is in /boot/manifest and we want to verify /boot/kernel/kernel. This will look for and load /boot/kernel/../manifest. Without these changes the manifest will load with skip="kernel". This will result with only the files in /boot/kernel being found correctly. kd: As for the skip, I'm not sure if I understand its purpose and if its working as intended. For… | |||||
sjgUnsubmitted Not Done Inline ActionsIf the manifest is /boot/manifest and the path loaded is /boot/kernel/kernel skip is badly named - though I've not come up with anything better, because prefix is already used - to identify where the manifest was found. MANIFEST_SKIP_NEVER does not exist (yet) I was positing that you might be wanting something that simply disables the setting of skip regardless skip=NULL is better than *skip = '\0' which should produce a compile error. sjg: If the manifest is /boot/manifest and the path loaded is /boot/kernel/kernel
the manifest entry… | |||||
} | |||||
#endif | #endif | ||||
} else | } else | ||||
skip = NULL; | skip = NULL; | ||||
#endif | #endif | ||||
rc = load_manifest(buf, prefix, skip, &st); | rc = load_manifest(buf, prefix, skip, &st); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
free(prefix); | free(prefix); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
if (!verifying) | if (!verifying) | ||||
return (0); | return (0); | ||||
if (fd < 0 || fstat(fd, &st) < 0 || !S_ISREG(st.st_mode)) | if (fd < 0 || fstat(fd, &st) < 0 || !S_ISREG(st.st_mode)) | ||||
return (0); | return (0); | ||||
DEBUG_PRINTF(3, ("fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n", | DEBUG_PRINTF(3, ("fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n", | ||||
fd, filename, (long long)off, st.st_dev,st.st_ino)); | fd, filename, (long long)off, | ||||
(long long)st.st_dev, (long long)st.st_ino)); | |||||
rc = is_verified(&st); | rc = is_verified(&st); | ||||
if (rc != VE_NOT_CHECKED) { | if (rc != VE_NOT_CHECKED) { | ||||
ve_status_set(fd, rc); | ve_status_set(fd, rc); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
rc = find_manifest(filename); | rc = find_manifest(filename); | ||||
if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) { | if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) { | ||||
if (severity <= VE_GUESS) | if (severity <= VE_GUESS) | ||||
severity = severity_guess(filename); | severity = severity_guess(filename); | ||||
if ((rc = verify_fd(fd, filename, off, &st)) >= 0) { | if ((rc = verify_fd(fd, filename, off, &st)) >= 0) { | ||||
if (verbose || severity > VE_WANT) { | if (verbose || severity > VE_WANT) { | ||||
#if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0 | #if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0 | ||||
printf("Verified %s %llu,%llu\n", filename, | printf("Verified %s %llu,%llu\n", filename, | ||||
st.st_dev, st.st_ino); | (long long)st.st_dev, (long long)st.st_ino); | ||||
#else | #else | ||||
printf("Verified %s\n", filename); | printf("Verified %s\n", filename); | ||||
#endif | #endif | ||||
} | } | ||||
if (severity < VE_MUST) { /* not a kernel or module */ | if (severity < VE_MUST) { /* not a kernel or module */ | ||||
if ((cp = strrchr(filename, '/'))) { | if ((cp = strrchr(filename, '/'))) { | ||||
cp++; | cp++; | ||||
if (strncmp(cp, "loader.ve.", 10) == 0) { | if (strncmp(cp, "loader.ve.", 10) == 0) { | ||||
cp += 10; | cp += 10; | ||||
verify_tweak(cp, | verify_tweak(cp, | ||||
&accept_no_fp, &verbose, | &accept_no_fp, &verbose, | ||||
&verifying); | &verifying); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 58 Lines • Show Last 20 Lines |
skip is const char *, not supposed to touch it.