uint16_t sa_size;
} sa_bulk_attr_t;
+/*
+ * The on-disk format of sa_hdr_phys_t limits SA lengths to 16-bit values.
+ */
+#define SA_ATTR_MAX_LEN UINT16_MAX
/*
* special macro for adding entries for bulk attr support
#define SA_ADD_BULK_ATTR(b, idx, attr, func, data, len) \
{ \
+ ASSERT3U(len, <=, SA_ATTR_MAX_LEN); \
b[idx].sa_attr = attr;\
b[idx].sa_data_func = func; \
b[idx].sa_data = data; \
int error;
sa_bulk_attr_t bulk;
+ VERIFY3U(buflen, <=, SA_ATTR_MAX_LEN);
+
bulk.sa_attr = attr;
bulk.sa_data = buf;
bulk.sa_length = buflen;
int error;
sa_bulk_attr_t bulk;
+ VERIFY3U(buflen, <=, SA_ATTR_MAX_LEN);
+
bulk.sa_attr = type;
bulk.sa_data_func = NULL;
bulk.sa_length = buflen;
int error;
sa_bulk_attr_t bulk;
+ VERIFY3U(buflen, <=, SA_ATTR_MAX_LEN);
+
bulk.sa_attr = attr;
bulk.sa_data = userdata;
bulk.sa_data_func = locator;
ASSERT(zp->z_is_sa);
error = nvlist_size(zp->z_xattr_cached, &size, NV_ENCODE_XDR);
+ if ((error == 0) && (size > SA_ATTR_MAX_LEN))
+ error = EFBIG;
if (error)
goto out;
if (error) {
dmu_tx_abort(tx);
} else {
- error = sa_update(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb),
- obj, size, tx);
- if (error)
- dmu_tx_abort(tx);
- else
- dmu_tx_commit(tx);
+ VERIFY0(sa_update(zp->z_sa_hdl, SA_ZPL_DXATTR(zsb),
+ obj, size, tx));
+ dmu_tx_commit(tx);
}
out_free:
zio_buf_free(obj, size);
error = -nvlist_add_byte_array(nvl, name,
(uchar_t *)value, size);
- if (error)
- return (error);
}
- /* Update the SA for additions, modifications, and removals. */
- if (!error)
+ /*
+ * Update the SA for additions, modifications, and removals. On
+ * error drop the inconsistent cached version of the nvlist, it
+ * will be reconstructed from the ARC when next accessed.
+ */
+ if (error == 0)
error = -zfs_sa_set_xattr(zp);
+ if (error) {
+ nvlist_free(nvl);
+ zp->z_xattr_cached = NULL;
+ }
+
ASSERT3S(error, <=, 0);
return (error);