AppArmor DBus rules for AkonadiServer
ClosedPublic

Authored by lukaskaras on Apr 20 2020, 9:27 PM.

Details

Summary

When I build and install Akonadi (branch release/20.04) on Kubuntu 20.04, server was not able to start, because AppArmor denied access to DBus. I am not expert on AppArmor, but with these modifications, Akonadi is able to run.

Test Plan
  • build install Akonadi on distribution with AppArmor (for example Kubuntu 20.04)
  • start akonadi without applied patch, it should fail
  • with this patch, it should run properly

Diff Detail

Repository
R165 Akonadi
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
lukaskaras created this revision.Apr 20 2020, 9:27 PM
Restricted Application added a project: KDE PIM. · View Herald TranscriptApr 20 2020, 9:27 PM
Restricted Application added a subscriber: kde-pim. · View Herald Transcript
lukaskaras requested review of this revision.Apr 20 2020, 9:27 PM

@knauss, could you please take a look at this? I have no clue about apparmor... :)

This dbus feature was added with newer AppArmor versions - I havn't heard about it until today ;) But this makes totally sense that also DBus access it controlled.

apparmor/usr.bin.akonadiserver
21

Why Akonadi needs access to interface=org.freedesktop.DBus?

31

is this really necessary?

44

Replace with /usr/share/mysql/* r as mysql should be able to access its complete data.

63

[0-9]* can be replaced with @{pid} as it does not need to access other processes.

65

is this really necessary?

66

is this really necessary?

dvratil added inline comments.Apr 21 2020, 6:58 PM
apparmor/usr.bin.akonadiserver
21

Probably introspection, or listening to service added/removed signals

lukaskaras planned changes to this revision.Apr 22 2020, 8:09 AM

Thank you for comments, I will make two small changes.

apparmor/usr.bin.akonadiserver
21

without this line, akonadiserver fails with

[C] 363117 Akonadi::Server::AkonadiServer::init:174 - Unable to connect to dbus service:  "An AppArmor policy prevents this sender from sending this message to this recipient; type=\"method_call\", sender=\":1.2248\" (uid=1000 pid=363117 comm=\"/usr/bin/akonadiserver \" label=\"/usr/bin/akonadiserver (enforce)\") interface=\"org.freedesktop.DBus\" member=\"RequestName\" error name=\"(unset)\" requested_reply=\"0\" destination=\"org.freedesktop.DBus\" (bus)"

It seems that "send" operation is enough... So, I will remove "receive".

31

It seems that yes. AppArmor kernel module is blocking drkonqi execution otherwise.

from dmesg:

[126899.769752] audit: type=1400 audit(1587542245.999:1317): apparmor="DENIED" operation="exec" profile="/usr/bin/akonadiserver" name="/usr/lib/x86_64-linux-gnu/libexec/drkonqi" pid=370105 comm="ItemRetrievalMa" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0
44

ok, changing to whole subtree:

/usr/share/mysql/** r,
63

It needs access to mysqld (-akonadi) process, not itself. See this line https://cgit.kde.org/akonadi.git/tree/src/server/storage/dbconfigmysql.cpp#n314

65

Seems that yes. Some child process (thread?) wants to access it.

When this line is removed, I see this audit message in dmesg:

[126899.758977] audit: type=1400 audit(1587542245.987:1316): apparmor="DENIED" operation="connect" profile="/usr/bin/akonadiserver" name="/run/user/1000/kdeinit5__0" pid=369882 comm="ItemRetrievalMa" requested_mask="wr" denied_mask="wr" fsuid=1000 ouid=1000
66

Similar to previous. When I remove this line, AppArmor block creation of this directory/file.

dmesg:

[127294.059394] audit: type=1400 audit(1587542640.298:1362): apparmor="DENIED" operation="mknod" profile="/usr/bin/akonadiserver" name="/run/user/1000/kcrash_370375" pid=370375 comm="ItemRetrievalMa" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
lukaskaras updated this revision to Diff 80848.Apr 22 2020, 8:11 AM
  • removed "receive" operation for org.freedesktop.DBus
  • change read access to whole mysql subtree /usr/share/mysql/** r 

Wait you add mysql stuff to the akonadiserver, that is totally wrong! The problem is that the mysql-akonadi script is not triggering the correct profile. The workaround with mysql-akonadi script was added because mysql start shipping AppArmor and Kubuntu/Debian mainatiners at that time created this script to make sure to workaround the AppArmor of mysql. Because this was triggering issues for Debian unstable I set down and started to do a proper AppArmor profile for Akonadi and there I learnt, that the mysql-akonadi script is not needed at all.

So please add /user/bin/mysql-akonadi PUx -> mysqld_akonadi, to your profile to make sure, that this ends up in the correct AppArmor space and than reevaluate the needed changes.

And I strongly recommend to get rid of this script too.

see:
https://bugs.kde.org/show_bug.cgi?id=399346#c13
https://salsa.debian.org/qt-kde-team/kde/akonadi/-/commit/f8096655237e9b716d51c36213ecaae79b8108de
https://salsa.debian.org/qt-kde-team/kde/akonadi/-/commit/dfd61ab8158a6938a707bebab00650e518411921

apparmor/usr.bin.akonadiserver
44

Ah wait, this is completly wrong here. Mysql stuff is only inside apparmor/mysqld_akonadi.

And I strongly recommend to get rid of this script too.

I may try to do it later. But not in scope of this review ;-)

apparmor/usr.bin.akonadiserver
44

I don't wrote it explicitly, but this read access is not required by mysqld server, but mysql client (library?).

Dmesg without this line:

audit: type=1400 audit(1587620441.071:186): apparmor="DENIED" operation="open" profile="/usr/bin/akonadiserver" name="/usr/share/mysql/charsets/Index.xml" pid=23027 comm="akonadiserver" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

from akonadi strace:

[pid 23027] execve("/usr/bin/akonadiserver", ["/usr/bin/akonadiserver"], 0x7ffda6565e98 /* 71 vars */ <unfinished ...>
[pid 23027] <... execve resumed> )      = 0
...
[pid 23027] stat("/usr/share/mysql/charsets/Index.xml", {st_mode=S_IFREG|0644, st_size=19495, ...}) = 0
[pid 23027] openat(AT_FDCWD, "/usr/share/mysql/charsets/Index.xml", O_RDONLY) = -1 EACCES

