Commit 3840f4c96dbf09953b6c83fdc338a29817d983d4

Stefan Sperling 2018-09-13T00:06:12

fix "rpath" pledge violation in got-read-pack

diff --git a/lib/got_lib_object_parse.h b/lib/got_lib_object_parse.h
index d77cc53..b427544 100644
--- a/lib/got_lib_object_parse.h
+++ b/lib/got_lib_object_parse.h
@@ -44,5 +44,3 @@ const struct got_error *got_object_read_packed_commit_privsep(
     struct got_commit_object **, struct got_object *, struct got_pack *);
 const struct got_error *got_object_read_packed_tree_privsep(
     struct got_tree_object **, struct got_object *, struct got_pack *);
-const struct got_error *got_object_read_packed_blob_privsep(size_t *, int,
-    struct got_object *, struct got_pack *);
diff --git a/lib/got_lib_pack.h b/lib/got_lib_pack.h
index c36360e..63c033d 100644
--- a/lib/got_lib_pack.h
+++ b/lib/got_lib_pack.h
@@ -165,7 +165,7 @@ int got_packidx_get_object_idx(struct got_packidx *, struct got_object_id *);
 const struct got_error *got_packfile_open_object(struct got_object **,
     struct got_pack *, struct got_packidx *, int, struct got_object_id *);
 const struct got_error *got_packfile_extract_object(struct got_pack *,
-    struct got_object *, FILE *);
+    struct got_object *, FILE *, FILE *, FILE *);
 const struct got_error *got_packfile_extract_object_to_mem(uint8_t **, size_t *,
     struct got_object *, struct got_pack *);
 const struct got_error *got_pack_get_packfile_size(size_t *, const char *);
diff --git a/lib/got_lib_privsep.h b/lib/got_lib_privsep.h
index 3620a1f..91f70c7 100644
--- a/lib/got_lib_privsep.h
+++ b/lib/got_lib_privsep.h
@@ -93,6 +93,9 @@ enum got_imsg_type {
 	GOT_IMSG_PACKIDX,
 	GOT_IMSG_PACK,
 	GOT_IMSG_PACKED_OBJECT_REQUEST,
+
+	/* Message sending file desciprtor to a temporary file. */
+	GOT_IMSG_TMPFD,
 };
 
 /* Structure for GOT_IMSG_ERROR. */
@@ -189,6 +192,7 @@ const struct got_error *got_privsep_send_obj_req(struct imsgbuf *, int,
     struct got_object *);
 const struct got_error *got_privsep_send_blob_req(struct imsgbuf *, int);
 const struct got_error *got_privsep_send_blob_outfd(struct imsgbuf *, int);
+const struct got_error *got_privsep_send_tmpfd(struct imsgbuf *, int);
 const struct got_error *got_privsep_send_obj(struct imsgbuf *,
     struct got_object *);
 const struct got_error *got_privsep_get_imsg_obj(struct got_object **,
diff --git a/lib/object.c b/lib/object.c
index 70d904c..7c7fdf3 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -443,6 +443,62 @@ got_object_tree_get_entries(struct got_tree_object *tree)
 	return &tree->entries;
 }
 
+static const struct got_error *
+read_packed_blob_privsep(size_t *size, int outfd, struct got_object *obj,
+    struct got_pack *pack)
+{
+	const struct got_error *err = NULL;
+	int outfd_child;
+	int basefd, accumfd; /* temporary files for delta application */
+
+	basefd = got_opentempfd();
+	if (basefd == -1)
+		return got_error_from_errno();
+	accumfd = got_opentempfd();
+	if (accumfd == -1)
+		return got_error_from_errno();
+
+	outfd_child = dup(outfd);
+	if (outfd_child == -1)
+		return got_error_from_errno();
+
+	err = got_privsep_send_obj_req(pack->privsep_child->ibuf, -1, obj);
+	if (err)
+		return err;
+
+	err = got_privsep_send_blob_outfd(pack->privsep_child->ibuf,
+	    outfd_child);
+	if (err) {
+		close(outfd_child);
+		return err;
+	}
+	err = got_privsep_send_tmpfd(pack->privsep_child->ibuf,
+	    basefd);
+	if (err) {
+		close(basefd);
+		close(accumfd);
+		close(outfd_child);
+		return err;
+	}
+
+	err = got_privsep_send_tmpfd(pack->privsep_child->ibuf,
+	    accumfd);
+	if (err) {
+		close(accumfd);
+		close(outfd_child);
+		return err;
+	}
+
+	err = got_privsep_recv_blob(size, pack->privsep_child->ibuf);
+	if (err)
+		return err;
+
+	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)
@@ -480,8 +536,7 @@ got_object_blob_open(struct got_blob_object **blob,
 			if (err)
 				goto done;
 		}
