Just to be clear: I do know that malloc and free are implemented in the C library, which usually allocates chunks of memory from the OS and does it
I would suggest that it is because it is very convenient not to have to manually track size information in this way (in some cases) and also less prone to programmer error.
Additionally, realloc would need this bookkeeping information, which I expect contains more than just the allocation size. i.e. it allows the mechanism by which it works to be implementation defined.
You could write your own allocator that worked somewhat in the way you suggest though and it is often done in c++ for pool allocators in a kind of similar way for specific cases (with potentially massive performance gains) though this is generally implemented in terms of operator new for allocating pool blocks.