eduvpn/documentation

PHP session files not removed

Closed this issue · 6 comments

Hi,

I'm not sure where to report this bug (and whether it even actually stands as a bug) ... but, this is the closest, so I'll file it here.

This morning, I started looking into an alert for our eduvpn deployment - /var was low on available i-nodes.

I traced it down to /var/lib/php/sessions with lots of files.

The systems is Ubuntu 18.04 - installed as per deploy_debian.sh from this repository (with minor changes, to adjust to PHP 7.2).

I found Ubuntu (and presumably also Debian) deployment of PHP comes with /usr/lib/php/sessionclean, called from either cron or a systemd timer.

The /usr/lib/php/sessionclean script is supposed to delete all stale files in /var/lib/php/sessions - but looks only for the sess_* pattern, the default base name for PHP session files storage.

I eventually found that the files not being deleted have a different basename - sses_* - and I traced this to /usr/share/php/fkooman/SeCookie/SessionStorage.php which has:

    const SESSION_FILE_PREFIX = 'sses_';

I don't know whether the different base name is intentional - but as a result, the session files are being left behind.

I worked around it by changing the pattern in /usr/lib/php/sessionclean:

--- before: /usr/lib/php/sessionclean
+++ after: /usr/lib/php/sessionclean
@@ -52,7 +52,7 @@
     sort -u -t: -k 1,1 | \
     while IFS=: read -r save_path gc_maxlifetime; do
 	# find all files older then maxlifetime and delete them
-	find -O3 "$save_path/" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin "+$gc_maxlifetime" -delete
+	find -O3 "$save_path/" -ignore_readdir_race -depth -mindepth 1 -regex '.*/ss?ess?_.*' -type f -cmin "+$gc_maxlifetime" -delete
     done

 exit 0

So I found a workaround that works for me, but thought I'd better report it so that it can be properly fixed. I can see several options:

  • Adjusting the basename to match what PHP distribution expects
  • Adjusting the cleanup script to match what SeCookie uses
  • Creating a separate cleanup script
  • ... and there would be more.

It got triggered in our setting because of the large number of hits or deployment was getting ... from our own website monitoring, so it may not be an absolute requirement - but still reporting it.

I hope this report is useful.

Cheers,
Vlad

I also found that

Thanks for this! I am seeing the same on Debian, but not on CentOS! Investigating...

Theory: the php-secookie library has built-in "garbage collection" to delete old session files which runs on average 1 of every 100 requests. However, on Debian (and obviously Ubuntu) the permissions for /var/lib/php/sessions are such that a script running as www-data can't delete files there, but only write to them.

CentOS:

drwxrwx---. 2 root apache 36864 Jul 27 06:28 session

Fedora 32:

drwxrwx---. 2 root apache 36864 Jul 27 06:28 session

Debian 9:

drwx-wx-wt 2 root root 1773568 Jul 27 11:15 sessions

Debian 10:

drwx-wx-wt 2 root root 20480 Jul 27 09:05 sessions

So it seems the script running as www-data on Debian is not allowed to enumerate the files in the session folder, which kinda makes sense for security purposes I guess...

I assume that is also one of the reasons Debian has this PHP session cleaner, as PHP's built-in session GC simply doesn't work on Debian either...

I think this works properly:

# find /var/lib/php/sessions -type f -mtime +0 -delete

I'll create a systemd service/timer file for this and have it installed as part of php-secookie. That seems the cleanest solution.

php-fkooman-secookie 4.0.0-2 contains the fix (a cron that runs the above command).

Please re-open if issue remains!

Thanks for the quick fix - does exactly what it should!