-		err = got_object_read_packed_blob_privsep(&size, outfd,
-		    obj, pack);
+		err = read_packed_blob_privsep(&size, outfd, obj, pack);
 		if (err)
 			goto done;
 		obj->size = size;
diff --git a/lib/object_parse.c b/lib/object_parse.c
index 0918775..bab79fa 100644
--- a/lib/object_parse.c
+++ b/lib/object_parse.c
@@ -838,38 +838,6 @@ got_object_read_packed_tree_privsep(struct got_tree_object **tree,
 	return got_privsep_recv_tree(tree, pack->privsep_child->ibuf);
 }
 
-const struct got_error *
-got_object_read_packed_blob_privsep(size_t *size, int outfd,
-    struct got_object *obj, struct got_pack *pack)
-{
-	const struct got_error *err = NULL;
-	int outfd_child;
-
-	outfd_child = dup(outfd);
-	if (outfd_child == -1)
-		return got_error_from_errno();
-
-	err = got_privsep_send_obj_req(pack->privsep_child->ibuf, -1, obj);
-	if (err)
-		return err;
-
-	err = got_privsep_send_blob_outfd(pack->privsep_child->ibuf,
-	    outfd_child);
-	if (err) {
-		close(outfd_child);
-		return err;
-	}
-
-	err = got_privsep_recv_blob(size, pack->privsep_child->ibuf);
-	if (err)
-		return err;
-
-	if (lseek(outfd, SEEK_SET, 0) == -1)
-		err = got_error_from_errno();
-
-	return err;
-}
-
 static const struct got_error *
 request_blob(size_t *size, int outfd, int infd, struct imsgbuf *ibuf)
 {
diff --git a/lib/pack.c b/lib/pack.c
index 3560e5c..a673172 100644
--- a/lib/pack.c
+++ b/lib/pack.c
@@ -975,11 +975,10 @@ get_delta_chain_max_size(uint64_t *max_size, struct got_delta_chain *deltas)
 
 static const struct got_error *
 dump_delta_chain_to_file(size_t *result_size, struct got_delta_chain *deltas,
-    struct got_pack *pack, FILE *outfile)
+    struct got_pack *pack, FILE *outfile, FILE *base_file, FILE *accum_file)
 {
 	const struct got_error *err = NULL;
 	struct got_delta *delta;
-	FILE *base_file = NULL, *accum_file = NULL;
 	uint8_t *base_buf = NULL, *accum_buf = NULL;
 	size_t accum_size = 0;
 	uint64_t max_size;
@@ -998,17 +997,8 @@ dump_delta_chain_to_file(size_t *result_size, struct got_delta_chain *deltas,
 		accum_buf = malloc(max_size);
 		if (accum_buf == NULL)
 			return got_error_from_errno();
-	} else {
-		base_file = got_opentemp();
-		if (base_file == NULL)
-			return got_error_from_errno();
-
-		accum_file = got_opentemp();
-		if (accum_file == NULL) {
-			err = got_error_from_errno();
-			fclose(base_file);
-			return err;
-		}
+		base_file = NULL;
+		accum_file = NULL;
 	}
 
 	/* Deltas are ordered in ascending order. */
@@ -1224,7 +1214,7 @@ done:
 
 const struct got_error *
 got_packfile_extract_object(struct got_pack *pack, struct got_object *obj,
-    FILE *outfile)
+    FILE *outfile, FILE *base_file, FILE *accum_file)
 {
 	const struct got_error *err = NULL;
 
@@ -1247,7 +1237,7 @@ got_packfile_extract_object(struct got_pack *pack, struct got_object *obj,
 		}
 	} else
 		err = dump_delta_chain_to_file(&obj->size, &obj->deltas, pack,
-		    outfile);
+		    outfile, base_file, accum_file);
 
 	return err;
 }
diff --git a/lib/privsep.c b/lib/privsep.c
index b7cdab1..9079955 100644
--- a/lib/privsep.c
+++ b/lib/privsep.c
@@ -277,6 +277,16 @@ got_privsep_send_blob_outfd(struct imsgbuf *ibuf, int outfd)
 }
 
 const struct got_error *
