From: tedu Date: Wed, 25 Dec 2013 01:46:00 +0000 (+0000) Subject: final circleq to tailq fix. restore the previous pointer check by reading X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=69fc06e639715202eabab23a29af17fc198ed86d;p=openbsd final circleq to tailq fix. restore the previous pointer check by reading the previous value again and checking prev.next is still next. maybe ok guenther --- diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 070c6da6334..b01b4d571be 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: inet.c,v 1.128 2013/12/24 22:26:19 tedu Exp $ */ +/* $OpenBSD: inet.c,v 1.129 2013/12/25 01:46:00 tedu Exp $ */ /* $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $ */ /* @@ -111,7 +111,7 @@ protopr(u_long off, char *name, int af, u_int tableid, u_long pcbaddr) { struct inpcbtable table; struct inpcb *prev, *next; - struct inpcb inpcb; + struct inpcb inpcb, prevpcb; int istcp, israw, isany; int addrlen = 22; int first = 1; @@ -129,6 +129,13 @@ protopr(u_long off, char *name, int af, u_int tableid, u_long pcbaddr) while (next != NULL) { kread((u_long)next, &inpcb, sizeof inpcb); + if (prev != NULL) { + kread((u_long)prev, &prevpcb, sizeof prevpcb); + if (TAILQ_NEXT(&prevpcb, inp_queue) != next) { + printf("PCB list changed\n"); + break; + } + } prev = next; next = TAILQ_NEXT(&inpcb, inp_queue); diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c index 3f4f38e2aeb..3bca253376e 100644 --- a/usr.bin/systat/netstat.c +++ b/usr.bin/systat/netstat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netstat.c,v 1.38 2013/12/24 22:26:20 tedu Exp $ */ +/* $OpenBSD: netstat.c,v 1.39 2013/12/25 01:46:00 tedu Exp $ */ /* $NetBSD: netstat.c,v 1.3 1995/06/18 23:53:07 cgd Exp $ */ /*- @@ -232,8 +232,8 @@ int read_ns(void) { struct inpcbtable pcbtable; - struct inpcb *next; - struct inpcb inpcb; + struct inpcb *next, *prev; + struct inpcb inpcb, prevpcb; struct socket sockb; struct tcpcb tcpcb; void *off; @@ -262,10 +262,19 @@ read_ns(void) again: KREAD(off, &pcbtable, sizeof (struct inpcbtable)); + prev = NULL; next = TAILQ_FIRST(&pcbtable.inpt_queue); while (next != NULL) { KREAD(next, &inpcb, sizeof (inpcb)); + if (prev != NULL) { + KREAD(prev, &prevpcb, sizeof (prevpcb)); + if (TAILQ_NEXT(&prevpcb, inp_queue) != next) { + error("Kernel state in transition"); + return 0; + } + } + prev = next; next = TAILQ_NEXT(&inpcb, inp_queue); if (!aflag) { diff --git a/usr.bin/tcpbench/tcpbench.c b/usr.bin/tcpbench/tcpbench.c index 6ae22ec7a42..43f59012ad1 100644 --- a/usr.bin/tcpbench/tcpbench.c +++ b/usr.bin/tcpbench/tcpbench.c @@ -291,7 +291,7 @@ kfind_tcb(int sock) { struct inpcbtable tcbtab; struct inpcb *next, *prev; - struct inpcb inpcb; + struct inpcb inpcb, prevpcb; struct tcpcb tcpcb; struct sockaddr_storage me, them; @@ -331,6 +331,17 @@ retry: if (ptb->vflag >= 2) fprintf(stderr, "Checking PCB %p\n", next); kget((u_long)next, &inpcb, sizeof(inpcb)); + if (prev != NULL) { + kget((u_long)prev, &prevpcb, sizeof(prevpcb)); + if (TAILQ_NEXT(&prevpcb, inp_queue) != next) { + if (nretry--) { + warnx("PCB prev pointer insane"); + goto retry; + } else + errx(1, "PCB prev pointer insane," + " all attempts exhaused"); + } + } prev = next; next = TAILQ_NEXT(&inpcb, inp_queue);