Skip to content

fix(linbo-torrent): never hand machine account files to nobody - #182

Merged
HappyBasher merged 1 commit into
linuxmuster:7.4from
TomlDev:fix/macct-permissions
Oct 7, 2026
Merged

HappyBasher merged 1 commit into
linuxmuster:7.4from
TomlDev:fix/macct-permissions

Conversation

@TomlDev

@TomlDev TomlDev commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Problem

*.macct files hold the Samba password hashes (unicodePwd, supplementalCredentials) of an image's machine account. The [linbo] rsync module serves LINBODIR as nobody without login, so a .macct owned by nobody can be downloaded by anyone who can reach rsync, even with mode 600.

update_permissions() in linbo-torrent chowned the whole images directory to nobody and gave only images/<image>/*.macct back to root:

  • .macct files further down stayed nobody-owned after every run, e.g. the copies rsync-post-upload.sh keeps in images/<image>/backups/<timestamp>/ and those below images/.incoming/.
  • The others were nobody-owned between the recursive chown and the chown back to root.
  • Without any .macct, chown and chmod failed on the unexpanded glob and printed errors.
  • A symlink named *.macct in an image directory was followed by chown and chmod.

rsync-post-upload.sh wrote a new .macct with the default umask and set mode 600 afterwards, so it was readable with mode 644 for a moment. An existing .macct was written in place and kept its mode until the chmod.

Change

  • .macct files at any depth below the images directory are made root:root 600 first and left out of the nobody chown, so they are never nobody-owned, not even for a moment. Symlinks are not followed (chown -h, as chown -R did before).
  • images/.incoming, the staging directory of the central image sync, is left out of the nobody chown too. The image sync keeps it root 700 while an upload waits there. The .macct files in it are still made root:root 600.
  • Everything else is chowned exactly as before, including the opentracker directory.
  • rsync-post-upload.sh removes an existing .macct and creates the new one with mode 600.

Companion fix for the central image sync: linuxmuster/linuxmuster-tools#44 creates staged and synced .macct files root:root 0600 and keeps images/.incoming root 0700.

Files already on disk are fixed by the next linbo-torrent run (e.g. linbo-torrent restart), or directly with:

find /srv/linbo/images -type f -name '*.macct' -exec chown root:root {} + -exec chmod 600 {} +

Testing

  • New tests/shell/test_linbo-torrent.sh, 7 tests: .macct root:root 600 at any depth, never handed to nobody, other files to nobody as before, .incoming left alone, opentracker directory to its user, no errors without any .macct, symlinks not followed. chown is stubbed since the tests don't run as root. 5 of them fail against 7.4; the other 2 check that nothing else changes.
  • sh tests/shell/run.sh and busybox ash tests/shell/run.sh: all test files OK.
  • Compared the chown calls of the old and new code with strace on a tree with symlinks, hard links and names with spaces or newlines: identical for everything except .macct and .incoming.

@HappyBasher

Copy link
Copy Markdown
Member

Thanks for this one, and for the thorough description. It is a security fix independent of #178, so we'll review and release it on its own, ahead of the per-school group work.

I reviewed it and ran the tests locally: all shell test files OK. I also checked the two find expressions against a tree with backups, .incoming and a hard link. They select the right files: .macct at every depth go to root, and .incoming is skipped for the nobody chown. The [linbo] module runs as uid = nobody without login, so the problem is real.

Existing installations are only fixed by the next linbo-torrent run. We'll put the find one-liner from your description into the release notes for admins.

Before merging, please add a Signed-off-by: trailer to the commit. It has to come from you as the author, so we can't add it for you. git rebase --signoff origin/7.4 and git push --force-with-lease will do it. We merge contributor PRs with a merge commit, so the commit message stays in the history. The commit has no Co-Authored-By, so nothing else to change there.

linuxmuster-tools#44 is independent of this PR. Neither has to wait for the other.

@TomlDev
TomlDev force-pushed the fix/macct-permissions branch from 48a06ed to 4434588 Compare October 1, 2026 10:11
@TomlDev

TomlDev commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review and for running the tests. I added the Signed-off-by: trailer with git rebase --signoff and pushed with --force-with-lease (head 4434588). Nothing else is open from my side, so this is ready to merge.

*.macct files hold the samba password hashes of an image's machine
account. The [linbo] rsync module serves LINBODIR as nobody without
login, so a .macct owned by nobody can be downloaded by anyone on the
network, even with mode 600.

update_permissions() chowned the whole images dir to nobody and gave only
images/<image>/*.macct back to root:

- .macct files further down stayed nobody-owned after every run, e.g. the
  copies rsync-post-upload.sh keeps in images/<image>/backups/<timestamp>/
  and those below images/.incoming/.
- The others were nobody-owned between the recursive chown and the chown
  back to root.
- Without any .macct, chown and chmod failed on the unexpanded glob and
  printed errors.
- A symlink named *.macct in an image dir was followed by chown and chmod.

Now .macct files at any depth below the images dir are made root:root 600
first and left out of the nobody chown. Symlinks are not followed (chown
-h, as chown -R did before). images/.incoming, the staging dir of the
central image sync (linuxmuster-tools), is left out of the nobody chown
too: the image sync keeps it root 700 while an upload waits there, and
every run gave it back to nobody. Its .macct files are still made root:root
600. Everything else is chowned as before.

rsync-post-upload.sh created a new .macct with the default umask and set
mode 600 only afterwards, so it was readable with mode 644 for a moment.
An existing .macct was written in place and kept its mode until the chmod.
The file is now removed and created anew with mode 600.

Signed-off-by: Tom Lehmann <tom.lehmann@netzint.de>
Assisted-by: Claude
@TomlDev
TomlDev force-pushed the fix/macct-permissions branch from 4434588 to b760996 Compare October 1, 2026 10:43
@HappyBasher
HappyBasher merged commit fa4637b into linuxmuster:7.4 Oct 7, 2026
HappyBasher added a commit that referenced this pull request Oct 7, 2026
…n upgrade

linbo-torrent handed *.macct files below the images dir (backups,
.incoming) to nobody before #182, and the [linbo] rsync module serves
LINBODIR as nobody without login, so their samba password hashes could
be downloaded. #182 fixes update_permissions(), but files already on
disk are only corrected on the next linbo-torrent run, and the package
configure step restarts linbo-torrent only when its config changed.

Set every *.macct below the images dir to root:root 600 on configure,
so a server is fixed right after the upgrade. Symlinks are not
followed (-type f).

Signed-off-by: thomas@linuxmuster.net
Assisted-by: Claude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants