Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You get an efficiency problem there in that it means that the first thing allocations have to do is re-zero the allocation.


I think you got it. From some grumblings on twitter, it seems like calloc no longer zeros allocations since it assumes the memory is already zero'd and so assuming most people on the platform do the right thing (call calloc instead of malloc+memset/bzero), this change has zero performance impact. That might have some fun effects for writing exploits (if you can predict what page will be allocated next, you can do a sideways spray by hitting the region before its allocated and then let the downstream calloc callers get hit with unexpectedly non-zero fields.


Why would malloc zeroing memory have any impact on that? Yes calloc obviously no longer zeros memory, but calloc _can_ rely on that as it is part of the same libc. If you hit a region before it's been allocated you're either going to trigger a page fault, or overwrite memory that's going to be zero'd on allocation.


[this is an edit to answer my own question but I can't update the comment]

It sounds like the calloc implementation is _assuming_ that the underlying alloc always zeros, so essentially (ignore overflow check) calloc is doing something like forward directly to malloc(size*count). So I think it _changes_ the exploit path to something new.


Yeah, more or less! This closes some paths and opens brand new ones, like more of the former and less of the latter. For example, let's consider this code.

   void f(void) {
      obj *a;
      a = calloc(1, sizeof(a));
      g(a);
   }

   void g(obj *o) {
      if (o->callback) {
         o->callback();
      }
   }
it's contrived for simplicity, but suppose obj had a function pointer in it and just after allocation the object is passed to another routine which does some work on the object and checks if the callback exists and calls it if it does. In a single threaded application, you would not be able to target the function pointer here because nothing interesting happens between calloc and the invocation since the if check will always fail due to it being zero'd from calloc.

Now, as you mention, if calloc didn't zero, an attacker could scribble over what they think will be the next allocated slot in the heap (either by targeting a partially used page or an entirely unused page that's just being kept in malloc's retainer) and write a value into the callback pointer field. Now when a new object is allocated there, we end up using the corrupted data and invoking the evil pointer, and the rest is history.

It's a bit of a weirder exploit path but honestly with how ridiculous UAF flows have gotten with modern mitigations on iOS, it's hardly the worst thing I've ever seen and I suspect someone will get decent mileage out of it




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: