On Sun, Sep 26, 2010 at 7:46 AM, Tetsuo Handa
<[email protected]> wrote:
>
> Radoslaw Szkodzinski wrote:
> > The hook would check the mask of the argument of mprotect, rejecting
> > PROT_EXEC | PROT_WRITE, check whether a formerly PROT_WRITE page is
> > being now mprotect()ed to PROT_EXEC
> > or vice versa.
>
> It will be possible to reject A-2 and B-2 below
>
> (Step A-1) Create a vma as PROT_WRITE .
> (Step A-2) Change that vma to PROT_EXECUTE .
>
> (Step B-1) Create a vma as PROT_EXECUTE .
> (Step B-2) Change that vma to PROT_WRITE .
>
> by doing
>

Do not touch vm_flags directly. grSecurity does that, because it's not
an LSM hook...
As I said before, mainline developers might not like touching them from a hook.

Fixed:
  if ((reqprot & (VM_MAYWRITE | VM_MAYEXEC)) ^ (prot & (VM_MAYWRITE |
VM_MAYEXEC))) &&
>       !ccs_capable(CCS_USE_WRITABLE_EXECUTABLE_VMA))
>    return -EPERM;

(or possibly with the check of vma->vm_flags_ever_specified like that below ;) )

This means that pages already marked write and executable would stay
that way and not throw -EPERM
when being marked VM_MAYREAD.

>
> inside security_file_mprotect(vma, reqprot, prot).
>
> But it is impossible to reject C-3 below
>
> (Step C-1) Create a vma as PROT_WRITE .
> (Step C-2) Change that vma to PROT_READ .
> (Step C-3) Change that vma to PROT_READ|PROT_EXECUTE .
>

Correct, this needs storage of the flags ever set on said mapping.
grSecurity seems to have a hole here.

> unless "struct vm_area_struct" has a variable which remembers the bitwise OR 
> of
> PROT_* flags ever specified since the moment a vma was created. I need to add

Yes, exactly, that would close the hole if there were such a
bitfield... That would go into vm_area_struct.

> Also, I think
>
> (Step D-1) Create a vma as PROT_WRITE|PROT_EXECUTE .
>
> is possible by using mmap().

Yes, but only of an anonymous mapping, file mapping can be stopped
with deny_open.
This should be caught too, possibly by adding a new LSM hook...

> If D-1 is possible, checking it at security_file_mprotect() is not sufficient.
> What do you think?

It isn't, but combined with a proposed security_mmap() hook it would be.

>
> > This means the all time state of access bits has to be checked.
> > For the implementation, you could take a look at PaX (grSecurity)
> > mprotect protection,
> > here: http://www.grsecurity.net/~paxguy1/
> > Look for CONFIG_PAX_MPROTECT.
>
> TOMOYO touches only arch independent part.
> CONFIG_PAX_MPROTECT is arch dependent and too complicated for me.

No, PAX_MPROTECT alone isn't arch-dependent, rest of the PaX is.
CONFIG_PAX_MPROTECT touches two files, fs/binfmt_elf.c
(to check its enable/disable flag) and mm/mprotect.c.

> (You can enable PaX and TOMOYO at the same time if you want to do so.)

Except PaX isn't mainline and TOMOYO somewhat is. :-)

Also, most of PaX is redundant now and useful only on older x86
machines without NX bit,
kernel since about 2.6.25 has Exec Shield which provides a bit worse
emulation of NX bit
than PaX on machines without it and also provides ASLR.

There are other useful things in PaX too, like port randomization, but
those aren't critical
and can be done elsewhere (e.g. with netfilter).

>
> > Especially elf_handle_mprotect() in the first file which would become your
> > security_file_mprotect() with minor changes... but the problem is how
> > to match vma to the domain.
> > [File fs/binfmt_elf.c, line 29013 of the 2.6.35.4 patch.]
> >
> > If CONFIG_MM_OWNER is defined (select it in Kconfig), you could use
> > vma->vm_mm->owner to find out which task the mapping belongs to,
> > and then check its domain for the flags.
> > If it's not defined, I'm not sure how to find out who owns the mapping
> > from the hook.
>
> TOMOYO simply validates arguments passed to syscalls. TOMOYO does not track
> owner of objects. TOMOYO tracks only subjects using domainnames
> (e.g. <kernel> /usr/sbin/httpd ). I think CONFIG_MM_OWNER=n is not a problem.

But the security_file_mprotect hook doesn't have a "domain" argument
or anything linking the mapping directly to the task, neither does
vm_addr_struct.
How can you get domain info without the domain name? :)

> Please be sure to call fflush() after writing a line (or use line buffering 
> mode)
> if your appliocation's write method does not call write() syscall.

Appreciated.

> I tried to let /usr/sbin/ccs-queryd search a database and reply if $retry is 0
> and let /usr/sbin/ccs-queryd ask the user what to do if $retry is not 0. But I
> haven't implemented it yet and therefore some dead code exists in queryd.c .
> You can just ignore it.

In fact, I want to implement exactly this, but a bit more involved.

Client uses a proposed ccs-ask-daemon, which connects to ccs-queryd
(with TLS authentication), sending the uid. ccs-queryd then sends all requests
that are marked as "ask about it" and concern a process owned by that uid
to the socket of ccs-ask-daemon.

The other thing missing is a policy definition like an ability to enable
or disable the prompt in the policy file, e.g.

ask_permission
no_ask_permission

It'd be also nice to have allow_stat for listing the directories
without allowing file read.

> /usr/sbin/ccs-queryd supports monitoring remote machines (e.g. embedded 
> devices
> running on emulator). ccs-editpolicy-agent can be used for waiting for TCP
> connections from ccs-loadpolicy/ccs-editpolicy/ccs-savepolicy/ccs-queryd etc.
> on remote machines. Its communication protocol is very simple.

Sounds similar to what I want to do, but not exactly what I need.

> I think you don't need to implement this feature for now.
> Those who can use emulator know how to use CUI.

Yes, but I'm not targetting users of emulators, but users in general, say,
a typical Ubuntu user of Firefox, so that I could write:

(in enforcing mode)
<kernel>
no_ask_permission # possibly default

<kernel> /usr/lib/firefox/firefox-bin
allow_read cookies
allow_write cookies
...
allow_network ...
allow_transit /uid:1234 /usr/lib/firefox/firefox-bin if task.uid=1234
allow_transit /uid:777 /usr/lib/firefox/firefox-bin if task.uid=2345
allow_execute /usr/lib/firefox/plugin-container
ask_permission

<kernel> /usr/lib/firefox/firefox-bin /usr/lib/firefox/plugin-container
allow_stat /store/downloads
allow_write /store/downloads
allow_execute flash
allow_execute java
...
ask_permission

<kernel> /uid:1234 /usr/lib/firefox/firefox-bin
allow_write /home/1234/downloads
allow_read /home/1234/downloads
allow_chmod 0770 /home/1234/downloads
# to allow overwriting
allow_rename /home/1234/downloads/* /home/1234/downloads/*
ask_permission

Then when, say, Flash or Java attempts to connect or open a socket, it
will ask the user.
The ccs-ask-daemon part could additionally filter what it asks about,
and what it denies or allows automatically per user
Or when firefox attempts to read or write something that's not in the downloads.

_______________________________________________
tomoyo-users-en mailing list
[email protected]
http://lists.sourceforge.jp/mailman/listinfo/tomoyo-users-en

Reply via email to