Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Safe-Linking to Single-Linked-Lists (SLL) #19

Closed
wants to merge 1 commit into from

Conversation

chkp-eyalit
Copy link

Safe-Linking is a security mechanism that protects single-linked
lists (such as the Free Lists) from being tampered by attackers. The
mechanism makes use of the randomness from ASLR (mmap_base), and when
combined with object alignment integrity checks, it protects the
pointers from being hijacked by an attacker.

While Safe-Unlinking protects double-linked lists (such as the Small
Bins in ptmalloc), there wasn't any siilar protection for attacks
against single-linked lists. This solution protects against three
common attacks:

  • Partial pointer override: Modifies the lower bytes (Little Endian)
  • Full pointer override: Hijacks the pointer to an attacker's location
  • Unaligned objects: Pointing the list to an unaligned address

The design assumes an attacker doesn't know where the heap is located,
and uses the ASLR randomness to "sign" the single-linked pointers. We
mark the pointer as P and the location in which it is stored as L, and
the calculation will be:

  • PROTECT(P) := (L >> PAGE_SHIFT) XOR (P)
  • *L = PROTECT(P)

This way, the random bits from the address L (which start at the bits
in the PAGE_SHIFT position), will be merged with the LSB of the stored
protected pointer. This protection layer prevents an attacker from
modifying the pointer into a controlled value.

An additionl check that the objects are kAligned adds an important
layer:

  • Attackers can't point to illegal (unaligned) memory address
  • Attackers must guess correctly the alignment bits

Due to kAlignment being 8, an attacker will directly fail 7 out of 8
times. And this could be improved in the future if the alignment will
match the class size, per Free List.

This proposed patch was benchmarked using gperftools's benchmarking suite
and on the worst test case it has an additional overhead of 1.5%, while the
overhead for the average test case was a negligible 0.02%. In addition, in
2013 a similar mitigation was incorporated into Chromium's Free List (FL)
implementation in their version of TCMalloc. According to Chromium's
documentation, the added overhead was less than 2%.

Safe-Linking will currently be activated if compiled using the MACRO:
TCMALLOC_USE_SLL_SAFE_LINKING.
Hopefully, this feature will be activated by default after further testings
by the repository's developers.

A similar pull request was also sent to GLIBC (ptmalloc), uClibg-NG (dlmalloc),
and gperftools's implementation of TCMalloc.

For more information, feel free to read our full white-paper (attached):
Safe-Linking-White-Paper.txt

Safe-Linking is a security mechanism that protects single-linked
lists (such as the Free Lists) from being tampered by attackers. The
mechanism makes use of the randomness from ASLR (mmap_base), and when
combined with object alignment integrity checks, it protects the
pointers from being hijacked by an attacker.

While Safe-Unlinking protects double-linked lists (such as the Small
Bins in ptmalloc), there wasn't any siilar protection for attacks
against single-linked lists. This solution protects against three
common attacks:
  * Partial pointer override: Modifies the lower bytes (Little Endian)
  * Full pointer override: Hijacks the pointer to an attacker's location
  * Unaligned objects: Pointing the list to an unaligned address

The design assumes an attacker doesn't know where the heap is located,
and uses the ASLR randomness to "sign" the single-linked pointers. We
mark the pointer as P and the location in which it is stored as L, and
the calculation will be:
  * PROTECT(P) := (L >> PAGE_SHIFT) XOR (P)
  * *L = PROTECT(P)

This way, the random bits from the address L (which start at the bits
in the PAGE_SHIFT position), will be merged with the LSB of the stored
protected pointer. This protection layer prevents an attacker from
modifying the pointer into a controlled value.

An additionl check that the objects are kAligned adds an important
layer:
  * Attackers can't point to illegal (unaligned) memory address
  * Attackers must guess correctly the alignment bits

Due to kAlignment being 8, an attacker will directly fail 7 out of 8
times. And this could be improved in the future if the alignment will
match the class size, per Free List.

This proposed patch was benchmarked using gperftools's benchmarking suite
and on the worst test case it has an additional overhead of 1.5%, while the
overhead for the average test case was a negligible 0.02%. In addition, in
2013 a similar mitigation was incorporated into Chromium's Free List (FL)
implementation in their version of TCMalloc. According to Chromium's
documentation, the added overhead was less than 2%.

Safe-Linking will currently be activated if compiled using the MACRO:
TCMALLOC_USE_SLL_SAFE_LINKING. Hopefully, this feature will be activated
by default after further testings by the repository's developers.
@ckennelly
Copy link
Collaborator

The performance costs of this are too high to merge. While macro-protected, it adds another configuration that needs to be built and regularly tested to ensure everything stays working.

As discussed in #2, TCMalloc has evolved considerably over the years. For the most part, we use per-CPU caches, which have their freelist metadata out-of-band from the allocations we hand out. While problematic nonetheless, it may not corrupt the front line caches used by TCMalloc.

We've also implemented GWP ASan for finding many bugs via sampling. This doesn't catch everything (right away), but its lower overhead allows it to be widely used.

For hardened use cases, the LLVM project's scudo allocator might be better suited than TCMalloc.

@chkp-eyalit
Copy link
Author

While it is your final decision as the developers of this repository, I still ask that you reconsider it. The performance implications were good enough to get integrated into Chrome years ago, the same browser that I now use to write this comment to you. The benchmarking of this feature using gperftool's TCMalloc, showed an average overhead of 0.02% on the GCP machine on which we tested it (and worst case of 1.5%). Could you please share the performance costs that you received in your setup so I could get a better understanding of the underlying problem?

In our test cases for this feature we easily shown that a simple buffer overflow corrupts the SLL pointer to achieve an exploit primitive of an arbitrary heap allocation. Needless to say that the same attack was immediately blocked by the proposed feature that adds only a few assembly instructions per call to Malloc/Free.

Our initial goal with the Safe-Linking feature was to integrate it to core Malloc implementations so to grant efficient security by default to as wide an audience as we can. For this cause we are now working with GLIBC's ptmalloc, uClibc-NG's dlmalloc and (both) TCMalloc implementation from Google. It would be sad to see that Google stay's behind while the rest of the popular implementations choose to help protect the users of their libraries.

@ckennelly ckennelly closed this Feb 29, 2020
@wchristian
Copy link

Closing this without even answering the last message does not strike me as good faith.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants