[apparmor] File delegation
Ángel González
ingenit at zoho.com
Thu Dec 8 23:17:35 UTC 2011
How hard would it be to have a dynamic list of rules (paths) per process?
They would need to be on a different structure than the dfa, not shared
between instances.
In this old mail you mentioned file delegation as passing an open file, but
I'd extend that to delegation of full paths, so programs don't need to
be changed,
yet only include their requisites in their dfa.
On 06/08/10 01:05, John Johansen wrote:
> File delegation (of authority) is the ability to pass an opened file to
> a delegate task, giving it access to the delegated file even if the
> policy being applied to the delegate would not ordinarily allow it.
>
> Delegation can allow for tighter profiles, while at the same time making
> them more flexible (think of sec comp), the trade off being that the
> profile no longer contains a static listing of all possible permissions.
> This does make analysis of policy more difficult but it is still possible
> using tools that can do flow analysis.
I view two ways of delegation:
- Explicit delegation through a special interface (eg. writing the
permissions and path
to /proc/$PID/attr/delegations).
- Automatic delegation by rules defined in the profile (eg. allow read
access to argv[1]).
With the obvious restriction that the authorization must be a subset of
that hold by the
authoriser.
Why would this be useful?
Let's take a look to a common case to be jailed: a profile for an
internet browser.
We find rules such as:
# Default profile allows downloads to ~/Downloads and uploads from ~/Public
owner @{HOME}/Public/** r,
owner @{HOME}/Downloads/** rw,
This is annoying. Aunt Tillie should be able to upload
@{HOME}/personal/photo1.jpg
to facebook without having to make a copy in public before. And download to
@{HOME}/funny/powerpoints/viewthis.pps without risking
@{HOME}/work/report2011.pdf
And yet it's incomplete, as there could be a copy in
~/Downloads/report2011.pdf since last
week when she downloaded it from gmail.
IMHO with the above feature, this can easily implemented with a trusted
program doing the
Open/Save as dialog. When a 'Save as' is started, the library would
route the call to that monitor
(it's a library call, so no code changes needed in the end program, it's
even doable by LD_PRELOAD)
The monitor then shows a trusted dialog [1] where the user selects the
file to open/write. Then, just
before returning control to the browser, it increments the caller
profile with that exact path [2].
This has been proposed before in the realm of chrooting a process and
doing all accesses by fd-passing
through a monitor, but that has the inconvenience of creating the chroot
with all the needed files.
AppArmor beautifully allows to solve it by allowing us to keep the
process in the normal filesystem, but
with access only to its files (eg. /usr/lib/*, ~/.mozilla/**).
I proceed now to automatic delegation. The goal is to provide access
just to the files the application is
expected to use. How do you tell evince which pdf it should open? They
could be anywhere in the filesystem,
from /home, to /usr/share/docs, in /tmp or a cdrom inside /media. But no
matter if the user opened it clicking
the icon in a folder, or if it's the browser what launched it. It gets
access to open it because that's how it's
supposed to work. The file could be in its final location inside $HOME,
at /tmp or inside ~/.mozilla/cache/0F3A/foo.pdf
(where it would _usually_ not need to read anything). It just works.
Worst case: the file contains evil javascript,
exploits a buffer overflow and tries to send all your data to a zombie
network. It isn't allowed to mess with
anything but the given file (and in this instance even read-only!), so
the adversary is defeated.
I have to admit that evince is an easy target, since it uses an instance
per file and does only one thing. It's harder
to make that isolation for processes which open new files in a existing
instance. There the automatic delegation
would need to catch the authorization flowing from the new instance to
the old, in order to increase the credentials
of the old one (I think they send the arguments through a socket, but
will probably vary a lot between programs),
and if that fat process went mad when opening that powerpoint, it could
corrupt the document with the payroll
you had open (in that case, opening the file needs to provide rw, so
that Save "just works").
If you want to open a suspicious document, you need to close the
previous instance so that it isn't reused (the whole
program, although with little code modification it could be changed to
drop the privileges for that file when closing the
document). Not much can be done from the outside. It's the program what
needs to be changed. Either to spawn new
instances or, if they need to be preloaded in memory, they could use a
zygote which forks for each document with the
appropiate rights.
I answer below the details for the other model, as there's an overlap
betwen
both also may also apply.
> Beyond those basics there are several details to be determined.
>
> 1. Whether the delegatee profile should have rules controlling receiving of
> delegated files.
The profile would contain what is being delegated (eg. second argument)
and how.
It would just specify in the profile the contract used by the program
parameters.
I don't think it should try to specify what profiles it could receive
files from. On the
contrary, it would be the caller, if any, the one to specify that "this
call shouldn't
delegate access".
> 2. Whether delegation rules should cover implicit, explicit delegation,
> or both. For the purpose of this discussion, explicit delegation occurs
> when a task deliberately marks a file for delegation, where implicit
> delegation occurs when a file is passed without the task taking any
> explicit action to mark the file.
As this proposal with paths, the rules would cover which strings get
interpreted
as paths, thus delegating the access. Attacks against this model would
involve
tricking a process into passing a capability unbeknown to it (eg. while
it believes
to be passing a caption). I find hard to trick an innocent app to pass
an arbitrary
string to a new (evil) process, though.
>
> 3. How delegated files are inherited
> When a file is delegated to a child does the authority to access that
> file also pass down to grand children?
>
> Also can a child explicitly delegate a file it has inherited access
> permission to? That is the right to explicitly redelegate an open file
> may be different than permission to implicitly inherit said file.
I would allow subdelegation by default. Suppose the program were a shell
script: it would *need* to pass the file to it's commands. But there
could be a
flag to restrict it.
>
> 4. How delegation should be expressed in policy
> So I don't have any great ideas on this, and suggestions are more than
> welcome, basically it will depend on how much we want to be able to
> specify and some of the choices made above.
I don't have any preference. It could be something like:
argument "$1" rw
argument "$1~" rw
argument "$2-*" r
Note that a bit of parsing would be needed in the kernel to extract $1
as the first
argument which is not an option, or the argument for the "-o" option.
They are straightforward, though.
Thanks for your patience reading so far :)
You can voice now your objections.
1- It's unspecified how it is done. The X11 protocol doesn't have
provisions to easily do so. But
although an integral part of making the whole secure, it should be
solved separatedly.
2- The monitor would need a few per-process rules such as not only
allowing $FILENAME, but also
.$FILENAME.part
More information about the AppArmor
mailing list