Subject: Re: inconsistency in MD mmmmap() implementations?
To: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
From: Elad Efrat <elad@NetBSD.org>
List: tech-kern
Date: 10/30/2006 01:18:55
This is a multi-part message in MIME format.
--Boundary_(ID_1qVwx2/kaoiCY4Iem1P4rQ)
Content-type: text/plain; charset=ISO-8859-1
Content-transfer-encoding: 7BIT
YAMAMOTO Takashi wrote:
>> YAMAMOTO Takashi wrote:
>>
>>> there is nothing wrong to be inconsistent between ports if they have
>>> different memory layouts.
>>> eg. "atop(off) >= physmem" can make sense if its memory is
>>> contiguously mapped from physical address 0.
>>> (well, maybe the "suser" part should be consistent. but it isn't
>>> what you are asking, right?)
>> I'm interested in both knowing if these are not wrong (like you say,
>> amd64 is wrong, maybe others are too?) and I also want to use kauth(9)
>> there. So before I'm writing the code I'm verifying that the current
>> behavior is correct.
>
> i386 and alpha seems sane. amd64 seems wrong.
> i don't know others.
>
>>> whether each versions are correct or not is a different question. :-)
>>> at least amd64 version seems wrong. it should be basically the same as i386.
>> Do you want to fix it?
>
> i don't think i'll fix it in a timely manner.
>
>> or should we wait for the amd64 port-master?
>
> no. it shouldn't be too hard for anyone interested.
I tried making a patch (adapted copy/paste of the i386 code) for amd64;
does it look okay?
-e.
--
Elad Efrat
--Boundary_(ID_1qVwx2/kaoiCY4Iem1P4rQ)
Content-type: text/plain; name=amd64_mem.c.diff
Content-transfer-encoding: 7BIT
Content-disposition: inline; filename=amd64_mem.c.diff
Index: sys/arch/amd64/amd64/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/mem.c,v
retrieving revision 1.7
diff -u -p -r1.7 mem.c
--- sys/arch/amd64/amd64/mem.c 23 Jul 2006 22:06:04 -0000 1.7
+++ sys/arch/amd64/amd64/mem.c 29 Oct 2006 23:14:07 -0000
@@ -115,6 +115,8 @@ const struct cdevsw mem_cdevsw = {
nostop, notty, nopoll, mmmmap, nokqfilter
};
+static int check_pa_acc(paddr_t, vm_prot_t);
+
/*ARGSUSED*/
int
mmrw(dev, uio, flags)
@@ -155,6 +157,9 @@ mmrw(dev, uio, flags)
v = uio->uio_offset;
prot = uio->uio_rw == UIO_READ ? VM_PROT_READ :
VM_PROT_WRITE;
+ error = check_pa_acc(uio->uio_offset, prot);
+ if (error)
+ break;
pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
trunc_page(v), prot, PMAP_WIRED|prot);
o = uio->uio_offset & PGOFSET;
@@ -220,14 +225,40 @@ mmrw(dev, uio, flags)
return (error);
}
+#include <sys/kcore.h>
+
+/*
+ * check_pa_acc: check if given pa is accessible.
+ */
+static int
+check_pa_acc(paddr_t pa, vm_prot_t prot __unused)
+{
+ 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 lstart = seg->start;
+
+ if (lstart <= pa && pa - lstart <= seg->size) {
+ return 0;
+ }
+ }
+
+ return EPERM;
+}
+
paddr_t
mmmmap(dev, off, prot)
dev_t dev;
off_t off;
int prot;
{
- struct lwp *l = curlwp; /* XXX */
-
/*
* /dev/mem is the only one that makes sense through this
* interface. For /dev/kmem any physaddr we return here
@@ -239,8 +270,8 @@ mmmmap(dev, off, prot)
if (minor(dev) != DEV_MEM)
return (-1);
- if (off > ctob(physmem) && kauth_authorize_generic(l->l_cred,
- KAUTH_GENERIC_ISSUSER, &l->l_acflag) != 0)
+ if (check_pa_acc(off, prot) != 0)
return (-1);
+
return (x86_btop(off));
}
--Boundary_(ID_1qVwx2/kaoiCY4Iem1P4rQ)--