1

While I was playing a little with kernel audit system, I made a small C program:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv){
        void *t;
        while(1){
                t = malloc(1);
                free(t);

        }
        return 0;
}

And applied the following filters to audit:

-a always,exit -F arch=b32 -S open,openat -F exit=-EACCES -F key=access
-a always,exit -F arch=b64 -S open,openat -F exit=-EACCES -F key=access
-a always,exit -F arch=b32 -S brk
-a always,exit -F arch=b64 -S brk

After compiling and running, I noticed that sys_brk wasn't showing up in the audit log. Furthermore it didn't also appear in strace, even tho malloc was called (checked with ltrace). Lastly I removed the free and the calls to sys_brk started showing up.

What is causing this type of behaviour? Does glibc make some kind of optimization in malloc and free functions to prevent useless syscalls?

TL;DR: free followed by malloc makes neither call the kernel. Why?

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
  • It might use brk () or mmap () – 炸鱼薯条德里克 Mar 08 '19 at 01:04
  • Neither appeared in strace – Jorge Heleno Mar 08 '19 at 02:07
  • malloc() and free() are both library functions, not system calls, and a free() doesn't immediately return the freed memory to the system (which isn't even possible to do with less than 1 mempage granularity), but is putting it on a free blocks list. This question is similar to "why isn't every putchar(3) resulting in a write(2)?" –  Mar 08 '19 at 07:45
  • I think you didn't read the question. The problem, as explained, is brk not being called when malloc is.... – Jorge Heleno Mar 08 '19 at 09:31
  • You haven't explained why you assume that brk() has to be called every time malloc() is called (or every 10 or 100 times, it doesn't matter). In the second case, the program break has to be adjusted with brk() because you're leaking memory (allocating memory without freeing it). –  Mar 08 '19 at 10:36

1 Answers1

2

Your program starts with an initial heap, and your one byte allocation fits within that heap. When you immediately free the allocated memory, the heap never needs to grow so you never see a corresponding system call.

See How quickly/often are process memory measurements updated in the kernel? for a similar experiment.

Stephen Kitt
  • 434,908