commit d5c81d448ae4eec21053152e1c82c66eb11ca7a4 from: Stefan Sperling date: Thu Jul 08 11:03:29 2021 UTC verify object ID checksums while loose objects are being accessed commit - 4f655d1bef17f1bc4ed551c53dd1b2d83c56b880 commit + d5c81d448ae4eec21053152e1c82c66eb11ca7a4 blob - 48165fc4dfb98dc55aa9bb49ceea9ff107e8fc26 blob + f571bc2b37e0f81d982871ec9029eb572253e75d --- include/got_error.h +++ include/got_error.h @@ -147,6 +147,7 @@ #define GOT_ERR_GIT_REPO_EXT 130 #define GOT_ERR_CANNOT_PACK 131 #define GOT_ERR_LONELY_PACKIDX 132 +#define GOT_ERR_OBJ_CSUM 133 static const struct got_error { int code; @@ -301,6 +302,7 @@ static const struct got_error { { GOT_ERR_GIT_REPO_EXT, "unsupported repository format extension" }, { GOT_ERR_CANNOT_PACK, "not enough objects to pack" }, { GOT_ERR_LONELY_PACKIDX, "pack index has no corresponding pack file" }, + { GOT_ERR_OBJ_CSUM, "bad object checksum" }, }; /* blob - ad8c052645bdb1fad1e36b8ca14e324f41bff53d blob + 3833fedc8b779ac09969970c0ae89d5732c651cf --- lib/got_lib_inflate.h +++ lib/got_lib_inflate.h @@ -20,6 +20,12 @@ struct got_inflate_checksum { /* If not NULL, mix input bytes into this SHA1 context. */ SHA1_CTX *input_sha1; + + /* If not NULL, mix output bytes into this CRC checksum. */ + uint32_t *output_crc; + + /* If not NULL, mix output bytes into this SHA1 context. */ + SHA1_CTX *output_sha1; }; struct got_inflate_buf { blob - 7f91b3bcc5e247a002e805274461026d32267fe5 blob + f107a850167bfb93f97e10313c9351627cd8eb68 --- lib/got_lib_object.h +++ lib/got_lib_object.h @@ -103,7 +103,7 @@ const struct got_error *got_object_open_loose_fd(int * const struct got_error *got_object_open_packed(struct got_object **, struct got_object_id *, struct got_repository *); const struct got_error *got_object_read_header_privsep(struct got_object **, - struct got_repository *, int); + struct got_object_id *, struct got_repository *, int); const struct got_error *got_object_open(struct got_object **, struct got_repository *, struct got_object_id *); const struct got_error *got_object_raw_open(struct got_raw_object **, blob - 852db60a614ec79d99a3416e34b5e0b018f27ed9 blob + 7592979912f4df4afc7d084b4a3779e769d66b04 --- lib/got_lib_object_parse.h +++ lib/got_lib_object_parse.h @@ -42,6 +42,7 @@ const struct got_error *got_read_file_to_mem(uint8_t * struct got_pack; struct got_packidx; +struct got_inflate_checksum; const struct got_error *got_object_parse_header(struct got_object **, char *, size_t); const struct got_error *got_object_read_header(struct got_object **, int); blob - dc1687fd0232a98260fd1d1f91425364de21521b blob + e35958fa1bceef186dcfd71f9d4a132377b31766 --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -369,6 +369,13 @@ struct got_imsg_pack { } __attribute__((__packed__)); /* + * Structure for GOT_IMSG_OBJECT_REQUEST, GOT_IMSG_BLOB_REQUEST, + * GOT_IMSG_TREE_REQUEST, GOT_IMSG_COMMIT_REQUEST, and + * GOT_IMSG_TAG_REQUEST data. + */ +struct got_object_id; + +/* * Structure for GOT_IMSG_PACKED_OBJECT_REQUEST and * GOT_IMSG_PACKED_RAW_OBJECT_REQUEST data. */ @@ -428,8 +435,10 @@ const struct got_error *got_privsep_recv_imsg(struct i void got_privsep_send_error(struct imsgbuf *, const struct got_error *); const struct got_error *got_privsep_send_ack(struct imsgbuf *); const struct got_error *got_privsep_wait_ack(struct imsgbuf *); -const struct got_error *got_privsep_send_obj_req(struct imsgbuf *, int); -const struct got_error *got_privsep_send_raw_obj_req(struct imsgbuf *, int); +const struct got_error *got_privsep_send_obj_req(struct imsgbuf *, int, + struct got_object_id *); +const struct got_error *got_privsep_send_raw_obj_req(struct imsgbuf *, int, + struct got_object_id *); const struct got_error *got_privsep_send_raw_obj_outfd(struct imsgbuf *, int); const struct got_error *got_privsep_send_commit_req(struct imsgbuf *, int, struct got_object_id *, int); blob - aa993fb6f2b096a240a470976cbe73249014215a blob + 5cb13a52c00956e749c0fce5abb67b88742b17b4 --- lib/inflate.c +++ lib/inflate.c @@ -93,6 +93,16 @@ csum_input(struct got_inflate_checksum *csum, const ch SHA1Update(csum->input_sha1, buf, len); } +static void +csum_output(struct got_inflate_checksum *csum, const char *buf, size_t len) +{ + if (csum->output_crc) + *csum->output_crc = crc32(*csum->output_crc, buf, len); + + if (csum->output_sha1) + SHA1Update(csum->output_sha1, buf, len); +} + const struct got_error * got_inflate_read(struct got_inflate_buf *zb, FILE *f, size_t *outlenp, size_t *consumed) @@ -109,8 +119,8 @@ got_inflate_read(struct got_inflate_buf *zb, FILE *f, if (consumed) *consumed = 0; do { - char *csum_in = NULL; - size_t csum_avail = 0; + char *csum_in = NULL, *csum_out = NULL; + size_t csum_avail_in = 0, csum_avail_out = 0; if (z->avail_in == 0) { size_t n = fread(zb->inbuf, 1, zb->inlen, f); @@ -126,11 +136,17 @@ got_inflate_read(struct got_inflate_buf *zb, FILE *f, } if (zb->csum) { csum_in = z->next_in; - csum_avail = z->avail_in; + csum_avail_in = z->avail_in; + csum_out = z->next_out; + csum_avail_out = z->avail_out; } ret = inflate(z, Z_SYNC_FLUSH); - if (zb->csum) - csum_input(zb->csum, csum_in, csum_avail - z->avail_in); + if (zb->csum) { + csum_input(zb->csum, csum_in, + csum_avail_in - z->avail_in); + csum_output(zb->csum, csum_out, + csum_avail_out - z->avail_out); + } } while (ret == Z_OK && z->avail_out > 0); if (ret == Z_OK || ret == Z_BUF_ERROR) { @@ -163,8 +179,8 @@ got_inflate_read_fd(struct got_inflate_buf *zb, int fd if (consumed) *consumed = 0; do { - char *csum_in = NULL; - size_t csum_avail = 0; + char *csum_in = NULL, *csum_out = NULL; + size_t csum_avail_in = 0, csum_avail_out = 0; if (z->avail_in == 0) { ssize_t n = read(fd, zb->inbuf, zb->inlen); @@ -180,11 +196,17 @@ got_inflate_read_fd(struct got_inflate_buf *zb, int fd } if (zb->csum) { csum_in = z->next_in; - csum_avail = z->avail_in; + csum_avail_in = z->avail_in; + csum_out = z->next_out; + csum_avail_out = z->avail_out; } ret = inflate(z, Z_SYNC_FLUSH); - if (zb->csum) - csum_input(zb->csum, csum_in, csum_avail - z->avail_in); + if (zb->csum) { + csum_input(zb->csum, csum_in, + csum_avail_in - z->avail_in); + csum_output(zb->csum, csum_out, + csum_avail_out - z->avail_out); + } } while (ret == Z_OK && z->avail_out > 0); if (ret == Z_OK || ret == Z_BUF_ERROR) { @@ -216,8 +238,8 @@ got_inflate_read_mmap(struct got_inflate_buf *zb, uint *consumed = 0; do { - char *csum_in = NULL; - size_t csum_avail = 0; + char *csum_in = NULL, *csum_out = NULL; + size_t csum_avail_in = 0, csum_avail_out = 0; size_t last_total_in = zb->z.total_in; if (z->avail_in == 0) { @@ -231,11 +253,17 @@ got_inflate_read_mmap(struct got_inflate_buf *zb, uint } if (zb->csum) { csum_in = z->next_in; - csum_avail = z->avail_in; + csum_avail_in = z->avail_in; + csum_out = z->next_out; + csum_avail_out = z->avail_out; } ret = inflate(z, Z_SYNC_FLUSH); - if (zb->csum) - csum_input(zb->csum, csum_in, csum_avail - z->avail_in); + if (zb->csum) { + csum_input(zb->csum, csum_in, + csum_avail_in - z->avail_in); + csum_output(zb->csum, csum_out, + csum_avail_out - z->avail_out); + } *consumed += z->total_in - last_total_in; } while (ret == Z_OK && z->avail_out > 0); blob - bd60cd8b6abcd2895c9cbddca8e0c99886f92531 blob + 66e51456da85f0477bef25d1074a69d766e38fe2 --- lib/object.c +++ lib/object.c @@ -367,14 +367,15 @@ done: } static const struct got_error * -request_object(struct got_object **obj, struct got_repository *repo, int fd) +request_object(struct got_object **obj, struct got_object_id *id, + struct got_repository *repo, int fd) { const struct got_error *err = NULL; struct imsgbuf *ibuf; ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].ibuf; - err = got_privsep_send_obj_req(ibuf, fd); + err = got_privsep_send_obj_req(ibuf, fd, id); if (err) return err; @@ -383,7 +384,7 @@ request_object(struct got_object **obj, struct got_rep static const struct got_error * request_raw_object(uint8_t **outbuf, off_t *size, size_t *hdrlen, int outfd, - struct got_repository *repo, int infd) + struct got_object_id *id, struct got_repository *repo, int infd) { const struct got_error *err = NULL; struct imsgbuf *ibuf; @@ -395,7 +396,7 @@ request_raw_object(uint8_t **outbuf, off_t *size, size if (outfd_child == -1) return got_error_from_errno("dup"); - err = got_privsep_send_raw_obj_req(ibuf, infd); + err = got_privsep_send_raw_obj_req(ibuf, infd, id); if (err) return err; @@ -453,12 +454,12 @@ start_read_object_child(struct got_repository *repo) const struct got_error * got_object_read_header_privsep(struct got_object **obj, - struct got_repository *repo, int obj_fd) + struct got_object_id *id, struct got_repository *repo, int obj_fd) { const struct got_error *err; if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].imsg_fd != -1) - return request_object(obj, repo, obj_fd); + return request_object(obj, id, repo, obj_fd); err = start_read_object_child(repo); if (err) { @@ -466,24 +467,26 @@ got_object_read_header_privsep(struct got_object **obj return err; } - return request_object(obj, repo, obj_fd); + return request_object(obj, id, repo, obj_fd); } static const struct got_error * read_object_raw_privsep(uint8_t **outbuf, off_t *size, size_t *hdrlen, - int outfd, struct got_repository *repo, int obj_fd) + int outfd, struct got_object_id *id, struct got_repository *repo, + int obj_fd) { const struct got_error *err; if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_OBJECT].imsg_fd != -1) - return request_raw_object(outbuf, size, hdrlen, outfd, repo, - obj_fd); + return request_raw_object(outbuf, size, hdrlen, outfd, id, + repo, obj_fd); err = start_read_object_child(repo); if (err) return err; - return request_raw_object(outbuf, size, hdrlen, outfd, repo, obj_fd); + return request_raw_object(outbuf, size, hdrlen, outfd, id, repo, + obj_fd); } const struct got_error * @@ -514,7 +517,7 @@ got_object_open(struct got_object **obj, struct got_re return err; } - err = got_object_read_header_privsep(obj, repo, fd); + err = got_object_read_header_privsep(obj, id, repo, fd); if (err) return err; @@ -568,7 +571,7 @@ got_object_raw_open(struct got_raw_object **obj, struc if (err) goto done; err = read_object_raw_privsep(&outbuf, &size, &hdrlen, outfd, - repo, fd); + id, repo, fd); } *obj = calloc(1, sizeof(**obj)); @@ -745,14 +748,14 @@ read_packed_commit_privsep(struct got_commit_object ** static const struct got_error * request_commit(struct got_commit_object **commit, struct got_repository *repo, - int fd) + int fd, struct got_object_id *id) { const struct got_error *err = NULL; struct imsgbuf *ibuf; ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf; - err = got_privsep_send_commit_req(ibuf, fd, NULL, -1); + err = got_privsep_send_commit_req(ibuf, fd, id, -1); if (err) return err; @@ -761,7 +764,7 @@ request_commit(struct got_commit_object **commit, stru static const struct got_error * read_commit_privsep(struct got_commit_object **commit, int obj_fd, - struct got_repository *repo) + struct got_object_id *id, struct got_repository *repo) { const struct got_error *err; int imsg_fds[2]; @@ -769,7 +772,7 @@ read_commit_privsep(struct got_commit_object **commit, struct imsgbuf *ibuf; if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].imsg_fd != -1) - return request_commit(commit, repo, obj_fd); + return request_commit(commit, repo, obj_fd, id); ibuf = calloc(1, sizeof(*ibuf)); if (ibuf == NULL) @@ -804,7 +807,7 @@ read_commit_privsep(struct got_commit_object **commit, imsg_init(ibuf, imsg_fds[0]); repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_COMMIT].ibuf = ibuf; - return request_commit(commit, repo, obj_fd); + return request_commit(commit, repo, obj_fd, id); } @@ -850,7 +853,7 @@ open_commit(struct got_commit_object **commit, err = got_object_open_loose_fd(&fd, id, repo); if (err) return err; - err = read_commit_privsep(commit, fd, repo); + err = read_commit_privsep(commit, fd, id, repo); } if (err == NULL) { @@ -959,14 +962,14 @@ read_packed_tree_privsep(struct got_tree_object **tree static const struct got_error * request_tree(struct got_tree_object **tree, struct got_repository *repo, - int fd) + int fd, struct got_object_id *id) { const struct got_error *err = NULL; struct imsgbuf *ibuf; ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].ibuf; - err = got_privsep_send_tree_req(ibuf, fd, NULL, -1); + err = got_privsep_send_tree_req(ibuf, fd, id, -1); if (err) return err; @@ -975,7 +978,7 @@ request_tree(struct got_tree_object **tree, struct got const struct got_error * read_tree_privsep(struct got_tree_object **tree, int obj_fd, - struct got_repository *repo) + struct got_object_id *id, struct got_repository *repo) { const struct got_error *err; int imsg_fds[2]; @@ -983,7 +986,7 @@ read_tree_privsep(struct got_tree_object **tree, int o struct imsgbuf *ibuf; if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].imsg_fd != -1) - return request_tree(tree, repo, obj_fd); + return request_tree(tree, repo, obj_fd, id); ibuf = calloc(1, sizeof(*ibuf)); if (ibuf == NULL) @@ -1019,7 +1022,7 @@ read_tree_privsep(struct got_tree_object **tree, int o repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TREE].ibuf = ibuf; - return request_tree(tree, repo, obj_fd); + return request_tree(tree, repo, obj_fd, id); } static const struct got_error * @@ -1064,7 +1067,7 @@ open_tree(struct got_tree_object **tree, struct got_re err = got_object_open_loose_fd(&fd, id, repo); if (err) return err; - err = read_tree_privsep(tree, fd, repo); + err = read_tree_privsep(tree, fd, id, repo); } if (err == NULL) { @@ -1301,7 +1304,7 @@ read_packed_blob_privsep(uint8_t **outbuf, size_t *siz static const struct got_error * request_blob(uint8_t **outbuf, size_t *size, size_t *hdrlen, int outfd, - int infd, struct imsgbuf *ibuf) + int infd, struct got_object_id *id, struct imsgbuf *ibuf) { const struct got_error *err = NULL; int outfd_child; @@ -1310,7 +1313,7 @@ request_blob(uint8_t **outbuf, size_t *size, size_t *h if (outfd_child == -1) return got_error_from_errno("dup"); - err = got_privsep_send_blob_req(ibuf, infd, NULL, -1); + err = got_privsep_send_blob_req(ibuf, infd, id, -1); if (err) return err; @@ -1330,7 +1333,7 @@ request_blob(uint8_t **outbuf, size_t *size, size_t *h static const struct got_error * read_blob_privsep(uint8_t **outbuf, size_t *size, size_t *hdrlen, - int outfd, int infd, struct got_repository *repo) + int outfd, int infd, struct got_object_id *id, struct got_repository *repo) { const struct got_error *err; int imsg_fds[2]; @@ -1339,7 +1342,8 @@ read_blob_privsep(uint8_t **outbuf, size_t *size, size if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].imsg_fd != -1) { ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].ibuf; - return request_blob(outbuf, size, hdrlen, outfd, infd, ibuf); + return request_blob(outbuf, size, hdrlen, outfd, infd, id, + ibuf); } ibuf = calloc(1, sizeof(*ibuf)); @@ -1375,7 +1379,7 @@ read_blob_privsep(uint8_t **outbuf, size_t *size, size imsg_init(ibuf, imsg_fds[0]); repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_BLOB].ibuf = ibuf; - return request_blob(outbuf, size, hdrlen, outfd, infd, ibuf); + return request_blob(outbuf, size, hdrlen, outfd, infd, id, ibuf); } static const struct got_error * @@ -1430,7 +1434,7 @@ open_blob(struct got_blob_object **blob, struct got_re if (err) goto done; err = read_blob_privsep(&outbuf, &size, &hdrlen, outfd, infd, - repo); + id, repo); } if (err) goto done; @@ -1674,14 +1678,14 @@ read_packed_tag_privsep(struct got_tag_object **tag, static const struct got_error * request_tag(struct got_tag_object **tag, struct got_repository *repo, - int fd) + int fd, struct got_object_id *id) { const struct got_error *err = NULL; struct imsgbuf *ibuf; ibuf = repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].ibuf; - err = got_privsep_send_tag_req(ibuf, fd, NULL, -1); + err = got_privsep_send_tag_req(ibuf, fd, id, -1); if (err) return err; @@ -1690,7 +1694,7 @@ request_tag(struct got_tag_object **tag, struct got_re static const struct got_error * read_tag_privsep(struct got_tag_object **tag, int obj_fd, - struct got_repository *repo) + struct got_object_id *id, struct got_repository *repo) { const struct got_error *err; int imsg_fds[2]; @@ -1698,7 +1702,7 @@ read_tag_privsep(struct got_tag_object **tag, int obj_ struct imsgbuf *ibuf; if (repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].imsg_fd != -1) - return request_tag(tag, repo, obj_fd); + return request_tag(tag, repo, obj_fd, id); ibuf = calloc(1, sizeof(*ibuf)); if (ibuf == NULL) @@ -1733,7 +1737,7 @@ read_tag_privsep(struct got_tag_object **tag, int obj_ imsg_init(ibuf, imsg_fds[0]); repo->privsep_children[GOT_REPO_PRIVSEP_CHILD_TAG].ibuf = ibuf; - return request_tag(tag, repo, obj_fd); + return request_tag(tag, repo, obj_fd, id); } static const struct got_error * @@ -1791,7 +1795,7 @@ open_tag(struct got_tag_object **tag, struct got_repos err = got_object_open_loose_fd(&fd, id, repo); if (err) return err; - err = got_object_read_header_privsep(&obj, repo, fd); + err = got_object_read_header_privsep(&obj, id, repo, fd); if (err) return err; obj_type = obj->type; @@ -1802,7 +1806,7 @@ open_tag(struct got_tag_object **tag, struct got_repos err = got_object_open_loose_fd(&fd, id, repo); if (err) return err; - err = read_tag_privsep(tag, fd, repo); + err = read_tag_privsep(tag, fd, id, repo); } if (err == NULL) { blob - acb20d28e5fa0d935383503926b1be70789b9e42 blob + 9b4a7ee1895805282b36a747dfb244b5dd775ef8 --- lib/privsep.c +++ lib/privsep.c @@ -250,20 +250,22 @@ got_privsep_send_stop(int fd) } const struct got_error * -got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd) +got_privsep_send_obj_req(struct imsgbuf *ibuf, int fd, + struct got_object_id *id) { - if (imsg_compose(ibuf, GOT_IMSG_OBJECT_REQUEST, 0, 0, fd, NULL, 0) - == -1) + if (imsg_compose(ibuf, GOT_IMSG_OBJECT_REQUEST, 0, 0, fd, + id, sizeof(*id)) == -1) return got_error_from_errno("imsg_compose OBJECT_REQUEST"); return flush_imsg(ibuf); } const struct got_error * -got_privsep_send_raw_obj_req(struct imsgbuf *ibuf, int fd) +got_privsep_send_raw_obj_req(struct imsgbuf *ibuf, int fd, + struct got_object_id *id) { - if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_REQUEST, 0, 0, fd, NULL, 0) - == -1) + if (imsg_compose(ibuf, GOT_IMSG_RAW_OBJECT_REQUEST, 0, 0, fd, + id, sizeof(*id)) == -1) return got_error_from_errno("imsg_compose RAW_OBJECT_REQUEST"); return flush_imsg(ibuf); @@ -384,20 +386,21 @@ got_privsep_send_commit_req(struct imsgbuf *ibuf, int struct got_object_id *id, int pack_idx) { const struct got_error *err = NULL; - struct got_imsg_packed_object iobj, *iobjp; + struct got_imsg_packed_object iobj; + void *data; size_t len; - if (id) { /* commit is packed */ + if (pack_idx != -1) { /* commit is packed */ iobj.idx = pack_idx; memcpy(iobj.id, id->sha1, sizeof(iobj.id)); - iobjp = &iobj; + data = &iobj; len = sizeof(iobj); } else { - iobjp = NULL; - len = 0; + data = id; + len = sizeof(*id); } - if (imsg_compose(ibuf, GOT_IMSG_COMMIT_REQUEST, 0, 0, fd, iobjp, len) + if (imsg_compose(ibuf, GOT_IMSG_COMMIT_REQUEST, 0, 0, fd, data, len) == -1) { err = got_error_from_errno("imsg_compose COMMIT_REQUEST"); close(fd); @@ -413,19 +416,24 @@ got_privsep_send_tree_req(struct imsgbuf *ibuf, int fd { const struct got_error *err = NULL; struct ibuf *wbuf; - size_t len = id ? sizeof(struct got_imsg_packed_object) : 0; + size_t len; + if (pack_idx != -1) + len = sizeof(struct got_imsg_packed_object); + else + len = sizeof(*id); + wbuf = imsg_create(ibuf, GOT_IMSG_TREE_REQUEST, 0, 0, len); if (wbuf == NULL) return got_error_from_errno("imsg_create TREE_REQUEST"); - if (id) { /* tree is packed */ - if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH) == -1) { - err = got_error_from_errno("imsg_add TREE_ENTRY"); - ibuf_free(wbuf); - return err; - } + if (imsg_add(wbuf, id->sha1, SHA1_DIGEST_LENGTH) == -1) { + err = got_error_from_errno("imsg_add TREE_ENTRY"); + ibuf_free(wbuf); + return err; + } + if (pack_idx != -1) { /* tree is packed */ if (imsg_add(wbuf, &pack_idx, sizeof(pack_idx)) == -1) { err = got_error_from_errno("imsg_add TREE_ENTRY"); ibuf_free(wbuf); @@ -443,20 +451,21 @@ const struct got_error * got_privsep_send_tag_req(struct imsgbuf *ibuf, int fd, struct got_object_id *id, int pack_idx) { - struct got_imsg_packed_object iobj, *iobjp; + struct got_imsg_packed_object iobj; + void *data; size_t len; - if (id) { /* tag is packed */ + if (pack_idx != -1) { /* tag is packed */ iobj.idx = pack_idx; memcpy(iobj.id, id->sha1, sizeof(iobj.id)); - iobjp = &iobj; + data = &iobj; len = sizeof(iobj); } else { - iobjp = NULL; - len = 0; + data = id; + len = sizeof(*id); } - if (imsg_compose(ibuf, GOT_IMSG_TAG_REQUEST, 0, 0, fd, iobjp, len) + if (imsg_compose(ibuf, GOT_IMSG_TAG_REQUEST, 0, 0, fd, data, len) == -1) return got_error_from_errno("imsg_compose TAG_REQUEST"); @@ -468,20 +477,21 @@ got_privsep_send_blob_req(struct imsgbuf *ibuf, int in struct got_object_id *id, int pack_idx) { const struct got_error *err = NULL; - struct got_imsg_packed_object iobj, *iobjp; + struct got_imsg_packed_object iobj; + void *data; size_t len; - if (id) { /* blob is packed */ + if (pack_idx != -1) { /* blob is packed */ iobj.idx = pack_idx; memcpy(iobj.id, id->sha1, sizeof(iobj.id)); - iobjp = &iobj; + data = &iobj; len = sizeof(iobj); } else { - iobjp = NULL; - len = 0; + data = id; + len = sizeof(*id); } - if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, iobjp, len) + if (imsg_compose(ibuf, GOT_IMSG_BLOB_REQUEST, 0, 0, infd, data, len) == -1) { err = got_error_from_errno("imsg_compose BLOB_REQUEST"); close(infd); blob - 42e4e1a923ac6b0970e0e49aaa75dcb4458deb0c blob + f315741522c813f2f4e3d56e2caa15969cd6200d --- lib/repository_admin.c +++ lib/repository_admin.c @@ -664,7 +664,8 @@ get_loose_object_ids(struct got_object_idset **loose_i err = got_error_from_errno("fstat"); goto done; } - err = got_object_read_header_privsep(&obj, repo, fd); + err = got_object_read_header_privsep(&obj, &id, repo, + fd); if (err) goto done; fd = -1; /* already closed */ blob - aac58b1e8c9fc029985629a172044af08fa045df blob + 6ba4490d952e266de433edbadd35609faaeff1bf --- libexec/got-index-pack/got-index-pack.c +++ libexec/got-index-pack/got-index-pack.c @@ -186,6 +186,7 @@ read_packed_object(struct got_pack *pack, struct got_i size_t mapoff = obj->off; struct got_inflate_checksum csum; + memset(&csum, 0, sizeof(csum)); csum.input_sha1 = pack_sha1_ctx; csum.input_crc = &obj->crc; blob - 59f45b5cd15bd0d3e89af07aecad3d6cf6798541 blob + c5a389ba424f515e20c4b3afb8f183a6b2cdd9ae --- libexec/got-read-blob/got-read-blob.c +++ libexec/got-read-blob/got-read-blob.c @@ -38,6 +38,7 @@ #include "got_lib_object.h" #include "got_lib_object_parse.h" #include "got_lib_privsep.h" +#include "got_lib_sha1.h" static volatile sig_atomic_t sigint_received; @@ -73,7 +74,15 @@ main(int argc, char *argv[]) size_t size; struct got_object *obj = NULL; uint8_t *buf = NULL; + struct got_object_id id; + struct got_object_id expected_id; + struct got_inflate_checksum csum; + SHA1_CTX sha1_ctx; + SHA1Init(&sha1_ctx); + memset(&csum, 0, sizeof(csum)); + csum.output_sha1 = &sha1_ctx; + memset(&imsg, 0, sizeof(imsg)); imsg.fd = -1; memset(&imsg_outfd, 0, sizeof(imsg_outfd)); @@ -99,6 +108,13 @@ main(int argc, char *argv[]) goto done; } + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (datalen != sizeof(expected_id)) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + goto done; + } + memcpy(&expected_id, imsg.data, sizeof(expected_id)); + if (imsg.fd == -1) { err = got_error(GOT_ERR_PRIVSEP_NO_FD); goto done; @@ -146,14 +162,23 @@ main(int argc, char *argv[]) if (obj->size + obj->hdrlen <= GOT_PRIVSEP_INLINE_BLOB_DATA_MAX) { - err = got_inflate_to_mem(&buf, &size, NULL, NULL, f); + err = got_inflate_to_mem(&buf, &size, NULL, &csum, f); if (err) goto done; } else { - err = got_inflate_to_fd(&size, f, NULL, imsg_outfd.fd); + err = got_inflate_to_fd(&size, f, &csum, imsg_outfd.fd); if (err) goto done; } + SHA1Final(id.sha1, &sha1_ctx); + if (memcmp(expected_id.sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) { + char buf[SHA1_DIGEST_STRING_LENGTH]; + err = got_error_fmt(GOT_ERR_OBJ_CSUM, + "checksum failure for object %s", + got_sha1_digest_to_str(expected_id.sha1, buf, + sizeof(buf))); + goto done; + } if (size < obj->hdrlen) { err = got_error(GOT_ERR_BAD_OBJ_HDR); blob - 93245b30e1136486de36bd3eb72dc2f86f739952 blob + 867dc5954e47c0673e815db7c0e25ae703e11658 --- libexec/got-read-commit/got-read-commit.c +++ libexec/got-read-commit/got-read-commit.c @@ -38,6 +38,7 @@ #include "got_lib_object.h" #include "got_lib_object_parse.h" #include "got_lib_privsep.h" +#include "got_lib_sha1.h" static volatile sig_atomic_t sigint_received; @@ -48,23 +49,39 @@ catch_sigint(int signo) } static const struct got_error * -read_commit_object(struct got_commit_object **commit, FILE *f) +read_commit_object(struct got_commit_object **commit, FILE *f, + struct got_object_id *expected_id) { - struct got_object *obj; + struct got_object *obj = NULL; const struct got_error *err = NULL; size_t len; uint8_t *p; + struct got_inflate_checksum csum; + SHA1_CTX sha1_ctx; + struct got_object_id id; - err = got_inflate_to_mem(&p, &len, NULL, NULL, f); + SHA1Init(&sha1_ctx); + memset(&csum, 0, sizeof(csum)); + csum.output_sha1 = &sha1_ctx; + + err = got_inflate_to_mem(&p, &len, NULL, &csum, f); if (err) return err; - err = got_object_parse_header(&obj, p, len); - if (err) { - free(p); - return err; + SHA1Final(id.sha1, &sha1_ctx); + if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) { + char buf[SHA1_DIGEST_STRING_LENGTH]; + err = got_error_fmt(GOT_ERR_OBJ_CSUM, + "checksum failure for object %s", + got_sha1_digest_to_str(expected_id->sha1, buf, + sizeof(buf))); + goto done; } + err = got_object_parse_header(&obj, p, len); + if (err) + goto done; + if (len < obj->hdrlen + obj->size) { err = got_error(GOT_ERR_BAD_OBJ_DATA); goto done; @@ -80,7 +97,8 @@ read_commit_object(struct got_commit_object **commit, err = got_object_parse_commit(commit, p + obj->hdrlen, len); done: free(p); - got_object_close(obj); + if (obj) + got_object_close(obj); return err; } @@ -89,6 +107,7 @@ main(int argc, char *argv[]) { const struct got_error *err = NULL; struct imsgbuf ibuf; + size_t datalen; signal(SIGINT, catch_sigint); @@ -107,6 +126,7 @@ main(int argc, char *argv[]) struct imsg imsg; FILE *f = NULL; struct got_commit_object *commit = NULL; + struct got_object_id expected_id; if (sigint_received) { err = got_error(GOT_ERR_CANCELLED); @@ -128,6 +148,13 @@ main(int argc, char *argv[]) goto done; } + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (datalen != sizeof(expected_id)) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + goto done; + } + memcpy(&expected_id, imsg.data, sizeof(expected_id)); + if (imsg.fd == -1) { err = got_error(GOT_ERR_PRIVSEP_NO_FD); goto done; @@ -140,7 +167,7 @@ main(int argc, char *argv[]) goto done; } - err = read_commit_object(&commit, f); + err = read_commit_object(&commit, f, &expected_id); if (err) goto done; blob - d91d50bca13d75a6d38de4482f7e5605960b206c blob + 4c0bf0f3e8dcb076c30c707c610ceca0aa0bdf80 --- libexec/got-read-object/got-read-object.c +++ libexec/got-read-object/got-read-object.c @@ -38,6 +38,7 @@ #include "got_lib_object.h" #include "got_lib_object_parse.h" #include "got_lib_privsep.h" +#include "got_lib_sha1.h" #ifndef nitems #define nitems(_a) (sizeof(_a) / sizeof((_a)[0])) @@ -57,13 +58,22 @@ catch_sigint(int signo) } static const struct got_error * -send_raw_obj(struct imsgbuf *ibuf, struct got_object *obj, int fd, int outfd) +send_raw_obj(struct imsgbuf *ibuf, struct got_object *obj, + struct got_object_id *expected_id, + int fd, int outfd) { const struct got_error *err = NULL; uint8_t *data = NULL; size_t len = 0, consumed; FILE *f; + struct got_object_id id; + struct got_inflate_checksum csum; + SHA1_CTX sha1_ctx; + SHA1Init(&sha1_ctx); + memset(&csum, 0, sizeof(csum)); + csum.output_sha1 = &sha1_ctx; + if (lseek(fd, SEEK_SET, 0) == -1) { err = got_error_from_errno("lseek"); close(fd); @@ -78,9 +88,9 @@ send_raw_obj(struct imsgbuf *ibuf, struct got_object * } if (obj->size + obj->hdrlen <= GOT_PRIVSEP_INLINE_OBJECT_DATA_MAX) - err = got_inflate_to_mem(&data, &len, &consumed, NULL, f); + err = got_inflate_to_mem(&data, &len, &consumed, &csum, f); else - err = got_inflate_to_fd(&len, f, NULL, outfd); + err = got_inflate_to_fd(&len, f, &csum, outfd); if (err) goto done; @@ -89,6 +99,17 @@ send_raw_obj(struct imsgbuf *ibuf, struct got_object * goto done; } + SHA1Final(id.sha1, &sha1_ctx); + if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) { + char buf[SHA1_DIGEST_STRING_LENGTH]; + err = got_error_fmt(GOT_ERR_OBJ_CSUM, + "checksum failure for object %s", + got_sha1_digest_to_str(expected_id->sha1, buf, + sizeof(buf))); + goto done; + } + + err = got_privsep_send_raw_obj(ibuf, obj->size, obj->hdrlen, data); done: @@ -107,6 +128,7 @@ main(int argc, char *argv[]) struct imsg imsg; struct imsgbuf ibuf; size_t datalen; + struct got_object_id expected_id; signal(SIGINT, catch_sigint); @@ -144,10 +166,11 @@ main(int argc, char *argv[]) } datalen = imsg.hdr.len - IMSG_HEADER_SIZE; - if (datalen != 0) { + if (datalen != sizeof(expected_id)) { err = got_error(GOT_ERR_PRIVSEP_LEN); goto done; } + memcpy(&expected_id, imsg.data, sizeof(expected_id)); if (imsg.fd == -1) { err = got_error(GOT_ERR_PRIVSEP_NO_FD); @@ -160,6 +183,7 @@ main(int argc, char *argv[]) if (imsg.hdr.type == GOT_IMSG_RAW_OBJECT_REQUEST) { struct imsg imsg_outfd; + err = got_privsep_recv_imsg(&imsg_outfd, &ibuf, 0); if (err) { if (imsg_outfd.hdr.len == 0) @@ -189,7 +213,8 @@ main(int argc, char *argv[]) imsg_free(&imsg_outfd); goto done; } - err = send_raw_obj(&ibuf, obj, imsg.fd, imsg_outfd.fd); + err = send_raw_obj(&ibuf, obj, &expected_id, + imsg.fd, imsg_outfd.fd); imsg.fd = -1; /* imsg.fd is owned by send_raw_obj() */ if (close(imsg_outfd.fd) == -1 && err == NULL) err = got_error_from_errno("close"); blob - f3ce48de8619073672d23d6c63b6e2e5208861c6 blob + 54b081f2cd307441ac03be98dfdf41222edcf15c --- libexec/got-read-tag/got-read-tag.c +++ libexec/got-read-tag/got-read-tag.c @@ -38,6 +38,7 @@ #include "got_lib_object.h" #include "got_lib_object_parse.h" #include "got_lib_privsep.h" +#include "got_lib_sha1.h" static volatile sig_atomic_t sigint_received; @@ -48,20 +49,38 @@ catch_sigint(int signo) } static const struct got_error * -read_tag_object(struct got_tag_object **tag, FILE *f) +read_tag_object(struct got_tag_object **tag, FILE *f, + struct got_object_id *expected_id) { const struct got_error *err = NULL; - struct got_object *obj; + struct got_object *obj = NULL; size_t len; uint8_t *p; + struct got_inflate_checksum csum; + SHA1_CTX sha1_ctx; + struct got_object_id id; - err = got_inflate_to_mem(&p, &len, NULL, NULL, f); + SHA1Init(&sha1_ctx); + memset(&csum, 0, sizeof(csum)); + csum.output_sha1 = &sha1_ctx; + + err = got_inflate_to_mem(&p, &len, NULL, &csum, f); if (err) return err; + SHA1Final(id.sha1, &sha1_ctx); + if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) { + char buf[SHA1_DIGEST_STRING_LENGTH]; + err = got_error_fmt(GOT_ERR_OBJ_CSUM, + "checksum failure for object %s", + got_sha1_digest_to_str(expected_id->sha1, buf, + sizeof(buf))); + goto done; + } + err = got_object_parse_header(&obj, p, len); if (err) - return err; + goto done; if (len < obj->hdrlen + obj->size) { err = got_error(GOT_ERR_BAD_OBJ_DATA); @@ -73,7 +92,8 @@ read_tag_object(struct got_tag_object **tag, FILE *f) err = got_object_parse_tag(tag, p + obj->hdrlen, len); done: free(p); - got_object_close(obj); + if (obj) + got_object_close(obj); return err; } @@ -82,6 +102,7 @@ main(int argc, char *argv[]) { const struct got_error *err = NULL; struct imsgbuf ibuf; + size_t datalen; signal(SIGINT, catch_sigint); @@ -100,6 +121,7 @@ main(int argc, char *argv[]) struct imsg imsg; FILE *f = NULL; struct got_tag_object *tag = NULL; + struct got_object_id expected_id; if (sigint_received) { err = got_error(GOT_ERR_CANCELLED); @@ -121,6 +143,13 @@ main(int argc, char *argv[]) goto done; } + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (datalen != sizeof(expected_id)) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + goto done; + } + memcpy(&expected_id, imsg.data, sizeof(expected_id)); + if (imsg.fd == -1) { err = got_error(GOT_ERR_PRIVSEP_NO_FD); goto done; @@ -133,7 +162,7 @@ main(int argc, char *argv[]) goto done; } - err = read_tag_object(&tag, f); + err = read_tag_object(&tag, f, &expected_id); if (err) goto done; blob - aab6f584103a469db2e8b399113952f556555726 blob + 95e34c068c96ce1a4a00a1ea034531e243919dfd --- libexec/got-read-tree/got-read-tree.c +++ libexec/got-read-tree/got-read-tree.c @@ -39,6 +39,7 @@ #include "got_lib_object.h" #include "got_lib_object_parse.h" #include "got_lib_privsep.h" +#include "got_lib_sha1.h" static volatile sig_atomic_t sigint_received; @@ -50,19 +51,36 @@ catch_sigint(int signo) static const struct got_error * read_tree_object(struct got_pathlist_head *entries, int *nentries, - uint8_t **p, FILE *f) + uint8_t **p, FILE *f, struct got_object_id *expected_id) { const struct got_error *err = NULL; - struct got_object *obj; + struct got_object *obj = NULL; size_t len; + struct got_inflate_checksum csum; + SHA1_CTX sha1_ctx; + struct got_object_id id; - err = got_inflate_to_mem(p, &len, NULL, NULL, f); + SHA1Init(&sha1_ctx); + memset(&csum, 0, sizeof(csum)); + csum.output_sha1 = &sha1_ctx; + + err = got_inflate_to_mem(p, &len, NULL, &csum, f); if (err) return err; + SHA1Final(id.sha1, &sha1_ctx); + if (memcmp(expected_id->sha1, id.sha1, SHA1_DIGEST_LENGTH) != 0) { + char buf[SHA1_DIGEST_STRING_LENGTH]; + err = got_error_fmt(GOT_ERR_OBJ_CSUM, + "checksum failure for object %s", + got_sha1_digest_to_str(expected_id->sha1, buf, + sizeof(buf))); + goto done; + } + err = got_object_parse_header(&obj, *p, len); if (err) - return err; + goto done; if (len < obj->hdrlen + obj->size) { err = got_error(GOT_ERR_BAD_OBJ_DATA); @@ -73,7 +91,8 @@ read_tree_object(struct got_pathlist_head *entries, in len -= obj->hdrlen; err = got_object_parse_tree(entries, nentries, *p + obj->hdrlen, len); done: - got_object_close(obj); + if (obj) + got_object_close(obj); return err; } @@ -82,6 +101,7 @@ main(int argc, char *argv[]) { const struct got_error *err = NULL; struct imsgbuf ibuf; + size_t datalen; signal(SIGINT, catch_sigint); @@ -102,6 +122,7 @@ main(int argc, char *argv[]) struct got_pathlist_head entries; int nentries = 0; uint8_t *buf = NULL; + struct got_object_id expected_id; TAILQ_INIT(&entries); @@ -125,6 +146,13 @@ main(int argc, char *argv[]) goto done; } + datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (datalen != sizeof(expected_id)) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + goto done; + } + memcpy(&expected_id, imsg.data, sizeof(expected_id)); + if (imsg.fd == -1) { err = got_error(GOT_ERR_PRIVSEP_NO_FD); goto done; @@ -137,7 +165,8 @@ main(int argc, char *argv[]) goto done; } - err = read_tree_object(&entries, &nentries, &buf, f); + err = read_tree_object(&entries, &nentries, &buf, f, + &expected_id); if (err) goto done;