Subject: Re: machdep kauth calls for i386_xxx
To: None <tls@rek.tjls.com>
From: Elad Efrat <elad@NetBSD.org>
List: port-i386
Date: 11/09/2006 10:20:48
(wow, this mail has a lot of cc's.. oh well)

Thor Lancelot Simon wrote:

> The proliferation of scopes and requests makes it very hard to understand
> the authorization semantics of any particular privileged operation. 

why? I think it's actually pretty easy. look:

> For
> example, I wanted to see whether the bug where i386_iopl() was permitted
> if securelevel <= 1 instead of < 1 had already been fixed. 

src/sys/arch/i386/i386/sys_machdep.c:

int
i386_iopl()
{
[...]
	if ((error = kauth_authorize_machdep(l->l_cred,
	    KAUTH_MACHDEP_X86, KAUTH_REQ_MACHDEP_X86_IOPL,
	    NULL, NULL, NULL)) != 0)
		return error;
[...]
}

standard authorization wrapper, so action=KAUTH_MACHDEP_X86 and
req(arg0)=KAUTH_REQ_MACHDEP_X86_IOPL. let's see what the bsd44 secmodel
has to say:

phyre:bsd44 {221} pwd
/usr/netbsd/src/sys/secmodel/bsd44
phyre:bsd44 {222} grep KAUTH_REQ_MACHDEP_X86_IOPL *
secmodel_bsd44_securelevel.c:           case KAUTH_REQ_MACHDEP_X86_IOPL:
secmodel_bsd44_suser.c:         case KAUTH_REQ_MACHDEP_X86_IOPL:
phyre:bsd44 {223}

okay, you want to check securelevel. so, secmodel_bsd44_securelevel.c:

int
secmodel_bsd44_securelevel_machdep_cb()
[...]
	switch (action) {
	case KAUTH_MACHDEP_X86:
		switch (req) {
		case KAUTH_REQ_MACHDEP_X86_IOPL:
		case KAUTH_REQ_MACHDEP_X86_IOPERM:
			if (securelevel < 2)
				result = KAUTH_RESULT_ALLOW;
			break;
[...]

pretty easy I think. as to your question - nope, we still allow
i386_iopl() in securelevel 1.

> It is very
> hard for me to concieve of a plausible security model where one would
> want to treat this operation differently from a raw memory write, so I
> assumed I could look at the raw memory write handler in the 4.4 security
> model -- but in fact that is not so; there is an additional (and in my
> opinion redundant, and thus obfuscatory) machdep request _specifically_
> for this operation.

that was the exact topic of a thread that ended only yesterday or two
days ago. some device "passthru" commands (that was the issue at hand)
can also be used to write directly to disk and possibly even memory.

so we thought whether to use the standard rawio disk/memory actions or
something else. we ended up moving the rawio disk/memory actions to the
device scope and adding a new passthru action, and noting in the
man-page about possible implications.

> If no requests are the same from the point of view of the kauth
> framework, actually understanding what any listener does is hopeless.
> But some requests clearly _are_ the same -- so why do we not treat this
> request, in particular, the same as a memory write?

I tend to agree that it may be somewhat confusing at first, but I think
the idea is that kauth(9) does not handle capabilities or privileges or
anything like it: it dispatches detailed requests of what the "upper"
layer wanted to do.

it is probably our job to make sure people are aware of what each
request means, so that the "bottom" layer can understand what's
happening and take appropriate action.

for example, we'd issue either a rawio/dev or rawio/passthru or
machdep/x86/iopl request, which can all end up writing to memory, but
the bottom layer will treat them all the same.

makes some sense? :)

-e.

-- 
Elad Efrat