[DTrace-devel] [PATCH v2] Ensure string constants that are too long are truncated correctly

Kris Van Hees kris.van.hees at oracle.com
Sat Nov 20 05:28:51 UTC 2021


The string table can contain strings that are longer than the maximum
string size for the program being compiled.  They need to be truncated
before they are used to ensure that string operations work correctly.

Since string constants can be used verbatim or as values of built-in
variables, it is easiest to just pre-process the string table before it
is loaded into the 'strtab' BPF map.  Every string that is longer than
the maximum string size has its length prefix set to the maximum string
size and the string itself is truncated to that length.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_bpf.c                           | 27 ++++++++++++++++----
 test/unittest/codegen/tst.str_const_length.d | 21 +++++++++++++++
 test/unittest/codegen/tst.str_const_length.r |  4 +++
 3 files changed, 47 insertions(+), 5 deletions(-)
 create mode 100644 test/unittest/codegen/tst.str_const_length.d
 create mode 100644 test/unittest/codegen/tst.str_const_length.r

diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index e0134a93..fc1e5e8f 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -240,6 +240,9 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 	int		stabsz, gvarsz, lvarsz, tvarc, aggsz, memsz;
 	int		ci_mapfd, st_mapfd, pr_mapfd;
 	uint32_t	key = 0;
+	size_t		strsize = dtp->dt_options[DTRACEOPT_STRSIZE];
+	uint8_t		*buf, *end;
+	char		*strtab;
 
 	/* If we already created the global maps, return success. */
 	if (dt_gmap_done)
@@ -325,13 +328,27 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 	 * value that is used to store the strtab.
 	 */
 	dtp->dt_strlen = dt_strtab_size(dtp->dt_ccstab);
-	stabsz = dtp->dt_strlen + dtp->dt_options[DTRACEOPT_STRSIZE];
-	dtp->dt_strtab = dt_zalloc(dtp, stabsz);
-	if (dtp->dt_strtab == NULL)
+	stabsz = dtp->dt_strlen + strsize;
+	strtab = dt_zalloc(dtp, stabsz);
+	if (strtab == NULL)
 		return dt_set_errno(dtp, EDT_NOMEM);
 
 	dt_strtab_write(dtp->dt_ccstab, (dt_strtab_write_f *)dt_strtab_copystr,
-			dtp->dt_strtab);
+			strtab);
+
+	/* Loop over the string table and truncate strings that are too long. */
+	buf = (uint8_t *)strtab;
+	end = buf + dtp->dt_strlen;
+	while (buf < end) {
+		uint_t	len = (buf[0] << 8) | buf[1];
+
+		if (len > strsize) {
+			buf[0] = strsize >> 8;
+			buf[1] = strsize & 0xff;
+			buf[2 + strsize] = '\0';
+		}
+		buf += 2 + len + 1;
+	}
 
 	st_mapfd = create_gmap(dtp, "strtab", BPF_MAP_TYPE_ARRAY,
 			       sizeof(uint32_t), stabsz, 1);
@@ -363,7 +380,7 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp)
 	dt_bpf_map_update(ci_mapfd, &key, dtp->dt_conf.cpus);
 
 	/* Populate the 'strtab' map. */
-	dt_bpf_map_update(st_mapfd, &key, dtp->dt_strtab);
+	dt_bpf_map_update(st_mapfd, &key, strtab);
 
 	/* Populate the 'probes' map. */
 	populate_probes_map(dtp, pr_mapfd);
diff --git a/test/unittest/codegen/tst.str_const_length.d b/test/unittest/codegen/tst.str_const_length.d
new file mode 100644
index 00000000..1c58ba13
--- /dev/null
+++ b/test/unittest/codegen/tst.str_const_length.d
@@ -0,0 +1,21 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+#pragma D option rawbytes
+#pragma D option strsize=5
+#pragma D option quiet
+
+BEGIN
+{
+	trace("abcdefgh");
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/codegen/tst.str_const_length.r b/test/unittest/codegen/tst.str_const_length.r
new file mode 100644
index 00000000..b6991a71
--- /dev/null
+++ b/test/unittest/codegen/tst.str_const_length.r
@@ -0,0 +1,4 @@
+
+             0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  0123456789abcdef
+         0: 00 05 61 62 63 64 65 00                          ..abcde.
+
-- 
2.33.0




More information about the DTrace-devel mailing list