Commit Diff


commit - 5033341e896cb4e7b6f7358e89d9348ba577e823
commit + 1636f5f1250f97681e81b91ecba276e147cbc4ec
blob - e8f36dc8c9e4dca41153d952a13e1120bff3f215
blob + c6531257554a0d495a7ef3a1e39d84a0be4ce03d
--- gotd/Makefile.am
+++ gotd/Makefile.am
@@ -48,6 +48,12 @@ gotd_SOURCES = gotd.c \
 	$(top_srcdir)/lib/reference_parse.c \
 	$(top_srcdir)/lib/repository.c \
 	$(top_srcdir)/lib/sigs.c
+
+if !HOST_OPENBSD
+nodist_gotd_SOURCES = chroot-notobsd.c
+else
+nodist_gotd_SOURCES = chroot-openbsd.c
+endif
        
 gotd_DEPENDENCIES = $(top_builddir)/compat/libopenbsd-compat.a
 EXTRA_DIST = gotd.8 gotd.conf.5 *.h
@@ -59,7 +65,8 @@ LDADD = -L$(top_builddir)/compat -lopenbsd-compat -lm
 LDADD += $(libuuid_LIBS) \
 	 $(zlib_LIBS) \
 	 $(libbsd_LIBS) \
-	 $(libevent_LIBS)
+	 $(libevent_LIBS) \
+	 $(libutil_LIBS)
 if HOST_FREEBSD
 LDADD += -lmd
 endif
blob - /dev/null
blob + 19506ed47c6c6a95b2e8984da0db9174f1a0afb8 (mode 644)
--- /dev/null
+++ gotd/chroot-notobsd.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023 Thomas Adam <thomas@xteddy.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "got_compat.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "log.h"
+
+int
+enter_chroot(const char *path)
+{
+	log_info("chroot into %s", path);
+	if (chroot(path) == -1)
+		fatal("chroot");
+	if (chdir("/") == -1)
+		fatal("chdir(\"/\")");
+
+	return 1;
+}
blob - d847e923a6c4676e526a8171f6813cb9686f9698
blob + 7fe8383caa546eb53fad4c421af5738bf34f0ea1
--- gotd/gotd.c
+++ gotd/gotd.c
@@ -116,6 +116,7 @@ static const struct got_error *start_auth_child(struct
     struct gotd_repo *, char *, const char *, int, int);
 static void kill_proc(struct gotd_child_proc *, int);
 static void disconnect(struct gotd_client *);
+static void drop_privs(struct passwd *);
 
 __dead static void
 usage(void)
@@ -1819,6 +1820,16 @@ apply_unveil_selfexec(void)
 
 	if (unveil(NULL, NULL) == -1)
 		fatal("unveil");
+}
+
+static void
+drop_privs(struct passwd *pw)
+{
+	/* 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);
 }
 
 int
@@ -1960,11 +1971,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 +2001,9 @@ main(int argc, char **argv)
 		 */
 		apply_unveil_none();
 
+		enter_chroot(GOTD_EMPTY_PATH);
+		drop_privs(pw);
+
 		listen_main(title, fd, gotd.connection_limits,
 		    gotd.nconnection_limits);
 		/* NOTREACHED */
@@ -2022,6 +2039,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 +2050,17 @@ main(int argc, char **argv)
 			err(1, "pledge");
 #endif
 		apply_unveil_repo_readonly(repo_path, 0);
+
+		if (enter_chroot(repo_path)) {
+			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);
+		}
+		drop_privs(pw);
+
 		repo_read_main(title, repo_path, pack_fds, temp_fds);
 		/* NOTREACHED */
 		exit(0);
@@ -2044,6 +2073,15 @@ 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)) {
+			free(repo_path);
+			repo_path = strdup("/");
+			if (repo_path == NULL)
+				fatal("strdup");
+		}
+		drop_privs(pw);
+
 		repo_write_main(title, repo_path, pack_fds, temp_fds,
 		    &repo->protected_tag_namespaces,
 		    &repo->protected_branch_namespaces,
blob - /dev/null
blob + ce373655b60c84b3b9b6f8a93fc01b6c40e8c401 (mode 644)
--- /dev/null
+++ gotd/chroot-openbsd.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2023 Thomas Adam <thomas@xteddy.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "got_compat.h"
+
+int
+enter_chroot(const char *path)
+{
+	(void)path;
+	return 0;
+}
blob - 3f19d8e3cb52c8795ccedfb4853ac60cab2de702
blob + a379ad89ec990acda3d6d8952f4e9ad3d45e92e0
--- gotd/gotd.h
+++ gotd/gotd.h
@@ -20,7 +20,13 @@
 #define GOTD_UNIX_SOCKET_BACKLOG 10
 #define GOTD_USER	"_gotd"
 #define GOTD_CONF_PATH	"/etc/gotd.conf"
+#ifdef __linux__
+/* FIXME: Will move to --configure */
+#define GOTD_EMPTY_PATH	"/var/run/gotd"
+#else
+/* Assumes *BSD, Apple, etc... */
 #define GOTD_EMPTY_PATH	"/var/empty"
+#endif
 
 #define GOTD_MAXCLIENTS		1024
 #define GOTD_MAX_CONN_PER_UID	4
@@ -444,6 +450,7 @@ struct gotd_imsg_auth {
 	uint32_t client_id;
 };
 
+int enter_chroot(const char *);
 int parse_config(const char *, enum gotd_procid, struct gotd *);
 struct gotd_repo *gotd_find_repo_by_name(const char *, struct gotd *);
 struct gotd_repo *gotd_find_repo_by_path(const char *, struct gotd *);