But it is true, that rule should not be here when akonadi is build with postgresql support. Should I add move it to mysqld profile?

Okay I want to verify on my system first. I may find time to do this next week.

I'm very sorry that it takes that long, but I really want to understand why a line is needed. And I also learn AppArmor ;)

apparmor/usr.bin.akonadiserver
44

Still seems fishy to me. Because that means that qt somehow changed their way how to connect to mysql.

Should I add move it to mysqld profile?

we can't move this, as this is in process. it is no new binary that we can move to a different namespace.

Can you explain me how you get strace output for akonadi?

Can you explain me how you get strace output for akonadi?

Stop Akonadi and start it with AKONADI_DEBUG_WAIT=akonadiserver, which will start the Akonadi Server and send it SIGSTOP immediately

AKONADI_DEBUG_WAIT=akonadiserver
akonadictl start

In another terminal, attach strace to the Akonadi server process:

strace -f -p $(pidof akonadiserver)

In the first terminal, send SIGCONT to Akonadi to resume it

kill -SIGCONT $(pidof akonadiserver)

Can you explain me how you get strace output for akonadi?

Or you can just stop whole akonadi, kill akonadi_control and start strace -f /usr/bin/akonadi_control 2>&1 | tee strace.log

knauss added a comment.May 6 2020, 6:27 PM

Thanks dvratil and lukaskaras for explaining me how to debug Akonadi - I haven't done it yet. Btw. is there documentation existing for this?

For my local kdepim 20.04 upgrade + mariadb 1:10.3.22-1 on Debian Sid. I need no modifications from the shipped ones to run my kdepim setup afterwards successfully ( and it is running for more than one day already :):

  • kcrash and drkonqi - this only happens, if Akonadi crashes and it does not crash for me yet - fully accepted
  • dbus interface, this is a new way to lockdown dbus usage - fully accepted
  • kdeinit - @dvratil does Akonadi uses/needs kdeinit?

