Description
isdaoscontainer() passes negative getxattr/listxattr return directly to calloc → calloc(1, SIZE_MAX). This is picked up by AddressSanitizer causing a false failure:
=================================================================
==1846880==ERROR: AddressSanitizer: requested allocation size 0xffffffffffffffff (0x800 after adjustments for alignment, red zones etc.) exceeds maximum supported size of 0x10000000000 (thread T0)
#0 0x7f8f4475ce47 in __interceptor_calloc /.../libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f8f3e4d4e7e in isdaoscontainer /.../src/libdispatch/dinfermodel.c:1633
#2 0x7f8f3e4d4e7e in NC_infermodel /.../src/libdispatch/dinfermodel.c:1008
Component: libdispatch/dinfermodel.c (path/model inference on open)
Version: netCDF-C main (present since isdaoscontainer was added; not in 4.9.2)
Environment: Linux, HDF5 ≥ 1.12, HAVE_SYS_XATTR_H defined, files on a filesystem that carries extended attributes (e.g. Lustre). Symptom is fatal only under AddressSanitizer, but the bad allocation request happens on every affected open.
Description
isdaoscontainer() is called by NC_infermodel() on every nc_open()/nc_create()-read of an HDF5-accessible file. It walks the file's extended attributes and casts the ssize_t return of GETXATTR/LISTXATTR straight to size_t before calling calloc:
ssize_t xlen;
xlen = LISTXATTR(path, NULL, 0);
if (xlen > 0) {
...
for (; p < endp; p += (strlen(p) + 1)) {
if (strstr(p, ".daos") != NULL) { rc = 1; break; }
xlen = GETXATTR(path, p, NULL, 0); /* can return -1 */
if ((xvalue = (char*)calloc(1, (size_t)xlen)) == NULL) /* (size_t)(-1) == SIZE_MAX */
{ stat = NC_ENOMEM; goto done; }
(void)GETXATTR(path, p, xvalue, xlen);
...
If getxattr(path, name, NULL, 0) returns -1 (e.g. EPERM/ENODATA for a trusted.*/system.* attribute as a non-privileged user, or a TOCTOU removal between listxattr and getxattr), (size_t)xlen becomes 0xffffffffffffffff and is passed to calloc.
Normally calloc just returns NULL and the function bails via the NC_ENOMEM branch, so it's silently benign. But under AddressSanitizer the oversized request aborts the process before calloc can return:
ERROR: AddressSanitizer: requested allocation size 0xffffffffffffffff
#0 __interceptor_calloc
#1 isdaoscontainer libdispatch/dinfermodel.c
#2 NC_infermodel
#3 NC_open
#4 nc_open
Reproducer (illustrates the cast bug in isolation)
#include <stdlib.h>
#include <sys/types.h>
int main(void) {
ssize_t xlen = -1; /* what getxattr returns on error */
void *p = calloc(1, (size_t)xlen); /* requests SIZE_MAX bytes */
return p ? 0 : 1;
}
cc -fsanitize=address repro.c && ./a.out
# => AddressSanitizer: requested allocation size 0xffffffffffffffff ... ABORTING
In situ, it reproduces by opening any HDF5/netCDF-4 file that carries an extended attribute whose getxattr(..., NULL, 0) returns -1, with the reader built -fsanitize=address.
Expected vs actual
- Expected: an attribute whose size cannot be queried is skipped; open proceeds.
- Actual: a
calloc(1, SIZE_MAX) request that ASAN treats as fatal (and that is a latent no-op-but-wrong allocation otherwise).
Suggested fix
Guard against the negative return before allocating (both calloc sites):
xlen = GETXATTR(path, p, NULL, 0);
if (xlen < 0) continue; /* cannot read this attr's value; skip it */
if (xlen == 0) continue; /* nothing to compare */
if ((xvalue = (char*)calloc(1, (size_t)xlen)) == NULL)
{ stat = NC_ENOMEM; goto done; }
and likewise treat a LISTXATTR result of 0 (no attributes) as "not a DAOS container" without allocating.
Written by enterprise github copilot AI
Description
isdaoscontainer()passes negativegetxattr/listxattrreturn directly tocalloc→calloc(1, SIZE_MAX). This is picked up by AddressSanitizer causing a false failure:Component:
libdispatch/dinfermodel.c(path/model inference on open)Version: netCDF-C main (present since
isdaoscontainerwas added; not in 4.9.2)Environment: Linux, HDF5 ≥ 1.12,
HAVE_SYS_XATTR_Hdefined, files on a filesystem that carries extended attributes (e.g. Lustre). Symptom is fatal only under AddressSanitizer, but the bad allocation request happens on every affected open.Description
isdaoscontainer()is called byNC_infermodel()on everync_open()/nc_create()-read of an HDF5-accessible file. It walks the file's extended attributes and casts thessize_treturn ofGETXATTR/LISTXATTRstraight tosize_tbefore callingcalloc:If
getxattr(path, name, NULL, 0)returns-1(e.g.EPERM/ENODATAfor atrusted.*/system.*attribute as a non-privileged user, or a TOCTOU removal betweenlistxattrandgetxattr),(size_t)xlenbecomes0xffffffffffffffffand is passed tocalloc.Normally
callocjust returnsNULLand the function bails via theNC_ENOMEMbranch, so it's silently benign. But under AddressSanitizer the oversized request aborts the process beforecalloccan return:Reproducer (illustrates the cast bug in isolation)
In situ, it reproduces by opening any HDF5/netCDF-4 file that carries an extended attribute whose
getxattr(..., NULL, 0)returns-1, with the reader built-fsanitize=address.Expected vs actual
calloc(1, SIZE_MAX)request that ASAN treats as fatal (and that is a latent no-op-but-wrong allocation otherwise).Suggested fix
Guard against the negative return before allocating (both
callocsites):and likewise treat a
LISTXATTRresult of0(no attributes) as "not a DAOS container" without allocating.Written by enterprise github copilot AI