REGRESSION: shellshock patch rejects valid function names

2014-09-26 Thread Jay Freeman (saurik)
Hello! ;P Yesterday, I upgraded to a new version of bash (from Debian), 
intended to fix "shellshock". Today, I'm finding that all of my build scripts 
have stopped working :(. I managed to narrow the breaking change to yesterday's 
patch: the problem is that the names of functions are allowed to contain 
colons, but the new patch refuses to import these exported functions.

The code issue is that the patch uses valid_identifier(name), when 
check_identifier(name, posixly_correct) is what is normally used for function 
names. (In the case of export, the check is "does this function exist", not "is 
this identifier valid".) The means that suddenly only a tiny subset of 
functions all previous version of bash had supported are now exportable :(.

As far as I can tell, the goal is to avoid accidentally executing embedded 
shell that might be in the name of the function? It would seem to me that a 
better way to go about this would be to run the parser on the name and verify 
that what comes back is a single WORD_DESC that can be given to 
check_identifier (but of course, I am nowhere near as versed in the bash code 
as any of you).

Below, I have included a code-oriented explanation of the incompatibility 
between these checks (based on bash 4.2, which is the version I got today from 
Debian; for the record, I had previously been running bash 3.2). I would be 
happy to attempt to help in any other way that seems relevant (such as if a 
maintainer has a general approach they agree with and would like to see 
attempted).

(Regardless, thanks to anyone who chooses to look at this issue, or even just 
read this e-mail ;P.)

>From execute_cmd.c:

   5100 execute_intern_function (name, function)
   5101  WORD_DESC *name;
   5102  COMMAND *function;
   5103 {
   5104   SHELL_VAR *var;
   5105
=> 5106   if (check_identifier (name, posixly_correct) == 0)
   5107 {
   5108   if (posixly_correct && interactive_shell == 0)
   5109 {
   5110   last_command_exit_value = EX_BADUSAGE;
   5111   jump_to_top_level (ERREXIT);
   5112 }
   5113   return (EXECUTION_FAILURE);
   5114 }

In the case where posixly_correct is false, check_identifier will allow colons 
in the identifier names.

224 int
225 check_identifier (word, check_word)
226  WORD_DESC *word;
227  int check_word;
228 {
229   if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
230 {
231   internal_error (_("`%s': not a valid identifier"), word->word);
232   return (0);
233 }
=>  234   else if (check_word && legal_identifier (word->word) == 0)
235 {
236   internal_error (_("`%s': not a valid identifier"), word->word);
237   return (0);
238 }
239   else
240 return (1);
241 }

>From the new shellshock patch:

350   /* Don't import function names that are invalid identifiers 
from the
351  environment. */
=>  352   if (legal_identifier (name))
353 parse_and_execute (temp_string, name, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);

This check is thereby incompatible with existing behavior and scripts, and 
leads to situations where both function and export -f are happy, but running 
bash causes a function import error. As mentioned, I do not believe that this 
is required to be secure, so it would seem a shame to break scripts that have 
been functioning without issue for almost a decade.

$ bash --norc
$ function std:echo() { echo "$@"; }
$ std:echo hello world
hello world
$ export -f std:echo
$ printenv | grep std:echo -A 1
std:echo=() {  echo "$@"
}
$ bash --norc
bash: error importing function definition for `std:echo'
$ std:echo hello world
bash: std:echo: command not found

Sincerely,
Jay Freeman (saurik)
sau...@saurik.com



REGRESSION: shellshock patch rejects valid function names

2014-09-26 Thread Jay Freeman (saurik)
(I am terribly sorry if this e-mail message comes through twice; I normally use 
a third-party SMTP relay service, but it marks my e-mail with various headers, 
including precedence bulk, that I think might have caused my first e-mail to 
have been eaten by your mailing list manager, as I did not see this e-mail 
appear in the archive. I've bypassed that service for this attempt.)

Hello! ;P Yesterday, I upgraded to a new version of bash (from Debian), 
intended to fix "shellshock". Today, I'm finding that all of my build scripts 
have stopped working :(. I managed to narrow the breaking change to yesterday's 
patch: the problem is that the names of functions are allowed to contain 
colons, but the new patch refuses to import these exported functions.

The code issue is that the patch uses valid_identifier(name), when 
check_identifier(name, posixly_correct) is what is normally used for function 
names. (In the case of export, the check is "does this function exist", not "is 
this identifier valid".) The means that suddenly only a tiny subset of 
functions all previous version of bash had supported are now exportable :(.

As far as I can tell, the goal is to avoid accidentally executing embedded 
shell that might be in the name of the function? It would seem to me that a 
better way to go about this would be to run the parser on the name and verify 
that what comes back is a single WORD_DESC that can be given to 
check_identifier (but of course, I am nowhere near as versed in the bash code 
as any of you).

Below, I have included a code-oriented explanation of the incompatibility 
between these checks (based on bash 4.2, which is the version I got today from 
Debian; for the record, I had previously been running bash 3.2). I would be 
happy to attempt to help in any other way that seems relevant (such as if a 
maintainer has a general approach they agree with and would like to see 
attempted).

(Regardless, thanks to anyone who chooses to look at this issue, or even just 
read this e-mail ;P.)

>From execute_cmd.c:

   5100 execute_intern_function (name, function)
   5101  WORD_DESC *name;
   5102  COMMAND *function;
   5103 {
   5104   SHELL_VAR *var;
   5105
=> 5106   if (check_identifier (name, posixly_correct) == 0)
   5107 {
   5108   if (posixly_correct && interactive_shell == 0)
   5109 {
   5110   last_command_exit_value = EX_BADUSAGE;
   5111   jump_to_top_level (ERREXIT);
   5112 }
   5113   return (EXECUTION_FAILURE);
   5114 }

In the case where posixly_correct is false, check_identifier will allow colons 
in the identifier names.

224 int
225 check_identifier (word, check_word)
226  WORD_DESC *word;
227  int check_word;
228 {
229   if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
230 {
231   internal_error (_("`%s': not a valid identifier"), word->word);
232   return (0);
233 }
=>  234   else if (check_word && legal_identifier (word->word) == 0)
235 {
236   internal_error (_("`%s': not a valid identifier"), word->word);
237   return (0);
238 }
239   else
240 return (1);
241 }

>From the new shellshock patch:

350   /* Don't import function names that are invalid identifiers 
from the
351  environment. */
=>  352   if (legal_identifier (name))
353 parse_and_execute (temp_string, name, 
SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);

This check is thereby incompatible with existing behavior and scripts, and 
leads to situations where both function and export -f are happy, but running 
bash causes a function import error. As mentioned, I do not believe that this 
is required to be secure, so it would seem a shame to break scripts that have 
been functioning without issue for almost a decade.

$ bash --norc
$ function std:echo() { echo "$@"; }
$ std:echo hello world
hello world
$ export -f std:echo
$ printenv | grep std:echo -A 1
std:echo=() {  echo "$@"
}
$ bash --norc
bash: error importing function definition for `std:echo'
$ std:echo hello world
bash: std:echo: command not found

Sincerely,
Jay Freeman (saurik)
sau...@saurik.com



Re: REGRESSION: shellshock patch rejects valid function names

2014-09-26 Thread Jay Freeman (saurik)
- "Eduardo A. Bustamante López"  wrote:

> Well, what did you expect? You're relying on undocumented features.
...
> So, fix your scripts, perhaps?

I am sorry I seem to have offended you so much to have warranted this form of 
response :(.

> It's common knowledge that if you rely on undocumented stuff, your
> code will eventually break, like it did now. It's not a regression
> though, nowhere in the manual you'll find that colons are allowed in
> function names.

Please note that I am by far not the only person who uses colons in function 
names: Google's style guide for shell actually states that using :: in function 
names to separate library names from function names and package names within 
library names is their best practice.

http://google-styleguide.googlecode.com/svn/trunk/shell.xml?showone=Function_Names#Function_Names

"Lower-case, with underscores to separate words. Separate libraries with ::. 
Parentheses are required after the function name. The keyword function is 
optional, but must be used consistently throughout a project." "If you're 
writing a package, separate package names with ::."

If we are going to be adamant that this functionality--functionality that many 
people have relied on since the dawn of bash (the earliest version of bash I 
have access to has always allowed this), functionality that the code went out 
of its way to support (that check_word flag exists SOLELY for this purpose: 
this isn't accidental), functionality that "makes sense" (as it allows function 
names to replace any normal executable command), functionality that one of the 
world's largest software companies not only uses but actively encourages 
third-parties to use--is a "duh, you shouldn't have done that, fix your s**t" 
scenario, can we at least 1) document this behavior change and 2) start a 
deprecation schedule on function/export supporting these identifiers in the 
first place?



Re: REGRESSION: shellshock patch rejects valid function names

2014-09-26 Thread Jay Freeman (saurik)
- "Ángel González"  wrote:

> The patch seems straightforward:
> 
> diff --git a/variables.c b/variables.c
> index 92a5a10..6552e69 100644
> --- a/variables.c
> +++ b/variables.c
> @@ -361,7 +361,7 @@ initialize_shell_variables (env, privmode)
...
> - if (legal_identifier (name))
> + if (check_identifier (name))
...

This patch would not work (it would not even compile if you tried it, in fact 
;P) because check_identifier takes two arguments: the second argument is 
whether to internally run legal_identifier on the name. Additionally, 
check_argument takes a WORD_DESC, not a string.

If these two issues were fixed (by using make_word or something, and then 
passing 0 or preferably posixly_correct), I am concerned that this might 
undermine the security fix itself, as check_identifier could potentially allow 
ludicrous things to be pasted in the name?

It seems, however, like SEVAL_FUNCDEF is sufficient to keep most things that 
should not happen from actually happening? I tested the attached patch against 
the following test case. It might be that I went overboard and don't actually 
need quote_escapes (I'm new to bash).

(function std:echo() { echo "$@"; }; export -f std:echo; env 'x$(date)=() { 
:;}' 'x`date`=() { :;}' 'date;x=() { date;}' ./bash --norc -c 'std:echo hello 
world')

./bash: `x$(date)': not a valid identifier
./bash: error importing function definition for `x$(date)'
./bash: `x`date`': not a valid identifier
./bash: error importing function definition for `x`date`'
./bash: warning: date;x: ignoring function definition attempt
./bash: error importing function definition for `date;x'
hello world

colon-functions-attempt-1.diff
Description: Binary data


Re: REGRESSION: shellshock patch rejects valid function names

2014-09-27 Thread Jay Freeman (saurik)
[I am terribly sorry that my In-Reply-To is wrong :/]

- "Eric Blake"  wrote:

> ... Remember, the security hole of
> Shell Shock is NOT what the function is named, but the fact that
> arbitrary variable contents were being parsed. ...

Not quite: the point of exploit can be in the variable name.

$ env 'date;x=() { :;}' bash --norc -c :
Sat Sep 27 20:40:41 UTC 2014
Segmentation fault (core dumped)
$ bash --version | head -n 1
GNU bash, version 4.2.45(1)-release (x86_64-pc-linux-gnu)

While AFAIK you can't create functions with names that eventually lead to 
dangerous variable names, this is due to a quoting requirement (to place that 
";", for example, in a function definition statement, I'd have to quote it, and 
check_identifier refuses to allow any quoted characters) that happens when 
parsing the function as it is created "in the first place" that are not quite 
so easily replicated when trying to use check_identifier to validate the name 
before importing the function (hence why, even with the patch I provided 
yesterday that verifies function names before importing using a mechanism 
similar to that used for definitions, I still rely on SEVAL_FUNCDEF to catch 
"date;x": the ; has not been "quoted", so check_identifier considers it not to 
be a problem; incidentally, this is why my original patch concept, before I 
understood the new SEVAL_FUNCDEF and verified it was sufficient as in the patch 
I provided yesterday, involved running the name itself through the parser to 
verify it was a single word).



Re: backward-kill-word is not refreshing correctly

2009-04-10 Thread Jay Freeman (saurik)
On Mar 18, 6:55 pm, m...@ice.filescope.com, zy...@ice.filescope.com
wrote:
...
>         When I type a long string of text and start pressing ctrl-W to 
> backwards-kill words, bash deletes the words but doesn't visually refresh 
> (the words still appear on the command line). This was not occurring for me 
> in the 3.x series of Bash.
>
> Repeat-By:
>         Write this text on the command line: "sample text sample text sample 
> text sample text sample text". Start pressing ctrl-W and notice it takes a 
> few kill-words before the words start disappearing.
>
> --Matt Zyzik

I having a problem similar to this. For me, kill-word /never/
refreshes the screen. Additionally, moving up/down through the command
history doesn't always cause a refresh either (in a manner
deterministic but stochastic).

I am using 4.0.17 on arm-apple-darwin9. I also cannot reproduce this
problem with bash 3.2. Unfortunately, I cannot reproduce this problem
on x86_64-unknown-linux-gnu.

I have tried building bash 4.x against ncurses 5.4 and 5.7, I have
tried compiling it against a standalone readline 6.x and using a built-
in copy, and I have tried compiling both for thumb and arm. I also
have tried copying the terminfo database off of my working x86_64 box
and I have even tried running without any terminfo database, in the
hope of determining why I can't reproduce the problem on my server.

Does anyone have any hints on what I could do to debug this? What
sections of code this might be using? I know very little about how
bash/readline/ncurses work together to handle this problem: even just
saying "check out these couple functions" could be useful, so I could
start seeing if they are getting called correctly.


Re: backward-kill-word is not refreshing correctly

2009-04-10 Thread Jay Freeman (saurik)
> > When I type a long string of text and start pressing ctrl-W to 
> > backwards-kill words, bash deletes the words but doesn't visually refresh 
> > (the words still appear on the command line). This was not occurring for me 
> > in the 3.x series of Bash.

> I having a problem similar to this. For me, kill-word /never/
> refreshes the screen. Additionally, moving up/down through the command
> history doesn't always cause a refresh either (in a manner
> deterministic but stochastic).
...
> I have tried building bash 4.x against ncurses 5.4 and 5.7, I have
> tried compiling it against a standalone readline 6.x and using a built-
> in copy, and I have tried compiling both for thumb and arm.

