[DTrace-devel] [PATCH] Support inet_ntoa() for addresses that are not DTrace pointers

eugene.loh at oracle.com eugene.loh at oracle.com
Thu Oct 13 18:58:36 UTC 2022


From: Eugene Loh <eugene.loh at oracle.com>

If the input argument to inet_ntoa() is not a DTrace pointer, the
BPF verifier cannot confirm it is safe.  So first copy the input
data to the BPF stack using the probe_read() helper function.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 bpf/inet_ntoa.S                             | 30 +++++++++++++--------
 test/unittest/funcs/tst.inet_ntoa_nonDPTR.d | 23 ++++++++++++++++
 test/unittest/funcs/tst.inet_ntoa_nonDPTR.r |  2 ++
 3 files changed, 44 insertions(+), 11 deletions(-)
 create mode 100644 test/unittest/funcs/tst.inet_ntoa_nonDPTR.d
 create mode 100644 test/unittest/funcs/tst.inet_ntoa_nonDPTR.r

diff --git a/bpf/inet_ntoa.S b/bpf/inet_ntoa.S
index ff36e226..a6676ff2 100644
--- a/bpf/inet_ntoa.S
+++ b/bpf/inet_ntoa.S
@@ -3,6 +3,8 @@
  * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
  */
 
+#define BPF_FUNC_probe_read	4
+
 	.text
 
 /*
@@ -115,25 +117,27 @@ dt_inet_ntoa_write_uint8:
  * void dt_inet_ntoa(uint8_t *src, char *dst) {
  *     uint64_t off, inp, len;
  *
- *     off = 0
+ *     bpf_probe_read(fp + -4, 4, src);
+ *
+ *     off = 0;
  *     len = STRSZ;
  *
- *     inp = src[0];
+ *     inp = *(fp + -4);
  *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
  *     if (off >= STRSZ) goto done:
  *     dst[off++] = ':';
  *
- *     inp = src[1];
+ *     inp = *(fp + -3);
  *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
  *     if (off >= STRSZ) goto done:
  *     dst[off++] = ':';
  *
- *     inp = src[2];
+ *     inp = *(fp + -2);
  *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
  *     if (off >= STRSZ) goto done:
  *     dst[off++] = ':';
  *
- *     inp = src[3];
+ *     inp = *(fp + -1);
  *     off = dt_inet_ntoa_write_uint8(inp, dst, off);
  *
  *     done:
@@ -148,17 +152,21 @@ dt_inet_ntoa:
 
 /* off cycles between %r3 (input arg to subroutine) and %r0 (its return) */
 #define INP %r1
-#define SRC %r6
 #define DST %r7
 #define LEN %r8
 
-	mov	SRC, %r1
 	mov	DST, %r2
 
+	mov	%r3, %r1
+	mov	%r2, 4
+	mov	%r1, %fp
+	add	%r1, -4
+	call	BPF_FUNC_probe_read
+
 	mov	%r3, 0
 	lddw	LEN, STRSZ
 
-	ldxb	INP, [SRC+0]
+	ldxb	INP, [%fp+-4]
 	mov	%r2, DST
 	call	dt_inet_ntoa_write_uint8
 	jge	%r0, LEN, .Ldone
@@ -167,7 +175,7 @@ dt_inet_ntoa:
 	add	%r0, DST
 	stb	[%r0+0], '.'
 
-	ldxb	INP, [SRC+1]
+	ldxb	INP, [%fp+-3]
 	mov	%r2, DST
 	call	dt_inet_ntoa_write_uint8
 	jge	%r0, LEN, .Ldone
@@ -176,7 +184,7 @@ dt_inet_ntoa:
 	add	%r0, DST
 	stb	[%r0+0], '.'
 
-	ldxb	INP, [SRC+2]
+	ldxb	INP, [%fp+-2]
 	mov	%r2, DST
 	call	dt_inet_ntoa_write_uint8
 	jge	%r0, LEN, .Ldone
@@ -185,7 +193,7 @@ dt_inet_ntoa:
 	add	%r0, DST
 	stb	[%r0+0], '.'
 
-	ldxb	INP, [SRC+3]
+	ldxb	INP, [%fp+-1]
 	mov	%r2, DST
 	call	dt_inet_ntoa_write_uint8
 
diff --git a/test/unittest/funcs/tst.inet_ntoa_nonDPTR.d b/test/unittest/funcs/tst.inet_ntoa_nonDPTR.d
new file mode 100644
index 00000000..9b51dad4
--- /dev/null
+++ b/test/unittest/funcs/tst.inet_ntoa_nonDPTR.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, 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 quiet
+#pragma D option destructive
+
+BEGIN
+{
+        system("printf '\xc0\xa8\x01\x17' > /dev/null 2>&1");
+}
+
+syscall::write:entry
+/ppid == $pid/
+{
+        printf("%s\n", inet_ntoa((void *)arg1));
+        exit(0);
+}
+
+ERROR { exit(1); }
diff --git a/test/unittest/funcs/tst.inet_ntoa_nonDPTR.r b/test/unittest/funcs/tst.inet_ntoa_nonDPTR.r
new file mode 100644
index 00000000..7257e488
--- /dev/null
+++ b/test/unittest/funcs/tst.inet_ntoa_nonDPTR.r
@@ -0,0 +1,2 @@
+192.168.1.23
+
-- 
2.18.4




More information about the DTrace-devel mailing list