익명 12:01

PHP code cannot connect to NetworkManager

PHP code cannot connect to NetworkManager

I need to access Network Manager functionality from PHP code by exec()-ing the "nmcli" command. However, when run from PHP code, "nmcli" command returns the error message "Network Manager is not running" and does nothing.

Network Manager is running and I can successfully run "nmcli" command from the command line even as the Apache user. I suspected it has something to do with the lack of DBUS_SESSION_BUS_ADDRESS environment variable in the environment in which PHP is running (and of course lack of the actual socket this variable points to) but probably it's not that issue, because when I run the "nmcli" command from command line with strace, I can see that it doesn't access that socket at all.

I suspected some SELinux issue, but I don't see any recent denials in the audit logs.

I don't know where to search. It's a standard Apache/PHP (FPM) installation on a RHEL10 OS.

Edit: The problem is not only in PHP. I wrote a simple CGI shell script that tries to run "nmcli" and it gives the same error message run directly by Apache webserver.

So it looks that both services (Apache and PHP-FPM) don't "see" something that is needed to connect to Network Manager. What is that "something" and how to make the services "see" it?

Edit 2: With regard to @sofia 's answer below, output of the commands systemctl status NetworkManager and busctl list differs in CGI script run within Apache and in PHP.

In CGI script systemctl displays Failed to get properties: Access denied, and busctl shows basically nothing:

NAME                                          PID PROCESS USER CONNECTION    UNIT SESSION DESCRIPTION
:1.2                                            - -       -    -             -    -       -
org.freedesktop.NetworkManager                  - -       -    -             -    -       -

(I'm including :1.2 because that's the endpoint that seems to be actually assigned to Network Manager when busctl is run from the shell - as I show later). Also I see a denial in ausearch -m avc -ts recent output regarding to systemctl process and a lot of denials regarding to busctl process. There are no denials regarding to nmcli, however (which is also run within the script).

In PHP, it's the same Failed to get properties: Access denied message from systemctl, but busctl output is different:

NAME                                             PID PROCESS USER    CONNECTION    UNIT            SESSION DESCRIPTION
:1.2                                            2403 n/a     root    :1.2          -               -       -
org.freedesktop.NetworkManager                  2403 n/a     root    :1.2          -               -       -

This time, there are no denials in ausearch output.

sudo -u apache nmcli run from the shell works correctly, as well as sudo -u apache busctl. This time the output is (the same as with busctl run directly from root):

NAME                                             PID PROCESS         USER    CONNECTION    UNIT                     SESSION DESCRIPTION
:1.2                                            2403 NetworkManager  root    :1.2          NetworkManager.service   -       -
org.freedesktop.NetworkManager                  2403 NetworkManager  root    :1.2          NetworkManager.service   -       -

Obviously NetworkManager service is visible when busctl is run from the shell, but is not visible when it's run either from PHP or from Apache directly (in the latter case it may be due to SELinux denials, in the former no denials are reported).

