Re: rpki-client: TZ=UTC + localtime -> gmtime?

2022-04-21 Thread Sebastian Benoit
Claudio Jeker(cje...@diehard.n-r-g.com) on 2022.04.20 15:12:57 +0200:
> On Wed, Apr 20, 2022 at 03:00:15PM +0200, Theo Buehler wrote:
> > Found this when looking at the timezone issue a couple of weeks back and
> > then forgot about it:
> > 
> > This setenv() + localtime() looks like a hack to me and I don't really
> > understand why it should be preferable over using gmtime() directly. The
> > only change in output that I can see is that it causes %Z to print GMT
> > instead of UTC, so I modified the format string accordingly (but I have
> > no strong opinion on this).
> 
> UTC is the proper timezone here. Not sure why gmtime results in %Z to
> return GMT since gmtime converts into UTC. On the other hand timezones
> in struct tm are strange so it probably just defaults to GMT for a 0
> offset time.

well, no.
UTC is not a timezone. UTC is a time standard.
GMT is the correct timezone.



Re: refcount btrace

2022-04-21 Thread Alexander Bluhm
I still think it is worth to have refcount debugging in generic
kernel dt(4).  Having tools is easier than first adding printf to
hunt a bug.  I see no downside.

ok?

bluhm

Index: dev/dt/dt_prov_static.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/dt/dt_prov_static.c,v
retrieving revision 1.13
diff -u -p -r1.13 dt_prov_static.c
--- dev/dt/dt_prov_static.c 17 Mar 2022 14:53:59 -  1.13
+++ dev/dt/dt_prov_static.c 21 Apr 2022 21:06:03 -
@@ -87,6 +87,12 @@ DT_STATIC_PROBE1(smr, barrier_exit, "int
 DT_STATIC_PROBE0(smr, wakeup);
 DT_STATIC_PROBE2(smr, thread, "uint64_t", "uint64_t");
 
+/*
+ * reference counting
+ */
+DT_STATIC_PROBE0(refcnt, none);
+DT_STATIC_PROBE3(refcnt, inpcb, "void *", "int", "int");
+DT_STATIC_PROBE3(refcnt, tdb, "void *", "int", "int");
 
 /*
  * List of all static probes
@@ -127,15 +133,24 @@ struct dt_probe *const dtps_static[] = {
&_DT_STATIC_P(smr, barrier_exit),
&_DT_STATIC_P(smr, wakeup),
&_DT_STATIC_P(smr, thread),
+   /* refcnt */
+   &_DT_STATIC_P(refcnt, none),
+   &_DT_STATIC_P(refcnt, inpcb),
+   &_DT_STATIC_P(refcnt, tdb),
 };
 
+struct dt_probe *const *dtps_index_refcnt;
+
 int
 dt_prov_static_init(void)
 {
int i;
 
-   for (i = 0; i < nitems(dtps_static); i++)
+   for (i = 0; i < nitems(dtps_static); i++) {
+   if (dtps_static[i] == &_DT_STATIC_P(refcnt, none))
+   dtps_index_refcnt = _static[i];
dt_dev_register_probe(dtps_static[i]);
+   }
 
return i;
 }
Index: dev/dt/dtvar.h
===
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/dt/dtvar.h,v
retrieving revision 1.13
diff -u -p -r1.13 dtvar.h
--- dev/dt/dtvar.h  27 Feb 2022 10:14:01 -  1.13
+++ dev/dt/dtvar.h  21 Apr 2022 21:06:03 -
@@ -313,11 +313,30 @@ extern volatile uint32_t  dt_tracing; /* 
 #defineDT_STATIC_ENTER(func, name, args...) do {   
\
extern struct dt_probe _DT_STATIC_P(func, name);\
struct dt_probe *dtp = &_DT_STATIC_P(func, name);   \
-   struct dt_provider *dtpv = dtp->dtp_prov;   \
\
if (__predict_false(dt_tracing) &&  \
__predict_false(dtp->dtp_recording)) {  \
+   struct dt_provider *dtpv = dtp->dtp_prov;   \
+   \
dtpv->dtpv_enter(dtpv, dtp, args);  \
+   }   \
+} while (0)
+
+#define _DT_INDEX_P(func)  (dtps_index_##func)
+
+#define DT_INDEX_ENTER(func, index, args...) do {  \
+   extern struct dt_probe **_DT_INDEX_P(func); \
+   \
+   if (__predict_false(dt_tracing) &&  \
+   __predict_false(index > 0) &&   \
+   __predict_true(_DT_INDEX_P(func) != NULL)) {\
+   struct dt_probe *dtp = _DT_INDEX_P(func)[index];\
+   \
+   if(__predict_false(dtp->dtp_recording)) {   \
+   struct dt_provider *dtpv = dtp->dtp_prov;   \
+   \
+   dtpv->dtpv_enter(dtpv, dtp, args);  \
+   }   \
}   \
 } while (0)
 
Index: kern/kern_synch.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_synch.c,v
retrieving revision 1.185
diff -u -p -r1.185 kern_synch.c
--- kern/kern_synch.c   18 Mar 2022 15:32:06 -  1.185
+++ kern/kern_synch.c   21 Apr 2022 21:06:03 -
@@ -804,7 +804,15 @@ sys___thrwakeup(struct proc *p, void *v,
 void
 refcnt_init(struct refcnt *r)
 {
+   refcnt_init_trace(r, 0);
+}
+
+void
+refcnt_init_trace(struct refcnt *r, int idx)
+{
+   r->r_traceidx = idx;
atomic_store_int(>r_refs, 1);
+   TRACEINDEX(refcnt, r->r_traceidx, r, 0, +1);
 }
 
 void
@@ -814,6 +822,7 @@ refcnt_take(struct refcnt *r)
 
refs = atomic_inc_int_nv(>r_refs);
KASSERT(refs != 0);
+   TRACEINDEX(refcnt, r->r_traceidx, r, refs - 1, +1);
(void)refs;
 }
 
@@ -824,6 +833,7 @@ refcnt_rele(struct refcnt *r)
 
refs = atomic_dec_int_nv(>r_refs);
KASSERT(refs != ~0);
+   TRACEINDEX(refcnt, r->r_traceidx, r, refs + 1, -1);

Re: Provide memory barriers in refcnt_rele() and refcnt_finalize()

2022-04-21 Thread Mark Kettenis
> Date: Thu, 21 Apr 2022 22:17:31 +0200
> From: Alexander Bluhm 
> 
> On Mon, Apr 18, 2022 at 08:33:06AM +, Visa Hankala wrote:
> > I think the sanest solution is to add the release and acquire barriers
> > in refcnt_rele().
> 
> Getting memory barriers right is too complicated for developers
> doing MP stuff.  The existing locking and refcount primitives have
> to implement that functionality.  I am on visa@'s side and would
> prefer a memory barrier in refcount API instead of searching for
> races in MP code.
> 
> Better waste some CPU cycles in some cases than having strange
> behavior due to missing barries in other cases.

I don't disagree with that.  The refcount API is at the same level as
the mutex API and explicit memory barriers should not be needed to use
it safely.  It's just that it isn't obvious what the right memory
ordering semantics are for a refcount API.  For some reason this
doesn't seem to be something that's widely discussed.

The Linux include/linux/refcount.h file has the following comment at
the start:

 * Memory ordering
 * ===
 *
 * Memory ordering rules are slightly relaxed wrt regular atomic_t functions
 * and provide only what is strictly required for refcounts.
 *
 * The increments are fully relaxed; these will not provide ordering. The
 * rationale is that whatever is used to obtain the object we're increasing the
 * reference count on will provide the ordering. For locked data structures,
 * its the lock acquire, for RCU/lockless data structures its the dependent
 * load.
 *
 * Do note that inc_not_zero() provides a control dependency which will order
 * future stores against the inc, this ensures we'll never modify the object
 * if we did not in fact acquire a reference.
 *
 * The decrements will provide release order, such that all the prior loads and
 * stores will be issued before, it also provides a control dependency, which
 * will order us against the subsequent free().
 *
 * The control dependency is against the load of the cmpxchg (ll/sc) that
 * succeeded. This means the stores aren't fully ordered, but this is fine
 * because the 1->0 transition indicates no concurrency.
 *
 * Note that the allocator is responsible for ordering things between free()
 * and alloc().
 *
 * The decrements dec_and_test() and sub_and_test() also provide acquire
 * ordering on success.

That is still a bit murky, but I think it matches what visa@'s diff
does for refcnt_rele(9).  And doing what Linux does in its refcount
API is probably a good thing.  But I don't think it covers the
membar_sync() added to the end of refcnt_finalize(9), so I'm not
confident about that bit, and would like to understand that better.

The other issue I have with the diff is that it documentations the
memory ordering in terms of acquire and release which is not what we
do in other places such as the membar_enter(9) man page.  Maybe this
should explicitly call out the memory ordering like what the Linux
comment does.



Re: Provide memory barriers in refcnt_rele() and refcnt_finalize()

2022-04-21 Thread Alexander Bluhm
On Mon, Apr 18, 2022 at 08:33:06AM +, Visa Hankala wrote:
> I think the sanest solution is to add the release and acquire barriers
> in refcnt_rele().

Getting memory barriers right is too complicated for developers
doing MP stuff.  The existing locking and refcount primitives have
to implement that functionality.  I am on visa@'s side and would
prefer a memory barrier in refcount API instead of searching for
races in MP code.

Better waste some CPU cycles in some cases than having strange
behavior due to missing barries in other cases.

bluhm



Re: pf igmp icmp6 multicast router alert

2022-04-21 Thread Florian Obser
On 2022-04-21 21:10 +02, Alexander Bluhm  wrote:
> On Thu, Apr 21, 2022 at 08:56:07PM +0200, Otto Moerbeek wrote:
>> > Currently it allows all options.  Should I make it specific to
>> > router alert with IGMP or ICMP6?
>> 
>> To me it looks like the icmp6 case already is limited to MLD?
>
> The question is the other way around.  My current diff allows any
> option with ICMP6 MLD.  Do we want to restict the option to router
> alert?
>
> In our ip6.h we have:
> #define IP6OPT_JUMBO0xC2/* 11 0 00010 = 194 */
> #define IP6OPT_NSAP_ADDR0xC3/* 11 0 00011 */
> #define IP6OPT_TUNNEL_LIMIT 0x04/* 00 0 00100 */
> #define IP6OPT_ROUTER_ALERT 0x05/* 00 0 00101 (RFC3542, recommended) 
> */
>
> And who knows what other options have been designed.
>
> In ip.h I see these:
> #define IPOPT_RR7   /* record packet route */
> #define IPOPT_TS68  /* timestamp */
> #define IPOPT_SECURITY  130 /* provide s,c,h,tcc */
> #define IPOPT_LSRR  131 /* loose source route */
> #define IPOPT_SATID 136 /* satnet id */
> #define IPOPT_SSRR  137 /* strict source route */
> #define IPOPT_RA148 /* router alert */
>
> The option I have ever seen in the wild is router alert.  So it may
> be better to allow IGMP and ICMP6 multicast if router alert is the
> only option in the packet.

