Bug 72755 - LibreOffice refuses to start without exec rights on ~ and /tmp
Summary: LibreOffice refuses to start without exec rights on ~ and /tmp
Status: RESOLVED FIXED
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: LibreOffice (show other bugs)
Version:
(earliest affected)
4.1.3.2 release
Hardware: x86-64 (AMD64) Linux (All)
: medium normal
Assignee: Stephan Bergmann
URL:
Whiteboard: target:4.5.0
Keywords:
Depends on:
Blocks:
 
Reported: 2013-12-16 11:34 UTC by henning mueller
Modified: 2015-01-16 12:44 UTC (History)
4 users (show)

See Also:
Crash report or crash signature:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description henning mueller 2013-12-16 11:34:03 UTC
Problem description:

I'm running Linux with the grsecurity patchset, which can prevent programs or scripts from starting, if they are in a world-writable directory or in one not owned by root.

When I start LibreOffice (for example with "libreoffice" from the terminal), it tries to run "$HOME/.execoooyiXWrf" and afterwards (as a failsave?) "/tmp/.execooouzDaC0". This is prevented and LibreOffice fails with:

The application can not be started.
Extension Manager: exception in synchronize

Is it necessary, LibreOffice executes those temporary scripts or binaries? Can it be deactivated somehow?


Steps to reproduce:

1. Start a grsecurity enabled kernel.
2. Ensure "Trusted Path Execution" is enabled for your user.
3. Run "libreoffice" from the terminal.


Platform:

* LibreOffice 4.1.3
* Linux 3.12.5
* grsecurity 3.0, 201312151212
* Arch Linux
Comment 1 Stephan Bergmann 2013-12-16 13:43:51 UTC
Note that LibreOffice itself does not come with an executable named "libreoffice", so this might be an artefact of how LibreOffice is packaged up for Arch Linux.
Comment 2 henning mueller 2013-12-16 14:13:22 UTC
When Trusted Path Execution is enabled and the temporary executable therefor can not be run, LibreOffice tries to create an executable anonymous mmap.

To get it running in grsecurity, either deactivating Trusted Path Execution or MPROTECT for soffice.bin (which allows it to call mprotect with RWX on an anonymous mapping) is necessary.

Is this RWX mmap very important? Maybe related to Java?

(Sounds a little unlikely, this issue could be solved easily.)
Comment 3 Stephan Bergmann 2013-12-16 14:42:35 UTC
Ach, right, the ".execooo" pattern looked familiar but I'd forgotten where it is used: bridges::cpp_uno::shared::VtableFactory::createBlock in bridges/source/cpp_uno/shared/vtablefactory.cxx is the code that creates those files in either $HOME or /tmp.  The files are necessary to obtain memory that is (first) writeable and (then) executable under SELinux (<https://issues.apache.org/ooo/show_bug.cgi?id=97320> "bridges: merge in Red Hat selinux support"), to synthesize C++ vtables for the C++--binary-UNO bridge.

An obvious change would be to use $TMPDIR if set instead of hardcoding /tmp only.  Will "Trusted Path Execution" ensure that TMPDIR points to a suitable directory so that this issue would be solved then?
Comment 4 henning mueller 2013-12-16 15:16:39 UTC
No, TPE prevents any execution of "files that are not in root-owned directories writable only by root" (quote from kernel config help of TPE) if activated most strictly.

"If the program really needs this behavior there is no really easy way out", because TPE is designed exactly to prevent the circumvention of RWX mmap as described here <https://issues.apache.org/ooo/show_bug.cgi?id=97320>.
Comment 5 Bryan Quigley 2014-03-18 04:30:00 UTC
I'm trying to figure out how important this is as well, to help in apparmoring LO.  Right now the .exec fails and the libreoffice still comes up, but I don't see it falling back to /tmp.  Can this just be removed?

See bug here: https://bugs.launchpad.net/ubuntu/+source/libreoffice/+bug/1284507
Comment 6 Andrei Cristian Petcu 2014-09-04 14:17:52 UTC
Hi, I have a similar issue on a Ubuntu GNU/Linux 14.04 headless server. LibreOffice 4.2.6.3 420m0(Build:3). I don't think I have grsecurity.

$uname -a
Linux HI14485 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

I want to convert a file with libreoffice in headless mode. I can do this with my user but not with tomcat7 user.

# all ok with my user
$sudo -u my_user libreoffice --headless --convert-to pdf /tmp/Replicate.ppt --outdir /tmp
convert /tmp/Replicate.ppt -> /tmp/Replicate.pdf using impress_pdf_Export

# with tomcat7 I get an error
$ sudo -u tomcat7 libreoffice --headless --convert-to pdf /tmp/Replicate.ppt --outdir /tmp
[Java framework] Error in function createSettingsDocument (elements.cxx).
javaldx failed!
Warning: failed to read path from javaldx
mkstemp("/home/my_user/.execoooNqjoex") failed: Permission denied
# application hangs

Do you think this is related to the current bug? Any ideas on finding a workaround? Thank you!
Comment 7 Stephan Bergmann 2014-09-05 07:31:26 UTC
(In reply to comment #6)
> # with tomcat7 I get an error
> $ sudo -u tomcat7 libreoffice --headless --convert-to pdf /tmp/Replicate.ppt
> --outdir /tmp
> [Java framework] Error in function createSettingsDocument (elements.cxx).
> javaldx failed!
> Warning: failed to read path from javaldx
> mkstemp("/home/my_user/.execoooNqjoex") failed: Permission denied
> # application hangs
> 
> Do you think this is related to the current bug? Any ideas on finding a
> workaround? Thank you!

You run libreoffice with the HOME env var still pointing to ~my_user, not ~tomcat7, so results are "as expected."  sudo's -H switch should take care of that.
Comment 8 Bryan Quigley 2014-09-24 03:43:31 UTC
In trying to help mitigate this (at least to make it easier for AppArmoring).  I was going to propose moving it to $XDG_RUNTIME_DIR, /run/user/1000.  Unfortunately, that won't work because it's (at least on Ubuntu) default mounted to noexec.

I'm considering moving it to /tmp by default.  I don't quite see the point in trying the home directory first.   Any thoughts either way?
Comment 9 Stephan Bergmann 2014-09-24 08:34:54 UTC
(In reply to comment #5)
> I'm trying to figure out how important this is as well, to help in
> apparmoring LO.  Right now the .exec fails and the libreoffice still comes
> up, but I don't see it falling back to /tmp.  Can this just be removed?

What exactly do you mean with "the .exec fails"?  Looking at the #ifdef USE_DOUBLE_MMAP definition of VtableFactory::createBlock in bridges/source/cpp_uno/shared/vtablefactory.cxx, there are four different things that can go wrong:

1  mkstemp fails
2  posix_fallocate resp. ftruncate fails
3  mmap(..., PROT_READ|PROT_WRITE, ...) fails
4  mmap(..., PROT_READ|PROT_EXEC, ...) fails

If (1) or (2) fails when trying $HOME, it will apparently not try again with /tmp, but just use a plain (read, write, non-exec) allocation.

Such a non-exec fallback allocation would make creation of the synthesized vtable work, but only when LO would later try to make a call via that vtable, executing the code generated into that non-exec fallback allocation would fail (with a SIGSEGV or SIGBUS or similar).  However, whether LO would later make such a call depends on how you use LO.  If you just start it up and shut it down again, chances are that you never trigger such a failing call.
Comment 10 Bryan Quigley 2014-09-24 16:47:04 UTC
>What exactly do you mean with "the .exec fails"?
Sorry that was vague, we blocked creation in HOME via apparmor and assumed it had fallen back to /tmp without us knowing.

Just having it go to $TMPDIR (and not try with HOME) I believe would fix it for the apparmor case. Unfortunately, I'm not sure if putting it in /tmp makes it less secure..

Sorry, if the below doesn't make any sense, this issue is a bit above my level:
Would it be possible to try to do the mmaps first, and then if they fail due to selinux to fallback to doing the file creation?   If so, that might fix it for all three cases (grsecurity, apparmor, and selinux).

>However, whether LO would later make such a call depends on how you use LO.
How would you verify this is successful?
Comment 11 Stephan Bergmann 2014-09-26 11:23:28 UTC
(In reply to comment #9)
> If (1) or (2) fails when trying $HOME, it will apparently not try again with
> /tmp, but just use a plain (read, write, non-exec) allocation.

Sorry, I misread our code.  In fact, it does create a read/write/exec allocation, or indicate failure if that is denied.

(In reply to comment #10)
> Would it be possible to try to do the mmaps first, and then if they fail due
> to selinux to fallback to doing the file creation?   If so, that might fix
> it for all three cases (grsecurity, apparmor, and selinux).

I'll ask around whether

> diff --git a/bridges/source/cpp_uno/shared/vtablefactory.cxx b/bridges/source/cpp_uno/shared/vtablefactory.cxx
> index 2daf76b..999bbc2 100644
> --- a/bridges/source/cpp_uno/shared/vtablefactory.cxx
> +++ b/bridges/source/cpp_uno/shared/vtablefactory.cxx
> @@ -230,9 +230,14 @@ bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const
>      sal_Size size = getBlockSize(slotCount);
>      sal_Size pagesize = sysconf(_SC_PAGESIZE);
>      block.size = (size + (pagesize - 1)) & ~(pagesize - 1);
> -    block.start = block.exec = NULL;
>      block.fd = -1;
>  
> +    // Try non-doublemmaped allocation first:
> +    block.start = block.exec = rtl_arena_alloc(m_arena, &block.size);
> +    if (block.start != nullptr) {
> +        return true;
> +    }
> +
>      osl::Security aSecurity;
>      OUString strDirectory;
>      OUString strURLDirectory;
> @@ -290,12 +295,6 @@ bool VtableFactory::createBlock(Block &block, sal_Int32 slotCount) const
>  
>          strDirectory = OUString();
>      }
> -    if (!block.start || !block.exec || block.fd == -1)
> -    {
> -       //Fall back to non-doublemmaped allocation
> -       block.fd = -1;
> -       block.start = block.exec = rtl_arena_alloc(m_arena, &block.size);
> -    }
>      return (block.start != 0 && block.exec != 0);
>  }
>  

would have any unwanted consequences on SELinux (like flooding some audit log).

(Some notes about observations on my Fedora 20 box with SELinux enforced:

* I need to explicitly "sudo setsebool deny_execmem on" to make mmap/mprotect fail for write+exec mappings.

* Neither OpenJDK 1.7 nor 1.8 appear to be prepared to work with deny_execmem on, already "java -version" fails.  Only GCJ 1.5 appears to potentially be prepared, at least "java -version" works there.

* The GNOME desktop appears to not be prepared to work with deny_execmem on.  It started to crash/freeze for me in weird ways---at which point I stopped my experiments with LO under deny_execmem on.)
Comment 12 Robinson Tryon (qubit) 2014-09-28 22:35:35 UTC
Sounds like this is currently a productive bug/discussion topic. Moving out of UNCONFIRMED

Status -> NEW
Comment 13 Bryan Quigley 2015-01-12 19:34:49 UTC
@Stephan

Any responses to "asking around" for the patch in Comment 11?
Comment 14 Commit Notification 2015-01-16 12:43:58 UTC
Stephan Bergmann committed a patch related to this issue.
It has been pushed to "master":

http://cgit.freedesktop.org/libreoffice/core/commit/?id=8b9968a26265facaf5e761485d750ce9cedab3ab

fdo#72755: Only use double mmap as fallback

It will be available in 4.5.0.

The patch should be included in the daily builds available at
http://dev-builds.libreoffice.org/daily/ in the next 24-48 hours. More
information about daily builds can be found at:
http://wiki.documentfoundation.org/Testing_Daily_Builds
Affected users are encouraged to test the fix and report feedback.