[Bug 64] Any user can trigger a panic in mmap with an overlapping mapping

2016-07-28 Thread Tim Newsham
Hi,  We just came across another issue that allows a user to crash the system 
through mmap.  Despite trying, we didn't notice any more serious privilege 
escalation opportunities.

/*
 * mmap_dup_panic.c
 *Demonstrate a panic through the mmap system call.
 *
 * gcc -g mmap_dup_panic.c -o mmap_dup_panic
 */

#ifdef BUG_WRITEUP //---
Any user can trigger a panic in mmap with an overlapping mapping

Impact: 
Any user can trigger a panic by requesting a large mapping
that overlaps with an existing mapping.

Description:
It is possible for an mmap() call to request a mapping at a 
virtual address that overlaps an existing mapping.  This is checked
for in uvm_map() by calling uvm_map_isavail() with the hint address and
size..  There is a flaw in uvm_map_isavail() when the requested size is very
large. The code looks up the maps at the start and end address with:

if (*start_ptr == NULL) {
*start_ptr = uvm_map_entrybyaddr(atree, addr);
if (*start_ptr == NULL)
return 0;
} else
KASSERT(*start_ptr == uvm_map_entrybyaddr(atree, addr));
if (*end_ptr == NULL) {
if (VMMAP_FREE_END(*start_ptr) >= addr + sz)
*end_ptr = *start_ptr;
else {
*end_ptr = uvm_map_entrybyaddr(atree, addr + sz - 1);
if (*end_ptr == NULL)
return 0;
}
} else
KASSERT(*end_ptr == uvm_map_entrybyaddr(atree, addr + sz - 1));

Due to an integer overflow that can occur when computing
"addr + sz" it is possible for the end_ptr map to be
computed incorrectly (setting "*end_ptr = *start_ptr"). Later
when this same function iterates over the maps between the start 
and end maps, the function may fail to notice that a large mapping 
overlaps with an existing mapping.

If uvm_map_isavail() indicates that the hint address is available,
uvm_map() will continue its processing without assigning a new
address.  It will eventually call uvm_map_fix_space() which
performs its own sanity lookup with uvm_mapent_addr_insert(),
and panics if an overlapping mapping is added:

res = RB_INSERT(uvm_map_addr, &map->addr, entry);
if (res != NULL) {
panic("uvm_mapent_addr_insert: map %p entry %p "
"(0x%lx-0x%lx G=0x%lx F=0x%lx) insert collision "
"with entry %p (0x%lx-0x%lx G=0x%lx F=0x%lx)",
map, entry,
entry->start, entry->end, entry->guard, entry->fspace,
res, res->start, res->end, res->guard, res->fspace);
}

An attacker can take advantage of this to intentionally
trigger a panic to crash the system.  This does not require
any special privileges.

In theory this flaw might allow an attacker to make a mapping
that wraps around from user addresses, through kernel addresses
and back to low user addresses.  Such a mapping might allow
access to kernel memory or to the NULL page (useful for performing
certain attacks against NULL pointer use in the kernel).
However NCC was unable to find any way to create such a mapping
without causing a panic since it does not appear to be possible
to make a mapping above the stack segment.  All wrap-around mappings
lower than this address overlap with the stack segment and result
in a panic.

Reproduction:
Run the attached mmap_dup_panic.c program. It first maps a
page in and then performs a second mmap() call to request
another mapping at the next page address.  This second mapping overlaps 
the first due to the large size, and causes a panic message such as
"panic: uvm_mapent_addr_insert: map 0xff00036be300 entry 0xff000311d178 
(0x1dcc5600-0x1dcc5600 G=0x0 F=0x2) insert collision with entry 
0xff000272de08 (0x1dcc5600-0x1dcc5600 G=0x0 F=0x1000)"
NCC Group was able to reproduce this issue on OpenBSD 5.9-stable kernel
pulled from CVS on July 25, 2016.

Recommendation:
Detect when "addr + sz" causes an integer overflow in uvm_map_isavail().
Return zero indicating that this mapping is not available in this case.

Reported: 2016-07-28
Fixed:notyet
#endif // BUG_WRITEUP ---
 
#include 
#include 
#include 
#include 
#include 

void xperror(int cond, char *msg)
{
if(cond) {
perror(msg);
exit(1);
}
}

