commit 2967a784ac51b6b48cb8165fd90ec290094455c8 from: Stefan Sperling date: Tue Apr 24 11:30:34 2018 UTC verify size of blob received from privsep child commit - ff6b18f831d03b1f4944716195089ced3e9b9fd8 commit + 2967a784ac51b6b48cb8165fd90ec290094455c8 blob - c594b658e1e12ce3a540b0176746a00706b16290 blob + 34977194ae28b73fef4ee4902fd621efaa92ef12 --- lib/got_lib_privsep.h +++ lib/got_lib_privsep.h @@ -123,6 +123,11 @@ struct got_imsg_tree_object { int nentries; /* This many TREE_ENTRY messages follow. */ }; +/* Structure for GOT_IMSG_BLOB. */ +struct got_imsg_blob { + size_t size; +}; + void got_privsep_send_error(struct imsgbuf *, const struct got_error *); const struct got_error *got_privsep_send_obj(struct imsgbuf *, struct got_object *, int); @@ -136,7 +141,7 @@ const struct got_error *got_privsep_recv_tree(struct g struct imsgbuf *); const struct got_error *got_privsep_send_tree(struct imsgbuf *, struct got_tree_object *); -const struct got_error *got_privsep_send_blob(struct imsgbuf *); -const struct got_error *got_privsep_recv_blob(struct imsgbuf *); +const struct got_error *got_privsep_send_blob(struct imsgbuf *, size_t); +const struct got_error *got_privsep_recv_blob(size_t *, struct imsgbuf *); /* TODO: Implement the above, and then add more message data types here. */ blob - f3845e17342adbffaf8c43ffc2b8143331bc475c blob + 6a880752bad61cf62471ea9cf36b1967548859ec --- lib/object.c +++ lib/object.c @@ -1016,11 +1016,9 @@ got_object_tree_close(struct got_tree_object *tree) } static const struct got_error * -read_blob_object(int outfd, int infd) +read_blob_object(size_t *size, int outfd, int infd) { - size_t size; - - return got_inflate_to_fd(&size, infd, outfd); + return got_inflate_to_fd(size, infd, outfd); } static const struct got_error * @@ -1029,6 +1027,7 @@ read_blob_object_privsep_child(int outfd, int infd, in const struct got_error *err = NULL; struct imsgbuf ibuf; int status = 0; + size_t size; setproctitle("got: read blob object"); close(imsg_fds[0]); @@ -1040,12 +1039,12 @@ read_blob_object_privsep_child(int outfd, int infd, in goto done; } - err = read_blob_object(outfd, infd); + err = read_blob_object(&size, outfd, infd); close(infd); if (err) goto done; - err = got_privsep_send_blob(&ibuf); + err = got_privsep_send_blob(&ibuf, size); done: if (err) { got_privsep_send_error(&ibuf, err); @@ -1058,7 +1057,7 @@ done: } static const struct got_error * -read_blob_object_privsep(int outfd, int infd) +read_blob_object_privsep(size_t *size, int outfd, int infd) { struct imsgbuf parent_ibuf; int imsg_fds[2]; @@ -1079,7 +1078,7 @@ read_blob_object_privsep(int outfd, int infd) close(imsg_fds[1]); imsg_init(&parent_ibuf, imsg_fds[0]); - err = got_privsep_recv_blob(&parent_ibuf); + err = got_privsep_recv_blob(size, &parent_ibuf); imsg_clear(&parent_ibuf); waitpid(pid, &child_status, 0); close(imsg_fds[0]); @@ -1115,6 +1114,8 @@ got_object_blob_open(struct got_blob_object **blob, goto done; } else { int infd, outfd; + size_t size; + struct stat sb; err = open_loose_object(&infd, obj, repo); if (err) @@ -1128,11 +1129,29 @@ got_object_blob_open(struct got_blob_object **blob, goto done; } - err = read_blob_object_privsep(outfd, infd); + err = read_blob_object_privsep(&size, outfd, infd); close(infd); if (err) goto done; + if (size != obj->hdrlen + obj->size) { + err = got_error(GOT_ERR_BAD_OBJ_HDR); + close(outfd); + goto done; + } + + if (fstat(outfd, &sb) == -1) { + err = got_error_from_errno(); + close(outfd); + goto done; + } + + if (sb.st_size != size) { + err = got_error(GOT_ERR_PRIVSEP_LEN); + close(outfd); + goto done; + } + (*blob)->f = fdopen(outfd, "rb"); if ((*blob)->f == NULL) { err = got_error_from_errno(); blob - da7628fd90ec8c45df94754fbc19460724c4828b blob + b542a8d8493a8740e0a95f43ba093ec43ecd36e7 --- lib/privsep.c +++ lib/privsep.c @@ -609,20 +609,26 @@ done: } const struct got_error * -got_privsep_send_blob(struct imsgbuf *ibuf) +got_privsep_send_blob(struct imsgbuf *ibuf, size_t size) { + struct got_imsg_blob iblob; + + iblob.size = size; /* Data has already been written to file descriptor. */ - if (imsg_compose(ibuf, GOT_IMSG_BLOB, 0, 0, -1, NULL, 0) == -1) + + if (imsg_compose(ibuf, GOT_IMSG_BLOB, 0, 0, -1, &iblob, sizeof(iblob)) + == -1) return got_error_from_errno(); return flush_imsg(ibuf); } const struct got_error * -got_privsep_recv_blob(struct imsgbuf *ibuf) +got_privsep_recv_blob(size_t *size, struct imsgbuf *ibuf) { const struct got_error *err = NULL; struct imsg imsg; + struct got_imsg_blob iblob; size_t datalen; err = recv_one_imsg(&imsg, ibuf, 0); @@ -636,8 +642,10 @@ got_privsep_recv_blob(struct imsgbuf *ibuf) err = recv_imsg_error(&imsg, datalen); break; case GOT_IMSG_BLOB: - if (datalen != 0) + if (datalen != sizeof(iblob)) err = got_error(GOT_ERR_PRIVSEP_LEN); + memcpy(&iblob, imsg.data, sizeof(iblob)); + *size = iblob.size; /* Data has been written to file descriptor. */ break; default: