LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware
User Name
Password
Slackware This Forum is for the discussion of Slackware Linux.

Notices

Reply
 
Search this Thread
Old 02-04-2010, 05:54 AM   #1
GazL
Senior Member
 
Registered: May 2008
Posts: 3,392

Rep: Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917
Ash segfaults on second backspace 64-current


I've found what seems to be a reproducible problem with 'ash' on slackware64-current (updates to and including Jan 31st)

Open a console
ash <enter>
type 2 or more characters, doesn't matter what.
press backspace
press backspace
**seg fault**

occurs under xterm, konsole, gnome-terminal in both kde4 and xfce and on a virtual console.

Can anyone else confirm please.


edit: Nuts! wrong forum. How did that happen! Sorry all.
Self reported for a move.

Last edited by GazL; 02-04-2010 at 06:03 AM.
 
Old 02-04-2010, 07:18 AM   #2
allend
Senior Member
 
Registered: Oct 2003
Location: Melbourne
Distribution: Slackware-current
Posts: 3,438

Rep: Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850
Same thing happens for me on Slackware64-current.
 
Old 02-04-2010, 08:15 AM   #3
GazL
Senior Member
 
Registered: May 2008
Posts: 3,392

Original Poster
Rep: Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917
I've tried rebuilding the existing version against the currently installed libraries just in case it needs a rebuild after the recent library changes, but it still doesn't work.

A strace of the sequence 1 2 3 backspace 4 backspace, produces this:
Code:
setpgid(0, 4416)                        = 0
ioctl(2, TIOCSPGRP, [4416])             = 0
wait4(4294967295, 0x7fff6d7c74ac, WNOHANG|WSTOPPED, NULL) = -1 ECHILD (No child processes)
write(2, "\\u@\\h:\\w\\$ "..., 11)      = 11
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig -icanon -echo ...}) = 0
read(0, "1"..., 1)                      = 1
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4bff1fc000
write(1, "1"..., 1)                     = 1
read(0, "2"..., 1)                      = 1
write(1, "2"..., 1)                     = 1
read(0, "3"..., 1)                      = 1
write(1, "3"..., 1)                     = 1
read(0, "\177"..., 1)                   = 1
write(1, "\10 \10 \10"..., 5)           = 5
read(0, "4"..., 1)                      = 1
write(1, "4"..., 1)                     = 1
read(0, "\177"..., 1)                   = 1
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
In contrast when doing a backspace in bash it results in a
Code:
write(2, "\10 \10"..., 3)               = 3
Might be barking up the wrong tree, but it looks a little strange.
 
Old 02-04-2010, 09:12 AM   #4
allend
Senior Member
 
Registered: Oct 2003
Location: Melbourne
Distribution: Slackware-current
Posts: 3,438

