Tcpdump not being able to write pcap file. Permission denied
Matthew Martinez
I am developing a network monitoring solution for my Java application so I can sniff packets on my machine interfaces and dump the result in rolling PCAP files. When launching the tcpdump command (using sudo) from the Java code, I get tcpdump: /path/to/app/log/GTP00: Permission denied
DETAILS
The command is executed using Runtime.getRuntime().exec(command) where command is a String valued sudo tcpdump -i eth0 -w /path/to/app/log/GTP -W 50 -C 20 -n net 10.246.212.0/24 and ip
The user launching the Java app is "testUser" which belongs to group "testGroup". This user is allowed to sudo tcpdump.
The destination dir has the following attributes:
[testUser@node ~]$ ls -ld /path/to/app/log
drwxrwxr-x. 2 testUser testGroup 4096 Feb 4 15:40 /path/to/app/log
MORE DETAILS
Launching the command from the command line SUCCESFULLY creates the pcap file in the specified folder.
[testUser@node ~]$ ls -l /path/to/app/log/GTP00
-rw-r--r--. 1 tcpdump tcpdump 1276 Feb 4 16:12 /path/to/app/log/GTP00
I have developed a simplified Java app for testing purposes
package execcommand;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ExecCommand { public static void main(String[] args) { try { String command; String line; String iface = "eth0"; String capturePointName = "GTP"; String pcapFilterExpression = "net 10.246.212.0/24 and ip"; int capturePointMaxNumberOfFilesKept = 50; int capturePointMaxSizeOfFilesInMBytes = 20; command = "sudo tcpdump -i " + iface + " -w /path/to/app/log/" + capturePointName + " -W " + capturePointMaxNumberOfFilesKept + " -C " + capturePointMaxSizeOfFilesInMBytes + " -n " + pcapFilterExpression; Process process = Runtime.getRuntime().exec(command); BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream())); while ((line = br.readLine()) != null) { System.err.println(line); } } catch (IOException ex) { Logger.getLogger(ExecCommand.class.getName()).log(Level.SEVERE, null, ex); } }
}This test program, launched by the same user, SUCCESFULLY creates the pcap file in the specified folder.
[testUser@node ~]$ ls -l /path/to/app/log/GTP00
-rw-r--r--. 1 tcpdump tcpdump 1448 Feb 4 16:21 /path/to/app/log/GTP00
Then, I can infer that the problem is somehow restricted to my Java app. This is how my Java app is launched:
exec java -Dknae_1 -Djavax.net.ssl.trustStorePassword=<trust_pass> -Djavax.net.ssl.trustStore=/path/to/app/etc/certificates/truststore -Djavax.net.ssl.keyStorePassword=<key_store_pass> -Djavax.net.ssl.keyStore=/path/to/app/etc/certificates/keystore -d64 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8887,suspend=y -XX:-UseLargePages -Xss7m -Xmx64m -cp /path/to/app/lib/knae.jar:/path/to/app/lib/xphere_baseentity.jar:/path/to/app/lib/mysql.jar:/path/to/app/lib/log4j-1.2.17.jar:/path/to/app/lib/tools.jar:/path/to/app/conf:/path/to/app/lib/pcap4j-core-1.7.5.jar:/path/to/app/lib/pcap4j-packetfactory-static-1.7.5.jar:/path/to/app/lib/jna-5.1.0.jar:/path/to/app/lib/slf4j-api-1.7.25.jar:/path/to/app/lib/slf4j-simple-1.7.25.jar com.app.package.knae.Knae knae_1
UPDATE
I am able to write the pcap file within /tmp.
I have also tried giving 777 permissions to /path/to/app/log to no avail.
These are the attibutes of both dirs:
[testUser@node ~]$ ls -ld /tmp
drwxrwxrwt. 10 root root 4096 Feb 6 10:13 /tmp
[testUser@node ~]$ ls -ld /path/to/app/log
drwxrwxrwx. 2 testUser testGroup 4096 Feb 6 09:25 /path/to/app/logI will provide any additional information as needed.
Why is tcpdump complaining about not being able to write this file?
21 Answer
- Use absolute paths in command line instead of "
sudo" and "tcpdump" - Use
ProcessBuilder.classinstead ofRuntime.exec()because you can specify the working directory, you can use spaces in options and more. - In tcpdump command you have to use
-Zflag to specify user because PCAP uses different than caller one. Check this link on ServerFault: tcpdump permisson denied