Skip to content

Commit

Permalink
Support inet_ntoa() for addresses that are not DTrace pointers
Browse files Browse the repository at this point in the history
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@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
euloh authored and kvanhees committed Feb 20, 2023
1 parent 267527c commit 5d0d980
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 12 deletions.
36 changes: 24 additions & 12 deletions bpf/inet_ntoa.S
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
*/

#define BPF_FUNC_probe_read 4

.text

/*
Expand Down Expand Up @@ -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:
Expand All @@ -146,19 +150,27 @@ dt_inet_ntoa_write_uint8:
.type dt_inet_ntoa, @function
dt_inet_ntoa:

/* off cycles between %r3 (input arg to subroutine) and %r0 (its return) */
/*
* the variable "off" is either in:
* %r3 (input arg to subroutine)
* %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
Expand All @@ -167,7 +179,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
Expand All @@ -176,7 +188,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
Expand All @@ -185,7 +197,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

Expand Down
25 changes: 25 additions & 0 deletions test/unittest/funcs/tst.inet_ntoa_alloca.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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/
{
p = alloca(4);
copyinto(arg1, 4, p);
printf("%s\n", inet_ntoa(p));
exit(0);
}

ERROR { exit(1); }
2 changes: 2 additions & 0 deletions test/unittest/funcs/tst.inet_ntoa_alloca.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
192.168.1.23

23 changes: 23 additions & 0 deletions test/unittest/funcs/tst.inet_ntoa_copyin.d
Original file line number Diff line number Diff line change
@@ -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(copyin(arg1,4)));
exit(0);
}

ERROR { exit(1); }
2 changes: 2 additions & 0 deletions test/unittest/funcs/tst.inet_ntoa_copyin.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
192.168.1.23

23 changes: 23 additions & 0 deletions test/unittest/funcs/tst.inet_ntoa_nonDPTR.d
Original file line number Diff line number Diff line change
@@ -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); }
2 changes: 2 additions & 0 deletions test/unittest/funcs/tst.inet_ntoa_nonDPTR.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
192.168.1.23

0 comments on commit 5d0d980

Please sign in to comment.