Skip to content

Commit

Permalink
File format security issues (#4234)
Browse files Browse the repository at this point in the history
  • Loading branch information
derobins authored Mar 27, 2024
1 parent 74498cb commit 136739b
Show file tree
Hide file tree
Showing 55 changed files with 1,234 additions and 295 deletions.
26 changes: 13 additions & 13 deletions src/H5Adense.c
Original file line number Diff line number Diff line change
Expand Up @@ -1104,12 +1104,12 @@ H5A__dense_iterate(H5F_t *f, hid_t loc_id, const H5O_ainfo_t *ainfo, H5_index_t
H5_iter_order_t order, hsize_t skip, hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op,
void *op_data)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */
haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */
herr_t ret_value = FAIL; /* Return value */
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
H5A_attr_table_t atable = {0, 0, NULL}; /* Table of attributes */
H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */
haddr_t bt2_addr; /* Address of v2 B-tree to use for lookup */
herr_t ret_value = FAIL; /* Return value */

FUNC_ENTER_PACKAGE

Expand Down Expand Up @@ -1499,12 +1499,12 @@ herr_t
H5A__dense_remove_by_idx(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type, H5_iter_order_t order,
hsize_t n)
{
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */
haddr_t bt2_addr; /* Address of v2 B-tree to use for operation */
herr_t ret_value = SUCCEED; /* Return value */
H5HF_t *fheap = NULL; /* Fractal heap handle */
H5HF_t *shared_fheap = NULL; /* Fractal heap handle for shared header messages */
H5A_attr_table_t atable = {0, 0, NULL}; /* Table of attributes */
H5B2_t *bt2 = NULL; /* v2 B-tree handle for index */
haddr_t bt2_addr; /* Address of v2 B-tree to use for operation */
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_PACKAGE

Expand Down Expand Up @@ -1586,7 +1586,7 @@ H5A__dense_remove_by_idx(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes");

/* Check for skipping too many attributes */
if (n >= atable.nattrs)
if (n >= atable.num_attrs)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified");

/* Delete appropriate attribute from dense storage */
Expand Down
109 changes: 52 additions & 57 deletions src/H5Aint.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,9 @@
typedef struct {
H5F_t *f; /* Pointer to file that fractal heap is in */
H5A_attr_table_t *atable; /* Pointer to attribute table to build */
size_t curr_attr; /* Current attribute to operate on */
bool bogus_crt_idx; /* Whether bogus creation index values need to be set */
} H5A_compact_bt_ud_t;

/* Data exchange structure to use when building table of dense attributes for an object */
typedef struct {
H5A_attr_table_t *atable; /* Pointer to attribute table to build */
size_t curr_attr; /* Current attribute to operate on */
} H5A_dense_bt_ud_t;

/* Data exchange structure to use when copying an attribute from _SRC to _DST */
typedef struct {
const H5O_ainfo_t *ainfo; /* dense information */
Expand Down Expand Up @@ -1455,30 +1448,31 @@ H5A__compact_build_table_cb(H5O_t H5_ATTR_UNUSED *oh, H5O_mesg_t *mesg /*in,out*
assert(mesg);

/* Re-allocate the table if necessary */
if (udata->curr_attr == udata->atable->nattrs) {
if (udata->atable->num_attrs == udata->atable->max_attrs) {
H5A_t **new_table; /* New table for attributes */
size_t new_table_size; /* Number of attributes in new table */

/* Allocate larger table */
new_table_size = MAX(1, 2 * udata->atable->nattrs);
new_table_size = MAX(1, 2 * udata->atable->max_attrs);
if (NULL == (new_table = (H5A_t **)H5FL_SEQ_REALLOC(H5A_t_ptr, udata->atable->attrs, new_table_size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "unable to extend attribute table");

/* Update table information in user data */
udata->atable->attrs = new_table;
udata->atable->nattrs = new_table_size;
udata->atable->attrs = new_table;
udata->atable->max_attrs = new_table_size;
} /* end if */

/* Copy attribute into table */
if (NULL == (udata->atable->attrs[udata->curr_attr] = H5A__copy(NULL, (const H5A_t *)mesg->native)))
if (NULL ==
(udata->atable->attrs[udata->atable->num_attrs] = H5A__copy(NULL, (const H5A_t *)mesg->native)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute");

/* Assign [somewhat arbitrary] creation order value, if requested */
if (udata->bogus_crt_idx)
((udata->atable->attrs[udata->curr_attr])->shared)->crt_idx = sequence;
((udata->atable->attrs[udata->atable->num_attrs])->shared)->crt_idx = sequence;

/* Increment current attribute */
udata->curr_attr++;
/* Increment attribute count */
udata->atable->num_attrs++;

done:
FUNC_LEAVE_NOAPI(ret_value)
Expand All @@ -1501,9 +1495,10 @@ herr_t
H5A__compact_build_table(H5F_t *f, H5O_t *oh, H5_index_t idx_type, H5_iter_order_t order,
H5A_attr_table_t *atable)
{
H5A_compact_bt_ud_t udata; /* User data for iteration callback */
H5O_mesg_operator_t op; /* Wrapper for operator */
herr_t ret_value = SUCCEED; /* Return value */
H5A_compact_bt_ud_t udata; /* User data for iteration callback */
H5O_mesg_operator_t op; /* Wrapper for operator */
bool iter_set_up = false; /* Is everything set up for iteration */
herr_t ret_value = SUCCEED; /* Return value */

FUNC_ENTER_PACKAGE

Expand All @@ -1513,34 +1508,37 @@ H5A__compact_build_table(H5F_t *f, H5O_t *oh, H5_index_t idx_type, H5_iter_order
assert(atable);

/* Initialize table */
atable->attrs = NULL;
atable->nattrs = 0;
atable->attrs = NULL;
atable->num_attrs = 0;
atable->max_attrs = 0;

/* Set up user data for iteration */
udata.f = f;
udata.atable = atable;
udata.curr_attr = 0;
udata.f = f;
udata.atable = atable;
udata.bogus_crt_idx =
(bool)((oh->version == H5O_VERSION_1 || !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED)) ? true
: false);

/* Iterate over existing attributes, checking for attribute with same name */
op.op_type = H5O_MESG_OP_LIB;
op.u.lib_op = H5A__compact_build_table_cb;
iter_set_up = true;
if (H5O__msg_iterate_real(f, oh, H5O_MSG_ATTR, &op, &udata) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error building attribute table");

/* Correct # of attributes in table */
atable->nattrs = udata.curr_attr;

/* Don't sort an empty table. */
if (atable->nattrs > 0) {
if (atable->num_attrs > 0)
/* Sort attribute table in correct iteration order */
if (H5A__attr_sort_table(atable, idx_type, order) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTSORT, FAIL, "error sorting attribute table");
} /* end if */

done:
if (ret_value < 0)
/* Clean up partially built table on error */
if (iter_set_up)
if (atable->attrs && H5A__attr_release_table(atable) < 0)
HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table");

FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__compact_build_table() */

Expand All @@ -1557,26 +1555,26 @@ H5A__compact_build_table(H5F_t *f, H5O_t *oh, H5_index_t idx_type, H5_iter_order
static herr_t
H5A__dense_build_table_cb(const H5A_t *attr, void *_udata)
{
H5A_dense_bt_ud_t *udata = (H5A_dense_bt_ud_t *)_udata; /* 'User data' passed in */
herr_t ret_value = H5_ITER_CONT; /* Return value */
H5A_attr_table_t *atable = (H5A_attr_table_t *)_udata; /* 'User data' passed in */
herr_t ret_value = H5_ITER_CONT; /* Return value */

FUNC_ENTER_PACKAGE

/* check arguments */
assert(attr);
assert(udata);
assert(udata->curr_attr < udata->atable->nattrs);
assert(atable);
assert(atable->num_attrs < atable->max_attrs);

/* Allocate attribute for entry in the table */
if (NULL == (udata->atable->attrs[udata->curr_attr] = H5FL_CALLOC(H5A_t)))
if (NULL == (atable->attrs[atable->num_attrs] = H5FL_CALLOC(H5A_t)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, H5_ITER_ERROR, "can't allocate attribute");

/* Copy attribute information. Share the attribute object in copying. */
if (NULL == H5A__copy(udata->atable->attrs[udata->curr_attr], attr))
if (NULL == H5A__copy(atable->attrs[atable->num_attrs], attr))
HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute");

/* Increment number of attributes stored */
udata->curr_attr++;
atable->num_attrs++;

done:
FUNC_LEAVE_NOAPI(ret_value)
Expand Down Expand Up @@ -1622,30 +1620,26 @@ H5A__dense_build_table(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type,
if (H5B2_get_nrec(bt2_name, &nrec) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve # of records in index");

/* Set size of table */
H5_CHECK_OVERFLOW(nrec, /* From: */ hsize_t, /* To: */ size_t);
atable->nattrs = (size_t)nrec;

/* Allocate space for the table entries */
if (atable->nattrs > 0) {
H5A_dense_bt_ud_t udata; /* User data for iteration callback */
if (nrec > 0) {
H5A_attr_iter_op_t attr_op; /* Attribute operator */

/* Allocate the table to store the attributes */
if ((atable->attrs = (H5A_t **)H5FL_SEQ_CALLOC(H5A_t_ptr, atable->nattrs)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
/* Check for overflow on the downcast */
H5_CHECK_OVERFLOW(nrec, /* From: */ hsize_t, /* To: */ size_t);

/* Set up user data for iteration */
udata.atable = atable;
udata.curr_attr = 0;
/* Allocate the table to store the attributes */
if (NULL == (atable->attrs = (H5A_t **)H5FL_SEQ_CALLOC(H5A_t_ptr, (size_t)nrec)))
HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "memory allocation failed");
atable->num_attrs = 0;
atable->max_attrs = (size_t)nrec;

/* Build iterator operator */
attr_op.op_type = H5A_ATTR_OP_LIB;
attr_op.u.lib_op = H5A__dense_build_table_cb;

/* Iterate over the links in the group, building a table of the link messages */
if (H5A__dense_iterate(f, (hid_t)0, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE, (hsize_t)0, NULL, &attr_op,
&udata) < 0)
atable) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table");

/* Sort attribute table in correct iteration order */
Expand Down Expand Up @@ -1791,18 +1785,18 @@ H5A__attr_sort_table(H5A_attr_table_t *atable, H5_index_t idx_type, H5_iter_orde
/* Pick appropriate comparison routine */
if (idx_type == H5_INDEX_NAME) {
if (order == H5_ITER_INC)
qsort(atable->attrs, atable->nattrs, sizeof(H5A_t *), H5A__attr_cmp_name_inc);
qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_name_inc);
else if (order == H5_ITER_DEC)
qsort(atable->attrs, atable->nattrs, sizeof(H5A_t *), H5A__attr_cmp_name_dec);
qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_name_dec);
else
assert(order == H5_ITER_NATIVE);
} /* end if */
else {
assert(idx_type == H5_INDEX_CRT_ORDER);
if (order == H5_ITER_INC)
qsort(atable->attrs, atable->nattrs, sizeof(H5A_t *), H5A__attr_cmp_corder_inc);
qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_corder_inc);
else if (order == H5_ITER_DEC)
qsort(atable->attrs, atable->nattrs, sizeof(H5A_t *), H5A__attr_cmp_corder_dec);
qsort(atable->attrs, atable->num_attrs, sizeof(H5A_t *), H5A__attr_cmp_corder_dec);
else
assert(order == H5_ITER_NATIVE);
} /* end else */
Expand Down Expand Up @@ -1839,7 +1833,7 @@ H5A__attr_iterate_table(const H5A_attr_table_t *atable, hsize_t skip, hsize_t *l

/* Iterate over attribute messages */
H5_CHECKED_ASSIGN(u, size_t, skip, hsize_t);
for (; u < atable->nattrs && !ret_value; u++) {
for (; u < atable->num_attrs && !ret_value; u++) {
/* Check which type of callback to make */
switch (attr_op->op_type) {
case H5A_ATTR_OP_APP2: {
Expand Down Expand Up @@ -1906,19 +1900,20 @@ H5A__attr_release_table(H5A_attr_table_t *atable)
assert(atable);

/* Release attribute info, if any. */
if (atable->nattrs > 0) {
if (atable->num_attrs > 0) {
size_t u; /* Local index variable */

/* Free attribute message information */
for (u = 0; u < atable->nattrs; u++)
for (u = 0; u < atable->num_attrs; u++)
if (atable->attrs[u] && H5A__close(atable->attrs[u]) < 0)
HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute");

/* Release array */
atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, atable->attrs);
} /* end if */
else
assert(atable->attrs == NULL);

atable->attrs = (H5A_t **)H5FL_SEQ_FREE(H5A_t_ptr, atable->attrs);

done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5A__attr_release_table() */
Expand Down
5 changes: 3 additions & 2 deletions src/H5Apkg.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ typedef struct H5A_bt2_ud_ins_t {

/* Data structure to hold table of attributes for an object */
typedef struct {
size_t nattrs; /* # of attributes in table */
H5A_t **attrs; /* Pointer to array of attribute pointers */
size_t num_attrs; /* Curr. # of attributes in table */
size_t max_attrs; /* Max. # of attributes in table */
H5A_t **attrs; /* Pointer to array of attribute pointers */
} H5A_attr_table_t;

/*****************************/
Expand Down
7 changes: 7 additions & 0 deletions src/H5Dint.c
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,13 @@ H5D__update_oh_info(H5F_t *file, H5D_t *dset, hid_t dapl_id)
if (NULL == (oh = H5O_pin(oloc)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header");

/* Check for creating dataset with unusual datatype */
if (H5T_is_numeric_with_unusual_unused_bits(type) &&
!(H5O_has_chksum(oh) || (H5F_RFIC_FLAGS(file) & H5F_RFIC_UNUSUAL_NUM_UNUSED_NUMERIC_BITS)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL,
"creating dataset with unusual datatype, see documentation for "
"H5Pset_relax_file_integrity_checks for details.");

/* Write the dataspace header message */
if (H5S_append(file, oh, dset->shared->space) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update dataspace header message");
Expand Down
6 changes: 5 additions & 1 deletion src/H5Dio.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,12 @@ H5D__read(size_t count, H5D_dset_io_info_t *dset_info)
H5AC_tag(dset_info[i].dset->oloc.addr, &prev_tag);

/* Invoke correct "high level" I/O routine */
if ((*dset_info[i].io_ops.multi_read)(&io_info, &dset_info[i]) < 0)
if ((*dset_info[i].io_ops.multi_read)(&io_info, &dset_info[i]) < 0) {
/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);

HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data");
}

/* Reset metadata tagging */
H5AC_tag(prev_tag, NULL);
Expand Down
4 changes: 4 additions & 0 deletions src/H5Fint.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,8 @@ H5F_get_access_plist(H5F_t *f, bool app_ref)
0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID,
"can't set initial metadata cache resize config.");
if (H5P_set(new_plist, H5F_ACS_RFIC_FLAGS_NAME, &(f->shared->rfic_flags)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set RFIC flags value");

/* Prepare the driver property */
driver_prop.driver_id = f->shared->lf->driver_id;
Expand Down Expand Up @@ -1230,6 +1232,8 @@ H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5F
if (H5P_get(plist, H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME, &(f->shared->mdc_initCacheImageCfg)) <
0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config");
if (H5P_get(plist, H5F_ACS_RFIC_FLAGS_NAME, &(f->shared->rfic_flags)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get RFIC flags value");

/* Get the VFD values to cache */
f->shared->maxaddr = H5FD_get_maxaddr(lf);
Expand Down
1 change: 1 addition & 0 deletions src/H5Fpkg.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ struct H5F_shared_t {
bool use_file_locking; /* Whether or not to use file locking */
bool ignore_disabled_locks; /* Whether or not to ignore disabled file locking */
bool closing; /* File is in the process of being closed */
uint64_t rfic_flags; /* Relaxed file integrity check (RFIC) flags */

/* Cached VOL connector ID & info */
hid_t vol_id; /* ID of VOL connector for the container */
Expand Down
6 changes: 5 additions & 1 deletion src/H5Fprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ typedef struct H5F_t H5F_t;
#define H5F_VOL_CLS(F) ((F)->shared->vol_cls)
#define H5F_VOL_OBJ(F) ((F)->vol_obj)
#define H5F_USE_FILE_LOCKING(F) ((F)->shared->use_file_locking)
#define H5F_RFIC_FLAGS(F) ((F)->shared->rfic_flags)
#else /* H5F_MODULE */
#define H5F_LOW_BOUND(F) (H5F_get_low_bound(F))
#define H5F_HIGH_BOUND(F) (H5F_get_high_bound(F))
Expand Down Expand Up @@ -165,6 +166,7 @@ typedef struct H5F_t H5F_t;
#define H5F_VOL_CLS(F) (H5F_get_vol_cls(F))
#define H5F_VOL_OBJ(F) (H5F_get_vol_obj(F))
#define H5F_USE_FILE_LOCKING(F) (H5F_get_use_file_locking(F))
#define H5F_RFIC_FLAGS(F) (H5F_get_rfic_flags(F))
#endif /* H5F_MODULE */

/* Macros to encode/decode offset/length's for storing in the file */
Expand Down Expand Up @@ -282,6 +284,7 @@ typedef struct H5F_t H5F_t;
#define H5F_ACS_MPI_PARAMS_COMM_NAME "mpi_params_comm" /* the MPI communicator */
#define H5F_ACS_MPI_PARAMS_INFO_NAME "mpi_params_info" /* the MPI info struct */
#endif /* H5_HAVE_PARALLEL */
#define H5F_ACS_RFIC_FLAGS_NAME "rfic_flags" /* Relaxed file integrity check (RFIC) flags */

/* ======================== File Mount properties ====================*/
#define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */
Expand Down Expand Up @@ -525,7 +528,8 @@ H5_DLL bool H5F_get_min_dset_ohdr(const H5F_t *f);
H5_DLL herr_t H5F_set_min_dset_ohdr(H5F_t *f, bool minimize);
H5_DLL const H5VL_class_t *H5F_get_vol_cls(const H5F_t *f);
H5_DLL H5VL_object_t *H5F_get_vol_obj(const H5F_t *f);
H5_DLL bool H5F_get_file_locking(const H5F_t *f);
H5_DLL bool H5F_get_use_file_locking(const H5F_t *f);
H5_DLL uint64_t H5F_get_rfic_flags(const H5F_t *f);

/* Functions than retrieve values set/cached from the superblock/FCPL */
H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
Expand Down
Loading

0 comments on commit 136739b

Please sign in to comment.