systemctl cat httpd shows a lot of sandboxing options active (I included all that I suppose may have impact, I'm not sure if all of them actually do):

DevicePolicy=closed
KeyringMode=private
LockPersonality=yes
MemoryDenyWriteExecute=yes
PrivateDevices=yes
PrivateTmp=true
ProtectClock=yes
ProtectControlGroups=yes
ProtectHome=read-only
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectSystem=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes

In systemctl cat php-fpm however, the only such option is PrivateTmp=true, which probably has no impact.

I don't care about Apache itself, the CGI script has been run only for test, what I really need is to run nmcli from PHP. I see no restrictions here.

I did strace in both cases you indicated, but the traces are too long to include here. However, in case when nmcli is run directly from the shell, strace doesn't show any access to any sockets. After loading all the libraries, locales etc. resources the process just does a lot of futex() calls, then displays output.

When it's run from PHP, after similar loading of libraries etc. there is a bunch of futex(), mprotect() and mmap() calls, of which quite a few seem probably unsuccessful(?), as they have the <unfinished> comment in strace output. Then there's open of the socket /run/dbus/system_bus_socket and an exchange on that socket which looks probably(?) like enumeration of services available on the bus. After several queries and replies, the following message is visible coming from the socket:

231390 recvmsg(6, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\5\1u\0\n\0\0\0\7\1s\0\24\0\0\0org.freedesktop.DBus\0\0\0\0\4\1s\0'\0\0\0org.freedesktop
.DBus.Error.AccessDenied\0\10\1g\0\1s\0\0\6\1s\0\7\0\0\0:1.5089\0(\0\0\0Sender is not authorized to send message\0", iov_len=157}], msg_iovlen=1, msg_control
len=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 157

after which nmcli writes the Network Manager is not running message and exits.

There's also the log message in /var/log/messages:

Jun 12 11:50:26 xymon dbus-broker[2402]: A security policy denied :1.5460 to sen
d method call /org/freedesktop:org.freedesktop.DBus.ObjectManager.GetManagedObje
cts to :1.2.

So that's probably the root cause why PHP cannot access network Manager. How to modify this security policy?



Top Answer/Comment:

As was confirmed in the discussion in comments, the problem is SELinux. The web server most likely runs in httpd_t context and this context is not allowed sending messages to the context NetworkManager runs in (NetworkManager_t):

bor@uefi:~> ps -efZ | grep httpd
system_u:system_r:httpd_t:s0    root        4059       1  0 17:59 ?        00:00:00 /usr/sbin/httpd-prefork -DSYSCONFIG -C PidFile /run/httpd.pid -C Include /etc/apache2/sysconfig.d//loadmodule.conf -C Include /etc/apache2/sysconfig.d//global.conf -f /etc/apache2/httpd.conf -c Include /etc/apache2/sysconfig.d//include.conf -DSYSTEMD -DFOREGROUND -k start
...
bor@uefi:~> ps -efZ | grep NetworkManager
system_u:system_r:NetworkManager_t:s0 root  1153       1  0 17:39 ?        00:00:00 /usr/sbin/NetworkManager --no-daemon
...
bor@uefi:~> sesearch -A -s httpd_t -t NetworkManager_t -c dbus -p send_msg
bor@uefi:~> 

All types for which sending messages is allowed can be listed with

bor@uefi:~> sesearch -A -t NetworkManager_t -c dbus -p send_msg
allow NetworkManager_dispatcher_t NetworkManager_t:dbus send_msg;
allow NetworkManager_dispatcher_tlp_t NetworkManager_t:dbus send_msg;
allow NetworkManager_ssh_t NetworkManager_t:dbus send_msg;
allow NetworkManager_t NetworkManager_t:dbus send_msg;
allow afterburn_t NetworkManager_t:dbus send_msg;
allow apmd_t NetworkManager_t:dbus send_msg;
...

You can check the contexts other services are using, but I expect the same.

The D-Bus rules are enforced by D-Bus daemon (dbus-broker in your case), so the denial messages will not appear in the audit log. When using systemd-journald, dbus-broker logs the reason for denial as the DBUS_BROKER_POLICY_TYPE field. So

bor@uefi:~> sudo journalctl --system -u dbus-broker.service  -o verbose --output-fields DBUS_BROKER_POLICY_TYPE,MESSAGE DBUS_BROKER_POLICY_TYPE=selinux
Sun 2026-03-08 20:00:40.445549 MSK [s=497fd528eab64ed29b6d1d3b939d2efd;i=2b638b;b=afbc2f5f50a9425ca4c064b0fc9>
    DBUS_BROKER_POLICY_TYPE=selinux
    MESSAGE=A security policy denied :1.106 to send method call /org/freedesktop/login1:org.freedesktop.login>
-- Boot cc6d2b08a37b44e0a23c28f080cf11d2 --
Sun 2026-03-08 20:05:42.630123 MSK [s=497fd528eab64ed29b6d1d3b939d2efd;i=2b6d96;b=cc6d2b08a37b44e0a23c28f080c>
    DBUS_BROKER_POLICY_TYPE=selinux
    MESSAGE=A security policy denied :1.23 to send method call /org/freedesktop/login1:org.freedesktop.login1>
-- Boot 3808ff15229641b5b8468aed6a245328 --
Sat 2026-03-21 09:52:04.282292 MSK [s=497fd528eab64ed29b6d1d3b939d2efd;i=2b75f0;b=3808ff15229641b5b8468aed6a2>
    DBUS_BROKER_POLICY_TYPE=selinux
    MESSAGE=A security policy denied :1.25 to send method call /org/freedesktop/login1:org.freedesktop.login1>

bor@uefi:~> 

These denials are due to SELinux, not the internal D-Bus policy.

Your options are - running web server unconfined or adding custom SELinux module to allow sending messages from the context of your service(s). Something like (untested):

bor@uefi:~/x> cat localpolicy.te
module localpolicy 1.0;

require {
  type httpd_t;
  type NetworkManager_t;
  class dbus { send_msg };
}

allow httpd_t NetworkManager_t:dbus send_msg;
bor@uefi:~/x> checkmodule -m localpolicy.te -o localpolicy.mod
bor@uefi:~/x> semodule_package -o localpolicy.pp -m localpolicy.mod
bor@uefi:~/x> sudo /usr/sbin/semodule -i localpolicy.pp 
bor@uefi:~/x> 
상단 광고의 [X] 버튼을 누르면 내용이 보입니다