Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-16 Thread Ron Yorston
Rich Felker wrote:
I suspect it can easily be made to do arbitrary code execution when
otherwise-safe (e.g. checked against whitelist for special chars)
strings from untrusted input are expanded inside eval commands.

Any new use of VLA/alloca should be completely banned. It's basically
always an exploitable bug.

I certainly don't want to be responsible for the next Shellshock.

Following up with a patch to revert the use of alloca.  The old code was
ugly but at least it should be safe.  I can't see any other way to do it.

I did spot an opportunity to save a few bytes, though, so there's a second
patch to partly make up for the loss of the 66 byte saving in the reverted
patch.

Ron
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-15 Thread Rich Felker
On Mon, Jul 13, 2015 at 04:25:02AM +0200, Denys Vlasenko wrote:
 On Thu, Jul 2, 2015 at 10:01 AM, Ron Yorston r...@frippery.org wrote:
  Rich Felker wrote:
 In general alloca is unsafe. It's not obvious to me what the code here
 is doing, so I can't tell for sure if it's safe or not, but I think
 this needs a strong justification of safety before being acceptable.
 
  It's a parser for a POSIXy shell, I doubt that the code is obvious to
  anyone.
 
  My understanding is that it's reading a token and has got to the point
  where a command substitution has been detected.  It wants to save the
  bit of the token it's already processed.  So if we have
 
 echo very long string`date`
 
  the code would allocate space for the very long string.
 
 In practice, it would be a problem if very long string
 is some hundreds of kbytes, even a few mbytes long.
 
  Is this safe?  In most cases it probably is, but not if the script is
  malicious.  If the very long string is too big for your stack you get a
  seg fault or worse.  With a suitably long string and small stack I can
  reliably crash dash.
 
 With a sufficiently small memory limits you can crash any shell.
 
 Let's go with this change, unless someone sees a way to not just
 crash, but do something worse.

I suspect it can easily be made to do arbitrary code execution when
otherwise-safe (e.g. checked against whitelist for special chars)
strings from untrusted input are expanded inside eval commands.

Any new use of VLA/alloca should be completely banned. It's basically
always an exploitable bug.

Rich
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-12 Thread Denys Vlasenko
Applied, thanks.

