Hardened Malloc - Hardened Memory Allocator

Merged.

Good question.

This one we can live with. If a user has an issue, easily sorted in support.

This one is a major bummer. Blocker. Servers using this could be locked out due to ssh breaking.

Related:

(Mostly an issue for Kicksecure.)

Telegram still broken.

OpenSSH I don’t see why it would be fixed since Debian won’t backport the fix to Debian buster. Hopefully fixed in Debian bullseye and above.

That patch should be submitted to upstream for review. I cannot carry such as C patch in Whonix / Kicksecure.

These don’t survive package upgrades?

ssh package upgraded → ACL missing → ssh broken

Doable similar to security-misc permission-hardening using dpkg-statoverwrite?

Similar to security-misc permission-hardening.

Seems quite hacky. Having an opt in, a group hardened-malloc-disable seems like a good feature. But enabling that by default seems quite complex, fragile. Not great for SSH.

Debian bullseye shouldn’t be too far away and then none of this would be needed anymore?

1 Like

Test if using a drop-in file to prepend the ld-system-preload-disable wrapper to ExecStart= works or running it as the disable-hardened-malloc group.

Would permissions be reset upon each package upgrade or only upon updates to the actual file /etc/ld.so.preload? If the latter, then we don’t need to worry about this since it’s never updated.

I don’t think dpkg-statoverwrite supports ACLs like this.

Hopefully not. Is there a timeline?

1 Like

Tested just now. Still broken in Debian buster.

It’s in Hard Freeze already.

https://wiki.debian.org/DebianBullseye

  • 2021-03-12: Hard Freeze - for key packages and packages without autopkgtests (scheduled)

Full Freeze date not yet determined.

/etc/ld.so.preload isn’t managed by any package. So no upgrades by packges.
But packages such as chromium replace every file on every upgrade. Even if the upgraded file didn’t actually change contents.

That modification would be lost each time the chromium package is upgraded. To test, just reinstall should be enough.

sudo apt install --reinstall chromium

I considered that earlier but /lib/systemd/system/ssh.service looks complex.

ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID

Any of that can change on any Debian release upgrade. I guess systemd lacks a “prepend this wrapper” directive.

Would have to overwrite like this:

ExecStart=/usr/bin/ld-system-preload-disable /usr/sbin/sshd -D $SSHD_OPTS

That could interfere with any overwrites by system administrator. Not sure anyone is doing that. Forgetting to drop/update that on release upgrades (to bullseye or bullseye +1) could later on also be fatal.

ExecStart=/usr/bin/ld-system-preload-disable /usr/sbin/sshd -D $SSHD_OPTS

Tested. Doesn’t work. sudo systemctl restart ssh hangs.

Starting OpenBSD Secure Shell server…
Server listening on 0.0.0.0 port 22.
Server listening on :: port 22.
ssh.service: Got notification message from PID 3377, but reception only permitted for main PID 3375
ssh.service: Start operation timed out. Terminating.
ssh.service: Main process exited, code=killed, status=15/TERM
ssh.service: Failed with result ‘timeout’.
Failed to start OpenBSD Secure Shell server.
pam_unix(sudo:session): session closed for user root
ssh.service: Service RestartSec=100ms expired, scheduling restart.
ssh.service: Scheduled restart job, restart counter is at 1.
Stopped OpenBSD Secure Shell server.
ssh.service: Found left-over process 3376 (bwrap) in control group while starting unit. Ignoring.
This usually indicates unclean termination of a previous run, or service implementation deficiencies.
ssh.service: Found left-over process 3377 (sshd) in control group while starting unit. Ignoring.
This usually indicates unclean termination of a previous run, or service implementation deficiencies.
Starting OpenBSD Secure Shell server…
ssh.service: Found left-over process 3376 (bwrap) in control group while starting unit. Ignoring.
This usually indicates unclean termination of a previous run, or service implementation deficiencies.
ssh.service: Found left-over process 3377 (sshd) in control group while starting unit. Ignoring.
This usually indicates unclean termination of a previous run, or service implementation deficiencies.
error: Bind to port 22 on 0.0.0.0 failed: Address already in use.
error: Bind to port 22 on :: failed: Address already in use.
fatal: Cannot bind any address.
ssh.service: Main process exited, code=exited, status=255/EXCEPTION
ssh.service: Failed with result ‘exit-code’.
Failed to start OpenBSD Secure Shell server.