int main(int argc, char **argv)
{
int fd;
char *p, *pg;

fd = open("/tmp/mapfile", O_RDWR|O_CREAT, 0666);
xperror(fd == -1, "/tmp/mapfile");
write(fd, "testing\n", 8);

pg = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 
-1, 0);
xperror(pg == MAP_FAILED, "mmap");

p = mmap(pg+4096, 0xff00, 0, 0, fd, 0);
xperror(pg == MAP_FAILED, "mmap2");
printf("no crash!\n");
return 0;
}

Tim Newsham
Distinguished Security Engineer, Security Consulting
NCC Group
Tim.Newsham@nccgroup.trust | PGP: B415 550D BEE9 07DB B4C9  F96C 8EFE CB2F 402D 
3DF0



format errors in {,s}bin

2016-07-28 Thread Ted Unangst
I have found this useful. It's caught a few errors.

Everything currently compiles (in my limited testing), so it's a good way to
keep it that way.

It could use some more testing on exotic archs so as to not break builds.

Index: sbin/Makefile.inc
===
RCS file: /cvs/src/sbin/Makefile.inc,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile.inc
--- sbin/Makefile.inc   11 Jul 2014 13:13:04 -  1.6
+++ sbin/Makefile.inc   6 Jan 2016 18:55:55 -
@@ -2,4 +2,4 @@
 
 BINDIR?=   /sbin
 LDSTATIC=  ${STATIC}
-COPTS+=-Werror-implicit-function-declaration
+COPTS+=-Werror-implicit-function-declaration -Wformat 
-Werror=format
Index: bin/Makefile.inc
===
RCS file: /cvs/src/bin/Makefile.inc,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile.inc
--- bin/Makefile.inc11 Jul 2014 13:13:04 -  1.6
+++ bin/Makefile.inc6 Jan 2016 18:55:07 -
@@ -2,4 +2,4 @@
 
 BINDIR?=   /bin
 LDSTATIC=  ${STATIC}
-COPTS+=-Werror-implicit-function-declaration
+COPTS+=-Werror-implicit-function-declaration -Wformat -Werror=format



patch for resolv.conf(5)

2016-07-28 Thread Remi Locherer
The resolver supports more than 3 nameservers.

Index: resolv.conf.5
===
RCS file: /cvs/src/share/man/man5/resolv.conf.5,v
retrieving revision 1.48
diff -u -p -r1.48 resolv.conf.5
--- resolv.conf.5   23 Nov 2015 18:04:53 -  1.48
+++ resolv.conf.5   28 Jul 2016 20:21:37 -
@@ -118,8 +118,8 @@ Scoped IPv6 address notation is accepted
 for details).
 .Pp
 Up to
-.Dv MAXNS
-(currently 3) name servers may be listed, one per line.
+.Dv ASR_MAXNS
+(currently 5) name servers may be listed, one per line.
 If there are multiple servers, the resolver library queries them in the
 order listed.
 If no



pmapassert

2016-07-28 Thread Artturi Alm
Hi,

personally, i like running w/pmap asserts w/o DEBUG too, and this
would allow just that, effortless switching between KDASSERT/assert.

-Artturi


Index: sys/arch/arm/include/pmap.h
===
RCS file: /cvs/src/sys/arch/arm/include/pmap.h,v
retrieving revision 1.40
diff -u -p -u -r1.40 pmap.h
--- sys/arch/arm/include/pmap.h 22 Mar 2016 23:35:01 -  1.40
+++ sys/arch/arm/include/pmap.h 28 Jul 2016 14:36:48 -
@@ -77,6 +77,8 @@
 #include 
 #endif
 
+#definePMAPASSERT  KDASSERT
+
 /*
  * a pmap describes a processes' 4GB virtual address space.  this
  * virtual address space can be broken up into 4096 1MB regions which
Index: sys/arch/arm/arm/pmap7.c
===
RCS file: /cvs/src/sys/arch/arm/arm/pmap7.c,v
retrieving revision 1.28
diff -u -p -u -r1.28 pmap7.c
--- sys/arch/arm/arm/pmap7.c27 Jul 2016 21:12:49 -  1.28
+++ sys/arch/arm/arm/pmap7.c28 Jul 2016 14:36:49 -
@@ -832,7 +832,7 @@ pmap_free_l2_bucket(pmap_t pm, struct l2
pt_entry_t *ptep;
u_short l1idx;
 
-   KDASSERT(count <= l2b->l2b_occupancy);
+   PMAPASSERT(count <= l2b->l2b_occupancy);
 
/*
 * Update the bucket's reference count according to how many
@@ -919,7 +919,7 @@ pmap_l2ptp_ctor(void *v)
 * correct.
 */
