Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • Guided learning
      Receive custom learning paths powered by our AI assistant.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

Securing malloc in glibc: Why malloc hooks had to go

August 25, 2021
Siddhesh Poyarekar
Related topics:
C, C#, C++LinuxSecuritySecure coding
Related products:
Red Hat Enterprise Linux

Memory access is one of the most basic operations in computer programs. It is also an unending source of program errors in C programs, because memory safety was never really a programming language goal in C. Memory-related issues also comprise a significant part of the top 25 security weaknesses that result in program vulnerabilities.

Memory access also plays an important role in performance, which makes memory management a prime target for performance tuning. It is natural, then, that dynamic memory management in the C runtime should have capabilities that allow fine-grained tracking and customizable actions on allocation events. These features allow users to diagnose memory issues in their programs and if necessary, override the C runtime allocator with their own to improve performance or memory utilization.

This article describes the clash between the quest for flexibility and introspection, on the one hand, and performance and security protections on the other. You'll learn why this clash ultimately led to a major change in how memory allocation (malloc) is implemented in the GNU C Library, or glibc. We'll also discuss how to adapt applications that depended on the old way of doing things, as well as the implications for future versions of Fedora and Red Hat Enterprise Linux (RHEL).

Debugging malloc in glibc

Until recently, the GNU C Library, which is the core runtime library for RHEL, provided diagnostic functionality in the form of function pointers that users could overwrite to implement their own allocation functions. These function pointers were collectively called malloc hooks. If a hook was set to a function address, glibc allocator functions would call the function instead of the internal implementations, allowing programmers to perform arbitrary actions. A programmer could even run a custom function and then, if necessary, call the glibc memory allocator function again (by momentarily setting the hook to NULL) to get the actual block of memory.

All of the malloc debugging features in glibc (i.e., mtrace, mcheck, and the MALLOC_CHECK_ environment variable) were implemented using these hooks. These debugging features, and the hooks in general, were very useful because they provided checking on a more lightweight basis than the memory checking done by full-fledged memory debugging programs such as Valgrind and sanitizers.

Malloc hooks in multi-threaded applications

As applications became increasingly multi-threaded, it was discovered that manipulating malloc hooks in such environments was fraught with risks. All of the debugging features in glibc malloc except MALLOC_CHECK_ were, and continue to be, unsafe in multi-threaded environments. Malloc hooks, the basis of the debugging features, were not the only way to override malloc, either; glibc always supported the interposition of malloc functions by preloading a shared library with those functions. Glibc itself always calls malloc functions through its procedure linkage table (PLT) so that it can invoke the interposed functions.

To make things worse, much of the debugging infrastructure was tightly integrated into system allocator functionality. This made the task of enhancing the allocator unnecessarily complex. Furthermore, there was always the possibility of corner cases inducing unexpected behavior. Finally, implementing debugging features in the system allocator created a minor but unnecessary performance overhead.

The key misfeature of the debugging hooks, though, was their presence as unprotected function pointers that were guaranteed to be executed at specific events. This made the hooks an easy exploit primitive in practically every program that ran on Linux distributions. A trivial search for __malloc_hook "house of" turns up a long list of exploit methods that use the hooks as either an intermediate step or the final goal for the exploit.

Malloc hooks had to go.

Excising malloc hooks from the main library

The last of the malloc hook variables were deprecated in glibc 2.32 and new applications were encouraged to use malloc interposition instead. The effect of deprecation was mild: Newer applications just got a warning during the build. In the interest of maintaining backward compatibility, the memory allocator continued to look for hooks and, if available, execute them. In glibc version 2.34 (August 2021), we finally bit the bullet and took support for malloc hooks out of the mainstream library.

The upstream glibc community agreed that malloc debugging features have no place in production. So we moved all debugging features into a separate library named libc_malloc_debug.so.0 that overrides system malloc behavior to enable debugging. Most importantly, we either moved unprotected hook function pointers into libc_malloc_debug.so.0 or removed them completely. Doing this eliminated a key exploit primitive from the library.

Debugging and hardening in a post-hook world

The new glibc without the problematic hooks will be available in future versions of Fedora and RHEL. With this glibc, malloc debugging features such as MALLOC_CHECK_, mtrace(), and mcheck() will no longer work by default. Users will need to preload libc_malloc_debug.so.0 to enable these debugging features. Additionally, the __after_morecore_hook, __default_morecore_hook, and __morecore function pointers are no longer read, and the system malloc uses the brk() and mmap() system calls to request memory from the kernel.

System administrators may also remove the library from the system and effectively disable malloc debugging and malloc hooks. This is useful hardening for production systems that have strong controls on what files are available on the system.

Conclusion

Separating malloc debugging from the main library is a significant security hardening improvement in glibc. It eliminates an exploit primitive from Linux distributions and adds an opportunity for hardening in both RHEL and Fedora. Simplifying system allocator code also sets the stage for improvements to malloc that may result in better security and performance. Watch out for more interesting changes to the malloc subsystem in future releases of glibc.

Last updated: October 8, 2024

Related Posts

  • Malloc Internals and You

  • Malloc systemtap probes: an example

  • Memory error checking in C and C++: Comparing Sanitizers and Valgrind

  • Valgrind Memcheck: Different ways to lose your memory

Recent Posts

  • Every layer counts: Defense in depth for AI agents with Red Hat AI

  • Fun in the RUN instruction: Why container builds with distroless images can surprise you

  • Trusted software factory: Building trust in the agentic AI era

  • Build a zero trust AI pipeline with OpenShift and RHEL CVMs

  • Red Hat Hardened Images: Top 5 benefits for software developers

Red Hat Developers logo LinkedIn YouTube Twitter Facebook

Platforms

  • Red Hat AI
  • Red Hat Enterprise Linux
  • Red Hat OpenShift
  • Red Hat Ansible Automation Platform
  • See all products

Build

  • Developer Sandbox
  • Developer tools
  • Interactive tutorials
  • API catalog

Quicklinks

  • Learning resources
  • E-books
  • Cheat sheets
  • Blog
  • Events
  • Newsletter

Communicate

  • About us
  • Contact sales
  • Find a partner
  • Report a website issue
  • Site status dashboard
  • Report a security problem

RED HAT DEVELOPER

Build here. Go anywhere.

We serve the builders. The problem solvers who create careers with code.

Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

Sign me up

Red Hat legal and privacy links

  • About Red Hat
  • Jobs
  • Events
  • Locations
  • Contact Red Hat
  • Red Hat Blog
  • Inclusion at Red Hat
  • Cool Stuff Store
  • Red Hat Summit
© 2026 Red Hat

Red Hat legal and privacy links

  • Privacy statement
  • Terms of use
  • All policies and guidelines
  • Digital accessibility

Chat Support

Please log in with your Red Hat account to access chat support.