Bug 72922 - linux emulation: suid/sgid threaded applications hang
Summary: linux emulation: suid/sgid threaded applications hang
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 5.2.1-RELEASE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-emulation (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-10-20 13:10 UTC by Andriy Gapon
Modified: 2005-03-18 09:50 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andriy Gapon 2004-10-20 13:10:31 UTC
linux applications using old linux threads (pre-NPTL) use signal 32 
(linux SIGRTMIN) for communication between thread-processes.
If such an linux application is installed suid or sgid and security.bsd.conservative_signals=1 (default),
then permission will be denied to send such a signal and the application will freeze.
Please see
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=13492+0+archive/2004/freebsd-emulation/20041017.freebsd-emulation
for an example and detailed investigation of such case.

Fix: 

1. either add signal 32 (linux SIGRTMIN) to list of "common signals" in cr_cansignal()
2. or detect the described situation in cr_cansignal() and produce a 
warning message explaining the situation and suggesting setting 
security.bsd.conservative_signals=0
How-To-Repeat: using the same environment as mine 
1. make any threaded linux application suid
2. run it so that it really changes privileges
3. see it freeze
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2004-10-24 01:46:06 UTC
Responsible Changed
From-To: freebsd-bugs->emulation

Over to mailing list.
Comment 2 Maxim Sobolev freebsd_committer freebsd_triage 2005-02-11 14:03:14 UTC
State Changed
From-To: open->closed

Fix comitted, thank you for reporting!
Comment 3 Maxim Sobolev freebsd_committer freebsd_triage 2005-02-13 19:12:42 UTC
State Changed
From-To: closed->open

Sorry, but the solution is not that simple as it appeares. The following 
explains the complexity: 

On Fri, 11 Feb 2005, Maxim Sobolev wrote: 



Comment 4 Maxim Sobolev 2005-02-20 17:21:28 UTC
Andriy,

Can you please test the following patch and let me know if it help or not.

http://www.pbxpress.com/~sobomax/72922.diff

-Maxim
Comment 5 Maxim Sobolev freebsd_committer freebsd_triage 2005-03-06 22:05:43 UTC
State Changed
From-To: open->closed

Should be fixed in the recent -current. Please test and let me know if the 
problem persists.
Comment 6 Andriy Gapon 2005-03-09 09:40:54 UTC
on 20.02.2005 19:21 Maxim Sobolev said the following:
> Andriy,
> 
> Can you please test the following patch and let me know if it help or not.
> 
> http://www.pbxpress.com/~sobomax/72922.diff

Maxim,
sorry that it took me so long to try this patch, I could do reboot only
 on the past weekend and, ufortunately, this patch didn't fix the
problem with MQ, strmqm command still hangs if conservative_signals=1. I
am not sure if you commited exactly this patch or something different in
current (unfortunately I am not able to test current), but this patch
apparently does not work in this particular case. I am not sure if I
will be able to help you with debugging kernel stuff (linux kld - most
probably yes, kernel - most propbably not), but I can definitely provide
you information about this particular program, strmqm, if you need it
and if you tell me what to check for.

-- 
Andriy Gapon
Comment 7 Maxim Sobolev 2005-03-09 09:59:48 UTC
Andriy Gapon wrote:
> on 20.02.2005 19:21 Maxim Sobolev said the following:
> 
>>Andriy,
>>
>>Can you please test the following patch and let me know if it help or not.
>>
>>http://www.pbxpress.com/~sobomax/72922.diff
> 
> 
> Maxim,
> sorry that it took me so long to try this patch, I could do reboot only
>  on the past weekend and, ufortunately, this patch didn't fix the
> problem with MQ, strmqm command still hangs if conservative_signals=1. I
> am not sure if you commited exactly this patch or something different in
> current (unfortunately I am not able to test current), but this patch
> apparently does not work in this particular case. I am not sure if I
> will be able to help you with debugging kernel stuff (linux kld - most
> probably yes, kernel - most propbably not), but I can definitely provide
> you information about this particular program, strmqm, if you need it
> and if you tell me what to check for.

Hmm, that's pretty strange. Can you please fetch the following Linux 
binary, make it suid root and try to run as ordinary user on your 
system? I've used it to verify that my patch is in fact works - after 
the change has been made it stopped hanging at my system.

http://www.pbxpress.com/~sobomax/aqueue_linux

It will make sense to execute that strmqm program under ktrace(8) with 
-i flag (use ports/devel/linux_kdump to decode resulting trace) and send 
me the output of linux_kdump. Maybe your version of linuxthreads uses 
some different set of flags in linux_clone(), so that my heuristics fails.

-Maxim
Comment 8 Andriy Gapon 2005-03-09 10:57:49 UTC
on 09.03.2005 11:59 Maxim Sobolev said the following:
> Hmm, that's pretty strange. Can you please fetch the following Linux
> binary, make it suid root and try to run as ordinary user on your
> system? I've used it to verify that my patch is in fact works - after
> the change has been made it stopped hanging at my system.
> 
> http://www.pbxpress.com/~sobomax/aqueue_linux
> 
> It will make sense to execute that strmqm program under ktrace(8) with
> -i flag (use ports/devel/linux_kdump to decode resulting trace) and send
> me the output of linux_kdump. Maybe your version of linuxthreads uses
> some different set of flags in linux_clone(), so that my heuristics fails.

Maxim,

1. I've tried to follow your advice, but a new strange thing happened
(or maybe it is not strange, but I never payed attention before): "-i"
in "ktrace -i" doesn't work on suid/sgid applications, when run as
normal user:

# chmod 6550 ~/tmp/aqueue_linux
# ls -l ~/tmp/aqueue_linux
-r-sr-s---  1 avg  topspin  16804  9 ÂÅÒ 13:47 /home/avg/tmp/aqueue_linux


$ ktrace -i ~avg/tmp/aqueue_linux -n 100
pusher started
poper started
$ linux_kdump > kdump.out
$ cat kdump.out
 16103 ktrace   RET   linux_brk 0
 16103 ktrace   CALL  linux_olduname(0xbfbfea4e,0xbfbfe95c,0xbfbfe96c)
 16103 ktrace   NAMI  "/home/avg/tmp/aqueue_linux"
 16103 ktrace   NAMI  "/compat/linux/lib/ld-linux.so.2"

If I set permission back to normal executable, "-i" works again.


2. "ktrace -i" works if executed as super-user and strmqm still hangs.
Here's some relevant info, whcih makes things quite obvious:

# egrep 'fork|exec|clone|kill|signal' kdump.out
 79953 strmqm   CALL  linux_clone(0xf00,0x8099370)
 79953 strmqm   RET   linux_clone 79954/0x13852
 79954 strmqm   RET   linux_fork 0
 79954 strmqm   CALL  linux_clone(0xf21,0xbf3ffbd0)
 79954 strmqm   RET   linux_clone 79955/0x13853
 79955 strmqm   RET   linux_fork 0
 79954 strmqm   CALL  linux_kill(0x13851,0x20)
 79954 strmqm   RET   linux_kill 0
 79955 strmqm   CALL  linux_kill(0x13851,0x20)
 79955 strmqm   RET   linux_kill 0
 79955 strmqm   CALL  linux_kill(0x13851,0x20)
 79955 strmqm   RET   linux_kill 0
 79955 strmqm   CALL  linux_kill(0x13851,0x20)
 79955 strmqm   RET   linux_kill 0
        uucp:*:66:66:UUCP
pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
 79954 strmqm   CALL  linux_clone(0xf21,0xbf1ffbd0)
 79954 strmqm   RET   linux_clone 79956/0x13854
 79956 strmqm   RET   linux_fork 0
 79954 strmqm   CALL  linux_kill(0x13851,0x20)
 79954 strmqm   RET   linux_kill 0
 79956 strmqm   CALL  linux_kill(0x13851,0x20)
 79956 strmqm   RET   linux_kill 0
 79953 strmqm   CALL  linux_kill(0x13854,0x20)
 79953 strmqm   RET   linux_kill 0
 79956 strmqm   CALL  linux_kill(0x13851,0x20)
 79956 strmqm   RET   linux_kill 0
 79956 strmqm   CALL  linux_kill(0x13851,0x20)
 79956 strmqm   RET   linux_kill 0
 79953 strmqm   CALL  linux_kill(0x13853,0x1c)
 79953 strmqm   RET   linux_kill RESTART
        permitted' from pthread_kill.)
        |   ('1 - Operation not permitted' from pthread_kill.)
              | "
       "| Comment1          :- '1 - Operation not permitted' from
pthread_kill.       |
 79954 strmqm   CALL  linux_kill(0x13854,0x21)
 79954 strmqm   RET   linux_kill RESTART
 79954 strmqm   CALL  linux_kill(0x13853,0x21)
 79954 strmqm   RET   linux_kill RESTART

Looks like signal 32 is OK, but there are 28 and 33 in addition to it.
33 seems to be another Linux real-time signal and is probably used with
linux threads for some purpose. Here's what I read in signal(7) Linux
man page:
<<<
Linux supports real-time signals as originally defined in the POSIX.4
real-time extensions (and now included in POSIX 1003.1-2001). Linux
supports 32 real-time signals, numbered from 32 (SIGRTMIN) to 63
(SIGRTMAX). (Programs should always refer to real-time signals using
notation SIGRTMIN+n, since the range of real-time signal numbers varies
across Unices.)

Unlike standard signals, real-time signals have no predefined meanings:
the entire set of real-time signals can be used for application-defined
purposes.

(Note, however, that the LinuxThreads implementation uses the first
three real-time signals.)
>>>>
So probably 32,33,34 should be subject to your patch.

I am not sure what signal 28 (SIGWINCH?) is used for (in this case), but
most probably it is not thread-related and not application critical,
because execution continues after that signal, but an error message is
logged.

-- 
Andriy Gapon
Comment 9 Maxim Sobolev 2005-03-10 12:56:41 UTC
I see. Try to replace the following line in kern_prot.c:

  if (signum == SIGTHR && td->td_proc->p_leader != NULL &&

with the following:

  if (signum >= SIGTHR && td->td_proc->p_leader != NULL &&

And let me know if it helps.

BTW, would be be interested in getting FreeBSD commit bit, so that you 
can do the work by yourself? ;-)

-Maxim

Andriy Gapon wrote:
> on 09.03.2005 11:59 Maxim Sobolev said the following:
> 
>>Hmm, that's pretty strange. Can you please fetch the following Linux
>>binary, make it suid root and try to run as ordinary user on your
>>system? I've used it to verify that my patch is in fact works - after
>>the change has been made it stopped hanging at my system.
>>
>>http://www.pbxpress.com/~sobomax/aqueue_linux
>>
>>It will make sense to execute that strmqm program under ktrace(8) with
>>-i flag (use ports/devel/linux_kdump to decode resulting trace) and send
>>me the output of linux_kdump. Maybe your version of linuxthreads uses
>>some different set of flags in linux_clone(), so that my heuristics fails.
> 
> 
> Maxim,
> 
> 1. I've tried to follow your advice, but a new strange thing happened
> (or maybe it is not strange, but I never payed attention before): "-i"
> in "ktrace -i" doesn't work on suid/sgid applications, when run as
> normal user:
> 
> # chmod 6550 ~/tmp/aqueue_linux
> # ls -l ~/tmp/aqueue_linux
> -r-sr-s---  1 avg  topspin  16804  9 ÂÅÒ 13:47 /home/avg/tmp/aqueue_linux
> 
> 
> $ ktrace -i ~avg/tmp/aqueue_linux -n 100
> pusher started
> poper started
> $ linux_kdump > kdump.out
> $ cat kdump.out
>  16103 ktrace   RET   linux_brk 0
>  16103 ktrace   CALL  linux_olduname(0xbfbfea4e,0xbfbfe95c,0xbfbfe96c)
>  16103 ktrace   NAMI  "/home/avg/tmp/aqueue_linux"
>  16103 ktrace   NAMI  "/compat/linux/lib/ld-linux.so.2"
> 
> If I set permission back to normal executable, "-i" works again.
> 
> 
> 2. "ktrace -i" works if executed as super-user and strmqm still hangs.
> Here's some relevant info, whcih makes things quite obvious:
> 
> # egrep 'fork|exec|clone|kill|signal' kdump.out
>  79953 strmqm   CALL  linux_clone(0xf00,0x8099370)
>  79953 strmqm   RET   linux_clone 79954/0x13852
>  79954 strmqm   RET   linux_fork 0
>  79954 strmqm   CALL  linux_clone(0xf21,0xbf3ffbd0)
>  79954 strmqm   RET   linux_clone 79955/0x13853
>  79955 strmqm   RET   linux_fork 0
>  79954 strmqm   CALL  linux_kill(0x13851,0x20)
>  79954 strmqm   RET   linux_kill 0
>  79955 strmqm   CALL  linux_kill(0x13851,0x20)
>  79955 strmqm   RET   linux_kill 0
>  79955 strmqm   CALL  linux_kill(0x13851,0x20)
>  79955 strmqm   RET   linux_kill 0
>  79955 strmqm   CALL  linux_kill(0x13851,0x20)
>  79955 strmqm   RET   linux_kill 0
>         uucp:*:66:66:UUCP
> pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
>  79954 strmqm   CALL  linux_clone(0xf21,0xbf1ffbd0)
>  79954 strmqm   RET   linux_clone 79956/0x13854
>  79956 strmqm   RET   linux_fork 0
>  79954 strmqm   CALL  linux_kill(0x13851,0x20)
>  79954 strmqm   RET   linux_kill 0
>  79956 strmqm   CALL  linux_kill(0x13851,0x20)
>  79956 strmqm   RET   linux_kill 0
>  79953 strmqm   CALL  linux_kill(0x13854,0x20)
>  79953 strmqm   RET   linux_kill 0
>  79956 strmqm   CALL  linux_kill(0x13851,0x20)
>  79956 strmqm   RET   linux_kill 0
>  79956 strmqm   CALL  linux_kill(0x13851,0x20)
>  79956 strmqm   RET   linux_kill 0
>  79953 strmqm   CALL  linux_kill(0x13853,0x1c)
>  79953 strmqm   RET   linux_kill RESTART
>         permitted' from pthread_kill.)
>         |   ('1 - Operation not permitted' from pthread_kill.)
>               | "
>        "| Comment1          :- '1 - Operation not permitted' from
> pthread_kill.       |
>  79954 strmqm   CALL  linux_kill(0x13854,0x21)
>  79954 strmqm   RET   linux_kill RESTART
>  79954 strmqm   CALL  linux_kill(0x13853,0x21)
>  79954 strmqm   RET   linux_kill RESTART
> 
> Looks like signal 32 is OK, but there are 28 and 33 in addition to it.
> 33 seems to be another Linux real-time signal and is probably used with
> linux threads for some purpose. Here's what I read in signal(7) Linux
> man page:
> <<<
> Linux supports real-time signals as originally defined in the POSIX.4
> real-time extensions (and now included in POSIX 1003.1-2001). Linux
> supports 32 real-time signals, numbered from 32 (SIGRTMIN) to 63
> (SIGRTMAX). (Programs should always refer to real-time signals using
> notation SIGRTMIN+n, since the range of real-time signal numbers varies
> across Unices.)
> 
> Unlike standard signals, real-time signals have no predefined meanings:
> the entire set of real-time signals can be used for application-defined
> purposes.
> 
> (Note, however, that the LinuxThreads implementation uses the first
> three real-time signals.)
> 
> So probably 32,33,34 should be subject to your patch.
> 
> I am not sure what signal 28 (SIGWINCH?) is used for (in this case), but
> most probably it is not thread-related and not application critical,
> because execution continues after that signal, but an error message is
> logged.
>
Comment 10 Andriy Gapon 2005-03-10 13:10:13 UTC
on 10.03.2005 14:56 Maxim Sobolev said the following:
> I see. Try to replace the following line in kern_prot.c:
> 
>  if (signum == SIGTHR && td->td_proc->p_leader != NULL &&
> 
> with the following:
> 
>  if (signum >= SIGTHR && td->td_proc->p_leader != NULL &&
> 
> And let me know if it helps.

that's what came to my mind too, but unfortunately I will only be able
to try it in a week or two.

> BTW, would be be interested in getting FreeBSD commit bit, so that you
> can do the work by yourself? ;-)

I have always dreamt about it, but I feel like it is more responsibility
than I can take now. Unfortunately, I am also too short of capabilities
to test kernel changes. Thank you, maybe later.

-- 
Andriy Gapon
Comment 11 Andriy Gapon 2005-03-18 09:44:00 UTC
on 10.03.2005 14:56 Maxim Sobolev said the following:
> I see. Try to replace the following line in kern_prot.c:
> 
>  if (signum == SIGTHR && td->td_proc->p_leader != NULL &&
> 
> with the following:
> 
>  if (signum >= SIGTHR && td->td_proc->p_leader != NULL &&
> 
> And let me know if it helps.
> 

Maxim,

this has fixed the problem completely, thank you.
As to your other question, I need to gather my thoughts on it :-)

-- 
Andriy Gapon