Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 404013

Summary: sys-apps/sandbox violation triggers infinite recursion from library constructor function
Product: Portage Development Reporter: Mike Gilbert <floppym>
Component: SandboxAssignee: Sandbox Maintainers <sandbox>
Status: VERIFIED FIXED    
Severity: normal CC: ryao
Priority: Normal    
Version: unspecified   
Hardware: All   
OS: Linux   
Whiteboard:
Package list:
Runtime testing required: ---

Description Mike Gilbert gentoo-dev 2012-02-16 04:54:37 UTC
I ran into an odd issue building grub-9999 against libzfs (sys-fs/zfs). I've simplified the issue below.

Basically, if a function with a constructor attribute in a shared library violates the sandbox restrictions, we can end up triggering an infinite recursion scenario.

For example. take fictional library libfoo with constuctor libfoo_init:

1. libfoo_init() is called before libsb_init(), so sb_unwrapped_open still points to open. See note [1] below.
2. libfoo_init() calls mkdir("/foo")
3. mkdir is wrapped by mkdir_DEFAULT
4. before_syscall
5. check_syscall; access fails
6. write_logfile
7. sb_open("/var/log/sandbox/...")
8. open("/var/log/sandbox/...")
9. open is wrapped by open_DEFAULT
10. before_syscall
11. check_syscall; access fails
12. write_logfile
13. sb_open("/var/log/sandbox/...")
14. open("/var/log/sandbox/...")
15. open is wrapped by open_DEFAULT
16. Repeat 10-15 until we run out of stack and segfault.

When threads are involved (as in libzfs), we end up locking somewhere and the sandbox code basically deadlocks instead of recursing. I haven't debugged this to see what is happening there.

I think we could avoid this by calling libsb_init() from before_syscall() or check_syscall(). I tried inserting it at the top of before_syscall, and that seemed to work.

DISCLAIMER: I don't normally work with stuff this low-level, so I may not actually know what I'm talking about.

[1] Based on a quick google search, it seems the run order of constructors in different compilation units is undefined. So, libsb_init() is not guaranteed to run before libfoo_init().

http://sources.redhat.com/ml/libc-help/2009-06/msg00000.html
Comment 1 Mike Gilbert gentoo-dev 2012-02-16 04:56:55 UTC
I have uploaded my simple test case to my devspace if you would like to try it for yourself.

http://dev.gentoo.org/~floppym/sandboxtest.tar
Comment 2 SpanKY gentoo-dev 2012-03-05 07:18:23 UTC
the constructor we're using atm lacks priory, so it runs in an arbitrary order

does it work if you do:
-__attribute__((constructor))
+__attribute__((constructor(0)))
Comment 3 Mike Gilbert gentoo-dev 2012-03-05 15:30:53 UTC
(In reply to comment #2)

Nope, same result.
Comment 4 SpanKY gentoo-dev 2012-03-05 21:23:03 UTC
should be fixed by:
http://git.overlays.gentoo.org/gitweb/?p=proj/sandbox.git;a=commitdiff;h=5498907383c7f1654188b6a0d02d8b03112a28c3

(really this just needed sbio_open to get initialized in the data section, but i figured might as well move as much out as possible while i was there)
Comment 5 Mike Gilbert gentoo-dev 2012-03-05 22:24:15 UTC
Confirmed. Thanks!
Comment 6 SpanKY gentoo-dev 2013-02-25 04:24:31 UTC
(In reply to comment #4)

unfortunately, that fix broke a different use case.  if an app starts up and doesn't make any syscalls before main() and modifies the env, things don't get initialized properly.  like `env -i env`.

fixed thusly:
http://git.overlays.gentoo.org/gitweb/?p=proj/sandbox.git;a=commit;h=d8b21b35fd536af8411975ad05eab85f89e84a2e

you might want to double check i didn't re-break you