That's my gut feeling as well. But I don't have any hard evidence that
that is actually correct. However, since we learned that router-alert is
an actual problem it is also a good incremental step.

>
> bluhm
>

-- 
I'm not entirely sure you are real.



Re: pf igmp icmp6 multicast router alert

2022-04-21 Thread Alexander Bluhm
On Thu, Apr 21, 2022 at 08:56:07PM +0200, Otto Moerbeek wrote:
> > Currently it allows all options.  Should I make it specific to
> > router alert with IGMP or ICMP6?
> 
> To me it looks like the icmp6 case already is limited to MLD?

The question is the other way around.  My current diff allows any
option with ICMP6 MLD.  Do we want to restict the option to router
alert?

In our ip6.h we have:
#define IP6OPT_JUMBO0xC2/* 11 0 00010 = 194 */
#define IP6OPT_NSAP_ADDR0xC3/* 11 0 00011 */
#define IP6OPT_TUNNEL_LIMIT 0x04/* 00 0 00100 */
#define IP6OPT_ROUTER_ALERT 0x05/* 00 0 00101 (RFC3542, recommended) */

And who knows what other options have been designed.

In ip.h I see these:
#define IPOPT_RR7   /* record packet route */
#define IPOPT_TS68  /* timestamp */
#define IPOPT_SECURITY  130 /* provide s,c,h,tcc */
#define IPOPT_LSRR  131 /* loose source route */
#define IPOPT_SATID 136 /* satnet id */
#define IPOPT_SSRR  137 /* strict source route */
#define IPOPT_RA148 /* router alert */

The option I have ever seen in the wild is router alert.  So it may
be better to allow IGMP and ICMP6 multicast if router alert is the
only option in the packet.

bluhm



Re: pf igmp icmp6 multicast router alert

2022-04-21 Thread Otto Moerbeek
On Thu, Apr 21, 2022 at 07:08:38PM +0200, Alexander Bluhm wrote:

> Hi,
> 
> IGMP and ICMP6 for multicast packets have router alert options.
> Per default pf drops all IP packets with options.  Usually people
> ask what is wrong until someone points out that they have to use a
> pf rule with allow-opts.
> 
> As this is normal behavior and our kernel generates such packets,
> the pf default is bad.
> 
> Diff is untested, but otto@ and florian@ could try it.

Tested this with success on two hosts that hasd issues because their
outgoing icmp6 messages were blcoked. 

> Currently it allows all options.  Should I make it specific to
> router alert with IGMP or ICMP6?

To me it looks like the icmp6 case already is limited to MLD?

-Otto

