php / php-src

The PHP Interpreter
https://www.php.net
Other
38.08k stars 7.74k forks source link

sodium lib: phpsessionclean.service displays a rogue WARNING on syslog #11513

Open ProceduralMan opened 1 year ago

ProceduralMan commented 1 year ago

Description

As documented on manual "As of PHP 7.2.0 this extension is bundled with PHP. "

Consistent with this, extension on php.ini is commented... ;extension=sodium

...while php -i shows support

sodium

sodium support => enabled
libsodium headers version => 1.0.18
libsodium library version => 1.0.18

A bug -I guess- in the startup code is causing a warning to appear on syslog:

Jun 23 10:39:03 dev systemd[1]: Starting Clean php session files...
Jun 23 10:39:03 dev sessionclean[69737]: PHP Warning:  PHP Startup: Unable to load dynamic library 'sodium' (tried: /usr/lib/php/20210902/sodium (/usr/lib/php/20210902/sodium: cannot open shared object file: No such file or directory), /usr/lib/php/20210902/sodium.so (/usr/lib/php/20210902/sodium.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
Jun 23 10:39:03 dev systemd[1]: phpsessionclean.service: Deactivated successfull

PHP Version

8.1.2-1ubuntu2.11

Operating System

Ubuntu 22.04

iluuu1994 commented 1 year ago

Hi @ProceduralMan! This depends on how PHP is built. If you compile PHP with configure --with-sodium then the sodium PHP extension (not libsodium itself) is indeed bundled with PHP. However, your distribution might be compiling PHP without this flag, and distribute the sodium extension separately. For example, on Debian you have php-sodium which is separately built, and thus a dynamic library.

How did you install PHP?

ProceduralMan commented 1 year ago

Hi!

Standard distro package installed, the exact command was:

sudo apt install php-fpm php-dev php-xml php-cli php-curl php-ftp php-gd php-mbstring php-zip php-imap zip unzip p7zip-full php-mailparse php-ssh2 -y

iluuu1994 commented 1 year ago

If it's only the sessionclean cronjob that shows this error, can you check if it uses the PHP version you're expecting? You can then do php --ini and check all the ini-files for extension=sodium entries. If PHP tries to load the extension you should find that line somewhere.

ProceduralMan commented 1 year ago

Sure thing! Loaded Configuration File => /etc/php/8.1/cli/php.ini Additional .ini files parsed => /etc/php/8.1/cli/conf.d/10-mysqlnd.ini, /etc/php/8.1/cli/conf.d/10-opcache.ini, /etc/php/8.1/cli/conf.d/10-pdo.ini, /etc/php/8.1/cli/conf.d/15-xml.ini, /etc/php/8.1/cli/conf.d/20-calendar.ini, /etc/php/8.1/cli/conf.d/20-ctype.ini, /etc/php/8.1/cli/conf.d/20-curl.ini, /etc/php/8.1/cli/conf.d/20-dom.ini, /etc/php/8.1/cli/conf.d/20-exif.ini, /etc/php/8.1/cli/conf.d/20-ffi.ini, /etc/php/8.1/cli/conf.d/20-fileinfo.ini, /etc/php/8.1/cli/conf.d/20-ftp.ini, /etc/php/8.1/cli/conf.d/20-gd.ini, /etc/php/8.1/cli/conf.d/20-gettext.ini, /etc/php/8.1/cli/conf.d/20-iconv.ini, /etc/php/8.1/cli/conf.d/20-imap.ini, /etc/php/8.1/cli/conf.d/20-mbstring.ini, /etc/php/8.1/cli/conf.d/20-mysqli.ini, /etc/php/8.1/cli/conf.d/20-pdo_mysql.ini, /etc/php/8.1/cli/conf.d/20-phar.ini, /etc/php/8.1/cli/conf.d/20-posix.ini, /etc/php/8.1/cli/conf.d/20-readline.ini, /etc/php/8.1/cli/conf.d/20-shmop.ini, /etc/php/8.1/cli/conf.d/20-simplexml.ini, /etc/php/8.1/cli/conf.d/20-sockets.ini, /etc/php/8.1/cli/conf.d/20-ssh2.ini, /etc/php/8.1/cli/conf.d/20-sysvmsg.ini, /etc/php/8.1/cli/conf.d/20-sysvsem.ini, /etc/php/8.1/cli/conf.d/20-sysvshm.ini, /etc/php/8.1/cli/conf.d/20-tokenizer.ini, /etc/php/8.1/cli/conf.d/20-xdebug.ini, /etc/php/8.1/cli/conf.d/20-xmlreader.ini, /etc/php/8.1/cli/conf.d/20-xmlwriter.ini, /etc/php/8.1/cli/conf.d/20-xsl.ini, /etc/php/8.1/cli/conf.d/20-zip.ini, /etc/php/8.1/cli/conf.d/25-mailparse.ini

cat /etc/php/8.1/cli/php.ini|grep sodium ;extension=sodium (commented)

sudo grep -rnw '/etc/php/8.1/cli/conf.d/' -e 'sodium' (no findings)

So no "sodium" string on any of the .ini files under conf.d

iluuu1994 commented 1 year ago

@ProceduralMan Is that the same PHP binary that sessionclean is using?

ProceduralMan commented 1 year ago

Yes, it is the only PHP installed AFAIK

ls -al /etc/php total 20 drwxr-xr-x 3 root root 4096 Jul 13 2022 . drwxr-xr-x 115 root root 12288 Jun 23 07:25 .. drwxr-xr-x 5 root root 4096 Jul 13 2022 8.1

iluuu1994 commented 1 year ago

Can you post the content of the sessionclean cron/script? Just to fully rule out that there's an issue there?

ProceduralMan commented 1 year ago

Sure!

cat /etc/cron.d/php

# /etc/cron.d/php@PHP_VERSION@: crontab fragment for PHP
#  This purges session files in session.save_path older than X,
#  where X is defined in seconds as the largest value of
#  session.gc_maxlifetime from all your SAPI php.ini files
#  or 24 minutes if not defined.  The script triggers only
#  when session.save_handler=files.
#
#  WARNING: The scripts tries hard to honour all relevant
#  session PHP options, but if you do something unusual
#  you have to disable this script and take care of your
#  sessions yourself.

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi

And the script reads cat /usr/lib/php/sessionclean

#!/bin/sh -e
#
# sessionclean - a script to cleanup stale PHP sessions
#
# Copyright 2013-2015 Ondřej Surý <ondrej@sury.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

SAPIS="apache2:apache2 apache2filter:apache2 cgi:php@VERSION@ fpm:php-fpm@VERSION@ cli:php@VERSION@"

# Iterate through all web SAPIs
(
proc_names=""
for version in $(/usr/sbin/phpquery -V); do
    for sapi in ${SAPIS}; do
        conf_dir=${sapi%%:*}
        proc_name=${sapi##*:}
        if [ -e "/etc/php/${version}/${conf_dir}/php.ini" ] && [ -x "/usr/bin/php${version}" ]; then
            # Get all session variables once so we don't need to start PHP to get each config option
            session_config=$(PHP_INI_SCAN_DIR=/etc/php/${version}/${conf_dir}/conf.d/ "/usr/bin/php${version}" -c "/etc/php/${version}/${conf_dir}/php.ini" -d "error_reporting='~E_ALL'" -r 'foreach(ini_get_all("session") as $k => $v) echo "$k=".$v["local_value"]."\n";')
            save_handler=$(echo "$session_config" | sed -ne 's/^session\.save_handler=\(.*\)$/\1/p')
            save_path=$(echo "$session_config" | sed -ne 's/^session\.save_path=\(.*;\)\?\(.*\)$/\2/p')
            gc_maxlifetime=$(($(echo "$session_config" | sed -ne 's/^session\.gc_maxlifetime=\(.*\)$/\1/p')/60))

            if [ "$save_handler" = "files" ] && [ -d "$save_path" ]; then
                proc_names="$proc_names $(echo "$proc_name" | sed -e "s,@VERSION@,$version,")";
                printf "%s:%s\n" "$save_path" "$gc_maxlifetime"
            fi
        fi
    done
done
# first find all open session files and touch them (hope it's not massive amount of files)
for pid in $(pidof $proc_names); do
    find "/proc/$pid/fd" -ignore_readdir_race -lname "$save_path/sess_*" -exec touch -c {} \; 2>/dev/null
done ) | \
    sort -rn -t: -k2,2 | \
    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
    done

exit 0