And, it turns out that had I tested a standalone readline 5.2, it
would have worked fine ;P. The problem was introduced somewhere in
readline between bash 3.2 and 4.0. I figured this out by playing with
bash some to figure out where it was displaying things to the screen,
and then started whittling away at the diff of readline's display.c
from 3.2 to 4.0.

In the end I managed to isolate it down to the single diff hunk that
was causing the problem. It should be made clear that I have no clue
what this code is doing, or why it was changed from 3.2 to 4.0: all I
know is that the old version worked for me, and this one did not. I am
therefore not advocating that removing it is the "correct" fix, and am
only providing this information in the hope it will help debug the
issue.

So, this patch solves my problem, and maybe it will solve Matt's as
well:

http://svn.telesphoreo.org/trunk/data/readline/lendiff.diff

While I'm at it, I highly recommend removing the extraneous CFLAGS
overrides from readline's configure.in: they break autoconf's gcc -g
detection, if nothing else.

http://svn.telesphoreo.org/trunk/data/readline/cflags.diff

Sincerely,
Jay Freeman (saurik)
sau...@saurik.com
http://www.saurik.com/




Re: backward-kill-word is not refreshing correctly

2009-04-11 Thread Jay Freeman (saurik)

And help I will definitely attempt. Here are the requested values:

