Add filesystem type and ignore variables to periodic/security

Many of us that run large ZFS filesystems have run into this issue. Everything runs great when you first configure the pool. Then, as you start to add data to the pool, into the TB+ range, things seem to get slower. And slower. And slower, everyday. You do a $ ps ax to see what's going on, only to find a slew of periodic and find processes running, all churning through your giant ZFS pool.

The reason? /etc/periodic/security/100.chksetuid and /etc/periodic/security/110.chkneggrppem both run massive find processes over all mounted UFS and ZFS filesystems. And these two find processes can take aeons to run, and chew through a lot of RAM while doing it.

I was manually editing the two files above to make them work with my setup. But, then I thought, "Maybe there are others in the same boat." So I've generalised it a bit, and made it fit into the periodic(8) and periodic.conf(5) way of doing things.

The result is 4 new variables that can be added to /etc/periodic.conf to control *exactly* how these two scripts do their scans. Here are the default values, as set in /etc/defaults/periodic.conf:
Code:
daily_status_security_chksetuid_fs="ufs,zfs"
daily_status_security_chksetuid_fs_ignore=""
daily_status_security_neggrpperm_fs="ufs,zfs"
daily_status_security_neggrpperm_fs_ignore=""

The default behaviour has not changed. By default, all mounted UFS and ZFS filesystems will be scanned.

If you only want UFS filesystems to be scanned, then just copy the *_fs variables into /etc/periodic.conf and remove the ,zfs part:
Code:
daily_status_security_chksetuid_fs="ufs"
daily_status_security_neggrpperm_fs="ufs"

Or, if you want to get fancier (maybe you have a root-on-ZFS setup), you can leave the *_fs variables alone, and just put a space-separated list of mountpoints to not scan:
Code:
daily_status_security_chksetuid_fs_ignore="/backups /cameras /var/log /usr/ports"
daily_status_security_neggrpperm_fs_ignore="backups"

Patch attached. To use it, save it somewhere, then:
Code:
# cd /etc
# patch -p0 < /path/to/periodic-fs-type.patch

If you run into any bugs, let me know. Or, if you have any comments, suggestions, of requests, drop me a line.

[Having technical difficulties with my browser, so will post code below, and upload patch later.]
 
periodic-fs-type.patch:
Code:
--- defaults/periodic.conf.orig	2012-05-04 10:44:13.000000000 -0700
+++ defaults/periodic.conf	2012-05-04 09:38:18.000000000 -0700
@@ -170,9 +170,13 @@

 # 100.chksetuid
 daily_status_security_chksetuid_enable="YES"
+daily_status_security_chksetuid_fs="ufs,zfs"		# Filesystem types to scan
+daily_status_security_chksetuid_fs_ignore=""		# List of filesystems to skip

 # 110.neggrpperm
 daily_status_security_neggrpperm_enable="YES"
+daily_status_security_neggrpperm_fs="ufs,zfs"		# Filesystem types to scan
+daily_status_security_neggrpperm_fs=""			# List of filesystems to skip

 # 200.chkmounts
 daily_status_security_chkmounts_enable="YES"

--- periodic/security/100.chksetuid.orig	2012-05-04 10:46:05.000000000 -0700
+++ periodic/security/100.chksetuid	2012-05-04 10:46:47.000000000 -0700
@@ -43,7 +43,12 @@
     [Yy][Ee][Ss])
 	echo ""
 	echo 'Checking setuid files and devices:'
-	MP=`mount -t ufs,zfs | awk '$0 !~ /no(suid|exec)/ { print $3 }'`
+	if [ -z "$daily_status_security_chksetuid_fs_ignore" ]; then
+		MP=`mount -t $daily_status_security_chksetuid_fs | awk '$0 !~ /no(suid|exec)/ { print $3 }'`
+	else
+		daily_status_security_chksetuid_fs_ignore=` echo $daily_status_security_chksetuid_fs_ignore | sed 's/\ /\|/g'`
+		MP=`mount -t $daily_status_security_chksetuid_fs | awk '$0 !~ /no(suid|exec)/ { print $3 }'| egrep -ve "$daily_status_security_chksetuid_fs_ignore"`
+	fi
 	find -sx $MP /dev/null -type f \
 	    \( -perm -u+x -or -perm -g+x -or -perm -o+x \) \
 	    \( -perm -u+s -or -perm -g+s \) -exec ls -liTd \{\} \+ |

--- periodic/security/110.neggrpperm.orig	2012-05-04 10:54:23.000000000 -0700
+++ periodic/security/110.neggrpperm	2012-05-04 10:48:16.000000000 -0700
@@ -41,6 +41,12 @@
     [Yy][Ee][Ss])
 	echo ""
 	echo 'Checking negative group permissions:'
+	if [ -z "$daily_status_security_neggrpperm_fs_ignore" ]; then
+		MP=`mount -t $daily_status_security_neggrpperm_fs | awk '$0 !~ /no(suid|exec)/ { print $3 }'`
+	else
+		daily_status_security_neggrpperm_fs_ignore=` echo $daily_status_security_neggrpperm_fs_ignore | sed 's/\ /\|/g'`
+		MP=`mount -t $daily_status_security_neggrpperm_fs | awk '$0 !~ /no(suid|exec)/ { print $3 }'| egrep -ve "$daily_status_security_neggrpperm_fs_ignore"`
+        fi
 	MP=`mount -t ufs,zfs | awk '$0 !~ /no(suid|exec)/ { print $3 }'`
 	n=$(find -sx $MP /dev/null -type f \
 	    \( \( ! -perm +010 -and -perm +001 \) -or \
 
Thanks a ton for this :) You have a typo in the patch:
Code:
 # 110.neggrpperm
 daily_status_security_neggrpperm_enable="YES"
+daily_status_security_neggrpperm_fs="ufs,zfs"		# Filesystem types to scan
+daily_status_security_neggrpperm_fs=""			# List of filesystems to skip

This should be:

Code:
 # 110.neggrpperm
 daily_status_security_neggrpperm_enable="YES"
+daily_status_security_neggrpperm_fs="ufs,zfs"		# Filesystem types to scan
+daily_status_security_neggrpperm_fs[b]_ignore[/b]=""	# List of filesystems to skip

Any chance you could get this committed to HEAD and RELENG_9 ?
 
Ooh, you're right. Wonder how I missed that one? I blame Klipper for being too helpful with the copy/paste duties. :D

I've sent the patch to the -stable mailing list to see if there was any interest in it and willing to test it. I'll think about sending in a PR about it after the weekend when I've tested it some more.
 
It turns out that it's possible to achieve the same effect at least for setuid files on filesystem basis without this patch, turn off setuid property on a ZFS dataset or mount an UFS filesystem with nosuid option. This of course prevents setuid completely on every file on the filesystem.

Edit: Works on 110.neggrpperm as well, both scripts use this construct to find out filesystems to check:

Code:
MP=`mount -t ufs,zfs | awk '$0 !~ /no(suid|exec)/ { print $3 }'`
 
For other zfs newbies out there, here's the command I used to switch off exec on my 43 TB ZFS partition where I was getting a similar problem (find slowing down file copying operations, looking for setuid files):

zfs set exec=off tank

Where tank is the name of your ZFS volume. It's effective immediately - no need to remount. You can test to see if 100.chksetuid would process your filesystem by running the following command (extracted from 100.chksetuid itself):

mount -t ufs,zfs | awk '$0 !~ /no(suid|exec)/ { print $3 }'

If your ZFS filesystem is listed, it would be processed; if it's not, it won't be processed.
 
Back
Top