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>