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

From:
Stefan Sperling <stsp@stsp.name>
Subject:
-portable gotd progress
To:
gameoftrees@openbsd.org
Date:
Sun, 20 Aug 2023 14:28:55 +0200

Download raw body.

Thread
The following patches provide some progress for gotd in -portable.
The patches are based on the ta/gotd branch, not the 'portable' branch!

I am restoring chroot support where possible. This requires the main
process to keep running as root. But that is probably better than not
chrooting.

A blocking issue I found during testing is that 'got send' never
exits after uploading the pack file. On the server side I see gotsh
hanging in poll on stdin, still waiting for more pack file data to
arrive. Any ideas how that can be fixed? We seem to be relying on
some OpenBSD-specific behaviour on the server side?

To test the changes, add a gotd user to the system, create an empty
directory at /var/run/gotd, put gotsh and gitwrapper in /usr/bin
with appropriate symlinks for gitwrapper.

Try a gotd.conf such as:
[[[
user gotd

repository "test" {
	path "/git/test.git"
	permit rw stsp
}
]]]

I don't want to commit the debug diff (#4). OK for any others?

Should I put patches on ta/gotd or do we create a separate branch?

Diffs #1 and #2 could probably go directly to the 'portable' branch?

-----------------------------------------------
commit fdd7ffc98a9c9a26d83d115d398c1cd1e609e7cd
from: Stefan Sperling <stsp@stsp.name>
date: Sun Aug 20 10:32:34 2023 UTC
 
 make sure program_invocation_short_name gets defined in getprogname.c
  
 This is needed for gitwrapper which will fail if its program name
 cannot be detected properly.
 
diff 497c206b2e1425e9a667723222a167d4f3b1dae6 fdd7ffc98a9c9a26d83d115d398c1cd1e609e7cd
commit - 497c206b2e1425e9a667723222a167d4f3b1dae6
commit + fdd7ffc98a9c9a26d83d115d398c1cd1e609e7cd
blob - 1dc2f493577b073fa65b7544928ff6ff61c1c2e6
blob + 975dd4f84e4975bf7c53aaa058770a333a96cfd4
--- compat/getprogname.c
+++ compat/getprogname.c
@@ -14,10 +14,15 @@
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define _GNU_SOURCE
+
 #include <sys/types.h>
 
 #include <errno.h>
+#include <argp.h>
 
+#include "got_compat.h"
+
 #if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
 const char *
 getprogname(void)

-----------------------------------------------
commit 13c8c4fddb5a359fdfb781028cfaa3529ae65043
from: Stefan Sperling <stsp@stsp.name>
date: Sun Aug 20 10:32:34 2023 UTC
 
 use a workng git libexec directory default on Linux
 
 Tested on ubuntu 22.04
 
diff fdd7ffc98a9c9a26d83d115d398c1cd1e609e7cd 13c8c4fddb5a359fdfb781028cfaa3529ae65043
commit - fdd7ffc98a9c9a26d83d115d398c1cd1e609e7cd
commit + 13c8c4fddb5a359fdfb781028cfaa3529ae65043
blob - 2b1255118b91d4c7edef0a6016130ed9de07bfcd
blob + af3cf15215d61e94a762d704ddca0ecf37080994
--- gitwrapper/gitwrapper.c
+++ gitwrapper/gitwrapper.c
@@ -43,8 +43,12 @@
 #include "log.h"
 
 #ifndef GITWRAPPER_GIT_LIBEXEC_DIR
+#ifdef __linux__
+#define GITWRAPPER_GIT_LIBEXEC_DIR "/usr/lib/git-core/"
+#else
 #define GITWRAPPER_GIT_LIBEXEC_DIR "/usr/local/libexec/git"
 #endif
+#endif
 
 #ifndef GITWRAPPER_MY_SERVER_PROG
 #define GITWRAPPER_MY_SERVER_PROG "gotsh"

-----------------------------------------------
commit bf9a5775e4bca9539f7e1064a16fe20f611028ef
from: Stefan Sperling <stsp@stsp.name>
date: Sun Aug 20 10:32:34 2023 UTC
 
 re-enable chroot in -portable gotd
 
 Reads (git clone) are working but writes (git push) run into an error
 
diff 13c8c4fddb5a359fdfb781028cfaa3529ae65043 bf9a5775e4bca9539f7e1064a16fe20f611028ef
commit - 13c8c4fddb5a359fdfb781028cfaa3529ae65043
commit + bf9a5775e4bca9539f7e1064a16fe20f611028ef
blob - d847e923a6c4676e526a8171f6813cb9686f9698
blob + 4fd361f420a38ab5a9dfe6a68516b93b5d1f9d2c
--- gotd/gotd.c
+++ gotd/gotd.c
@@ -1821,6 +1821,29 @@ int
 		fatal("unveil");
 }
 
