Search code examples
phplinuxbashshelltmux

Why can't tmux read the session file when ran from PHP?


I want to create a PHP site which can manage multiple sessions and read contents from them. So in order to realize this I decided to use tmux with the PHP exec() command.

The sessions will run under the user www-data, each running their separate task.

I use the following code to get a list of all running sessions in PHP:

$command = "tmux -S /tmp/tmux-33/default ls";
$command."<br>";
exec($command . " 2>&1", $output, $result_code);

$output = JSON_Format($output);
echo "$output<br>";

And that echoes

tmux -S /tmp/tmux-33/default ls
[ "no server running on \/tmp\/tmux-33\/default" ]

That would mean that the file does not exist, right? Well no. That's because If I open the terminal and run

sudo tmux -S /tmp/tmux-33/default ls

Than the output would be

0: 1 windows (created Sat Mar  9 18:09:34 2024)
2: 1 windows (created Sat Mar  9 18:16:42 2024) (attached)

Even reading the file with nano outputs [ Error reading /tmp/tmux-33/default: No such device or address ], which proves the file exists.

And I can confirm that tmux-33 corresponds to www-data, because If I don't provide the -S parameter, It default to that file.

Another thing I tried to confirm that www-data is properly configured is connecting to It's shell directly as follows:

codrut@Linux-Server:/tmp$ sudo -u www-data -s /bin/bash
www-data@Linux-Server:/tmp$ tmux list-s
0: 1 windows (created Sat Mar  9 18:09:34 2024)
2: 1 windows (created Sat Mar  9 18:16:42 2024) (attached)
www-data@Linux-Server:/tmp$

So clearly the two sessions can be read by the apache account, but not from PHP with exec. I tried shell_exec as well, but that provided the same result.

It also seems the user superfuzzy also had this issue. For them, downgrading to PHP 7.1 fixed the error. I am running PHP 8.3.3-1. Unfortunately, I cannot afford to downgrade to an older version, as much of my website infrastructure relies on new functions introduced in PHP 8.

The user superfuzzy also noticed the following

Another weird thing: when launching the tmux sessions over php the terminal has no user and no location Normally it looks like user@machinename$ ... With php it just looks like $ ... nothing more

And after a bit of digging, I found that this is caused by the fact that Apache2 uses '/bin/sh' as the shell. Which in Ubuntu, does not default to '/bin/bash' but to '/bin/dash', which from my understanding is a more lightweight and faster version of bash with a little less features. But from my testing, this should not affect tmux in any way.

I also tried creating a test.sh script and then executing /bin/bash on the script. The script is as follows:

#/bin/bash
echo "test script"
tmux ls

And the output: [ "test script", "no server running on /tmp/tmux-33/default" ]

So is there anything I can do, or maybe some alternatives to the exec() function? I'd really appreciate some advice.

Thank you.


Solution

  • The issue was caused by how the systemd service manager in linux allows access to the /tmp/folder. Or in other words, by how It does not.

    I was able to find out that all the files I was writing in the /tmp/ folder via PHP were actually being written to /tmp/systemd-private-<GUID>-apache2.service-mMSZ8e/tmp.

    This is a security feature implemented to disallow different services from snooping on data in the /tmp/ folder by using known file names. More on this can be read here.

    As tmux uses the /tmp/ folder to store sessions, It could not read the required files.

    There are two solutions to this problem

    The recommended approach

    This would require to point tmux to a know file using the -f parameter.

    Example:

    tmux -f /home/user1/tmux/knownfile
    

    Disabling Primate /tmp folder for Apache2 (not recommended)

    This would require to edit the systemd service for apache2 and setting PrivateTmp to false, this is not recommended as It could potentially introduce security issues with PHP scripts accessing sensitive files OR other programs accessing sensitive files of the scripts.

    It can be done by editing the file as follows:

    sudo nano /lib/systemd/system/apache2.service
    

    and then replace

    PrivateTmp=true
    

    with

    PrivateTmp=false