[systemd-devel] [PATCH] selinux: fix missing SELinux unit access check

HATAYAMA Daisuke d.hatayama at jp.fujitsu.com
Tue Jun 9 20:18:48 PDT 2015


From: Lennart Poettering <lennart at poettering.net>
Subject: Re: [systemd-devel] [PATCH] selinux: fix missing SELinux unit access check
Date: Mon, 8 Jun 2015 12:37:14 +0200

> On Mon, 08.06.15 19:00, HATAYAMA Daisuke (d.hatayama at jp.fujitsu.com) wrote:
> 
>> Currently, SELinux unit access check is not performed if a given unit
>> file has not been registered in a hash table. This is because function
>> manager_get_unit() only tries to pick up a Unit object from a Unit
>> hash table. Instead, we use function manager_load_unit() searching
>> Unit file pathes for the given Unit file.
> 
> Were precisely is this relevant? I mean, we generally invoke
> operations on units that are already loaded?
> 

The SELinux unit access check is performed in terms of the following rule:

~]# sesearch -A -s init_t | grep "systemd_unit_file_type" | grep service
   allow init_t systemd_unit_file_type : service { start stop status reload kill load enable disable } ;

where systemd_unit_file_type is the attribute that is assigned to
context types that unit files have, e.g. systemd_unit_file_t.

Because this SELinux unit access check uses context types that unit
files have, we need to be able to refer to given unit files when we
perform requested unit operations.

Here's how to reproduce this issue. Note that:

- the systemd used here is with the fixing patch, and

- test.service has not been loaded (even tried to get loaded)
  throughout this boot to guarantee that test.service is not registered
  in the unit hash table.

Then,

~]# cat ./test.service
[Unit]
Description=test

[Service]
Type=oneshot
ExecStart=/usr/bin/true
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
~]# cat ./foo.sh
#! /bin/sh

mv test.service /etc/systemd/system
systemctl daemon-reload
systemctl enable test.service
~]# ./foo.sh

Then, here is a gdb log:

break mac_selinux_unit_access_check_strv
Breakpoint 1 at 0x7f5339807a28: file src/core/selinux-access.c, line 288.
(gdb) continue
Continuing.
Detaching after fork from child process 2198.

Breakpoint 1, mac_selinux_unit_access_check_strv (units=0x7f533a1324f0, message=0x7f533a166a10, m=0x7f533a07c680, permission=0x7f533992bdb6 "enable", error=0x7ffe80abaec0) at src/core/selinux-access.c:288
288                                     sd_bus_error *error) {
(gdb) l
283
284     int mac_selinux_unit_access_check_strv(char **units,
285                                     sd_bus_message *message,
286                                     Manager *m,
287                                     const char *permission,
288                                     sd_bus_error *error) {
289     #ifdef HAVE_SELINUX
290             char **i;
291             Unit *u;
292             int r;
(gdb) n
294             STRV_FOREACH(i, units) {
(gdb) n
295                     r = manager_load_unit(m, *i, NULL, error, &u);
(gdb) s
manager_load_unit (m=0x7f533a07c680, name=0x7f533a11ef30 "test.service", path=0x0, e=0x7ffe80abaec0, _ret=0x7ffe80abad80) at src/core/manager.c:1369
1369            assert(m);
(gdb) n
1374            r = manager_load_unit_prepare(m, name, path, e, _ret);
(gdb) n
1375            if (r != 0)
(gdb) n
1378            manager_dispatch_load_queue(m);
(gdb) p r
$1 = 0

Here variable r has a return value of manager_load_unit_prepare() and
its value is 0 here, meaning that now there's no unit file with the
requested unit file name in the unit hash table.

(gdb) p *_ret
$2 = (Unit *) 0x7f533a166ea0
(gdb) p *_ret->load_state
Attempt to take contents of a non-pointer value.
(gdb) p (*_ret)->load_state
$3 = UNIT_STUB

Actually, its load_state is still UNIT_STUB.

(gdb) n
1380            if (_ret)
(gdb) p (*_ret)->load_state
$4 = UNIT_LOADED

After dipatching the load queue by manager_dispatch_load_queue(), the
given unit file has just been loaded and the load_state has been
changed into UNIT_LOADED.

(gdb) finish
Run till exit from #0  manager_load_unit (m=0x7f533a07c680, name=0x7f533a11ef30 "test.service", path=0x0, e=0x7ffe80abaec0, _ret=0x7ffe80abad80) at src/core/manager.c:1380
0x00007f5339807a6a in mac_selinux_unit_access_check_strv (units=0x7f533a1324f0, message=0x7f533a166a10, m=0x7f533a07c680, permission=0x7f533992bdb6 "enable", error=0x7ffe80abaec0) at src/core/selinux-access.c:295
295                     r = manager_load_unit(m, *i, NULL, error, &u);
(gdb) continue


>> Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
> 
> We don't use S-o-b in systemd.
> 

Sorry, I'll not use the tag next. I decided to use it becuase I found
commits with the tag in git log (of course, I found the commits
without the tag, too).

--
Thanks.
HATAYAMA, Daisuke



More information about the systemd-devel mailing list