"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
convert imsg->fd to imsg_get_fd()
To:
gameoftrees@openbsd.org
Date:
Wed, 17 Jan 2024 12:01:06 +0100

Download raw body.

Thread
This is a first step in stopping reaching into the imsg struct.
Follow-up will be for imsg_get_data(), _len() etc, this was getting big
enough and tricky to review to be worth being sent on its own.

recap: now (in -CURRENT) imsg_free() closes imsg.fd too, unless it was
requested by the application with imsg_get_fd().

There is also a (supposely) fd leak in got-read-pack.  We dup(imsg.fd)
and then leave imsg.fd alone.  in -CURRENT this is not a leak since
imsg_free() will close imsg.fd too, but in the previous release I
believe it's a fd leak.  I 'fixed' it to just obtain the fd.

regress seems happy, gotwebd by manual inspection too.

Oh, this also means that got can't be built on the latest release.


diff /home/op/w/got
commit - cfcfb026c8c94bb60b400f6b21b89bce7b698873
path + /home/op/w/got
blob - 9b609e44eeac3d33dce8caa01cf42c14e12968fd
file + gotd/auth.c
--- gotd/auth.c
+++ gotd/auth.c
@@ -187,6 +187,7 @@ recv_authreq(struct imsg *imsg, struct gotd_imsgev *ie
 	char *username = NULL;
 	size_t len;
 	const size_t maxlen = MAX_IMSGSIZE - IMSG_HEADER_SIZE;
+	int fd = -1;
 
 	log_debug("authentication request received");
 
@@ -196,10 +197,11 @@ recv_authreq(struct imsg *imsg, struct gotd_imsgev *ie
 
 	memcpy(&iauth, imsg->data, datalen);
 
-	if (imsg->fd == -1)
+	fd = imsg_get_fd(imsg);
+	if (fd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
-	if (getpeereid(imsg->fd, &euid, &egid) == -1)
+	if (getpeereid(fd, &euid, &egid) == -1)
 		return got_error_from_errno("getpeerid");
 
 	if (iauth.euid != euid)
blob - ed4f349309e803afa86a9c0fa10c1b204d43250a
file + gotd/gotd.c
--- gotd/gotd.c
+++ gotd/gotd.c
@@ -668,7 +668,7 @@ recv_connect(uint32_t *client_id, struct imsg *imsg)
 		return got_error(GOT_ERR_PRIVSEP_LEN);
 	memcpy(&iconnect, imsg->data, sizeof(iconnect));
 
-	s = imsg->fd;
+	s = imsg_get_fd(imsg);
 	if (s == -1) {
 		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 		goto done;
blob - 4dcacace4ec9959df611dda2a6fa9adf1eb3fb90
file + gotd/repo_read.c
--- gotd/repo_read.c
+++ gotd/repo_read.c
@@ -267,11 +267,12 @@ list_refs(struct imsg *imsg)
 	size_t datalen;
 	struct gotd_imsg_reflist irefs;
 	struct imsgbuf ibuf;
-	int client_fd = imsg->fd;
+	int client_fd;
 	struct got_object_id *head_target_id = NULL;
 
 	TAILQ_INIT(&refs);
 
+	client_fd = imsg_get_fd(imsg);
 	if (client_fd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
@@ -562,9 +563,6 @@ receive_delta_cache_fd(struct imsg *imsg,
 
 	log_debug("receiving delta cache file");
 
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
-
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != sizeof(ireq))
 		return got_error(GOT_ERR_PRIVSEP_LEN);
@@ -573,7 +571,10 @@ receive_delta_cache_fd(struct imsg *imsg,
 	if (client->delta_cache_fd != -1)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
-	client->delta_cache_fd = imsg->fd;
+	client->delta_cache_fd = imsg_get_fd(imsg);
+	if (client->delta_cache_fd == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
+
 	client->report_progress = ireq.report_progress;
 	return NULL;
 }
@@ -587,9 +588,6 @@ receive_pack_pipe(struct imsg *imsg, struct gotd_imsge
 
 	log_debug("receiving pack pipe descriptor");
 
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
-
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != sizeof(ireq))
 		return got_error(GOT_ERR_PRIVSEP_LEN);
@@ -598,7 +596,10 @@ receive_pack_pipe(struct imsg *imsg, struct gotd_imsge
 	if (client->pack_pipe != -1)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
-	client->pack_pipe = imsg->fd;
+	client->pack_pipe = imsg_get_fd(imsg);
+	if (client->pack_pipe == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
+
 	return NULL;
 }
 
@@ -776,13 +777,13 @@ recv_connect(struct imsg *imsg)
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != 0)
 		return got_error(GOT_ERR_PRIVSEP_LEN);
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
 	if (repo_read.session_fd != -1)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
-	repo_read.session_fd = imsg->fd;
+	repo_read.session_fd = imsg_get_fd(imsg);
+	if (repo_read.session_fd == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
 	imsg_init(&iev->ibuf, repo_read.session_fd);
 	iev->handler = repo_read_dispatch_session;
blob - 77d19b7ba1f7170166ad70f68c5f8c7e0fe92f3c
file + gotd/repo_write.c
--- gotd/repo_write.c
+++ gotd/repo_write.c
@@ -243,10 +243,11 @@ list_refs(struct imsg *imsg)
 	size_t datalen;
 	struct gotd_imsg_reflist irefs;
 	struct imsgbuf ibuf;
-	int client_fd = imsg->fd;
+	int client_fd;
 
 	TAILQ_INIT(&refs);
 
+	client_fd = imsg_get_fd(imsg);
 	if (client_fd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
@@ -1227,12 +1228,12 @@ recv_packfile(int *have_packfile, struct imsg *imsg)
 
 	imsg_init(&ibuf, client->fd);
 
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
-
 	pack = &client->pack;
 	memset(pack, 0, sizeof(*pack));
-	pack->fd = imsg->fd;
+	pack->fd = imsg_get_fd(imsg);
+	if (pack->fd == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
+
 	err = got_delta_cache_alloc(&pack->delta_cache);
 	if (err)
 		return err;
@@ -1593,9 +1594,6 @@ receive_pack_pipe(struct imsg *imsg, struct gotd_imsge
 
 	log_debug("receiving pack pipe descriptor");
 
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
-
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != sizeof(ireq))
 		return got_error(GOT_ERR_PRIVSEP_LEN);
@@ -1604,7 +1602,10 @@ receive_pack_pipe(struct imsg *imsg, struct gotd_imsge
 	if (client->pack_pipe != -1)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
-	client->pack_pipe = imsg->fd;
+	client->pack_pipe = imsg_get_fd(imsg);
+	if (client->pack_pipe == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
+
 	return NULL;
 }
 
@@ -1617,9 +1618,6 @@ receive_pack_idx(struct imsg *imsg, struct gotd_imsgev
 
 	log_debug("receiving pack index output file");
 
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
-
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != sizeof(ireq))
 		return got_error(GOT_ERR_PRIVSEP_LEN);
@@ -1628,7 +1626,10 @@ receive_pack_idx(struct imsg *imsg, struct gotd_imsgev
 	if (client->packidx_fd != -1)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
-	client->packidx_fd = imsg->fd;
+	client->packidx_fd = imsg_get_fd(imsg);
+	if (client->packidx_fd == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
+
 	return NULL;
 }
 
@@ -1756,13 +1757,13 @@ recv_connect(struct imsg *imsg)
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != 0)
 		return got_error(GOT_ERR_PRIVSEP_LEN);
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
 	if (repo_write.session_fd != -1)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
-	repo_write.session_fd = imsg->fd;
+	repo_write.session_fd = imsg_get_fd(imsg);
+	if (repo_write.session_fd == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
 	imsg_init(&iev->ibuf, repo_write.session_fd);
 	iev->handler = repo_write_dispatch_session;
blob - 1c4f5ef4003d20c175c7cccfb4dd5cf5a9f79c80
file + gotd/session.c
--- gotd/session.c
+++ gotd/session.c
@@ -1303,12 +1303,11 @@ recv_connect(struct imsg *imsg)
 		return got_error(GOT_ERR_PRIVSEP_LEN);
 	memcpy(&iconnect, imsg->data, sizeof(iconnect));
 
-	if (imsg->fd == -1)
-		return got_error(GOT_ERR_PRIVSEP_NO_FD);
-
-	client->fd = imsg->fd;
 	client->euid = iconnect.euid;
 	client->egid = iconnect.egid;
+	client->fd = imsg_get_fd(imsg);
+	if (client->fd == -1)
+		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
 	imsg_init(&client->iev.ibuf, client->fd);
 	client->iev.handler = session_dispatch_client;
@@ -1328,6 +1327,7 @@ recv_repo_child(struct imsg *imsg)
 	struct gotd_imsg_connect_repo_child ichild;
 	struct gotd_session_client *client = &gotd_session_client;
 	size_t datalen;
+	int fd;
 
 	if (client->state != GOTD_STATE_EXPECT_LIST_REFS)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
@@ -1351,10 +1351,11 @@ recv_repo_child(struct imsg *imsg)
 		return got_error_msg(GOT_ERR_PRIVSEP_MSG,
 		    "bad child process type");
 
-	if (imsg->fd == -1)
+	fd = imsg_get_fd(imsg);
+	if (fd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
-	imsg_init(&client->repo_child_iev.ibuf, imsg->fd);
+	imsg_init(&client->repo_child_iev.ibuf, fd);
 	client->repo_child_iev.handler = session_dispatch_repo_child;
 	client->repo_child_iev.events = EV_READ;
 	client->repo_child_iev.handler_arg = NULL;
blob - bde889cb381f5d8e90f44b27a11986e29f2f27d2
file + gotwebd/config.c
--- gotwebd/config.c
+++ gotwebd/config.c
@@ -132,13 +132,11 @@ config_getsock(struct gotwebd *env, struct imsg *imsg)
 
 	/* create a new socket */
 	if ((sock = calloc(1, sizeof(*sock))) == NULL) {
-		if (imsg->fd != -1)
-			close(imsg->fd);
 		return 1;
 	}
 
 	memcpy(&sock->conf, &sock_conf, sizeof(sock->conf));
-	sock->fd = imsg->fd;
+	sock->fd = imsg_get_fd(imsg);
 
 	TAILQ_INSERT_TAIL(&env->sockets, sock, entry);
 
@@ -195,7 +193,7 @@ config_getfd(struct gotwebd *env, struct imsg *imsg)
 {
 	struct socket *sock;
 	uint8_t *p = imsg->data;
-	int sock_id, match = 0, i;
+	int sock_id, match = 0, i, j;
 
 	if (IMSG_DATA_SIZE(imsg) != sizeof(sock_id))
 		fatalx("%s: wrong size", __func__);
@@ -206,16 +204,18 @@ config_getfd(struct gotwebd *env, struct imsg *imsg)
 		const int nfds = (GOTWEB_PACK_NUM_TEMPFILES + PRIV_FDS__MAX);
 		for (i = 0; i < nfds; i++) {
 			if (i < PRIV_FDS__MAX && sock->priv_fd[i] == -1) {
+				sock->priv_fd[i] = imsg_get_fd(imsg);
 				log_debug("%s: assigning socket %d priv_fd %d",
-				    __func__, sock_id, imsg->fd);
-				sock->priv_fd[i] = imsg->fd;
+				    __func__, sock_id, sock->priv_fd[i]);
 				match = 1;
 				break;
 			}
-			if (sock->pack_fds[i - PRIV_FDS__MAX] == -1) {
+
+			j = i - PRIV_FDS__MAX;
+			if (sock->pack_fds[j] == -1) {
+				sock->pack_fds[j] = imsg_get_fd(imsg);
 				log_debug("%s: assigning socket %d pack_fd %d",
-				    __func__, sock_id, imsg->fd);
-				sock->pack_fds[i - PRIV_FDS__MAX] = imsg->fd;
+				    __func__, sock_id, sock->pack_fds[j]);
 				match = 1;
 				break;
 			}
blob - 4b4b5a6eb83db18b356def90dad243397510f7d5
file + lib/serve.c
--- lib/serve.c
+++ lib/serve.c
@@ -666,6 +666,7 @@ recv_done(int *packfd, int outfd, struct imsgbuf *ibuf
 {
 	const struct got_error *err;
 	struct imsg imsg;
+	int fd;
 
 	*packfd = -1;
 
@@ -686,8 +687,9 @@ recv_done(int *packfd, int outfd, struct imsgbuf *ibuf
 			err = gotd_imsg_recv_error(NULL, &imsg);
 			break;
 		case GOTD_IMSG_PACKFILE_PIPE:
-			if (imsg.fd != -1)
-				*packfd = imsg.fd;
+			fd = imsg_get_fd(&imsg);
+			if (fd != -1)
+				*packfd = fd;
 			else
 				err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			break;
@@ -1072,10 +1074,10 @@ recv_packfile(struct imsg *imsg, int infd)
 	if (datalen != 0)
 		return got_error(GOT_ERR_PRIVSEP_MSG);
 
-	if (imsg->fd == -1)
+	packfd = imsg_get_fd(imsg);
+	if (packfd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
-	packfd = imsg->fd;
 	while (!pack_done) {
 		ssize_t r = 0;
 
blob - cb8defa207bb0da2d9fc2ed1c5efbf17d671c6c1
file + libexec/got-fetch-pack/got-fetch-pack.c
--- libexec/got-fetch-pack/got-fetch-pack.c
+++ libexec/got-fetch-pack/got-fetch-pack.c
@@ -893,7 +893,7 @@ main(int argc, char **argv)
 		goto done;
 	}
 	memcpy(&fetch_req, imsg.data, sizeof(fetch_req));
-	fetchfd = imsg.fd;
+	fetchfd = imsg_get_fd(&imsg);
 
 	if (datalen != sizeof(fetch_req) +
 	    fetch_req.worktree_branch_len + fetch_req.remote_head_len) {
@@ -1070,7 +1070,7 @@ main(int argc, char **argv)
 		err = got_error(GOT_ERR_PRIVSEP_LEN);
 		goto done;
 	}
-	packfd = imsg.fd;
+	packfd = imsg_get_fd(&imsg);
 
 	err = fetch_pack(fetchfd, packfd, pack_sha1, &have_refs,
 	    fetch_req.fetch_all_branches, &wanted_branches,
blob - 9d814fc7b44d62a6a31880c030beba561c834ba0
file + libexec/got-index-pack/got-index-pack.c
--- libexec/got-index-pack/got-index-pack.c
+++ libexec/got-index-pack/got-index-pack.c
@@ -129,7 +129,7 @@ main(int argc, char **argv)
 		goto done;
 	}
 	memcpy(pack_hash, imsg.data, sizeof(pack_hash));
-	pack.fd = imsg.fd;
+	pack.fd = imsg_get_fd(&imsg);
 
 	err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
 	if (err)
@@ -144,7 +144,7 @@ main(int argc, char **argv)
 		err = got_error(GOT_ERR_PRIVSEP_LEN);
 		goto done;
 	}
-	idxfd = imsg.fd;
+	idxfd = imsg_get_fd(&imsg);
 
 	for (i = 0; i < nitems(tmpfiles); i++) {
 		err = got_privsep_recv_imsg(&imsg, &ibuf, 0);
@@ -160,7 +160,7 @@ main(int argc, char **argv)
 			err = got_error(GOT_ERR_PRIVSEP_LEN);
 			goto done;
 		}
-		tmpfd = imsg.fd;
+		tmpfd = imsg_get_fd(&imsg);
 		tmpfiles[i] = fdopen(tmpfd, "w+");
 		if (tmpfiles[i] == NULL) {
 			err = got_error_from_errno("fdopen");
blob - e4c92bbc9d32142b0790c085ca4e39a36991795e
file + libexec/got-read-blob/got-read-blob.c
--- libexec/got-read-blob/got-read-blob.c
+++ libexec/got-read-blob/got-read-blob.c
@@ -72,6 +72,7 @@ main(int argc, char *argv[])
 	for (;;) {
 		struct imsg imsg, imsg_outfd;
 		FILE *f = NULL;
+		int fd = -1, outfd = -1;
 		size_t size;
 		struct got_object *obj = NULL;
 		uint8_t *buf = NULL;
@@ -85,9 +86,7 @@ main(int argc, char *argv[])
 		csum.output_ctx = &ctx;
 
 		memset(&imsg, 0, sizeof(imsg));
-		imsg.fd = -1;
 		memset(&imsg_outfd, 0, sizeof(imsg_outfd));
-		imsg_outfd.fd = -1;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -116,7 +115,8 @@ main(int argc, char *argv[])
 		}
 		memcpy(&expected_id, imsg.data, sizeof(expected_id));
 
-		if (imsg.fd == -1) {
+		fd = imsg_get_fd(&imsg);
+		if (fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
@@ -141,21 +141,22 @@ main(int argc, char *argv[])
 			err = got_error(GOT_ERR_PRIVSEP_LEN);
 			goto done;
 		}
-		if (imsg_outfd.fd == -1) {
+		outfd = imsg_get_fd(&imsg_outfd);
+		if (outfd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
 
-		err = got_object_read_header(&obj, imsg.fd);
+		err = got_object_read_header(&obj, fd);
 		if (err)
 			goto done;
 
-		if (lseek(imsg.fd, SEEK_SET, 0) == -1) {
+		if (lseek(fd, SEEK_SET, 0) == -1) {
 			err = got_error_from_errno("lseek");
 			goto done;
 		}
 
-		f = fdopen(imsg.fd, "rb");
+		f = fdopen(fd, "rb");
 		if (f == NULL) {
 			err = got_error_from_errno("fdopen");
 			goto done;
@@ -167,7 +168,7 @@ main(int argc, char *argv[])
 			if (err)
 				goto done;
 		} else {
-			err = got_inflate_to_fd(&size, f, &csum, imsg_outfd.fd);
+			err = got_inflate_to_fd(&size, f, &csum, outfd);
 			if (err)
 				goto done;
 		}
@@ -188,12 +189,12 @@ done:
 		if (f) {
 			if (fclose(f) == EOF && err == NULL)
 				err = got_error_from_errno("fclose");
-		} else if (imsg.fd != -1) {
-			if (close(imsg.fd) == -1 && err == NULL)
+		} else if (fd != -1) {
+			if (close(fd) == -1 && err == NULL)
 				err = got_error_from_errno("close");
 		}
-		if (imsg_outfd.fd != -1) {
-			if (close(imsg_outfd.fd) == -1 && err == NULL)
+		if (outfd != -1) {
+			if (close(outfd) == -1 && err == NULL)
 				err = got_error_from_errno("close");
 		}
 
blob - 349ab039f60b6ca3745866df6ab52257ed03fd1b
file + libexec/got-read-commit/got-read-commit.c
--- libexec/got-read-commit/got-read-commit.c
+++ libexec/got-read-commit/got-read-commit.c
@@ -74,6 +74,7 @@ main(int argc, char *argv[])
 		struct imsg imsg;
 		struct got_commit_object *commit = NULL;
 		struct got_object_id expected_id;
+		int fd = -1;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -102,19 +103,20 @@ main(int argc, char *argv[])
 		}
 		memcpy(&expected_id, imsg.data, sizeof(expected_id));
 
-		if (imsg.fd == -1) {
+		fd = imsg_get_fd(&imsg);
+		if (fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
 
-		err = got_object_read_commit(&commit, imsg.fd, &expected_id, 0);
+		err = got_object_read_commit(&commit, fd, &expected_id, 0);
 		if (err)
 			goto done;
 
 		err = got_privsep_send_commit(&ibuf, commit);
 		got_object_commit_close(commit);
 done:
-		if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL)
+		if (fd != -1 && close(fd) == -1 && err == NULL)
 			err = got_error_from_errno("close");
 		imsg_free(&imsg);
 		if (err)
blob - 99f2a5a5d4fdc582151efa06eb679bf4bfd09a69
file + libexec/got-read-gitconfig/got-read-gitconfig.c
--- libexec/got-read-gitconfig/got-read-gitconfig.c
+++ libexec/got-read-gitconfig/got-read-gitconfig.c
@@ -359,9 +359,9 @@ main(int argc, char *argv[])
 
 	for (;;) {
 		struct imsg imsg;
+		int fd = -1;
 
 		memset(&imsg, 0, sizeof(imsg));
-		imsg.fd = -1;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -385,14 +385,15 @@ main(int argc, char *argv[])
 				err = got_error(GOT_ERR_PRIVSEP_LEN);
 				break;
 			}
-			if (imsg.fd == -1){
+			fd = imsg_get_fd(&imsg);
+			if (fd == -1){
 				err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 				break;
 			}
 
 			if (gitconfig)
 				got_gitconfig_close(gitconfig);
-			err = got_gitconfig_open(&gitconfig, imsg.fd);
+			err = got_gitconfig_open(&gitconfig, fd);
 			break;
 		case GOT_IMSG_GITCONFIG_REPOSITORY_FORMAT_VERSION_REQUEST:
 			err = gitconfig_num_request(&ibuf, gitconfig, "core",
@@ -420,8 +421,8 @@ main(int argc, char *argv[])
 			break;
 		}
 
-		if (imsg.fd != -1) {
-			if (close(imsg.fd) == -1 && err == NULL)
+		if (fd != -1) {
+			if (close(fd) == -1 && err == NULL)
 				err = got_error_from_errno("close");
 		}
 
blob - 0c3010abcae4d96473ce98b378f9dd456bbfe4c0
file + libexec/got-read-gotconfig/got-read-gotconfig.c
--- libexec/got-read-gotconfig/got-read-gotconfig.c
+++ libexec/got-read-gotconfig/got-read-gotconfig.c
@@ -503,9 +503,9 @@ main(int argc, char *argv[])
 
 	for (;;) {
 		struct imsg imsg;
+		int fd = -1;
 
 		memset(&imsg, 0, sizeof(imsg));
-		imsg.fd = -1;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -529,14 +529,15 @@ main(int argc, char *argv[])
 				err = got_error(GOT_ERR_PRIVSEP_LEN);
 				break;
 			}
-			if (imsg.fd == -1){
+			fd = imsg_get_fd(&imsg);
+			if (fd == -1){
 				err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 				break;
 			}
 
 			if (gotconfig)
 				gotconfig_free(gotconfig);
-			err = gotconfig_parse(&gotconfig, filename, &imsg.fd);
+			err = gotconfig_parse(&gotconfig, filename, &fd);
 			if (err)
 				break;
 			err = validate_config(gotconfig);
@@ -588,8 +589,8 @@ main(int argc, char *argv[])
 			break;
 		}
 
-		if (imsg.fd != -1) {
-			if (close(imsg.fd) == -1 && err == NULL)
+		if (fd != -1) {
+			if (close(fd) == -1 && err == NULL)
 				err = got_error_from_errno("close");
 		}
 
blob - 4396edfaac8ae4bf97e83da86f49717f922fdee0
file + libexec/got-read-object/got-read-object.c
--- libexec/got-read-object/got-read-object.c
+++ libexec/got-read-object/got-read-object.c
@@ -110,6 +110,8 @@ main(int argc, char *argv[])
 #endif
 
 	for (;;) {
+		int fd = -1, outfd = -1;
+
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
 			break;
@@ -138,12 +140,13 @@ main(int argc, char *argv[])
 		}
 		memcpy(&expected_id, imsg.data, sizeof(expected_id));
 
-		if (imsg.fd == -1) {
+		fd = imsg_get_fd(&imsg);
+		if (fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
 
-		err = got_object_read_header(&obj, imsg.fd);
+		err = got_object_read_header(&obj, fd);
 		if (err)
 			goto done;
 
@@ -174,15 +177,16 @@ main(int argc, char *argv[])
 				imsg_free(&imsg_outfd);
 				goto done;
 			}
-			if (imsg_outfd.fd == -1) {
+			outfd = imsg_get_fd(&imsg_outfd);
+			if (outfd == -1) {
 				err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 				imsg_free(&imsg_outfd);
 				goto done;
 			}
 			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)
+			    fd, outfd);
+			fd = -1; /* fd is owned by send_raw_obj() */
+			if (close(outfd) == -1 && err == NULL)
 				err = got_error_from_errno("close");
 			imsg_free(&imsg_outfd);
 			if (err)
@@ -190,7 +194,7 @@ main(int argc, char *argv[])
 		} else
 			err = got_privsep_send_obj(&ibuf, obj);
 done:
-		if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL)
+		if (fd != -1 && close(fd) == -1 && err == NULL)
 			err = got_error_from_errno("close");
 		imsg_free(&imsg);
 		if (obj)
blob - 47432bc05913abd4ec23ec1b1aed9d66279e7d3c
file + libexec/got-read-pack/got-read-pack.c
--- libexec/got-read-pack/got-read-pack.c
+++ libexec/got-read-pack/got-read-pack.c
@@ -268,6 +268,7 @@ receive_file(FILE **f, struct imsgbuf *ibuf, uint32_t 
 	const struct got_error *err;
 	struct imsg imsg;
 	size_t datalen;
+	int fd;
 
 	err = got_privsep_recv_imsg(&imsg, ibuf, 0);
 	if (err)
@@ -283,15 +284,16 @@ receive_file(FILE **f, struct imsgbuf *ibuf, uint32_t 
 		err = got_error(GOT_ERR_PRIVSEP_LEN);
 		goto done;
 	}
-	if (imsg.fd == -1) {
+	fd = imsg_get_fd(&imsg);
+	if (fd == -1) {
 		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 		goto done;
 	}
 
-	*f = fdopen(imsg.fd, "w+");
+	*f = fdopen(fd, "w+");
 	if (*f == NULL) {
 		err = got_error_from_errno("fdopen");
-		close(imsg.fd);
+		close(fd);
 		goto done;
 	}
 done:
@@ -303,19 +305,24 @@ static const struct got_error *
 receive_tempfile(FILE **f, const char *mode, struct imsg *imsg,
     struct imsgbuf *ibuf)
 {
+	const struct got_error *err;
 	size_t datalen;
+	int fd;
 
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != 0)
 		return got_error(GOT_ERR_PRIVSEP_LEN);
 
-	if (imsg->fd == -1)
+	fd = imsg_get_fd(imsg);
+	if (fd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
 
-	*f = fdopen(imsg->fd, mode);
-	if (*f == NULL)
-		return got_error_from_errno("fdopen");
-	imsg->fd = -1;
+	*f = fdopen(fd, mode);
+	if (*f == NULL) {
+		err = got_error_from_errno("fdopen");
+		close(fd);
+		return err;
+	}
 
 	return NULL;
 }
@@ -906,8 +913,6 @@ raw_delta_request(struct imsg *imsg, struct imsgbuf *i
 	memcpy(&req, imsg->data, sizeof(req));
 	memcpy(&id, &req.id, sizeof(id));
 
-	imsg->fd = -1;
-
 	err = got_packfile_extract_raw_delta(&delta_buf, &delta_size,
 	    &delta_compressed_size, &delta_offset, &delta_data_offset,
 	    &base_offset, &base_id, &base_size, &result_size,
@@ -1135,11 +1140,6 @@ receive_packidx(struct got_packidx **packidx, struct i
 		goto done;
 	}
 
-	if (imsg.fd == -1) {
-		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
-		goto done;
-	}
-
 	datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != sizeof(ipackidx)) {
 		err = got_error(GOT_ERR_PRIVSEP_LEN);
@@ -1147,10 +1147,10 @@ receive_packidx(struct got_packidx **packidx, struct i
 	}
 	memcpy(&ipackidx, imsg.data, sizeof(ipackidx));
 
+	p->fd = imsg_get_fd(&imsg);
 	p->len = ipackidx.len;
-	p->fd = dup(imsg.fd);
 	if (p->fd == -1) {
-		err = got_error_from_errno("dup");
+		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 		goto done;
 	}
 	if (lseek(p->fd, 0, SEEK_SET) == -1) {
@@ -1168,9 +1168,8 @@ receive_packidx(struct got_packidx **packidx, struct i
 	err = got_packidx_init_hdr(p, 1, ipackidx.packfile_size);
 done:
 	if (err) {
-		if (imsg.fd != -1)
-			close(imsg.fd);
-		got_packidx_close(p);
+		if (p != NULL)
+			got_packidx_close(p);
 	} else
 		*packidx = p;
 	imsg_free(&imsg);
@@ -1875,11 +1874,6 @@ receive_pack(struct got_pack **packp, struct imsgbuf *
 		goto done;
 	}
 
-	if (imsg.fd == -1) {
-		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
-		goto done;
-	}
-
 	datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != sizeof(ipack)) {
 		err = got_error(GOT_ERR_PRIVSEP_LEN);
@@ -1888,9 +1882,9 @@ receive_pack(struct got_pack **packp, struct imsgbuf *
 	memcpy(&ipack, imsg.data, sizeof(ipack));
 
 	pack->filesize = ipack.filesize;
-	pack->fd = dup(imsg.fd);
+	pack->fd = imsg_get_fd(&imsg);
 	if (pack->fd == -1) {
-		err = got_error_from_errno("dup");
+		err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 		goto done;
 	}
 	if (lseek(pack->fd, 0, SEEK_SET) == -1) {
@@ -1917,9 +1911,8 @@ receive_pack(struct got_pack **packp, struct imsgbuf *
 #endif
 done:
 	if (err) {
-		if (imsg.fd != -1)
-			close(imsg.fd);
-		free(pack);
+		if (pack != NULL)
+			got_pack_close(pack);
 	} else
 		*packp = pack;
 	imsg_free(&imsg);
@@ -1976,8 +1969,6 @@ main(int argc, char *argv[])
 	}
 
 	for (;;) {
-		imsg.fd = -1;
-
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
 			break;
@@ -1990,8 +1981,10 @@ main(int argc, char *argv[])
 			break;
 		}
 
-		if (imsg.hdr.type == GOT_IMSG_STOP)
+		if (imsg.hdr.type == GOT_IMSG_STOP) {
+			imsg_free(&imsg);
 			break;
+		}
 
 		switch (imsg.hdr.type) {
 		case GOT_IMSG_TMPFD:
@@ -2083,8 +2076,6 @@ main(int argc, char *argv[])
 			break;
 		}
 
-		if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL)
-			err = got_error_from_errno("close");
 		imsg_free(&imsg);
 		if (err)
 			break;
blob - 9a510beab9f689e0356e77e698d30b666c6f4521
file + libexec/got-read-tag/got-read-tag.c
--- libexec/got-read-tag/got-read-tag.c
+++ libexec/got-read-tag/got-read-tag.c
@@ -73,6 +73,7 @@ main(int argc, char *argv[])
 		struct imsg imsg;
 		struct got_tag_object *tag = NULL;
 		struct got_object_id expected_id;
+		int fd = -1;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -101,19 +102,20 @@ main(int argc, char *argv[])
 		}
 		memcpy(&expected_id, imsg.data, sizeof(expected_id));
 
-		if (imsg.fd == -1) {
+		fd = imsg_get_fd(&imsg);
+		if (fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
 
 		/* Always assume file offset zero. */
-		err = got_object_read_tag(&tag, imsg.fd, &expected_id, 0);
+		err = got_object_read_tag(&tag, fd, &expected_id, 0);
 		if (err)
 			goto done;
 
 		err = got_privsep_send_tag(&ibuf, tag);
 done:
-		if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL)
+		if (fd != -1 && close(fd) == -1 && err == NULL)
 			err = got_error_from_errno("close");
 		imsg_free(&imsg);
 		if (err)
blob - b8c40928c6dbf801b5730c92cd5ada9803a890d1
file + libexec/got-read-tree/got-read-tree.c
--- libexec/got-read-tree/got-read-tree.c
+++ libexec/got-read-tree/got-read-tree.c
@@ -76,6 +76,7 @@ main(int argc, char *argv[])
 		struct imsg imsg;
 		uint8_t *buf = NULL;
 		struct got_object_id expected_id;
+		int fd = -1;
 
 		if (sigint_received) {
 			err = got_error(GOT_ERR_CANCELLED);
@@ -104,21 +105,22 @@ main(int argc, char *argv[])
 		}
 		memcpy(&expected_id, imsg.data, sizeof(expected_id));
 
-		if (imsg.fd == -1) {
+		fd = imsg_get_fd(&imsg);
+		if (fd == -1) {
 			err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			goto done;
 		}
 
 		/* Always assume file offset zero. */
 		err = got_object_read_tree(&entries, &nentries, &nentries_alloc,
-		    &buf, imsg.fd, &expected_id);
+		    &buf, fd, &expected_id);
 		if (err)
 			goto done;
 
 		err = got_privsep_send_tree(&ibuf, entries, nentries);
 done:
 		free(buf);
-		if (imsg.fd != -1 && close(imsg.fd) == -1 && err == NULL)
+		if (fd != -1 && close(fd) == -1 && err == NULL)
 			err = got_error_from_errno("close");
 		imsg_free(&imsg);
 		if (err)
blob - 654cb49d9d96580f6af08455db5b1407f1483dbd
file + libexec/got-send-pack/got-send-pack.c
--- libexec/got-send-pack/got-send-pack.c
+++ libexec/got-send-pack/got-send-pack.c
@@ -137,7 +137,7 @@ recv_packfd(int *packfd, struct imsgbuf *ibuf)
 		goto done;
 	}
 
-	*packfd = imsg.fd;
+	*packfd = imsg_get_fd(&imsg);
 done:
 	imsg_free(&imsg);
 	return err;
@@ -649,7 +649,7 @@ main(int argc, char **argv)
 		goto done;
 	}
 	memcpy(&send_req, imsg.data, sizeof(send_req));
-	sendfd = imsg.fd;
+	sendfd = imsg_get_fd(&imsg);
 	imsg_free(&imsg);
 
 	if (send_req.verbosity > 0)