1 Like

What if we autogenerate it?

cat <<EOF > /lib/systemd/system/sshd.service.d/20_preload_disable.conf
[Service]
ExecStart=$(sed -n 's/ExecStart=/\/usr\/bin\/ld-system-preload-disable /p' /lib/systemd/system/ssh.service)
EOF

Bit hacky but seems to work.

Likely due to bwrap. Since OpenSSH runs as root anyway, we could try unshare:

ExecStart=/usr/bin/unshare -m /bin/bash -c "mount --bind /dev/null /etc/ld.so.preload; /usr/sbin/sshd -D $SSHD_OPTS"

But that’s even uglier and hackier.

1 Like

Release 8 · GrapheneOS/hardened_malloc · GitHub is in testers repository for a while now.

1 Like

updated on my vms , no weird behavior observed.

1 Like

Currently, our fork’s tree looks pretty messy and it’s difficult to determine Whonix’s changes as everything is mixed in with upstream’s commits: Commits · Kicksecure/hardened_malloc · GitHub

Could you manage it in a way similar to how GrapheneOS/linux-hardened does forks? By rebasing upon each release, applying custom commits on top and squashing related commits together so everything is neat and tidy. It would make it significantly easier to review.

For example, look at:

https://github.com/GrapheneOS/platform_bionic/commits/11
https://github.com/GrapheneOS/kernel_google_coral/commits/11
Commits · anthraxx/linux-hardened · GitHub

1 Like

No source by upstream is modified. Only additional files. Comparison should be pretty simple. Check this…

git diff --stat 8

 .travis.yml                                       |   18 +
 README_generic.md                                 |   80 ++
 changelog.upstream                                | 4165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 debian/30_hardened-malloc-kicksecure.conf         |    8 +
 debian/50hardened-malloc                          |   16 +
 debian/changelog                                  |  167 +++
 debian/ci_test                                    |    9 +
 debian/compat                                     |    1 +
 debian/control                                    |   55 +
 debian/copyright                                  |   22 +
 debian/hardened-malloc-kicksecure                 |    7 +
 debian/hardened-malloc-kicksecure-enable.install  |    9 +
 debian/hardened-malloc-kicksecure-enable.postinst |   57 +
 debian/hardened-malloc-kicksecure-enable.prerm    |   52 +
 debian/hardened-malloc.install                    |    7 +
 debian/hardened_malloc.conf                       |    2 +
 debian/make-helper-overrides.bsh                  |   13 +
 debian/rules                                      |   28 +
 debian/source/format                              |    1 +
 debian/source/lintian-overrides                   |    2 +
 debian/source/options                             |    1 +
 debian/watch                                      |    6 +
 22 files changed, 4726 insertions(+)

git diff 8

Helps?

1 Like

It’s still pretty messy when viewing the commit history.

This branch is 97 commits ahead, 3 commits behind GrapheneOS:main.

All fixes, tests, configuration changes, etc. could be squashed into just a few commits and moved to the top of the tree. Then our fork would only be like 5 commits ahead of upstream and they would be easily accessible by looking at the top of the history. It would look much cleaner.

1 Like

I would squash them into a single commit. How do I do that? git rebase 8 somehow misses things. This would probably require git force push?

1 Like

Would probably be simplest to just drop all of your commits so it’s identical to upstream, then copy debian/, .travis.yml, README_generic.md and changelog.upstream and push a completely new commit. For every GrapheneOS release, you can just rebase upon upstream and add that one commit.

1 Like

Fixed in Debian bullseye.

Not fixed in Debian bullseye. Reported upstream.

1 Like

Updated package.

new release by upstream: