[cfe-dev] Question about optimization of new and delete

Jonathan Sauer jonathan.sauer at gmx.de
Mon Sep 30 11:20:23 PDT 2013


Hello,

>> The superfluous NULL check here is preventing the elimination of the
>> store. In my opinion we should optimize this based on the assumption
>> that a pointer can't be NULL after a load/store to it. GCC does this
>> and got some flak because it turned a crash into a security problem
>> in the Linux kernel (-fno-delete-null-pointer-checks was introduced
>> as a remedy). I'm not sure how to best implement that with our
>> current VRP infrastructure.
> 
> Interesting. Do you mean that the kernel will not internally fault if it stores to some place near 0x0? Or was the offset so large that it was going someplace valid?

The former. From the paper "Undefined Behavior: What Happened to My Code"
(<pdos.csail.mit.edu/papers/ub:apsys12.pdf>):

| unsigned int
| tun_chr_poll(struct file *file, poll_table * wait) {
|   struct tun_file *tfile = file->private_data;
|   struct tun_struct *tun = __tun_get(tfile);
|   struct sock *sk = tun->sk;
|   if (!tun)
|     return POLLERR;
|   ...
| }
|
| Figure 6: An invalid null pointer check due to null pointer dereference, in
| drivers/net/tun.c of the Linux kernel, which uses GCC’s -fno-delete-null-pointer-checks
| to prevent such checks from being removed.
|
| Figure 6 shows an example from the Linux kernel. The code dereferences tun
| via tun->sk, and only afterward does it validate that tun is non-null. Given
| a null tun, it was expected that this null-check-after-dereference bug would
| either cause a kernel oops as a result of the tun->sk dereference, or return an
| error code due to the null pointer check (e.g., when address 0 is mapped). Neither
| was considered a serious vulnerability.
|
| However, an unexpected optimization makes this bug exploitable. When GCC sees
| the dereference, it assumes that tun is non-null, and removes the “redundant”
| null pointer check. An attacker can then continue to run the rest of the function
| with tun pointing to address 0, leading to privilege escalation [9]. The Linux
| kernel started using GCC’s -fno-delete-null-pointer-checks to disable such
| optimizations.

> In any case, I guess that we should probably do the same.

I agree. This is undefined behavior clang should exploit for optimizations.


Jonathan





More information about the cfe-commits mailing list