* __thread and fork() is a big no-no
@ 2013-01-15 20:35 Eric Paris
2013-01-15 21:01 ` Stephen Smalley
0 siblings, 1 reply; 5+ messages in thread
From: Eric Paris @ 2013-01-15 20:35 UTC (permalink / raw)
To: selinux
Looking at the set*createcon cache patch we realized it wasn't working
right. Quickly putting together a test program we found that:
static __thread pid_t tid = 0;
int main(void)
{
pid_t child;
tid = syscall(__NR_gettid);
printf("parent=%d\n", tid);
child = fork();
if (child == 0)
printf("child=%d\n", tid);
return 0;
}
We expected to get results like:
parent=6500
child=0
Instead you find result like:
parent=6500
child=6500
Thread local storage is NOT initialized across fork(). It's always been
known that threads and fork() don't play well together:
http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
But we weren't threading the parent or the child, so we expected it to
work. Instead we've had to add a call to pthread_atfork() which
explicitly resets tid at fork. Basically just:
static void clear(void)
{
tid = 0;
}
int main(void)
{
...
int rc;
rc = pthread_atfork(NULL, NULL, clear);
if (rc)
return rc;
...
}
We actually call this ptherad_atfork() inside the init_procattr()
function which is only called once. I'm wondering if we suffer from the
same problems with __thread variables and fork() in the library callers
elsewhere in the code. I'll take a look.
Just letting folks know something interesting we found yesterday, in
case they find it interesting...
-Eric
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: __thread and fork() is a big no-no
2013-01-15 20:35 __thread and fork() is a big no-no Eric Paris
@ 2013-01-15 21:01 ` Stephen Smalley
2013-01-15 21:11 ` Stephen Smalley
0 siblings, 1 reply; 5+ messages in thread
From: Stephen Smalley @ 2013-01-15 21:01 UTC (permalink / raw)
To: Eric Paris; +Cc: selinux
On 01/15/2013 03:35 PM, Eric Paris wrote:
> Looking at the set*createcon cache patch we realized it wasn't working
> right. Quickly putting together a test program we found that:
>
> static __thread pid_t tid = 0;
>
> int main(void)
> {
> pid_t child;
>
> tid = syscall(__NR_gettid);
> printf("parent=%d\n", tid);
>
> child = fork();
> if (child == 0)
> printf("child=%d\n", tid);
> return 0;
> }
>
> We expected to get results like:
> parent=6500
> child=0
>
> Instead you find result like:
> parent=6500
> child=6500
>
> Thread local storage is NOT initialized across fork(). It's always been
> known that threads and fork() don't play well together:
> http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
>
> But we weren't threading the parent or the child, so we expected it to
> work. Instead we've had to add a call to pthread_atfork() which
> explicitly resets tid at fork. Basically just:
>
> static void clear(void)
> {
> tid = 0;
> }
>
> int main(void)
> {
> ...
> int rc;
> rc = pthread_atfork(NULL, NULL, clear);
> if (rc)
> return rc;
> ...
> }
>
> We actually call this ptherad_atfork() inside the init_procattr()
> function which is only called once. I'm wondering if we suffer from the
> same problems with __thread variables and fork() in the library callers
> elsewhere in the code. I'll take a look.
>
> Just letting folks know something interesting we found yesterday, in
> case they find it interesting...
Hmm...seems like caching things like gettid() might be frowned upon, if
this is any guide,
http://marc.info/?t=108644931500001&r=1&w=2
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: __thread and fork() is a big no-no
2013-01-15 21:01 ` Stephen Smalley
@ 2013-01-15 21:11 ` Stephen Smalley
0 siblings, 0 replies; 5+ messages in thread
From: Stephen Smalley @ 2013-01-15 21:11 UTC (permalink / raw)
To: Eric Paris; +Cc: selinux
On 01/15/2013 04:01 PM, Stephen Smalley wrote:
> On 01/15/2013 03:35 PM, Eric Paris wrote:
>> Looking at the set*createcon cache patch we realized it wasn't working
>> right. Quickly putting together a test program we found that:
>>
>> static __thread pid_t tid = 0;
>>
>> int main(void)
>> {
>> pid_t child;
>>
>> tid = syscall(__NR_gettid);
>> printf("parent=%d\n", tid);
>>
>> child = fork();
>> if (child == 0)
>> printf("child=%d\n", tid);
>> return 0;
>> }
>>
>> We expected to get results like:
>> parent=6500
>> child=0
>>
>> Instead you find result like:
>> parent=6500
>> child=6500
>>
>> Thread local storage is NOT initialized across fork(). It's always been
>> known that threads and fork() don't play well together:
>> http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
>>
>>
>> But we weren't threading the parent or the child, so we expected it to
>> work. Instead we've had to add a call to pthread_atfork() which
>> explicitly resets tid at fork. Basically just:
>>
>> static void clear(void)
>> {
>> tid = 0;
>> }
>>
>> int main(void)
>> {
>> ...
>> int rc;
>> rc = pthread_atfork(NULL, NULL, clear);
>> if (rc)
>> return rc;
>> ...
>> }
>>
>> We actually call this ptherad_atfork() inside the init_procattr()
>> function which is only called once. I'm wondering if we suffer from the
>> same problems with __thread variables and fork() in the library callers
>> elsewhere in the code. I'll take a look.
>>
>> Just letting folks know something interesting we found yesterday, in
>> case they find it interesting...
>
> Hmm...seems like caching things like gettid() might be frowned upon, if
> this is any guide,
> http://marc.info/?t=108644931500001&r=1&w=2
BTW, we used to just use /proc/self/attr there, and could conceivably go
back to using that. Then you don't need the tid. The tradeoff is
whether you care to support set*con for threads other than the thread
group leader in multi-threaded applications.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: __thread and fork() is a big no-no
@ 2013-01-15 21:58 Eric Paris
2013-01-15 22:27 ` Colin Walters
0 siblings, 1 reply; 5+ messages in thread
From: Eric Paris @ 2013-01-15 21:58 UTC (permalink / raw)
To: sds; +Cc: selinux
[-- Attachment #1: Type: text/plain, Size: 2649 bytes --]
It is not about caching tid, it is about ALL __thread variables not being cleared across fork. In this case the parent used a setfscreatecon, forked, then the child tried to use setfscreatecon! and found the cached version. But in kernel the child did not have a Sid set. Failure. __thread variables and fork() == bad stuff.
-----Original Message-----
From: Stephen Smalley [sds@tycho.nsa.gov]
Received: Tuesday, 15 Jan 2013, 4:13pm
To: Eric Paris [eparis@redhat.com]
CC: selinux@tycho.nsa.gov
Subject: Re: __thread and fork() is a big no-no
On 01/15/2013 04:01 PM, Stephen Smalley wrote:
> On 01/15/2013 03:35 PM, Eric Paris wrote:
>> Looking at the set*createcon cache patch we realized it wasn't working
>> right. Quickly putting together a test program we found that:
>>
>> static __thread pid_t tid = 0;
>>
>> int main(void)
>> {
>> pid_t child;
>>
>> tid = syscall(__NR_gettid);
>> printf("parent=%d\n", tid);
>>
>> child = fork();
>> if (child == 0)
>> printf("child=%d\n", tid);
>> return 0;
>> }
>>
>> We expected to get results like:
>> parent=6500
>> child=0
>>
>> Instead you find result like:
>> parent=6500
>> child=6500
>>
>> Thread local storage is NOT initialized across fork(). It's always been
>> known that threads and fork() don't play well together:
>> http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
>>
>>
>> But we weren't threading the parent or the child, so we expected it to
>> work. Instead we've had to add a call to pthread_atfork() which
>> explicitly resets tid at fork. Basically just:
>>
>> static void clear(void)
>> {
>> tid = 0;
>> }
>>
>> int main(void)
>> {
>> ...
>> int rc;
>> rc = pthread_atfork(NULL, NULL, clear);
>> if (rc)
>> return rc;
>> ...
>> }
>>
>> We actually call this ptherad_atfork() inside the init_procattr()
>> function which is only called once. I'm wondering if we suffer from the
>> same problems with __thread variables and fork() in the library callers
>> elsewhere in the code. I'll take a look.
>>
>> Just letting folks know something interesting we found yesterday, in
>> case they find it interesting...
>
> Hmm...seems like caching things like gettid() might be frowned upon, if
> this is any guide,
> http://marc.info/?t=108644931500001&r=1&w=2
BTW, we used to just use /proc/self/attr there, and could conceivably go
back to using that. Then you don't need the tid. The tradeoff is
whether you care to support set*con for threads other than the thread
group leader in multi-threaded applications.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: __thread and fork() is a big no-no
2013-01-15 21:58 Eric Paris
@ 2013-01-15 22:27 ` Colin Walters
0 siblings, 0 replies; 5+ messages in thread
From: Colin Walters @ 2013-01-15 22:27 UTC (permalink / raw)
To: Eric Paris; +Cc: sds, selinux
On Tue, 2013-01-15 at 16:58 -0500, Eric Paris wrote:
> It is not about caching tid, it is about ALL __thread variables not being cleared across fork.
Using pthread_atfork() is a way to ensure it *is* cleared.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-01-15 22:27 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-15 20:35 __thread and fork() is a big no-no Eric Paris
2013-01-15 21:01 ` Stephen Smalley
2013-01-15 21:11 ` Stephen Smalley
-- strict thread matches above, loose matches on Subject: below --
2013-01-15 21:58 Eric Paris
2013-01-15 22:27 ` Colin Walters
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.