Re: [RESEND][RFC][PATCH 2/7] implementation of LSM hooks

Tony Jones
2006-04-19T23:29:18Z

On Wed, Apr 19, 2006 at 02:50:40PM -0400, Valdis.Kletnieks@vt.edu wrote:
> On Wed, 19 Apr 2006 11:32:56 PDT, Crispin Cowan said:
>
> > AppArmor initially validates your access at open time, and there after
> > you can read&write to it without mediation. AppArmor re-validates your
> > access if policy is reloaded, you exec() a new program, you get passed
> > the fd from another process, or you call our change_hat() API.
> >
> > So, if the file is unlinked or renamed while you have it open, and
> > policy says you don't have access to the new name, then:
> >
> > * within the same process you get to keep accessing it until
> > o policy is reloaded by the administrator
> > o you call the change_hat() API
> > * in some other process, either a child or some process you passed
> > an fd to, you don't get to access it because your access gets
> > revalidated
>
> My brain is small, and my eyes glaze over easily... ;)

Join the club :)

> What happens for the following sequence:
>
> a) Process A does fd = open("/some/protected");
> b) Somebody then does an unlink("/some/protected");
> c) A then does a fork/exec, handing the exec'ed process B the open FD
> as its stdin.

I just wrote the following which I believe is your test scenario?

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
int fd, err, pid;

fd = open("/tmp/protected", O_RDONLY);
if (fd == -1){
perror("open") ; return 1;
}

err=unlink("/tmp/protected");
if (err == -1){
perror("unlink"); close(fd); return 1;
}

pid=fork();

if (pid){
wait();
}else{
close(0);
dup(fd);

execl("/bin/cat", "/bin/cat", NULL);
}

close(fd);
}

d_path reports "/tmp/protected (deleted)" for the dentry in this situation
when /bin/cat attempts to access it.

It happens a lot with nscd which likes to open files, unlink them and pass
them over unix domain sockets. Our old code used to have to remove the
(deleted) [in a safe manner of course]. With the posted patch to d_path to
generate pathnames back to the namespace root I took advantage of including
some control of the appending for unhashed dentries.

> What name do you use to re-validate B's access to the data described by
> the inode that open file is referencing?

Now how you handle what confinement the forked process should have is
determined when you generate policy. /bin/cat in this situation can run under
it's own policy (probably not ideal in this situation), inherit the openers
(probably the ideal choice), or none at all (if you believe it does not
require confinement).

> Note that although B can't get any access to the data that A didn't have,
> it can still be used to bypass security, because B may be able to *copy* that
> data to an area where A couldn't write (presumably because A is in a confined box).

I'm not sure how. Perhaps with the above example you can elaborate as
necessary. Also thanks for posting the question.

Tony