Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Oct 2016 14:18:01 -0700
From:      Mark Millard <markmi@dsl-only.net>
To:        John Baldwin <jhb@freebsd.org>
Cc:        freebsd-current@freebsd.org, freebsd-arm <freebsd-arm@freebsd.org>, FreeBSD-STABLE Mailing List <freebsd-stable@freebsd.org>, FreeBSD Toolchain <freebsd-toolchain@freebsd.org>
Subject:   Re: stable/11 -r307797 on BPi-M3 (cortex-a7): truss gets segmentation fault for handling unknown system call
Message-ID:  <D37C545D-0646-4839-98FD-A7C495DB4B10@dsl-only.net>
In-Reply-To: <2661167.K5IN9JAPmQ@ralph.baldwin.cx>
References:  <0699F744-DEB3-4ED5-91A9-B77EA2ACED37@dsl-only.net> <2661167.K5IN9JAPmQ@ralph.baldwin.cx>

next in thread | previous in thread | raw e-mail | index | archive | help
[I re-established the crotchet-build based failure context finally. =
Unfortunately truss just dies in a new place.]

On 2016-Oct-28, at 7:29 AM, John Baldwin <jhbat freebsd.org> wrote:

> On Tuesday, October 25, 2016 11:40:38 AM Mark Millard wrote:
>> [The following has been reported in: =
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D213778 .]
>>=20
>> In trying to build lang/gcc6 xgcc's cc1 got some SIGSYS examples. In =
trying to track things down I ran into truss getting a SIGSEGV when it =
tries to handle the situation. . .
>>=20
>> In truss's enter_syscall there is (from a live gdb on truss, after =
the segmentation fault):
>>=20
>> 380		t->cs.name =3D sysdecode_syscallname(t->proc->abi->abi, =
t->cs.number);
>> 381		if (t->cs.name =3D=3D NULL)
>> (gdb)=20
>> 382			fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d =
--\n",
>> 383			    t->proc->abi->type, t->cs.number);
>> 384=09
>> 385		sc =3D get_syscall(t->cs.name, narg);
>> 386		t->cs.nargs =3D sc->nargs;
>> 387		assert(sc->nargs <=3D nitems(t->cs.s_args));
>> 388=09
>> 389		t->cs.sc =3D sc;
>>=20
>> (gdb) print *t
>> $2 =3D {entries =3D {le_next =3D 0x0, le_prev =3D 0x20617070}, proc =3D=
 0x20617060, tid =3D 100150, in_syscall =3D 1, cs =3D {sc =3D 0x0, name =
=3D 0x0, number =3D 580828064, args =3D 0x2061b0c0, nargs =3D 0,=20
>>    s_args =3D 0x2061b0ec}, before =3D {tv_sec =3D 1477418265, tv_nsec =
=3D 492342263}, after =3D {tv_sec =3D 1477418265, tv_nsec =3D =
492496630}}
>>=20
>> (gdb) print sc
>> $3 =3D (struct syscall *) 0x0
>>=20
>> So line 386 listed above gets a segmentation fault for sc->nargs when =
t->cs.name is a NULL pointer: sc ends up NULL.
>>=20
>> Looking at the two things that the fprintf on lines 382 and 383 would =
report:
>>=20
>> (gdb) print t->proc->abi->type
>> $4 =3D 0x10166 "FreeBSD ELF32"
>>=20
>> (gdb) print t->cs.number
>> $5 =3D 580828064
>>=20
>> (gdb) print narg
>> $6 =3D 0
>>=20
>> (that last is for context for the get_syscall arguments).
>>=20
>> FYI: 580828064 =3D 0x229EBBA0
>=20
> I have a patchset I have tested some in a git branch that I believe =
fixes handling of
> unknown system calls.  Please try this:
>=20
> =
https://github.com/freebsd/freebsd/compare/master...bsdjhb:truss_unknown
>=20
> (Add .diff to get a diff you can apply with patch)
>=20
>=20
> --=20
> John Baldwin

[Watch out for inlining consequences in how gdb presents things. Also I =
extracted from my explorations and changed the presentation order to =
eliminate junk.]

Summary: st->syscalls ends up NULL from reallocf refusing a huge =
allocation because t->cs.number=3D=3D580828064, which would make for a =
huge offset in st->syscalls[number] . new_count * =
sizeof(st->syscalls[0]) would be rather large (new_count =3D=3D =
number+1) .

reallocf's result needs to be tested and/or reasonable-value-checks on =
t->cs.number (a.k.a. number) need to be made and unreasonable value =
handled some other way.


The supporting details:

