Re: acpi interrupt storm on HP EliteBook 840 G1

2020-04-26 Thread Greg Steuck
I searched a bit more and found a few cases when other people reported
this behavior:

https://marc.info/?l=openbsd-misc&m=154348280502809&w=2
https://marc.info/?l=openbsd-bugs&m=152022260714390&w=2

I applied a variation of the Thomas Merkel's patch (at the bottom)
which took care of the symptoms while also reporting the masked event.

I am facing a choice. This appears to be a rarely reported problem.  I
don't see a good reason to build any non-trivial mitigation (some
variation of event rate limiting comes to mind). I can just carry a
minimized patch forward for as long as I use the defective machine and
rebuild GENERIC.MP as part of my weekly sysupgrade ritual.

Anybody see a reason to prefer complicating the kernel? Will it stand a
chance of getting committed? Any design ideas for such a workaround?

Thanks
Greg

diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index c3871e007a3..9c069fd5314 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -2296,6 +2296,15 @@ acpi_gpe(struct acpi_softc *sc, int gpe, void *arg)
  struct aml_node *node = arg;
  uint8_t mask, en;

+ if (gpe == 0x2a && (sc->gpe_table[gpe].flags & GPE_LEVEL)) {
+ static unsigned short i;
+ if (i == 0) {
+ i++;
+ printf("acpi_gpe %d %s IGNORING\n", gpe, node->name);
+ }
+ return (0);
+ }
+ printf("acpi_gpe %d %s\n", gpe, node->name);
  dnprintf(10, "handling GPE %.2x\n", gpe);
  aml_evalnode(sc, node, 0, NULL, NULL);



Re: [patch] Check for -1 explicitly in getpeereid.c

2020-04-26 Thread Theo de Raadt
Patrick Wildt  wrote:

> I don't know userland very well, so I have a question.  In the middle of
> 2019 there have been plenty of changes in regards to changing checks of
> syscalls from < 0 to a more strict == -1, like this one in isakmpd:
> 
> 
> revision 1.26
> date: 2019/06/28 13:32:44;  author: deraadt;  state: Exp;  lines: +2 -2;  
> commitid: JJ6Ck4WTrgUiEjJp;
> When system calls indicate an error they return -1, not some arbitrary
> value < 0.  errno is only updated in this case.  Change all (most?)
> callers of syscalls to follow this better, and let's see if this strictness
> helps us in the future.
> 

I have about 4000 more changes like that, but I'm stuck with trying to
push it further forward.  For various reasons, some of which can be
guessed from this thread.

> getsockopt(), I think, is also a system call.  And the manpage indicates
> that a failure is always -1, and not some arbitrary number:
> 
> RETURN VALUES
>  Upon successful completion, the value 0 is returned; otherwise the
>  value -1 is returned and the global variable errno is set to indicate the
>  error.
> 
> What is the difference between the diff in this mail, and the changes
> done in the middle of last year?

The difference is this is direct checking of the syscalls.

Versus checking at a higher layer of abstraction, or conversion of
that result to something else.

Say you have an interface which returns precisely 0 and -1 for two conditions.
Well then it has a large set of out-of-range values which (a) won't occur
but (b) if they occur, how do you handle them?  At which layer?  

The range of numbers returned really express 3 conditions.  One which is
impossible, yet if it happens, do you want to convert the impossible to
success, or to failure?

In the recently supplied diff, a return value of 50 at the system call
layer, is returned into a library returning 0 (success).  Furthermore, the
diff itself proposes treating the out-of-range impossible as a success,
and accesses memory which is very probably unintialized.

> getsockopt() isn't allowed to return
> anything else but 0 and 1, right?  Though I guess the current check
> (error != 0) is the one that also catches instances where getsockopt()
> isn't behaving well, even though it shouldn't.  But then, with the -1
> check, wouldn't we be catching more instances of syscalls misbehaving
> if we checked for < -1?

Correct.  I hope you have reached the same indecision point as me.

I feel uncomfortable changing all checking-points to 3-way decision.
And imagine what a modern compiler would do there...



Re: [patch] Check for -1 explicitly in getpeereid.c

2020-04-26 Thread Patrick Wildt
Hi,

I don't know userland very well, so I have a question.  In the middle of
2019 there have been plenty of changes in regards to changing checks of
syscalls from < 0 to a more strict == -1, like this one in isakmpd:


revision 1.26
date: 2019/06/28 13:32:44;  author: deraadt;  state: Exp;  lines: +2 -2;  
commitid: JJ6Ck4WTrgUiEjJp;
When system calls indicate an error they return -1, not some arbitrary
value < 0.  errno is only updated in this case.  Change all (most?)
callers of syscalls to follow this better, and let's see if this strictness
helps us in the future.


getsockopt(), I think, is also a system call.  And the manpage indicates
that a failure is always -1, and not some arbitrary number:

RETURN VALUES
 Upon successful completion, the value 0 is returned; otherwise the
 value -1 is returned and the global variable errno is set to indicate the
 error.

What is the difference between the diff in this mail, and the changes
done in the middle of last year?  getsockopt() isn't allowed to return
anything else but 0 and 1, right?  Though I guess the current check
(error != 0) is the one that also catches instances where getsockopt()
isn't behaving well, even though it shouldn't.  But then, with the -1
check, wouldn't we be catching more instances of syscalls misbehaving
if we checked for < -1?

Patrick

On Sun, Apr 26, 2020 at 02:45:54PM -0600, Theo de Raadt wrote:
> If it returns 50 then the creds structure is not valid, and can't be copied
> from.  It only returns valid creds *IF* success is indicated by 0.  But then
> you convert 50 to a return value of 0, and hide any indication that things
> went weird?
> 
> No way, I'm not buying your argument.   I think the code is making the
> correct choice now.
> 
> Martin Vahlensieck  wrote:
> 
> > Hi there
> > 
> > From the getsockopt(2) manual page says getsockopt(2) returns -1 on
> > error and 0 on success. Also getpeereid(3) only lists those 2 values.
> > This diff makes the return value check in getpeereid explicit. I guess
> > this is how it is done elsewhere in the tree (there is a commit turning
> > a bunch of "... < 0" to "== -1" I think this falls under that category).
> > 
> > Best,
> > 
> > Martin
> > 
> > Index: net/getpeereid.c
> > ===
> > RCS file: /cvs/src/lib/libc/net/getpeereid.c,v
> > retrieving revision 1.1
> > diff -u -p -r1.1 getpeereid.c
> > --- net/getpeereid.c1 Jul 2010 19:15:30 -   1.1
> > +++ net/getpeereid.c26 Apr 2020 20:28:50 -
> > @@ -28,7 +28,7 @@ getpeereid(int s, uid_t *euid, gid_t *eg
> >  
> > error = getsockopt(s, SOL_SOCKET, SO_PEERCRED,
> > &creds, &credslen);
> > -   if (error)
> > +   if (error == -1)
> > return (error);
> > *euid = creds.uid;
> > *egid = creds.gid;
> > 
> 



Re: [patch] Check for -1 explicitly in getpeereid.c

2020-04-26 Thread Theo de Raadt
If it returns 50 then the creds structure is not valid, and can't be copied
from.  It only returns valid creds *IF* success is indicated by 0.  But then
you convert 50 to a return value of 0, and hide any indication that things
went weird?

No way, I'm not buying your argument.   I think the code is making the
correct choice now.

Martin Vahlensieck  wrote:

> Hi there
> 
> From the getsockopt(2) manual page says getsockopt(2) returns -1 on
> error and 0 on success. Also getpeereid(3) only lists those 2 values.
> This diff makes the return value check in getpeereid explicit. I guess
> this is how it is done elsewhere in the tree (there is a commit turning
> a bunch of "... < 0" to "== -1" I think this falls under that category).
> 
> Best,
> 
> Martin
> 
> Index: net/getpeereid.c
> ===
> RCS file: /cvs/src/lib/libc/net/getpeereid.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 getpeereid.c
> --- net/getpeereid.c  1 Jul 2010 19:15:30 -   1.1
> +++ net/getpeereid.c  26 Apr 2020 20:28:50 -
> @@ -28,7 +28,7 @@ getpeereid(int s, uid_t *euid, gid_t *eg
>  
>   error = getsockopt(s, SOL_SOCKET, SO_PEERCRED,
>   &creds, &credslen);
> - if (error)
> + if (error == -1)
>   return (error);
>   *euid = creds.uid;
>   *egid = creds.gid;
> 



[patch] Check for -1 explicitly in getpeereid.c

2020-04-26 Thread Martin Vahlensieck
Hi there

>From the getsockopt(2) manual page says getsockopt(2) returns -1 on
error and 0 on success. Also getpeereid(3) only lists those 2 values.
This diff makes the return value check in getpeereid explicit. I guess
this is how it is done elsewhere in the tree (there is a commit turning
a bunch of "... < 0" to "== -1" I think this falls under that category).

Best,

Martin

Index: net/getpeereid.c
===
RCS file: /cvs/src/lib/libc/net/getpeereid.c,v
retrieving revision 1.1
diff -u -p -r1.1 getpeereid.c
--- net/getpeereid.c1 Jul 2010 19:15:30 -   1.1
+++ net/getpeereid.c26 Apr 2020 20:28:50 -
@@ -28,7 +28,7 @@ getpeereid(int s, uid_t *euid, gid_t *eg
 
error = getsockopt(s, SOL_SOCKET, SO_PEERCRED,
&creds, &credslen);
-   if (error)
+   if (error == -1)
return (error);
*euid = creds.uid;
*egid = creds.gid;



Re: coherent em(4) descriptor rings (to be able to run on my arm64 machine)

2020-04-26 Thread Mark Kettenis
> Date: Sun, 26 Apr 2020 18:03:20 +0200
> From: Patrick Wildt 
> 
> Hi,
> 
> I have a HummingBoard Pulse, which is an NXP i.MX8MQ based board
> featuring two ethernets, with the second ethernet being an em(4) on
> a PCIe controller.
> 
> I had trouble getting it to work, but realized that the issue is the
> descriptor ring coherency.  I looked into the code, tried to find if
> there are incorrect flushes, or something else, but nothing worked.
> 
> Looking at the Linux driver I realized that their descriptor rings are
> allocated coherent.  Some arm64 machines are fine with em(4), since the
> PCIe controller is coherent, but on my machine it is not.  Explicitly
> mapping the rings coherent made my machine happy, so I believe that
> maybe the way that em(4) works, we need to make sure the rings are
> coherent.
> 
> So I'd propose the following diff, which *only* makes the desciptor
> rings coherent, the packets stay cached and fast.  This allows me to
> push plenty of traffic through my machine!
> 
> This is a no-op on all x86, and on arm64-machines with coherent PCIe
> controllers.
> 
> Opinions? ok?

In principle the BUS_DMAMAP_COHERENT flag should not matter; things
should work either way.  This indicates there is something wrong in
the code here, either a missing bus_dmamap_sync() call, or a bug in
the arm64 bus_dmamp_sync() implementation.  Things are always tricky
for descriptor rings, where software and hardware are modifying the
memory contents.  Things get especially tricky when a cache line
covers multiple ring entries.  Given that ARMv8 typically has a cache
line size of 64 bytes and em(4) has descriptors of 16 bytes, that may
very well be a problem here.

That said.  BUS_DMA_COHERENT makes a lot of sense for descriptor rings
like this since otherwise you just end up doing doing lots of cache
flushes.  And I think you've spent enough time looking for the real
bug.

Quickly tested on the Ampere machine.

ok kettenis@

> diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
> index aca6b4bb02f..27d0630bf9f 100644
> --- a/sys/dev/pci/if_em.c
> +++ b/sys/dev/pci/if_em.c
> @@ -2113,7 +2113,7 @@ em_dma_malloc(struct em_softc *sc, bus_size_t size, 
> struct em_dma_alloc *dma)
>   goto destroy;
>  
>   r = bus_dmamem_map(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg, size,
> - &dma->dma_vaddr, BUS_DMA_WAITOK);
> + &dma->dma_vaddr, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
>   if (r != 0)
>   goto free;
>  
> 
> 



smtpd: fix catch-all in virtual aliases

2020-04-26 Thread Eric Faurot
Hi.

When a catch-all entry (@) is used in a virtual alias table, it
eventually (and mistakenly) catches everything that expands to a
username. For example, with:

f...@example.com  user
@catchall

"f...@example.com" expands to "user" as expected, but then "user"
expands to "catchall" because it is interpreted as "user@" (empty
domain).

The catch-all fallback mechanism is really meant for full email
addresses in virtual context, and should not happen for usernames.
The following diff fixes it.


Eric.

Index: aliases.c
===
RCS file: /cvs/src/usr.sbin/smtpd/aliases.c,v
retrieving revision 1.77
diff -u -p -r1.77 aliases.c
--- aliases.c   28 Dec 2018 12:47:28 -  1.77
+++ aliases.c   26 Apr 2020 16:04:51 -
@@ -164,6 +164,10 @@ aliases_virtual_get(struct expand *expan
if (ret)
goto expand;
 
+   /* Do not try catch-all entries if there is no domain */
+   if (domain[0] == '\0')
+   return 0;
+
if (!bsnprintf(buf, sizeof(buf), "@%s", domain))
return 0;
/* Failed ? We lookup for catch all for virtual domain */



coherent em(4) descriptor rings (to be able to run on my arm64 machine)

2020-04-26 Thread Patrick Wildt
Hi,

I have a HummingBoard Pulse, which is an NXP i.MX8MQ based board
featuring two ethernets, with the second ethernet being an em(4)
on a PCIe controller.

I had trouble getting it to work, but realized that the issue is the
descriptor ring coherency.  I looked into the code, tried to find if
there are incorrect flushes, or something else, but nothing worked.

Looking at the Linux driver I realized that their descriptor rings are
allocated coherent.  Some arm64 machines are fine with em(4), since the
PCIe controller is coherent, but on my machine it is not.  Explicitly
mapping the rings coherent made my machine happy, so I believe that
maybe the way that em(4) works, we need to make sure the rings are
coherent.

So I'd propose the following diff, which *only* makes the desciptor
rings coherent, the packets stay cached and fast.  This allows me to
push plenty of traffic through my machine!

This is a no-op on all x86, and on arm64-machines with coherent PCIe
controllers.

Opinions? ok?

Patrick

diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index aca6b4bb02f..27d0630bf9f 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -2113,7 +2113,7 @@ em_dma_malloc(struct em_softc *sc, bus_size_t size, 
struct em_dma_alloc *dma)
goto destroy;
 
r = bus_dmamem_map(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg, size,
-   &dma->dma_vaddr, BUS_DMA_WAITOK);
+   &dma->dma_vaddr, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
if (r != 0)
goto free;
 



Re: correction for insque.3

2020-04-26 Thread Jason McIntyre
On Thu, Apr 23, 2020 at 05:48:42PM -0400, Andras Farkas wrote:
> I was reading the thread about STAILQ and SIMPLEQ and thought it was
> interesting, so I then read a little about sys/queue.h and search.h
> I noticed an error in insque.3:
> https://man.openbsd.org/insque.3
> The words "next" and "previous" are swapped, as it is the first
> pointer that points to the next element, and the second pointer that
> points to the previous element.
> I confirmed this both in insque.c (to make sure I understood the
> directionality correctly):
> https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/insque.c?rev=1.3&content-type=text/x-cvsweb-markup
> and in POSIX, which the man page states OpenBSD's insque() conforms to:
> https://pubs.opengroup.org/onlinepubs/9699919799/functions/insque.html
> 
> I have the diff to fix this both inline and attached.
> Checksum for anyone trying to grab the diff from inline, since my
> inline diffs usually get mangled:
> SHA256 (insque3diff.txt) =
> 8340d135c06abc46127a12307b9611d274e1ad3e35dc6cf662da15a1f4502dec
> 
> Index: insque.3
> ===
> RCS file: /cvs/src/lib/libc/stdlib/insque.3,v
> retrieving revision 1.10
> diff -u -p -r1.10 insque.3
> --- insque.3 30 Nov 2014 20:19:12 - 1.10
> +++ insque.3 23 Apr 2020 21:13:10 -
> @@ -61,7 +61,7 @@ struct qelem {
>  .Ed
>  .Pp
>  The first two elements in the struct must be pointers of the
> -same type that point to the previous and next elements in
> +same type that point to the next and previous elements in
>  the queue respectively.
>  Any subsequent data in the struct is application-dependent.
>  .Pp
> 

hi. i just committed this part.

> Also, I feel the phrasing isn't as clear as it could be.  The way
> "respectively" is used makes more sense in the way the other BSD man
> pages use "first and second" (in "first and second members") rather
> than the OpenBSD man page's "first two" (in "first two elements").  I
> think "respectively" makes more sense when used in analogy, or pairing
> up words.
> https://www.freebsd.org/cgi/man.cgi?query=insque&apropos=0&sektion=0&manpath=FreeBSD+12.1-RELEASE+and+Ports&arch=default&format=html
> https://netbsd.gw.com/cgi-bin/man-cgi?insque
> https://leaf.dragonflybsd.org/cgi/web-man?command=insque§ion=ANY
> Their wording is identical.
> 

but could;t convince myself that this was any clearer.

jmc

> I have a larger diff as an option, in light of the above:
> SHA256 (insque3difflarge.txt) =
> c2e242221f016ae4bafa3b40a466f27016d4f44b3f58053a60204e06aecefaf9
> 
> Index: insque.3
> ===
> RCS file: /cvs/src/lib/libc/stdlib/insque.3,v
> retrieving revision 1.10
> diff -u -p -r1.10 insque.3
> --- insque.3 30 Nov 2014 20:19:12 - 1.10
> +++ insque.3 23 Apr 2020 21:42:07 -
> @@ -60,8 +60,8 @@ struct qelem {
>  };
>  .Ed
>  .Pp
> -The first two elements in the struct must be pointers of the
> -same type that point to the previous and next elements in
> +The first and second elements in the struct must be pointers of the
> +same type that point to the next and previous elements in
>  the queue respectively.
>  Any subsequent data in the struct is application-dependent.
>  .Pp
> 
> Thanks for reading!

> Index: insque.3
> ===
> RCS file: /cvs/src/lib/libc/stdlib/insque.3,v
> retrieving revision 1.10
> diff -u -p -r1.10 insque.3
> --- insque.3  30 Nov 2014 20:19:12 -  1.10
> +++ insque.3  23 Apr 2020 21:13:10 -
> @@ -61,7 +61,7 @@ struct qelem {
>  .Ed
>  .Pp
>  The first two elements in the struct must be pointers of the
> -same type that point to the previous and next elements in
> +same type that point to the next and previous elements in
>  the queue respectively.
>  Any subsequent data in the struct is application-dependent.
>  .Pp

> Index: insque.3
> ===
> RCS file: /cvs/src/lib/libc/stdlib/insque.3,v
> retrieving revision 1.10
> diff -u -p -r1.10 insque.3
> --- insque.3  30 Nov 2014 20:19:12 -  1.10
> +++ insque.3  23 Apr 2020 21:42:07 -
> @@ -60,8 +60,8 @@ struct qelem {
>  };
>  .Ed
>  .Pp
> -The first two elements in the struct must be pointers of the
> -same type that point to the previous and next elements in
> +The first and second elements in the struct must be pointers of the
> +same type that point to the next and previous elements in
>  the queue respectively.
>  Any subsequent data in the struct is application-dependent.
>  .Pp



Raspberry Pi GPIO

2020-04-26 Thread Mark Kettenis
Diff below adds GPIO support to bcmgpio(4).  It also adds the bits to
attach gpio(4) such that GPIO pins can be controlled from userland.
This makes sense on boards like the Raspberry Pi and the
implementation makes sure that pins used by kernel drivers can't be
touched.

ok?


Index: arch/arm64/conf/GENERIC
===
RCS file: /cvs/src/sys/arch/arm64/conf/GENERIC,v
retrieving revision 1.161
diff -u -p -r1.161 GENERIC
--- arch/arm64/conf/GENERIC 25 Apr 2020 22:28:12 -  1.161
+++ arch/arm64/conf/GENERIC 26 Apr 2020 10:51:19 -
@@ -148,6 +148,7 @@ bcmclock*   at fdt? early 1
 bcmdmac*   at fdt? early 1
 bcmdog*at fdt?
 bcmgpio*   at fdt? early 1
+gpio*  at bcmgpio?
 bcmintc*   at fdt? early 1
 bcmirng*   at fdt?
 bcmmbox*   at fdt? early 1
Index: dev/fdt/bcm2835_gpio.c
===
RCS file: /cvs/src/sys/dev/fdt/bcm2835_gpio.c,v
retrieving revision 1.2
diff -u -p -r1.2 bcm2835_gpio.c
--- dev/fdt/bcm2835_gpio.c  25 Apr 2020 22:15:00 -  1.2
+++ dev/fdt/bcm2835_gpio.c  26 Apr 2020 10:51:20 -
@@ -17,16 +17,21 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 #include 
 #include 
 
+#include 
 #include 
+#include 
 #include 
 #include 
 
+#include "gpio.h"
+
 /* Registers */
 #define GPFSEL(n)  (0x00 + ((n) * 4))
 #define  GPFSEL_MASK   0x7
@@ -38,6 +43,9 @@
 #define  GPFSEL_ALT3   0x7
 #define  GPFSEL_ALT4   0x3
 #define  GPFSEL_ALT5   0x2
+#define GPSET(n)   (0x1c + ((n) * 4))
+#define GPCLR(n)   (0x28 + ((n) * 4))
+#define GPLEV(n)   (0x34 + ((n) * 4))
 #define GPPUD  0x94
 #define  GPPUD_PUD 0x3
 #define  GPPUD_PUD_OFF 0x0
@@ -47,6 +55,8 @@
 #define GPPULL(n)  (0xe4 + ((n) * 4))
 #define  GPPULL_MASK   0x3
 
+#define BCMGPIO_MAX_PINS   58
+
 #define HREAD4(sc, reg)
\
(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
 #define HWRITE4(sc, reg, val)  \
@@ -58,6 +68,13 @@ struct bcmgpio_softc {
bus_space_handle_t  sc_ioh;
 
void(*sc_config_pull)(struct bcmgpio_softc *, int, int);
+   int sc_num_pins;
+
+   struct gpio_controller  sc_gc;
+
+   struct gpio_chipset_tag sc_gpio_tag;
+   gpio_pin_t  sc_gpio_pins[BCMGPIO_MAX_PINS];
+   int sc_gpio_claimed[BCMGPIO_MAX_PINS];
 };
 
 intbcmgpio_match(struct device *, void *, void *);
@@ -74,6 +91,10 @@ struct cfdriver bcmgpio_cd = {
 void   bcm2711_config_pull(struct bcmgpio_softc *, int, int);
 void   bcm2835_config_pull(struct bcmgpio_softc *, int, int);
 intbcmgpio_pinctrl(uint32_t, void *);
+void   bcmgpio_config_pin(void *, uint32_t *, int);
+intbcmgpio_get_pin(void *, uint32_t *);
+void   bcmgpio_set_pin(void *, uint32_t *, int);
+void   bcmgpio_attach_gpio(struct device *);
 
 int
 bcmgpio_match(struct device *parent, void *match, void *aux)
@@ -104,12 +125,24 @@ bcmgpio_attach(struct device *parent, st
 
printf("\n");
 
-   if (OF_is_compatible(faa->fa_node, "brcm,bcm2711-gpio"))
+   if (OF_is_compatible(faa->fa_node, "brcm,bcm2711-gpio")) {
sc->sc_config_pull = bcm2711_config_pull;
-   else
+   sc->sc_num_pins = 58;
+   } else {
sc->sc_config_pull = bcm2835_config_pull;
+   sc->sc_num_pins = 54;
+   }
 
pinctrl_register(faa->fa_node, bcmgpio_pinctrl, sc);
+
+   sc->sc_gc.gc_node = faa->fa_node;
+   sc->sc_gc.gc_cookie = sc;
+   sc->sc_gc.gc_config_pin = bcmgpio_config_pin;
+   sc->sc_gc.gc_get_pin = bcmgpio_get_pin;
+   sc->sc_gc.gc_set_pin = bcmgpio_set_pin;
+   gpio_controller_register(&sc->sc_gc);
+
+   config_mountroot(self, bcmgpio_attach_gpio);
 }
 
 void
@@ -186,6 +219,7 @@ bcmgpio_pinctrl(uint32_t phandle, void *
bcmgpio_config_func(sc, pins[i], func);
if (plen > 0 && i < plen / sizeof(uint32_t))
sc->sc_config_pull(sc, pins[i], pull[i]);
+   sc->sc_gpio_claimed[pins[i]] = 1;
}
 
free(pull, M_TEMP, plen);
@@ -196,4 +230,176 @@ fail:
free(pull, M_TEMP, plen);
free(pins, M_TEMP, len);
return -1;
+}
+
+void
+bcmgpio_config_pin(void *cookie, uint32_t *cells, int config)
+{
+   struct bcmgpio_softc *sc = cookie;
+   uint32_t pin = cells[0];
+
+   if (pin >= sc->sc_num_pins)
+   return;
+
+   if (config & GPIO_CONFIG_OUTPUT)
+   bcmgpio_config_func(sc, pin, GPFSEL_GPIO_OUT);
+   else
+   bcmgpio_config_func(sc, pin, GPFSEL_GPIO_OUT);
+   if (config & GPIO_CONFIG_PULL_UP)
+   sc->sc_config_pull(sc, pin, GPPUD_PUD_UP);
+   else

Re: OpenSMTPD: unprivileged mode - now with diff

2020-04-26 Thread Gregory Edigarov

Hello, Christopher

On the right of a person who had successfully run rootless sendmail 
installations for many years,

please find some comments below.

On 2020-04-26 12:30, Christopher Zimmermann wrote:
Thanks for giving it a thought. I'm not entirely convinced either. But 
believe some thought should be given to it.
In your opinion would it be generaly a bad idea to try run smtpd 
without root privileges?

What exectly will cease to work?

- .forward and alias _filtering_ will break for sure.


not necessarily. at least as long as users will have smtpd and their 
.forward and in the same group and you've documented it. also, .forward 
and authentication could be handled by a separate daemon bound to unix 
socket only, which won't listen to outside world. or even better, 
separate all the functions, that usually need root access to such 
daemon(s).


the only thing was broken for me in sendmail's case, was mbox 
deliveries. but AFAIR, that was solved by having patched version of 
mail.local.


--

With best regards,

  Gregory Edigarov




Re: OpenSMTPD: unprivileged mode - now with diff

2020-04-26 Thread Christopher Zimmermann

On Sun, Apr 26, 2020 at 08:55:14AM +, gil...@poolp.org wrote:

April 26, 2020 10:34 AM, "Christopher Zimmermann"  wrote:

- always run lmtp deliveries as SMTPD_USER. The change to 
  mda_unpriv.c is needed, because otherwise

all mails would be delivered to SMTPD_USER.

- add two internal flags NOPRIV and NEEDPRIV. NOPRIV can be configured by the 
simple directive
"no-priv". NEEDPRIV gets set on all delivery methods / options requiring 
setuid() to run as the
receipient user.
A configuration error is produced on any conflict betweed NEEDPRIV and NOPRIV.
In case of a NOPRIV run smtpd will drop root privileges.
This will break .forward and alias filters.



Hi, thanks for your fast reply.


The LMTP change seems interesting to me, it means that a broken LMTP delivery
will fail with _smtpd privileges instead of the (unprivileged) recipient user
so I think it's a good move.


That's great. Is there anything that needs to change or be clarified 
before you can give an ok?



I'm less convinced by the other change and it doesn't only break .forward and
alias, it also breaks authentication, tables reloading, and probably stuff my
mind is not yet awake enough to think of.


Thanks for giving it a thought. I'm not entirely convinced either. But 
believe some thought should be given to it.
In your opinion would it be generaly a bad idea to try run smtpd without 
root privileges?

What exectly will cease to work?

- .forward and alias _filtering_ will break for sure.
  Forwarding won't break.

- Authentication: Authentication of system users will break. So I would 
  mark auth without auth-table as need_priv() in parse.y.


- tables reloading: this is a problem only for tables with restricted 
  read permissions, isn't it?
  I could try to figure out whether it is a problem in parse.y and mark 
  it as need_priv() if necessary, but one could also just document the 
  no-priv option with its limitations.


- other stuff: Can it be dealt with need_priv()? Will it lead to 
  unpleasant surprises for users?


The general idea is to allow running smtpd without root priviliges where 
possible and maybe try to change it to support running without root for 
more use-cases over time. Like try to pick the low-hanging fruits first.


One less low-hanging fruits would be to integrate mail.lmtp(8) into 
smtpd and move other mail.* functionality into a privileged lmtpd 
daemon.
This would remove those vulnerable mda-exec lines from the envelope 
files. That's just one idea how one could proceed. The current proposal 
is to start stripping privileges where possible.



Christopher


 
-- http://gmerlin.de

OpenPGP: http://gmerlin.de/christopher.pub
CB07 DA40 B0B6 571D 35E2  0DEF 87E2 92A7 13E5 DEE1



Re: OpenSMTPD: unprivileged mode - now with diff

2020-04-26 Thread gilles
April 26, 2020 10:34 AM, "Christopher Zimmermann"  wrote:

> Hi,
> 
> I further developed my approach to allow running smtpd with fewer privileges. 
> This diff does two
> things:
> 
> - always run lmtp deliveries as SMTPD_USER. The change to mda_unpriv.c is 
> needed, because otherwise
> all mails would be delivered to SMTPD_USER.
>
> - add two internal flags NOPRIV and NEEDPRIV. NOPRIV can be configured by the 
> simple directive
> "no-priv". NEEDPRIV gets set on all delivery methods / options requiring 
> setuid() to run as the
> receipient user.
> A configuration error is produced on any conflict betweed NEEDPRIV and NOPRIV.
> In case of a NOPRIV run smtpd will drop root privileges.
> This will break .forward and alias filters.
> 
> The change to the lmtp delivery has benefits even without the second change. 
> With the second change
> my smtpd now runs without root privileges.
> The NEEDPRIV/NOPRIV options are meant to allow restricting of the privileges 
> of other delivery
> methods.
> 
> I am now looking for OKs on the first change to do unprivileged lmtp 
> deliveries and feedback on the
> general approach of the second change.
> 

The LMTP change seems interesting to me, it means that a broken LMTP delivery
will fail with _smtpd privileges instead of the (unprivileged) recipient user
so I think it's a good move.

I'm less convinced by the other change and it doesn't only break .forward and
alias, it also breaks authentication, tables reloading, and probably stuff my
mind is not yet awake enough to think of.



> Index: mda_unpriv.c
> ===
> RCS file: /cvs/src/usr.sbin/smtpd/mda_unpriv.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 mda_unpriv.c
> --- mda_unpriv.c 2 Feb 2020 22:13:48 - 1.6
> +++ mda_unpriv.c 26 Apr 2020 05:27:34 -
> @@ -69,8 +69,8 @@ mda_unpriv(struct dispatcher *dsp, struc
> xasprintf(&mda_environ[idx++], "RECIPIENT=%s@%s", deliver->dest.user, 
> deliver->dest.domain);
> xasprintf(&mda_environ[idx++], "SHELL=/bin/sh");
> xasprintf(&mda_environ[idx++], "LOCAL=%s", deliver->rcpt.user);
> - xasprintf(&mda_environ[idx++], "LOGNAME=%s", pw_name);
> - xasprintf(&mda_environ[idx++], "USER=%s", pw_name);
> + xasprintf(&mda_environ[idx++], "LOGNAME=%s", deliver->userinfo.username);
> + xasprintf(&mda_environ[idx++], "USER=%s", deliver->userinfo.username);
> if (deliver->sender.user[0])
> xasprintf(&mda_environ[idx++], "SENDER=%s@%s",
> Index: parse.y
> ===
> RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
> retrieving revision 1.277
> diff -u -p -r1.277 parse.y
> --- parse.y 24 Feb 2020 23:54:27 - 1.277
> +++ parse.y 26 Apr 2020 05:27:35 -
> @@ -154,6 +154,7 @@ static int host_v4(struct listen_opts *)
> static int host_v6(struct listen_opts *);
> static int host_dns(struct listen_opts *);
> static int interface(struct listen_opts *);
> +static void need_priv(const char *);
> int delaytonum(char *);
> int is_if_in_group(const char *, const char *);
> @@ -186,7 +187,7 @@ typedef struct {
> %token KEY
> %token LIMIT LISTEN LMTP LOCAL
> %token MAIL_FROM MAILDIR MASK_SRC MASQUERADE MATCH MAX_MESSAGE_SIZE 
> MAX_DEFERRED MBOX MDA MTA MX
> -%token NO_DSN NO_VERIFY NOOP
> +%token NO_DSN NO_PRIV NO_VERIFY NOOP
> %token ON
> %token PHASE PKI PORT PROC PROC_EXEC PROXY_V2
> %token QUEUE QUIT
> @@ -212,6 +213,7 @@ grammar : /* empty */
> | grammar ca '\n'
> | grammar mda '\n'
> | grammar mta '\n'
> + | grammar privs '\n'
> | grammar pki '\n'
> | grammar proc '\n'
> | grammar queue '\n'
> @@ -379,6 +381,20 @@ MTA MAX_DEFERRED NUMBER {
> ;
> +privs:
> +NO_PRIV {
> + if (conf->sc_opts & SMTPD_OPT_NEEDPRIV) {
> + yyerror("Unprivileged operation is not possible.");
> + YYERROR;
> + }
> + else {
> + log_warnx("Unprivileged operation requested.");
> + conf->sc_opts |= SMTPD_OPT_NOPRIV;
> + }
> +}
> +;
> +
> +
> pki:
> PKI STRING {
> char buf[HOST_NAME_MAX+1];
> @@ -566,6 +582,8 @@ SRS KEY STRING {
> dispatcher_local_option:
> USER STRING {
> + need_priv("with user");
> +
> if (dispatcher->u.local.is_mbox) {
> yyerror("user may not be specified for this dispatcher");
> YYERROR;
> @@ -662,16 +680,20 @@ dispatcher_local_option dispatcher_local
> dispatcher_local:
> MBOX {
> + need_priv("mbox");
> dispatcher->u.local.is_mbox = 1;
> asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.local -f 
> %%{mbox.from} --
> %%{user.username}");
> } dispatcher_local_options
> | MAILDIR {
> + need_priv("maildir");
> asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.maildir");
> } dispatcher_local_options
> | MAILDIR JUNK {
> + need_priv("maildir");
> asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.maildir -j");
> } dispatcher_local_options
> | MAILDIR STRING {
> + need_priv("maildir");
> if (strncmp($2, "~/", 2) == 0)
> asprintf(&dispatcher->u.local.command,
> "/usr/libexec/mail.maildir \"%%{user.directory}/%s\"", $2+2);
> @@ -680,6 +702,7 @@ MBOX {
> "/usr/libexe

OpenSMTPD: unprivileged mode - now with diff

2020-04-26 Thread Christopher Zimmermann

Hi,

I further developed my approach to allow running smtpd with fewer 
privileges. This diff does two things:


- always run lmtp deliveries as SMTPD_USER. The change to mda_unpriv.c 
  is needed, because otherwise all mails would be delivered to 
  SMTPD_USER.
- add two internal flags NOPRIV and NEEDPRIV. NOPRIV can be configured 
  by the simple directive "no-priv". NEEDPRIV gets set on all delivery 
  methods / options requiring setuid() to run as the receipient user.
  A configuration error is produced on any conflict betweed NEEDPRIV and 
  NOPRIV.

  In case of a NOPRIV run smtpd will drop root privileges.
  This will break .forward and alias filters.

The change to the lmtp delivery has benefits even without the second 
change. With the second change my smtpd now runs without root 
privileges.
The NEEDPRIV/NOPRIV options are meant to allow restricting of the 
privileges of other delivery methods.


I am now looking for OKs on the first change to do unprivileged lmtp 
deliveries and feedback on the general approach of the second change.



Christopher



Index: mda_unpriv.c
===
RCS file: /cvs/src/usr.sbin/smtpd/mda_unpriv.c,v
retrieving revision 1.6
diff -u -p -r1.6 mda_unpriv.c
--- mda_unpriv.c2 Feb 2020 22:13:48 -   1.6
+++ mda_unpriv.c26 Apr 2020 05:27:34 -
@@ -69,8 +69,8 @@ mda_unpriv(struct dispatcher *dsp, struc
xasprintf(&mda_environ[idx++], "RECIPIENT=%s@%s", deliver->dest.user, 
deliver->dest.domain);
xasprintf(&mda_environ[idx++], "SHELL=/bin/sh");
xasprintf(&mda_environ[idx++], "LOCAL=%s", deliver->rcpt.user);
-   xasprintf(&mda_environ[idx++], "LOGNAME=%s", pw_name);
-   xasprintf(&mda_environ[idx++], "USER=%s", pw_name);
+   xasprintf(&mda_environ[idx++], "LOGNAME=%s", 
deliver->userinfo.username);
+   xasprintf(&mda_environ[idx++], "USER=%s", deliver->userinfo.username);
 
 	if (deliver->sender.user[0])

xasprintf(&mda_environ[idx++], "SENDER=%s@%s",
Index: parse.y
===
RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
retrieving revision 1.277
diff -u -p -r1.277 parse.y
--- parse.y 24 Feb 2020 23:54:27 -  1.277
+++ parse.y 26 Apr 2020 05:27:35 -
@@ -154,6 +154,7 @@ static int  host_v4(struct listen_opts *)
 static int host_v6(struct listen_opts *);
 static int host_dns(struct listen_opts *);
 static int interface(struct listen_opts *);
+static voidneed_priv(const char *);
 
 int		 delaytonum(char *);

 int is_if_in_group(const char *, const char *);
@@ -186,7 +187,7 @@ typedef struct {
 %token KEY
 %token LIMIT LISTEN LMTP LOCAL
 %token MAIL_FROM MAILDIR MASK_SRC MASQUERADE MATCH MAX_MESSAGE_SIZE 
MAX_DEFERRED MBOX MDA MTA MX
-%token NO_DSN NO_VERIFY NOOP
+%token NO_DSN NO_PRIV NO_VERIFY NOOP
 %token ON
 %token PHASE PKI PORT PROC PROC_EXEC PROXY_V2
 %token QUEUE QUIT
@@ -212,6 +213,7 @@ grammar : /* empty */
| grammar ca '\n'
| grammar mda '\n'
| grammar mta '\n'
+   | grammar privs '\n'
| grammar pki '\n'
| grammar proc '\n'
| grammar queue '\n'
@@ -379,6 +381,20 @@ MTA MAX_DEFERRED NUMBER  {
 ;
 
 
+privs:

+NO_PRIV {
+   if (conf->sc_opts & SMTPD_OPT_NEEDPRIV) {
+   yyerror("Unprivileged operation is not possible.");
+   YYERROR;
+   }
+   else {
+   log_warnx("Unprivileged operation requested.");
+   conf->sc_opts |= SMTPD_OPT_NOPRIV;
+   }
+}
+;
+
+
 pki:
 PKI STRING {
char buf[HOST_NAME_MAX+1];
@@ -566,6 +582,8 @@ SRS KEY STRING {
 
 dispatcher_local_option:

 USER STRING {
+   need_priv("with user");
+
if (dispatcher->u.local.is_mbox) {
yyerror("user may not be specified for this dispatcher");
YYERROR;
@@ -662,16 +680,20 @@ dispatcher_local_option dispatcher_local
 
 dispatcher_local:

 MBOX {
+   need_priv("mbox");
dispatcher->u.local.is_mbox = 1;
asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.local -f 
%%{mbox.from} -- %%{user.username}");
 } dispatcher_local_options
 | MAILDIR {
+   need_priv("maildir");
asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.maildir");
 } dispatcher_local_options
 | MAILDIR JUNK {
+   need_priv("maildir");
asprintf(&dispatcher->u.local.command, "/usr/libexec/mail.maildir -j");
 } dispatcher_local_options
 | MAILDIR STRING {
+   need_priv("maildir");
if (strncmp($2, "~/", 2) == 0)
asprintf(&dispatcher->u.local.command,
"/usr/libexec/mail.maildir \"%%{user.directory}/%s\"", 
$2+2);
@@ -680,6 +702,7 @@ MBOX {
"/usr/libexec/mail.maildir \"%s\"", $2);
 } dispatcher_local_options
 | MAILDIR STRING JUNK {
+   need_priv("maildir");