Re: [PATCH] sepolicy: Allow bluetooth to send D-Bus messages to systemd

Wei Deng <[email protected]> Thu, 9 Apr 2026 19:36:04 +0800
Newsgroups org.kernel.vger.selinux-refpolicy
Message-ID <[email protected]>
Hi Chris,

On 4/7/2026 8:40 PM, Christopher J. PeBenito wrote:
> On 4/4/26 5:19 AM, Wei Deng wrote:
>> Hi Chris,
>>
>> Thanks for the review.
>>
>> On 4/3/2026 10:01 PM, Christopher J. PeBenito wrote:
>>> On 4/3/26 2:31 AM, Wei Deng wrote:
>>>> Add init_dbus_chat() for bluetooth_t to allow bluetoothd to send
>>>> D-Bus method_return messages back to systemd (init_t) over the
>>>> system bus.
>>>>
>>>> Below avc denial is fixed with this patch:
>>>>
>>>> avc:  denied  { send_msg } for  msgtype=method_return dest=:1.11
>>>> scontext=system_u:system_r:bluetooth_t:s0
>>>> tcontext=system_u:system_r:init_t:s0 tclass=dbus permissive=0
>>>>
>>>> Signed-off-by: Wei Deng <[email protected]>
>>>> ---
>>>>    policy/modules/services/bluetooth.te | 1 +
>>>>    1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/policy/modules/services/bluetooth.te b/policy/modules/services/bluetooth.te
>>>> index ceb42d147..a73cb5db0 100644
>>>> --- a/policy/modules/services/bluetooth.te
>>>> +++ b/policy/modules/services/bluetooth.te
>>>> @@ -136,6 +136,7 @@ userdom_dontaudit_search_user_home_dirs(bluetooth_t)
>>>>    optional_policy(`
>>>>        dbus_system_bus_client(bluetooth_t)
>>>>        dbus_connect_system_bus(bluetooth_t)
>>>> +  init_dbus_chat(bluetooth_t)
>>>>        init_dbus_send_script(bluetooth_t)
>>>>          optional_policy(`
>>> Can you confirm this response is going to systemd/pid1? Is there a fuller set of log messages corresponding to this denial? The init_dbus_send_script() makes me wonder.
>> The two log entries list here:
>>
>>    type=SERVICE_START msg=audit(19.419:292): pid=1 uid=0
>>      subj=system_u:system_r:init_t:s0
>>      msg='unit=bluetooth comm="systemd"
>>      exe="/usr/lib/systemd/systemd" ... res=success'
>>
>>    type=USER_AVC msg=audit(19.547:319):
>>      subj=system_u:system_r:system_dbusd_t:s0
>>      msg='avc: denied { send_msg } for msgtype=method_return
>>      dest=:1.11 spid=684 tpid=843
>>      scontext=system_u:system_r:bluetooth_t:s0
>>      tcontext=system_u:system_r:init_t:s0
>>      tclass=dbus permissive=0
>>      exe="/usr/bin/dbus-daemon"'
>>
>>> Can you confirm this response is going to systemd/pid1?
>>> Is there a fuller set of log messages corresponding to this denial?
>> Yes. The SERVICE_START entry shows pid=1 with
>> exe="/usr/lib/systemd/systemd" running under init_t, confirming that
>> init_t is systemd's SELinux domain.
> 
> These two audit messages are not related, as they have different event IDs (292 vs 319). Additionally, SERVICE_START messages are expected to come from pid=1.
> 

> Can you confirm this response is going to systemd/pid1?
> Is there a fuller set of log messages corresponding to
> this denial?

You are right. I apologize for the confusion. The two audit
messages are unrelated, as they have different event IDs.

Here is the full AVC denial:

  type=USER_AVC msg=audit(1773416627.807:455):
    pid=801 uid=997 auid=4294967295 ses=4294967295
    subj=system_u:system_r:system_dbusd_t:s0
    msg='avc: denied { send_msg } for
    msgtype=method_return dest=:1.27
    spid=1942 tpid=1944
    scontext=system_u:system_r:bluetooth_t:s0
    tcontext=system_u:system_r:init_t:s0
    tclass=dbus permissive=0
    exe="/usr/bin/dbus-daemon"'

The tpid=1944 is obexd, not systemd/pid1, as confirmed by:

  ps -p 1944 -o pid,ppid,comm,exe,label
      PID  PPID COMMAND  EXE                           LABEL
     1944     1 obexd    /usr/libexec/bluetooth/obexd  system_u:system_r:init_t:s0

So the real issue is not bluetooth_t -> init_t (systemd),
but bluetooth_t -> init_t (obexd running in the wrong domain).

The root cause is that obex.te currently uses
userdom_user_application_domain(), which does not create a
domain transition from init_t. obexd therefore inherits
systemd's domain instead of transitioning to obex_t.

The fix is to replace userdom_user_application_domain()
with init_daemon_domain() in obex.te:

  -attribute_role obex_roles;
  -
   type obex_t;
   type obex_exec_t;
  -userdom_user_application_domain(obex_t, obex_exec_t)
  -role obex_roles types obex_t;
  +init_daemon_domain(obex_t, obex_exec_t)

With this change, obexd correctly transitions to obex_t:

  ps -eZ | grep obexd
  system_u:system_r:obex_t:s0  986  ?  00:00:00 obexd

This shifts the denial from bluetooth_t -> init_t to
bluetooth_t -> obex_t, which is the correct relationship
to address in policy.

If this approach is acceptable, I will submit a follow-up
patch to update the obex policy accordingly, including
fixing the resulting AVC denials for obex_t.

Would you have any concerns or suggestions?


> 
>>> The init_dbus_send_script() makes me wonder.
>> They target different domains:
>>
>>    init_dbus_send_script(): bluetooth_t -> initrc_t (SysV init scripts)
>>    init_dbus_chat():        bluetooth_t <-> init_t  (systemd itself)
>>
>> Both are needed for cross-platform compatibility.
> 
> initrc_t also exists on systemd systems for generic commands run from systemd units. However, if these rules are needed for sysvinit vs systemd, then these two rules should be put in an if/else of an init_systemd block.
> 
> 

-- 
Best Regards,
Wei Deng