2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 10:07:12 +00:00

Merge Initial lsof profile (+ comments)

Initial profile for review + extra descriptions to summarize why each rule / chunk is there.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1486
Approved-by: John Johansen <john@jjmx.net>
Merged-by: Maxime Bélair <maxime.belair@canonical.com>
This commit is contained in:
Maxime Bélair 2025-05-12 14:19:20 +00:00
commit 2a7b84cd73
2 changed files with 258 additions and 0 deletions

52
profiles/apparmor.d/lsof Normal file
View File

@ -0,0 +1,52 @@
# Last Modified: Mon Jan 20 20:17:22 2025
abi <abi/4.0>,
include <tunables/global>
#------------------------------------------------------------------
# Copyright (C) 2025 Canonical Ltd.
#
# Author: Nicolas Campuzano Jimenez <nicolas.campuzano@canonical.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#------------------------------------------------------------------
# vim: ft=apparmor
#
profile lsof /usr/bin/lsof flags=(attach_disconnected.path=/aa_disconnected/) {
include <abstractions/base>
include <abstractions/nameservice>
/usr/bin/lsof mr,
capability sys_ptrace,
capability dac_read_search,
capability dac_override,
ptrace read,
mqueue getattr type=posix,
/ r,
/**/ r,
@{PROC} r,
@{PROC}/locks r,
@{PROC}/@{pids}/fd/ r,
@{PROC}/@{pids}/fdinfo/* r,
@{PROC}/@{pids}/lock r,
@{PROC}/@{pids}/mounts r,
@{PROC}/@{pids}/stat r,
@{PROC}/@{pids}/task/ r,
@{PROC}/@{pids}/task/@{tid}/fd/ r,
@{PROC}/@{pids}/task/@{tid}/fdinfo/* r,
@{PROC}/@{pids}/task/@{tid}/maps r,
@{PROC}/@{pids}/task/@{tid}/stat r,
@{PROC}/@{pid}/net/* r,
include if exists <local/lsof>
}

View File

@ -0,0 +1,206 @@
summary: stress test for the lsof profile
execute: |
###########
## SETUP ##
###########
# Create character device (check it doesn't exist!!)
[ -e /dev/mem ] || sudo mknod /dev/mem c 1 1 # major 1-> memory device; #minor 1-> DMA
# make sure we can run lsof -d mem later
sudo chmod 660 /dev/mem
# Create loopback test device (check it doesn't exist either!)
[ -e /dev/loop10 ] || sudo mknod /dev/loop10 b 7 10 # major 1 -> loopback device; #minor10 -> instance 10 of device driver; shouldn't be in use.
dd if=/dev/zero of=/tmp/test.img bs=1M count=10 # Fill /tmp/test.img with 10MB of 0's
sudo losetup /dev/loop10 /tmp/test.img # mount /tmp/test.img on /dev/loop10 so it looks like a block device
# Create character test device (check again!)
[ -e /dev/char-test ] || sudo mknod /dev/char-test c 99 1 # this major shouldn't be defined, should be a useless device just for extra testing
###########
## TESTS ##
###########
# List all open files attached to /, recursively
# sudo lsof +D /
# these 2 could be combined in one (-i -U) to list all UNIX sockets and network files
sudo lsof -i
sudo lsof -U
# these 5 could be combined ( -d mem,mmap,txt,CHR,BLK) for mapped, memory-mapped, binaries, character & block devices)
sudo lsof -d mem
sudo lsof -d mmap
sudo lsof -d txt
sudo lsof -d CHR
sudo lsof -d BLK
#############################
# Test Deleted but Open Files
#############################
# Create a test file and open it in the background
echo "test data" > /tmp/deleted-file
sleep 1
tail -f /tmp/deleted-file & # Keep file open in background
TAIL_PID=$!
sleep 2
# Delete the file while it's in use
rm /tmp/deleted-file
# See if lsof still detects it
sudo lsof | grep -F "/tmp/deleted-file (deleted)"
# Cleanup
kill $TAIL_PID
##############################
# Start a temporary web server
##############################
python3 -m http.server 8080 &
PYTHON_PID=$!
sleep 2
# Check what process is using port 8080
sudo lsof -i :8080
# Cleanup
kill $PYTHON_PID
####################
# Test Named Pipe
####################
# Open a named pipe
mkfifo /tmp/testpipe
# open the pipe for r/w so that it remains open
exec 3<> /tmp/testpipe
# Check lsof dislays open pipe
sudo lsof +E | tee /tmp/lsof.log | grep /tmp/testpipe || grep FIFO /tmp/lsof.log
# Cleanup
exec 3<&- # Close fd 3
rm /tmp/testpipe
#####################
# Open network sockets
#####################
# Start a temporary web server
python3 -m http.server 8080 &
sleep 1
PYTHON_PID=$!
sleep 1
# Check what process is using port 8080
sudo lsof -i :8080
sleep 1
# Cleanup
kill $PYTHON_PID
# ###################################
# Process deletes its own binary
echo -e '#!/bin/bash\nrm -- "$0"\nsleep 60' > /tmp/self-delete.sh
chmod +x /tmp/self-delete.sh
# Run it in the background
/tmp/self-delete.sh &
SCRIPT_PID=$!
sleep 2
# Check if `lsof` can still track it
echo "Process PID: $SCRIPT_PID"
sudo lsof -p $SCRIPT_PID
# Cleanup
kill $SCRIPT_PID 2>/dev/null
#################
# Zombie process
#################
# Create a process that turns into a zombie
bash -c 'sleep 10 & wait $!' &
PARENT_PID=$!
# Wait a moment and check for zombies
sleep 2
ps -ef | grep defunct
sudo lsof -p $PARENT_PID
# Cleanup
kill $PARENT_PID 2>/dev/null
###########################
# Encrypted loopback device
###########################
# Create an encrypted loopback device
dd if=/dev/zero of=/tmp/encrypted.img bs=1M count=30
sudo losetup /dev/loop20 /tmp/encrypted.img
echo "securest passphrase" | sudo cryptsetup luksFormat /dev/loop20 --key-file=-
echo "securest passphrase" | sudo cryptsetup luksOpen /dev/loop20 encdev --key-file=-
# Mount it and check open files
sudo mkfs.ext4 /dev/mapper/encdev
mkdir -p /mnt/encrypted
sudo mount /dev/mapper/encdev /mnt/encrypted
sleep 2
echo "test data" > /mnt/encrypted/testfile
# Start tail in the background and capture the correct PID
exec 3</mnt/encrypted/testfile # Open file descriptor 3 for reading
sleep 2
sudo lsof /mnt/encrypted
exec 3<&- # Close file descriptor after lsof
# Cleanup
sudo umount /mnt/encrypted
sudo cryptsetup luksClose encdev
sudo losetup -d /dev/loop20
rm /tmp/encrypted.img
########
#Try SMB
########
#Install SMB and Mount SMB share
sudo apt update && sudo apt install -y samba
sleep 1
sudo mkdir -p /srv/samba/share
sudo chmod 777 /srv/samba/share # Allow all users to access (for testing)
# Inline the 'testshare' entry to the samba config file
printf "\n[testshare]\npath = /srv/samba/share\nbrowseable = yes\nread only = no\nguest ok = yes\nforce user = nobody\n" | sudo tee -a /etc/samba/smb.conf
sleep 1
sudo systemctl restart smbd nmbd
# sudo ss -tulnp | grep smbd # uncomment if need to troubleshoot SMB.
sudo modprobe cifs
sleep 1
sudo mkdir -p /mnt/smb
sudo mount -t cifs //127.0.0.1/testshare /mnt/smb -o guest
# Try open file from mounted share
echo "test content" | sudo tee /srv/samba/share/testfile.txt
sudo sync # sync samba to update testfile.txt
# Open shared file for reading and assign fd 3. Open for r/w can be tricky in smb, this does the trick.
exec 3</mnt/smb/testfile.txt
sleep 2
#lsof on open share
sudo lsof -c smbd
# Cleanup
exec 3<&- # Close fd 3
sudo umount /mnt/smb
#########
# Try NFS
#########
#mount NFS
sudo apt install -y nfs-kernel-server
sleep 1
sudo mkdir -p /srv/nfs/share
sudo chmod 777 /srv/nfs/share # Allow all users for testing
# Update nfs share config
echo '/srv/nfs/share 127.0.0.1(rw,sync,no_subtree_check,no_root_squash)' | sudo tee -a /etc/exports
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
sudo mkdir -p /mnt/nfs
sudo mount -t nfs 127.0.0.1:/srv/nfs/share /mnt/nfs
sudo lsof -c nfsd
sudo umount /mnt/nfs