+static int
+enter_chroot(const char *path, struct passwd *pw)
+{
+	int ret = 0;
+
+#ifndef HAVE_UNVEIL
+	log_info("chroot into %s", path);
+	if (chroot(path) == -1)
+		fatal("chroot");
+	if (chdir("/") == -1)
+		fatal("chdir(\"/\")");
+	ret = 1;
+#endif
+
+	/* Drop root privileges. */
+	if (setgid(pw->pw_gid) == -1)
+		fatal("setgid %d failed", pw->pw_gid);
+	if (setuid(pw->pw_uid) == -1)
+		fatal("setuid %d failed", pw->pw_uid);
+
+	return ret;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -1960,11 +1983,14 @@ main(int argc, char **argv)
 	setproctitle("%s", title);
 	log_procinit(title);
 
-	/* Drop root privileges. */
-	if (setgid(pw->pw_gid) == -1)
-		fatal("setgid %d failed", pw->pw_gid);
-	if (setuid(pw->pw_uid) == -1)
-		fatal("setuid %d failed", pw->pw_uid);
+	if (proc_id != PROC_GOTD && proc_id != PROC_LISTEN &&
+	    proc_id != PROC_REPO_READ && proc_id != PROC_REPO_WRITE) {
+		/* Drop root privileges. */
+		if (setgid(pw->pw_gid) == -1)
+			fatal("setgid %d failed", pw->pw_gid);
+		if (setuid(pw->pw_uid) == -1)
+			fatal("setuid %d failed", pw->pw_uid);
+	}
 
 	event_init();
 
@@ -1987,6 +2013,8 @@ main(int argc, char **argv)
 		 */
 		apply_unveil_none();
 
+		enter_chroot(GOTD_EMPTY_PATH, pw);
+
 		listen_main(title, fd, gotd.connection_limits,
 		    gotd.nconnection_limits);
 		/* NOTREACHED */
@@ -2022,6 +2050,7 @@ main(int argc, char **argv)
 			apply_unveil_repo_readonly(repo_path, 1);
 		else
 			apply_unveil_repo_readwrite(repo_path);
+
 		session_main(title, repo_path, pack_fds, temp_fds,
 		    &gotd.request_timeout, proc_id);
 		/* NOTREACHED */
@@ -2032,6 +2061,16 @@ main(int argc, char **argv)
 			err(1, "pledge");
 #endif
 		apply_unveil_repo_readonly(repo_path, 0);
+
+		if (enter_chroot(repo_path, pw)) {
+			log_info("change repo path %s", repo_path);
+			free(repo_path);
+			repo_path = strdup("/");
+			if (repo_path == NULL)
+				fatal("strdup");
+			log_info("repo path is now %s", repo_path);
+		}
+
 		repo_read_main(title, repo_path, pack_fds, temp_fds);
 		/* NOTREACHED */
 		exit(0);
@@ -2044,6 +2083,14 @@ main(int argc, char **argv)
 		repo = gotd_find_repo_by_path(repo_path, &gotd);
 		if (repo == NULL)
 			fatalx("no repository for path %s", repo_path);
+
+		if (enter_chroot(repo_path, pw)) {
+			free(repo_path);
+			repo_path = strdup("/");
+			if (repo_path == NULL)
+				fatal("strdup");
+		}
+
 		repo_write_main(title, repo_path, pack_fds, temp_fds,
 		    &repo->protected_tag_namespaces,
 		    &repo->protected_branch_namespaces,
blob - 3f19d8e3cb52c8795ccedfb4853ac60cab2de702
blob + 104969391e88b00555dda0b771c28af94e7b9f06
--- gotd/gotd.h
+++ gotd/gotd.h
@@ -20,7 +20,11 @@
 #define GOTD_UNIX_SOCKET_BACKLOG 10
 #define GOTD_USER	"_gotd"
 #define GOTD_CONF_PATH	"/etc/gotd.conf"
+#ifdef __linux__
+#define GOTD_EMPTY_PATH	"/var/run/gotd"
+#else
 #define GOTD_EMPTY_PATH	"/var/empty"
+#endif
 
 #define GOTD_MAXCLIENTS		1024
 #define GOTD_MAX_CONN_PER_UID	4

-----------------------------------------------
commit 40b0f0fa8f9f421c31757f17284754c53eb8e443
from: Stefan Sperling <stsp@stsp.name>
date: Sun Aug 20 10:32:34 2023 UTC
 
 debug that shows where the git push error occurs
 
diff bf9a5775e4bca9539f7e1064a16fe20f611028ef 40b0f0fa8f9f421c31757f17284754c53eb8e443
commit - bf9a5775e4bca9539f7e1064a16fe20f611028ef
commit + 40b0f0fa8f9f421c31757f17284754c53eb8e443
blob - f08a5f86379cbe0217a47636363ab3ab49ad063b
blob + 7c7e5d3ebd3a007abdc4367fa3533f3942762e53
--- lib/serve.c
+++ lib/serve.c
@@ -208,11 +208,11 @@ announce_refs(int outfd, struct imsgbuf *ibuf, int cli
 			goto done;
 		case GOTD_IMSG_REFLIST:
 			if (have_nrefs || nrefs > 0) {
-				err = got_error(GOT_ERR_PRIVSEP_MSG);
+				err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "1");
 				goto done;
 			}
 			if (datalen != sizeof(ireflist)) {
-				err = got_error(GOT_ERR_PRIVSEP_MSG);
+				err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "2");
 				goto done;
 			}
 			memcpy(&ireflist, imsg.data, sizeof(ireflist));
@@ -224,11 +224,11 @@ announce_refs(int outfd, struct imsgbuf *ibuf, int cli
 			break;
 		case GOTD_IMSG_REF:
 			if (!have_nrefs || nrefs == 0) {
-				err = got_error(GOT_ERR_PRIVSEP_MSG);
+				err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "3");
 				goto done;
 			}
 			if (datalen < sizeof(iref)) {
-				err = got_error(GOT_ERR_PRIVSEP_MSG);
+				err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "4");
 				goto done;
 			}
 			memcpy(&iref, imsg.data, sizeof(iref));
