Download raw body.
gotd: branch namespace protection and forced push
Hi,
I just installed OpenBSD, beautiful system, love it.
I'm setting up gotd/gotsysd 0.129 so my git repositories behave like a
ledger: a push may add commits, but nobody, including someone with a
stolen key, can rewrite or delete history.
Setup
Every repository in gotsys.conf had:
protect {
branch namespace "refs/heads/"
tag namespace "refs/tags/"
}
What I tested
In a throwaway repository, from a git client:
git push origin HEAD:refs/heads/ledger-test # accepted
git push --force origin HEAD~1:refs/heads/ledger-test # accepted
git push origin --delete ledger-test # refused:
refs/heads/: reference namespace is protected
The deletion was refused, but the forced push rewound the branch.
gotsys.conf(5) says that for a branch namespace, "attempts to change the
history of branches or delete them will be denied", so I expected the
second push to be refused as well.
How I worked around it
I added the branches by name to each protect block:
branch "master"
branch "main"
branch "ledger-test"
With that, the same test gives:
git push origin HEAD:refs/heads/ledger-test # accepted
git push --force origin HEAD~1:refs/heads/ledger-test # refused:
refs/heads/ledger-test: reference is protected
Question
Is this expected behaviour, or a bug?
In case it helps: the rewind sends an empty pack, so I think it goes
through protect_refs_from_moving() in gotd/repo_write.c. There the
namespace check is
if (strcmp(pe->path, refname) != 0)
continue;
which never matches "refs/heads/" against "refs/heads/ledger-test".
The other path, protect_branch_namespace(), uses a prefix match. If it
is a bug, maybe this:
--- gotd/repo_write.c
+++ gotd/repo_write.c
@@ -1565,7 +1565,7 @@
RB_FOREACH(pe, got_pathlist_head,
&repo_write.protected_branch_namespaces) {
- if (strcmp(pe->path, refname) != 0)
+ if (strncmp(pe->path, refname, strlen(pe->path)) != 0)
continue;
err = protect_require_yca(&ref_update->new_id, 0,
Thanks,
Cas
gotd: branch namespace protection and forced push