From f714625100e66a85ced520b5367d624c33d8ed4b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 23 Mar 2025 20:04:52 -0400 Subject: [PATCH 01/10] ndb/dns: fix refresh to purge cached dns lookups --- sys/src/cmd/ndb/dblookup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/src/cmd/ndb/dblookup.c b/sys/src/cmd/ndb/dblookup.c index 333c1e724..6b5229f82 100644 --- a/sys/src/cmd/ndb/dblookup.c +++ b/sys/src/cmd/ndb/dblookup.c @@ -737,10 +737,12 @@ db2cache(int doit) /* remove old entries */ dnageall(1); - } else + } else { + dnpurge(); /* read all the soa's to get database defaults */ for(ndb = db; ndb; ndb = ndb->next) dbfile2area(ndb); + } doit = 0; lastyoungest = youngest; From b4a411e2c075599010d0d32410ea3293a962d373 Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 16:04:42 +0700 Subject: [PATCH 02/10] Fix livelock in rebalance (thanks Richard Miller, from 9) 1. Once a second rebalance() is called on cpu0 to adjust priorities, so cpu-bound processes won't lock others out. However it was only adjusting processes which were running on cpu0. This was observed to lead to livelock, eg when a higher-priority process spin-waits for a lock held by a lower priority one. Reference: /n/sources/patch/proc-smp-fixes Date: Tue Apr 19 13:42:06 CES 2016 Signed-off-by: miller@hamnavoe.com --- sys/src/9k/port/proc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/src/9k/port/proc.c b/sys/src/9k/port/proc.c index 79fe6d30e..5d49bca7c 100644 --- a/sys/src/9k/port/proc.c +++ b/sys/src/9k/port/proc.c @@ -463,8 +463,6 @@ rebalance(void) p = rq->head; if(p == nil) continue; - if(p->mp != m) - continue; if(pri == p->basepri) continue; updatecpu(p); From 88cf8702209309a5f261f8e4cba9eb8abf43ec96 Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 16:31:33 +0700 Subject: [PATCH 03/10] Fix "no living children" issue (thanks Richard Miller) If a process is started with RFNOWAIT, up->parent points to the parent's Proc but up->parentpid is set to 0 (not the parent's actual pid). If the parent exits before the child, its pid becomes 0, and when the child exits later, this code p = up->parent; .... /* * Check that parent is still alive. */ if(p->pid == up->parentpid && p->state != Broken) { incorrectly treats the parent as still alive (because up->parent->pid and up->parentpid are both zero). So the exiting child's wait record is passed to the dead parent ... or worse, if another fork occurs soon which reuses the parent's Proc, we have a race which can pass the child's wait record to some random new process (and decrement its p->nchild field). This results in a "no living children" error if the new process tries to wait for its real children. The correction is to avoid the above check when up->parentpid == 0. Reference: /n/sources/patch/exit-wrong-parent Date: Thu Apr 5 21:37:43 GMT 2018 Signed-off-by: miller@hamnavoe.com --- sys/src/9k/port/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9k/port/proc.c b/sys/src/9k/port/proc.c index 5d49bca7c..fdc4d59b6 100644 --- a/sys/src/9k/port/proc.c +++ b/sys/src/9k/port/proc.c @@ -1050,7 +1050,7 @@ pexit(char *exitstr, int freemem) * if not a kernel process and have a parent, * do some housekeeping. */ - if(up->kp == 0) { + if(up->kp == 0 && up->parentpid != 0) { p = up->parent; if(p == nil) { if(exitstr == nil) From 25d460bd504a49a4886cf6abd5e8228ceb40edba Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 16:32:59 +0700 Subject: [PATCH 04/10] Increase number of wait records to 2000 (thanks Charles Forsyth) --- sys/src/9k/port/proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9k/port/proc.c b/sys/src/9k/port/proc.c index fdc4d59b6..7f2ecb912 100644 --- a/sys/src/9k/port/proc.c +++ b/sys/src/9k/port/proc.c @@ -1085,13 +1085,13 @@ pexit(char *exitstr, int freemem) p->time[TCUser] += utime; p->time[TCSys] += stime; /* - * If there would be more than 128 wait records + * If there would be more than 2000 wait records * processes for my parent, then don't leave a wait * record behind. This helps prevent badly written * daemon processes from accumulating lots of wait * records. */ - if(p->nwait < 128) { + if(p->nwait < 2000) { wq->next = p->waitq; p->waitq = wq; p->nwait++; From eb4420a69be929e267e7640a9f9d2d4032f828a1 Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 16:51:18 +0700 Subject: [PATCH 05/10] Move close-on-exec after up->nnote is cleared (thanks Richard Miller) Plan 9 sysexec clears pending notes (unlike posix which leaves pending signals active across exec). So if fork+exec is followed immediately by postnote("kill"), there is a window in sysexec between the last sleep and the clearing of up->nnote where the note from the parent can be lost. This also triggers another bug: exec clears up->nnote but does not clear up->notepending, and therefore the first system call in the child process which calls sleep() will be wrongly terminated with Eintr. The parent process can detect when the child's exec has succeeded, by opening a close-on-exec file before the fork, and waiting for it to be closed before sending a note. (The Go language runtime, for example, does this.) To eliminate the exec-postnote race in this case, this patch moves the close-on-exec code to a later point in the sysexec function, after pending notes have been cleared. The race could be eliminated more simply by not clearing up->nnote on exec, but that would change the semantics of exec and possibly disturb some existing programs. Reference: /n/sources/patch/exec-postnote-race Date: Thu Apr 5 13:36:20 GMT 2018 Signed-off-by: miller@hamnavoe.com --- sys/src/9k/port/sysproc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sys/src/9k/port/sysproc.c b/sys/src/9k/port/sysproc.c index 5366fc812..e38b90984 100644 --- a/sys/src/9k/port/sysproc.c +++ b/sys/src/9k/port/sysproc.c @@ -514,13 +514,6 @@ sysexec(Ar0* ar0, va_list list) up->nargs = nargs; poperror(); /* args */ - /* - * Close on exec - */ - f = up->fgrp; - for(i=0; i<=f->maxfd; i++) - fdclose(i, CCEXEC); - /* * Free old memory. * Special segments maintained across exec. @@ -602,6 +595,7 @@ sysexec(Ar0* ar0, va_list list) mmuflush(); qlock(&up->debug); up->nnote = 0; + up->notepending = 0; up->notify = 0; up->notified = 0; up->privatemem = 0; @@ -610,6 +604,13 @@ sysexec(Ar0* ar0, va_list list) if(up->hang) up->procctl = Proc_stopme; + /* + * Close on exec + */ + f = up->fgrp; + for(i=0; i<=f->maxfd; i++) + fdclose(i, CCEXEC); + ar0->v = sysexecregs(entry, TSTKTOP - PTR2UINT(argv), argc); } From ec5b82659e4ece100834dc01fd7cf4efa25b6d4b Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 16:54:13 +0700 Subject: [PATCH 06/10] Fix cb->f[0] nil dereference due to short control request (thanks Cinap Lenrek, from 9) --- sys/src/9k/ip/iproute.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/src/9k/ip/iproute.c b/sys/src/9k/ip/iproute.c index 6055374a8..12ec16ee7 100644 --- a/sys/src/9k/ip/iproute.c +++ b/sys/src/9k/ip/iproute.c @@ -817,6 +817,9 @@ routewrite(Fs *f, Chan *c, char *p, int n) nexterror(); } + if(cb->nf < 1) + error("short control request"); + if(strcmp(cb->f[0], "flush") == 0){ tag = cb->f[1]; for(h = 0; h < nelem(f->v4root); h++) @@ -880,7 +883,8 @@ routewrite(Fs *f, Chan *c, char *p, int n) print("no route\n"); else printroute(q); - } + } else + error(Ebadctl); poperror(); free(cb); From 512e5518ae845b319a5c82a58efd64444cb40702 Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 16:56:07 +0700 Subject: [PATCH 07/10] Increase MaxTlsDevs in devtls. --- sys/src/9k/port/devtls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/src/9k/port/devtls.c b/sys/src/9k/port/devtls.c index de35f0cde..723f3a20d 100644 --- a/sys/src/9k/port/devtls.c +++ b/sys/src/9k/port/devtls.c @@ -180,7 +180,7 @@ static TlsErrs tlserrs[] = { enum { /* max. open tls connections */ - MaxTlsDevs = 1024 + MaxTlsDevs = 16*1024 }; static Lock tdlock; From ab4f1406b8068a507811044461ccf645286cc833 Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 16:58:06 +0700 Subject: [PATCH 08/10] Fix leak in devtls (thanks Cinap Lenrek) From: cinap_lenrek Date: Sat, 25 Sep 2021 20:35:04 +0000 Subject: [PATCH] devtls: fix bwrite memory leak when channel stops being open tlsbwrite() would call checkstate() before calling tlsrecwrite() to make sure the channel is open. however, because checkstate() only raises the error, the Block* passed wont be freed and would result in a memory leak. move the checkstate() call inside tlsrecwrite() to reuse the error handling that frees the block on error. --- sys/src/9k/port/devtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9k/port/devtls.c b/sys/src/9k/port/devtls.c index 723f3a20d..fe7371e4c 100644 --- a/sys/src/9k/port/devtls.c +++ b/sys/src/9k/port/devtls.c @@ -1255,7 +1255,8 @@ tlsrecwrite(TlsRec *tr, int type, Block *b) if(tr->debug)pprint("send %ld\n", BLEN(b)); if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); - + if(type == RApplication) + checkstate(tr, 0, SOpen); ok = SHandshake|SOpen|SRClose; if(type == RAlert) ok |= SAlert; @@ -1372,7 +1373,6 @@ tlsbwrite(Chan *c, Block *b, vlong offset) tr->handout += n; break; case Qdata: - checkstate(tr, 0, SOpen); tlsrecwrite(tr, RApplication, b); tr->dataout += n; break; From b46dc9fbd21c16f7e1f45fecc43c91737aba35b2 Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 17:00:14 +0700 Subject: [PATCH 09/10] Reject zero length records (thanks Cinap Lenrek) commit a4c1f3cc18df6fddd548f4df9f209695c4eb7263 Author: cinap_lenrek Date: Tue Nov 9 01:46:13 2021 +0000 devtls: reject zero length records (thanks sigrid) zero length record causes ensure() todo nothing, while qgrab() assumes there is at least one buffer in the queue and would dereference the nil buffer. --- sys/src/9k/port/devtls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/src/9k/port/devtls.c b/sys/src/9k/port/devtls.c index fe7371e4c..839cd1d2f 100644 --- a/sys/src/9k/port/devtls.c +++ b/sys/src/9k/port/devtls.c @@ -769,8 +769,8 @@ if(tr->debug)pprint("consumed %d header\n", RecHdrLen); if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion)) rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'", tr->version, tr->verset?"/set":"", len, type, ver, (char*)header); - if(len > MaxCipherRecLen || len < 0) - rcvError(tr, ERecordOverflow, "record message too long %d", len); + if(len > MaxCipherRecLen || len <= 0) + rcvError(tr, ERecordOverflow, "bad record message length %d", len); ensure(tr, &tr->unprocessed, len); nconsumed = 0; poperror(); From c0cf0a2f9572473f3d8284681354228420651b3e Mon Sep 17 00:00:00 2001 From: hahahahacker2009 Date: Sat, 28 Feb 2026 17:30:17 +0700 Subject: [PATCH 10/10] termrc: set NPROC --- rc/bin/termrc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rc/bin/termrc b/rc/bin/termrc index d4555af60..3a5566515 100755 --- a/rc/bin/termrc +++ b/rc/bin/termrc @@ -5,6 +5,9 @@ NDBFILE=/lib/ndb/local mntgen -s slashn && chmod 666 /srv/slashn +# parallelism for mk +NPROC = `{wc -l /dev/sysstat} + # bind all likely devices (#S was bound in boot) for(i in f t m v L P u U '$' Σ κ) /bin/bind -a '#'^$i /dev >/dev/null >[2=1]