Preserve itx alloc size for zio_data_buf_free()

Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free.  Using a different itx->itx_lr.lrc_reclen
size in zio_data_buf_free() can result in the allocation being
returned to the wrong kmem cache.

This issue can be avoided entirely by storing the allocation size
in itx->itx_size and using that for zio_data_buf_free().

Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #6912
This commit is contained in:
Brian Behlendorf 2017-12-04 11:44:39 -08:00 committed by GitHub
parent d4677269f2
commit 72841b9fd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 6 additions and 2 deletions

View File

@ -395,6 +395,7 @@ typedef struct itx {
uint8_t itx_sync; /* synchronous transaction */ uint8_t itx_sync; /* synchronous transaction */
zil_callback_t itx_callback; /* Called when the itx is persistent */ zil_callback_t itx_callback; /* Called when the itx is persistent */
void *itx_callback_data; /* User data for the callback */ void *itx_callback_data; /* User data for the callback */
size_t itx_size; /* allocated itx structure size */
uint64_t itx_oid; /* object id */ uint64_t itx_oid; /* object id */
lr_t itx_lr; /* common part of log record */ lr_t itx_lr; /* common part of log record */
/* followed by type-specific part of lr_xx_t and its immediate data */ /* followed by type-specific part of lr_xx_t and its immediate data */

View File

@ -1254,17 +1254,20 @@ cont:
itx_t * itx_t *
zil_itx_create(uint64_t txtype, size_t lrsize) zil_itx_create(uint64_t txtype, size_t lrsize)
{ {
size_t itxsize;
itx_t *itx; itx_t *itx;
lrsize = P2ROUNDUP_TYPED(lrsize, sizeof (uint64_t), size_t); lrsize = P2ROUNDUP_TYPED(lrsize, sizeof (uint64_t), size_t);
itxsize = offsetof(itx_t, itx_lr) + lrsize;
itx = zio_data_buf_alloc(offsetof(itx_t, itx_lr) + lrsize); itx = zio_data_buf_alloc(itxsize);
itx->itx_lr.lrc_txtype = txtype; itx->itx_lr.lrc_txtype = txtype;
itx->itx_lr.lrc_reclen = lrsize; itx->itx_lr.lrc_reclen = lrsize;
itx->itx_lr.lrc_seq = 0; /* defensive */ itx->itx_lr.lrc_seq = 0; /* defensive */
itx->itx_sync = B_TRUE; /* default is synchronous */ itx->itx_sync = B_TRUE; /* default is synchronous */
itx->itx_callback = NULL; itx->itx_callback = NULL;
itx->itx_callback_data = NULL; itx->itx_callback_data = NULL;
itx->itx_size = itxsize;
return (itx); return (itx);
} }
@ -1272,7 +1275,7 @@ zil_itx_create(uint64_t txtype, size_t lrsize)
void void
zil_itx_destroy(itx_t *itx) zil_itx_destroy(itx_t *itx)
{ {
zio_data_buf_free(itx, offsetof(itx_t, itx_lr)+itx->itx_lr.lrc_reclen); zio_data_buf_free(itx, itx->itx_size);
} }
/* /*