l2b = pmap_get_l2_bucket(pmap_kernel(), va);
-   KDASSERT(l2b != NULL);
+   PMAPASSERT(l2b != NULL);
ptep = &l2b->l2b_kva[l2pte_index(va)];
pte = *ptep;
 
@@ -1004,7 +1004,7 @@ pmap_clearbit(struct vm_page *pg, u_int 
pv->pv_flags &= ~maskbits;
 
l2b = pmap_get_l2_bucket(pm, va);
-   KDASSERT(l2b != NULL);
+   PMAPASSERT(l2b != NULL);
 
ptep = &l2b->l2b_kva[l2pte_index(va)];
npte = opte = *ptep;
@@ -1152,7 +1152,7 @@ pmap_page_remove(struct vm_page *pg)
pm = pv->pv_pmap;
 
l2b = pmap_get_l2_bucket(pm, pv->pv_va);
-   KDASSERT(l2b != NULL);
+   PMAPASSERT(l2b != NULL);
 
ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
if (*ptep != 0) {
@@ -1253,8 +1253,8 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 
NPDEBUG(PDB_ENTER, printf("pmap_enter: pm %p va 0x%lx pa 0x%lx prot %x 
flag %x\n", pm, va, pa, prot, flags));
 
-   KDASSERT((flags & PMAP_WIRED) == 0 || (flags & PROT_MASK) != 0);
-   KDASSERT(((va | pa) & PGOFSET) == 0);
+   PMAPASSERT((flags & PMAP_WIRED) == 0 || (flags & PROT_MASK) != 0);
+   PMAPASSERT(((va | pa) & PGOFSET) == 0);
 
/*
 * Get a pointer to the page.  Later on in this function, we
@@ -1593,7 +1593,7 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v
va, pa, prot));
 
l2b = pmap_get_l2_bucket(pmap_kernel(), va);
-   KDASSERT(l2b != NULL);
+   PMAPASSERT(l2b != NULL);
 
ptep = &l2b->l2b_kva[l2pte_index(va)];
opte = *ptep;
@@ -1642,7 +1642,7 @@ pmap_kremove(vaddr_t va, vsize_t len)
next_bucket = eva;
 
l2b = pmap_get_l2_bucket(pmap_kernel(), va);
-   KDASSERT(l2b != NULL);
+   PMAPASSERT(l2b != NULL);
 
sptep = ptep = &l2b->l2b_kva[l2pte_index(va)];
mappings = 0;
@@ -1664,7 +1664,7 @@ pmap_kremove(vaddr_t va, vsize_t len)
va += PAGE_SIZE;
ptep++;
}
-   KDASSERT(mappings <= l2b->l2b_occupancy);
+   PMAPASSERT(mappings <= l2b->l2b_occupancy);
l2b->l2b_occupancy -= mappings;
}
cpu_cpwait();
@@ -1688,7 +1688,7 @@ pmap_extract(pmap_t pm, vaddr_t va, padd
/*
 * These should only happen for pmap_kernel()
 */
-   KDASSERT(pm == pmap_kernel());
+   PMAPASSERT(pm == pmap_kernel());
pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET);
} else {
/*
@@ -2116,7 +2116,7 @@ pmap_unwire(pmap_t pm, vaddr_t va)
NPDEBUG(PDB_WIRING, printf("pmap_unwire: pm %p, va 0x%08lx\n", pm, va));
 
l2b = pmap_get_l2_bucket(pm, va);
-   KDASSERT(l2b != NULL);
+   PMAPASSERT(l2b != NULL);
 
ptep = &l2b->l2b_kva[l2pte_index(va)];
pte = *ptep;
@@ -2337,7 +2337,7 @@ pmap_grow_map(vaddr_t va, pt_entry_t cac
*pap = pa;
 
l2b = pmap_get_l2_bucket(pmap_kernel(), va);
-   KDASSERT(l2b != NULL);
+   PMAPASSERT(l2b != NULL);
 
ptep = &l2b->l2b_kva[l2pte_index(va)];
*ptep = L2_S_PROTO | pa | cache_mode |
@@ -2450,7 +2450,7 @@ pmap_growkernel(vaddr_t maxkvaddr)
printf("pmap_growkernel: growing kernel from 0x%lx to 0x%lx\n",
pmap_curmaxkvaddr, maxkvaddr));
 
-   KDASSERT(maxkvaddr <= virtual_end);
+   PMAPASSERT(maxkvaddr <= virtual_end);
 
/*
   

Re: Regression tests for calendar(1)

2016-07-28 Thread Andy Bradford
Thus said "Andy Bradford" on 28 Jul 2016 02:56:59 -0600:

> Not enough? Different style required? Does the patch need to be broken
> up?

Or  a  different  approach?  Specifically, I  originally  had  in  mind,
a  single  monolithic  input  file  (generated  with  as  many  possible
combinations of rules  as I did in the current  wdout.in) with 366+ test
outputs (one  for each day  of the  year, with maybe  a few more  from a
non-leap year), but wasn't certain if that was necessary.

Thanks,

Andy
-- 
TAI64 timestamp: 4000579a1a60




Style update for some files in arch/arm

2016-07-28 Thread Robert Tate
I found a few files that could use updated function declarations. Here
is my diff:


Index: sys/arch/arm/arm/conf.c
===
RCS file: /cvs/src/sys/arch/arm/arm/conf.c,v
retrieving revision 1.46
diff -u -r1.46 conf.c
--- sys/arch/arm/arm/conf.c23 May 2016 00:05:34 -1.46
+++ sys/arch/arm/arm/conf.c28 Jul 2016 14:26:46 -
@@ -403,8 +403,7 @@
  * Returns true if dev is /dev/mem or /dev/kmem.
  */
 int
-iskmemdev(dev)
-dev_t dev;
+iskmemdev(dev_t dev)
 {
 return (major(dev) == mem_no && minor(dev) < 2);
 }
@@ -413,8 +412,7 @@
  * Returns true if dev is /dev/zero.
  */
 int
-iszerodev(dev)
-dev_t dev;
+iszerodev(dev_t dev)
 {
 return (major(dev) == mem_no && minor(dev) == 3);
 }
Index: sys/arch/arm/arm/vm_machdep.c
===
RCS file: /cvs/src/sys/arch/arm/arm/vm_machdep.c,v
retrieving revision 1.17
diff -u -r1.17 vm_machdep.c
--- sys/arch/arm/arm/vm_machdep.c24 Apr 2016 01:31:02 -1.17
+++ sys/arch/arm/arm/vm_machdep.c28 Jul 2016 14:26:46 -
@@ -96,13 +96,8 @@
  * accordingly.
  */
 void
-cpu_fork(p1, p2, stack, stacksize, func, arg)
-struct proc *p1;
-struct proc *p2;
-void *stack;
-size_t stacksize;
-void (*func) (void *);
-void *arg;
+cpu_fork(struct proc *p1, struct proc *p2, void *stack,
+size_t stacksize, void (*func) (void *), void *arg)
 {
 struct pcb *pcb = (struct pcb *)&p2->p_addr->u_pcb;
 struct trapframe *tf;
@@ -166,9 +161,7 @@
  * do not need to pass an access_type to pmap_enter().
  */
 void
-vmapbuf(bp, len)
-struct buf *bp;
-vsize_t len;
+vmapbuf(struct buf *bp, vsize_t len)
 {
 vaddr_t faddr, taddr, off;
 paddr_t fpa;
@@ -204,9 +197,7 @@
  * Unmap a previously-mapped user I/O request.
  */
 void
-vunmapbuf(bp, len)
-struct buf *bp;
-vsize_t len;
+vunmapbuf(struct buf *bp, vsize_t len)
 {
 vaddr_t addr, off;

@@ -227,5 +218,3 @@
 bp->b_data = bp->b_saveaddr;
 bp->b_saveaddr = 0;
 }
-
-/* End of vm_machdep.c */



-- 
-Rob Tate



Re: jot(1) bugs, test suite

2016-07-28 Thread Theo Buehler
Here's a full patch including two small manpage tweaks.

It contains the three hunks that fix FreeBSD's regress tests from my
previous mail:

* initialize begin, ender, step, reps (from attila)
* set steps to -1 if ender < begin (adapted from FreeBSD)
* properly skip "%%" in the format string (from OpenBSD r1.8, pjanzen)

In addition, get rid of the nasty mask loop and just compute whatever we
need to compute in the most sensible order. This simplifies the code
quite a bit and is inspired by dsl@NetBSD's r1.21. Note that the output
loop only depends on reps, begin and step, so we never need to compute
ender and we only need to compute something else if ender was specified.

We now only produce infinite output if it was explicitly requested by
setting reps or steps to zero on the command line.

Also note that if randomized output is requested, there's never the need
to compute anything, so just skip that piece of code in that case.

I will import a tweaked and expanded version of the regress tests when
the tree is fully unlocked.

Index: jot.1
===
RCS file: /var/cvs/src/usr.bin/jot/jot.1,v
retrieving revision 1.21
diff -u -p -r1.21 jot.1
--- jot.1   17 Jul 2016 04:15:25 -  1.21
+++ jot.1   27 Jul 2016 19:27:38 -
@@ -104,11 +104,10 @@ in which case the data is inserted rathe
 The last four arguments indicate, respectively,
 the maximum number of data, the lower bound, the upper bound,
 and the step size.
-While at least one of them must appear,
-any of the other three may be omitted, and
+Any of these may be omitted, and
 will be considered as such if given as
 .Ql - .
-Any three of these arguments determines the fourth.
+Any three of these arguments determine the fourth.
 If four are specified and the given and computed values of
 .Ar reps
 conflict, the lower value is used.
Index: jot.c
===
RCS file: /var/cvs/src/usr.bin/jot/jot.c,v
retrieving revision 1.28
diff -u -p -r1.28 jot.c
--- jot.c   17 Jul 2016 04:04:46 -  1.28
+++ jot.c   28 Jul 2016 11:26:16 -
@@ -52,12 +52,17 @@
 #defineENDER_DEF   100
 #defineSTEP_DEF1
 
+#defineSTEP1
+#defineENDER   2
+#defineBEGIN   4
+#defineREPS8
+
 #defineis_default(s)   (strcmp((s), "-") == 0)
 
-static double  begin;
-static double  ender;
-static double  s;
-static longreps;
+static double  begin = BEGIN_DEF;
+static double  ender = ENDER_DEF;
+static double  step = STEP_DEF;
+static longreps = REPS_DEF;
 static boolrandomize;
 static boolinfinity;
 static boolboring;
@@ -131,9 +136,9 @@ main(int argc, char *argv[])
switch (argc) { /* examine args right to left, falling thru cases */
case 4:
if (!is_default(argv[3])) {
-   if (!sscanf(argv[3], "%lf", &s))
+   if (!sscanf(argv[3], "%lf", &step))
errx(1, "Bad s value:  %s", argv[3]);
-   mask |= 01;
+   mask |= STEP;
if (randomize)
warnx("random seeding not supported");
}
@@ -141,7 +146,7 @@ main(int argc, char *argv[])
if (!is_default(argv[2])) {
if (!sscanf(argv[2], "%lf", &ender))
ender = argv[2][strlen(argv[2])-1];
-   mask |= 02;
+   mask |= ENDER;
if (prec == -1)
n = getprec(argv[2]);
}
@@ -149,7 +154,7 @@ main(int argc, char *argv[])
if (!is_default(argv[1])) {
if (!sscanf(argv[1], "%lf", &begin))
begin = argv[1][strlen(argv[1])-1];
-   mask |= 04;
+   mask |= BEGIN;
if (prec == -1)
prec = getprec(argv[1]);
if (n > prec)   /* maximum precision */
@@ -159,114 +164,65 @@ main(int argc, char *argv[])
if (!is_default(argv[0])) {
if (!sscanf(argv[0], "%ld", &reps))
errx(1, "Bad reps value:  %s", argv[0]);
-   mask |= 010;
+   mask |= REPS;
if (prec == -1)
prec = 0;
}
break;
case 0:
-   usage();
+   /* Use defaults. */
break;
default:
errx(1, "Too many arguments.  What do you mean by %s?",
argv[4]);
}
getformat();
-   while (mask)/* 4 bit mask has 1's where last 4 args were given */
-   switch (mask) { /* fill in the 0's by default or computation */

Followup patch for regression to calendar(1)

2016-07-28 Thread Andy Bradford
Hello,

Here's  the  followup  patch  that   accounts  for  the  missed  events.
Specifically, some kinds  of events actually can have  a differing month
(specifically Easter and Weekly events like Every Monday).

This allows all tests to pass (from previous email):

Index: day.c
===
RCS file: /home/cvs/src/usr.bin/calendar/day.c,v
retrieving revision 1.33
diff -u -p -r1.33 day.c
--- day.c   13 Jul 2016 21:32:01 -  1.33
+++ day.c   28 Jul 2016 08:46:54 -
@@ -543,7 +543,9 @@ isnow(char *endp, int bodun)
tdiff = difftime(ttmp, f_time)/ SECSPERDAY;
if (tdiff <= offset + f_dayAfter ||
(bodun && tdiff == -1)) {
-   if ((tmtmp.tm_mon == month) &&
+   if (((tmtmp.tm_mon == month) ||
+(flags & F_SPECIAL) ||
+(interval == WEEKLY)) &&
(tdiff >=  0 ||
(bodun && tdiff == -1))) {
if ((tmp = malloc(sizeof(struct 
match))) == NULL)


-- 
TAI64 timestamp: 40005799c9d4




Regression tests for calendar(1)

2016-07-28 Thread Andy Bradford
Hello,

A few weeks ago I submitted a patch to calendar(1) that helped it handle
fifth  weekday events  and 31st  events, and  afterward, I  noticed that
there were no regression tests. In writing them, I discovered that while
the patch fixed these two particular cases, it broke others. I'll send a
potential  fix which  passes all  the tests  in a  following email.  But
here  is a  potential set  of regressions  and comments/suggestions  are
appreciated.  Are there  too  many tests?  Not  enough? Different  style
required? Does the patch need to be broken up?

Thanks.

Index: Makefile
===
RCS file: /home/cvs/src/regress/usr.bin/Makefile,v
retrieving revision 1.32
diff -u -p -r1.32 Makefile
--- Makefile26 Jul 2015 17:29:41 -  1.32
+++ Makefile28 Jul 2016 08:25:26 -
@@ -1,7 +1,7 @@
 #  $OpenBSD: Makefile,v 1.32 2015/07/26 17:29:41 zhuk Exp $
 #  $NetBSD: Makefile,v 1.1 1997/12/30 23:27:11 cgd Exp $
 
-SUBDIR+= basename bc dc diff diff3 dirname doas file grep gzip
+SUBDIR+= basename bc calendar dc diff diff3 dirname doas file grep gzip
 SUBDIR+= m4 mandoc openssl sdiff sed signify sort tsort
 SUBDIR+= xargs
 
Index: calendar/20160101.wdout
===
RCS file: calendar/20160101.wdout
diff -N calendar/20160101.wdout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160101.wdout 28 Jul 2016 08:25:26 -
@@ -0,0 +1,8 @@
+Jan 01*First Friday
+Jan 01*First Friday in Jan
+Jan 02*First Saturday
+Jan 02*First Saturday in Jan
+Jan 03*First Sunday
+Jan 03*First Sunday in Jan
+Jan 04*First Monday
+Jan 04*First Monday in Jan
Index: calendar/20160114.manout
===
RCS file: calendar/20160114.manout
diff -N calendar/20160114.manout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160114.manout28 Jul 2016 08:25:26 -
@@ -0,0 +1,2 @@
+Jan 14*Every Thursday
+Jan 15*15th of every month
Index: calendar/20160115.wdout
===
RCS file: calendar/20160115.wdout
diff -N calendar/20160115.wdout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160115.wdout 28 Jul 2016 08:25:26 -
@@ -0,0 +1,8 @@
+Jan 15*Third Friday
+Jan 15*Third Friday in Jan
+Jan 16*Third Saturday
+Jan 16*Third Saturday in Jan
+Jan 17*Third Sunday
+Jan 17*Third Sunday in Jan
+Jan 18*Third Monday
+Jan 18*Third Monday in Jan
Index: calendar/20160129.wdout
===
RCS file: calendar/20160129.wdout
diff -N calendar/20160129.wdout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160129.wdout 28 Jul 2016 08:25:26 -
@@ -0,0 +1,9 @@
+Jan 29*Fifth Friday
+Jan 29*Fifth Friday in Jan
+Jan 30*Fifth Saturday
+Jan 30*Fifth Saturday in Jan
+Jan 31*Fifth Sunday
+Jan 31*Fifth Sunday in Jan
+Feb 01*First Monday
+Feb 01*First Monday in Feb
+Feb 01*Fifth Monday in Jan
Index: calendar/20160131.monout
===
RCS file: calendar/20160131.monout
diff -N calendar/20160131.monout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160131.monout28 Jul 2016 08:25:26 -
@@ -0,0 +1,3 @@
+Jan 31*Every Sunday
+Feb 01*First of Month
+Feb 01*Every Monday
Index: calendar/20160201.wdout
===
RCS file: calendar/20160201.wdout
diff -N calendar/20160201.wdout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160201.wdout 28 Jul 2016 08:25:26 -
@@ -0,0 +1,6 @@
+Feb 01*First Monday
+Feb 01*First Monday in Feb
+Feb 01*Fifth Monday in Jan
+Feb 02*First Tuesday
+Feb 02*First Tuesday in Feb
+Feb 02*Fifth Tuesday in Jan
Index: calendar/20160203.wdout
===
RCS file: calendar/20160203.wdout
diff -N calendar/20160203.wdout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160203.wdout 28 Jul 2016 08:25:26 -
@@ -0,0 +1,6 @@
+Feb 03*First Wednesday
+Feb 03*First Wednesday in Feb
+Feb 03*Fifth Wednesday in Jan
+Feb 04*First Thursday
+Feb 04*First Thursday in Feb
+Feb 04*Fifth Thursday in Jan
Index: calendar/20160229.wdout
===
RCS file: calendar/20160229.wdout
diff -N calendar/20160229.wdout
--- /dev/null   1 Jan 1970 00:00:00 -
+++ calendar/20160229.wdout 28 Jul 2016 08:25:26 -
@@ -0,0 +1,5 @@
+Feb 29*Fifth Monday
+Feb 29*Fifth Monday in Feb
+Mar 01*First Tuesday
+Mar 01*Firs

Re: arm: pmap uvm_fault findings

2016-07-28 Thread Patrick Wildt
On Wed, Jul 27, 2016 at 08:06:57PM +0200, Patrick Wildt wrote:
> On Tue, Jul 26, 2016 at 06:43:18PM +0200, Patrick Wildt wrote:
> > Hi,
> > 
> > I've been trying to debug a pmap issue on ARM.  I have no solution, but
> > I would like to share my findings so far.
> > 
> > First of all, the panic/uvm_fault:
> > 
> > 
> > login:
> > uvm_fault(0xca06c858, 0, 1, 0) -> e
> > Fatal kernel mode data abort: 'Translation Fault (P)'
> > trapframe: 0xc986bd98
> > DFSR=0007, DFAR=000c, spsr=6113
> > r0 =, r1 =ccaa7148, r2 =00136000, r3 =
> > r4 =0012, r5 =ccaa7148, r6 =3213, r7 =0005
> > r8 =3213000e, r9 =0021, r10=cc634698, r11=c986be34
> > r12=cd43a9a0, ssp=c986bde8, slr=c054c1d0, pc =c054c1d0
> > 
> > Stopped at  pmap_enter+0x178:   ldr r6, [r0, #0x00c]
> > ddb> trace
> > pmap_enter+0xc
> > scp=0xc054c064 rlv=0xc04f60c0 (uvm_fault+0xa28)
> > rsp=0xc986be38 rfp=0xc986bf54
> > r10=0x r9=0x0001 r8=0x r7=0xc050fe80
> > r6=0x r5=0xc4a5aad0 r4=0x0001
> > uvm_fault+0xc
> > scp=0xc04f56a4 rlv=0xc0547e68 (data_abort_handler+0x264)
> > rsp=0xc986bf58 rfp=0xc986bfac
> > r10=0xc986bfb0 r9=0x0007 r8=0xc986a000 r7=0x0001
> > r6=0xca06c858 r5=0x0001 r4=0x00136000
> > data_abort_handler+0xc
> > scp=0xc0547c10 rlv=0xc05477bc (exception_exit)
> > rsp=0xc986bfb0 rfp=0xbffc2430
> > r10=0x00da776c r9=0x0001 r8=0x60165dbc r7=0x
> > r6=0x0200 r5=0x00d0c920 r4=0x4188e9f4
> > 
> > The faulting instruction is in pmap_enter() of pamp7.c:
> > 
> > if (opg) {
> > /*
> >  * Replacing an existing mapping with a new 
> > one.
> >  * It is part of our managed memory so we
> >  * must remove it from the PV list
> >  */
> > pve = pmap_remove_pv(opg, pm, va);
> > pve is NULL ->  oflags = pve->pv_flags;
> > } else
> > 
> > How did we come here?  pmap_enter() was called to enter mapping for a
> > given virtual and physical address.  The VA is 0x136000.  Then it looked
> > if there is already a mapping at the given address.  Turns out there is!
> > opte (old pagetable entry) is set to 0x429f202c.  This is an "invalid"
> > (means not active) page entry pointing to the physical page 0x429f2000.
> > Using the vm_pages struct for that physical address, we can have a look
> > at its virtual addresses.
> > 
> > vm_pages:
> > 0xc4f86754: 429f1000
> > 0xc4f86758: 0
> > 0xc4f8675c: 0
> > 0xc4f86760: 3
> > 0xc4f86764: 0
> > 0xc4f86768: 0
> > 0xc4f8676c: 0
> > 0xc4f86770: c47263f0
> > 0xc4f86774: c4f86590
> > 0xc4f86778: c4a721d0
> > 0xc4f8677c: c520d200
> > 0xc4f86780: 0
> > 0xc4f86784: 0
> > 0xc4f86788: ca32b230
> > 0xc4f8678c: 0
> > 0xc4f86790: 0
> > 0xc4f86794: 0
> > 0xc4f86798: 14
> > 0xc4f8679c: 41
> > 0xc4f867a0: 0
> > 0xc4f867a4: 429f2000  <-- vm_page.phys_addr
> > 0xc4f867a8: 0
> > 0xc4f867ac: cd43a9a0  <-- vm_page.mdpage.pvh_list
> > 0xc4f867b0: 3
> > 0xc4f867b4: 0
> > 0xc4f867b8: 0
> > 0xc4f867bc: 0
> > 0xc4f867c0: 
> > 0xc4f867c4: 
> > 0xc4f867c8: c4f50760
> > 0xc4f867cc: c4c67990
> > 0xc4f867d0: c50374d0
> > 0xc4f867d4: 0
> > 0xc4f867d8: 0
> > 0xc4f867dc: c0714248
> > 0xc4f867e0: cf2c6000
> > 0xc4f867e4: 0
> > 0xc4f867e8: 4d
> > 0xc4f867ec: 385
> > 0xc4f867f0: 1
> > 0xc4f867f4: 429f3000
> > 
> > vm_page.mdpage.pvh_list:
> > 0xcd43a9a0: 0 <-- next ptr in list
> > 0xcd43a9a4: ccaa7148 <- pmap
> > 0xcd43a9a8: 717c7000 <- va
> > 0xcd43a9ac: b <- flags
> > 
> > This means, the physical page already has a VA.  Oh, and it belongs
> > to the same pmap.  Have a look at register r5, that's the pmap we want
> > to enter a mapping for.  But it's not the kernel pmap:
> > 
> > ddb> print kernel_pmap_store
> > c073b8f4
> > 
> > So wait, the only VA for that physical address is 0x717c7000; but the
> > VA I used to look the physical page up is 0x136000.  That is weird.
> > 
> > So now we got a pmap_enter() for a physical address and a virtual
> > address, where the virtual address is already used by the same pmap
> > for another physical address.  But that physical address thinks a
> > completely different VA is using it.
> > 
> > The phys address behind the mapping is 0x429f2000.  The phys address
> > it wanted to map the VA to is in R6: 0x3213.
> > 
> > That's probably not enough to find the exact fault, but it's a writeup
> > of what I have found so far.
> > 
> > Patrick
> 
> So, I found a suspicious place, added printfs, triggered the bug again
> and voila, I think I got it.
> 
> I was looking for places w