Download raw body.
Stop non root users from blocking gotctl(8) reload
On Sat, Mar 14, 2026 at 12:00:19PM -0400, Henry Ford wrote:
> 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).
Applied, thanks!
> 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;
>
>
Stop non root users from blocking gotctl(8) reload