jetty.project
jetty.project copied to clipboard
Jetty 11.0.18 does not startup with setuid-mechanism as jetty.state not writable
Jetty version(s) Jetty 11.0.18
Java version/vendor openjdk version "21.0.1" 2023-10-17 LTS
OS type/version Debian/Bookworm
Description
Some months ago I upgraded from Jetty 11.0.16 to 11.0.18. My setup uses the setuid-mechanism. So it is started as root to use port 80 and 443 and switches to a jetty-user. Since 11.0.18 the jetty.state-file is created with root-privileges and is not writable by the jetty-user any more. This results in a failed startup. When i manually change the owner of the jetty.state-file to jetty
during startup, it starts successfully.
09:58:55.072 [wnThread] WARN StateLifeCycleListener - Unable to append to state file: /home/luk/jbase/jetty.state
java.nio.file.AccessDeniedException: /home/luk/jbase/jetty.state
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:90) ~[?:?]
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[?:?]
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[?:?]
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:261) ~[?:?]
at java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:482) ~[?:?]
at java.nio.file.Files.newOutputStream(Files.java:227) ~[?:?]
at java.nio.file.Files.newBufferedWriter(Files.java:2988) ~[?:?]
at org.eclipse.jetty.server.StateLifeCycleListener.appendStateChange(StateLifeCycleListener.java:62) ~[jetty-server-11.0.18.jar:11.0.18]
at org.eclipse.jetty.server.StateLifeCycleListener.lifeCycleStopped(StateLifeCycleListener.java:104) ~[jetty-server-11.0.18.jar:11.0.18]
at org.eclipse.jetty.util.component.AbstractLifeCycle.setStopped(AbstractLifeCycle.java:286) ~[jetty-util-11.0.18.jar:11.0.18]
at org.eclipse.jetty.util.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:133) ~[jetty-util-11.0.18.jar:11.0.18]
at org.eclipse.jetty.util.thread.ShutdownThread.run(ShutdownThread.java:136) ~[jetty-util-11.0.18.jar:11.0.18]
How to reproduce?
Start Jetty with the jetty.sh-script and the setuid-module as root, e.g. sudo ./jetty.sh start
.
First steps. delete the jetty.state file, upgrade to Jetty 11.0.19, and try again.
We introduced testing for starting Jetty via the jetty.sh in Jetty 11.0.18. Looks like we need to add test cases for JDK21 use, and setuid use.
Are you using the old-school setuid? or the new setuid-jna stuff? Are you starting via the old school System V init.d behaviors? or are you kicking off jetty.sh from a systemd service file?
Deleted jetty.state, upgraded to Jetty 11.0.19, same error.
I'm using the standard-setuid-module, that is added with java -jar start.jar --add-modules=setuid
. In our production-environment we use systemd, where jetty.sh is called.
The startup of Jetty 11.0.19 works ok with the version of jetty.sh from the 11.0.16-release.
No, it does not work ok. It only reports to successfully startup, but it still can't write to jetty.state.
Same issue for me, Jetty 11.0.20, when using setuid. jetty.sh starts, creates the state file as root (not writable by non-root), launches the process as non-root, and that process then cannot update the state file, so jetty.sh kills the process. It worked in 11.0.16 but not in any version after that. I don't really have a good proposed fix for this. Jetty would need to chown the state file to the setuid user.
Edit: using JDK 21, this happens using jetty.sh.
The state file is created very early in the lifecycle of the server. The setuid call happens much later. So it makes sense that the state file is owned by the user starting jetty (root in your cases). The state file cannot be deleted by Jetty once the setuid call is performed. What about just having the jetty.sh delete the state file (if the pid file shows that the process isn't running)?
As a not very beautiful hack to let me upgrade my jetty installations, I added this at line 155 in jetty.sh
:
chmod ugo+w $STATEFILE
This situation still exists in Jetty 12.0.9. For Setuid module to work, I need to add that line at 155 in jetty.sh. I realize the right answer might be, don't use setuid, instead use
setcap 'cap_net_bind_service=+ep' /path/to/jetty/bin/jetty.sh
and just run the whole thing as that user. I haven't tested this.