+got_privsep_send_tmpfd(struct imsgbuf *ibuf, int fd)
+{
+	if (imsg_compose(ibuf, GOT_IMSG_TMPFD, 0, 0, fd, NULL, 0)
+	    == -1)
+		return got_error_from_errno();
+
+	return flush_imsg(ibuf);
+}
+
+const struct got_error *
 got_privsep_send_obj(struct imsgbuf *ibuf, struct got_object *obj)
 {
 	struct got_imsg_object iobj;
diff --git a/libexec/got-read-pack/got-read-pack.c b/libexec/got-read-pack/got-read-pack.c
index 001b16f..51e3ea5 100644
--- a/libexec/got-read-pack/got-read-pack.c
+++ b/libexec/got-read-pack/got-read-pack.c
@@ -180,67 +180,82 @@ tree_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
 }
 
 static const struct got_error *
-blob_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
-    struct got_packidx *packidx, struct got_object_cache *objcache)
+receive_file(FILE **f, struct imsgbuf *ibuf, int imsg_code)
 {
-	const struct got_error *err = NULL;
-	struct got_object *obj = NULL;
-	FILE *f = NULL;
-	struct imsg imsg_outfd;
+	const struct got_error *err;
+	struct imsg imsg;
 	size_t datalen;
 
-	memset(&imsg_outfd, 0, sizeof(imsg_outfd));
-	imsg_outfd.fd = -1;
-
-	err = get_object(&obj, imsg, ibuf, pack, packidx, objcache,
-	    GOT_OBJ_TYPE_BLOB);
-	if (err)
-		return err;
-
-	err = got_privsep_recv_imsg(&imsg_outfd, ibuf, 0);
+	err = got_privsep_recv_imsg(&imsg, ibuf, 0);
 	if (err)
 		return err;
 
-	if (imsg_outfd.hdr.type != GOT_IMSG_BLOB_OUTFD) {
+	if (imsg.hdr.type != imsg_code) {
 		err = got_error(GOT_ERR_PRIVSEP_MSG);
 		goto done;
 	}
 
-	datalen = imsg_outfd.hdr.len - IMSG_HEADER_SIZE;
+	datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != 0) {
 		err = got_error(GOT_ERR_PRIVSEP_LEN);
 		goto done;
 	}
-	if (imsg_outfd.fd == -1) {
+	if (imsg.fd == -1) {
 		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 		goto done;
 	}
 
-	f = fdopen(imsg_outfd.fd, "w+");
-	if (f == NULL) {
+	*f = fdopen(imsg.fd, "w+");
+	if (*f == NULL) {
+		close(imsg.fd);
 		err = got_error_from_errno();
 		goto done;
 	}
+done:
+	imsg_free(&imsg);
+	return err;
+}
 
-	err = got_packfile_extract_object(pack, obj, f);
+static const struct got_error *
+blob_request(struct imsg *imsg, struct imsgbuf *ibuf, struct got_pack *pack,
+    struct got_packidx *packidx, struct got_object_cache *objcache)
+{
+	const struct got_error *err = NULL;
+	struct got_object *obj = NULL;
+	FILE *outfile = NULL, *basefile = NULL, *accumfile = NULL;
+
+	err = get_object(&obj, imsg, ibuf, pack, packidx, objcache,
+	    GOT_OBJ_TYPE_BLOB);
+	if (err)
+		return err;
+
+	err = receive_file(&outfile, ibuf, GOT_IMSG_BLOB_OUTFD);
+	if (err)
+		return err;
+	err = receive_file(&basefile, ibuf, GOT_IMSG_TMPFD);
+	if (err)
+		return err;
+	err = receive_file(&accumfile, ibuf, GOT_IMSG_TMPFD);
+	if (err)
+		return err;
+
+	err = got_packfile_extract_object(pack, obj, outfile, basefile,
+	    accumfile);
 	if (err)
 		goto done;
 
 	err = got_privsep_send_blob(ibuf, obj->size);
 done:
-	if (f)
-		fclose(f);
-	else if (imsg_outfd.fd != -1)
-		close(imsg_outfd.fd);
-	imsg_free(&imsg_outfd);
+	if (outfile)
+		fclose(outfile);
+	if (basefile)
+		fclose(basefile);
+	if (accumfile)
+		fclose(accumfile);
 	if (obj)
 		got_object_close(obj);
-	if (err) {
-		if (err->code == GOT_ERR_PRIVSEP_PIPE)
-			err = NULL;
-		else
-			got_privsep_send_error(ibuf, err);
-	}
+	if (err && err->code != GOT_ERR_PRIVSEP_PIPE)
+		got_privsep_send_error(ibuf, err);
 
 	return err;
 }