=
root@bananapi-m3:/usr/obj/portswork/usr/ports/lang/gcc6/work/.build/armv6-=
portbld-freebsd11.0/libgcc # gdb truss
GNU gdb 6.1.1 [FreeBSD]
. . .
(gdb) run -faeH -o truss.log =
/usr/obj/portswork/usr/ports/lang/gcc6/work/.build/./gcc/xgcc =
-B/usr/obj/portswork/usr/ports/lang/gcc6/work/.build/./gcc/ =
-B/usr/local/armv6-portbld-freebsd11.0/bin/ =
-B/usr/local/armv6-portbld-freebsd11.0/lib/ -isystem =
/usr/local/armv6-portbld-freebsd11.0/include -isystem =
/usr/local/armv6-portbld-freebsd11.0/sys-include -O2 -pipe =
-mcpu=3Dcortex-a7 -DLIBICONV_PLUG -g -fno-strict-aliasing -O2 -O2 -pipe =
-mcpu=3Dcortex-a7 -DLIBICONV_PLUG -g -fno-strict-aliasing -DIN_GCC -W =
-Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wno-format =
-Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -isystem =
./include -fPIC -pthread -fno-inline -fomit-frame-pointer -g =
-DIN_LIBGCC2 -fbuilding-libgcc -fno-stack-protector -fPIC -pthread =
-fno-inline -fomit-frame-pointer -I. -I. -I../.././gcc =
-I/usr/obj/portswork/usr/ports/lang/gcc6/work/gcc-6.2.0/libgcc =
-I/usr/obj/portswork/usr/ports/lang/gcc6/work/gcc-6.2.0/libgcc/. =
-I/usr/obj/portswork/usr/ports/lang/gcc6/work/gcc-6.2.0/libgcc/../gcc =
-I/usr/obj/portswork/usr/ports/lang/gcc6/work/gcc-6.2.0/libgcc/../include =
-DHAVE_CC_TLS -o _muldi3.o -MT _muldi3.o -MD -MP -MF _muldi3.dep =
-DL_muldi3 -c =
/usr/obj/portswork/usr/ports/lang/gcc6/work/gcc-6.2.0/libgcc/libgcc2.c =
-fvisibility=3Dhidden -DHIDE_EXPORTS
Starting program: /usr/bin/truss -faeH -o truss.log .
. . .
Program received signal SIGSEGV, Segmentation fault.
0x20241ebc in memset () from /lib/libc.so.7
Current language:  auto; currently minimal
(gdb) bt
#0  0x20241ebc in memset () from /lib/libc.so.7
#1  0x0000aec8 in get_syscall (t=3D<value optimized out>, =
number=3D580828064, nargs=3D0) at /usr/src/usr.bin/truss/syscalls.c:956
#2  0x0000ab8c in enter_syscall (info=3D0x20612000, t=3D0x2061b0a0, =
pl=3D<value optimized out>) at /usr/src/usr.bin/truss/setup.c:380
#3  0x0000a798 in eventloop (info=3D<value optimized out>) at =
/usr/src/usr.bin/truss/setup.c:664
#4  0x000098d4 in $a.6 () at /usr/src/usr.bin/truss/main.c:207
#5  0x000098d4 in $a.6 () at /usr/src/usr.bin/truss/main.c:207
(gdb) up
#1  0x0000aec8 in get_syscall (t=3D<value optimized out>, =
number=3D580828064, nargs=3D0) at /usr/src/usr.bin/truss/syscalls.c:956
956		memset(st->syscalls + st->count, 0, (new_count - =
st->count) *
. . .
0x20241eac <memset+244>:	cmp	r1, #4	; 0x4
0x20241eb0 <memset+248>:	bge	0x20241dd4 <memset+28>
0x20241eb4 <memset+252>:	cmp	r1, #0	; 0x0
0x20241eb8 <memset+256>:	moveq	pc, lr
0x20241ebc <memset+260>:	strb	r3, [r12], #1
. . .
(gdb) info reg
r0             0x0	0
r1             0x8a7aee84	-1971655036
r2             0x8a7aee84	-1971655036
r3             0x0	0
r4             0x1	1
r5             0x2062000c	543293452
r6             0x20620000	543293440
r7             0x229ebba1	580828065
r8             0x2061b0b0	543273136
r9             0x0	0
r10            0x229ebba0	580828064
r11            0xbfbfe478	-1077943176
r12            0x0	0
sp             0xbfbfe450	-1077943216
lr             0xaec8	44744
pc             0x20241ebc	539238076
fps            0x0	0
cpsr           0xa0000010	-1610612720
. . .
(gdb)=20
946	static void
947	grow_syscall_table(struct syscall_table *st, u_int number)
948	{
949		u_int new_count;
950=09
951		new_count =3D number + 1;
952		if (st->count >=3D new_count)
953			return;
954		st->syscalls =3D reallocf(st->syscalls, new_count *
955		    sizeof(st->syscalls[0]));
(gdb)=20
956		memset(st->syscalls + st->count, 0, (new_count - =
st->count) *
957		    sizeof(st->syscalls[0]));
958	}
959=09
960	/*
961	 * If/when the list gets big, it might be desirable to do it
962	 * as a hash table or binary search.
963	 */
964	struct syscall *
965	get_syscall(struct threadinfo *t, u_int number, u_int nargs)
(gdb)=20
966	{
967		struct syscall_table *st;
968		struct syscall *sc;
969		const char *name;
970		u_int i;
971=09
972		st =3D lookup_syscall_table(t->proc->abi->abi);
973		grow_syscall_table(st, number);
974		sc =3D st->syscalls[number];
975		if (sc !=3D NULL)
(gdb)=20
976			return (sc);
.  . .
951		new_count =3D number + 1;
952		if (st->count >=3D new_count)
953			return;
954		st->syscalls =3D reallocf(st->syscalls, new_count *
955		    sizeof(st->syscalls[0]));
956		memset(st->syscalls + st->count, 0, (new_count - =
st->count) *
957		    sizeof(st->syscalls[0]));
958	}
959=09
960	/*
(gdb) up
#2  0x0000ab8c in enter_syscall (info=3D0x20612000, t=3D0x2061b0a0, =
pl=3D<value optimized out>) at /usr/src/usr.bin/truss/setup.c:380
380		sc =3D get_syscall(t, t->cs.number, narg);
(gdb) list
375		if (narg !=3D 0 && t->proc->abi->fetch_args(info, narg) =
!=3D 0) {
376			free_syscall(t);
377			return;
378		}
379=09
380		sc =3D get_syscall(t, t->cs.number, narg);
381		if (sc->unknown)
382			fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d =
--\n",
383			    t->proc->abi->type, t->cs.number);
384=09
(gdb) print *t=20
$1 =3D {entries =3D {le_next =3D 0x0, le_prev =3D 0x20617028}, proc =3D =
0x20617018, tid =3D 100103, in_syscall =3D 1, cs =3D {sc =3D 0x0, number =
=3D 580828064, nargs =3D 0, args =3D 0x2061b0c0, s_args =3D 0x2061b0e8},=20=

  before =3D {tv_sec =3D 1477771714, tv_nsec =3D 696971654}, after =3D =
{tv_sec =3D 1477771714, tv_nsec =3D 697117646}}
(gdb) print narg
$2 =3D 0
. . .
(gdb) print t->cs.number
$9 =3D 580828064
. . .
(gdb) print *(t->proc)
$6 =3D {entries =3D {le_next =3D 0x20617000, le_prev =3D 0x20617048}, =
pid =3D 808, abi =3D 0x1ee68, threadlist =3D {lh_first =3D 0x2061b0a0}}
(gdb) print *(t->proc->abi)
$7 =3D {type =3D 0x1026b "FreeBSD ELF32", abi =3D SYSDECODE_ABI_FREEBSD, =
fetch_args =3D 0xda44 <arm_fetch_args>, fetch_retval =3D 0xdb64 =
<arm_fetch_retval>}
(gdb) print t->proc->abi->abi
$8 =3D SYSDECODE_ABI_FREEBSD

So for t->cs.number=3D=3D580828064 :

380		sc =3D get_syscall(t, t->cs.number, narg);
. . .
965	get_syscall(struct threadinfo *t, u_int number, u_int nargs)
. . .
973		grow_syscall_table(st, number);
974		sc =3D st->syscalls[number];

would get very far away from st->syscalls after indexing by the large =
number=3D=3D580828064 --if the grow could even complete for =
number=3D=3D580828064 :

947	grow_syscall_table(struct syscall_table *st, u_int number)
948	{
. ..
951		new_count =3D number + 1;
. . .
954		st->syscalls =3D reallocf(st->syscalls, new_count *
955		    sizeof(st->syscalls[0]));
956		memset(st->syscalls + st->count, 0, (new_count - =
st->count) *
957		    sizeof(st->syscalls[0]));

st->syscalls was NULL after reallocf returned the value NUKL.

=3D=3D=3D
Mark Millard
markmi at dsl-only.net




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?D37C545D-0646-4839-98FD-A7C495DB4B10>