On Wed, Jul 1, 2015 at 5:46 PM, Ron Yorston r...@frippery.org wrote:
 Now that the only thing protected by setjmp/longjmp is the saved string,
 we can allocate it on the stack to get rid of the jump.

 Based on commit bd35d8e from git://git.kernel.org/pub/scm/utils/dash/dash.git
 by Herbert Xu.

 function old new   delta
 readtoken1  31823116 -66
 --
 (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-66) Total: -66 bytes

 Signed-off-by: Ron Yorston r...@pobox.com
 ---
  shell/ash.c | 36 ++--
  1 file changed, 2 insertions(+), 34 deletions(-)

 diff --git a/shell/ash.c b/shell/ash.c
 index 1b33fbd..531e9e2 100644
 --- a/shell/ash.c
 +++ b/shell/ash.c
 @@ -11133,19 +11133,6 @@ readtoken1(int c, int syntax, char *eofmark, int 
 striptabs)

 IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)

 -#if __GNUC__
 -   /* Avoid longjmp clobbering */
 -   (void) out;
 -   (void) quotef;
 -   (void) dblquote;
 -   (void) varnest;
 -   (void) arinest;
 -   (void) parenlevel;
 -   (void) dqvarnest;
 -   (void) oldstyle;
 -   (void) prevsyntax;
 -   (void) syntax;
 -#endif
 startlinno = g_parsefile-linno;
 bqlist = NULL;
 quotef = 0;
 @@ -11610,30 +11597,16 @@ parsesub: {
  parsebackq: {
 struct nodelist **nlpp;
 union node *n;
 -   char *volatile str;
 -   struct jmploc jmploc;
 -   struct jmploc *volatile savehandler;
 +   char *str;
 size_t savelen;
 smallint saveprompt = 0;

 -#ifdef __GNUC__
 -   (void) saveprompt;
 -#endif
 -   if (setjmp(jmploc.loc)) {
 -   free(str);
 -   exception_handler = savehandler;
 -   longjmp(exception_handler-loc, 1);
 -   }
 -   INT_OFF;
 str = NULL;
 savelen = out - (char *)stackblock();
 if (savelen  0) {
 -   str = ckmalloc(savelen);
 +   str = alloca(savelen);
 memcpy(str, stackblock(), savelen);
 }
 -   savehandler = exception_handler;
 -   exception_handler = jmploc;
 -   INT_ON;
 if (oldstyle) {
 /* We must read until the closing backquote, giving special
  * treatment to some slashes, and then push the string and
 @@ -11732,12 +11705,7 @@ parsebackq: {
 if (str) {
 memcpy(out, str, savelen);
 STADJUST(savelen, out);
 -   INT_OFF;
 -   free(str);
 -   str = NULL;
 -   INT_ON;
 }
 -   exception_handler = savehandler;
 USTPUTC(CTLBACKQ, out);
 if (oldstyle)
 goto parsebackq_oldreturn;
 --
 2.4.3

 ___
 busybox mailing list
 busybox@busybox.net
 http://lists.busybox.net/mailman/listinfo/busybox
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-02 Thread Bernd Petrovitsch
On Mit, 2015-07-01 at 14:35 -0400, Rich Felker wrote:
 On Wed, Jul 01, 2015 at 04:46:18PM +0100, Ron Yorston wrote:
  Now that the only thing protected by setjmp/longjmp is the saved string,
  we can allocate it on the stack to get rid of the jump.
  
  Based on commit bd35d8e from 
  git://git.kernel.org/pub/scm/utils/dash/dash.git
  by Herbert Xu.
 
 In general alloca is unsafe. It's not obvious to me what the code here
 is doing, so I can't tell for sure if it's safe or not, but I think
 this needs a strong justification of safety before being acceptable.

Since (GNU-)C99 is used: What about variable length arrays instead of
alloca?
BTW this wouldn't be the first use of alloca():
  snip  
{13}find -name '*.[ch]' -type f | xargs fgrep -wc alloca | grep -v ':0$'
./networking/inetd.c:4
./networking/httpd.c:2
./libpwdgrp/uidgid_get.c:1
./findutils/find.c:3
./shell/ash.c:1
./shell/math.c:3
./libbb/pw_encrypt_sha.c:2
./libbb/xconnect.c:1
./libbb/copyfd.c:1
./libbb/getopt32.c:2
./scripts/basic/docproc.c:3
./scripts/basic/fixdep.c:3
./scripts/kconfig/lex.zconf.c:1
./scripts/kconfig/zconf.tab.c:2
./modutils/modutils-24.c:7
  snip  
(did that just after a `git pull`)

Kind regards,
Bernd
-- 
I dislike type abstraction if it has no real reason. And saving
on typing is not a good reason - if your typing speed is the main
issue when you're coding, you're doing something seriously wrong.
- Linus Torvalds

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-02 Thread Ron Yorston
Rich Felker wrote:
In general alloca is unsafe. It's not obvious to me what the code here
is doing, so I can't tell for sure if it's safe or not, but I think
this needs a strong justification of safety before being acceptable.

It's a parser for a POSIXy shell, I doubt that the code is obvious to
anyone.

My understanding is that it's reading a token and has got to the point
where a command substitution has been detected.  It wants to save the
bit of the token it's already processed.  So if we have

   echo very long string`date`

the code would allocate space for the very long string.  (Putting a space
between the string and the substitution makes two separate tokens so no
allocation would be required.  And the first part doesn't have to be a
string literal, that's just an example, it can consist of other stuff,
so long as it's all treated as making one token.)

Is this safe?  In most cases it probably is, but not if the script is
malicious.  If the very long string is too big for your stack you get a
seg fault or worse.  With a suitably long string and small stack I can
reliably crash dash.

Ron
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-02 Thread Sam Liddicott
On 1 Jul 2015 19:36, Rich Felker dal...@libc.org wrote:

 On Wed, Jul 01, 2015 at 04:46:18PM +0100, Ron Yorston wrote:
  Now that the only thing protected by setjmp/longjmp is the saved string,
  we can allocate it on the stack to get rid of the jump.
 
  Based on commit bd35d8e from git://
git.kernel.org/pub/scm/utils/dash/dash.git
  by Herbert Xu.

 In general alloca is unsafe. It's not obvious to me what the code here
 is doing, so I can't tell for sure if it's safe or not, but I think
 this needs a strong justification of safety before being acceptable.

If you are allocating small amounts of memory then allocated is as safe as
calling a function - i.e. marginally increases the chance of stack overflow
by moving the stack pointer closer to it's limit.

Compare the size of the allocated to the saving of not needing the other
stack based variables, including jmploc.

Sam
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-02 Thread Ron Yorston
Bernd Petrovitsch wrote:
Since (GNU-)C99 is used: What about variable length arrays instead of
alloca?

I haven't looked at the code of gcc but I understand that it allocates
VLAs on the stack, so they'd be subject to the same limits as alloca.

Ron
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-01 Thread Rich Felker
On Wed, Jul 01, 2015 at 04:46:18PM +0100, Ron Yorston wrote:
 Now that the only thing protected by setjmp/longjmp is the saved string,
 we can allocate it on the stack to get rid of the jump.
 
 Based on commit bd35d8e from git://git.kernel.org/pub/scm/utils/dash/dash.git
 by Herbert Xu.

In general alloca is unsafe. It's not obvious to me what the code here
is doing, so I can't tell for sure if it's safe or not, but I think
this needs a strong justification of safety before being acceptable.

Rich
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH 2/2] ash: use alloca to get rid of setjmp

2015-07-01 Thread Ron Yorston
Now that the only thing protected by setjmp/longjmp is the saved string,
we can allocate it on the stack to get rid of the jump.

Based on commit bd35d8e from git://git.kernel.org/pub/scm/utils/dash/dash.git
by Herbert Xu.

function old new   delta
readtoken1  31823116 -66
--
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-66) Total: -66 bytes

Signed-off-by: Ron Yorston r...@pobox.com
---
 shell/ash.c | 36 ++--
 1 file changed, 2 insertions(+), 34 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 1b33fbd..531e9e2 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -11133,19 +11133,6 @@ readtoken1(int c, int syntax, char *eofmark, int 
striptabs)
 
IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
 
-#if __GNUC__
-   /* Avoid longjmp clobbering */
-   (void) out;
-   (void) quotef;
-   (void) dblquote;
-   (void) varnest;
-   (void) arinest;
-   (void) parenlevel;
-   (void) dqvarnest;
-   (void) oldstyle;
-   (void) prevsyntax;
-   (void) syntax;
-#endif
startlinno = g_parsefile-linno;
bqlist = NULL;
quotef = 0;
@@ -11610,30 +11597,16 @@ parsesub: {
 parsebackq: {
struct nodelist **nlpp;
union node *n;
-   char *volatile str;
-   struct jmploc jmploc;
-   struct jmploc *volatile savehandler;
+   char *str;
size_t savelen;
smallint saveprompt = 0;
 
-#ifdef __GNUC__
-   (void) saveprompt;
-#endif
-   if (setjmp(jmploc.loc)) {
-   free(str);
-   exception_handler = savehandler;
-   longjmp(exception_handler-loc, 1);
-   }
-   INT_OFF;
str = NULL;
savelen = out - (char *)stackblock();
if (savelen  0) {
-   str = ckmalloc(savelen);
+   str = alloca(savelen);
memcpy(str, stackblock(), savelen);
}
-   savehandler = exception_handler;
-   exception_handler = jmploc;
-   INT_ON;
if (oldstyle) {
/* We must read until the closing backquote, giving special
 * treatment to some slashes, and then push the string and
@@ -11732,12 +11705,7 @@ parsebackq: {
if (str) {
memcpy(out, str, savelen);
STADJUST(savelen, out);
-   INT_OFF;
-   free(str);
-   str = NULL;
-   INT_ON;
}
-   exception_handler = savehandler;
USTPUTC(CTLBACKQ, out);
if (oldstyle)
goto parsebackq_oldreturn;
-- 
2.4.3

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox