[DTrace-devel] [PATCH 2/6] usdt_parser: harden DOF and note bounds checks

Alan Maguire alan.maguire at oracle.com
Sun Aug 30 10:57:22 UTC 2026


On 28/08/2026 20:09, Kris Van Hees via DTrace-devel wrote:
> Validate DOF section metadata before use, require ELF note strings to
> terminate within their declared payloads, and check parsed DOF record
> sizes before DTrace consumes them.  This keeps malformed parser input
> or stash data from driving out-of-bounds reads in either the parser or
> the host.
> 
> Orabug: 39352038
> Orabug: 39352051
> Orabug: 39351967
> CVE: CVE-2026-46831
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>

LGTM,

Reviewed-by: Alan Maguire <alan.maguire at oracle.com>

> ---
>  include/dtrace/pid.h          |   2 +-
>  libcommon/usdt_parser.h       |  10 ++-
>  libcommon/usdt_parser_dof.c   |  25 +++---
>  libcommon/usdt_parser_notes.c | 106 +++++++++++++++++++------
>  libdtrace/dt_pid.c            | 142 ++++++++++++++++++++++++++++++----
>  5 files changed, 233 insertions(+), 52 deletions(-)
> 
> diff --git a/include/dtrace/pid.h b/include/dtrace/pid.h
> index 4a239b07..88f9366c 100644
> --- a/include/dtrace/pid.h
> +++ b/include/dtrace/pid.h
> @@ -45,7 +45,7 @@ typedef struct pid_probespec {
>  	size_t pps_nargvlen;			/* (high estimate of) length of array */
>  	char *pps_xargv;			/* array of xlated args */
>  	size_t pps_xargvlen;			/* (high estimate of) length of array */
> -	int8_t *pps_argmap;			/* mapped arg indexes */
> +	uint8_t *pps_argmap;			/* mapped arg indexes */
>  	char *pps_sargv;			/* list of arg sources */
>  	int pps_flags;				/* flags */
>  
> diff --git a/libcommon/usdt_parser.h b/libcommon/usdt_parser.h
> index b11207d1..99fc3033 100644
> --- a/libcommon/usdt_parser.h
> +++ b/libcommon/usdt_parser.h
> @@ -136,7 +136,7 @@ typedef struct dof_parsed {
>  			 * Mapping from native arg index to xlated arg index.
>  			 * xargc in length.
>  			 */
> -			int8_t argmap[1];
> +			uint8_t argmap[1];
>  		} argmap;
>  
>  		struct dpi_tracepoint_info {
> @@ -171,6 +171,14 @@ typedef struct dof_parsed {
>  	};
>  } dof_parsed_t;
>  
> +#define DIT_PROVIDER_HEADSZ	offsetof(dof_parsed_t, provider.name)
> +#define DIT_PROBE_HEADSZ	offsetof(dof_parsed_t, probe.name)
> +#define DIT_TRACEPOINT_HEADSZ	offsetof(dof_parsed_t, tracepoint.args)
> +#define DIT_ERR_HEADSZ		offsetof(dof_parsed_t, err.err)
> +#define DIT_ARGS_NATIVE_HEADSZ	offsetof(dof_parsed_t, nargs.args)
> +#define DIT_ARGS_XLAT_HEADSZ	offsetof(dof_parsed_t, xargs.args)
> +#define DIT_ARGS_MAP_HEADSZ	offsetof(dof_parsed_t, argmap.argmap)
> +
>  /*
>   * Host-side: in usdt_parser_host.c.
>   * The host is the non-jailed process that talks to the jailed parser.
> diff --git a/libcommon/usdt_parser_dof.c b/libcommon/usdt_parser_dof.c
> index bc8e185a..e2166985 100644
> --- a/libcommon/usdt_parser_dof.c
> +++ b/libcommon/usdt_parser_dof.c
> @@ -275,8 +275,8 @@ dof_slurp(int out, dof_hdr_t *dof, uint64_t ubase)
>  		return -1;
>  	}
>  
> -	if (dof->dofh_secsize == 0) {
> -		usdt_error(out, EINVAL, "zero section header size");
> +	if (dof->dofh_secsize != sizeof(dof_sec_t)) {
> +		usdt_error(out, EINVAL, "incorrect section header size");
>  		return -1;
>  	}
>  
> @@ -462,7 +462,7 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
>  		return -1;
>  	}
>  
> -	if (prb_sec->dofs_entsize == 0 ||
> +	if (prb_sec->dofs_entsize < sizeof(dof_probe_t) ||
>  	    prb_sec->dofs_entsize > prb_sec->dofs_size) {
>  		usdt_error(out, EINVAL, "invalid entry size %x, max %lx",
>  			   prb_sec->dofs_entsize, prb_sec->dofs_size);
> @@ -615,11 +615,11 @@ validate_provider(int out, dof_hdr_t *dof, dof_sec_t *sec)
>  		typeidx = prb->dofpr_xargv;
>  		typestr = strtab + prb->dofpr_xargv;
>  		for (k = 0; k < prb->dofpr_xargc; k++) {
> -			if (arg[prb->dofpr_argidx + k] > prb->dofpr_nargc) {
> +			if (arg[prb->dofpr_argidx + k] >= prb->dofpr_nargc) {
>  				usdt_error(out, EINVAL, "bad native argument index "
>  					   "for arg %i: %i (max %i)", k,
>  					   arg[prb->dofpr_argidx + k],
> -					   prb->dofpr_nargc);
> +					   prb->dofpr_nargc - 1);
>  				return -1;
>  			}
>  
> @@ -748,7 +748,7 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
>  	 * flags.
>  	 */
>  
> -	msg_size = offsetof(dof_parsed_t, probe.name) +
> +	msg_size = DIT_PROBE_HEADSZ +
>  		   strlen(dhpb->dthpb_mod) + 1 +
>  		   strlen(dhpb->dthpb_func) + 1 +
>  		   strlen(dhpb->dthpb_name) + 1;
> @@ -786,7 +786,7 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
>  		size_t	nargs_size;
>  
>  		nargs_size = strings_len(dhpb->dthpb_ntypes, dhpb->dthpb_nargc);
> -		msg_size = offsetof(dof_parsed_t, nargs.args) + nargs_size;
> +		msg_size = DIT_ARGS_NATIVE_HEADSZ + nargs_size;
>  
>  		msg = malloc(msg_size);
>  		if (!msg)
> @@ -808,8 +808,7 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
>  
>  			xargs_size = strings_len(dhpb->dthpb_xtypes,
>  						 dhpb->dthpb_xargc);
> -			msg_size = offsetof(dof_parsed_t, xargs.args) +
> -				   xargs_size;
> +			msg_size = DIT_ARGS_XLAT_HEADSZ + xargs_size;
>  
>  			msg = malloc(msg_size);
>  			if (!msg)
> @@ -826,9 +825,8 @@ emit_probe(int out, dtrace_helper_probedesc_t *dhpb)
>  
>  			/* Then the mapping table. */
>  
> -			map_size = dhpb->dthpb_xargc * sizeof(int8_t);
> -			msg_size = offsetof(dof_parsed_t, argmap.argmap) +
> -				   map_size;
> +			map_size = dhpb->dthpb_xargc * sizeof(uint8_t);
> +			msg_size = DIT_ARGS_MAP_HEADSZ + map_size;
>  
>  			msg = malloc(msg_size);
>  			if (!msg)
> @@ -922,8 +920,7 @@ emit_provider(int out, dof_helper_t *dhp,
>  	}
>  
>  	dhpb.dthpb_prov = strtab + prov->dofpv_name;
> -	provider_msg_size = offsetof(dof_parsed_t, provider.name) +
> -	    strlen(dhpb.dthpb_prov) + 1;
> +	provider_msg_size = DIT_PROVIDER_HEADSZ + strlen(dhpb.dthpb_prov) + 1;
>  
>  	provider_msg = malloc(provider_msg_size);
>  	if (!provider_msg) {
> diff --git a/libcommon/usdt_parser_notes.c b/libcommon/usdt_parser_notes.c
> index c98c9fb0..7742024e 100644
> --- a/libcommon/usdt_parser_notes.c
> +++ b/libcommon/usdt_parser_notes.c
> @@ -73,6 +73,10 @@ get_note(int out, usdt_data_t *data, ssize_t off, usdt_note_t *note)
>  	}
>  
>  	note->name = (char *)data->buf + off;
> +	if (memchr(note->name, '\0', sz) == NULL) {
> +		usdt_error(out, EINVAL, "Unterminated name");
> +		return -1;
> +	}
>  	off += ALIGN(sz, 4);
>  
>  	dt_dbg_usdt("ELF note '%s' (%d bytes)\n",
> @@ -272,6 +276,25 @@ static dt_htab_ops_t pmap_htab_ops = {
>          .next = (htab_next_fn)prb_next
>  };
>  
> +/*
> + * Return the length of string 'str' (excluding the terminating NUL, if it
> + * terminates before the supplied 'end', and -1 otherwise.
> + */
> +static ssize_t
> +cstrlen(const char *str, const char *end)
> +{
> +	const char	*p;
> +
> +	if (str >= end)
> +		return -1;
> +
> +	p = memchr(str, '\0', end - str);
> +	if (p == NULL)
> +		return -1;
> +
> +	return p - str;
> +}
> +
>  /*
>   * Return the cummulative string length of 'cnt' consecutive 0-terminated
>   * strings.  If skip > 0, it indicates how many extra bytes are to be skipped
> @@ -284,10 +307,12 @@ strarray_size(uint8_t cnt, const char *str, const char *end, size_t skip)
>  	const char	*p = str;
>  
>  	while (cnt-- > 0) {
> -		if (p >= end)
> +		ssize_t	len = cstrlen(p, end);
> +
> +		if (len < 0 || skip > (size_t)(end - (p + len + 1)))
>  			return -1;
>  
> -		p += strlen(p) + 1 + skip;
> +		p += len + 1 + skip;
>  	}
>  
>  	return p - str;
> @@ -298,14 +323,21 @@ parse_prov_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  		usdt_note_t *note)
>  {
>  	const char	*p = note->desc;
> +	const char	*end = p + note->hdr->n_descsz;
>  	dt_provider_t	prvt, *pvp;
>  	const uint32_t	*vals;
>  	uint32_t	probec;
> +	ssize_t		len;
>  	int		i;
>  
> +	len = cstrlen(p, end);
> +	if (len == -1) {
> +		usdt_error(out, EINVAL, "Unterminated provider name");
> +		return -1;
> +	}
>  	prvt.name = p;
> -	p += ALIGN(strlen(p) + 1, 4);
> -	if (p + 6 * sizeof(uint32_t) - note->desc > note->hdr->n_descsz) {
> +	p += ALIGN(len + 1, 4);
> +	if (p + 6 * sizeof(uint32_t) > end) {
>  		usdt_error(out, EINVAL, "Incomplete note data");
>  		return -1;
>  	}
> @@ -342,13 +374,18 @@ parse_prov_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  		ssize_t		len;
>  
>  		p = (const char *)ALIGN((uintptr_t)p, 4);
> +		len = cstrlen(p, end);
> +		if (len == -1) {
> +			usdt_error(out, EINVAL, "Unterminated probe name");
> +			return -1;
> +		}
>  		prbt.prv = pvp->name;
>  		prbt.mod = dhp->dofhp_mod;
>  		prbt.fun = NULL;
>  		prbt.prb = p;
>  		prbt.off = 0;
> -		p += strlen(p) + 1;
> -		if (p + 2 * sizeof(uint8_t) - note->desc > note->hdr->n_descsz) {
> +		p += len + 1;
> +		if (p + 2 * sizeof(uint8_t) > end) {
>  			usdt_error(out, EINVAL, "Incomplete note data");
>  			return -1;
>  		}
> @@ -374,8 +411,7 @@ parse_prov_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  		prp->ntp = 0;
>  		prp->is_enabled = 0;
>  		prp->nargc = argc = *(uint8_t *)p++;
> -		len = strarray_size(argc, p, note->desc + note->hdr->n_descsz,
> -				    0);
> +		len = strarray_size(argc, p, end, 0);
>  		if (len == -1) {
>  			usdt_error(out, EINVAL, "Incomplete note data");
>  			return -1;
> @@ -384,7 +420,7 @@ parse_prov_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  		prp->nargs = p;
>  
>  		p += len;
> -		if (p - note->desc > note->hdr->n_descsz) {
> +		if (p >= end) {
>  			usdt_error(out, EINVAL, "Incomplete note data");
>  			return -1;
>  		}
> @@ -411,6 +447,11 @@ parse_prov_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  				q = stpcpy(q, p);
>  				q++;
>  				p += strlen(p) + 1;
> +				if (*(uint8_t *)p >= prp->nargc) {
> +					usdt_error(out, EINVAL,
> +						   "bad native argument index");
> +					return -1;
> +				}
>  				prp->xmap[j] = *p;
>  				p++;
>  			}
> @@ -432,7 +473,9 @@ parse_usdt_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  		usdt_note_t *note)
>  {
>  	const char	*p = note->desc;
> +	const char	*end = p + note->hdr->n_descsz;
>  	uint64_t	off, fno;
> +	ssize_t		len;
>  	dt_probe_t	prbt, *prp;
>  
>  	data = data->next;
> @@ -441,7 +484,7 @@ parse_usdt_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  		return -1;
>  	}
>  
> -	if (p + 2 * sizeof(uint64_t) - note->desc > note->hdr->n_descsz) {
> +	if (p + 2 * sizeof(uint64_t) >= end) {
>  		usdt_error(out, EINVAL, "Incomplete note data");
>  		return -1;
>  	}
> @@ -450,10 +493,15 @@ parse_usdt_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  	p += sizeof(uint64_t);
>  	fno = *(uint64_t *)p;
>  	p += sizeof(uint64_t);
> +	len = cstrlen(p, end);
> +	if (len == -1) {
> +		usdt_error(out, EINVAL, "Unterminated provider name");
> +		return -1;
> +	}
>  
>  	prbt.prv = p;
> -	p += strlen(p) + 1;
> -	if (p - note->desc > note->hdr->n_descsz) {
> +	p += len + 1;
> +	if (p >= end) {
>  		usdt_error(out, EINVAL, "Incomplete note data");
>  		return -1;
>  	}
> @@ -463,9 +511,18 @@ parse_usdt_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  		return -1;
>  	}
>  	prbt.fun = (char *)data->buf + fno;
> +	if (cstrlen(prbt.fun, (char *)data->buf + data->size) == -1) {
> +		usdt_error(out, EINVAL, "Unterminated function name");
> +		return -1;
> +	}
> +	len = cstrlen(p, end);
> +	if (len == -1) {
> +		usdt_error(out, EINVAL, "Unterminated probe name");
> +		return -1;
> +	}
>  	prbt.prb = p;
> -	p += strlen(p) + 1;
> -	if (p - note->desc > note->hdr->n_descsz) {
> +	p += len + 1;
> +	if (p >= end) {
>  		usdt_error(out, EINVAL, "Incomplete note data");
>  		return -1;
>  	}
> @@ -510,9 +567,14 @@ parse_usdt_note(int out, dof_helper_t *dhp, usdt_data_t *data,
>  	prp->is_enabled = (note->hdr->n_type == _USDT_EN_NOTE_TYPE ? 1 : 0);
>  	prp->ntp = 0;
>  	prp->sargc = *p++;
> +	len = cstrlen(p, end);
> +	if (len == -1) {
> +		usdt_error(out, EINVAL, "Unterminated argument string");
> +		return -1;
> +	}
>  	prp->sargs = p;
> -	p += strlen(p) + 1;
> -	if (p - note->desc > note->hdr->n_descsz) {
> +	p += len + 1;
> +	if (p > end) {
>  		usdt_error(out, EINVAL, "Incomplete note data");
>  		return -1;
>  	}
> @@ -537,22 +599,22 @@ alloc_msg(int out, dof_parsed_info_t type, size_t len)
>  
>  	switch (type) {
>  	case DIT_PROVIDER:
> -		len += offsetof(dof_parsed_t, provider.name);
> +		len += DIT_PROVIDER_HEADSZ;
>  		break;
>  	case DIT_PROBE:
> -		len += offsetof(dof_parsed_t, probe.name);
> +		len += DIT_PROBE_HEADSZ;
>  		break;
>  	case DIT_ARGS_NATIVE:
> -		len += offsetof(dof_parsed_t, nargs.args);
> +		len += DIT_ARGS_NATIVE_HEADSZ;
>  		break;
>  	case DIT_ARGS_XLAT:
> -		len += offsetof(dof_parsed_t, xargs.args);
> +		len += DIT_ARGS_XLAT_HEADSZ;
>  		break;
>  	case DIT_ARGS_MAP:
> -		len += offsetof(dof_parsed_t, argmap.argmap);
> +		len += DIT_ARGS_MAP_HEADSZ;
>  		break;
>  	case DIT_TRACEPOINT:
> -		len += offsetof(dof_parsed_t, tracepoint.args);
> +		len += DIT_TRACEPOINT_HEADSZ;
>  		break;
>  	default:
>  		usdt_error(out, EINVAL, "Unknown dof_parsed_t type: %d", type);
> diff --git a/libdtrace/dt_pid.c b/libdtrace/dt_pid.c
> index 7e6e5d90..e20bc82b 100644
> --- a/libdtrace/dt_pid.c
> +++ b/libdtrace/dt_pid.c
> @@ -782,25 +782,93 @@ err:
>  }
>  
>  /*
> - * A quick check that a parsed DOF record read hasn't incurred a buffer overrun
> - * and is of the type expected.
> + * Ensure that the buffer has enough data to read the record of the expected
> + * type.  Ensure that all records have at least 1 byte of payload data.
>   */
>  static int
>  validate_dof_record(const char *path, const dof_parsed_t *parsed,
> -		    dof_parsed_info_t expected, size_t buf_size,
> +		    dof_parsed_info_t type, size_t headsz, size_t buf_size,
>  		    size_t seen_size)
>  {
> -	if (buf_size < seen_size) {
> +	size_t	data_size;
> +
> +	/* If we have read more than there is, we must always fail. */
> +	if (buf_size < seen_size)
> +		data_size = 0;
> +	else
> +		data_size = buf_size - seen_size;
> +
> +	if (data_size < headsz || data_size < parsed->size) {
>  		dt_dprintf("DOF too small when adding probes (seen %zi bytes)\n",
>  			   seen_size);
>  		return 0;
>  	}
>  
> -	if (parsed->type != expected) {
> +	if (parsed->size < headsz + 1) {
> +		dt_dprintf("DOF record too small: expected %zi, got %zi\n",
> +			   headsz, parsed->size);
> +		return 0;
> +	}
> +
> +	if (parsed->type != type) {
>  		dt_dprintf("%s format invalid: expected %i, got %i\n", path,
> -			   expected, parsed->type);
> +			   type, parsed->type);
>  		return 0;
>  	}
> +
> +	return 1;
> +}
> +
> +/*
> + * Validate a payload containing CNT consecutive NUL-terminated strings.
> + */
> +static int
> +validate_string_payload(const char *path, const char *payload,
> +			size_t payload_size, size_t cnt)
> +{
> +	const char	*p = payload;
> +	const char	*end = payload + payload_size;
> +	size_t		i;
> +
> +	for (i = 0; i < cnt; i++) {
> +		const char	*nul;
> +
> +		if (p >= end) {
> +			dt_dprintf("%s string payload too small\n", path);
> +			return 0;
> +		}
> +
> +		nul = memchr(p, '\0', end - p);
> +		if (nul == NULL) {
> +			dt_dprintf("%s string payload unterminated\n", path);
> +			return 0;
> +		}
> +
> +		p = nul + 1;
> +	}
> +
> +	return 1;
> +}
> +
> +static int
> +validate_argmap_payload(const char *path, const uint8_t *argmap,
> +			size_t payload_size, size_t nargc, size_t xargc)
> +{
> +	size_t	i;
> +
> +	if (payload_size < xargc * sizeof(uint8_t)) {
> +		dt_dprintf("%s argmap payload too small\n", path);
> +		return 0;
> +	}
> +
> +	for (i = 0; i < xargc; i++) {
> +		if (argmap[i] >= nargc) {
> +			dt_dprintf("%s argmap entry %zi invalid: %u >= %zi\n",
> +				   path, i, argmap[i], nargc);
> +			return 0;
> +		}
> +	}
> +
>  	return 1;
>  }
>  
> @@ -908,13 +976,13 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  		char *dof_buf = NULL, *p;
>  		struct stat s;
>  		char *path;
> -		size_t dof_buf_size, seen_size = 0;
> +		size_t dof_buf_size, seen_size = 0, payload_size;
>  		uint64_t *dof_version;
>  		char *prv, *mod, *fun, *prb;
>  		dof_parsed_t *provider, *probe;
>  		ssize_t nargvlen = 0, xargvlen = 0;
>  		char *nargv = NULL, *xargv = NULL;
> -		int8_t *argmap = NULL;
> +		uint8_t *argmap = NULL;
>  
>  		/*
>  		 * Regular files only: in particular, skip . and ..,
> @@ -929,7 +997,7 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  			goto per_mapping_err;
>  
>  		dof_buf = read_file(path, &dof_buf_size);
> -		if (dof_buf == NULL)
> +		if (dof_buf == NULL || dof_buf_size < sizeof(uint64_t))
>  			goto per_mapping_err;
>  		dof_version = (uint64_t *) dof_buf;
>  		if (*dof_version != DOF_PARSED_VERSION) {
> @@ -945,27 +1013,50 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  		 * probe.
>  		 */
>  		provider = (dof_parsed_t *) p;
> -		if (!validate_dof_record(path, provider, DIT_PROVIDER, dof_buf_size,
> +		if (!validate_dof_record(path, provider, DIT_PROVIDER,
> +					 DIT_PROVIDER_HEADSZ, dof_buf_size,
>  					 seen_size))
>  			goto parse_err;
>  
> +		/*
> +		 * Ensure that a validly terminated string follows the record
> +		 * header.
> +		 */
>  		prv = provider->provider.name;
> +		payload_size = provider->size - DIT_PROVIDER_HEADSZ;
> +		if (memchr(prv, '\0', payload_size) == NULL)
> +			goto parse_err;
>  
>  		p += provider->size;
>  		seen_size += provider->size;
>  
>  		probe = (dof_parsed_t *) p;
> -		if (!validate_dof_record(path, probe, DIT_PROBE, dof_buf_size,
> +		if (!validate_dof_record(path, probe, DIT_PROBE,
> +					 DIT_PROBE_HEADSZ, dof_buf_size,
>  					 seen_size))
>  			goto parse_err;
>  
>  		mod = probe->probe.name;
> +		payload_size = probe->size - DIT_PROBE_HEADSZ;
> +		if (memchr(mod, '\0', payload_size) == NULL)
> +			goto parse_err;
> +
>  		fun = mod + strlen(mod) + 1;
> +		payload_size -= strlen(mod) + 1;
> +		if (memchr(fun, '\0', payload_size) == NULL)
> +			goto parse_err;
>  		prb = fun + strlen(fun) + 1;
> +		payload_size -= strlen(fun) + 1;
> +		if (memchr(prb, '\0', payload_size) == NULL)
> +			goto parse_err;
>  
>  		p += probe->size;
>  		seen_size += probe->size;
>  
> +		if (probe->probe.nargc > UINT8_MAX ||
> +		    probe->probe.xargc > UINT8_MAX)
> +			goto parse_err;
> +
>  		/*
>  		 * Assume the order given in dof_parser.h, for simplicity.
>  		 */
> @@ -973,11 +1064,16 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  			dof_parsed_t *args = (dof_parsed_t *) p;
>  
>  			if (!validate_dof_record(path, args, DIT_ARGS_NATIVE,
> +						 DIT_ARGS_NATIVE_HEADSZ,
>  						 dof_buf_size, seen_size))
>  				goto parse_err;
>  
>  			nargv = args->nargs.args;
> -			nargvlen = args->size - offsetof(dof_parsed_t, nargs.args);
> +			payload_size = args->size - DIT_ARGS_NATIVE_HEADSZ;
> +			if (!validate_string_payload(path, nargv, payload_size,
> +						     probe->probe.nargc))
> +				goto parse_err;
> +			nargvlen = payload_size;
>  			assert(nargvlen >= 0);
>  
>  			p += args->size;
> @@ -987,11 +1083,16 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  			dof_parsed_t *args = (dof_parsed_t *) p;
>  
>  			if (!validate_dof_record(path, args, DIT_ARGS_XLAT,
> +						 DIT_ARGS_XLAT_HEADSZ,
>  						 dof_buf_size, seen_size))
>  				goto parse_err;
>  
>  			xargv = args->xargs.args;
> -			xargvlen = args->size - offsetof(dof_parsed_t, xargs.args);
> +			payload_size = args->size - DIT_ARGS_XLAT_HEADSZ;
> +			if (!validate_string_payload(path, xargv, payload_size,
> +						     probe->probe.xargc))
> +				goto parse_err;
> +			xargvlen = payload_size;
>  			assert(xargvlen >= 0);
>  
>  			p += args->size;
> @@ -999,10 +1100,16 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  			args = (dof_parsed_t *) p;
>  
>  			if (!validate_dof_record(path, args, DIT_ARGS_MAP,
> +						 DIT_ARGS_MAP_HEADSZ,
>  						 dof_buf_size, seen_size))
>  				goto parse_err;
>  
>  			argmap = args->argmap.argmap;
> +			payload_size = args->size - DIT_ARGS_MAP_HEADSZ;
> +			if (!validate_argmap_payload(path, argmap, payload_size,
> +						     probe->probe.nargc,
> +						     probe->probe.xargc))
> +				goto parse_err;
>  
>  			p += args->size;
>  			seen_size += args->size;
> @@ -1017,6 +1124,7 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  			const prmap_t *pmp;
>  
>  			if (!validate_dof_record(path, tp, DIT_TRACEPOINT,
> +						 DIT_TRACEPOINT_HEADSZ,
>  						 dof_buf_size, seen_size))
>  				goto parse_err;
>  
> @@ -1073,9 +1181,15 @@ dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, pid_t pid, dt_proc_t *dpr,
>  			if (argmap)
>  				psp.pps_argmap = argmap;
>  
> -			if (tp->tracepoint.args[0] != 0)
> +			if (tp->tracepoint.args[0] != 0) {
>  				psp.pps_sargv = tp->tracepoint.args;
>  
> +				payload_size = tp->size - DIT_TRACEPOINT_HEADSZ;
> +				if (memchr(psp.pps_sargv, '\0',
> +					   payload_size) == NULL)
> +					goto parse_err;
> +			}
> +
>  			dt_dprintf("providing %s:%s:%s:%s for pid %d @ %lx\n",
>  				   psp.pps_prv, psp.pps_mod, psp.pps_fun,
>  				   psp.pps_prb, psp.pps_pid, psp.pps_off);
> -- 
> 2.52.0
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel
> 




More information about the DTrace-devel mailing list