Markakd / safe_tcmalloc

Apache License 2.0
0 stars 0 forks source link

Pointer propagated through register #6

Open Markakd opened 1 year ago

Markakd commented 1 year ago
#include<stdlib.h>
#include<stdio.h>
char *src;
void start(char **ptr){
 *ptr = realloc(0,0x100);
}

void end(char **ptr){
 char *tmp = realloc(*ptr,0x0);
}
int main(){

 start(&src);
 char *b = src + 0x40;
 end(&src);
 *b = 'a';
 return 0;
}

An example provided by @kitaharazy, since char *b = src + 0x40; is very likely to be optimized into register, there will be no escape, resulting in the fn of UAF.

Markakd commented 1 year ago

https://github.com/nginx/njs/issues/444 is a similar case. The code is like the following:

njs_int_t
njs_value_to_primitive(njs_vm_t *vm, njs_value_t *dst, njs_value_t *value,
    njs_uint_t hint)
{
...
for ( ;; ) {
        ret = NJS_ERROR;
        if (njs_is_object(value) && tries < 2) { // UAF access here inside the loop, value is the dangling pointer after free
            hint ^= tries++;

            lhq.key_hash = hashes[hint];
            lhq.key = names[hint];

            ret = njs_object_property(vm, value, &lhq, &method);

            if (njs_slow_path(ret == NJS_ERROR)) {
                return ret;
            }

            if (njs_is_function(&method)) {
                // value is freed inside this function
                ret = njs_function_apply(vm, njs_function(&method), value, 1,
                                         &retval);

                if (njs_slow_path(ret != NJS_OK)) {
                    return ret;
                }

                if (njs_is_primitive(&retval)) {
                    break;
                }
            }

            /* Try the second method. */
            continue;
         }

        njs_type_error(vm, "Cannot convert object to primitive value");

        return ret;
    }
}