col_lendiff = 5
_rl_last_c_pos = 194
_rl_screenwidth = 126

Some random other variables, in case they end up being requested:

lendiff = 5
old = 8403456
new = 8457216
ne = 8457410
oe = 8403655
temp = 0

My cursor is definitely not past the end of my screen. This seems to be a 
bug in the way prompts are handled. I have a ludicrously complex prompt that 
has a large number of non-printing characters. This issue then only occurs 
(as one would expect) if the math works out so the total number of 
characters in the prompt (/including non-printing ones/) plus my true cursor 
offset from the prompt is past the edge of the screen, but isn't /actually/.


And yes, I am definitely being very careful about using \[ and \] to bound 
my non-printable characters. I even got it down to this very trivial test 
case, where ... indicates "more numbers to fill space here", so I could 
easily see "yes, the \[ and \] are placed correctly". ;P


PS1=$'0123456789...0123456789\\[\e[0m\\]'

However, even given this knowledge, the bug remains unreproducable on my 
amd64 box. I have, however, found someone using FreeBSD who said he was 
seeing related-sounding issues with Bash 4.x, and I know he's also using 
colored prompts. I am also now confident this is the same problem Matt was 
having, as once he had killed enough words to get out of the danger region 
(his prompt was probably not as ludicrous as mine), it started working 
again.