> 
> bluhm
> 
> Index: net/pf.c
> ===
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
> retrieving revision 1.1126
> diff -u -p -r1.1126 pf.c
> --- net/pf.c  17 Mar 2022 18:27:55 -  1.1126
> +++ net/pf.c  21 Apr 2022 16:30:18 -
> @@ -6398,6 +6398,9 @@ pf_walk_header(struct pf_pdesc *pd, stru
>   end = pd->off + ntohs(h->ip_len);
>   pd->off += hlen;
>   pd->proto = h->ip_p;
> + /* IGMP packets have router alert options, allow them */
> + if (pd->proto == IPPROTO_IGMP)
> + pd->badopts = 0;
>   /* stop walking over non initial fragments */
>   if ((h->ip_off & htons(IP_OFFMASK)) != 0)
>   return (PF_PASS);
> @@ -6494,6 +6497,7 @@ pf_walk_header6(struct pf_pdesc *pd, str
>  {
>   struct ip6_frag  frag;
>   struct ip6_ext   ext;
> + struct icmp6_hdr icmp6;
>   struct ip6_rthdr rthdr;
>   u_int32_tend;
>   int  hdr_cnt, fraghdr_cnt = 0, rthdr_cnt = 0;
> @@ -6607,9 +6611,23 @@ pf_walk_header6(struct pf_pdesc *pd, str
>   pd->off += (ext.ip6e_len + 1) * 8;
>   pd->proto = ext.ip6e_nxt;
>   break;
> + case IPPROTO_ICMPV6:
> + if (!pf_pull_hdr(pd->m, pd->off, , sizeof(icmp6),
> + NULL, reason, AF_INET6)) {
> + DPFPRINTF(LOG_NOTICE, "IPv6 short icmp6hdr");
> + return (PF_DROP);
> + }
> + /* ICMP multicast packets have router alert options */
> + switch (icmp6.icmp6_type) {
> + case MLD_LISTENER_QUERY:
> + case MLD_LISTENER_REPORT:
> + case MLD_LISTENER_DONE:
> + pd->badopts = 0;
> + break;
> + }
> + /* FALLTHROUGH */
>   case IPPROTO_TCP:
>   case IPPROTO_UDP:
> - case IPPROTO_ICMPV6:
>   /* fragments may be short, ignore inner header then */
>   if (pd->fragoff != 0 && end < pd->off +
>   (pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) :
> 



Re: obscure vi crash, fix

2022-04-21 Thread Theo Buehler
On Thu, Apr 21, 2022 at 11:07:50AM -0600, Todd C. Miller wrote:
> On Thu, 21 Apr 2022 09:35:44 -0700, Jeremy Mates wrote:
> 
> > The cause is an unguarded use of the NULL output pointer. I am pretty
> > sure an .exrc cannot cause this condition (map rhs requires
> > something, not nothing) only recompiling with a NULL output string
> > for some command.
> >
> > One fix is to guard the "init_nomap = !e_memcmp(qp->output," line in
> > common/key.c with something like
> >
> >   if (qp->output)
> > init_nomap = !e_memcmp(qp->output, >i_event[gp->i_next], qp->ilen);
> 
> That seems reasonable to me since the other users of qp->output do
> check for NULL.  We don't need to worry about init_nomap being unset
> due to the "goto retry" that happens a few lines down.

This makes sense.  As QREM() modifies gp->inext, we can't simply move
this assignment down.

ok tb



pf igmp icmp6 multicast router alert

2022-04-21 Thread Alexander Bluhm
Hi,

IGMP and ICMP6 for multicast packets have router alert options.
Per default pf drops all IP packets with options.  Usually people
ask what is wrong until someone points out that they have to use a
pf rule with allow-opts.

As this is normal behavior and our kernel generates such packets,
the pf default is bad.

Diff is untested, but otto@ and florian@ could try it.

Currently it allows all options.  Should I make it specific to
router alert with IGMP or ICMP6?

bluhm

Index: net/pf.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1126
diff -u -p -r1.1126 pf.c
--- net/pf.c17 Mar 2022 18:27:55 -  1.1126
+++ net/pf.c21 Apr 2022 16:30:18 -
@@ -6398,6 +6398,9 @@ pf_walk_header(struct pf_pdesc *pd, stru
end = pd->off + ntohs(h->ip_len);
pd->off += hlen;
pd->proto = h->ip_p;
+   /* IGMP packets have router alert options, allow them */
+   if (pd->proto == IPPROTO_IGMP)
+   pd->badopts = 0;
/* stop walking over non initial fragments */
if ((h->ip_off & htons(IP_OFFMASK)) != 0)
return (PF_PASS);
@@ -6494,6 +6497,7 @@ pf_walk_header6(struct pf_pdesc *pd, str
 {
struct ip6_frag  frag;
struct ip6_ext   ext;
+   struct icmp6_hdr icmp6;
struct ip6_rthdr rthdr;
u_int32_tend;
int  hdr_cnt, fraghdr_cnt = 0, rthdr_cnt = 0;
@@ -6607,9 +6611,23 @@ pf_walk_header6(struct pf_pdesc *pd, str
pd->off += (ext.ip6e_len + 1) * 8;
pd->proto = ext.ip6e_nxt;
break;
+   case IPPROTO_ICMPV6:
+   if (!pf_pull_hdr(pd->m, pd->off, , sizeof(icmp6),
+   NULL, reason, AF_INET6)) {
+   DPFPRINTF(LOG_NOTICE, "IPv6 short icmp6hdr");
+   return (PF_DROP);
+   }
+   /* ICMP multicast packets have router alert options */
+   switch (icmp6.icmp6_type) {
+   case MLD_LISTENER_QUERY:
+   case MLD_LISTENER_REPORT:
+   case MLD_LISTENER_DONE:
+   pd->badopts = 0;
+   break;
+   }
+   /* FALLTHROUGH */
case IPPROTO_TCP:
case IPPROTO_UDP:
-   case IPPROTO_ICMPV6:
/* fragments may be short, ignore inner header then */
if (pd->fragoff != 0 && end < pd->off +
(pd->proto == IPPROTO_TCP ? sizeof(struct tcphdr) :



Re: obscure vi crash, fix

2022-04-21 Thread Todd C . Miller
On Thu, 21 Apr 2022 09:35:44 -0700, Jeremy Mates wrote:

> The cause is an unguarded use of the NULL output pointer. I am pretty
> sure an .exrc cannot cause this condition (map rhs requires
> something, not nothing) only recompiling with a NULL output string
> for some command.
>
> One fix is to guard the "init_nomap = !e_memcmp(qp->output," line in
> common/key.c with something like
>
>   if (qp->output)
> init_nomap = !e_memcmp(qp->output, >i_event[gp->i_next], qp->ilen);

That seems reasonable to me since the other users of qp->output do
check for NULL.  We don't need to worry about init_nomap being unset
due to the "goto retry" that happens a few lines down.

 - todd

Index: usr.bin/vi/common/key.c
===
RCS file: /cvs/src/usr.bin/vi/common/key.c,v
retrieving revision 1.19
diff -u -p -u -r1.19 key.c
--- usr.bin/vi/common/key.c 18 Apr 2017 01:45:35 -  1.19
+++ usr.bin/vi/common/key.c 21 Apr 2022 17:03:26 -
@@ -650,7 +650,10 @@ not_digit: argp->e_c = CH_NOT_DIGIT;
}
 
/* Find out if the initial segments are identical. */
-   init_nomap = !e_memcmp(qp->output, >i_event[gp->i_next], qp->ilen);
+   if (qp->output != NULL) {
+   init_nomap =
+   !e_memcmp(qp->output, >i_event[gp->i_next], qp->ilen);
+   }
 
/* Delete the mapped characters from the queue. */
QREM(qp->ilen);



obscure vi crash, fix

2022-04-21 Thread Jeremy Mates
One may wish to disable the arrow keys in vi(1), because it is cold and
the jacket will sometimes brush up against said keys, causing unexpected
cursor motions. This may be done by modifying cl/cl_term.c to set
"kcud1" and friends to use NULL for the output string, plus some obvious
tkp->output string length changes just below that. This is according to
the seq_set() comment:

  * An input string must always be present.  The output string
  * can be NULL, when set internally, that's how we throw away
  * input.

However, after recompiling, vi crashes when the arrow keys are pressed.

The cause is an unguarded use of the NULL output pointer. I am pretty
sure an .exrc cannot cause this condition (map rhs requires
something, not nothing) only recompiling with a NULL output string
for some command.

One fix is to guard the "init_nomap = !e_memcmp(qp->output," line in
common/key.c with something like

  if (qp->output)
init_nomap = !e_memcmp(qp->output, >i_event[gp->i_next], qp->ilen);



Re: router timer mutex

2022-04-21 Thread Alexander Bluhm
On Wed, Apr 20, 2022 at 08:12:51PM +0200, Alexander Bluhm wrote:
> mvs@ reminded me of a crash I have seen in December.  Route timers
> are not MP safe, but I think this can be fixed with a mutex.  The
> idea is to protect the global lists with a mutex and move the rttimer
> into a temporary list.  Then the callback and pool put can be called
> later without mutex.

I have a tiny update to the diff.

- Global locks are documented with capital letter, so use [T].

- rt_timer_add() grabbed the mutex twice, first remove then add.
  Better exchange in one critical section.  pool_get before and
  pool_put after.

ok?

Index: net/route.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/net/route.c,v
retrieving revision 1.406
diff -u -p -r1.406 route.c
--- net/route.c 20 Apr 2022 17:58:22 -  1.406
+++ net/route.c 21 Apr 2022 13:31:52 -
@@ -1361,7 +1361,8 @@ rt_ifa_purge_walker(struct rtentry *rt, 
  * for multiple queues for efficiency's sake...
  */
 
-LIST_HEAD(, rttimer_queue) rttimer_queue_head;
+struct mutex   rttimer_mtx;
+LIST_HEAD(, rttimer_queue) rttimer_queue_head; /* [T] */
 
 #define RTTIMER_CALLOUT(r) {   \
if (r->rtt_func != NULL) {  \
@@ -1393,6 +1394,7 @@ rt_timer_init(void)
pool_init(_queue_pool, sizeof(struct rttimer_queue), 0,
IPL_MPFLOOR, 0, "rttmrq", NULL);
 
+   mtx_init(_mtx, IPL_MPFLOOR);
LIST_INIT(_queue_head);
timeout_set_proc(_timer_timeout, rt_timer_timer, _timer_timeout);
timeout_add_sec(_timer_timeout, 1);
@@ -1408,7 +1410,10 @@ rt_timer_queue_create(int timeout)
rtq->rtq_timeout = timeout;
rtq->rtq_count = 0;
TAILQ_INIT(>rtq_head);
+
+   mtx_enter(_mtx);
LIST_INSERT_HEAD(_queue_head, rtq, rtq_link);
+   mtx_leave(_mtx);
 
return (rtq);
 }
@@ -1416,28 +1421,36 @@ rt_timer_queue_create(int timeout)
 void
 rt_timer_queue_change(struct rttimer_queue *rtq, int timeout)
 {
+   mtx_enter(_mtx);
rtq->rtq_timeout = timeout;
+   mtx_leave(_mtx);
 }
 
 void
 rt_timer_queue_destroy(struct rttimer_queue *rtq)
 {
-   struct rttimer  *r;
+   struct rttimer  *r;
+   TAILQ_HEAD(, rttimer)rttlist;
 
NET_ASSERT_LOCKED();
 
+   TAILQ_INIT();
+   mtx_enter(_mtx);
while ((r = TAILQ_FIRST(>rtq_head)) != NULL) {
LIST_REMOVE(r, rtt_link);
TAILQ_REMOVE(>rtq_head, r, rtt_next);
+   TAILQ_INSERT_TAIL(, r, rtt_next);
+   KASSERT(rtq->rtq_count > 0);
+   rtq->rtq_count--;
+   }
+   LIST_REMOVE(rtq, rtq_link);
+   mtx_leave(_mtx);
+
+   while ((r = TAILQ_FIRST()) != NULL) {
+   TAILQ_REMOVE(, r, rtt_next);
RTTIMER_CALLOUT(r);
pool_put(_pool, r);
-   if (rtq->rtq_count > 0)
-   rtq->rtq_count--;
-   else
-   printf("rt_timer_queue_destroy: rtq_count reached 0\n");
}
-
-   LIST_REMOVE(rtq, rtq_link);
pool_put(_queue_pool, rtq);
 }
 
@@ -1450,15 +1463,22 @@ rt_timer_queue_count(struct rttimer_queu
 void
 rt_timer_remove_all(struct rtentry *rt)
 {
-   struct rttimer  *r;
+   struct rttimer  *r;
+   TAILQ_HEAD(, rttimer)rttlist;
 
+   TAILQ_INIT();
+   mtx_enter(_mtx);
while ((r = LIST_FIRST(>rt_timer)) != NULL) {
LIST_REMOVE(r, rtt_link);
TAILQ_REMOVE(>rtt_queue->rtq_head, r, rtt_next);
-   if (r->rtt_queue->rtq_count > 0)
-   r->rtt_queue->rtq_count--;
-   else
-   printf("rt_timer_remove_all: rtq_count reached 0\n");
+   TAILQ_INSERT_TAIL(, r, rtt_next);
+   KASSERT(r->rtt_queue->rtq_count > 0);
+   r->rtt_queue->rtq_count--;
+   }
+   mtx_leave(_mtx);
+
+   while ((r = TAILQ_FIRST()) != NULL) {
+   TAILQ_REMOVE(, r, rtt_next);
pool_put(_pool, r);
}
 }
@@ -1467,12 +1487,23 @@ int
 rt_timer_add(struct rtentry *rt, void (*func)(struct rtentry *,
 struct rttimer *), struct rttimer_queue *queue, u_int rtableid)
 {
-   struct rttimer  *r;
+   struct rttimer  *r, *rnew;
time_t   current_time;
 
+   rnew = pool_get(_pool, PR_NOWAIT | PR_ZERO);
+   if (rnew == NULL)
+   return (ENOBUFS);
+
current_time = getuptime();
-   rt->rt_expire = current_time + queue->rtq_timeout;
 
+   rnew->rtt_rt = rt;
+   rnew->rtt_time = current_time;
+   rnew->rtt_func = func;
+   rnew->rtt_queue = queue;
+   rnew->rtt_tableid = rtableid;
+
+   mtx_enter(_mtx);
+   rt->rt_expire = current_time + queue->rtq_timeout;
/*
 * If there's already a timer with this action, destroy it 

Re: [External] : parallel IP forwarding

2022-04-21 Thread Alexandr Nedvedicky
On Fri, Apr 08, 2022 at 12:56:12PM +0200, Alexander Bluhm wrote:
> Hi,
> 
> I now the right time to commit the parallel forwarding diff?
> 
> Known limitiations are:
> - Hrvoje has seen a crash with both pfsync and ipsec on his production
>   machine.  But he cannot reproduce it in his lab.
> - TCP processing gets slower as we have an additional queue between
>   IP and protocol layer.
> - Protocol layer may starve as 1 exclusive lock is fightig with 4
>   shared locks.  This happens only when forwardig a lot.
> 
> The advantage of commiting is that we see how relevant these things
> are in real world.  But the most important thing is that we learn
> how all the locks behave under MP pressure.  You can add a lot of
> locking, but only when you run in parallel, you see if it is correct.
> 
> An alternative could be to commit it with NET_TASKQ 1.  With only
> one softnet thread I would expect to see less bugs, but there is
> also less to learn.  NET_TASKQ 1 could be a safe point where we
> could easily switch back.
> 
> bluhm
> 

I think it's worth to give it a try. May be I would just split
it to three commits/diffs:

diff which adds task queues for forwarding

diff which adds a KERNEL_LOCK to deal with arp

diff which deals with local delivery to socket

it's up to you. all changes look good to me. You have my OK,
in case you want to proceed in one big step.

OK sashan



Re: router timer kernel lock

2022-04-21 Thread Claudio Jeker
On Thu, Apr 21, 2022 at 03:25:03PM +0200, Alexander Bluhm wrote:
> Hi,
> 
> As claudio@ wants to refactor router timer before making them MP
> safe, I would like to protect them with kernel lock.  It should fix
> this panic.
> 
> https://marc.info/?l=openbsd-tech=164038527425440=2
> 
> I hope this is the final step before running IP forwarding in
> parallel.
> 
> ok?

I prefer the other diff, I don't like that other diff but this one is worse.
 
> bluhm
> 
> Index: netinet/ip_icmp.c
> ===
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_icmp.c,v
> retrieving revision 1.188
> diff -u -p -r1.188 ip_icmp.c
> --- netinet/ip_icmp.c 20 Apr 2022 09:38:26 -  1.188
> +++ netinet/ip_icmp.c 21 Apr 2022 12:45:40 -
> @@ -634,8 +634,10 @@ reflect:
>   rtredirect(sintosa(), sintosa(),
>   sintosa(), , m->m_pkthdr.ph_rtableid);
>   if (newrt != NULL && icmp_redirtimeout > 0) {
> + KERNEL_LOCK();
>   rt_timer_add(newrt, icmp_redirect_timeout,
>   icmp_redirect_timeout_q, m->m_pkthdr.ph_rtableid);
> + KERNEL_UNLOCK();
>   }
>   rtfree(newrt);
>   pfctlinput(PRC_REDIRECT_HOST, sintosa());
> @@ -884,8 +886,10 @@ icmp_sysctl(int *name, u_int namelen, vo
>   NET_LOCK();
>   error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
>   _redirtimeout, 0, INT_MAX);
> + KERNEL_LOCK();
>   rt_timer_queue_change(icmp_redirect_timeout_q,
>   icmp_redirtimeout);
> + KERNEL_UNLOCK();
>   NET_UNLOCK();
>   break;
>  
> @@ -975,8 +979,10 @@ icmp_mtudisc_clone(struct in_addr dst, u
>   rt = nrt;
>   rtm_send(rt, RTM_ADD, 0, rtableid);
>   }
> + KERNEL_LOCK();
>   error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q,
>   rtableid);
> + KERNEL_UNLOCK();
>   if (error)
>   goto bad;
>  
> Index: netinet/ip_input.c
> ===
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.367
> diff -u -p -r1.367 ip_input.c
> --- netinet/ip_input.c20 Apr 2022 09:38:26 -  1.367
> +++ netinet/ip_input.c21 Apr 2022 13:00:33 -
> @@ -1616,9 +1616,11 @@ ip_sysctl(int *name, u_int namelen, void
>   NET_LOCK();
>   error = sysctl_int(oldp, oldlenp, newp, newlen, _mtudisc);
>   if (ip_mtudisc == 0) {
> + KERNEL_LOCK();
>   rt_timer_queue_destroy(ip_mtudisc_timeout_q);
>   ip_mtudisc_timeout_q =
>   rt_timer_queue_create(ip_mtudisc_timeout);
> + KERNEL_UNLOCK();
>   }
>   NET_UNLOCK();
>   return error;
> @@ -1626,8 +1628,10 @@ ip_sysctl(int *name, u_int namelen, void
>   NET_LOCK();
>   error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
>   _mtudisc_timeout, 0, INT_MAX);
> + KERNEL_LOCK();
>   rt_timer_queue_change(ip_mtudisc_timeout_q,
>   ip_mtudisc_timeout);
> + KERNEL_UNLOCK();
>   NET_UNLOCK();
>   return (error);
>  #ifdef IPSEC
> Index: netinet/ip_mroute.c
> ===
> RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_mroute.c,v
> retrieving revision 1.131
> diff -u -p -r1.131 ip_mroute.c
> --- netinet/ip_mroute.c   15 Dec 2021 17:21:08 -  1.131
> +++ netinet/ip_mroute.c   21 Apr 2022 13:02:43 -
> @@ -520,7 +520,9 @@ ip_mrouter_init(struct socket *so, struc
>   return (EADDRINUSE);
>  
>   ip_mrouter[rtableid] = so;
> + KERNEL_LOCK();
>   mrouterq[rtableid] = rt_timer_queue_create(MCAST_EXPIRE_FREQUENCY);
> + KERNEL_UNLOCK();
>  
>   return (0);
>  }
> @@ -572,7 +574,9 @@ ip_mrouter_done(struct socket *so)
>  
>   mrt_api_config = 0;
>  
> + KERNEL_LOCK();
>   rt_timer_queue_destroy(mrouterq[rtableid]);
> + KERNEL_UNLOCK();
>   mrouterq[rtableid] = NULL;
>   ip_mrouter[rtableid] = NULL;
>   mrt_count[rtableid] = 0;
> @@ -799,8 +803,10 @@ mfc_expire_route(struct rtentry *rt, str
>   /* Not expired, add it back to the queue. */
>   if (mfc->mfc_expire == 0) {
>   mfc->mfc_expire = 1;
> + KERNEL_LOCK();
>   rt_timer_add(rt, mfc_expire_route, mrouterq[rtableid],
>   rtableid);
> + KERNEL_UNLOCK();
>   return;
>   }
>  
> @@ -834,8 +840,10 @@ mfc_add_route(struct ifnet *ifp, struct 
>  
>   rt->rt_llinfo = (caddr_t)mfc;
>  
> + KERNEL_LOCK();
>   rt_timer_add(rt, mfc_expire_route, 

router timer kernel lock

2022-04-21 Thread Alexander Bluhm
Hi,

As claudio@ wants to refactor router timer before making them MP
safe, I would like to protect them with kernel lock.  It should fix
this panic.

https://marc.info/?l=openbsd-tech=164038527425440=2

I hope this is the final step before running IP forwarding in
parallel.

ok?

bluhm

Index: netinet/ip_icmp.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.188
diff -u -p -r1.188 ip_icmp.c
--- netinet/ip_icmp.c   20 Apr 2022 09:38:26 -  1.188
+++ netinet/ip_icmp.c   21 Apr 2022 12:45:40 -
@@ -634,8 +634,10 @@ reflect:
rtredirect(sintosa(), sintosa(),
sintosa(), , m->m_pkthdr.ph_rtableid);
if (newrt != NULL && icmp_redirtimeout > 0) {
+   KERNEL_LOCK();
rt_timer_add(newrt, icmp_redirect_timeout,
icmp_redirect_timeout_q, m->m_pkthdr.ph_rtableid);
+   KERNEL_UNLOCK();
}
rtfree(newrt);
pfctlinput(PRC_REDIRECT_HOST, sintosa());
@@ -884,8 +886,10 @@ icmp_sysctl(int *name, u_int namelen, vo
NET_LOCK();
error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
_redirtimeout, 0, INT_MAX);
+   KERNEL_LOCK();
rt_timer_queue_change(icmp_redirect_timeout_q,
icmp_redirtimeout);
+   KERNEL_UNLOCK();
NET_UNLOCK();
break;
 
@@ -975,8 +979,10 @@ icmp_mtudisc_clone(struct in_addr dst, u
rt = nrt;
rtm_send(rt, RTM_ADD, 0, rtableid);
}
+   KERNEL_LOCK();
error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q,
rtableid);
+   KERNEL_UNLOCK();
if (error)
goto bad;
 
Index: netinet/ip_input.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.367
diff -u -p -r1.367 ip_input.c
--- netinet/ip_input.c  20 Apr 2022 09:38:26 -  1.367
+++ netinet/ip_input.c  21 Apr 2022 13:00:33 -
@@ -1616,9 +1616,11 @@ ip_sysctl(int *name, u_int namelen, void
NET_LOCK();
error = sysctl_int(oldp, oldlenp, newp, newlen, _mtudisc);
if (ip_mtudisc == 0) {
+   KERNEL_LOCK();
rt_timer_queue_destroy(ip_mtudisc_timeout_q);
ip_mtudisc_timeout_q =
rt_timer_queue_create(ip_mtudisc_timeout);
+   KERNEL_UNLOCK();
}
NET_UNLOCK();
return error;
@@ -1626,8 +1628,10 @@ ip_sysctl(int *name, u_int namelen, void
NET_LOCK();
error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
_mtudisc_timeout, 0, INT_MAX);
+   KERNEL_LOCK();
rt_timer_queue_change(ip_mtudisc_timeout_q,
ip_mtudisc_timeout);
+   KERNEL_UNLOCK();
NET_UNLOCK();
return (error);
 #ifdef IPSEC
Index: netinet/ip_mroute.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.131
diff -u -p -r1.131 ip_mroute.c
--- netinet/ip_mroute.c 15 Dec 2021 17:21:08 -  1.131
+++ netinet/ip_mroute.c 21 Apr 2022 13:02:43 -
@@ -520,7 +520,9 @@ ip_mrouter_init(struct socket *so, struc
return (EADDRINUSE);
 
ip_mrouter[rtableid] = so;
+   KERNEL_LOCK();
mrouterq[rtableid] = rt_timer_queue_create(MCAST_EXPIRE_FREQUENCY);
+   KERNEL_UNLOCK();
 
return (0);
 }
@@ -572,7 +574,9 @@ ip_mrouter_done(struct socket *so)
 
mrt_api_config = 0;
 
+   KERNEL_LOCK();
rt_timer_queue_destroy(mrouterq[rtableid]);
+   KERNEL_UNLOCK();
mrouterq[rtableid] = NULL;
ip_mrouter[rtableid] = NULL;
mrt_count[rtableid] = 0;
@@ -799,8 +803,10 @@ mfc_expire_route(struct rtentry *rt, str
/* Not expired, add it back to the queue. */
if (mfc->mfc_expire == 0) {
mfc->mfc_expire = 1;
+   KERNEL_LOCK();
rt_timer_add(rt, mfc_expire_route, mrouterq[rtableid],
rtableid);
+   KERNEL_UNLOCK();
return;
}
 
@@ -834,8 +840,10 @@ mfc_add_route(struct ifnet *ifp, struct 
 
rt->rt_llinfo = (caddr_t)mfc;
 
+   KERNEL_LOCK();
rt_timer_add(rt, mfc_expire_route, mrouterq[rtableid],
rtableid);
+   KERNEL_UNLOCK();
 
mfc->mfc_parent = mfccp->mfcc_parent;
mfc->mfc_pkt_cnt = 0;
@@ -1342,7 +1350,9 @@ mrt_mcast_del(struct rtentry *rt, unsign
int  error;
 
/* Remove all 

Re: [External] : Re: pfsync(4) snapshot lists must have dedicated link element

2022-04-21 Thread Alexandr Nedvedicky
Hello,

On Thu, Apr 21, 2022 at 02:42:45PM +0200, Alexander Bluhm wrote:
> On Wed, Apr 20, 2022 at 11:22:27PM +0200, Alexandr Nedvedicky wrote:
> > updated diff is below
> 
> OK bluhm@
> 
> You have to merge again, as I removed #ifdef PFSYNC_DEBUG and added
> a #ifdef DIAGNOSTIC.  Sorry.
> 

thanks for reminder. will merge and commit.

regards
sashan



Re: [External] : Re: pfsync(4) snapshot lists must have dedicated link element

2022-04-21 Thread Alexander Bluhm
On Wed, Apr 20, 2022 at 11:22:27PM +0200, Alexandr Nedvedicky wrote:
> updated diff is below

OK bluhm@

You have to merge again, as I removed #ifdef PFSYNC_DEBUG and added
a #ifdef DIAGNOSTIC.  Sorry.

> 8<---8<---8<--8<
> diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c
> index fc6843b541f..3061318cec9 100644
> --- a/sys/net/if_pfsync.c
> +++ b/sys/net/if_pfsync.c
> @@ -181,6 +181,7 @@ void  pfsync_q_del(struct pf_state *);
>  
>  struct pfsync_upd_req_item {
>   TAILQ_ENTRY(pfsync_upd_req_item)ur_entry;
> + TAILQ_ENTRY(pfsync_upd_req_item)ur_snap;
>   struct pfsync_upd_req   ur_msg;
>  };
>  TAILQ_HEAD(pfsync_upd_reqs, pfsync_upd_req_item);
> @@ -295,7 +296,7 @@ void  pfsync_bulk_update(void *);
>  void pfsync_bulk_fail(void *);
>  
>  void pfsync_grab_snapshot(struct pfsync_snapshot *, struct pfsync_softc *);
> -void pfsync_drop_snapshot(struct pfsync_snapshot *, struct pfsync_softc *);
> +void pfsync_drop_snapshot(struct pfsync_snapshot *);
>  
>  void pfsync_send_dispatch(void *);
>  void pfsync_send_pkt(struct mbuf *);
> @@ -422,8 +423,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
>   sc->sc_deferred = 0;
>   mtx_leave(>sc_deferrals_mtx);
>  
> - while (!TAILQ_EMPTY()) {
> - pd = TAILQ_FIRST();
> + while ((pd = TAILQ_FIRST()) != NULL) {
>   TAILQ_REMOVE(, pd, pd_entry);
>   pfsync_undefer(pd, 0);
>   }
> @@ -1574,6 +1574,9 @@ void
>  pfsync_grab_snapshot(struct pfsync_snapshot *sn, struct pfsync_softc *sc)
>  {
>   int q;
> + struct pf_state *st;
> + struct pfsync_upd_req_item *ur;
> + struct tdb *tdb;
>  
>   sn->sn_sc = sc;
>  
> @@ -1583,14 +1586,31 @@ pfsync_grab_snapshot(struct pfsync_snapshot *sn, 
> struct pfsync_softc *sc)
>  
>   for (q = 0; q < PFSYNC_S_COUNT; q++) {
>   TAILQ_INIT(>sn_qs[q]);
> - TAILQ_CONCAT(>sn_qs[q], >sc_qs[q], sync_list);
> +
> + while ((st = TAILQ_FIRST(>sc_qs[q])) != NULL) {
> + KASSERT(st->snapped == 0);
> + TAILQ_REMOVE(>sc_qs[q], st, sync_list);
> + TAILQ_INSERT_TAIL(>sn_qs[q], st, sync_snap);
> + st->snapped = 1;
> + }
>   }
>  
>   TAILQ_INIT(>sn_upd_req_list);
> - TAILQ_CONCAT(>sn_upd_req_list, >sc_upd_req_list, ur_entry);
> + while ((ur = TAILQ_FIRST(>sc_upd_req_list)) != NULL) {
> + TAILQ_REMOVE(>sc_upd_req_list, ur, ur_entry);
> + TAILQ_INSERT_TAIL(>sn_upd_req_list, ur, ur_snap);
> + }
>  
>   TAILQ_INIT(>sn_tdb_q);
> - TAILQ_CONCAT(>sn_tdb_q, >sc_tdb_q, tdb_sync_entry);
> + while ((tdb = TAILQ_FIRST(>sc_tdb_q)) != NULL) {
> + TAILQ_REMOVE(>sc_tdb_q, tdb, tdb_sync_entry);
> + TAILQ_INSERT_TAIL(>sn_tdb_q, tdb, tdb_sync_snap);
> +
> + mtx_enter(>tdb_mtx);
> + KASSERT(!ISSET(tdb->tdb_flags, TDBF_PFSYNC_SNAPPED));
> + SET(tdb->tdb_flags, TDBF_PFSYNC_SNAPPED);
> + mtx_leave(>tdb_mtx);
> + }
>  
>   sn->sn_len = sc->sc_len;
>   sc->sc_len = PFSYNC_MINPKT;
> @@ -1606,41 +1626,40 @@ pfsync_grab_snapshot(struct pfsync_snapshot *sn, 
> struct pfsync_softc *sc)
>  }
>  
>  void
> -pfsync_drop_snapshot(struct pfsync_snapshot *sn, struct pfsync_softc * sc)
> +pfsync_drop_snapshot(struct pfsync_snapshot *sn)
>  {
>   struct pf_state *st;
>   struct pfsync_upd_req_item *ur;
>   struct tdb *t;
>   int q;
>  
> -
>   for (q = 0; q < PFSYNC_S_COUNT; q++) {
>   if (TAILQ_EMPTY(>sn_qs[q]))
>   continue;
>  
>   while ((st = TAILQ_FIRST(>sn_qs[q])) != NULL) {
> - TAILQ_REMOVE(>sn_qs[q], st, sync_list);
> -#ifdef PFSYNC_DEBUG
>   KASSERT(st->sync_state == q);
> -#endif
> + KASSERT(st->snapped == 1);
> + TAILQ_REMOVE(>sn_qs[q], st, sync_snap);
>   st->sync_state = PFSYNC_S_NONE;
> + st->snapped = 0;
>   pf_state_unref(st);
>   }
>   }
>  
>   while ((ur = TAILQ_FIRST(>sn_upd_req_list)) != NULL) {
> - TAILQ_REMOVE(>sn_upd_req_list, ur, ur_entry);
> + TAILQ_REMOVE(>sn_upd_req_list, ur, ur_snap);
>   pool_put(>sn_sc->sc_pool, ur);
>   }
>  
> - mtx_enter(>sc_tdb_mtx);
>   while ((t = TAILQ_FIRST(>sn_tdb_q)) != NULL) {
> - TAILQ_REMOVE(>sn_tdb_q, t, tdb_sync_entry);
> + TAILQ_REMOVE(>sn_tdb_q, t, tdb_sync_snap);
>   mtx_enter(>tdb_mtx);
> + KASSERT(ISSET(t->tdb_flags, TDBF_PFSYNC_SNAPPED));
> + CLR(t->tdb_flags, TDBF_PFSYNC_SNAPPED);
>   CLR(t->tdb_flags, TDBF_PFSYNC);
>   mtx_leave(>tdb_mtx);
>   }
> - 

Re: rpki-client more refactoring

2022-04-21 Thread Theo Buehler
On Thu, Apr 21, 2022 at 02:15:14PM +0200, Claudio Jeker wrote:
> On Thu, Apr 21, 2022 at 02:08:01PM +0200, Theo Buehler wrote:
> > On Thu, Apr 21, 2022 at 01:14:31PM +0200, Claudio Jeker wrote:
> > > So here is the cleanup of filemode.c and also a bit of cleanup in parse.c
> > > This should also fix a few bugs in parse_load_certchain() (mainly
> > > memleaks).
> > 
> > A couple of suggestions for parse_load_certchain() below.
> > 
> 
> Always good to have extra eyes on such changes. Here updated diff with
> your suggested changes.

Sure.

>   /* TA found play back the stack and add all certs */
> - for (failed = 0; i >= 0; i--) {
> + for (; i >= 0; i--) {
>   cert = stack[i];
>   uri = filestack[i];
>  
> - if (failed)
> - cert_free(cert);
> - else if (proc_parser_cert_validate(uri, cert) == NULL)
> - failed = 1;
> + crl = crl_get(, a);
> + if (!valid_x509(uri, ctx, cert->x509, a, crl, 0) || 
> + !valid_cert(uri, a, cert))
> + goto fail;
> + cert->talid = a->cert->talid;
> + a = auth_insert(, cert, a);
> + stack[i] = NULL;
>   }

I'd add a

return;

Then it's ok.

> +
> +fail:
> + for (i = 0; i < MAX_CERT_DEPTH; i++)
> + cert_free(stack[i]);
>  }



Re: rpki-client more refactoring

2022-04-21 Thread Claudio Jeker
On Thu, Apr 21, 2022 at 02:08:01PM +0200, Theo Buehler wrote:
> On Thu, Apr 21, 2022 at 01:14:31PM +0200, Claudio Jeker wrote:
> > So here is the cleanup of filemode.c and also a bit of cleanup in parse.c
> > This should also fix a few bugs in parse_load_certchain() (mainly
> > memleaks).
> 
> A couple of suggestions for parse_load_certchain() below.
> 

Always good to have extra eyes on such changes. Here updated diff with
your suggested changes.

-- 
:wq Claudio

Index: cert.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.70
diff -u -p -r1.70 cert.c
--- cert.c  21 Apr 2022 09:53:07 -  1.70
+++ cert.c  21 Apr 2022 10:45:17 -
@@ -999,6 +999,9 @@ out:
 struct cert *
 cert_parse(const char *fn, struct cert *p)
 {
+   if (p == NULL)
+   return NULL;
+
if (p->aki == NULL) {
warnx("%s: RFC 6487 section 8.4.2: "
"non-trust anchor missing AKI", fn);
@@ -1032,6 +1035,9 @@ ta_parse(const char *fn, struct cert *p,
ASN1_TIME   *notBefore, *notAfter;
EVP_PKEY*pk, *opk;
 
+   if (p == NULL)
+   return NULL;
+
/* first check pubkey against the one from the TAL */
pk = d2i_PUBKEY(NULL, , pkeysz);
if (pk == NULL) {
@@ -1207,7 +1213,7 @@ auth_find(struct auth_tree *auths, const
return RB_FIND(auth_tree, auths, );
 }
 
-void
+struct auth *
 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
 {
struct auth *na;
@@ -1221,6 +1227,8 @@ auth_insert(struct auth_tree *auths, str
 
if (RB_INSERT(auth_tree, auths, na) != NULL)
err(1, "auth tree corrupted");
+
+   return na;
 }
 
 static void
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.131
diff -u -p -r1.131 extern.h
--- extern.h21 Apr 2022 09:53:07 -  1.131
+++ extern.h21 Apr 2022 10:46:09 -
@@ -308,7 +308,7 @@ struct auth {
 RB_HEAD(auth_tree, auth);
 
 struct auth*auth_find(struct auth_tree *, const char *);
-voidauth_insert(struct auth_tree *, struct cert *, struct auth *);
+struct auth*auth_insert(struct auth_tree *, struct cert *, struct auth *);
 
 enum http_result {
HTTP_FAILED,/* anything else */
Index: filemode.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v
retrieving revision 1.1
diff -u -p -r1.1 filemode.c
--- filemode.c  21 Apr 2022 09:53:07 -  1.1
+++ filemode.c  21 Apr 2022 12:12:06 -
@@ -46,80 +46,6 @@ static struct crl_treecrlt = RB_INITIA
 struct tal *talobj[TALSZ_MAX];
 
 /*
- * Validate a certificate, if invalid free the resouces and return NULL.
- */
-static struct cert *
-proc_parser_cert_validate(char *file, struct cert *cert)
-{
-   struct auth *a;
-   struct crl  *crl;
-
-   a = valid_ski_aki(file, , cert->ski, cert->aki);
-   crl = crl_get(, a);
-
-   if (!valid_x509(file, ctx, cert->x509, a, crl, 0)) {
-   cert_free(cert);
-   return NULL;
-   }
-
-   cert->talid = a->cert->talid;
-
-   /* Validate the cert */
-   if (!valid_cert(file, a, cert)) {
-   cert_free(cert);
-   return NULL;
-   }
-
-   /*
-* Add validated CA certs to the RPKI auth tree.
-*/
-   if (cert->purpose == CERT_PURPOSE_CA)
-   auth_insert(, cert, a);
-
-   return cert;
-}
-
-/*
- * Root certificates come from TALs (has a pkey and is self-signed).
- * Parse the certificate, ensure that its public key matches the
- * known public key from the TAL, and then validate the RPKI
- * content.
- *
- * This returns a certificate (which must not be freed) or NULL on
- * parse failure.
- */
-static struct cert *
-proc_parser_root_cert(char *file, const unsigned char *der, size_t len,
-unsigned char *pkey, size_t pkeysz, int talid)
-{
-   struct cert *cert;
-
-   /* Extract certificate data. */
-
-   cert = cert_parse_pre(file, der, len);
-   if (cert == NULL)
-   return NULL;
-   cert = ta_parse(file, cert, pkey, pkeysz);
-   if (cert == NULL)
-   return NULL;
-
-   if (!valid_ta(file, , cert)) {
-   warnx("%s: certificate not a valid ta", file);
-   cert_free(cert);
-   return NULL;
-   }
-
-   cert->talid = talid;
-
-   /*
-* Add valid roots to the RPKI auth tree.
-*/
-   auth_insert(, cert, NULL);
-
-   return cert;
-}
-
-/*
  * Use the X509 CRL Distribution Points to locate the CRL needed for
  * verification.
  */
@@ -207,25 +133,25 @@ parse_load_cert(char *uri)
 static void
 parse_load_certchain(char *uri)
 {
-   struct cert 

Re: rpki-client more refactoring

2022-04-21 Thread Theo Buehler
On Thu, Apr 21, 2022 at 01:14:31PM +0200, Claudio Jeker wrote:
> So here is the cleanup of filemode.c and also a bit of cleanup in parse.c
> This should also fix a few bugs in parse_load_certchain() (mainly
> memleaks).

A couple of suggestions for parse_load_certchain() below.

ok

> 
> -- 
> :wq Claudio
> 
> Index: cert.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.70
> diff -u -p -r1.70 cert.c
> --- cert.c21 Apr 2022 09:53:07 -  1.70
> +++ cert.c21 Apr 2022 10:45:17 -
> @@ -999,6 +999,9 @@ out:
>  struct cert *
>  cert_parse(const char *fn, struct cert *p)
>  {
> + if (p == NULL)
> + return NULL;
> +
>   if (p->aki == NULL) {
>   warnx("%s: RFC 6487 section 8.4.2: "
>   "non-trust anchor missing AKI", fn);
> @@ -1032,6 +1035,9 @@ ta_parse(const char *fn, struct cert *p,
>   ASN1_TIME   *notBefore, *notAfter;
>   EVP_PKEY*pk, *opk;
>  
> + if (p == NULL)
> + return NULL;
> +
>   /* first check pubkey against the one from the TAL */
>   pk = d2i_PUBKEY(NULL, , pkeysz);
>   if (pk == NULL) {
> @@ -1207,7 +1213,7 @@ auth_find(struct auth_tree *auths, const
>   return RB_FIND(auth_tree, auths, );
>  }
>  
> -void
> +struct auth *
>  auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
>  {
>   struct auth *na;
> @@ -1221,6 +1227,8 @@ auth_insert(struct auth_tree *auths, str
>  
>   if (RB_INSERT(auth_tree, auths, na) != NULL)
>   err(1, "auth tree corrupted");
> +
> + return na;
>  }
>  
>  static void
> Index: extern.h
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.131
> diff -u -p -r1.131 extern.h
> --- extern.h  21 Apr 2022 09:53:07 -  1.131
> +++ extern.h  21 Apr 2022 10:46:09 -
> @@ -308,7 +308,7 @@ struct auth {
>  RB_HEAD(auth_tree, auth);
>  
>  struct auth  *auth_find(struct auth_tree *, const char *);
> -void  auth_insert(struct auth_tree *, struct cert *, struct auth *);
> +struct auth  *auth_insert(struct auth_tree *, struct cert *, struct auth *);
>  
>  enum http_result {
>   HTTP_FAILED,/* anything else */
> Index: filemode.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 filemode.c
> --- filemode.c21 Apr 2022 09:53:07 -  1.1
> +++ filemode.c21 Apr 2022 10:47:24 -
> @@ -46,80 +46,6 @@ static struct crl_tree  crlt = RB_INITIA
>  struct tal   *talobj[TALSZ_MAX];
>  
>  /*
> - * Validate a certificate, if invalid free the resouces and return NULL.
> - */
> -static struct cert *
> -proc_parser_cert_validate(char *file, struct cert *cert)
> -{
> - struct auth *a;
> - struct crl  *crl;
> -
> - a = valid_ski_aki(file, , cert->ski, cert->aki);
> - crl = crl_get(, a);
> -
> - if (!valid_x509(file, ctx, cert->x509, a, crl, 0)) {
> - cert_free(cert);
> - return NULL;
> - }
> -
> - cert->talid = a->cert->talid;
> -
> - /* Validate the cert */
> - if (!valid_cert(file, a, cert)) {
> - cert_free(cert);
> - return NULL;
> - }
> -
> - /*
> -  * Add validated CA certs to the RPKI auth tree.
> -  */
> - if (cert->purpose == CERT_PURPOSE_CA)
> - auth_insert(, cert, a);
> -
> - return cert;
> -}
> -
> -/*
> - * Root certificates come from TALs (has a pkey and is self-signed).
> - * Parse the certificate, ensure that its public key matches the
> - * known public key from the TAL, and then validate the RPKI
> - * content.
> - *
> - * This returns a certificate (which must not be freed) or NULL on
> - * parse failure.
> - */
> -static struct cert *
> -proc_parser_root_cert(char *file, const unsigned char *der, size_t len,
> -unsigned char *pkey, size_t pkeysz, int talid)
> -{
> - struct cert *cert;
> -
> - /* Extract certificate data. */
> -
> - cert = cert_parse_pre(file, der, len);
> - if (cert == NULL)
> - return NULL;
> - cert = ta_parse(file, cert, pkey, pkeysz);
> - if (cert == NULL)
> - return NULL;
> -
> - if (!valid_ta(file, , cert)) {
> - warnx("%s: certificate not a valid ta", file);
> - cert_free(cert);
> - return NULL;
> - }
> -
> - cert->talid = talid;
> -
> - /*
> -  * Add valid roots to the RPKI auth tree.
> -  */
> - auth_insert(, cert, NULL);
> -
> - return cert;
> -}
> -
> -/*
>   * Use the X509 CRL Distribution Points to locate the CRL needed for
>   * verification.
>   */
> @@ -207,25 +133,25 @@ parse_load_cert(char *uri)
>  static void
>  parse_load_certchain(char *uri)
>  {
> - struct 

rpki-client more refactoring

2022-04-21 Thread Claudio Jeker
So here is the cleanup of filemode.c and also a bit of cleanup in parse.c
This should also fix a few bugs in parse_load_certchain() (mainly
memleaks).

-- 
:wq Claudio

Index: cert.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.70
diff -u -p -r1.70 cert.c
--- cert.c  21 Apr 2022 09:53:07 -  1.70
+++ cert.c  21 Apr 2022 10:45:17 -
@@ -999,6 +999,9 @@ out:
 struct cert *
 cert_parse(const char *fn, struct cert *p)
 {
+   if (p == NULL)
+   return NULL;
+
if (p->aki == NULL) {
warnx("%s: RFC 6487 section 8.4.2: "
"non-trust anchor missing AKI", fn);
@@ -1032,6 +1035,9 @@ ta_parse(const char *fn, struct cert *p,
ASN1_TIME   *notBefore, *notAfter;
EVP_PKEY*pk, *opk;
 
+   if (p == NULL)
+   return NULL;
+
/* first check pubkey against the one from the TAL */
pk = d2i_PUBKEY(NULL, , pkeysz);
if (pk == NULL) {
@@ -1207,7 +1213,7 @@ auth_find(struct auth_tree *auths, const
return RB_FIND(auth_tree, auths, );
 }
 
-void
+struct auth *
 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
 {
struct auth *na;
@@ -1221,6 +1227,8 @@ auth_insert(struct auth_tree *auths, str
 
if (RB_INSERT(auth_tree, auths, na) != NULL)
err(1, "auth tree corrupted");
+
+   return na;
 }
 
 static void
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.131
diff -u -p -r1.131 extern.h
--- extern.h21 Apr 2022 09:53:07 -  1.131
+++ extern.h21 Apr 2022 10:46:09 -
@@ -308,7 +308,7 @@ struct auth {
 RB_HEAD(auth_tree, auth);
 
 struct auth*auth_find(struct auth_tree *, const char *);
-voidauth_insert(struct auth_tree *, struct cert *, struct auth *);
+struct auth*auth_insert(struct auth_tree *, struct cert *, struct auth *);
 
 enum http_result {
HTTP_FAILED,/* anything else */
Index: filemode.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v
retrieving revision 1.1
diff -u -p -r1.1 filemode.c
--- filemode.c  21 Apr 2022 09:53:07 -  1.1
+++ filemode.c  21 Apr 2022 10:47:24 -
@@ -46,80 +46,6 @@ static struct crl_treecrlt = RB_INITIA
 struct tal *talobj[TALSZ_MAX];
 
 /*
- * Validate a certificate, if invalid free the resouces and return NULL.
- */
-static struct cert *
-proc_parser_cert_validate(char *file, struct cert *cert)
-{
-   struct auth *a;
-   struct crl  *crl;
-
-   a = valid_ski_aki(file, , cert->ski, cert->aki);
-   crl = crl_get(, a);
-
-   if (!valid_x509(file, ctx, cert->x509, a, crl, 0)) {
-   cert_free(cert);
-   return NULL;
-   }
-
-   cert->talid = a->cert->talid;
-
-   /* Validate the cert */
-   if (!valid_cert(file, a, cert)) {
-   cert_free(cert);
-   return NULL;
-   }
-
-   /*
-* Add validated CA certs to the RPKI auth tree.
-*/
-   if (cert->purpose == CERT_PURPOSE_CA)
-   auth_insert(, cert, a);
-
-   return cert;
-}
-
-/*
- * Root certificates come from TALs (has a pkey and is self-signed).
- * Parse the certificate, ensure that its public key matches the
- * known public key from the TAL, and then validate the RPKI
- * content.
- *
- * This returns a certificate (which must not be freed) or NULL on
- * parse failure.
- */
-static struct cert *
-proc_parser_root_cert(char *file, const unsigned char *der, size_t len,
-unsigned char *pkey, size_t pkeysz, int talid)
-{
-   struct cert *cert;
-
-   /* Extract certificate data. */
-
-   cert = cert_parse_pre(file, der, len);
-   if (cert == NULL)
-   return NULL;
-   cert = ta_parse(file, cert, pkey, pkeysz);
-   if (cert == NULL)
-   return NULL;
-
-   if (!valid_ta(file, , cert)) {
-   warnx("%s: certificate not a valid ta", file);
-   cert_free(cert);
-   return NULL;
-   }
-
-   cert->talid = talid;
-
-   /*
-* Add valid roots to the RPKI auth tree.
-*/
-   auth_insert(, cert, NULL);
-
-   return cert;
-}
-
-/*
  * Use the X509 CRL Distribution Points to locate the CRL needed for
  * verification.
  */
@@ -207,25 +133,25 @@ parse_load_cert(char *uri)
 static void
 parse_load_certchain(char *uri)
 {
-   struct cert *stack[MAX_CERT_DEPTH];
+   struct cert *stack[MAX_CERT_DEPTH] = { 0 };
char *filestack[MAX_CERT_DEPTH];
struct cert *cert;
-   int i, failed;
+   struct crl *crl;
+   struct auth *a;
+   int i;
 
for (i = 0; i < MAX_CERT_DEPTH; i++) {
-   cert = 

Re: router timer mutex

2022-04-21 Thread Claudio Jeker
On Wed, Apr 20, 2022 at 08:12:51PM +0200, Alexander Bluhm wrote:
> Hi,
> 
> mvs@ reminded me of a crash I have seen in December.  Route timers
> are not MP safe, but I think this can be fixed with a mutex.  The
> idea is to protect the global lists with a mutex and move the rttimer
> into a temporary list.  Then the callback and pool put can be called
> later without mutex.
> 
> It survived a full regress with witness.
> 
> Hrvoje: Can you put this on your test machine together with parallel
> IP forwarding?
> 
> ok?

I would have prefer if the code was refactored first. The removal of a
rt_timer is copied over in 4 or 5 places with almost no difference.
In the rt_timer_queue_destroy() case you can use TAILQ_CONCAT and kill one
loop. Also I would use TAILQ_HEAD_INITIALIZER() instead of TAILQ_INIT().

To be honest most of this code should be directly replaced with the
timeout API. I bet the timeout API is more efficent.
 
> Index: net/route.c
> ===
> RCS file: /cvs/src/sys/net/route.c,v
> retrieving revision 1.406
> diff -u -p -r1.406 route.c
> --- net/route.c   20 Apr 2022 17:58:22 -  1.406
> +++ net/route.c   20 Apr 2022 18:00:39 -
> @@ -1361,7 +1361,8 @@ rt_ifa_purge_walker(struct rtentry *rt, 
>   * for multiple queues for efficiency's sake...
>   */
>  
> -LIST_HEAD(, rttimer_queue)   rttimer_queue_head;
> +struct mutex rttimer_mtx;
> +LIST_HEAD(, rttimer_queue)   rttimer_queue_head; /* [t] */
>  
>  #define RTTIMER_CALLOUT(r)   {   \
>   if (r->rtt_func != NULL) {  \
> @@ -1393,6 +1394,7 @@ rt_timer_init(void)
>   pool_init(_queue_pool, sizeof(struct rttimer_queue), 0,
>   IPL_MPFLOOR, 0, "rttmrq", NULL);
>  
> + mtx_init(_mtx, IPL_MPFLOOR);
>   LIST_INIT(_queue_head);
>   timeout_set_proc(_timer_timeout, rt_timer_timer, _timer_timeout);
>   timeout_add_sec(_timer_timeout, 1);
> @@ -1408,7 +1410,10 @@ rt_timer_queue_create(int timeout)
>   rtq->rtq_timeout = timeout;
>   rtq->rtq_count = 0;
>   TAILQ_INIT(>rtq_head);
> +
> + mtx_enter(_mtx);
>   LIST_INSERT_HEAD(_queue_head, rtq, rtq_link);
> + mtx_leave(_mtx);
>  
>   return (rtq);
>  }
> @@ -1416,28 +1421,36 @@ rt_timer_queue_create(int timeout)
>  void
>  rt_timer_queue_change(struct rttimer_queue *rtq, int timeout)
>  {
> + mtx_enter(_mtx);
>   rtq->rtq_timeout = timeout;
> + mtx_leave(_mtx);
>  }
>  
>  void
>  rt_timer_queue_destroy(struct rttimer_queue *rtq)
>  {
> - struct rttimer  *r;
> + struct rttimer  *r;
> + TAILQ_HEAD(, rttimer)rttlist;
>  
>   NET_ASSERT_LOCKED();
>  
> + TAILQ_INIT();
> + mtx_enter(_mtx);
>   while ((r = TAILQ_FIRST(>rtq_head)) != NULL) {
>   LIST_REMOVE(r, rtt_link);
>   TAILQ_REMOVE(>rtq_head, r, rtt_next);
> + TAILQ_INSERT_TAIL(, r, rtt_next);
> + KASSERT(rtq->rtq_count > 0);
> + rtq->rtq_count--;
> + }
> + LIST_REMOVE(rtq, rtq_link);
> + mtx_leave(_mtx);
> +
> + while ((r = TAILQ_FIRST()) != NULL) {
> + TAILQ_REMOVE(, r, rtt_next);
>   RTTIMER_CALLOUT(r);
>   pool_put(_pool, r);
> - if (rtq->rtq_count > 0)
> - rtq->rtq_count--;
> - else
> - printf("rt_timer_queue_destroy: rtq_count reached 0\n");
>   }
> -
> - LIST_REMOVE(rtq, rtq_link);
>   pool_put(_queue_pool, rtq);
>  }
>  
> @@ -1450,15 +1463,22 @@ rt_timer_queue_count(struct rttimer_queu
>  void
>  rt_timer_remove_all(struct rtentry *rt)
>  {
> - struct rttimer  *r;
> + struct rttimer  *r;
> + TAILQ_HEAD(, rttimer)rttlist;
>  
> + TAILQ_INIT();
> + mtx_enter(_mtx);
>   while ((r = LIST_FIRST(>rt_timer)) != NULL) {
>   LIST_REMOVE(r, rtt_link);
>   TAILQ_REMOVE(>rtt_queue->rtq_head, r, rtt_next);
> - if (r->rtt_queue->rtq_count > 0)
> - r->rtt_queue->rtq_count--;
> - else
> - printf("rt_timer_remove_all: rtq_count reached 0\n");
> + TAILQ_INSERT_TAIL(, r, rtt_next);
> + KASSERT(r->rtt_queue->rtq_count > 0);
> + r->rtt_queue->rtq_count--;
> + }
> + mtx_leave(_mtx);
> +
> + while ((r = TAILQ_FIRST()) != NULL) {
> + TAILQ_REMOVE(, r, rtt_next);
>   pool_put(_pool, r);
>   }
>  }
> @@ -1471,8 +1491,9 @@ rt_timer_add(struct rtentry *rt, void (*
>   time_t   current_time;
>  
>   current_time = getuptime();
> - rt->rt_expire = current_time + queue->rtq_timeout;
>  
> + mtx_enter(_mtx);
> + rt->rt_expire = current_time + queue->rtq_timeout;
>   /*
>* If there's already a timer with this action, destroy it before
>* we add a new one.
> @@ -1481,27 +1502,31 

Re: [External] : Re: pfsync(4) snapshot lists must have dedicated link element

2022-04-21 Thread Hrvoje Popovski
On 20.4.2022. 23:22, Alexandr Nedvedicky wrote:
> Hello,
> 
> On Wed, Apr 20, 2022 at 03:43:06PM +0200, Alexander Bluhm wrote:
>> On Sat, Apr 09, 2022 at 01:51:05AM +0200, Alexandr Nedvedicky wrote:
>>> updated diff is below.
>> I am not sure what Hrvoje actually did test and what not.  My
>> impression was, that he got a panic with the previous version of
>> this diff, but the machine was stable with the code in current.
>>
>> But maybe I got it wrong and we need this code to run pfsync with
>> IPsec in parallel.
> that's correct. Hrvoje was testing several diffs stacked
> on each other:
>   diff which enables parallel forwarding
>   diff which fixes tunnel descriptor block handling (tdb) for ipsec
>   diff which fixes pfsync

Yes,

panics that we exchange privately was on production and I couldn't
reproduce them in lab. In production I don't have ipsec, only simple
pfsync setup. It seems to me that pfsync mpfloor diff solved panics that
I had in production.

At the same time I was running sasyncd setup with 5 site-to-site ipsec
tunnels with same diffs and for now it seems stable ..




Re: router timer mutex

2022-04-21 Thread Hrvoje Popovski
On 20.4.2022. 20:12, Alexander Bluhm wrote:
> Hi,
> 
> mvs@ reminded me of a crash I have seen in December.  Route timers
> are not MP safe, but I think this can be fixed with a mutex.  The
> idea is to protect the global lists with a mutex and move the rttimer
> into a temporary list.  Then the callback and pool put can be called
> later without mutex.
> 
> It survived a full regress with witness.
> 
> Hrvoje: Can you put this on your test machine together with parallel
> IP forwarding?
> 
> ok?


No problem,

I'm running this and parallel forwarding diff in lab and production.



Re: xenodm and login_fbtab

2022-04-21 Thread Mark Kettenis
> Date: Thu, 21 Apr 2022 11:49:45 +1000
> From: Jonathan Gray 
> 
> On Wed, Apr 20, 2022 at 05:17:58PM -0500, joshua stein wrote:
> > xenodm supports login_fbtab(3) to chown devices but it currently 
> > doesn't do anything because /etc/fbtab does not list /dev/ttyC4.  It 
> > uses the GiveConsole and TakeConsole scripts in /etc/X11/xenodm/ to 
> > do this manually, but the file lists are not complete.
> > 
> > I would like to remove all of the custom chown/chmod calls in the 
> > GiveConsole and TakeConsole scripts and move this into /etc/fbtab by 
> > adding /dev/ttyC4 and all of the wskbd* and wsmouse* devices so that 
> > wsconsctl from within X11 works. (These wildcards require the 
> > just-committed changes to libutil.)
> > 
> > The current fbtab lists many of these devices for /dev/ttyC0 which 
> > seems only relevant for running OpenGL applications from the console 
> > (is this even possible?) or running X11 as an unprivileged user 
> > which we don't support anymore.
> 
> using startx still works with the modesetting xorg driver
> when the pci bus does not need to be probed
> 
> does your diff no longer change ownership of the devices for
> startx?

Right this proposal breaks startx.

Maybe the installer could change /etc/fbtab when it enables xenodm?

> 
> revision 1.7
> date: 2019/09/15 12:25:40;  author: kettenis;  state: Exp;  lines: +1 -1;  
> commitid: zDNBYfUsKpdfByaf;
> Add ttyC4 to lost of devices to change when logging in on ttyC0 (and in
> some cases also the serial console) such that X can use it as its VT
> when running without root privileges.
> 
> ok jsg@, matthieu@
> 
> 
> > 
> > Is there any particular reason to keep these around for /dev/ttyC0?
> > 
> > This has bit me before when I am logged into X11 as my normal user, 
> > I login to ttyC0 as root to check something which chowns all the 
> > devices to root, then later in X11 I notice no GL-using apps like 
> > Firefox work anymore because they can't open /dev/dri nodes.
> > 
> > Once these file lists are ironed out, I will make diffs for all the 
> > other arches.
> > 
> > 
> > diff --git etc/etc.amd64/fbtab etc/etc.amd64/fbtab
> > index aec447931a7..df5a7a29cdd 100644
> > --- etc/etc.amd64/fbtab
> > +++ etc/etc.amd64/fbtab
> > @@ -1 +1,2 @@
> > -/dev/ttyC0 0600
> > /dev/console:/dev/wskbd:/dev/wskbd0:/dev/wsmouse:/dev/wsmouse0:/dev/ttyCcfg:/dev/ttyC4:/dev/dri/card0:/dev/dri/renderD128
> > +/dev/ttyC0 0600/dev/console:/dev/wskbd*:/dev/wsmouse*:/dev/ttyCcfg
> > +/dev/ttyC4 0600
> > /dev/console:/dev/wskbd*:/dev/wsmouse*:/dev/ttyCcfg:/dev/ttyC4:/dev/dri/*
> > 
> > 
> 
>