From: Mark Jamsek <mark@jamsek.com> Subject: Re: fix gotd failing to protect refs To: Stefan Sperling <stsp@stsp.name> Cc: gameoftrees@openbsd.org Date: Mon, 27 Jan 2025 17:00:37 +1100 Stefan Sperling <stsp@stsp.name> wrote: > martijn@ pointed out on IRC that it is possible to modify a > protected branch via send -f, which is unexpected behaviour. > > The reason for this is that gotd's reference protection checks only > happen if the client sends a pack file. In martijn's simple test case > the client doesn't send a pack file, and protection checks are skipped. Nice work on the quick solve :) And thanks martijn for finding and reporting this bug! > Our test suite didn't catch this because in our test the client has > always sent a pack file. This is due to an unrelated bug in the pack > creation code, where a parent commit far down the line is added to > the pack file (as the only commit) while it should have been dropped. > This looks like an error in got_pack_paint_commits(). > I will investigate this second issue later. > For now, shortening the commit history used by our ref protection test > works around the pack creation bug and allows our test to cover the > problem martijn@ found. > > ok? ok I see the failure with the regress/gotd change applied and a gotd binary from HEAD, and your change does indeed fix it. There's a tiny style nit in protect_refs_from_moving::repo_write.c:1540: + RB_FOREACH(pe, got_pathlist_head, repo_write.protected_branches) + { but there are other instances in repo_write.c of lines exceeding 80 cols and using Allman instead of K&R style braces, so below is a diff that is comprised entirely of style(9) changes; if ok, I'll commit after you send up your fix? M gotd/repo_write.c | 16+ 16- 1 file changed, 16 insertions(+), 16 deletions(-) path + /home/mark/src/got commit - ef20d7bf45a8d6e280ec3583ef729a4102e5b35a blob - 1a330d17a4953ab17612922f651ca2ebfae95496 file + gotd/repo_write.c --- gotd/repo_write.c +++ gotd/repo_write.c @@ -840,8 +840,8 @@ copy_ref_delta(int infd, int outfd, off_t *outsize, BU } static const struct got_error * -copy_offset_delta(int infd, int outfd, off_t *outsize, BUF *buf, size_t *buf_pos, - struct got_hash *ctx) +copy_offset_delta(int infd, int outfd, off_t *outsize, BUF *buf, + size_t *buf_pos, struct got_hash *ctx) { const struct got_error *err = NULL; uint64_t o = 0; @@ -1405,7 +1405,8 @@ verify_packfile(void) if (ref_update->delete_ref) continue; - RB_FOREACH(pe, got_pathlist_head, repo_write.protected_tag_namespaces) { + RB_FOREACH(pe, got_pathlist_head, + repo_write.protected_tag_namespaces) { err = protect_tag_namespace(pe->path, &client->pack, packidx, ref_update); if (err) @@ -1437,15 +1438,15 @@ verify_packfile(void) } } - RB_FOREACH(pe, got_pathlist_head, repo_write.protected_branch_namespaces) - { + RB_FOREACH(pe, got_pathlist_head, + repo_write.protected_branch_namespaces) { err = protect_branch_namespace(pe->path, &client->pack, packidx, ref_update); if (err) goto done; } - RB_FOREACH(pe, got_pathlist_head, repo_write.protected_branches) - { + RB_FOREACH(pe, got_pathlist_head, + repo_write.protected_branches) { err = protect_branch(pe->path, &client->pack, packidx, ref_update); if (err) @@ -1492,8 +1493,8 @@ protect_refs_from_deletion(void) return err; } - RB_FOREACH(pe, got_pathlist_head, repo_write.protected_branches) - { + RB_FOREACH(pe, got_pathlist_head, + repo_write.protected_branches) { if (strcmp(refname, pe->path) == 0) { return got_error_fmt(GOT_ERR_REF_PROTECTED, "%s", refname); @@ -1537,8 +1538,8 @@ protect_refs_from_moving(void) return err; } - RB_FOREACH(pe, got_pathlist_head, repo_write.protected_branches) - { + RB_FOREACH(pe, got_pathlist_head, + repo_write.protected_branches) { if (strcmp(refname, pe->path) == 0) { return got_error_fmt(GOT_ERR_REF_PROTECTED, "%s", refname); @@ -1774,8 +1775,8 @@ print_diffstat(struct got_diffstat_cb_arg *dsa, int fd int pad = dsa->max_path_len - pe->path_len + 1; dprintf(fd, " %c %s%*c | %*d+ %*d-\n", cp->status, - pe->path, pad, ' ', dsa->add_cols + 1, cp->add, - dsa->rm_cols + 1, cp->rm); + pe->path, pad, ' ', dsa->add_cols + 1, cp->add, + dsa->rm_cols + 1, cp->rm); } dprintf(fd, "\n%d file%s changed, %d insertion%s(+), %d deletion%s(-)\n\n", @@ -2326,9 +2327,8 @@ repo_write_dispatch_session(int fd, short event, void } if (!shut && check_cancelled(NULL) == NULL) { - if (err && - gotd_imsg_send_error_event(iev, PROC_REPO_WRITE, - client->id, err) == -1) { + if (err && gotd_imsg_send_error_event(iev, PROC_REPO_WRITE, + client->id, err) == -1) { log_warnx("could not send error to parent: %s", err->msg); } -- Mark Jamsek <https://bsdbox.org> GPG: F2FF 13DE 6A06 C471 CA80 E6E2 2930 DC66 86EE CF68