Also, while looking into this (in the hope of reproducing it on Linux), I 
noticed that in builtins/Makefile.in, LDFLAGS_FOR_BUILD uses LDFLAGS which 
uses CFLAGS... which is the CFLAGS for the target, not for the build. This 
became a problem as I tried to do a 32-bit build of bash (using 
CFLAGS='-O2 -m32 -g') and mkbuiltins.o was compiled without -m32 (as it uses 
CCFLAGS_FOR_BUILD, which bypasses CFLAGS to use BASE_CCFLAGS) but was being 
linked with -m32. I do not yet have a correct fix for this unrelated issue.


Sincerely,
Jay Freeman (saurik)
sau...@saurik.com
http://www.saurik.com/

- Original Message ----- 
From: "Chet Ramey" 

To: "Jay Freeman (saurik)" 
Cc: ; ; 
Sent: Saturday, April 11, 2009 9:14 AM
Subject: Re: backward-kill-word is not refreshing correctly
...

I can't reproduce the problem, and it seems to only appear in builds
for your iphone.  I'm going to need help with it. :-)

Please check the values of _rl_last_c_pos and _rl_screenwidth when this
code is executed and the problem occurs.  It's likely that the former is
set incorrectly somewhere, but I can't tell that for sure yet.

Chet

--
``The lyf so short, the craft so long to lerne.'' - Chaucer

Chet Ramey, ITS, CWRUc...@case.edu 
http://cnswww.cns.cwru.edu/~chet/








Re: pipefail with SIGPIPE/EPIPE

2017-03-23 Thread Jay Freeman (saurik)
> Errexit (a.k.a. set -e) is horrible,
> and you should not be using it in any new shell scripts you write.
> It exists solely for support of legacy scripts.

Wow. For those of us who don't know this, what should we be using instead? Is 
using a trap on ERR any better? Is your suggestion that || exit 1 be added to 
the end of every command?

(Potentially of mild interest is this thread on Hacker News from earlier today, 
where multiple people are suggesting the usage of "set -e" along with "set -u" 
and "set -o pipefile".)

https://news.ycombinator.com/item?id=13940322