In the end we have those two modifications /usr/share/mysql/** and @{PROC}/[0-9]*/stat that I do not get, why it does not explode for me.
So I want to understand, why you need such stuff and I don't:
@lukaskaras:

  • Do you use MariaDB or Mysql?
  • Do you test a new installation or running an existing one?

Both are points that already made in the past big difference for AppArmor profile and may explain the difference.

@lukaskaras - I'm very sorry that I am such an nip-picker on this issue. I hope you understand, that AppArmor only gives us more security, if we only allow the needed stuff. I see that it is your second proposed patch on Phabricator - and than such a hard one, that keeps you busy for a long time - I hope I do not scared you off from this team because of my reaction. I hope you still will propose more patches, normally patches get merged without such a lot discussion. I really enjoy that others enable AppArmor and also proposing patches and also like the really detailed answers from your side.

Re documentation: It's partially documented here: https://techbase.kde.org/KDE_PIM/Akonadi/Development_Tools - strace is not documented as far as I can see
Re kdeinit: Akonadi does not use kdeinit at all

lukaskaras added a comment.EditedMay 7 2020, 7:41 AM
  • kcrash and drkonqi - this only happens, if Akonadi crashes and it does not crash for me yet - fully accepted

You may try to abort akonadi server by command:

killall -s ABRT akonadiserver

it should trigger Dr Konqi for your akonadiserver process

In the end we have those two modifications /usr/share/mysql/** and @{PROC}/[0-9]*/stat that I do not get, why it does not explode for me.
So I want to understand, why you need such stuff and I don't:
@lukaskaras:

  • Do you use MariaDB or Mysql?

I am using MySQL 8.0.20.

from /usr/share/mysql/charsets/README:

Index.xml
    The Index.xml file lists all of the available charset configurations,
    including collations.

    Each collation must have a unique number.  The number is stored
    IN THE DATABASE TABLE FILES and must not be changed.

    The max-id attribute of the <charsets> element must be set to
    the largest collation number.

and from configuration I just found this path:

mysql> show variables like 'character_sets_dir';
+--------------------+----------------------------+
| Variable_name      | Value                      |
+--------------------+----------------------------+
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------+----------------------------+
1 row in set (0.00 sec)

It is possible that MariaDB store these files somewhere else...

  • Do you test a new installation or running an existing one?

It is existing installation. For clean installation, I would need to seetup virtual system...

Both are points that already made in the past big difference for AppArmor profile and may explain the difference.

Understand. There is always possibility that I made some configuration change that I forgot.

@lukaskaras - I'm very sorry that I am such an nip-picker on this issue. I hope you understand, that AppArmor only gives us more security, if we only allow the needed stuff. I see that it is your second proposed patch on Phabricator - and than such a hard one, that keeps you busy for a long time - I hope I do not scared you off from this team because of my reaction. I hope you still will propose more patches, normally patches get merged without such a lot discussion. I really enjoy that others enable AppArmor and also proposing patches and also like the really detailed answers from your side.

No problem, I am patient :-) It is more frustrating when you spend few hours with patch and receive no reply at all... I am happy that akonadi project is alive and has active community...

knauss accepted this revision.May 22 2020, 5:25 PM
  • kcrash and drkonqi - this only happens, if Akonadi crashes and it does not crash for me yet - fully accepted

You may try to abort akonadi server by command:

killall -s ABRT akonadiserver

it should trigger Dr Konqi for your akonadiserver process

thanks for this idea to break the Akonadi process. Okay I used this methods to test this on my system and I need these two lines added:

ptrace read peer=mysqld_akonadi,
owner /{,var/}run/user/@{uid}/kcrash** rwk,
mysql> show variables like 'character_sets_dir';
+--------------------+----------------------------+
| Variable_name      | Value                      |
+--------------------+----------------------------+
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------+----------------------------+
1 row in set (0.00 sec)

Same for my system but do not need to add /usr/share/mysql/, strange. I also can verify that it is accessed by akonadiserver via strace. Maybe the default Apparmor rules differ for Ubuntu and Debian.

Okay I think adding /usr/share/mysql/ won't hurt as there is no private data inside.

Let's add this and we reevalute this later.

This revision is now accepted and ready to land.May 22 2020, 5:25 PM
This revision was automatically updated to reflect the committed changes.