Hardened Malloc - Hardened Memory Allocator

Got a reply on the CLIP OS issue:

We looked at hardened_malloc a while ago and are likely to integrate it to CLIP OS (at least to the Core ). As we still have quite important things to accomplish beforehand, we won’t tackle this straightaway but contributions are of course welcome.

Thanks for opening this issue, I’ll leave it open to track related progress.

2 Likes

We can disable hardened_malloc per program by using bubblewrap (or any other namespacing program):

bwrap --dev-bind / / --tmpfs /usr/lib/libhardened_malloc.so program_name

This makes the /usr/lib/libhardened_malloc.so directory an empty tmpfs without the hardened_malloc library so it isn’t preloaded:

ERROR: ld.so: object '/usr/lib/libhardened_malloc.so/libhardened_malloc.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.

This can be verified with cat /proc/self/maps. You’ll see /usr/lib/libhardened_malloc.so/libhardened_malloc.so in the output without bubblewrap and it’ll be missing with bubblewrap.

So if we have any issues with programs, we can just use bubblewrap.

2 Likes
1 Like
1 Like
1 Like

This is now in Whonix testers repository.

1 Like

Tested this by globally preloading it and there are a few issues (likely not with hardened_malloc itself though):

  • It’s quite slow
  • The mouse is a bit janky
  • Xorg bugs out but then fixes itself
  • The Tor Browser refuses to start

I still think we should enable this globally by default though. Just with a few exceptions + reporting any bugs uncovered upstream. Or, alternatively, we can try disabling a few options and see if it fixes anything.

GitHub - GrapheneOS/hardened_malloc: Hardened allocator designed for modern systems. It has integration into Android's Bionic libc and can be used externally with musl and glibc as a dynamic library for use on other Linux-based platforms. It will gain more portability / integration over time.

Even with all of those options disabled, it’s still pretty secure.

2 Likes

I tried the leaner configuration example and literally all issues are fixed.

make \
CONFIG_WRITE_AFTER_FREE_CHECK=false \
CONFIG_SLOT_RANDOMIZE=false \
CONFIG_SLAB_QUARANTINE_RANDOM_LENGTH=0 \
CONFIG_SLAB_QUARANTINE_QUEUE_LENGTH=0 \
CONFIG_GUARD_SLABS_INTERVAL=8

I don’t even see much of a performance loss anymore. Can you test this also?

1 Like

Hardened Malloc is a Debian package for “public service” for lack of better term. Changing compile time options would be weird because then it would be a fork. It would reduce security for those who are using it right now.

Though, could always stop providing that public service and call it a Kicksecure specific fork.

Or compile it twice during build if that is possible (probably is). The default, not-used by default hardened-malloc package and perhaps hardened-malloc-kicksecure - the latter could be installed to a different path and enabled by default.

1 Like

That would be the best choice. Users could use the default hardened_malloc for some applications if they want for the extra security features.

2 Likes

delete pyc files in test folder by adrelanos · Pull Request #121 · GrapheneOS/hardened_malloc · GitHub

2 Likes

@madaidan yet another option: is there a way to blacklist the apps that run into problems when running under the standard hardened_malloc and maybe redirect them to the system default one? Can multiple mem allocators coexist on the same system?

Or maybe reserve the permissive fork for problematic programs and otherwise defer them to the more secure version (by default) as is from Micay?

2 Likes

Yes.

Those problematic programs seem to be most things so it would make more sense to keep the permissive one as the default.

2 Likes

Managed to trim the config down to

CONFIG_SLAB_QUARANTINE_RANDOM_LENGTH=0
CONFIG_SLAB_QUARANTINE_QUEUE_LENGTH=0
CONFIG_GUARD_SLABS_INTERVAL=8

with the help of Daniel.

2 Likes

I’ve tried to implement this. What do you think?

GitHub - madaidan/hardened_malloc at kicksecure

1 Like

I don’t want to fork any of the files shipped by upstream if not absolutely required. make isn’t something I am comfortable with long term. However, if such Makefile changes were upstreamed this were very much OK. But in this case I doubt upstream would accept a patch to introduce libhardened_malloc_kicksecure.so: $(OBJECTS) and code duplication.

What upstream might accept is configuring the resulting “end product” (for lack for better term) file name libhardened_malloc.so. I.e. could libhardened_malloc.so: $(OBJECTS) be made configurable? If not set, default to libhardened_malloc.so. If set, use that filename set from a make variable.


rm *.o

Better run make clean. More appropriate and future proof.


Here is an approach which would not need any upstream patches, which doesn’t require modifications of files shipped by upstream that should be sold.

override_dh_auto_build:
	dh_auto_build -- libhardened_malloc.so CONFIG_NATIVE=false CC=$(CC)
	mv libhardened_malloc.so libhardened_malloc.so_original
	make clean
	dh_auto_build -- libhardened_malloc.so CONFIG_SLAB_QUARANTINE_RANDOM_LENGTH=0 CONFIG_SLAB_QUARANTINE_QUEUE_LENGTH=0 CONFIG_GUARD_SLABS_INTERVAL=8 CC=$(CC)
	mv libhardened_malloc.so libhardened_malloc.so_kicksecure

and…

libhardened_malloc.so_original usr/lib/libhardened_malloc.so/libhardened_malloc.so
libhardened_malloc.so_kicksecure usr/lib/libhardened_malloc.so/libhardened_malloc_kicksecure.so

Would that work?

2 Likes

Yes, that’d be perfect.

1 Like

Could you do a new test / PR please?