Good question. There's a good reason for that.
On default scenarios, such as the default provided pre and post processing routines, dataBuf "comes back" with the same value of srcBuf. Essentially, nothing was done to the buffer. Data was not "transformed".

If you see the code gridfs_store_buffer():

...
oChunk = chunk_new(id, chunkNumber, &targetBuf, (void*)data_ptr, chunkLen, flags );
    memAllocated = targetBuf != data_ptr;
...

 if( memAllocated ) {
    bson_free( targetBuf );
  }

If the returned targetBuf is different than the data_ptr, then we know memory was allocated and the code bellow will free the allocated memory. Assumption is that bson_malloc was called, therefore bson_free is utilized.
We could provide extra functionality to control deallocation using a callback, because the pre-processing logic or even the post-processing logic could control the allocation using some other function, therefore it will be more proper to delegate deallocation to this callbacks.... ( the more I think about, I should implement this whole pre/post processing using a delegation pattern object )

Allowing callbacks to allocate memory is necessary when creating algorithms for the pre or post processing that will transform data. You don't want to write to the source buffer. While, this double buffer variable mechanism is handy for scenarios where all you want to do is "look" at the data without transforming it. What you do is return the same value as provided in source.

Now, this is how I coded compression using pre and post processing:

static int ZlibPreProcessChunk(void** targetBuf, size_t* targetLen, void* srcBuf, size_t srcLen, int flags) {
  uLongf tmpLen = compressBound( DEFAULT_CHUNK_SIZE );
  if( flags & GRIDFILE_COMPRESS ) {    
    if( *targetBuf == NULL ) {
      *targetBuf = bson_malloc( tmpLen );
    }
    if( compress2( (Bytef*)(*targetBuf), &tmpLen, (Bytef*)srcBuf, (uLong)srcLen, Z_BEST_SPEED ) != Z_OK ) {
      return -1;
    }    
    *targetLen = (size_t)tmpLen;
  } else {
    *targetBuf = (void*)srcBuf;
    *targetLen = srcLen;
  }
  return 0;
}

static int ZlibPostProcessChunk(void** targetBuf, size_t* targetLen, void* srcData, size_t srcLen, int flags) {   
  uLongf tmpLen = DEFAULT_CHUNK_SIZE;
  if( flags & GRIDFILE_COMPRESS ) {  
    if( *targetBuf == NULL ) {
      *targetBuf = (void*)bson_malloc( tmpLen );
    }  
    if (uncompress( (Bytef*)(*targetBuf), &tmpLen, (Bytef*)srcData, (uLong)srcLen ) != Z_OK ) {
      return -1;
    }
    *targetLen = (size_t)tmpLen;
  } else {
    *targetBuf = srcData;
    *targetLen = srcLen;
  }
  return 0;
}

static size_t ZlibPendingDataNeededSize (int flags) {
  if( flags & GRIDFILE_COMPRESS ) {
    return compressBound( DEFAULT_CHUNK_SIZE );
  } else {
    return DEFAULT_CHUNK_SIZE;
  }
}

MONGO_EXPORT int initPrepostChunkProcessing( int flags ){
  setBufferProcessingProcs( ZlibPreProcessChunk, ZlibPostProcessChunk, ZlibPendingDataNeededSize );  
  return 0;
}

Notice how on ZlibPreProcessChunk will allocate memory for the targetBuf using compressBound() which will return a value higher than DEFAULT_CHUNK_SIZE ( you probably already know compression can result on a higher target size than source for already compressed data ).

Currently a flaw on the implementation of the pre and post processing is that I don't provide access to the underlying GridFile object, and that could be handy to know the real chunk size. Right now it's assuming the DEFAULT_CHUNK_SIZE on my Zlib compression implementation.
I plan to improve this by allowing access to gridfile.

Finally, the second improvement I want to do is to provide access to a "context" member on the GridFile to allocate this special temporary buffers only once. Yet give the responsability to the callback pre/post processing routines to perform the allocation and decide on the size to allocate. The current implementation incurs on overhead to allocate/deallocate this memory every call. Of course, compared to the cost of compression/decompression it's negligible cost anyway.