Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.debian.kernel > #71205 > unrolled thread
| Started by | Thorsten Glaser <tg@debian.org> |
|---|---|
| First post | 2021-05-03 22:20 +0200 |
| Last post | 2021-05-06 00:30 +0200 |
| Articles | 5 — 3 participants |
Back to article view | Back to linux.debian.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Bug#943425: klibc: [s390x] SIGSEGV in mksh testcase funsub-2 Thorsten Glaser <tg@debian.org> - 2021-05-03 22:20 +0200
Bug#943425: Use of $v10 register (was Re: klibc: [s390x] SIGSEGV in mksh testcase funsub-2) Thorsten Glaser <tg@debian.org> - 2021-05-03 23:00 +0200
Processed: Use of $v10 register (was Re: klibc: [s390x] SIGSEGV in mksh testcase funsub-2) "Debian Bug Tracking System" <owner@bugs.debian.org> - 2021-05-03 23:00 +0200
Bug#943425: Debian #943425: [s390x] setjmp/longjmp do not save/restore all registers in use Thorsten Glaser <tg@mirbsd.de> - 2021-05-05 05:00 +0200
Bug#943425: [klibc] Bug#943425: Debian #943425: klibc: [s390x] setjmp/longjmp do not save/restore all registers in use Thorsten Glaser <tg@mirbsd.de> - 2021-05-06 00:30 +0200
| From | Thorsten Glaser <tg@debian.org> |
|---|---|
| Date | 2021-05-03 22:20 +0200 |
| Subject | Bug#943425: klibc: [s390x] SIGSEGV in mksh testcase funsub-2 |
| Message-ID | <CaNcS-1DV-13@gated-at.bofh.it> |
Package: libklibc-dev
Version: 2.0.8-6
Followup-For: Bug #943425
X-Debbugs-Cc: tg@debian.org
I am able to track this down on the porterbox zelenka.
$ apt-get source mksh
$ cd mksh-59c
$ mkdir -p build/klibc
$ cd build/klibc
$ cp /usr/lib/klibc/bin/mksh .
$ chmod +x mksh # because the x attribute is removed if testsfail
$ gdb --args ./mksh -c 'x=q; e=1; x=${ echo a; typeset e=2; return 3; echo x$e;}; echo 3:y$x,$e,$?.'
(gdb) r
[...]
Program received signal SIGSEGV, Segmentation fault.
0x0000000001007c32 in comsub (fn=14, cp=0x0, xp=<synthetic pointer>) at ../../eval.c:1611
warning: Source file is more recent than executable.
1611 lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
(gdb) bt
#0 0x0000000001007c32 in comsub (fn=14, cp=0x0, xp=<synthetic pointer>) at ../../eval.c:1611
#1 expand (ccp=ccp@entry=0x3fffdfe4768 "\001x\001=\016\\echo a ; \\typeset e=2 ; \\return 3 ; \\echo x$e ",
wp=wp@entry=0x3ffffffed48, f=f@entry=4128) at ../../eval.c:346
#2 0x000000000100a366 in evalstr (
cp=0x3fffdfe4768 "\001x\001=\016\\echo a ; \\typeset e=2 ; \\return 3 ; \\echo x$e ", f=f@entry=4128)
at ../../eval.c:173
#3 0x000000000100d082 in comexec (t=0x3fffdfe4888, tp=tp@entry=0x0, ap=0x3fffdfe45e8, flags=<optimized out>,
xerrok=<optimized out>) at ../../exec.c:640
#4 0x000000000100bf0a in execute (t=<optimized out>, flags=<optimized out>, xerrok=xerrok@entry=0x0)
at ../../exec.c:162
#5 0x000000000100c0a2 in execute (t=t@entry=0x3fffdfe4588, flags=flags@entry=0, xerrok=xerrok@entry=0x0)
at ../../exec.c:204
#6 0x000000000101e048 in shell (s=s@entry=0x3fffdfe3b68, level=level@entry=0) at ../../main.c:954
#7 0x0000000001000e78 in main (argc=<optimized out>, argv=<optimized out>) at ../../main.c:742
(gdb) print shf
$1 = (struct shf *) 0x0
The code in question (where it crashes) is thus:
1584 } else if (fn == FUNSUB) {
1585 int ofd1;
1586 struct temp *tf = NULL;
1587
1588 /*
1589 * create a temporary file, open for reading and writing,
1590 * with an shf open for reading (buffered) but yet unused
1591 */
1592 maketemp(ATEMP, TT_FUNSUB, &tf);
1593 if (!tf->shf) {
1594 errorf(Tf_temp,
1595 Tcreate, tf->tffn, cstrerror(errno));
1596 }
1597 /* extract shf from temporary file, unlink and free it */
1598 shf = tf->shf;
1599 unlink(tf->tffn);
1600 afree(tf, ATEMP);
1601 /* save stdout and let it point to the tempfile */
1602 ofd1 = savefd(1);
1603 ksh_dup2(shf_fileno(shf), 1, false);
1604 /*
1605 * run tree, with output thrown into the tempfile,
1606 * in a new function block
1607 */
1608 valsub(t, NULL);
1609 subst_exstat = exstat & 0xFF;
1610 /* rewind the tempfile and restore regular stdout */
1611 lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
1612 restfd(1, ofd1);
The crash occurs in line 1611 because shf (a local variable) is nil.
The really interesting part, though, is in line 1608, a call to valsub():
2093 /* helper function due to setjmp/longjmp woes */
2094 static char *
2095 valsub(struct op *t, Area *ap)
2096 {
2097 char * volatile cp = NULL;
2098 struct tbl * volatile vp = NULL;
2099
2100 newenv(E_FUNC);
2101 newblock();
2102 if (ap)
2103 vp = local(TREPLY, false);
2104 if (!kshsetjmp(e->jbuf))
2105 execute(t, XXCOM | XERROK, NULL);
2106 if (vp)
2107 strdupx(cp, str_val(vp), ap);
2108 quitenv(NULL);
2109
2110 return (cp);
2111 }
Let's look again at the invocation that caused the crash:
x=q; e=1; x=${ echo a; typeset e=2; return 3; echo x$e;}; echo 3:y$x,$e,$?.
This one does not crash:
x=q; e=1; x=${ echo a; typeset e=2; echo x$e;}; echo 2:y$x,$e,$?.
The difference here is that 'return' is used in the crash case,
which executes a kshlongjmp(), that is siglongjmp(); kshsetjmp(x)
is sigsetjmp(x,0), which klibc defines as:
34 #define sigsetjmp(__env, __save) \
35 ({ \
36 struct __sigjmp_buf *__e = (__env); \
37 sigprocmask(0, NULL, &__e->__sigs); \
38 setjmp(__e->__jmpbuf); \
39 })
This apparently has two problems:
- the __save argument is ignored, contrary to sigsetjmp docs:
If, and only if, the savesigs argument provided to sigsetjmp() is non-
zero, the process's current signal mask is saved in env and will be re-
stored if a siglongjmp() is later performed with this env.
- it appears as if the combination of sigsetjmp/siglongjmp does not restore
all callee-saved variables correctly on s390x; comparing with glibc shows
that the wrong FPU registers seem to be saved but mksh does not use the
FPU anyway
Setting breakpoints to lines 1608 (valsub call) and 1609:
Breakpoint 3, comsub (fn=14, cp=0x3fffdfe476d "\\echo a ; \\typeset e=2 ; \\return 3 ; \\echo x$e ",
xp=<synthetic pointer>) at ../../eval.c:1608
1608 valsub(t, NULL);
(gdb) print shf
$5 = (struct shf *) 0x3fffdfe5de8
(gdb) print &shf
Address requested for identifier "shf" which is in register $v10
(gdb) info r
pswm 0x705200180000000 505845723963588608
pswa 0x1007c06 16808966
r0 0x11f 287
r1 0xfffffffffffff000 18446744073709547520
r2 0x1 1
r3 0x102dea0 16965280
r4 0x0 0
r5 0x120 288
r6 0x3ff0000000e 4393751543822
r7 0x1020 4128
r8 0x0 0
r9 0xe 14
r10 0x0 0
r11 0xc 12
r12 0x3fffdfe5708 4398012847880
r13 0x102ee90 16969360
r14 0x1007c06 16808966
r15 0x3ffffffea90 4398046505616
acr0 0x3ff 1023
acr1 0xfdff7710 4261377808
acr2 0x0 0
acr3 0x0 0
acr4 0x0 0
acr5 0x0 0
acr6 0x0 0
acr7 0x0 0
acr8 0x0 0
acr9 0x0 0
acr10 0x0 0
acr11 0x0 0
acr12 0x0 0
acr13 0x0 0
acr14 0x0 0
acr15 0x0 0
fpc 0x0 0
orig_r2 0xb 11
last_break 0x101d89c 0x101d89c <ksh_dup2+68>
system_call 0x0 0
tdb0 <unavailable>
tac <unavailable>
tct <unavailable>
atia <unavailable>
tr0 <unavailable>
tr1 <unavailable>
tr2 <unavailable>
tr3 <unavailable>
tr4 <unavailable>
tr5 <unavailable>
tr6 <unavailable>
tr7 <unavailable>
tr8 <unavailable>
tr9 <unavailable>
tr10 <unavailable>
tr11 <unavailable>
tr12 <unavailable>
tr13 <unavailable>
tr14 <unavailable>
tr15 <unavailable>
gsd <unavailable>
gssm <unavailable>
gsepla <unavailable>
bc_gsd <unavailable>
bc_gssm <unavailable>
bc_gsepla <unavailable>
pc 0x1007c06 0x1007c06 <expand+2342>
cc 0x2 2
... uhm, $v10 does not appear here?
(gdb) print $v10
$6 = {v4_float = {1.43352833e-42, -4.22639375e+37, 0, 0}, v2_double = {2.1729070589754877e-311, 0}, v16_int8 = {
0, 0, 3, -1, -3, -2, 93, -24, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {0, 1023, -514, 24040, 0, 0, 0, 0},
v4_int32 = {1023, -33661464, 0, 0}, v2_int64 = {4398012849640, 0}, uint128 = 81129017470195127308370827018240}
0x3FFFDFE5DE8 is 4398012849640 which is in v2_int64, found.
I have a feeling... anyway:
(gdb) c
Continuing.
Breakpoint 2, comsub (fn=14, cp=0x0, xp=<synthetic pointer>) at ../../eval.c:1609
1609 subst_exstat = exstat & 0xFF;
(gdb) info r
pswm 0x705100180000000 505828131777544192
pswa 0x1007c14 16808980
r0 0xffffffffffffffff 18446744073709551615
r1 0x10fc0 69568
r2 0x0 0
r3 0x9fc0 40896
r4 0xfc0 4032
r5 0x0 0
r6 0x3ff0000000e 4393751543822
r7 0x1020 4128
r8 0x0 0
r9 0xe 14
r10 0x0 0
r11 0xc 12
r12 0x3fffdfe5708 4398012847880
r13 0x102ee90 16969360
r14 0x1007c14 16808980
r15 0x3ffffffea90 4398046505616
acr0 0x3ff 1023
acr1 0xfdff7710 4261377808
acr2 0x0 0
acr3 0x0 0
acr4 0x0 0
acr5 0x0 0
acr6 0x0 0
acr7 0x0 0
acr8 0x0 0
acr9 0x0 0
acr10 0x0 0
acr11 0x0 0
acr12 0x0 0
acr13 0x0 0
acr14 0x0 0
acr15 0x0 0
fpc 0x0 0
orig_r2 0x2 2
last_break 0x10066d0 0x10066d0 <valsub+160>
system_call 0x0 0
tdb0 <unavailable>
tac <unavailable>
tct <unavailable>
atia <unavailable>
tr0 <unavailable>
tr1 <unavailable>
tr2 <unavailable>
tr3 <unavailable>
tr4 <unavailable>
tr5 <unavailable>
tr6 <unavailable>
tr7 <unavailable>
tr8 <unavailable>
tr9 <unavailable>
tr10 <unavailable>
tr11 <unavailable>
tr12 <unavailable>
tr13 <unavailable>
tr14 <unavailable>
tr15 <unavailable>
gsd <unavailable>
gssm <unavailable>
gsepla <unavailable>
bc_gsd <unavailable>
bc_gssm <unavailable>
bc_gsepla <unavailable>
pc 0x1007c14 0x1007c14 <expand+2356>
cc 0x1 1
(gdb) print $v10
$7 = {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0,
0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0}, uint128 = 0}
-- System Information:
Debian Release: 11.0
APT prefers unstable-debug
APT policy: (500, 'unstable-debug'), (500, 'unstable')
Architecture: s390x
Kernel: Linux 4.19.0-16-s390x (SMP w/2 CPU threads)
Locale: LANG=C, LC_CTYPE=C.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /bin/dash
Init: unable to detect
Versions of packages libklibc-dev depends on:
ii libklibc 2.0.8-6
ii linux-libc-dev 5.10.28-1
libklibc-dev recommends no packages.
libklibc-dev suggests no packages.
-- no debconf information
[toc] | [next] | [standalone]
| From | Thorsten Glaser <tg@debian.org> |
|---|---|
| Date | 2021-05-03 23:00 +0200 |
| Subject | Bug#943425: Use of $v10 register (was Re: klibc: [s390x] SIGSEGV in mksh testcase funsub-2) |
| Message-ID | <CaNPA-1R6-7@gated-at.bofh.it> |
| In reply to | #71205 |
retitle 943425 klibc: [s390x] setjmp/longjmp do not save/restore all registers in use
# because this affects a release architecture
severity 943425 serious
thanks
Recapping for the benefit of d-s390@l.d.o:
> The code in question (where it crashes) is thus:
> 1607 */
> 1608 valsub(t, NULL);
> 1609 subst_exstat = exstat & 0xFF;
> 1610 /* rewind the tempfile and restore regular stdout */
> 1611 lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
> The crash occurs in line 1611 because shf (a local variable) is nil.
>
> The really interesting part, though, is in line 1608, a call to valsub():
[…]
> 2104 if (!kshsetjmp(e->jbuf))
> 2105 execute(t, XXCOM | XERROK, NULL);
[…]
kshsetjmp(x) is sigsetjmp(x,0) (though klibc ignores the 0).
execute() calls siglongjmp().
> - it appears as if the combination of sigsetjmp/siglongjmp does not restore
> all callee-saved variables correctly on s390x; comparing with glibc shows
> that the wrong FPU registers seem to be saved but mksh does not use the
> FPU anyway
>
> Setting breakpoints to lines 1608 (valsub call) and 1609:
[…]
> 1608 valsub(t, NULL);
> (gdb) print shf
> $5 = (struct shf *) 0x3fffdfe5de8
> (gdb) print &shf
> Address requested for identifier "shf" which is in register $v10
> (gdb) print $v10
> $6 = {v4_float = {1.43352833e-42, -4.22639375e+37, 0, 0}, v2_double = {2.1729070589754877e-311, 0}, v16_int8 = {
> 0, 0, 3, -1, -3, -2, 93, -24, 0, 0, 0, 0, 0, 0, 0, 0}, v8_int16 = {0, 1023, -514, 24040, 0, 0, 0, 0},
> v4_int32 = {1023, -33661464, 0, 0}, v2_int64 = {4398012849640, 0}, uint128 = 81129017470195127308370827018240}
>
> 0x3FFFDFE5DE8 is 4398012849640 which is in v2_int64, found.
[…]
> Breakpoint 2, comsub (fn=14, cp=0x0, xp=<synthetic pointer>) at ../../eval.c:1609
> 1609 subst_exstat = exstat & 0xFF;
[…]
> (gdb) print $v10
> $7 = {v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0 <repeats 16 times>}, v8_int16 = {0, 0, 0, 0,
> 0, 0, 0, 0}, v4_int32 = {0, 0, 0, 0}, v2_int64 = {0, 0}, uint128 = 0}
------------------------------------------------------------------
So, setjmp/longjmp in klibc save f1/f3/f5/f7 (as shown on Wikipedia
https://en.wikipedia.org/wiki/Calling_convention#IBM_System/360_and_successors
“the z/Architecture ABI,[11] used in Linux” a page down), while
glibc’s save f8–f15 instead.
https://share.confex.com/share/124/webprogram/Handout/Session16897/SHARE_Seattle_2015_SIMD.pdf
shows that the vector registers overlap and extend the FPU registers.
(gdb) info float
[…]
f10 2.172907066248134e-311 (raw 0x000003fffdfe9768)
(gdb) print shf
$2 = (struct shf *) 0x3fffdfe9768
The real questions here are:
• is register v10 (vector extension) even supposed to be used?
• klibc does not really support the FPU anyway
• the half of v10 that equals f10 just HAPPENS to be saved by
glibc, but what if the upper half, that is outside of the FPU,
is used?
• where *is* the s390x̲ ABI documented anyway? syscall(2) has the
kernel side only
Building with -mno-vx does not seem to help, %f* are still in
the .s files generated by gcc.
So I assume klibc should save registers f8–15 on s390x but what
happened to f1/f3/f5/f7?
Thanks,
//mirabilos
--
[17:15:07] Lukas Degener: Kleines Asterix-Latinum für Softwaretechniker:
veni, vidi, fixi(t) ;-)
[toc] | [prev] | [next] | [standalone]
| From | "Debian Bug Tracking System" <owner@bugs.debian.org> |
|---|---|
| Date | 2021-05-03 23:00 +0200 |
| Subject | Processed: Use of $v10 register (was Re: klibc: [s390x] SIGSEGV in mksh testcase funsub-2) |
| Message-ID | <CaNPA-1R6-11@gated-at.bofh.it> |
| In reply to | #71207 |
Processing commands for control@bugs.debian.org: > retitle 943425 klibc: [s390x] setjmp/longjmp do not save/restore all registers in use Bug #943425 [libklibc-dev] klibc: [s390x] SIGSEGV in mksh testcase funsub-2 Changed Bug title to 'klibc: [s390x] setjmp/longjmp do not save/restore all registers in use' from 'klibc: [s390x] SIGSEGV in mksh testcase funsub-2'. > # because this affects a release architecture > severity 943425 serious Bug #943425 [libklibc-dev] klibc: [s390x] setjmp/longjmp do not save/restore all registers in use Severity set to 'serious' from 'normal' > thanks Stopping processing here. Please contact me if you need assistance. -- 943425: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943425 Debian Bug Tracking System Contact owner@bugs.debian.org with problems
[toc] | [prev] | [next] | [standalone]
| From | Thorsten Glaser <tg@mirbsd.de> |
|---|---|
| Date | 2021-05-05 05:00 +0200 |
| Subject | Bug#943425: Debian #943425: [s390x] setjmp/longjmp do not save/restore all registers in use |
| Message-ID | <CbfVv-21l-1@gated-at.bofh.it> |
| In reply to | #71207 |
Dixi quod…
>Jessica Clarke brought out docs saying f8‥f15 must be saved, the
>other FPU registers not:
This needs to be fixed in klibc.
>>• klibc does not really support the FPU anyway
>
>… GCC chooses to allocate an FPU register for a pointer value.
This is a curiosity.
>>• the half of v10 that equals f10 just HAPPENS to be saved by
>> glibc, but what if the upper half, that is outside of the FPU,
>> is used?
>
>The question here is, does GCC only use the halves of the half
>of the vector registers that match the FPU registers?
04:41⎜«jrtc27:#debian-x32» hephaistor: re s390x vector registers, reading the gcc and llvm sources they're
⎜ all call-clobbered by default, only the float parts are call-saved
04:41⎜«jrtc27:#debian-x32» so that's why setjmp/longjmp don't need to save/restore them
04:42⎜«jrtc27:#debian-x32» there *is* a vector calling convention, but it's not the default for the ABI,
⎜ it's opt-in, and setjmp/longjmp won't be annotated as such
So we indeed need to only save the registers glibc does.
>@klibc list: as indicated earlier, I can provide a patch if needed
>(though it should be obvious).
bye,
//mirabilos
--
[00:02] <Vutral> gecko: benutzt du emacs ?
[00:03] <gecko> nö [00:03] <gecko> nur n normalen mac
[00:04] <Vutral> argl [00:04] <Vutral> ne den editor
-- Vutral und gecko2 in #deutsch (NB: Editor? Betriebssystem.)
[toc] | [prev] | [next] | [standalone]
| From | Thorsten Glaser <tg@mirbsd.de> |
|---|---|
| Date | 2021-05-06 00:30 +0200 |
| Subject | Bug#943425: [klibc] Bug#943425: Debian #943425: klibc: [s390x] setjmp/longjmp do not save/restore all registers in use |
| Message-ID | <CbybL-4Iv-3@gated-at.bofh.it> |
| In reply to | #71222 |
[Multipart message — attachments visible in raw view] — view raw
tags 943425 + patch
tags 988027 + patch
thanks
Dixi quod…
>Patches for klibc upstream git attched; I’m currently trying to test
>them, will report.
This was really tricky given we can’t install patched B-Ds on
porterboxen, but I managed. I can confirm this fixes my issue.
bye,
//mirabilos
--
<diogenese> Beware of ritual lest you forget the meaning behind it.
<igli> yeah but it means if you really care about something, don't
ritualise it, or you will lose it. don't fetishise it, don't
obsess. or you'll forget why you love it in the first place.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.debian.kernel
csiph-web