From: Henry Ford Subject: Stop non root users from blocking gotctl(8) reload To: gameoftrees@openbsd.org Date: Sat, 14 Mar 2026 12:00:19 -0400 A gotctl(8) reload request is composed of two messages: a GOTD_IMSG_RELOAD_SECRETS message, optionally with a secrets file, and a GOTD_IMSG_RELOAD message, with a config file. If no secrets file is specified, gotctl(8) will still send a GOTD_IMSG_RELOAD_SECRETS message with no payload to indicate this. If a GOTD_IMSG_RELOAD message is sent by a non root user, then gotd(8) will deny the request. However, gotd(8) will accept a GOTD_IMSG_RELOAD_SECRETS message from any client regardless of their uid. After receiving a GOTD_IMSG_RELOAD_SECRETS message gotd(8) will not accept another such message until it receives a GOTD_IMSG_RELOAD message to complete the reload request. Thus, a non root user can block any future gotctl(8) reload requests from succeeding by sending a GOTD_IMSG_RELOAD_SECRETS message to gotd(8). You can reproduce this by running the following commands with gotd(8) running: $ gotctl reload -c /dev/null gotctl: reload: Operation not permitted # gotctl reload gotctl: received unexpected privsep message To prevent this we can just have gotd(8) reject GOTD_IMSG_RELOAD_SECRETS requests from non root users. In the patch at the bottom of this email I do this. I chose to make the error message say "reload" instead of "reload secrets" because this is what users will see if they try to run gotctl(8) reload when they are not root. A user with root access can still block gotctl(8) reload requests from succeeding with this method, but they could also just SIGSTOP gotd(8). diff /home/user/ext/got path + /home/user/ext/got commit - 7c0bf6cc9b78f83c42c53d38c9ecacb7420c5e0f blob - 749adfaf1adfe968546d819330f3dbcfa89666b6 file + gotd/gotd.c --- gotd/gotd.c +++ gotd/gotd.c @@ -983,6 +987,10 @@ gotd_request(int fd, short events, void *arg) err = stop_gotd(client); break; case GOTD_IMSG_RELOAD_SECRETS: + if (client->euid != 0) { + err = got_error_set_errno(EPERM, "reload"); + break; + } if (have_reload_secrets) { err = got_error(GOT_ERR_PRIVSEP_MSG); break;