2008-08-18 14:09:47

by Pavel Emelyanov

[permalink] [raw]
Subject: Re: [PATCH] binfmt_misc.c: avoid potential kernel stack overflow

(Put lkml in Cc. The original message is beyond)

Oops! My fault. The problem is that in case of modularized binfmt,
the appropriate binary handler gets registered _before_ the script
one and sets the misc_bang flag even too early.

Thus when we launch a script the load_misc_binary sets this bang,
then returns error, since the binary is actually a script, then the
load_script_binary successfully loads the script, then it loads the
misc binary again, which exits with the -ENOEXEC error due to bang
set.

This patch helped my box, what about yours?

diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 7562053..8d7e88e 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -120,8 +120,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
if (bprm->misc_bang)
goto _ret;

- bprm->misc_bang = 1;
-
/* to keep locking time low, we copy the interpreter string */
read_lock(&entries_lock);
fmt = check_file(bprm);
@@ -199,6 +197,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
if (retval < 0)
goto _error;

+ bprm->misc_bang = 1;
+
retval = search_binary_handler (bprm, regs);
if (retval < 0)
goto _error;

> On Tue, Apr 29, 2008 at 12:59:24AM -0700, Pavel Emelyanov wrote:
>> This can be triggered with root help only, but...
>>
>> Register the ":text:E::txt::/root/cat.txt:' rule in binfmt_misc (by root) and
>> try launching the cat.txt file (by anyone) :) The result is - the endless
>> recursion in the load_misc_binary -> open_exec -> load_misc_binary chain and
>> stack overflow.
>>
>> There's a similar problem with binfmt_script, and there's a sh_bang memner on
>> linux_binprm structure to handle this, but simply raising this in binfmt_misc
>> may break some setups when the interpreter of some misc binaries is a script.
>>
>> So the proposal is to turn sh_bang into a bit, add a new one (the misc_bang)
>> and raise it in load_misc_binary. After this, even if we set up the misc ->
>> script -> misc loop for binfmts one of them will step on its own bang and
>> exit.
>
> This patch causes problem in some cases, if the kernel compiled with
> CONFIG_BINFMT_MISC=m:
>
> $ pwd
> /tmp/chroot
> $ cat test0.c
> #include <stdio.h>
>
> int main(void)
> {
> printf("test\n");
> return 0;
> }
> $ gcc test0.c -o test0 -static
> $ sudo sh -c 'echo ":test:M::123::/test0:" > /proc/sys/fs/binfmt_misc/register'
> $ cat test1
> 123
> $ cat test2
> #!/test1
> $ sudo chroot /tmp/chroot /test2
> chroot: cannot run command `/test2': No such file or directory
> $ sudo strace chroot /tmp/chroot /test2
> ...
> execve("/test2", ["/test2"], [/* 54 vars */]) = -1 ENOEXEC (Exec format error)
> ...
>
> This test works fine if I revert the patch or compile with CONFIG_BINFMT_MISC=y.
>


2008-08-18 14:44:48

by Kirill A. Shutemov

[permalink] [raw]
Subject: Re: [PATCH] binfmt_misc.c: avoid potential kernel stack overflow

On Mon, Aug 18, 2008 at 06:09:23PM +0400, Pavel Emelyanov wrote:
> (Put lkml in Cc. The original message is beyond)
>
> Oops! My fault. The problem is that in case of modularized binfmt,
> the appropriate binary handler gets registered _before_ the script
> one and sets the misc_bang flag even too early.
>
> Thus when we launch a script the load_misc_binary sets this bang,
> then returns error, since the binary is actually a script, then the
> load_script_binary successfully loads the script, then it loads the
> misc binary again, which exits with the -ENOEXEC error due to bang
> set.
>
> This patch helped my box, what about yours?

It works. Thank you.

Reported-and-tested-by: Kirill A. Shutemov <[email protected]>

I have noticed yet another problem: more than one bit of sh_bang can be
used on alpha:

fs/exec.c
1189 return retval;
1190
1191 /* Remember if the application is TASO. */
1192 bprm->sh_bang = eh->ah.entry < 0x100000000UL;
1193
1194 bprm->file = file;


--
Regards, Kirill A. Shutemov
+ Belarus, Minsk
+ ALT Linux Team, http://www.altlinux.com/


Attachments:
(No filename) (1.13 kB)
signature.asc (197.00 B)
Digital signature
Download all attachments

2008-08-18 14:51:56

by Kirill A. Shutemov

[permalink] [raw]
Subject: Re: [PATCH] binfmt_misc.c: avoid potential kernel stack overflow

On Mon, Aug 18, 2008 at 05:44:19PM +0300, Kirill A. Shutemov wrote:
> I have noticed yet another problem: more than one bit of sh_bang can be
> used on alpha:
>
> fs/exec.c
> 1189 return retval;
> 1190
> 1191 /* Remember if the application is TASO. */
> 1192 bprm->sh_bang = eh->ah.entry < 0x100000000UL;
> 1193
> 1194 bprm->file = file;

Sorry. Please ignore this part of the message. %)

--
Regards, Kirill A. Shutemov
+ Belarus, Minsk
+ ALT Linux Team, http://www.altlinux.com/


Attachments:
(No filename) (561.00 B)
signature.asc (197.00 B)
Digital signature
Download all attachments

2008-08-18 23:21:00

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] binfmt_misc.c: avoid potential kernel stack overflow

On Mon, 18 Aug 2008 18:09:23 +0400
Pavel Emelyanov <[email protected]> wrote:

> (Put lkml in Cc. The original message is beyond)
>
> Oops! My fault. The problem is that in case of modularized binfmt,
> the appropriate binary handler gets registered _before_ the script
> one and sets the misc_bang flag even too early.
>
> Thus when we launch a script the load_misc_binary sets this bang,
> then returns error, since the binary is actually a script, then the
> load_script_binary successfully loads the script, then it loads the
> misc binary again, which exits with the -ENOEXEC error due to bang
> set.
>
> This patch helped my box, what about yours?
>
> diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
> index 7562053..8d7e88e 100644
> --- a/fs/binfmt_misc.c
> +++ b/fs/binfmt_misc.c
> @@ -120,8 +120,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
> if (bprm->misc_bang)
> goto _ret;
>
> - bprm->misc_bang = 1;
> -
> /* to keep locking time low, we copy the interpreter string */
> read_lock(&entries_lock);
> fmt = check_file(bprm);
> @@ -199,6 +197,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
> if (retval < 0)
> goto _error;
>
> + bprm->misc_bang = 1;
> +
> retval = search_binary_handler (bprm, regs);
> if (retval < 0)
> goto _error;

<scrabble, hunt>

I put together the below description. It has no signed-off-by: (yet).
Has this been sufficiently well tested and checked to be in a merge-ready
state?

Thanks.



From: Pavel Emelyanov <[email protected]>

Fix a regression introduced by 3a2e7f47d71e1df86acc1dda6826890b6546a4e1
("binfmt_misc.c: avoid potential kernel stack overflow").

In the case of modularized binfmt, the appropriate binary handler gets
registered _before_ the script one and sets the misc_bang flag even too
early.

Thus when we launch a script the load_misc_binary sets this bang, then
returns error, since the binary is actually a script, then the
load_script_binary successfully loads the script, then it loads the misc
binary again, which exits with the -ENOEXEC error due to bang set.

Reported-and-tested-by: Kirill A. Shutemov <[email protected]>
Cc: <[email protected]> [2.6.26.x]
Signed-off-by: Andrew Morton <[email protected]>
---

fs/binfmt_misc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff -puN fs/binfmt_misc.c~binfmt_miscc-avoid-potential-kernel-stack-overflow fs/binfmt_misc.c
--- a/fs/binfmt_misc.c~binfmt_miscc-avoid-potential-kernel-stack-overflow
+++ a/fs/binfmt_misc.c
@@ -120,8 +120,6 @@ static int load_misc_binary(struct linux
if (bprm->misc_bang)
goto _ret;

- bprm->misc_bang = 1;
-
/* to keep locking time low, we copy the interpreter string */
read_lock(&entries_lock);
fmt = check_file(bprm);
@@ -199,6 +197,8 @@ static int load_misc_binary(struct linux
if (retval < 0)
goto _error;

+ bprm->misc_bang = 1;
+
retval = search_binary_handler (bprm, regs);
if (retval < 0)
goto _error;
_

2008-08-19 10:09:19

by Pavel Emelyanov

[permalink] [raw]
Subject: Re: [PATCH] binfmt_misc.c: avoid potential kernel stack overflow

Andrew Morton wrote:
> On Mon, 18 Aug 2008 18:09:23 +0400
> Pavel Emelyanov <[email protected]> wrote:
>
>> (Put lkml in Cc. The original message is beyond)
>>
>> Oops! My fault. The problem is that in case of modularized binfmt,
>> the appropriate binary handler gets registered _before_ the script
>> one and sets the misc_bang flag even too early.
>>
>> Thus when we launch a script the load_misc_binary sets this bang,
>> then returns error, since the binary is actually a script, then the
>> load_script_binary successfully loads the script, then it loads the
>> misc binary again, which exits with the -ENOEXEC error due to bang
>> set.
>>
>> This patch helped my box, what about yours?
>>
>> diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
>> index 7562053..8d7e88e 100644
>> --- a/fs/binfmt_misc.c
>> +++ b/fs/binfmt_misc.c
>> @@ -120,8 +120,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
>> if (bprm->misc_bang)
>> goto _ret;
>>
>> - bprm->misc_bang = 1;
>> -
>> /* to keep locking time low, we copy the interpreter string */
>> read_lock(&entries_lock);
>> fmt = check_file(bprm);
>> @@ -199,6 +197,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
>> if (retval < 0)
>> goto _error;
>>
>> + bprm->misc_bang = 1;
>> +
>> retval = search_binary_handler (bprm, regs);
>> if (retval < 0)
>> goto _error;
>
> <scrabble, hunt>
>
> I put together the below description. It has no signed-off-by: (yet).

Well, sorry for that, I just wanted to get the Kirill's approval of the
fix, while testing other things myself. I sent the properly formatted
patch later. So can you, please, pick the comment and/or subject from
that one (which is a bit less messy, I think)?

> Has this been sufficiently well tested and checked to be in a merge-ready
> state?

I have checked different combinations, so I believe it has.

> Thanks.

Thanks,
Pavel