Hi all,
this weekend I spent some time on trying to get kscreenlocker_greet into
a sandbox through libseccomp. My aim was to make it impossible for a lnf
package to intercept the password and e.g. write it to a file.
In this mail I want to outline my findings.
First of all, what does libseccomp allow:
It is a filter on syscalls and you can filter on the arguments of the
syscall. The filter can then allow, make it fail with errno, raise a
signal or just crash.
My first approach was to install the filtering prior to any QtQuick
interaction and deny all syscalls and whitelist the syscalls which are
used. The approach utterly failed. After something like 40 syscalls I
gave up on the approach as I still wasn't seeing the window.
Next approach: allow everything and deny the syscalls which would allow
writing out the password. This kind of works, but not really.
We cannot disallow write as that is needed to wake up threads. So
instead let's disallow open for files with write.
Problem 1: OpenGL needs to open /dev/dri/card* with write mode, which
means QtQuick would fail. The seccomp filter does not allow to filter on
the path in open. It can only compare pointer values but not pointer
content. Thus I cannot check whether the path includes e.g. /dev/dri/
and allow that.
I solved this by ensuring Qt inits OpenGL prior to installing the
seccomp filter.
At that point the greeter loaded and showed the view. I am able to see
that my filter works as KSharedDataCache reports that it cannot open
files for writing (fine).
But I'm not able to authenticate any more. The seccomp filter gets
inherited to forked processes and cannot be disabled any more (the idea
is that you cannot escape the sandbox). KScreenlocker forks+exec
kcheckpass and that somehow opens a file in write mode for the pam
interaction.
Kcheckpass only allows to be run once, so I cannot start it early
enough.
At that point I'm currently stuck. I have huge problems understanding
the kcheckpass source code, what it does and how to debug it.
I think the approach taken can work, but would need to change the PAM
interaction. Given that our code is ancient, that would not be the worst
thing to do.
So the lessons learned: libseccomp is difficult to use as the
documentation is bad. The claim is that everything is documented, but
it's documented in a way that it's obvious for the one familiar with it.
For someone not familiar with libseccomp it's quite difficult to use.
An application interacting with OpenGL and DBus has too many syscalls to
use a whitelist approach. Also we don't get to the fds we need to allow
stuff for.
Seccomp needs to be installed quite late in the process. E.g. if we
would want to use it in KWin_Wayland it would only make sense to install
it after all the init work is done and the window manager is fully
running.
How it could be used in future:
* in kscreenlocker it would be nice to solve the PAM interaction problem
and then get open/write disabled also network access would be nice to
get disabled
* in KWin_Wayland a disallow of open/write could also make sense once
everything is started, but would only work once the kscreenlocker issue
is resolved
* in KWin_Wayland disabling network access could be useful
* baloo could use it for the file extractors to prevent the
Chrome+download vulnerability
Cheers
Martin