final circleq to tailq fix. restore the previous pointer check by reading
authortedu <tedu@openbsd.org>
Wed, 25 Dec 2013 01:46:00 +0000 (01:46 +0000)
committertedu <tedu@openbsd.org>
Wed, 25 Dec 2013 01:46:00 +0000 (01:46 +0000)
the previous value again and checking prev.next is still next.
maybe ok guenther

usr.bin/netstat/inet.c
usr.bin/systat/netstat.c
usr.bin/tcpbench/tcpbench.c

index 070c6da..b01b4d5 100644 (file)
@@ -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);
 
index 3f4f38e..3bca253 100644 (file)
@@ -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) {
index 6ae22ec..43f5901 100644 (file)
@@ -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);