Re: diff: pledge snmpd
ok with 2 comments below Rob Pierce(r...@2keys.ca) on 2017.08.11 16:35:21 -0400: > The following diff pledges two of three processes in snmpd: the parent snmpd > process and the trap handler. We cannot currently pledge snmpe as snmp > requests > asking for privileged kernel info are disallowed by pledge. > > I have included a commented pledge block in snmpe.c below (which will not be > committed) which I believe would be possible if we moved the code that > violates pledge to another unpledged process. If we think that is worth while > I could pursue it further. > > In the mean time I am looking for comments and/or ok's for the snmpd.c and > traphandler.c diffs below. > > This passes the newly committed snmpd regression tests. > > Regards, > > Rob try to sort the pledge arguments in this order: stdio rpath wpath cpath fattr flock inet unix dns route mcast dns id getpw \ proc recvfd sendfd exec tty > Index: snmpd.c > === > RCS file: /cvs/src/usr.sbin/snmpd/snmpd.c,v > retrieving revision 1.36 > diff -u -p -r1.36 snmpd.c > --- snmpd.c 4 Apr 2017 02:37:15 - 1.36 > +++ snmpd.c 11 Aug 2017 20:10:50 - > @@ -255,6 +255,9 @@ main(int argc, char *argv[]) > > proc_connect(ps); > > + if (pledge("stdio rpath cpath sendfd dns proc exec id", NULL) == -1) > + fatal("pledge"); > + > event_dispatch(); > > log_debug("%d parent exiting", getpid()); > Index: snmpe.c > === > RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v > retrieving revision 1.48 > diff -u -p -r1.48 snmpe.c > --- snmpe.c 27 Jul 2017 14:04:16 - 1.48 > +++ snmpe.c 11 Aug 2017 20:10:50 - > @@ -105,6 +105,10 @@ snmpe_init(struct privsep *ps, struct pr > snmpe_recvmsg, env); > event_add(&so->s_ev, NULL); > } > +/* > + if (pledge("stdio recvfd inet vminfo route", NULL) == -1) > + fatal("pledge"); > + */ add a XXX not enabled because foobarbaz > } > > void > Index: traphandler.c > === > RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v > retrieving revision 1.8 > diff -u -p -r1.8 traphandler.c > --- traphandler.c 9 Jan 2017 14:49:22 - 1.8 > +++ traphandler.c 11 Aug 2017 20:10:50 - > @@ -96,6 +96,9 @@ traphandler_init(struct privsep *ps, str > struct snmpd*env = ps->ps_env; > struct listen_sock *so; > > + if (pledge("stdio recvfd proc exec id", NULL) == -1) > + fatal("pledge"); > + > if (!env->sc_traphandler) > return; > >
rw_enter_write(&netlock) -> NET_LOCK()
Now that NET_LOCK() does not take any argument, we can use it everywhere. ok? Index: net/if_pppx.c === RCS file: /cvs/src/sys/net/if_pppx.c,v retrieving revision 1.62 diff -u -p -r1.62 if_pppx.c --- net/if_pppx.c 11 Aug 2017 21:24:19 - 1.62 +++ net/if_pppx.c 11 Aug 2017 22:52:53 - @@ -855,9 +855,9 @@ pppx_add_session(struct pppx_dev *pxd, s pipex_timer_start(); /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); + NET_UNLOCK(); if_attach(ifp); - rw_enter_write(&netlock); + NET_LOCK(); if_addgroup(ifp, "pppx"); if_alloc_sadl(ifp); @@ -970,9 +970,9 @@ pppx_if_destroy(struct pppx_dev *pxd, st pipex_timer_stop(); /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); + NET_UNLOCK(); if_detach(ifp); - rw_enter_write(&netlock); + NET_LOCK(); rw_enter_write(&pppx_ifs_lk); if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL) Index: net/if.c === RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.510 diff -u -p -r1.510 if.c --- net/if.c11 Aug 2017 21:24:19 - 1.510 +++ net/if.c11 Aug 2017 21:47:38 - @@ -1176,9 +1176,9 @@ if_clone_create(const char *name, int rd return (EEXIST); /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); + NET_UNLOCK(); ret = (*ifc->ifc_create)(ifc, unit); - rw_enter_write(&netlock); + NET_LOCK(); if (ret != 0 || (ifp = ifunit(name)) == NULL) return (ret); @@ -1221,9 +1221,9 @@ if_clone_destroy(const char *name) } /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); + NET_UNLOCK(); ret = (*ifc->ifc_destroy)(ifp); - rw_enter_write(&netlock); + NET_LOCK(); return (ret); } Index: net/if_pflow.c === RCS file: /cvs/src/sys/net/if_pflow.c,v retrieving revision 1.82 diff -u -p -r1.82 if_pflow.c --- net/if_pflow.c 11 Aug 2017 21:24:19 - 1.82 +++ net/if_pflow.c 11 Aug 2017 22:53:56 - @@ -527,12 +527,11 @@ pflowioctl(struct ifnet *ifp, u_long cmd return (error); /* XXXSMP breaks atomicity */ - rw_exit_write(&netlock); + NET_UNLOCK(); error = pflow_set(sc, &pflowr); - if (error != 0) { - rw_enter_write(&netlock); + NET_LOCK(); + if (error != 0) return (error); - } if ((ifp->if_flags & IFF_UP) && sc->so != NULL) { ifp->if_flags |= IFF_RUNNING; @@ -542,7 +541,6 @@ pflowioctl(struct ifnet *ifp, u_long cmd } else ifp->if_flags &= ~IFF_RUNNING; - rw_enter_write(&netlock); break; default: Index: uvm/uvm_vnode.c === RCS file: /cvs/src/sys/uvm/uvm_vnode.c,v retrieving revision 1.97 diff -u -p -r1.97 uvm_vnode.c --- uvm/uvm_vnode.c 15 May 2017 12:26:00 - 1.97 +++ uvm/uvm_vnode.c 11 Aug 2017 21:31:53 - @@ -1183,7 +1183,7 @@ uvn_io(struct uvm_vnode *uvn, vm_page_t * faulted in copyin() or copyout() in the network stack. */ if (netlocked) - rw_exit_write(&netlock); + NET_UNLOCK(); /* NOTE: vnode now locked! */ if (rw == UIO_READ) @@ -1194,7 +1194,7 @@ uvn_io(struct uvm_vnode *uvn, vm_page_t curproc->p_ucred); if (netlocked) - rw_enter_write(&netlock); + NET_LOCK(); if ((uvn->u_flags & UVM_VNODE_VNISLOCKED) == 0) VOP_UNLOCK(vn, curproc);
fktrace
adds fktrace syscall. currently with same behavior (regular files only) as existing code. tested with ktrace and... #include #include #include #include #include int main() { int fd; fd = open("ledump", O_CREAT, 0666); syscall(113, fd, KTROP_SET, KTRFAC_NAMEI, 14750); } kdump -f ledump Index: syscalls.master === RCS file: /cvs/src/sys/kern/syscalls.master,v retrieving revision 1.176 diff -u -p -r1.176 syscalls.master --- syscalls.master 28 Apr 2017 13:50:55 - 1.176 +++ syscalls.master 11 Aug 2017 21:22:59 - @@ -237,7 +237,12 @@ 111STD { int sys_sigsuspend(int mask); } 112STD { int sys_sendsyslog(const void *buf, size_t nbyte, \ int flags); } -113OBSOL orecvmsg +#ifdef KTRACE +113STD { int sys_fktrace(int fd, int ops, \ + int facs, pid_t pid); } +#else +113UNIMPL fktrace +#endif 114OBSOL osendmsg 115OBSOL vtrace 116OBSOL t32_gettimeofday Index: kern_ktrace.c === RCS file: /cvs/src/sys/kern/kern_ktrace.c,v retrieving revision 1.91 diff -u -p -r1.91 kern_ktrace.c --- kern_ktrace.c 14 Feb 2017 10:31:15 - 1.91 +++ kern_ktrace.c 11 Aug 2017 21:27:14 - @@ -392,42 +392,28 @@ ktrpledge(struct proc *p, int error, uin /* Interface and common routines */ -/* - * ktrace system call - */ int -sys_ktrace(struct proc *p, void *v, register_t *retval) +doktrace(struct vnode *vp, int ops, int facs, pid_t pid, struct proc *p) { - struct sys_ktrace_args /* { - syscallarg(const char *) fname; - syscallarg(int) ops; - syscallarg(int) facs; - syscallarg(pid_t) pid; - } */ *uap = v; - struct vnode *vp = NULL; struct process *pr = NULL; struct ucred *cred = NULL; struct pgrp *pg; - int facs = SCARG(uap, facs) & ~((unsigned) KTRFAC_ROOT); - int ops = KTROP(SCARG(uap, ops)); - int descend = SCARG(uap, ops) & KTRFLAG_DESCEND; + int descend = ops & KTRFLAG_DESCEND; int ret = 0; int error = 0; - struct nameidata nd; + + facs = facs & ~((unsigned)KTRFAC_ROOT); + ops = KTROP(ops); if (ops != KTROP_CLEAR) { /* * an operation which requires a file argument. */ cred = p->p_ucred; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname), - p); - nd.ni_pledge = PLEDGE_CPATH | PLEDGE_WPATH; - if ((error = vn_open(&nd, FWRITE|O_NOFOLLOW, 0)) != 0) + if (!vp) { + error = EINVAL; goto done; - vp = nd.ni_vp; - - VOP_UNLOCK(vp, p); + } if (vp->v_type != VREG) { error = EACCES; goto done; @@ -462,11 +448,11 @@ sys_ktrace(struct proc *p, void *v, regi /* * do it */ - if (SCARG(uap, pid) < 0) { + if (pid < 0) { /* * by process group */ - pg = pgfind(-SCARG(uap, pid)); + pg = pgfind(-pid); if (pg == NULL) { error = ESRCH; goto done; @@ -482,7 +468,7 @@ sys_ktrace(struct proc *p, void *v, regi /* * by pid */ - pr = prfind(SCARG(uap, pid)); + pr = prfind(pid); if (pr == NULL) { error = ESRCH; goto done; @@ -495,9 +481,75 @@ sys_ktrace(struct proc *p, void *v, regi if (!ret) error = EPERM; done: - if (vp != NULL) - (void) vn_close(vp, FWRITE, cred, p); return (error); +} + +/* + * ktrace system call + */ +int +sys_ktrace(struct proc *p, void *v, register_t *retval) +{ + struct sys_ktrace_args /* { + syscallarg(const char *) fname; + syscallarg(int) ops; + syscallarg(int) facs; + syscallarg(pid_t) pid; + } */ *uap = v; + struct vnode *vp = NULL; + const char *fname = SCARG(uap, fname); + struct ucred *cred = NULL; + int error; + + if (fname) { + struct nameidata nd; + + cred = p->p_ucred; + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, p); + nd.ni_pledge = PLEDGE_CPATH | PLEDGE_WPATH; + if ((error = vn_open(&nd, FWRITE|O_NOFOLLOW, 0)) != 0) + return error; + vp = nd.ni_vp; + + VOP_UNLOCK(vp, p); + } + + error = doktrace(vp
Re: amd64: remove clock warning
> Date: Fri, 11 Aug 2017 17:11:11 -0400 > From: joshua stein > > Removes this useless error that appears on some modern machines: > > RTC BIOS diagnostic error > ff Those bits have lost their meaning a while ago... ok kettenis@ > Index: sys/arch/amd64/isa/clock.c > === > RCS file: /cvs/src/sys/arch/amd64/isa/clock.c,v > retrieving revision 1.24 > diff -u -p -u -p -r1.24 clock.c > --- sys/arch/amd64/isa/clock.c25 Jan 2017 08:23:50 - 1.24 > +++ sys/arch/amd64/isa/clock.c11 Aug 2017 21:08:43 - > @@ -157,16 +157,10 @@ u_long rtclock_tval; > void > startclocks(void) > { > - int s; > - > mtx_enter(&timer_mutex); > rtclock_tval = TIMER_DIV(hz); > i8254_startclock(); > mtx_leave(&timer_mutex); > - > - /* Check diagnostic status */ > - if ((s = mc146818_read(NULL, NVRAM_DIAG)) != 0) /* XXX softc */ > - printf("RTC BIOS diagnostic error %b\n", s, NVRAM_DIAG_BITS); > } > > int > >
Re: ksh: remove special handling of export PS1 as root
On Fri, Aug 11 2017, Philip Guenther wrote: > Currently, if ksh starts as root and PS1 was exported but doesn't contain > '#' or '\$' (which will be expanded to '#') then it'll override it with > the root default of '# '. This is kind of a corner case, because PS1 is > not normally exported. > > phessler's research seems to indicate that we're alone in behaving this > way: everyone else seems to not check but just uses the exported PS1 > blindly. > > This is making it difficult to port mininet to OpenBSD. Let's stop being > different. > > ok? ok -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE
Re: slaacd: simplify route message handling
On Fri, Aug 11 2017, Florian Obser wrote: > When read(2)'ing from the routing socket only one message is returned. > Clue provided by jca and claudio. > > OK? ok jca@ -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE
amd64: remove clock warning
Removes this useless error that appears on some modern machines: RTC BIOS diagnostic error ff Index: sys/arch/amd64/isa/clock.c === RCS file: /cvs/src/sys/arch/amd64/isa/clock.c,v retrieving revision 1.24 diff -u -p -u -p -r1.24 clock.c --- sys/arch/amd64/isa/clock.c 25 Jan 2017 08:23:50 - 1.24 +++ sys/arch/amd64/isa/clock.c 11 Aug 2017 21:08:43 - @@ -157,16 +157,10 @@ u_long rtclock_tval; void startclocks(void) { - int s; - mtx_enter(&timer_mutex); rtclock_tval = TIMER_DIV(hz); i8254_startclock(); mtx_leave(&timer_mutex); - - /* Check diagnostic status */ - if ((s = mc146818_read(NULL, NVRAM_DIAG)) != 0) /* XXX softc */ - printf("RTC BIOS diagnostic error %b\n", s, NVRAM_DIAG_BITS); } int
Re: rtadvd: open ioctl socket up front
On Fri, Aug 11 2017, Florian Obser wrote: > No need to constantly re-open a socket. Just open it up front and keep > it around. ok jca@ -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE
diff: pledge snmpd
The following diff pledges two of three processes in snmpd: the parent snmpd process and the trap handler. We cannot currently pledge snmpe as snmp requests asking for privileged kernel info are disallowed by pledge. I have included a commented pledge block in snmpe.c below (which will not be committed) which I believe would be possible if we moved the code that violates pledge to another unpledged process. If we think that is worth while I could pursue it further. In the mean time I am looking for comments and/or ok's for the snmpd.c and traphandler.c diffs below. This passes the newly committed snmpd regression tests. Regards, Rob Index: snmpd.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpd.c,v retrieving revision 1.36 diff -u -p -r1.36 snmpd.c --- snmpd.c 4 Apr 2017 02:37:15 - 1.36 +++ snmpd.c 11 Aug 2017 20:10:50 - @@ -255,6 +255,9 @@ main(int argc, char *argv[]) proc_connect(ps); + if (pledge("stdio rpath cpath sendfd dns proc exec id", NULL) == -1) + fatal("pledge"); + event_dispatch(); log_debug("%d parent exiting", getpid()); Index: snmpe.c === RCS file: /cvs/src/usr.sbin/snmpd/snmpe.c,v retrieving revision 1.48 diff -u -p -r1.48 snmpe.c --- snmpe.c 27 Jul 2017 14:04:16 - 1.48 +++ snmpe.c 11 Aug 2017 20:10:50 - @@ -105,6 +105,10 @@ snmpe_init(struct privsep *ps, struct pr snmpe_recvmsg, env); event_add(&so->s_ev, NULL); } +/* + if (pledge("stdio recvfd inet vminfo route", NULL) == -1) + fatal("pledge"); + */ } void Index: traphandler.c === RCS file: /cvs/src/usr.sbin/snmpd/traphandler.c,v retrieving revision 1.8 diff -u -p -r1.8 traphandler.c --- traphandler.c 9 Jan 2017 14:49:22 - 1.8 +++ traphandler.c 11 Aug 2017 20:10:50 - @@ -96,6 +96,9 @@ traphandler_init(struct privsep *ps, str struct snmpd*env = ps->ps_env; struct listen_sock *so; + if (pledge("stdio recvfd proc exec id", NULL) == -1) + fatal("pledge"); + if (!env->sc_traphandler) return;
Re: Implement __cxa_thread_atexit
On Fri, Aug 11, 2017 at 04:31:44PM +0200, Mark Kettenis wrote: > The diff below implements __cxa_thread_atexit(). Calls to this > function are emitted by the compiler to schedule running desctructors > for thread_local objects when a thread terminates or calls exit(3). > The Linux implementation prevents unloading of shared libraries that > registered such destructors to prevent things from crashing. This > diff does not implement that functionality yet. I plan to add that > later. I expect this to be a bit of a corner case. Well, if you don't care that much about the corner case, you can directly use the generic fallback implementation in libc++abi. Preventing unloading is the least stupid of all options, the rest basically break one major promise or another. > I've chosen to implement __cxa_thread_atexit() directly instead of > __cxa_thread_atexit_impl(). I think that is cleaner. It means we > don't need to make changes to libc++ for this to start working. It > looks like modern libstdc++ version will detect __cxa_thread_atexit(). Which version did you look at? All cases I have seen check exclusively for *_impl(). That's why I settled down on making it the official interface in NetBSD and providing the more natural __cxa_thread_atexit only as weak alias. Joerg
Re: csu: _dl_printf no longer needed
> Date: Fri, 11 Aug 2017 10:13:16 -0700 > From: Philip Guenther > > The _dl_printf() used to be used in libexec/ld.so/*/archdep.h if an > unexpected type of relocation was encountered in ld.so itself. Those went > away (we test ld.so before installing it; _dl_exit() is enough) so the > static pie bits in lib/csu/*/md_init.h no longer need to supply a > no-op _dl_printf() stub. > > ok? ok kettenis@ > Index: aarch64/md_init.h > === > RCS file: /data/src/openbsd/src/lib/csu/aarch64/md_init.h,v > retrieving revision 1.3 > diff -u -p -r1.3 md_init.h > --- aarch64/md_init.h 26 Feb 2017 22:26:42 - 1.3 > +++ aarch64/md_init.h 8 Jun 2017 06:16:41 - > @@ -113,6 +113,4 @@ > "_dl_exit: \n" \ > " mov x8, #1 \n" \ > " svc #0 \n" \ > - "_dl_printf:\n" \ > - " ret \n" \ > ".previous"); > Index: alpha/md_init.h > === > RCS file: /data/src/openbsd/src/lib/csu/alpha/md_init.h,v > retrieving revision 1.8 > diff -u -p -r1.8 md_init.h > --- alpha/md_init.h 19 Jan 2017 23:47:04 - 1.8 > +++ alpha/md_init.h 31 Jan 2017 08:52:37 - > @@ -102,10 +102,6 @@ > "_dl_exit: \n" \ > " lda $0, 1 \n" \ > " callsys \n" \ > - " ret \n" \ > - ".globl _dl_printf \n" \ > - ".type _dl_printf@function \n" \ > - "_dl_printf:\n" \ > " ret") > > #define MD_START_ARGS char **sp, void (*cleanup)(void) > Index: arm/md_init.h > === > RCS file: /data/src/openbsd/src/lib/csu/arm/md_init.h,v > retrieving revision 1.11 > diff -u -p -r1.11 md_init.h > --- arm/md_init.h 26 Feb 2017 15:20:58 - 1.11 > +++ arm/md_init.h 8 Jun 2017 06:16:41 - > @@ -157,6 +157,4 @@ > "_dl_exit: \n" \ > " mov r12, #1 \n" \ > " swi #0 \n" \ > - "_dl_printf:\n" \ > - " mov pc, lr \n" \ > ".previous"); > Index: hppa/md_init.h > === > RCS file: /data/src/openbsd/src/lib/csu/hppa/md_init.h,v > retrieving revision 1.12 > diff -u -p -r1.12 md_init.h > --- hppa/md_init.h26 Feb 2017 22:26:42 - 1.12 > +++ hppa/md_init.h8 Jun 2017 06:16:41 - > @@ -156,17 +156,6 @@ > "1: bv %r0(%rp)\n" \ > " sub %r0, %ret0, %ret0 \n" \ > " .exit \n" \ > - " .procend\n" \ > - " .export _dl_printf, entry \n" \ > - " .type _dl_printf,@function\n" \ > - " .label _dl_printf \n" \ > - " .proc \n" \ > - " .callinfo frame=0, calls\n" \ > - " .entry \n" \ > - "_dl_printf:\n" \ > - " bv %r0(%rp)\n" \ > - " nop \n" \ > - " .exit \n" \ > " .procend") > > > Index: i386/md_init.h > === > RCS file: /data/src/openbsd/src/lib/csu/i386/md_init.h,v > retrieving revision 1.8 > diff -u -p -r1.8 md_init.h > --- i386/md_init.h7 Aug 2016 02:30:55 - 1.8 > +++ i386/md_init.h31 Jan 2017 08:53:28 - > @@ -118,14 +118,6 @@ > " xorl%ebp,%ebp # mark deepest stack frame\n" \ > " call___start# ___start(argc,argv,envp,0) \n" \ > " \n" \ > - ".text \n" \ > - " .align 4 \n" \ > - " .globl _dl_printf \n" \ > - " .type _dl_printf,@function\n" \ > - "_dl_printf:\n" \ > - " ret \n" \ > - " \n" \ > - ".text \n" \ > " .align 4 \n" \ > " .globl _dl_exit\n" \ > " .type _dl_exit,@function \n" \
Re: solock() & nfs_connect
On 11/08/17(Fri) 20:31, Alexander Bluhm wrote: > On Fri, Aug 11, 2017 at 01:18:48PM -0400, Martin Pieuchot wrote: > > Diff below merge all solock()/sounlock() dances inside nfs_connect(). > > Now we sleep for memory while holding the lock. Is this a good > idea? As long as a subsystem outside the NET_LOCK() can release memory, sleeping with the lock held is fine. >What is the advantage of changing it? Not introducing multiple sleeping points in a function manipulating a socket. > The label names "bad" and "out" are confusing. Both are bad, but > bad also does an unlock. I kept 'bad' which now does the unlock and get rid of the 'out' label, ok? Index: nfs/nfs_socket.c === RCS file: /cvs/src/sys/nfs/nfs_socket.c,v retrieving revision 1.122 diff -u -p -r1.122 nfs_socket.c --- nfs/nfs_socket.c10 Aug 2017 19:20:43 - 1.122 +++ nfs/nfs_socket.c11 Aug 2017 19:31:41 - @@ -244,9 +244,13 @@ nfs_connect(struct nfsmount *nmp, struct saddr = mtod(nmp->nm_nam, struct sockaddr *); error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, nmp->nm_soproto); - if (error) - goto bad; + if (error) { + nfs_disconnect(nmp); + return (error); + } + so = nmp->nm_so; + s = solock(so); nmp->nm_soflags = so->so_proto->pr_flags; /* @@ -262,9 +266,7 @@ nfs_connect(struct nfsmount *nmp, struct mopt->m_len = sizeof(int); ip = mtod(mopt, int *); *ip = IP_PORTRANGE_LOW; - s = solock(so); error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); - sounlock(s); if (error) goto bad; @@ -275,9 +277,7 @@ nfs_connect(struct nfsmount *nmp, struct sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; sin->sin_port = htons(0); - s = solock(so); error = sobind(so, m, &proc0); - sounlock(s); m_freem(m); if (error) goto bad; @@ -286,9 +286,7 @@ nfs_connect(struct nfsmount *nmp, struct mopt->m_len = sizeof(int); ip = mtod(mopt, int *); *ip = IP_PORTRANGE_DEFAULT; - s = solock(so); error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); - sounlock(s); if (error) goto bad; } @@ -303,12 +301,9 @@ nfs_connect(struct nfsmount *nmp, struct goto bad; } } else { - s = solock(so); error = soconnect(so, nmp->nm_nam); - if (error) { - sounlock(s); + if (error) goto bad; - } /* * Wait for the connection to complete. Cribbed from the @@ -321,23 +316,19 @@ nfs_connect(struct nfsmount *nmp, struct so->so_error == 0 && rep && (error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){ so->so_state &= ~SS_ISCONNECTING; - sounlock(s); goto bad; } } if (so->so_error) { error = so->so_error; so->so_error = 0; - sounlock(s); goto bad; } - sounlock(s); } /* * Always set receive timeout to detect server crash and reconnect. * Otherwise, we can get stuck in soreceive forever. */ - s = solock(so); so->so_rcv.sb_timeo = (5 * hz); if (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_INT)) so->so_snd.sb_timeo = (5 * hz); @@ -372,11 +363,11 @@ nfs_connect(struct nfsmount *nmp, struct sizeof (u_int32_t)) * 2; } error = soreserve(so, sndreserve, rcvreserve); - sounlock(s); if (error) goto bad; so->so_rcv.sb_flags |= SB_NOINTR; so->so_snd.sb_flags |= SB_NOINTR; + sounlock(s); /* Initialize other non-zero congestion variables */ nfs_init_rtt(nmp); @@ -386,6 +377,7 @@ nfs_connect(struct nfsmount *nmp, struct return (0); bad: + sounlock(s); nfs_disconnect(nmp); return (error); }
csu: _dl_printf no longer needed
The _dl_printf() used to be used in libexec/ld.so/*/archdep.h if an unexpected type of relocation was encountered in ld.so itself. Those went away (we test ld.so before installing it; _dl_exit() is enough) so the static pie bits in lib/csu/*/md_init.h no longer need to supply a no-op _dl_printf() stub. ok? Philip Index: aarch64/md_init.h === RCS file: /data/src/openbsd/src/lib/csu/aarch64/md_init.h,v retrieving revision 1.3 diff -u -p -r1.3 md_init.h --- aarch64/md_init.h 26 Feb 2017 22:26:42 - 1.3 +++ aarch64/md_init.h 8 Jun 2017 06:16:41 - @@ -113,6 +113,4 @@ "_dl_exit: \n" \ " mov x8, #1 \n" \ " svc #0 \n" \ - "_dl_printf:\n" \ - " ret \n" \ ".previous"); Index: alpha/md_init.h === RCS file: /data/src/openbsd/src/lib/csu/alpha/md_init.h,v retrieving revision 1.8 diff -u -p -r1.8 md_init.h --- alpha/md_init.h 19 Jan 2017 23:47:04 - 1.8 +++ alpha/md_init.h 31 Jan 2017 08:52:37 - @@ -102,10 +102,6 @@ "_dl_exit: \n" \ " lda $0, 1 \n" \ " callsys \n" \ - " ret \n" \ - ".globl _dl_printf \n" \ - ".type _dl_printf@function \n" \ - "_dl_printf:\n" \ " ret") #defineMD_START_ARGS char **sp, void (*cleanup)(void) Index: arm/md_init.h === RCS file: /data/src/openbsd/src/lib/csu/arm/md_init.h,v retrieving revision 1.11 diff -u -p -r1.11 md_init.h --- arm/md_init.h 26 Feb 2017 15:20:58 - 1.11 +++ arm/md_init.h 8 Jun 2017 06:16:41 - @@ -157,6 +157,4 @@ "_dl_exit: \n" \ " mov r12, #1 \n" \ " swi #0 \n" \ - "_dl_printf:\n" \ - " mov pc, lr \n" \ ".previous"); Index: hppa/md_init.h === RCS file: /data/src/openbsd/src/lib/csu/hppa/md_init.h,v retrieving revision 1.12 diff -u -p -r1.12 md_init.h --- hppa/md_init.h 26 Feb 2017 22:26:42 - 1.12 +++ hppa/md_init.h 8 Jun 2017 06:16:41 - @@ -156,17 +156,6 @@ "1: bv %r0(%rp)\n" \ " sub %r0, %ret0, %ret0 \n" \ " .exit \n" \ - " .procend\n" \ - " .export _dl_printf, entry \n" \ - " .type _dl_printf,@function\n" \ - " .label _dl_printf \n" \ - " .proc \n" \ - " .callinfo frame=0, calls\n" \ - " .entry \n" \ - "_dl_printf:\n" \ - " bv %r0(%rp)\n" \ - " nop \n" \ - " .exit \n" \ " .procend") Index: i386/md_init.h === RCS file: /data/src/openbsd/src/lib/csu/i386/md_init.h,v retrieving revision 1.8 diff -u -p -r1.8 md_init.h --- i386/md_init.h 7 Aug 2016 02:30:55 - 1.8 +++ i386/md_init.h 31 Jan 2017 08:53:28 - @@ -118,14 +118,6 @@ " xorl%ebp,%ebp # mark deepest stack frame\n" \ " call___start# ___start(argc,argv,envp,0) \n" \ " \n" \ - ".text \n" \ - " .align 4 \n" \ - " .globl _dl_printf \n" \ - " .type _dl_printf,@function\n" \ - "_dl_printf:\n" \ - " ret \n" \ - " \n" \ - ".text \n" \ " .align 4 \n" \ " .globl _dl_exit\n" \ " .type _dl_exit,@function \n" \ Index: mips64/md_init.h === RCS file: /data/src/openbsd/src/lib/csu/mips64/md_init.h,v re
Re: NET_LOCK() w/o argument
On 11.8.2017. 19:56, Martin Pieuchot wrote: > Two weeks ago I remove the splsoftnet()/splx() dance inside the > NET_LOCK(). Turns out we found a single bug, a missing splx() > in net/if_spppsubr.c. > > I believe it's time to move forward and completely remove the > argument. This will allow us to do more funky dances with the > NET_LOCK(). i'm testing this diff with pf, pfsync, ipsec, carp, vlan, trunk, full bgp table and that kind of stuff and for now boxes seems stable...
Re: NET_LOCK() w/o argument
On Fri, Aug 11, 2017 at 01:56:28PM -0400, Martin Pieuchot wrote: > I believe it's time to move forward and completely remove the > argument. This will allow us to do more funky dances with the > NET_LOCK(). OK bluhm@ > diff --git sys/dev/usb/if_umb.c sys/dev/usb/if_umb.c > index 1fbf2ea9c15..8c6c9ccfbe9 100644 > --- sys/dev/usb/if_umb.c > +++ sys/dev/usb/if_umb.c > @@ -947,7 +947,7 @@ umb_state_task(void *arg) > struct ifnet *ifp = GET_IFP(sc); > struct ifreq ifr; > struct in_aliasreq ifra; > - int s, ns; > + int s; > int state; > > s = splnet(); > @@ -971,7 +971,7 @@ umb_state_task(void *arg) >*/ > memset(sc->sc_info.ipv4dns, 0, > sizeof (sc->sc_info.ipv4dns)); > - NET_LOCK(ns); > + NET_LOCK(); > if (in_ioctl(SIOCGIFADDR, (caddr_t)&ifr, ifp, 1) == 0 && > satosin(&ifr.ifr_addr)->sin_addr.s_addr != > INADDR_ANY) { > @@ -980,7 +980,7 @@ umb_state_task(void *arg) > sizeof (ifra.ifra_addr)); > in_ioctl(SIOCDIFADDR, (caddr_t)&ifra, ifp, 1); > } > - NET_UNLOCK(ns); > + NET_UNLOCK(); > } > if_link_state_change(ifp); > } > @@ -1613,7 +1613,7 @@ umb_decode_ip_configuration(struct umb_softc *sc, void > *data, int len) > { > struct mbim_cid_ip_configuration_info *ic = data; > struct ifnet *ifp = GET_IFP(sc); > - int s, ns; > + int s; > uint32_t avail; > uint32_t val; > int n, i; > @@ -1667,9 +1667,9 @@ umb_decode_ip_configuration(struct umb_softc *sc, void > *data, int len) > sin->sin_len = sizeof (ifra.ifra_mask); > in_len2mask(&sin->sin_addr, ipv4elem.prefixlen); > > - NET_LOCK(ns); > + NET_LOCK(); > rv = in_ioctl(SIOCAIFADDR, (caddr_t)&ifra, ifp, 1); > - NET_UNLOCK(ns); > + NET_UNLOCK(); > if (rv == 0) { > if (ifp->if_flags & IFF_DEBUG) > log(LOG_INFO, "%s: IPv4 addr %s, mask %s, " > diff --git sys/kern/kern_sysctl.c sys/kern/kern_sysctl.c > index 7b71ccfde26..3eca46534e0 100644 > --- sys/kern/kern_sysctl.c > +++ sys/kern/kern_sysctl.c > @@ -1302,9 +1302,8 @@ sysctl_file(int *name, u_int namelen, char *where, > size_t *sizep, > extern struct inpcbtable rawin6pcbtable; > #endif > struct inpcb *inp; > - int s; > > - NET_LOCK(s); > + NET_LOCK(); > TAILQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) > FILLSO(inp->inp_socket); > TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) > @@ -1316,7 +1315,7 @@ sysctl_file(int *name, u_int namelen, char *where, > size_t *sizep, > inp_queue) > FILLSO(inp->inp_socket); > #endif > - NET_UNLOCK(s); > + NET_UNLOCK(); > } > fp = LIST_FIRST(&filehead); > /* don't FREF when f_count == 0 to avoid race in fdrop() */ > diff --git sys/kern/sys_socket.c sys/kern/sys_socket.c > index d842d0bd5c1..03883df1ece 100644 > --- sys/kern/sys_socket.c > +++ sys/kern/sys_socket.c > @@ -125,9 +125,9 @@ soo_ioctl(struct file *fp, u_long cmd, caddr_t data, > struct proc *p) >* different entry since a socket's unnecessary >*/ > if (IOCGROUP(cmd) == 'i') { > - NET_LOCK(s); > + NET_LOCK(); > error = ifioctl(so, cmd, data, p); > - NET_UNLOCK(s); > + NET_UNLOCK(); > return (error); > } > if (IOCGROUP(cmd) == 'r') > diff --git sys/kern/uipc_domain.c sys/kern/uipc_domain.c > index ce7091b540c..aad485b865f 100644 > --- sys/kern/uipc_domain.c > +++ sys/kern/uipc_domain.c > @@ -165,7 +165,7 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t > *oldlenp, void *newp, > { > struct domain *dp; > struct protosw *pr; > - int s, error, family, protocol; > + int error, family, protocol; > > /* >* All sysctl names at this level are nonterminal. > @@ -207,10 +207,10 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t > *oldlenp, void *newp, > protocol = name[1]; > for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) > if (pr->pr_protocol == protocol && pr->pr_sysctl) { > - NET_LOCK(s); > + NET_LOCK(); > error = (*pr->pr_sysctl)(name + 2, namelen - 2, >
Re: solock() & nfs_connect
On Fri, Aug 11, 2017 at 01:18:48PM -0400, Martin Pieuchot wrote: > Diff below merge all solock()/sounlock() dances inside nfs_connect(). Now we sleep for memory while holding the lock. Is this a good idea? What is the advantage of changing it? The label names "bad" and "out" are confusing. Both are bad, but bad also does an unlock. bluhm > Index: nfs/nfs_socket.c > === > RCS file: /cvs/src/sys/nfs/nfs_socket.c,v > retrieving revision 1.122 > diff -u -p -r1.122 nfs_socket.c > --- nfs/nfs_socket.c 10 Aug 2017 19:20:43 - 1.122 > +++ nfs/nfs_socket.c 11 Aug 2017 17:14:57 - > @@ -245,8 +245,9 @@ nfs_connect(struct nfsmount *nmp, struct > error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, > nmp->nm_soproto); > if (error) > - goto bad; > + goto out; > so = nmp->nm_so; > + s = solock(so); > nmp->nm_soflags = so->so_proto->pr_flags; > > /* > @@ -262,9 +263,7 @@ nfs_connect(struct nfsmount *nmp, struct > mopt->m_len = sizeof(int); > ip = mtod(mopt, int *); > *ip = IP_PORTRANGE_LOW; > - s = solock(so); > error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); > - sounlock(s); > if (error) > goto bad; > > @@ -275,9 +274,7 @@ nfs_connect(struct nfsmount *nmp, struct > sin->sin_family = AF_INET; > sin->sin_addr.s_addr = INADDR_ANY; > sin->sin_port = htons(0); > - s = solock(so); > error = sobind(so, m, &proc0); > - sounlock(s); > m_freem(m); > if (error) > goto bad; > @@ -286,9 +283,7 @@ nfs_connect(struct nfsmount *nmp, struct > mopt->m_len = sizeof(int); > ip = mtod(mopt, int *); > *ip = IP_PORTRANGE_DEFAULT; > - s = solock(so); > error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); > - sounlock(s); > if (error) > goto bad; > } > @@ -303,12 +298,9 @@ nfs_connect(struct nfsmount *nmp, struct > goto bad; > } > } else { > - s = solock(so); > error = soconnect(so, nmp->nm_nam); > - if (error) { > - sounlock(s); > + if (error) > goto bad; > - } > > /* >* Wait for the connection to complete. Cribbed from the > @@ -321,23 +313,19 @@ nfs_connect(struct nfsmount *nmp, struct > so->so_error == 0 && rep && > (error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){ > so->so_state &= ~SS_ISCONNECTING; > - sounlock(s); > goto bad; > } > } > if (so->so_error) { > error = so->so_error; > so->so_error = 0; > - sounlock(s); > goto bad; > } > - sounlock(s); > } > /* >* Always set receive timeout to detect server crash and reconnect. >* Otherwise, we can get stuck in soreceive forever. >*/ > - s = solock(so); > so->so_rcv.sb_timeo = (5 * hz); > if (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_INT)) > so->so_snd.sb_timeo = (5 * hz); > @@ -372,11 +360,11 @@ nfs_connect(struct nfsmount *nmp, struct > sizeof (u_int32_t)) * 2; > } > error = soreserve(so, sndreserve, rcvreserve); > - sounlock(s); > if (error) > goto bad; > so->so_rcv.sb_flags |= SB_NOINTR; > so->so_snd.sb_flags |= SB_NOINTR; > + sounlock(s); > > /* Initialize other non-zero congestion variables */ > nfs_init_rtt(nmp); > @@ -386,6 +374,8 @@ nfs_connect(struct nfsmount *nmp, struct > return (0); > > bad: > + sounlock(s); > +out: > nfs_disconnect(nmp); > return (error); > }
Re: bsd.regress.mk.5 typo fix
On Fri, Aug 11, 2017 at 12:40:24PM -0400, Rob Pierce wrote: > I just ran across this. Ok? OK bluhm@ > Index: bsd.regress.mk.5 > === > RCS file: /cvs/src/share/man/man5/bsd.regress.mk.5,v > retrieving revision 1.14 > diff -u -p -r1.14 bsd.regress.mk.5 > --- bsd.regress.mk.5 3 Jul 2017 18:19:55 - 1.14 > +++ bsd.regress.mk.5 11 Aug 2017 16:39:12 - > @@ -155,7 +155,7 @@ to run > before, this directory or symlink may not exist. > Then the test should run anyway. > .Pp > -Test are executed with > +Tests are executed with > .Sy make Cm regress , > but running > .Sy make Cm all
NET_LOCK() w/o argument
Two weeks ago I remove the splsoftnet()/splx() dance inside the NET_LOCK(). Turns out we found a single bug, a missing splx() in net/if_spppsubr.c. I believe it's time to move forward and completely remove the argument. This will allow us to do more funky dances with the NET_LOCK(). ok? diff --git sys/dev/usb/if_umb.c sys/dev/usb/if_umb.c index 1fbf2ea9c15..8c6c9ccfbe9 100644 --- sys/dev/usb/if_umb.c +++ sys/dev/usb/if_umb.c @@ -947,7 +947,7 @@ umb_state_task(void *arg) struct ifnet *ifp = GET_IFP(sc); struct ifreq ifr; struct in_aliasreq ifra; - int s, ns; + int s; int state; s = splnet(); @@ -971,7 +971,7 @@ umb_state_task(void *arg) */ memset(sc->sc_info.ipv4dns, 0, sizeof (sc->sc_info.ipv4dns)); - NET_LOCK(ns); + NET_LOCK(); if (in_ioctl(SIOCGIFADDR, (caddr_t)&ifr, ifp, 1) == 0 && satosin(&ifr.ifr_addr)->sin_addr.s_addr != INADDR_ANY) { @@ -980,7 +980,7 @@ umb_state_task(void *arg) sizeof (ifra.ifra_addr)); in_ioctl(SIOCDIFADDR, (caddr_t)&ifra, ifp, 1); } - NET_UNLOCK(ns); + NET_UNLOCK(); } if_link_state_change(ifp); } @@ -1613,7 +1613,7 @@ umb_decode_ip_configuration(struct umb_softc *sc, void *data, int len) { struct mbim_cid_ip_configuration_info *ic = data; struct ifnet *ifp = GET_IFP(sc); - int s, ns; + int s; uint32_t avail; uint32_t val; int n, i; @@ -1667,9 +1667,9 @@ umb_decode_ip_configuration(struct umb_softc *sc, void *data, int len) sin->sin_len = sizeof (ifra.ifra_mask); in_len2mask(&sin->sin_addr, ipv4elem.prefixlen); - NET_LOCK(ns); + NET_LOCK(); rv = in_ioctl(SIOCAIFADDR, (caddr_t)&ifra, ifp, 1); - NET_UNLOCK(ns); + NET_UNLOCK(); if (rv == 0) { if (ifp->if_flags & IFF_DEBUG) log(LOG_INFO, "%s: IPv4 addr %s, mask %s, " diff --git sys/kern/kern_sysctl.c sys/kern/kern_sysctl.c index 7b71ccfde26..3eca46534e0 100644 --- sys/kern/kern_sysctl.c +++ sys/kern/kern_sysctl.c @@ -1302,9 +1302,8 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, extern struct inpcbtable rawin6pcbtable; #endif struct inpcb *inp; - int s; - NET_LOCK(s); + NET_LOCK(); TAILQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) FILLSO(inp->inp_socket); TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) @@ -1316,7 +1315,7 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep, inp_queue) FILLSO(inp->inp_socket); #endif - NET_UNLOCK(s); + NET_UNLOCK(); } fp = LIST_FIRST(&filehead); /* don't FREF when f_count == 0 to avoid race in fdrop() */ diff --git sys/kern/sys_socket.c sys/kern/sys_socket.c index d842d0bd5c1..03883df1ece 100644 --- sys/kern/sys_socket.c +++ sys/kern/sys_socket.c @@ -125,9 +125,9 @@ soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p) * different entry since a socket's unnecessary */ if (IOCGROUP(cmd) == 'i') { - NET_LOCK(s); + NET_LOCK(); error = ifioctl(so, cmd, data, p); - NET_UNLOCK(s); + NET_UNLOCK(); return (error); } if (IOCGROUP(cmd) == 'r') diff --git sys/kern/uipc_domain.c sys/kern/uipc_domain.c index ce7091b540c..aad485b865f 100644 --- sys/kern/uipc_domain.c +++ sys/kern/uipc_domain.c @@ -165,7 +165,7 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, { struct domain *dp; struct protosw *pr; - int s, error, family, protocol; + int error, family, protocol; /* * All sysctl names at this level are nonterminal. @@ -207,10 +207,10 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, protocol = name[1]; for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) if (pr->pr_protocol == protocol && pr->pr_sysctl) { - NET_LOCK(s); + NET_LOCK(); error = (*pr->pr_sysctl)(name + 2, namelen - 2,
Re: Implement __cxa_thread_atexit
On Fri, 11 Aug 2017, Todd C. Miller wrote: > On Fri, 11 Aug 2017 16:31:44 +0200, Mark Kettenis wrote: > > > I've chosen to implement __cxa_thread_atexit() directly instead of > > __cxa_thread_atexit_impl(). I think that is cleaner. It means we > > don't need to make changes to libc++ for this to start working. It > > looks like modern libstdc++ version will detect __cxa_thread_atexit(). > > > > This adds a member to the "TIB". This means that you'll need to > > install the new headers and rebuild ld.so before rebuilding libpthread > > and libc. > > Is there a reason you didn't use mmap() and mprotect() like we do > for __cxa_atexit()? Good point. It's per thread so it doesn't need the locking that the atexit() bits require. (Actually, the atfork bits should be converted to that too. Free project!) Philip
Re: Implement __cxa_thread_atexit
On Fri, 11 Aug 2017 16:31:44 +0200, Mark Kettenis wrote: > I've chosen to implement __cxa_thread_atexit() directly instead of > __cxa_thread_atexit_impl(). I think that is cleaner. It means we > don't need to make changes to libc++ for this to start working. It > looks like modern libstdc++ version will detect __cxa_thread_atexit(). > > This adds a member to the "TIB". This means that you'll need to > install the new headers and rebuild ld.so before rebuilding libpthread > and libc. Is there a reason you didn't use mmap() and mprotect() like we do for __cxa_atexit()? - todd
ksh: remove special handling of export PS1 as root
Currently, if ksh starts as root and PS1 was exported but doesn't contain '#' or '\$' (which will be expanded to '#') then it'll override it with the root default of '# '. This is kind of a corner case, because PS1 is not normally exported. phessler's research seems to indicate that we're alone in behaving this way: everyone else seems to not check but just uses the exported PS1 blindly. This is making it difficult to port mininet to OpenBSD. Let's stop being different. ok? Philip Index: main.c === RCS file: /data/src/openbsd/src/bin/ksh/main.c,v retrieving revision 1.82 diff -u -p -r1.82 main.c --- main.c 17 Oct 2016 17:44:47 - 1.82 +++ main.c 11 Aug 2017 15:16:36 - @@ -313,14 +313,11 @@ main(int argc, char *argv[]) { struct tbl *vp = global("PS1"); - /* Set PS1 if it isn't set, or we are root and prompt doesn't -* contain a # or \$ (only in ksh mode). -*/ - if (!(vp->flag & ISSET) || - (!ksheuid && !strchr(str_val(vp), '#') && - (Flag(FSH) || !strstr(str_val(vp), "\\$" + /* Set PS1 if it isn't set */ + if (!(vp->flag & ISSET)) { /* setstr can't fail here */ setstr(vp, safe_prompt, KSH_RETURN_ERROR); + } } /* Set this before parsing arguments */ Index: ksh.1 === RCS file: /data/src/openbsd/src/bin/ksh/ksh.1,v retrieving revision 1.191 diff -u -p -r1.191 ksh.1 --- ksh.1 6 Jul 2017 15:42:04 - 1.191 +++ ksh.1 11 Aug 2017 15:17:09 - @@ -1535,15 +1535,6 @@ The default prompt is for non-root users, .Sq #\ \& for root. -If -.Nm -is invoked by root and -.Ev PS1 -does not contain a -.Sq # -character, the default value will be used even if -.Ev PS1 -already exists in the environment. .Pp The following backslash-escaped special characters can be used to customise the prompt:
solock() & nfs_connect
Diff below merge all solock()/sounlock() dances inside nfs_connect(). ok? Index: nfs/nfs_socket.c === RCS file: /cvs/src/sys/nfs/nfs_socket.c,v retrieving revision 1.122 diff -u -p -r1.122 nfs_socket.c --- nfs/nfs_socket.c10 Aug 2017 19:20:43 - 1.122 +++ nfs/nfs_socket.c11 Aug 2017 17:14:57 - @@ -245,8 +245,9 @@ nfs_connect(struct nfsmount *nmp, struct error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype, nmp->nm_soproto); if (error) - goto bad; + goto out; so = nmp->nm_so; + s = solock(so); nmp->nm_soflags = so->so_proto->pr_flags; /* @@ -262,9 +263,7 @@ nfs_connect(struct nfsmount *nmp, struct mopt->m_len = sizeof(int); ip = mtod(mopt, int *); *ip = IP_PORTRANGE_LOW; - s = solock(so); error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); - sounlock(s); if (error) goto bad; @@ -275,9 +274,7 @@ nfs_connect(struct nfsmount *nmp, struct sin->sin_family = AF_INET; sin->sin_addr.s_addr = INADDR_ANY; sin->sin_port = htons(0); - s = solock(so); error = sobind(so, m, &proc0); - sounlock(s); m_freem(m); if (error) goto bad; @@ -286,9 +283,7 @@ nfs_connect(struct nfsmount *nmp, struct mopt->m_len = sizeof(int); ip = mtod(mopt, int *); *ip = IP_PORTRANGE_DEFAULT; - s = solock(so); error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, mopt); - sounlock(s); if (error) goto bad; } @@ -303,12 +298,9 @@ nfs_connect(struct nfsmount *nmp, struct goto bad; } } else { - s = solock(so); error = soconnect(so, nmp->nm_nam); - if (error) { - sounlock(s); + if (error) goto bad; - } /* * Wait for the connection to complete. Cribbed from the @@ -321,23 +313,19 @@ nfs_connect(struct nfsmount *nmp, struct so->so_error == 0 && rep && (error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){ so->so_state &= ~SS_ISCONNECTING; - sounlock(s); goto bad; } } if (so->so_error) { error = so->so_error; so->so_error = 0; - sounlock(s); goto bad; } - sounlock(s); } /* * Always set receive timeout to detect server crash and reconnect. * Otherwise, we can get stuck in soreceive forever. */ - s = solock(so); so->so_rcv.sb_timeo = (5 * hz); if (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_INT)) so->so_snd.sb_timeo = (5 * hz); @@ -372,11 +360,11 @@ nfs_connect(struct nfsmount *nmp, struct sizeof (u_int32_t)) * 2; } error = soreserve(so, sndreserve, rcvreserve); - sounlock(s); if (error) goto bad; so->so_rcv.sb_flags |= SB_NOINTR; so->so_snd.sb_flags |= SB_NOINTR; + sounlock(s); /* Initialize other non-zero congestion variables */ nfs_init_rtt(nmp); @@ -386,6 +374,8 @@ nfs_connect(struct nfsmount *nmp, struct return (0); bad: + sounlock(s); +out: nfs_disconnect(nmp); return (error); }
Re: pfctl -N: no dns resolution
On Fri, Aug 11, 2017 at 06:05:09PM +0200, Sebastian Benoit wrote: > Hi, > > this adds a -N option to pfctl that turns of dns resolution for all the > things where a dns entry is a possible thing, i.e. in rules ("pass in from > www.openbsd.org") or table entries. > > Its usefull to make sure the configuration will load when DNS is not > available. > While I don't like adding knobs I have been convinced of the operational need and the need to not break installed sytems (however fragile they might be). The diff reads OK > ok? > > > diff --git regress/sbin/pfctl/Makefile regress/sbin/pfctl/Makefile > index ff9c38e28a8..80364b8ba14 100644 > --- regress/sbin/pfctl/Makefile > +++ regress/sbin/pfctl/Makefile > @@ -29,6 +29,7 @@ PFOPT=1 2 6 > PFIF2IP=1 2 3 > PFCHKSUM=1 2 3 > PFCMD=1 > +PFCMDFAIL=1 > > MAKEOBJDIRPREFIX= > > @@ -252,6 +253,32 @@ REGRESS_TARGETS+=pfcmd > REGRESS_ROOT_TARGETS+=pfcmd > UPDATE_TARGETS+=pfcmd-update > > +.for n in ${PFCMDFAIL} > +PFCMDFAIL_TARGETS+=pfcmdfail${n} > +PFCMDFAIL_UPDATES+=pfcmdfail${n}-update > + > +pfcmdfail${n}: > + ${SUDO} pfctl `cat ${.CURDIR}/pfcmdfail${n}.opts` \ > + -f - < ${.CURDIR}/pfcmdfail${n}.in 2>&1 | \ > +diff -u ${.CURDIR}/pfcmdfail${n}.ok /dev/stdin > + > +pfcmdfail${n}-update: > + if ${SUDO} pfctl `cat ${.CURDIR}/pfcmdfail${n}.opts` \ > + -f - < ${.CURDIR}/pfcmdfail${n}.in > \ > + ${.CURDIR}/pfcmdfail${n}.ok 2>&1; then \ > + true; \ > + fi; > + > +.endfor > + > +pfcmdfail: ${PFCMDFAIL_TARGETS} > +pfcmdfail-update:${PFCMDFAIL_UPDATES} > +NODEFAULT_TARGETS+=pfcmdfail > +REGRESS_TARGETS+=pfcmdfail > + > +REGRESS_ROOT_TARGETS+=pfcmd > +UPDATE_TARGETS+=pfcmd-update > + > .for n in ${PFSETUP} > PFSETUP_TARGETS+=pfsetup${n} > PFSETUP_UPDATES+=pfsetup${n}-update > diff --git regress/sbin/pfctl/pfcmd2.out regress/sbin/pfctl/pfcmd2.out > new file mode 100644 > index 000..e991e53a580 > --- /dev/null > +++ regress/sbin/pfctl/pfcmd2.out > @@ -0,0 +1,2 @@ > +no IP address found for localhost > +pfcmd2.in:1: could not parse host specification > diff --git regress/sbin/pfctl/pfcmdfail1.in regress/sbin/pfctl/pfcmdfail1.in > new file mode 100644 > index 000..68d5b071164 > --- /dev/null > +++ regress/sbin/pfctl/pfcmdfail1.in > @@ -0,0 +1 @@ > +pass in from localhost > diff --git regress/sbin/pfctl/pfcmdfail1.ok regress/sbin/pfctl/pfcmdfail1.ok > new file mode 100644 > index 000..011baa3283d > --- /dev/null > +++ regress/sbin/pfctl/pfcmdfail1.ok > @@ -0,0 +1,2 @@ > +no IP address found for localhost > +stdin:1: could not parse host specification > diff --git regress/sbin/pfctl/pfcmdfail1.opts > regress/sbin/pfctl/pfcmdfail1.opts > new file mode 100644 > index 000..b641baefa31 > --- /dev/null > +++ regress/sbin/pfctl/pfcmdfail1.opts > @@ -0,0 +1 @@ > +-nN > diff --git sbin/pfctl/parse.y sbin/pfctl/parse.y > index 5ae134e04a2..0cbb2d651be 100644 > --- sbin/pfctl/parse.y > +++ sbin/pfctl/parse.y > @@ -342,7 +342,7 @@ intdisallow_table(struct node_host *, > const char *); > int disallow_urpf_failed(struct node_host *, const char *); > int disallow_alias(struct node_host *, const char *); > int rule_consistent(struct pf_rule *, int); > -int process_tabledef(char *, struct table_opts *); > +int process_tabledef(char *, struct table_opts *, int); > void expand_label_str(char *, size_t, const char *, const char *); > void expand_label_if(const char *, char *, size_t, const char *); > void expand_label_addr(const char *, char *, size_t, u_int8_t, > @@ -1176,7 +1176,7 @@ tabledef: TABLE '<' STRING '>' table_opts { > free($3); > YYERROR; > } > - if (process_tabledef($3, &$5)) { > + if (process_tabledef($3, &$5, pf->opts)) { > free($3); > YYERROR; > } > @@ -2035,7 +2035,7 @@ filter_opt : USER uids { > filter_opts.rtableid = $2; > } > | DIVERTTO STRING PORT portplain { > - if ((filter_opts.divert.addr = host($2)) == NULL) { > + if ((filter_opts.divert.addr = host($2, pf->opts)) == > NULL) { > yyerror("could not parse divert address: %s", > $2); > free($2); > @@ -2670,7 +2670,7 @@ optweight : WEIGHT NUMBER { > ; > > host : STRING{ > - if (($$ = host($1)) == NULL){ > + if (($$ = host($1, pf->opts)) == NULL) { > /* error. "any" is handled elsewhere */ > free($1); > yyerror(
bsd.regress.mk.5 typo fix
I just ran across this. Ok? Index: bsd.regress.mk.5 === RCS file: /cvs/src/share/man/man5/bsd.regress.mk.5,v retrieving revision 1.14 diff -u -p -r1.14 bsd.regress.mk.5 --- bsd.regress.mk.53 Jul 2017 18:19:55 - 1.14 +++ bsd.regress.mk.511 Aug 2017 16:39:12 - @@ -155,7 +155,7 @@ to run before, this directory or symlink may not exist. Then the test should run anyway. .Pp -Test are executed with +Tests are executed with .Sy make Cm regress , but running .Sy make Cm all
Re: Implement __cxa_thread_atexit
On Fri, 11 Aug 2017, Mark Kettenis wrote: > The diff below implements __cxa_thread_atexit(). Calls to this function > are emitted by the compiler to schedule running desctructors for > thread_local objects when a thread terminates or calls exit(3). The > Linux implementation prevents unloading of shared libraries that > registered such destructors to prevent things from crashing. This diff > does not implement that functionality yet. I plan to add that later. > I expect this to be a bit of a corner case. > > I've chosen to implement __cxa_thread_atexit() directly instead of > __cxa_thread_atexit_impl(). I think that is cleaner. It means we > don't need to make changes to libc++ for this to start working. It > looks like modern libstdc++ version will detect __cxa_thread_atexit(). > > This adds a member to the "TIB". Tis means that you'll need to > install the new headers and rebuild ld.so before rebuilding libpthread > and libc. > > This will require a libc minor bump. But maybe it could ride the > scheduled major bump? Either seems fine. Couple comments below... > --- include/tib.h 20 Apr 2017 16:07:52 - 1.4 > +++ include/tib.h 11 Aug 2017 14:20:30 - > @@ -135,6 +135,7 @@ > */ > > struct tib { > + void*tib_atexit; > int tib_thread_flags; /* internal to libpthread */ > pid_t tib_tid; > int tib_cantcancel; > @@ -182,6 +183,7 @@ struct tib { > int tib_cantcancel; > pid_t tib_tid; > int tib_thread_flags; /* internal to libpthread */ > + void*tib_atexit; > #if !defined(__LP64__) && !defined(__i386) > int __tib_padding; /* padding for 8byte alignment */ > #endif To keep this structure a multiple of 8 in size, the padding conditionals need to swap around, so that the extra member is only present on i386. HOWEVER, looking again at _dl_tib_allocate(), I already taught it to round up the sizes for correct alignment of the structs! I think __tib_padding can go away now. ... > +DEF_STRONG(__cxa_thread_atexit); ... > +PROTO_NORMAL(__cxa_thread_atexit); It's not actually called inside libc, right? If not, you can delete DEF_STRONG() and use PROTO_STD_DEPRECATED() intead of PROTO_NORMAL() (case IIb1 in libc/include/README) Philip
pfctl -N: no dns resolution
Hi, this adds a -N option to pfctl that turns of dns resolution for all the things where a dns entry is a possible thing, i.e. in rules ("pass in from www.openbsd.org") or table entries. Its usefull to make sure the configuration will load when DNS is not available. ok? diff --git regress/sbin/pfctl/Makefile regress/sbin/pfctl/Makefile index ff9c38e28a8..80364b8ba14 100644 --- regress/sbin/pfctl/Makefile +++ regress/sbin/pfctl/Makefile @@ -29,6 +29,7 @@ PFOPT=1 2 6 PFIF2IP=1 2 3 PFCHKSUM=1 2 3 PFCMD=1 +PFCMDFAIL=1 MAKEOBJDIRPREFIX= @@ -252,6 +253,32 @@ REGRESS_TARGETS+=pfcmd REGRESS_ROOT_TARGETS+=pfcmd UPDATE_TARGETS+=pfcmd-update +.for n in ${PFCMDFAIL} +PFCMDFAIL_TARGETS+=pfcmdfail${n} +PFCMDFAIL_UPDATES+=pfcmdfail${n}-update + +pfcmdfail${n}: + ${SUDO} pfctl `cat ${.CURDIR}/pfcmdfail${n}.opts` \ + -f - < ${.CURDIR}/pfcmdfail${n}.in 2>&1 | \ +diff -u ${.CURDIR}/pfcmdfail${n}.ok /dev/stdin + +pfcmdfail${n}-update: + if ${SUDO} pfctl `cat ${.CURDIR}/pfcmdfail${n}.opts` \ + -f - < ${.CURDIR}/pfcmdfail${n}.in > \ + ${.CURDIR}/pfcmdfail${n}.ok 2>&1; then \ + true; \ + fi; + +.endfor + +pfcmdfail: ${PFCMDFAIL_TARGETS} +pfcmdfail-update: ${PFCMDFAIL_UPDATES} +NODEFAULT_TARGETS+=pfcmdfail +REGRESS_TARGETS+=pfcmdfail + +REGRESS_ROOT_TARGETS+=pfcmd +UPDATE_TARGETS+=pfcmd-update + .for n in ${PFSETUP} PFSETUP_TARGETS+=pfsetup${n} PFSETUP_UPDATES+=pfsetup${n}-update diff --git regress/sbin/pfctl/pfcmd2.out regress/sbin/pfctl/pfcmd2.out new file mode 100644 index 000..e991e53a580 --- /dev/null +++ regress/sbin/pfctl/pfcmd2.out @@ -0,0 +1,2 @@ +no IP address found for localhost +pfcmd2.in:1: could not parse host specification diff --git regress/sbin/pfctl/pfcmdfail1.in regress/sbin/pfctl/pfcmdfail1.in new file mode 100644 index 000..68d5b071164 --- /dev/null +++ regress/sbin/pfctl/pfcmdfail1.in @@ -0,0 +1 @@ +pass in from localhost diff --git regress/sbin/pfctl/pfcmdfail1.ok regress/sbin/pfctl/pfcmdfail1.ok new file mode 100644 index 000..011baa3283d --- /dev/null +++ regress/sbin/pfctl/pfcmdfail1.ok @@ -0,0 +1,2 @@ +no IP address found for localhost +stdin:1: could not parse host specification diff --git regress/sbin/pfctl/pfcmdfail1.opts regress/sbin/pfctl/pfcmdfail1.opts new file mode 100644 index 000..b641baefa31 --- /dev/null +++ regress/sbin/pfctl/pfcmdfail1.opts @@ -0,0 +1 @@ +-nN diff --git sbin/pfctl/parse.y sbin/pfctl/parse.y index 5ae134e04a2..0cbb2d651be 100644 --- sbin/pfctl/parse.y +++ sbin/pfctl/parse.y @@ -342,7 +342,7 @@ int disallow_table(struct node_host *, const char *); int disallow_urpf_failed(struct node_host *, const char *); int disallow_alias(struct node_host *, const char *); int rule_consistent(struct pf_rule *, int); -int process_tabledef(char *, struct table_opts *); +int process_tabledef(char *, struct table_opts *, int); voidexpand_label_str(char *, size_t, const char *, const char *); voidexpand_label_if(const char *, char *, size_t, const char *); voidexpand_label_addr(const char *, char *, size_t, u_int8_t, @@ -1176,7 +1176,7 @@ tabledef : TABLE '<' STRING '>' table_opts { free($3); YYERROR; } - if (process_tabledef($3, &$5)) { + if (process_tabledef($3, &$5, pf->opts)) { free($3); YYERROR; } @@ -2035,7 +2035,7 @@ filter_opt: USER uids { filter_opts.rtableid = $2; } | DIVERTTO STRING PORT portplain { - if ((filter_opts.divert.addr = host($2)) == NULL) { + if ((filter_opts.divert.addr = host($2, pf->opts)) == NULL) { yyerror("could not parse divert address: %s", $2); free($2); @@ -2670,7 +2670,7 @@ optweight : WEIGHT NUMBER { ; host : STRING{ - if (($$ = host($1)) == NULL){ + if (($$ = host($1, pf->opts)) == NULL) { /* error. "any" is handled elsewhere */ free($1); yyerror("could not parse host specification"); @@ -2682,7 +2682,8 @@ host : STRING{ | STRING '-' STRING { struct node_host *b, *e; - if ((b = host($1)) == NULL || (e = host($3)) == NULL) { + if ((b = host($1, pf->opts)) == NULL || + (e = host($3, pf->opts)) == NULL) {
slaacd: simplify route message handling
When read(2)'ing from the routing socket only one message is returned. Clue provided by jca and claudio. OK? diff --git frontend.c frontend.c index f78c9802292..4193517e37b 100644 --- frontend.c +++ frontend.c @@ -536,11 +536,9 @@ route_receive(int fd, short events, void *arg) { static uint8_t buf[ROUTE_SOCKET_BUF_SIZE]; - struct rt_msghdr*rtm; + struct rt_msghdr*rtm = (struct rt_msghdr *)buf; struct sockaddr *sa, *rti_info[RTAX_MAX]; - size_t len, offset; ssize_t n; - char*next; if ((n = read(fd, &buf, sizeof(buf))) == -1) { if (errno == EAGAIN || errno == EINTR) @@ -549,26 +547,21 @@ route_receive(int fd, short events, void *arg) return; } - if (n == 0) { - log_warnx("routing socket closed"); + if (n == 0) + fatal("routing socket closed"); + + if (n < rtm->rtm_msglen) { + log_warnx("partial rtm in buffer"); return; } - len = n; - for (offset = 0; offset < len; offset += rtm->rtm_msglen) { - next = buf + offset; - rtm = (struct rt_msghdr *)next; - if (len < offset + sizeof(u_short) || - len < offset + rtm->rtm_msglen) - fatalx("rtmsg_process: partial rtm in buffer"); - if (rtm->rtm_version != RTM_VERSION) - continue; + if (rtm->rtm_version != RTM_VERSION) + return; - sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); - get_rtaddrs(rtm->rtm_addrs, sa, rti_info); + sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); + get_rtaddrs(rtm->rtm_addrs, sa, rti_info); - handle_route_message(rtm, rti_info); - } + handle_route_message(rtm, rti_info); } void -- I'm not entirely sure you are real.
Implement __cxa_thread_atexit
The diff below implements __cxa_thread_atexit(). Calls to this function are emitted by the compiler to schedule running desctructors for thread_local objects when a thread terminates or calls exit(3). The Linux implementation prevents unloading of shared libraries that registered such destructors to prevent things from crashing. This diff does not implement that functionality yet. I plan to add that later. I expect this to be a bit of a corner case. I've chosen to implement __cxa_thread_atexit() directly instead of __cxa_thread_atexit_impl(). I think that is cleaner. It means we don't need to make changes to libc++ for this to start working. It looks like modern libstdc++ version will detect __cxa_thread_atexit(). This adds a member to the "TIB". Tis means that you'll need to install the new headers and rebuild ld.so before rebuilding libpthread and libc. This will require a libc minor bump. But maybe it could ride the scheduled major bump? Index: include/tib.h === RCS file: /cvs/src/include/tib.h,v retrieving revision 1.4 diff -u -p -r1.4 tib.h --- include/tib.h 20 Apr 2017 16:07:52 - 1.4 +++ include/tib.h 11 Aug 2017 14:20:30 - @@ -135,6 +135,7 @@ */ struct tib { + void*tib_atexit; int tib_thread_flags; /* internal to libpthread */ pid_t tib_tid; int tib_cantcancel; @@ -182,6 +183,7 @@ struct tib { int tib_cantcancel; pid_t tib_tid; int tib_thread_flags; /* internal to libpthread */ + void*tib_atexit; #if !defined(__LP64__) && !defined(__i386) int __tib_padding; /* padding for 8byte alignment */ #endif @@ -207,6 +209,7 @@ struct tib { #defineTIB_INIT(tib, dtv, thread) do {\ (tib)->tib_thread = (thread); \ + (tib)->tib_atexit = NULL; \ (tib)->tib_locale = NULL; \ (tib)->tib_cantcancel = 0;\ (tib)->tib_cancel_point = 0;\ Index: lib/librthread/rthread.c === RCS file: /cvs/src/lib/librthread/rthread.c,v retrieving revision 1.95 diff -u -p -r1.95 rthread.c --- lib/librthread/rthread.c27 Jul 2017 16:35:08 - 1.95 +++ lib/librthread/rthread.c11 Aug 2017 14:20:30 - @@ -331,6 +331,12 @@ pthread_exit(void *retval) oclfn->fn(oclfn->arg); free(oclfn); } + while (tib->tib_atexit) { + struct thread_atexit_fn *fnp = tib->tib_atexit; + tib->tib_atexit = fnp->next; + fnp->func(fnp->arg); + free(fnp); + } _rthread_tls_destructors(thread); _spinlock(&_thread_lock); LIST_REMOVE(thread, threads); Index: lib/libc/Symbols.list === RCS file: /cvs/src/lib/libc/Symbols.list,v retrieving revision 1.54 diff -u -p -r1.54 Symbols.list --- lib/libc/Symbols.list 19 Jun 2017 03:06:26 - 1.54 +++ lib/libc/Symbols.list 11 Aug 2017 14:20:30 - @@ -1420,6 +1420,7 @@ random /* stdlib */ _Exit __cxa_atexit +__cxa_thread_atexit __cxa_finalize __isthreaded a64l Index: lib/libc/include/thread_private.h === RCS file: /cvs/src/lib/libc/include/thread_private.h,v retrieving revision 1.29 diff -u -p -r1.29 thread_private.h --- lib/libc/include/thread_private.h 15 Oct 2016 18:24:40 - 1.29 +++ lib/libc/include/thread_private.h 11 Aug 2017 14:20:31 - @@ -96,6 +96,12 @@ struct thread_callbacks { __pid_t (*tc_vfork)(void); }; +struct thread_atexit_fn { + void (*func)(void *); + void *arg; + struct thread_atexit_fn *next; +}; + __BEGIN_PUBLIC_DECLS /* * Set the callbacks used by libc Index: lib/libc/stdlib/atexit.c === RCS file: /cvs/src/lib/libc/stdlib/atexit.c,v retrieving revision 1.24 diff -u -p -r1.24 atexit.c --- lib/libc/stdlib/atexit.c10 Nov 2015 04:14:03 - 1.24 +++ lib/libc/stdlib/atexit.c11 Aug 2017 14:20:31 - @@ -38,6 +38,8 @@ #include "atfork.h" #include "thread_private.h" +#include "tib.h" + struct atexit *__atexit; static int restartloop; @@ -121,6 +123,25 @@ atexit(void (*fn)(void)) } DEF_STRONG(atexit); +int +__cxa_thread_atexit(void (*func)(void *), void *arg, void *dso) +{ + struct thread_atexit_fn *fnp; + struct tib *tib = TIB_GET(); + + fnp = calloc(1, sizeof(struct thread_atexit_fn)); + if (fnp == NULL) + return -1; + + fnp->func = func; + fnp->arg = arg; + fnp->next = tib->tib_atexit; + tib->tib_atexit = fnp; + + return 0; +} +DEF_STRONG(__cxa_thread_atexit); +
Re: openssl(1) not error exiting on full file system
Ping: On Tue, 11 Apr 2017 11:28:38 +0100 Craig Skinner wrote: > Hi again, > > On 2017-04-10 Mon 14:31 PM |, Craig Skinner wrote: > > On Mon, 10 Apr 2017 12:46:03 +0100 Craig Skinner wrote: > > > $ openssl enc -bf -salt \ > > > -pass file:/etc/myname -in /bsd \ > > > -out /altroot/tmp/bsd.crypto > > > > > > /altroot: write failed, file system is full > > > $ print $? > > > 0 > > > > openssl error exits for other output file creation problems: > ... .. http://marc.info/?l=openbsd-tech&m=149190654818169 http://marc.info/?t=14918248523