commit - 068fd2bf0c2848bb0ee960b1178e229560cadc0c
commit + ff6b18f831d03b1f4944716195089ced3e9b9fd8
blob - 76986d61d779c996002c47abcc96117f7c5c7a9d
blob + c594b658e1e12ce3a540b0176746a00706b16290
--- lib/got_lib_privsep.h
+++ lib/got_lib_privsep.h
* This behaviour is transparent to users of the library.
*
* We generally transmit data in imsg buffers, split across several messages
- * if necessary. File descriptor passing is used in cases where this is
- * impractical, such as when accessing pack files or when transferring
- * large blobs.
+ * if necessary. File descriptors are used in cases where this is impractical,
+ * such as when accessing pack files or when transferring large blobs.
*
* We currently do not exec(2) after a fork(2).
* To achieve fork+exec, relevant parts of our library functionality could
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 *);
/* TODO: Implement the above, and then add more message data types here. */
blob - 3a874e61bc0c9fade6d20095e6be681ad8b584a9
blob + f3845e17342adbffaf8c43ffc2b8143331bc475c
--- lib/object.c
+++ lib/object.c
return got_inflate_to_fd(&size, infd, outfd);
}
+static const struct got_error *
+read_blob_object_privsep_child(int outfd, int infd, int imsg_fds[2])
+{
+ const struct got_error *err = NULL;
+ struct imsgbuf ibuf;
+ int status = 0;
+
+ setproctitle("got: read blob object");
+ close(imsg_fds[0]);
+ imsg_init(&ibuf, imsg_fds[1]);
+
+ /* revoke access to most system calls */
+ if (pledge("stdio", NULL) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ err = read_blob_object(outfd, infd);
+ close(infd);
+ if (err)
+ goto done;
+
+ err = got_privsep_send_blob(&ibuf);
+done:
+ if (err) {
+ got_privsep_send_error(&ibuf, err);
+ status = 1;
+ }
+ close(outfd);
+ imsg_clear(&ibuf);
+ close(imsg_fds[1]);
+ _exit(status);
+}
+
+static const struct got_error *
+read_blob_object_privsep(int outfd, int infd)
+{
+ struct imsgbuf parent_ibuf;
+ int imsg_fds[2];
+ const struct got_error *err = NULL;
+ pid_t pid;
+ int child_status;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1)
+ return got_error_from_errno();
+
+ pid = fork();
+ if (pid == -1)
+ return got_error_from_errno();
+ else if (pid == 0) {
+ read_blob_object_privsep_child(outfd, infd, imsg_fds);
+ /* not reached */
+ }
+
+ close(imsg_fds[1]);
+ imsg_init(&parent_ibuf, imsg_fds[0]);
+ err = got_privsep_recv_blob(&parent_ibuf);
+ imsg_clear(&parent_ibuf);
+ waitpid(pid, &child_status, 0);
+ close(imsg_fds[0]);
+ if (lseek(outfd, SEEK_SET, 0) == -1)
+ err = got_error_from_errno();
+ return err;
+}
+
const struct got_error *
got_object_blob_open(struct got_blob_object **blob,
struct got_repository *repo, struct got_object *obj, size_t blocksize)
goto done;
}
- err = read_blob_object(outfd, infd);
+ err = read_blob_object_privsep(outfd, infd);
close(infd);
if (err)
goto done;
blob - 71bf646c05ae45da7a0b1a9da854bcbebd59404a
blob + da7628fd90ec8c45df94754fbc19460724c4828b
--- lib/privsep.c
+++ lib/privsep.c
return err;
}
+
+const struct got_error *
+got_privsep_send_blob(struct imsgbuf *ibuf)
+{
+ /* Data has already been written to file descriptor. */
+ if (imsg_compose(ibuf, GOT_IMSG_BLOB, 0, 0, -1, NULL, 0) == -1)
+ return got_error_from_errno();
+
+ return flush_imsg(ibuf);
+}
+
+const struct got_error *
+got_privsep_recv_blob(struct imsgbuf *ibuf)
+{
+ const struct got_error *err = NULL;
+ struct imsg imsg;
+ size_t datalen;
+
+ err = recv_one_imsg(&imsg, ibuf, 0);
+ if (err)
+ return err;
+
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+
+ switch (imsg.hdr.type) {
+ case GOT_IMSG_ERROR:
+ err = recv_imsg_error(&imsg, datalen);
+ break;
+ case GOT_IMSG_BLOB:
+ if (datalen != 0)
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ /* Data has been written to file descriptor. */
+ break;
+ default:
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+
+ imsg_free(&imsg);
+
+ return err;
+}