[systemd-devel] [PATCH] selinux: fix missing SELinux unit access check
HATAYAMA Daisuke
d.hatayama at jp.fujitsu.com
Tue Jun 9 20:55:55 PDT 2015
From: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
Subject: Re: [systemd-devel] [PATCH] selinux: fix missing SELinux unit access check
Date: Wed, 10 Jun 2015 12:18:48 +0900 (JST)
> 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
>
Also, I used selinux-context branch of
https://github.com/keszybz/systemd.git in this test to avoid the issue
in https://bugzilla.redhat.com/show_bug.cgi?id=1224211.
--
Thanks.
HATAYAMA, Daisuke
More information about the systemd-devel
mailing list