From 86776bf17f1644c76fdf8b87042645cf77bd3873 Mon Sep 17 00:00:00 2001 From: chantra Date: Wed, 2 Feb 2022 13:34:28 -0800 Subject: [PATCH 11/30] [rpm2extents] Perform digest computation within the validator The validator calls `rpmcliVerifySignaturesFD` which under the hood performs `Fread`. Digests are computed/updated for each `Fread`. This diffs takes advantage of that by initializing the digest before calling `rpmcliVerifySignaturesFD`. Once `rpmcliVerifySignaturesFD` as returned and the file has been read, the digests are available. This saves us from spawning a `digestor` process, as well as performing an extra file read within it. --- rpm2extents.c | 234 +++++++++++++++++++++++--------------------------- 1 file changed, 106 insertions(+), 128 deletions(-) diff --git a/rpm2extents.c b/rpm2extents.c index 065a00306..e316a2834 100644 --- a/rpm2extents.c +++ b/rpm2extents.c @@ -64,38 +64,37 @@ static struct poptOption optionsTable[] = { }; -static int digestor( +static void FDDigestInit(FD_t fdi, uint8_t algos[], uint32_t algos_len){ + int algo; + + for (algo = 0; algo < algos_len; algo++) { + fdInitDigest(fdi, algos[algo], 0); + } +} + +static int FDWriteDigests( FD_t fdi, FD_t fdo, - FD_t validationo, uint8_t algos[], - uint32_t algos_len -) + uint32_t algos_len) { - ssize_t fdilength; const char *filedigest, *algo_name; size_t filedigest_len, len; uint32_t algo_name_len, algo_digest_len; int algo; rpmRC rc = RPMRC_FAIL; - for (algo = 0; algo < algos_len; algo++) { - fdInitDigest(fdi, algos[algo], 0); - } - fdilength = ufdCopy(fdi, fdo); - if (fdilength == -1) { - fprintf(stderr, _("digest cat failed\n")); - goto exit; - } + ssize_t fdilength = fdOp(fdi, FDSTAT_READ)->bytes; len = sizeof(fdilength); - if (Fwrite(&fdilength, len, 1, validationo) != len) { + if (Fwrite(&fdilength, len, 1, fdo) != len) { fprintf(stderr, _("Unable to write input length %zd\n"), fdilength); goto exit; } len = sizeof(algos_len); - if (Fwrite(&algos_len, len, 1, validationo) != len) { - fprintf(stderr, _("Unable to write number of validation digests\n")); + if (Fwrite(&algos_len, len, 1, fdo) != len) { + algo_digest_len = (uint32_t)filedigest_len; + fprintf(stderr, _("Unable to write number of digests\n")); goto exit; } for (algo = 0; algo < algos_len; algo++) { @@ -106,24 +105,24 @@ static int digestor( algo_digest_len = (uint32_t)filedigest_len; len = sizeof(algo_name_len); - if (Fwrite(&algo_name_len, len, 1, validationo) != len) { + if (Fwrite(&algo_name_len, len, 1, fdo) != len) { fprintf(stderr, - _("Unable to write validation algo name length\n")); + _("Unable to write digest algo name length\n")); goto exit; } len = sizeof(algo_digest_len); - if (Fwrite(&algo_digest_len, len, 1, validationo) != len) { + if (Fwrite(&algo_digest_len, len, 1, fdo) != len) { fprintf(stderr, - _("Unable to write number of bytes for validation digest\n")); + _("Unable to write number of bytes for digest\n")); goto exit; } - if (Fwrite(algo_name, algo_name_len, 1, validationo) != algo_name_len) { - fprintf(stderr, _("Unable to write validation algo name\n")); + if (Fwrite(algo_name, algo_name_len, 1, fdo) != algo_name_len) { + fprintf(stderr, _("Unable to write digest algo name\n")); goto exit; } - if (Fwrite(filedigest, algo_digest_len, 1, validationo ) != algo_digest_len) { + if (Fwrite(filedigest, algo_digest_len, 1, fdo ) != algo_digest_len) { fprintf(stderr, - _("Unable to write validation digest value %u, %zu\n"), + _("Unable to write digest value %u, %zu\n"), algo_digest_len, filedigest_len); goto exit; } @@ -133,38 +132,66 @@ exit: return rc; } -static rpmRC validator(FD_t fdi, FD_t fdo){ - int rc; - char *msg = NULL; - rpmts ts = rpmtsCreate(); +static rpmRC FDWriteSignaturesValidation(FD_t fdo, int rpmvsrc, char *msg) { size_t len; + rpmRC rc = RPMRC_FAIL; - rpmtsSetRootDir(ts, rpmcliRootDir); - rc = rpmcliVerifySignaturesFD(ts, fdi, &msg); - if(rc){ - fprintf(stderr, _("Error validating package\n")); + if(rpmvsrc){ + fprintf(stderr, _("Error verifying package signatures\n")); } - len = sizeof(rc); - if (Fwrite(&rc, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write validator RC code %d\n"), rc); + + len = sizeof(rpmvsrc); + if (Fwrite(&rpmvsrc, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write signature verification RC code %d\n"), rpmvsrc); + goto exit; + } + size_t content_len = msg ? strlen(msg) : 0; + len = sizeof(content_len); + if (Fwrite(&content_len, len, 1, fdo) != len) { + fprintf(stderr, _("Unable to write signature verification output length %zd\n"), content_len); goto exit; } - size_t validator_len = msg ? strlen(msg) : 0; - len = sizeof(validator_len); - if (Fwrite(&validator_len, len, 1, fdo) != len) { - fprintf(stderr, _("Unable to write validator output length code %zd\n"), validator_len); + if (Fwrite(msg, content_len, 1, fdo) != content_len) { + fprintf(stderr, _("Unable to write signature verification output %s\n"), msg); goto exit; } - if (Fwrite(msg, validator_len, 1, fdo) != validator_len) { - fprintf(stderr, _("Unable to write validator output %s\n"), msg); + + rc = RPMRC_OK; +exit: + + return rc; +} + +static rpmRC validator(FD_t fdi, FD_t digesto, FD_t sigo, + uint8_t algos[], + uint32_t algos_len){ + int rpmvsrc; + rpmRC rc = RPMRC_FAIL; + char *msg = NULL; + rpmts ts = rpmtsCreate(); + + rpmtsSetRootDir(ts, rpmcliRootDir); + + FDDigestInit(fdi, algos, algos_len); + + rpmvsrc = rpmcliVerifySignaturesFD(ts, fdi, &msg); + + // Write result of digest computation + if(FDWriteDigests(fdi, digesto, algos, algos_len) != RPMRC_OK) { + fprintf(stderr, _("Failed to write digests")); goto exit; } + // Write result of signature validation. + if(FDWriteSignaturesValidation(sigo, rpmvsrc, msg)) { + goto exit; + } + rc = RPMRC_OK; exit: if(msg) { free(msg); } - return rc ? RPMRC_FAIL : RPMRC_OK; + return rc; } static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi) @@ -422,12 +449,16 @@ static off_t ufdTee(FD_t sfd, FD_t *fds, int len) return total; } -static int teeRpm(FD_t fdi, FD_t digestori) { - rpmRC rc; +static rpmRC teeRpm(FD_t fdi, uint8_t algos[], uint32_t algos_len) { + rpmRC rc = RPMRC_FAIL; off_t offt = -1; + // tee-ed stdin int processorpipefd[2]; int validatorpipefd[2]; - int rpmsignpipefd[2]; + // metadata + int meta_digestpipefd[2]; + int meta_rpmsignpipefd[2]; + pid_t cpids[2], w; int wstatus; FD_t fds[2]; @@ -442,8 +473,13 @@ static int teeRpm(FD_t fdi, FD_t digestori) { return RPMRC_FAIL; } - if (pipe(rpmsignpipefd) == -1) { - fprintf(stderr, _("Validator pipe failure\n")); + if (pipe(meta_digestpipefd) == -1) { + fprintf(stderr, _("Meta digest pipe failure\n")); + return RPMRC_FAIL; + } + + if (pipe(meta_rpmsignpipefd) == -1) { + fprintf(stderr, _("Meta rpm signature pipe failure\n")); return RPMRC_FAIL; } @@ -453,16 +489,20 @@ static int teeRpm(FD_t fdi, FD_t digestori) { close(processorpipefd[0]); close(processorpipefd[1]); close(validatorpipefd[1]); - close(rpmsignpipefd[0]); + close(meta_digestpipefd[0]); + close(meta_rpmsignpipefd[0]); FD_t fdi = fdDup(validatorpipefd[0]); - FD_t fdo = fdDup(rpmsignpipefd[1]); - close(rpmsignpipefd[1]); - rc = validator(fdi, fdo); + FD_t digesto = fdDup(meta_digestpipefd[1]); + FD_t sigo = fdDup(meta_rpmsignpipefd[1]); + close(meta_digestpipefd[1]); + close(meta_rpmsignpipefd[1]); + rc = validator(fdi, digesto, sigo, algos, algos_len); if(rc != RPMRC_OK) { fprintf(stderr, _("Validator failed\n")); } Fclose(fdi); - Fclose(fdo); + Fclose(digesto); + Fclose(sigo); if (rc != RPMRC_OK) { exit(EXIT_FAILURE); } @@ -475,18 +515,21 @@ static int teeRpm(FD_t fdi, FD_t digestori) { close(validatorpipefd[0]); close(validatorpipefd[1]); close(processorpipefd[1]); - close(rpmsignpipefd[1]); + close(meta_digestpipefd[1]); + close(meta_rpmsignpipefd[1]); FD_t fdi = fdDup(processorpipefd[0]); close(processorpipefd[0]); - FD_t validatori = fdDup(rpmsignpipefd[0]); - close(rpmsignpipefd[0]); + FD_t sigi = fdDup(meta_rpmsignpipefd[0]); + close(meta_rpmsignpipefd[0]); + FD_t digestori = fdDup(meta_digestpipefd[0]); + close(meta_digestpipefd[0]); - rc = process_package(fdi, digestori, validatori); + rc = process_package(fdi, digestori, sigi); if(rc != RPMRC_OK) { fprintf(stderr, _("Validator failed\n")); } Fclose(digestori); - Fclose(validatori); + Fclose(sigi); /* fdi is normally closed through the stacked file gzdi in the * function */ @@ -505,8 +548,10 @@ static int teeRpm(FD_t fdi, FD_t digestori) { fds[1] = fdDup(validatorpipefd[1]); close(validatorpipefd[1]); close(processorpipefd[1]); - close(rpmsignpipefd[0]); - close(rpmsignpipefd[1]); + close(meta_digestpipefd[0]); + close(meta_digestpipefd[1]); + close(meta_rpmsignpipefd[0]); + close(meta_rpmsignpipefd[1]); rc = RPMRC_OK; offt = ufdTee(fdi, fds, 2); @@ -534,16 +579,10 @@ static int teeRpm(FD_t fdi, FD_t digestori) { int main(int argc, char *argv[]) { rpmRC rc; - int cprc = 0; poptContext optCon = NULL; const char **args = NULL; int nb_algos = 0; - int mainpipefd[2]; - int metapipefd[2]; - pid_t cpid, w; - int wstatus; - xsetprogname(argv[0]); /* Portability call -- see system.h */ rpmReadConfigFiles(NULL, NULL); optCon = rpmcliInit(argc, argv, optionsTable); @@ -570,69 +609,8 @@ int main(int argc, char *argv[]) { } } - if (pipe(mainpipefd) == -1) { - fprintf(stderr, _("Main pipe failure\n")); - exit(EXIT_FAILURE); - } - if (pipe(metapipefd) == -1) { - fprintf(stderr, _("Meta pipe failure\n")); - exit(EXIT_FAILURE); - } - - cpid = fork(); - if (cpid == 0) { - /* child: digestor */ - close(mainpipefd[0]); - close(metapipefd[0]); - FD_t fdi = fdDup(STDIN_FILENO); - FD_t fdo = fdDup(mainpipefd[1]); - FD_t validationo = fdDup(metapipefd[1]); - rc = digestor(fdi, fdo, validationo, algos, nb_algos); - Fclose(validationo); - Fclose(fdo); - Fclose(fdi); - } else { - /* parent: main program */ - close(mainpipefd[1]); - close(metapipefd[1]); - FD_t fdi = fdDup(mainpipefd[0]); - FD_t digestori = fdDup(metapipefd[0]); - rc = teeRpm(fdi, digestori); - Fclose(digestori); - /* Wait for child process (digestor for stdin) to complete. - */ - if (rc != RPMRC_OK) { - if (kill(cpid, SIGTERM) != 0) { - fprintf(stderr, - _("Failed to kill digest process when main process failed: %s\n"), - strerror(errno)); - } - } - w = waitpid(cpid, &wstatus, 0); - if (w == -1) { - fprintf(stderr, _("waitpid %d failed %s\n"), cpid, strerror(errno)); - cprc = EXIT_FAILURE; - } else if (WIFEXITED(wstatus)) { - cprc = WEXITSTATUS(wstatus); - if (cprc != 0) { - fprintf(stderr, - _("Digest process non-zero exit code %d\n"), - cprc); - } - } else if (WIFSIGNALED(wstatus)) { - fprintf(stderr, - _("Digest process was terminated with a signal: %d\n"), - WTERMSIG(wstatus)); - cprc = EXIT_FAILURE; - } else { - /* Don't think this can happen, but covering all bases */ - fprintf(stderr, _("Unhandled circumstance in waitpid\n")); - cprc = EXIT_FAILURE; - } - if (cprc != EXIT_SUCCESS) { - rc = RPMRC_FAIL; - } - } + FD_t fdi = fdDup(STDIN_FILENO); + rc = teeRpm(fdi, algos, nb_algos); if (rc != RPMRC_OK) { /* translate rpmRC into generic failure return code. */ return EXIT_FAILURE; -- 2.35.1