- How to monitor file access on Linux with auditd
- Install auditd on Linux
- For Ubuntu, Debian or Linux Mint:
- For Fedora, CentOS or RHEL:
- Configure auditd
- Query auditd Daemon Log
- Check if a specific file has been accessed by anyone
- Check if a specific directory has been accessed by anyone
- Support Xmodulo
- Linux — How to track all files accessed by a process?
- 4 Answers 4
- lsof :
- strace :
How to monitor file access on Linux with auditd
If you are running a mission critical web server, or maintaining a storage server loaded with sensitive data, you probably want to closely monitor file access activities within the server. For example, you want to track any unauthorized change in system configuration files such as /etc/passwd .
To monitor who changed or accessed files or directories on Linux, you can use the Linux Audit System which provides system call auditing and monitoring. In the Linux Audit System, a daemon called auditd is responsible for monitoring individual system calls, and logging them for inspection.
In this tutorial, I will describe how to monitor file access on Linux by using auditd .
Install auditd on Linux
For Ubuntu, Debian or Linux Mint:
$ sudo apt-get install auditd
Once installed by apt-get , auditd will be set to start automatically upon boot.
For Fedora, CentOS or RHEL:
If you want to start auditd automatically upon boot on Fedora, CentOS or RHEL, you need to run the following.
Configure auditd
Once you installed auditd , you can configure it by two methods. One is to use a command-line utility called auditctl . The other method is to edit the audit configuration file located at /etc/audit/audit.rules . In this tutorial, I will use the auditd configuration file.
The following is an example auditd configuration file.
$ sudo vi /etc/audit/audit.rules
# First rule - delete all -D # increase the buffers to survive stress events. make this bigger for busy systems. -b 1024 # monitor unlink() and rmdir() system calls. -a exit,always -S unlink -S rmdir # monitor open() system call by Linux UID 1001. -a exit,always -S open -F loginuid=1001 # monitor write-access and change in file properties (read/write/execute) of the following files. -w /etc/group -p wa -w /etc/passwd -p wa -w /etc/shadow -p wa -w /etc/sudoers -p wa # monitor read-access of the following directory. -w /etc/secret_directory -p r # lock the audit configuration to prevent any modification of this file. -e 2
Once you finish editing the audit configuration, restart auditd .
$ sudo service auditd restart
Once auditd starts running, it will start generating an audit daemon log in /var/log/audit/audit.log as auditing is in progress.
A command-line tool called ausearch allows you to query audit daemon logs for specific violations.
Query auditd Daemon Log
Check if a specific file has been accessed by anyone
The following command checks if /etc/passwd has been accessed by anyone. As shown in the above example audit configuration, auditd checks if /etc/passwd is modified or tampered with using chmod .
$ sudo ausearch -f /etc/passwd
time->Sun May 12 19:22:31 2013 type=PATH msg=audit(1368411751.734:94): item=0 name="/etc/passwd" inode=655761 dev=08:01 mode=0100644 ouid=0 ogid=0 rdev=00:00 type=CWD msg=audit(1368411751.734:94): cwd="/home/xmodulo" type=SYSCALL msg=audit(1368411751.734:94): arch=40000003 syscall=306 success=yes exit=0 a0=ffffff9c a1=8624900 a2=1a6 a3=8000 items=1 ppid=14971 pid=14972 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=19 comm="chmod" exe="/bin/chmod" key=(null)
The ausearch output above shows that chmod has been applied to /etc/passwd by the root once.
Check if a specific directory has been accessed by anyone
The following command checks if /etc/secret_directory has been accessed by anyone.
$ sudo ausearch -f /etc/secret_directory
time->Sun May 12 19:59:58 2013 type=PATH msg=audit(1368413998.927:108): item=0 name="/etc/secret_directory/" inode=686341 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00 type=CWD msg=audit(1368413998.927:108): cwd="/home/xmodulo" type=SYSCALL msg=audit(1368413998.927:108): arch=40000003 syscall=230 success=no exit=-61 a0=bfcdc4e4 a1=b76f0fa9 a2=8c65c70 a3=ff items=1 ppid=2792 pid=11300 auid=1001 uid=1001 gid=1001 euid=1001 suid=1001 fsuid=1001 egid=1001 sgid=1001 fsgid=1001 tty=pts1 ses=2 comm="ls" exe="/bin/ls" key=(null)
The output shows that /etc/secret_directory was looked into by Linux UID 1001 .
In our example audit configuration, auditd was placed in immutable mode, which means that if you attempt to modify /etc/audit/audit.rules , and restart auditd , you will get the following error.
$ sudo /etc/init.d/auditd restart
Error deleting rule (Operation not permitted) The audit system is in immutable mode, no rules loaded
If you want to be able to modify the audit rules again after auditd is put in immutable mode, you need to reboot your machine after changing the rules in /etc/audit/audit.rules .
If you want to enable daily log rotation for the audit log generated in /var/log/audit directory, use the following command in a daily cron job.
$ sudo service auditd rotate
Support Xmodulo
This website is made possible by minimal ads and your gracious donation via PayPal or credit card
Please note that this article is published by Xmodulo.com under a Creative Commons Attribution-ShareAlike 3.0 Unported License. If you would like to use the whole or any part of this article, you need to cite this web page at Xmodulo.com as the original source.
Linux — How to track all files accessed by a process?
Is there a way to track all file I/O for a given process? All I really need is the locations of files being read from/written to from a given process (and ideally if it was a read or write operation although that’s not as important). I can run the process and track it rather than needing to attach to an existing process which I would assume is significantly simpler. Is there any kind of wrapper utility I can run a process though that will monitor file access?
4 Answers 4
lsof :
Try doing this as a starter :
this command will list all currently open files, fd, sockets for the process with the passed process ID.
For your special needs, see what I can offer as a solution to monitor a php script :
php foo.php & _pid=$! lsof -r1 -p $_pid kill %1 # if you want to kill php script
strace :
I recommend the use of strace . Unlike lsof , it stays running for as long as the process is running. It will print out which syscalls are being called when they are called. -e trace=file filters only for syscalls that access the filesystem:
sudo strace -f -t -e trace=file php foo.php
or for an already running process :
sudo strace -f -t -e trace=file -p
Thanks that’s a good starting point! It works for processes already running at the moment it’s run. I’m trying to do this for a PHP script for its entire execution, tracking the files from the start of the process until it exists. Looking at the help, There’s a -r repeat option but this seems to periodically scan the files that are open by the process rather than have been opened. Essentially I want to do this: lsof -p $$ && exec php foo.php This doesn’t seem to list files that are opened by foo.php
thanks, that’s certainly providing more relevant information and showing all the php extensions being loaded, the script contains unfortunately, file.txt is not listed in the output. I can verify the file is being opened by amending the script to print the contents of file.txt but I still don’t see file.txt in the output of lsof.?php>
To properly trace an AppImage, I needed to run strace as root but the command using my own user. This got the job done: sudo strace -fte trace=%file -u $(id -un)
Mixing your two solutions together becomes perfect: php foo.php & sudo strace -f -t -e trace=file -p $! especially for short running tasks.
Besides strace there is another option which does not substantially slow down the monitored process. Using the Liunx kernel’s fanotify (not to be confused with the more popular inotify) it is possible to monitor whole mount-points for IO-activity. With unshared mountnamespaces the mounts of a given process can be isolated fromt the rest of the system (a key technology behind docker).
An implementation of this concept can be found in shournal, which I am the author of.
$ shournal -e sh -c 'cat foo > bar' $ shournal --query --history 1 . 1 written file(s): /home/user/bar 1 read file(s): /home/user/foo
External links are always highly appreciated as sources, but imagine this one was to become invalid — your solution would be unsalvageable for future SO users. Please consider posting code here and explaining your solution so we all can learn.
@harmonica141: That’s always the problem: what to write and what to omit. A complete, minimal example would be not much shorter than the example at the bottom at man7.org/linux/man-pages/man7/fanotify.7.html . In fact, it could be almost the same with a leading unshare( CLONE_NEWNS); . Do you think it would be helpful to include the full source here?
strace is an amazing tool but its output is a bit verbose.
If you want you can use a tool I’ve written which processes strace output and provide a CSV report of all files accessed (TCP sockets too) with the following data:
1. Filename
2. Read/Written bytes
3. Number of read/write operations
4. Number of time the file was opened
It can be run on new processes or processes already running (using /proc/fd data).
I found it useful for debugging scenarios and performance analysis.
You can find it here: iotrace
Filename, Read bytes, Written bytes, Opened, Read op, Write op /dev/pts/1,1,526512,0,1,8904 socket_127.0.0.1:47948->127.0.0.1:22,1781764,396,0,8905,11 myfile.txt,65,0,9,10,0 pipe:[3339],0,0,0,1,0
Afterward, you can process the CSV data in Excel or other tools for sorting or other analysis required.
The downside is you need to download & compile and it isn’t always 100% accurate.