@@ -255,7 +255,7 @@ announce_refs(int outfd, struct imsgbuf *ibuf, int cli
 			break;
 		case GOTD_IMSG_SYMREF:
 			if (!have_nrefs || nrefs == 0) {
-				err = got_error(GOT_ERR_PRIVSEP_MSG);
+				err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "5");
 				goto done;
 			}
 			if (datalen < sizeof(isymref)) {
@@ -309,7 +309,7 @@ announce_refs(int outfd, struct imsgbuf *ibuf, int cli
 				nrefs--;
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "6");
 			break;
 		}
 
@@ -554,7 +554,7 @@ recv_want(int *use_sidebands, int outfd, struct imsgbu
 			done = 1;
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "7");
 			break;
 		}
 
@@ -651,7 +651,7 @@ recv_have(int *have_ack, int outfd, struct imsgbuf *ib
 			done = 1;
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "8");
 			break;
 		}
 
@@ -692,7 +692,7 @@ recv_done(int *packfd, int outfd, struct imsgbuf *ibuf
 				err = got_error(GOT_ERR_PRIVSEP_NO_FD);
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "9");
 			break;
 		}
 
@@ -753,7 +753,7 @@ relay_progress_reports(struct imsgbuf *ibuf, int outfd
 			err = got_pkt_writepkt(outfd, buf, 1 + n, chattygot);
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "10");
 			break;
 		}
 
@@ -1047,7 +1047,7 @@ recv_ref_update(int *report_status, int outfd, struct 
 			done = 1;
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "11");
 			break;
 		}
 
@@ -1070,7 +1070,7 @@ recv_packfile(struct imsg *imsg, int infd)
 
 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 	if (datalen != 0)
-		return got_error(GOT_ERR_PRIVSEP_MSG);
+		return got_error_msg(GOT_ERR_PRIVSEP_MSG, "13");
 
 	if (imsg->fd == -1)
 		return got_error(GOT_ERR_PRIVSEP_NO_FD);
@@ -1329,7 +1329,7 @@ serve_write(int infd, int outfd, int gotd_sock, const 
 			curstate = STATE_PACKFILE_RECEIVED;
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_fmt(GOT_ERR_PRIVSEP_MSG, "14: %d", imsg.hdr.type);
 			break;
 		}
 
@@ -1366,7 +1366,7 @@ serve_write(int infd, int outfd, int gotd_sock, const 
 			err = got_pkt_flushpkt(outfd, chattygot);
 			break;
 		default:
-			err = got_error(GOT_ERR_PRIVSEP_MSG);
+			err = got_error_msg(GOT_ERR_PRIVSEP_MSG, "15");
 			break;
 		}
 

-----------------------------------------------
commit 7c045a52e6d559f699fd241c2451ff17de39f7ee (gotd-chroot)
from: Stefan Sperling <stsp@stsp.name>
date: Sun Aug 20 12:05:45 2023 UTC
 
 fix -portable specific mismerge in serve_write()
 
diff 40b0f0fa8f9f421c31757f17284754c53eb8e443 7c045a52e6d559f699fd241c2451ff17de39f7ee
commit - 40b0f0fa8f9f421c31757f17284754c53eb8e443
commit + 7c045a52e6d559f699fd241c2451ff17de39f7ee
blob - 7c7e5d3ebd3a007abdc4367fa3533f3942762e53
blob + f016d8400617c19bdb55eec1b8cfca2dda2e0248
--- lib/serve.c
+++ lib/serve.c
@@ -1313,7 +1313,7 @@ serve_write(int infd, int outfd, int gotd_sock, const 
 		case GOTD_IMSG_ERROR:
 			err = gotd_imsg_recv_error(NULL, &imsg);
 			goto done;
-		case GOTD_IMSG_RECV_PACKFILE:
+		case GOTD_IMSG_PACKFILE_PIPE:
 			err = recv_packfile(&imsg, infd);
 			if (err) {
 				if (err->code != GOT_ERR_EOF)