Rep: Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850Reputation: 850
In Slackware 12.2 (where no segfault occurs), strace of the sequence 1 2 3 backspace 4 backspace, produces this:
Code:
setpgid(0, 3565)                        = 0
ioctl(2, TIOCSPGRP, [3565])             = 0
wait4(-1, 0xbfdb1eb4, WNOHANG|WSTOPPED, NULL) = -1 ECHILD (No child processes)
stat64("/var/spool/mail/root", {st_mode=S_IFREG|0600, st_size=162433, ...}) = 0
write(2, "\\u@\\h:\\w\\$ ", 11\u@\h:\w\$ )         = 11
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig -icanon -echo ...}) = 0
read(0, "1", 1)                         = 1
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 1), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f94000
write(1, "1", 11)                        = 1
read(0, "2", 1)                         = 1
write(1, "2", 12)                        = 1
read(0, "3", 1)                         = 1
write(1, "3", 13)                        = 1
read(0, "\177", 1)                      = 1
write(1, "\10 \10 \10", )              = 5
read(0, "4", 1)                         = 1
write(1, "4", 14)                        = 1
read(0, "\177", 1)                      = 1
write(1, "\10 \10 \10", )              = 5
read(0,
 
Old 02-04-2010, 09:44 AM   #5
GazL
Senior Member
 
Registered: May 2008
Posts: 3,392

Original Poster
Rep: Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917
Thanks allen. I don't pretend to understand why it has to write 3 backspaces to the output anyway, but clearly that's not the problem then.
 
Old 02-04-2010, 09:53 AM   #6
Tsomi
LQ Newbie
 
Registered: Oct 2006
Posts: 13

Rep: Reputation: 6
The thing is that bluewhite64's package works:

ftp://ftp.devall.hu/bluewhite64/blue...0-x86_64-1.tgz

But actually, it has not been recompiled since Bluewhite64 11.0. So I guess this problem has something to do with recent versions of gcc/glibc, or the patches added in slackware64-13.0 to make ash compile.

I've never been able to build a package of ash that would not have this bug on my Slackware64 box, though...
 
Old 02-04-2010, 10:44 AM   #7
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,755

Rep: Reputation: 466Reputation: 466Reputation: 466Reputation: 466Reputation: 466
Try uaing dash instead, it is actively developed and should be more compatible with recent glibc.
 
1 members found this post helpful.
Old 02-04-2010, 06:52 PM   #8
GazL
Senior Member
 
Registered: May 2008
Posts: 3,392

Original Poster
Rep: Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917
I've rebuilt ash and left the debugging symbols in it just out of curiosity so I could run it through gdb

Code:
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-slackware-linux"...
(gdb) watch parsenextc
Hardware watchpoint 1: parsenextc
(gdb) run
Starting program: /bin/ash
$ Hardware watchpoint 1: parsenextc

Old value = 0x0
New value = 0x61f020 ""
0x0000000000409b2a in preadbuffer () at input.c:193
193             parsenextc = buf;
(gdb) c
Continuing.
123  *I press backspace here*
Hardware watchpoint 1: parsenextc

Old value = 0x61f020 "12"
New value = 0x61f0f0 ""
0x00007f90d573586a in memmove () from /lib64/libc.so.6
(gdb) c
Continuing.
3 *and another backspace*
Hardware watchpoint 1: parsenextc

Old value = 0x61f0f0 ""
New value = 0xff000000000061f0 <Address 0xff000000000061f0 out of bounds>
0x00007f90d57374a1 in _wordcopy_fwd_dest_aligned () from /lib64/libc.so.6
(gdb) bt
#0  0x00007f90d57374a1 in _wordcopy_fwd_dest_aligned () from /lib64/libc.so.6
#1  0x00007f90d573583e in memmove () from /lib64/libc.so.6
#2  0x0000000000416013 in input_backspace (cursor=0x7fff13552a24, len=0x7fff13552a28) at hetio.c:147
#3  0x000000000041662b in hetio_read_input (fd=0) at hetio.c:214
#4  0x0000000000409b5b in preadbuffer () at input.c:211
#5  0x0000000000410505 in xxreadtoken () at parser.c:770
#6  0x0000000000410803 in readtoken () at parser.c:687
#7  0x0000000000410957 in parsecmd (interact=<value optimized out>) at parser.c:138
#8  0x000000000040bc60 in cmdloop (top=1) at main.c:269
#9  0x000000000040c08a in main (argc=<value optimized out>, argv=<value optimized out>) at main.c:229
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000416031 in input_backspace (cursor=0x7fff13552a24, len=0x7fff13552a28) at hetio.c:151
151                             if (!*(parsenextc + j))
If I'm reading this right it looks like somethings going wrong within the libc memmove() call, corrupting the parsenextc pointer which then causes the segfault later when it's used in input_backspace().

Anyway, per gnashley's advice (thanks matey), I've built a static dash and put that on my system to try. However, I'm wondering if there's an underlying libc issue here. I'm on the limit of my skills here, so I could be misunderstanding things.

Last edited by GazL; 02-04-2010 at 06:53 PM.
 
Old 02-05-2010, 02:15 AM   #9
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,755

Rep: Reputation: 466Reputation: 466Reputation: 466Reputation: 466Reputation: 466
Okay, try this:
Code:
diff -ruN ash-0.4.0/output.h ash-0.4.0.new/output.h
--- ash-0.4.0/output.h 2006-11-06 21:14:41.000000000 +0300
+++ ash-0.4.0.new/output.h 2006-11-06 21:13:35.000000000 +0300
@@ -56,7 +56,7 @@
 char *nextc;
 int nleft;
 char *buf;
- int bufsize;
+ size_t bufsize;
 int fd;
 short flags;
 };
