Subject: Re: inconsistency in MD mmmmap() implementations?
To: None <tech-kern@NetBSD.org>
From: Elad Efrat <elad@NetBSD.org>
List: tech-kern
Date: 10/10/2006 14:44:08
The message quoted below was sent on August 8th, over two months ago,
left unanswered. I'm going to have to change some of that code for
kauth(9). Can I adjust the policies as I see fit? does anyone have any
insightful comments?

-e.

Elad Efrat wrote:
> hi,
> 
> i've been looking lately at the different mmmmap() implementations
> each of our archs has and noticed some inconsistency.
> 
> first, each mmmmap() routine can be (usually) found in
> src/sys/arch/<arch>/<arch>/mem.c:mmmmap()
> 
> we'll take a look at differences between several archs: i386, amd64,
> alpha, vax, hp300, powerpc, and sun3. for all archs, i'll be referring
> to the access conditions for DEV_MEM.
> 
> i386:
> if (check_pa_acc(off, prot) != 0) {
> 	return -1;
> }
> 
> (and check_pa_acc() is:)
> 
> static int
> check_pa_acc(paddr_t pa, vm_prot_t prot)
> {
> 	extern phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
> 	extern int mem_cluster_cnt;
> 	int i;
> 
> 	if (securelevel <= 0) {
> 		return 0;
> 	}
> 
> 	for (i = 0; i < mem_cluster_cnt; i++) {
> 		const phys_ram_seg_t *seg = &mem_clusters[i];
> 		paddr_t start = seg->start;
> 
> 		if (start <= pa && pa - start <= seg->size) {
> 			return 0;
> 		}
> 	}
> 
> 	return EPERM;
> }
> 
> as we can see above, freely accessing physical memory, even outside
> ram, is only permitted in securelevel 0 and below.
> 
> this is very similar to what happens on alpha:
> 
> if ((prot & alpha_pa_access(off)) != prot)
> 	return (-1);
> 
> (and alpha_pa_access() is:)
> 
> int
> alpha_pa_access(pa)
> 	u_long pa;
> {
> 	int i;
> 
> 	for (i = 0; i < mem_cluster_cnt; i++) {
> 		if (pa < mem_clusters[i].start)
> 			continue;
> 		if ((pa - mem_clusters[i].start) >=
> 		    (mem_clusters[i].size & ~PAGE_MASK))
> 			continue;
> 		return (mem_clusters[i].size & PAGE_MASK); /* prot */
> 	}
> 
> 	if (securelevel > 0)
> 		return (PROT_NONE);
> 	else
> 		return (PROT_READ | PROT_WRITE);
> }
> 
> so far so good. however, looking at amd64, vax, and powerpc we see
> different behavior:
> 
> amd64:
> if (off > ctob(physmem) && kauth_authorize_generic(l->l_cred,
>     KAUTH_GENERIC_ISSUSER, &l->l_acflag) != 0)
> 		return (-1);
> 
> vax:
> if ((u_int)off > ctob(physmem) && kauth_authorize_generic(l->l_cred,
>     KAUTH_GENERIC_ISSUSER, &l->l_acflag) != 0)
> 		return (-1);
> 
> powerpc:
> if (atop(off) >= physmem && kauth_authorize_generic(l->l_cred,
>     KAUTH_GENERIC_ISSUSER, &l->l_acflag) != 0)
> 		return (-1);
> 
> but alas, looking further, for example, hp300 and sun3, we see a
> different behavior again:
> 
> hp300:
> if ((u_int)off < lowram || (u_int)off >= 0xFFFFFFFC)
> 	return -1;
> 
> sun3:
> if (off < avail_start || off >= avail_end)
> 	break;
> 
> 
> now; i'm not an expert on any of these architectures so i can't tell
> if there are special reasons why *eventually* these somehow achieve the
> same behavior via different code, but the way i see it, we have three
> (or more) kinds of behavior for more-or-less access to the same type
> of resource (physical memory) on different architectures.
> 
> what i'm asking, is if the above is intentional (and if yes, if there
> is any documentation on the matter), and if it's not, what should be
> the consistent behavior.
> 
> thanks,
> 
> -e.
> 


-- 
Elad Efrat