2

I have a java web application by Tomcat 9 servlet container which tries to read a file in /tmp folder with 777 permission on Ubuntu 18.04

ls -ltr /tmp/test.txt
-rwxrwxrwx 1 vagrant vagrant 10 Jan  3 17:03 /tmp/test.txt

The java code is:

    try {
        result = FileUtils.readFileToString(new File("/tmp/test.txt"));
    } catch (IOException ex) {
        log.info("##### Cannot read file. Reason: " + ex.getMessage());
    }

But it always show the error

##### Cannot read file. Reason: File '/tmp/test.txt' does not exist

This test file can be opened fine by a normal user on a terminal window (example user: vagrant).

vagrant@ras:~$ cat /tmp/test.txt

EDIT: The exact same root issue can cause the slightly different symptom that the Tomcat Manager application cannot be used to deploy a war file located in /tmp. To help future internet searches, here's a typical error you might see in catalina.out when you are encountering this problem. The file /tmp/my_app.war is correctly readable by the user tomcat. Nonetheless you get this problem:

02-Apr-2021 22:25:20.254 SEVERE [http-nio-80-exec-4] org.apache.catalina.startup.ExpandWar.copy Error copying [/tmp/my_app.war] to [/var/lib/tomcat9/webapps/my_app.war]
    java.io.FileNotFoundException: /tmp/my_app.war (No such file or directory)
            at java.io.FileInputStream.open0(Native Method)
            at java.io.FileInputStream.open(FileInputStream.java:195)
            at java.io.FileInputStream.<init>(FileInputStream.java:138)
            at org.apache.catalina.startup.ExpandWar.copy(ExpandWar.java:276)
            at org.apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:1016)

Does anybody know about the problem with Tomcat 9? I'll need the java web application to read this test file as string.

mdahlman
  • 9,204
  • 4
  • 44
  • 72
Bằng Rikimaru
  • 1,512
  • 2
  • 24
  • 50
  • Are you sure Tomcat is running as the `vagrant` user? – erickson Jan 03 '20 at 17:28
  • 1
    `ls -al /tmp` probably does not give rights to Tomcat for reading. A Tomcat security restrictions on not reading executable (x) files would be thinkable but is a bit farfetched. – Joop Eggen Jan 03 '20 at 17:37
  • Guessing from the user name "vagrant" perhaps your Tomcat is running in a virtual machine and so Tomcat's /tmp is not the same as your shell's /tmp. – Andrew Gilmartin Jan 03 '20 at 17:58
  • Are you using SELinux, AppArmor or any other such security tools? – Luke Woodward Jan 03 '20 at 18:57
  • @LukeWoodward there is no SELinux in Ubuntu 18.04. I think it must due to Tomcat 9. – Bằng Rikimaru Jan 04 '20 at 14:18
  • Does this answer your question? [How to allow Tomcat war app to write in folder](https://stackoverflow.com/questions/56827735/how-to-allow-tomcat-war-app-to-write-in-folder) – Olaf Kock Jan 06 '20 at 08:36
  • @OlafKock haha, we met each other on tomcat user mailing list. No, it didn't help me. I needed to disable PrivateTmp from yes to no. Then, tomcat process can read file created by another process in /tmp. – Bằng Rikimaru Jan 06 '20 at 13:55
  • Ha, well, it's still _very_ related - even though it's not about writing to arbitrary folders. The comment comes from voting to close as duplicate - I'll keep that vote up because I'd expect the comment to go away otherwise and the crossreference is good to have as it explains the underlying principle, rather than the concrete steps you needed in your case. – Olaf Kock Jan 06 '20 at 14:34

3 Answers3

2

I had to ask directly in tomcat users mailing list instead at http://tomcat.10.x6.nabble.com/Tomcat-9-does-not-allow-to-read-file-in-tmp-folder-with-777-permission-td5093298.html

What I needed to do is to update /lib/systemd/system/tomcat9.service and set PrivateTmp=yes to PrivateTmp=no. Then, run these 2 commands:

sudo  systemctl daemon-reload
sudo  systemctl restart tomcat9

After that, it works normally (my java web application can create folders in /tmp/ and read files from them).

Bằng Rikimaru
  • 1,512
  • 2
  • 24
  • 50
1

Following the pattern described in this answer, it seems to me that this is perhaps a better way to de-privatize /tmp:

sudo systemctl edit tomcat9

Add these two lines then save:
[Service]
PrivateTmp=no

sudo systemctl daemon-reload
sudo systemctl restart tomcat9

Clearly, this is functionally equivalent to Bằng's answer. But it seems to me that the override file is intended for exactly this use case. So it seems this is a very clean technique.

For reference, the override file gets created here (on my Ubuntu 20.04 system):

/etc/systemd/system/tomcat9.service.d/override.conf

And the overrides can be removed easily if you decide to lock things down again later:

sudo systemctl revert tomcat9
mdahlman
  • 9,204
  • 4
  • 44
  • 72
  • Detail, for non-emacs folks... I actually use this to get a vim editor: `sudo EDITOR=vim systemctl edit tomcat9` – mdahlman Apr 07 '21 at 21:46
  • Note: I wrote "for non-emacs folks", but really the default on Ubuntu is `nano`, not emacs. – mdahlman Apr 23 '21 at 23:00
1

I will rather make /etc/systemd/system/tomcat9.service.d/override.conf file content like that :

[Service]
ReadWritePaths=/tmp
PrivateTmp=no

As you might end up having an exception like this:

java.io.IOException: Read-only file system
at java.base/java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.base/java.io.File.createTempFile(File.java:2129)
at java.base/java.io.File.createTempFile(File.java:2175)
...

When trying to create a temp file within your application.