You may have to manually apply the change if the spacing on the diff is bad.
 
Old 02-05-2010, 07:54 AM   #10
GazL
Senior Member
 
Registered: May 2008
Posts: 3,392

Original Poster
Rep: Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917
Thanks gnashley. Changing bufsize to a size_t certainly fixes a compile time warning, but doesn't seem to change the symptoms of the crash. gdb still looks to be pointing to parsenextc being set out of bounds in _wordcopy_fwd_dest_aligned () within the memmove() libc call.

I've written this workaround, which seems to prove my hypothesis:
Code:
--- hetio.c.orig        2010-02-05 12:42:19.573236474 +0000
+++ hetio.c     2010-02-05 13:46:20.151236467 +0000
@@ -141,13 +141,16 @@
 {
        int j = 0;

+        char *saved_parsenextc ;

        if (*cursor > 0) {
                out1str("\b \b");
                --*cursor;
+                saved_parsenextc = parsenextc ;
                memmove(parsenextc + *cursor, parsenextc + *cursor + 1,
                        BUFSIZ - *cursor + 1);
-
+                parsenextc = saved_parsenextc ;
+
                for (j = *cursor; j < (BUFSIZ - 1); j++) {
                        if (!*(parsenextc + j))
                                break;
Now, whether this is a compiler bug, library bug, or just a bad assumption in the ash code that memmove() won't corrupt the pointer arguments passed to it, I don't know.

Should I drop Pat a note about this?

Last edited by GazL; 02-05-2010 at 07:56 AM.
 
Old 02-05-2010, 01:36 PM   #11
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,755

Rep: Reputation: 466Reputation: 466Reputation: 466Reputation: 466Reputation: 466
Okay, another stab in the dark:
Code:
--- ./input.c.00	2010-02-05 19:20:52.000000000 +0100
+++ ./input.c	2010-02-05 19:58:04.000000000 +0100
@@ -255,7 +255,7 @@
 	if (parsefile->strpush) {
 		popstring();
 		if (--parsenleft >= 0)
-			return (*parsenextc++);
+			return (signed char)(*parsenextc++);
 	}
 	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
 		return PEOF;
@@ -325,7 +325,7 @@
 
 	*q = savec;
 
-	return *parsenextc++;
+	return (signed char)*parsenextc++;
 }
 
 /*
--- ./input.h.00	2000-05-23 12:03:19.000000000 +0200
+++ ./input.h	2010-02-05 19:58:50.000000000 +0100
@@ -63,4 +63,4 @@
 void popallfiles __P((void));
 void closescript __P((void));
 
-#define pgetc_macro()	(--parsenleft >= 0? *parsenextc++ : preadbuffer())
+#define pgetc_macro()	(--parsenleft >= 0? (signed char)*parsenextc++ : preadbuffer())
Also, you may be able to get better debugging by using:
CFLAGS="-O0 -fno-inline"
 
Old 02-05-2010, 02:27 PM   #12
GazL
Senior Member
 
Registered: May 2008
Posts: 3,392

Original Poster
Rep: Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917
Yep, I've already discovered the '-O0'. My first attempt to fix it was to change the offending code to:
Code:
 if (*cursor > 0) {
                out1str("\b \b");
                --*cursor;
                to = parsenextc + *cursor ;
                from = to + 1 ;
                memmove(to, from,
                        BUFSIZ - *cursor + 1);
... but the damn silly compiler optimised the new 'to' and 'from' pointers out making no difference to what was there before. '-O0' fixed that, but it's still acting strange. The really strange part, is when I use that snippet above, the memmove() still changes the value of the parsenextc pointer (+56 bytes), even though it's not passed as a parameter to the memmove() function at all.

I wasn't aware of the -fno-inline, so thanks for that tip. I'll have to check it out.


Anyway, My patch in the post above already prevents the segfault in ash. I was more concerned by whether there's a underlying libc/toolchain issue going on here in current64. I'm pretty confident now that the pointer is being corrupted within that memmove() libc call in input_backspace(), What I don't understand is why.


Thanks for your "stab in the dark" patch, but the memmove() args are both (void *) so if I'm correct in my thinking then I don't see how it'll help as type shouldn't matter.


I think I understand the 'what', it's just the why that's eluding me.
(As I said at the beginning, I'm at the very edge of my skill level with this type of debugging. and libc internals are a bit beyond my competence level)

Last edited by GazL; 02-05-2010 at 04:32 PM.
 
Old 04-01-2010, 10:45 AM   #13
Richard Cranium
Senior Member
 
Registered: Apr 2009
Location: Carrollton, Texas
Distribution: Slackware64 14.1
Posts: 1,494

Rep: Reputation: 437Reputation: 437Reputation: 437Reputation: 437Reputation: 437
Quote:
Originally Posted by GazL View Post
Now, whether this is a compiler bug, library bug, or just a bad assumption in the ash code that memmove() won't corrupt the pointer arguments passed to it, I don't know.
This is C. memmove() should not be able to corrupt parsenextc itself, since all function parameters are call-by-value. For memmove() to change the value of parsenextc, you would have to pass in the address of parsenextc itself (by &parsenextc).

Just for a data point, the current 32 bit ash code does not have this problem. I just tried out your test case on my Slackware 13.0 box and there's no segfault there. (It fails on my Slackware64 13.0 box as you've documented above.)
 
Old 04-01-2010, 02:11 PM   #14
GazL
Senior Member
 
Registered: May 2008
Posts: 3,392

Original Poster
Rep: Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917Reputation: 917
Thanks. I've done some digging since the last post on here and I sent a patch to Pat back at the beginning of the month, but I've not heard anything from him about it and it didn't show up in the latest set of updates.


As you've taken an interest in this I'll post it here too for completeness...

Code:
#  Patch file for use against Slackware64 13.0/current(2010-03-08)
#    .../slackware64/source/ap/ash/patches/ash-hetio.patch.gz
#
#  May also be applicable to 32bit, but I haven't checked.  
# 
#  Instructions
#    Apply with:
#      cd .../slackware64/source/ap/ash/patches
#      gunzip ash-hetio.patch.gz
#      patch < this_file
#      gzip ash-hetio.patch
#    and rebuild package.
#
#  What this fixes: 
#    Incorrect size calculation on the memmove() in hetio.c:input_backspace()
#    results in parsenextc's storage location being overwritten.
#
#    Pressing backspace once will result in silent corruption of the 
#    parsenextc pointer. Pressing backspace a second time will take 
#    parsenextc out of bounds and result in a segfault.
#  


--- ash-hetio.patch     2010-03-08 13:47:44.982364101 +0000
+++ ash-hetio.patch     2010-03-08 13:54:08.443871155 +0000
@@ -177,7 +177,7 @@
 +              out1str("\b \b");
 +              --*cursor;
 +              memmove(parsenextc + *cursor, parsenextc + *cursor + 1, 
-+                      BUFSIZ - *cursor + 1);
++                      BUFSIZ - (*cursor + 1) ) ;
 +
 +              for (j = *cursor; j < (BUFSIZ - 1); j++) {
 +                      if (!*(parsenextc + j))
The underlying problem is that memmove() is being asked to move 2 bytes too many due to the above error. On 64bit, the parsenextc pointer is stored in the memory location directly after the buffer that parsenextc is manipulating. The upshot is that the second byte of parsenextc is being moved over the first by the call to memmove().

As for 32bit, my guess is that the parsenextc pointer is being stored at a slightly different memory location and some other less vital variable is being overwritten by the move.

Good stuff eh? I learned quite a bit while trying to diagnose that one.

Last edited by GazL; 04-01-2010 at 06:32 PM.
 
Old 04-02-2010, 03:11 AM   #15
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,755

Rep: Reputation: 466Reputation: 466Reputation: 466Reputation: 466Reputation: 466
Does the fix still work with 3 or more backspaces?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Slack64-current - CTRL-ALT-BACKSPACE doesn't kill X GrapefruiTgirl Slackware 8 08-29-2009 09:32 AM
Slackware64-current: Creation of LUKS encrypted partition segfaults titopoquito Slackware 16 08-16-2009 04:02 AM
which script does ash shell execute first Jurrian Linux - Newbie 0 01-21-2009 04:06 AM
Use bash as an alternative to ash? J_Szucs Linux - General 3 05-30-2005 04:44 AM
ash script (please) sourceman Linux - General 1 04-18-2002 09:38 AM


All times are GMT -5. The time now is 07:11 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration