Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LIBFFI_TMPDIR should point somewhere that permits executables #77014

Closed
DaveCTurner opened this issue Aug 30, 2021 · 12 comments · Fixed by #80617 or #80651
Closed

LIBFFI_TMPDIR should point somewhere that permits executables #77014

DaveCTurner opened this issue Aug 30, 2021 · 12 comments · Fixed by #80617 or #80651
Assignees
Labels
:Delivery/Packaging RPM and deb packaging, tar and zip archives, shell and batch scripts >enhancement stalled Team:Delivery Meta label for Delivery team

Comments

@DaveCTurner
Copy link
Contributor

DaveCTurner commented Aug 30, 2021

JNA requires a temporary directory which is not mounted noexec, but JNA also uses libffi which itself requires a temporary directory that isn't mounted noexec. If none of the usual suspects work, libffi will fall back to $HOME which will often work, but in general might also not permit executables (or even exist).

We override the temporary directory that JNA uses by setting the java.io.tmpdir system property to ES_TMPDIR. I believe we should do the same thing for libffi, by setting the LIBFFI_TMPDIR environment variable. We should also document that this can be overridden much as we do for the jna.tmpdir system property (which trumps java.io.tmpdir if set).

Fixing this would, I believe, also fix #73309.

@DaveCTurner DaveCTurner added >enhancement :Delivery/Packaging RPM and deb packaging, tar and zip archives, shell and batch scripts labels Aug 30, 2021
@elasticmachine elasticmachine added the Team:Delivery Meta label for Delivery team label Aug 30, 2021
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-delivery (Team:Delivery)

@pugnascotia
Copy link
Contributor

This sounds like a reasonable change. Do we have any ideas around testing this?

@DaveCTurner
Copy link
Contributor Author

I see a couple of options:

  1. We could have packaging tests that run on a SELinux installation that's sufficiently well-locked-down to reproduce the crash, and then confirm that setting LIBFFI_TMPDIR does resolve the problem. I now believe I have a decent handle on why the crash happens and how to reproduce it, so it's just™ a matter of setting up SELinux packaging tests 😉

  2. We could just verify that Elasticsearch sees the LIBFFI_TMPDIR variable we expect it to see. Maybe we could even fail the node if running on Linux and that variable is not set, given that the startup scripts should be setting it?

@DaveCTurner
Copy link
Contributor Author

After a bit of digging, it turns out that support for $LIBFFI_TMPDIR was added in libffi-3.4.2 but the latest release of JNA is using libffi-3.3.0, so we'll need to wait for JNA to pick up the newer version, then pick up the new JNA, and only then can we proceed with this.

@mark-vieira
Copy link
Contributor

We could have packaging tests that run on a SELinux installation that's sufficiently well-locked-down to reproduce the crash

Yeah, seems we don't have such a testing environment right now but probably should. Do we have an idea of the specific controls that need to be enabled to reproduce?

@DaveCTurner
Copy link
Contributor Author

DaveCTurner commented Sep 1, 2021

Do we have an idea of the specific controls that need to be enabled to reproduce?

We know at least some of them I think:

  • SELinux enabled & configured to prevent mmap() from creating anonymous executable & writeable mappings
  • /tmp, /var/tmp, /dev/shm all nonexistent or mounted noexec
  • $HOME nonexistent for the elasticsearch user
  • All mount points in /etc/mtab not writable by elasticsearch, or mounted noexec
  • $ES_TMPDIR (and hence java.io.tmpdir and/or jna.tmpdir) pointing somewhere writeable and not mounted noexec.
  • $TMPDIR unset

That might not be everything, but this problem comes up frequently enough that I don't think it's going to need anything especially weird to reproduce. If the list above isn't enough then we can use strace to see what we're still missing I think (by comparing to the log shared in #77053 (comment)).

DaveCTurner added a commit to elastic/jna-build that referenced this issue Nov 10, 2021
Upgrade to 5.10.0

The latest JNA release introduces the features needed to resolve
elastic/elasticsearch#77014. This commit
updates the version we repackage to pick these features up.
@DaveCTurner
Copy link
Contributor Author

Didn't intend to close this, reopening.

@DaveCTurner DaveCTurner reopened this Nov 10, 2021
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this issue Nov 10, 2021
This commit upgrades JNA to 5.10.0. The primary reason for this upgrade
is to adopt a newer version of `libffi` which supports the
`LIBFFI_TMPDIR` environment variable so that we can change the location
of temporary executables and resolve elastic#77014.

This commit also switches to the upstream JNA releases rather than using
the specially-repackaged ones we've used in the past.
@spricer
Copy link

spricer commented Nov 10, 2021

It seems that -Djava.io.tmpdir alone is not enough to allow elasticsearch startup.
I analyzed running tasks of elasticsearch when /tmp is mounted with noexec removed and there is additional path required for elasticsearch to work.
This variable is called TMPDIR.
So in order to make it work the best way is to append next in /etc/sysconfig/elasticsearch file:

ES_TMPDIR=/var/lib/elasticsearch/tmp
TMPDIR=$ES_TMPDIR

If you have issue with above path (e.g. also mounted with noexec flag) you can introduce new path that is not under
noexec flag:

mkdir /opt/tmp
chown elasticsearch:elasticsearch /opt/tmp
chmod 755 /opt/tmp

Then update /etc/sysconfig/elasticsearch file accordingly:

ES_TMPDIR=/opt/tmp
TMPDIR=$ES_TMPDIR

I think developers need to hardcode somewhere TMPDIR=$ES_TMPDIR

@DaveCTurner
Copy link
Contributor Author

That's one possible workaround @spricer, but TMPDIR has a wide impact and it's not always acceptable to redirect all temporary files to a location that permits executables. Instead we plan to set LIBFFI_TMPDIR instead as described above.

DaveCTurner added a commit that referenced this issue Nov 11, 2021
This commit upgrades JNA to 5.10.0. The primary reason for this upgrade
is to adopt a newer version of `libffi` which supports the
`LIBFFI_TMPDIR` environment variable so that we can change the location
of temporary executables and resolve #77014.

This commit also switches to the upstream JNA releases rather than using
the specially-repackaged ones we've used in the past.
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this issue Nov 11, 2021
This commit upgrades JNA to 5.10.0. The primary reason for this upgrade
is to adopt a newer version of `libffi` which supports the
`LIBFFI_TMPDIR` environment variable so that we can change the location
of temporary executables and resolve elastic#77014.

This commit also switches to the upstream JNA releases rather than using
the specially-repackaged ones we've used in the past.
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this issue Nov 11, 2021
This commit upgrades JNA to 5.10.0. The primary reason for this upgrade
is to adopt a newer version of `libffi` which supports the
`LIBFFI_TMPDIR` environment variable so that we can change the location
of temporary executables and resolve elastic#77014.

This commit also switches to the upstream JNA releases rather than using
the specially-repackaged ones we've used in the past.
elasticsearchmachine pushed a commit that referenced this issue Nov 11, 2021
This commit upgrades JNA to 5.10.0. The primary reason for this upgrade
is to adopt a newer version of `libffi` which supports the
`LIBFFI_TMPDIR` environment variable so that we can change the location
of temporary executables and resolve #77014.

This commit also switches to the upstream JNA releases rather than using
the specially-repackaged ones we've used in the past.
elasticsearchmachine pushed a commit that referenced this issue Nov 11, 2021
This commit upgrades JNA to 5.10.0. The primary reason for this upgrade
is to adopt a newer version of `libffi` which supports the
`LIBFFI_TMPDIR` environment variable so that we can change the location
of temporary executables and resolve #77014.

This commit also switches to the upstream JNA releases rather than using
the specially-repackaged ones we've used in the past.
@DaveCTurner
Copy link
Contributor Author

Ugh Github keeps misinterpreting commit messages and closing this. Reopening again...

@DaveCTurner DaveCTurner reopened this Nov 11, 2021
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this issue Nov 11, 2021
Today if `libffi` cannot allocate pages of memory which are both
writeable and executable then it will attempt to write code to a
temporary file. Elasticsearch configures itself a suitable temporary
directory for use by JNA but by default `libffi` won't find this
directory and will try various other places. In certain configurations,
none of the other places that `libffi` tries are suitable. With older
versions of JNA this would result in a `SIGSEGV`; since elastic#80617 the JVM
will exit with an exception.

With this commit we use the `LIBFFI_TMPDIR` environment variable to
configure `libffi` to use the same directory as JNA for its temporary
files if they are needed.

Closes elastic#18272
Closes elastic#73309
Closes elastic#74545
Closes elastic#77014
Closes elastic#77053
Relates elastic#77285

Co-authored-by: Rory Hunter <[email protected]>
DaveCTurner added a commit that referenced this issue Nov 15, 2021
Today if `libffi` cannot allocate pages of memory which are both
writeable and executable then it will attempt to write code to a
temporary file. Elasticsearch configures itself a suitable temporary
directory for use by JNA but by default `libffi` won't find this
directory and will try various other places. In certain configurations,
none of the other places that `libffi` tries are suitable. With older
versions of JNA this would result in a `SIGSEGV`; since #80617 the JVM
will exit with an exception.

With this commit we use the `LIBFFI_TMPDIR` environment variable to
configure `libffi` to use the same directory as JNA for its temporary
files if they are needed.

Closes #18272
Closes #73309
Closes #74545
Closes #77014
Closes #77053
Relates #77285

Co-authored-by: Rory Hunter <[email protected]>
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this issue Nov 15, 2021
Today if `libffi` cannot allocate pages of memory which are both
writeable and executable then it will attempt to write code to a
temporary file. Elasticsearch configures itself a suitable temporary
directory for use by JNA but by default `libffi` won't find this
directory and will try various other places. In certain configurations,
none of the other places that `libffi` tries are suitable. With older
versions of JNA this would result in a `SIGSEGV`; since elastic#80617 the JVM
will exit with an exception.

With this commit we use the `LIBFFI_TMPDIR` environment variable to
configure `libffi` to use the same directory as JNA for its temporary
files if they are needed.

Closes elastic#18272
Closes elastic#73309
Closes elastic#74545
Closes elastic#77014
Closes elastic#77053
Relates elastic#77285

Co-authored-by: Rory Hunter <[email protected]>
DaveCTurner added a commit to DaveCTurner/elasticsearch that referenced this issue Nov 15, 2021
Today if `libffi` cannot allocate pages of memory which are both
writeable and executable then it will attempt to write code to a
temporary file. Elasticsearch configures itself a suitable temporary
directory for use by JNA but by default `libffi` won't find this
directory and will try various other places. In certain configurations,
none of the other places that `libffi` tries are suitable. With older
versions of JNA this would result in a `SIGSEGV`; since elastic#80617 the JVM
will exit with an exception.

With this commit we use the `LIBFFI_TMPDIR` environment variable to
configure `libffi` to use the same directory as JNA for its temporary
files if they are needed.

Closes elastic#18272
Closes elastic#73309
Closes elastic#74545
Closes elastic#77014
Closes elastic#77053
Relates elastic#77285

Co-authored-by: Rory Hunter <[email protected]>
elasticsearchmachine pushed a commit that referenced this issue Nov 15, 2021
Today if `libffi` cannot allocate pages of memory which are both
writeable and executable then it will attempt to write code to a
temporary file. Elasticsearch configures itself a suitable temporary
directory for use by JNA but by default `libffi` won't find this
directory and will try various other places. In certain configurations,
none of the other places that `libffi` tries are suitable. With older
versions of JNA this would result in a `SIGSEGV`; since #80617 the JVM
will exit with an exception.

With this commit we use the `LIBFFI_TMPDIR` environment variable to
configure `libffi` to use the same directory as JNA for its temporary
files if they are needed.

Closes #18272
Closes #73309
Closes #74545
Closes #77014
Closes #77053
Relates #77285

Co-authored-by: Rory Hunter <[email protected]>

Co-authored-by: Rory Hunter <[email protected]>
@spricer
Copy link

spricer commented Nov 15, 2021

That's one possible workaround @spricer, but TMPDIR has a wide impact and it's not always acceptable to redirect all temporary files to a location that permits executables. Instead we plan to set LIBFFI_TMPDIR instead as described above.

Hi Dave I understand your concern but please also consider that elasticsearch is executing under elasticsearch user session (at least Linux side) with its own env vars. That means that TMPDIR would be affected for that session/user only and if no other JAVA app is running noting else would be affected.

elasticsearchmachine pushed a commit that referenced this issue Nov 15, 2021
* Set LIBFFI_TMPDIR at startup (#80651)

Today if `libffi` cannot allocate pages of memory which are both
writeable and executable then it will attempt to write code to a
temporary file. Elasticsearch configures itself a suitable temporary
directory for use by JNA but by default `libffi` won't find this
directory and will try various other places. In certain configurations,
none of the other places that `libffi` tries are suitable. With older
versions of JNA this would result in a `SIGSEGV`; since #80617 the JVM
will exit with an exception.

With this commit we use the `LIBFFI_TMPDIR` environment variable to
configure `libffi` to use the same directory as JNA for its temporary
files if they are needed.

Closes #18272
Closes #73309
Closes #74545
Closes #77014
Closes #77053
Relates #77285

Co-authored-by: Rory Hunter <[email protected]>

* Fix incorrect SSL usage

Co-authored-by: Rory Hunter <[email protected]>
@DaveCTurner
Copy link
Contributor Author

Sorry for the delay in getting back to you on this @spricer. I'm not sure I understand your last message. Are you saying that the fix in 7.16 (now released) doesn't work for you? If so, can you share more details of how it fails?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Delivery/Packaging RPM and deb packaging, tar and zip archives, shell and batch scripts >enhancement stalled Team:Delivery Meta label for Delivery team
Projects
None yet
5 participants