Re: malloc: fix setting errno on out-of-memory

2016-05-10 Thread Otto Moerbeek
On Tue, May 10, 2016 at 02:48:18PM -0400, Daniel Micay wrote:

> The ENOMEM errno wasn't being set in some code paths where it was gated
> behind mopts.malloc_xmalloc:

Called functions do set errno..., you're effectively overriding those.
Which means those can go if this is applied. This needs more work/thought (and
is gong to conflict with my milt-pool diff).

-Otto


> 
> diff --git a/stdlib/malloc.c b/stdlib/malloc.c
> index bc328d2..aa6f0a3 100644
> --- a/stdlib/malloc.c
> +++ b/stdlib/malloc.c
> @@ -1224,8 +1224,9 @@ malloc(size_t size)
>   r = omalloc(d, size, 0, CALLER);
>   d->active--;
>   _MALLOC_UNLOCK();
> - if (r == NULL && mopts.malloc_xmalloc) {
> - wrterror(d, "out of memory", NULL);
> + if (r == NULL) {
> + if (mopts.malloc_xmalloc)
> + wrterror(d, "out of memory", NULL);
>   errno = ENOMEM;
>   }
>   if (r != NULL)
> @@ -1510,8 +1511,9 @@ realloc(void *ptr, size_t size)
>  
>   d->active--;
>   _MALLOC_UNLOCK();
> - if (r == NULL && mopts.malloc_xmalloc) {
> - wrterror(d, "out of memory", NULL);
> + if (r == NULL) {
> + if (mopts.malloc_xmalloc)
> + wrterror(d, "out of memory", NULL);
>   errno = ENOMEM;
>   }
>   if (r != NULL)
> @@ -1563,8 +1565,9 @@ calloc(size_t nmemb, size_t size)
>  
>   d->active--;
>   _MALLOC_UNLOCK();
> - if (r == NULL && mopts.malloc_xmalloc) {
> - wrterror(d, "out of memory", NULL);
> + if (r == NULL) {
> + if (mopts.malloc_xmalloc)
> + wrterror(d, "out of memory", NULL);
>   errno = ENOMEM;
>   }
>   if (r != NULL)
> @@ -1694,10 +1697,9 @@ posix_memalign(void **memptr, size_t alignment, size_t 
> size)
>   d->active--;
>   _MALLOC_UNLOCK();
>   if (r == NULL) {
> - if (mopts.malloc_xmalloc) {
> + if (mopts.malloc_xmalloc)
>   wrterror(d, "out of memory", NULL);
> - errno = ENOMEM;
> - }
> + errno = ENOMEM;
>   goto err;
>   }
>   errno = saved_errno;
> -- 
> 2.8.2



free size for descript tables

2016-05-10 Thread Ted Unangst
this is tricky, but not too hard. expanded dfff context to see the malloc.

Index: kern_descrip.c
===
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.130
diff -u -p -u -1 -7 -r1.130 kern_descrip.c
--- kern_descrip.c  25 Apr 2016 20:18:31 -  1.130
+++ kern_descrip.c  10 May 2016 22:53:35 -
@@ -836,55 +836,57 @@ fdexpand(struct proc *p)
 
newofile = mallocarray(nfiles, OFILESIZE, M_FILEDESC, M_WAITOK);
newofileflags = (char *) [nfiles];
 
/*
 * Copy the existing ofile and ofileflags arrays
 * and zero the new portion of each array.
 */
copylen = sizeof(struct file *) * fdp->fd_nfiles;
memcpy(newofile, fdp->fd_ofiles, copylen);
memset((char *)newofile + copylen, 0,
nfiles * sizeof(struct file *) - copylen);
copylen = sizeof(char) * fdp->fd_nfiles;
memcpy(newofileflags, fdp->fd_ofileflags, copylen);
memset(newofileflags + copylen, 0, nfiles * sizeof(char) - copylen);
 
if (fdp->fd_nfiles > NDFILE)
-   free(fdp->fd_ofiles, M_FILEDESC, 0);
+   free(fdp->fd_ofiles, M_FILEDESC, fdp->fd_nfiles * OFILESIZE);
 
if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
newhimap = mallocarray(NDHISLOTS(nfiles), sizeof(u_int),
M_FILEDESC, M_WAITOK);
newlomap = mallocarray(NDLOSLOTS(nfiles), sizeof(u_int),
M_FILEDESC, M_WAITOK);
 
copylen = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int);
memcpy(newhimap, fdp->fd_himap, copylen);
memset((char *)newhimap + copylen, 0,
NDHISLOTS(nfiles) * sizeof(u_int) - copylen);
 
copylen = NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int);
memcpy(newlomap, fdp->fd_lomap, copylen);
memset((char *)newlomap + copylen, 0,
NDLOSLOTS(nfiles) * sizeof(u_int) - copylen);
 
if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
-   free(fdp->fd_himap, M_FILEDESC, 0);
-   free(fdp->fd_lomap, M_FILEDESC, 0);
+   free(fdp->fd_himap, M_FILEDESC,
+   NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int));
+   free(fdp->fd_lomap, M_FILEDESC,
+   NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int));
}
fdp->fd_himap = newhimap;
fdp->fd_lomap = newlomap;
}
fdp->fd_ofiles = newofile;
fdp->fd_ofileflags = newofileflags;
fdp->fd_nfiles = nfiles;
 }
 
 /*
  * Create a new open file structure and allocate
  * a file descriptor for the process that refers to it.
  */
 int
 falloc(struct proc *p, struct file **resultfp, int *resultfd)
 {
struct file *fp, *fq;
@@ -1068,38 +1070,40 @@ fdfree(struct proc *p)
struct filedesc *fdp = p->p_fd;
struct file **fpp, *fp;
int i;
 
if (--fdp->fd_refcnt > 0)
return;
fpp = fdp->fd_ofiles;
for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
fp = *fpp;
if (fp != NULL) {
FREF(fp);
*fpp = NULL;
(void) closef(fp, p);
}
}
p->p_fd = NULL;
if (fdp->fd_nfiles > NDFILE)
-   free(fdp->fd_ofiles, M_FILEDESC, 0);
+   free(fdp->fd_ofiles, M_FILEDESC, fdp->fd_nfiles * OFILESIZE);
if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
-   free(fdp->fd_himap, M_FILEDESC, 0);
-   free(fdp->fd_lomap, M_FILEDESC, 0);
+   free(fdp->fd_himap, M_FILEDESC,
+   NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int));
+   free(fdp->fd_lomap, M_FILEDESC,
+   NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int));
}
if (fdp->fd_cdir)
vrele(fdp->fd_cdir);
if (fdp->fd_rdir)
vrele(fdp->fd_rdir);
free(fdp->fd_knlist, M_TEMP, fdp->fd_knlistsize * sizeof(struct klist));
free(fdp->fd_knhash, M_TEMP, 0);
pool_put(_pool, fdp);
 }
 
 /*
  * Internal form of close.
  * Decrement reference count on file structure.
  * Note: p may be NULL when closing a file
  * that was being passed in a message.
  *
  * The fp must have its usecount bumped and will be FRELEd here.



bcopy in libkvm

2016-05-10 Thread Ted Unangst
memcpy is newer and better.


Index: kvm.c
===
RCS file: /cvs/src/lib/libkvm/kvm.c,v
retrieving revision 1.59
diff -u -p -r1.59 kvm.c
--- kvm.c   19 Dec 2015 18:40:30 -  1.59
+++ kvm.c   10 May 2016 22:46:07 -
@@ -713,7 +713,7 @@ kvm_dbopen(kvm_t *kd, const char *uf)
if (rec.data == 0 || rec.size > sizeof(dbversion))
goto close;
 
-   bcopy(rec.data, dbversion, rec.size);
+   memcpy(dbversion, rec.data, rec.size);
dbversionlen = rec.size;
 
/*
@@ -727,7 +727,7 @@ kvm_dbopen(kvm_t *kd, const char *uf)
goto close;
if (rec.data == 0 || rec.size != sizeof(struct nlist))
goto close;
-   bcopy(rec.data, , sizeof(nitem));
+   memcpy(, rec.data, sizeof(nitem));
if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
dbversionlen)
goto close;
@@ -791,10 +791,10 @@ kvm_nlist(kvm_t *kd, struct nlist *nl)
/*
 * Avoid alignment issues.
 */
-   bcopy(&((struct nlist *)rec.data)->n_type,
-   >n_type, sizeof(p->n_type));
-   bcopy(&((struct nlist *)rec.data)->n_value,
-   >n_value, sizeof(p->n_value));
+   memcpy(>n_type, &((struct nlist *)rec.data)->n_type,
+   sizeof(p->n_type));
+   memcpy(>n_value, &((struct nlist *)rec.data)->n_value,
+   sizeof(p->n_value));
}
/*
 * Return the number of entries that weren't found.
Index: kvm_proc.c
===
RCS file: /cvs/src/lib/libkvm/kvm_proc.c,v
retrieving revision 1.52
diff -u -p -r1.52 kvm_proc.c
--- kvm_proc.c  22 Oct 2014 04:13:35 -  1.52
+++ kvm_proc.c  10 May 2016 22:47:07 -
@@ -490,7 +490,7 @@ kvm_ureadm(kvm_t *kd, const struct kinfo
return (0);
}
cc = (size_t)MIN(cnt, len);
-   bcopy(dp, cp, cc);
+   memcpy(cp, dp, cc);
cp += cc;
uva += cc;
len -= cc;



Re: Allow top(1) to search arguments (again)

2016-05-10 Thread Ted Unangst
Edd Barrett wrote:
> On Thu, Apr 28, 2016 at 03:26:48PM +0100, Edd Barrett wrote:
> > Resubmitting this diff, as I've been unable to get an OK.
> 
> Style tweaks fixed, as pointed out by Michal Mazurek. Thanks for this.
> 
> OK?

ok



Re: Allow top(1) to search arguments (again)

2016-05-10 Thread Edd Barrett
On Thu, Apr 28, 2016 at 03:26:48PM +0100, Edd Barrett wrote:
> Resubmitting this diff, as I've been unable to get an OK.

Style tweaks fixed, as pointed out by Michal Mazurek. Thanks for this.

OK?

Index: machine.c
===
RCS file: /home/edd/cvsync/src/usr.bin/top/machine.c,v
retrieving revision 1.85
diff -u -p -r1.85 machine.c
--- machine.c   20 Aug 2015 22:32:42 -  1.85
+++ machine.c   4 May 2016 22:09:32 -
@@ -57,6 +57,8 @@
 static int swapmode(int *, int *);
 static char*state_abbr(struct kinfo_proc *);
 static char*format_comm(struct kinfo_proc *);
+static int cmd_matches(struct kinfo_proc *, char *);
+static char**get_proc_args(struct kinfo_proc *);
 
 /* get_process_info passes back a handle.  This is what it looks like: */
 
@@ -360,6 +362,60 @@ getprocs(int op, int arg, int *cnt)
return (procbase);
 }
 
+static char **
+get_proc_args(struct kinfo_proc *kp)
+{
+   static char **s;
+   size_t  siz = 100;
+   int mib[4];
+
+   for (;; siz *= 2) {
+   if ((s = realloc(s, siz)) == NULL)
+   err(1, NULL);
+   mib[0] = CTL_KERN;
+   mib[1] = KERN_PROC_ARGS;
+   mib[2] = kp->p_pid;
+   mib[3] = KERN_PROC_ARGV;
+   if (sysctl(mib, 4, s, , NULL, 0) == 0)
+   break;
+   if (errno != ENOMEM)
+   return NULL;
+   }
+   return s;
+}
+
+static int
+cmd_matches(struct kinfo_proc *proc, char *term)
+{
+   extern int  show_args;
+   char**args = NULL;
+
+   if (!term) {
+   /* No command filter set */
+   return 1;
+   } else {
+   /* Filter set, process name needs to contain term */
+   if (strstr(proc->p_comm, term))
+   return 1;
+   /* If showing arguments, search those as well */
+   if (show_args) {
+   args = get_proc_args(proc);
+
+   if (args == NULL) {
+   /* Failed to get args, so can't search them */
+   return 0;
+   }
+
+   while (*args != NULL) {
+   if (strstr(*args, term))
+   return 1;
+   args++;
+   }
+   }
+   }
+   return 0;
+}
+
 caddr_t
 get_process_info(struct system_info *si, struct process_select *sel,
 int (*compare) (const void *, const void *))
@@ -421,8 +477,7 @@ get_process_info(struct system_info *si,
(!hide_uid || pp->p_ruid != sel->huid) &&
(!show_uid || pp->p_ruid == sel->uid) &&
(!show_pid || pp->p_pid == sel->pid) &&
-   (!show_cmd || strstr(pp->p_comm,
-   sel->command))) {
+   (!show_cmd || cmd_matches(pp, sel->command))) {
*prefp++ = pp;
active_procs++;
}
@@ -462,27 +517,17 @@ state_abbr(struct kinfo_proc *pp)
 static char *
 format_comm(struct kinfo_proc *kp)
 {
-   static char **s, buf[MAX_COLS];
-   size_t siz = 100;
-   char **p;
-   int mib[4];
-   extern int show_args;
+   static char buf[MAX_COLS];
+   char**p, **s;
+   extern int  show_args;
 
if (!show_args)
return (kp->p_comm);
 
-   for (;; siz *= 2) {
-   if ((s = realloc(s, siz)) == NULL)
-   err(1, NULL);
-   mib[0] = CTL_KERN;
-   mib[1] = KERN_PROC_ARGS;
-   mib[2] = kp->p_pid;
-   mib[3] = KERN_PROC_ARGV;
-   if (sysctl(mib, 4, s, , NULL, 0) == 0)
-   break;
-   if (errno != ENOMEM)
-   return (kp->p_comm);
-   }
+   s = get_proc_args(kp);
+   if (s == NULL)
+   return kp->p_comm;
+
buf[0] = '\0';
for (p = s; *p != NULL; p++) {
if (p != s)
Index: top.1
===
RCS file: /home/edd/cvsync/src/usr.bin/top/top.1,v
retrieving revision 1.66
diff -u -p -r1.66 top.1
--- top.1   6 May 2015 07:53:29 -   1.66
+++ top.1   4 May 2016 22:15:10 -
@@ -108,6 +108,7 @@ The default is 1 for dumb terminals.
 Display only processes that contain
 .Ar string
 in their command name.
+If displaying of arguments is enabled, the arguments are searched too.
 .It Fl H
 Show process threads in the display.
 Normally, only the main process is shown.
@@ -306,6 +307,7 @@ command.
 Display only processes that contain
 .Ar string
 in their command name.
+If displaying 

smu(4) PWM Fan Support

2016-05-10 Thread Marcus Glocker
I've recently noticed that two of five fans in my G5 don't spin up.
That's because smu(4) currently just supports RPM fans.
The attached diff adds initial support for PWM fans as well.

sysctl before:
# sysctl -a | grep fan
hw.sensors.smu0.fan0=994 RPM (Rear Fan 0)
hw.sensors.smu0.fan1=994 RPM (Rear fan 1)
hw.sensors.smu0.fan2=994 RPM (Front Fan)

sysctl after:
# sysctl -a | grep fan
hw.sensors.smu0.fan0=994 RPM (Rear Fan 0)
hw.sensors.smu0.fan1=994 RPM (Rear fan 1)
hw.sensors.smu0.fan2=994 RPM (Front Fan)
hw.sensors.smu0.fan3=589 RPM (Slots Fan)
hw.sensors.smu0.fan4=589 RPM (Drive Bay)

I was first thinking to introduce a new sensor type in sys/sensor.h
called SENSOR_FANPWM, but finally I think it's more intuitive to
display the RPM value for all fans in general.

In case this makes it in I would like to split the RPM read which
is currently done in smu_fan_refresh() in a own function as next,
same as for the PWM read.  Also with the background that there seems
to be another set/read method for new style fans which may fail
currently which we could implement.


Index: sys/arch/macppc/dev/smu.c
===
RCS file: /cvs/src/sys/arch/macppc/dev/smu.c,v
retrieving revision 1.28
diff -u -p -u -p -r1.28 smu.c
--- sys/arch/macppc/dev/smu.c   4 May 2016 08:20:58 -   1.28
+++ sys/arch/macppc/dev/smu.c   10 May 2016 21:26:39 -
@@ -41,6 +41,13 @@ voidsmu_attach(struct device *, stru
 
 struct smu_fan {
u_int8_treg;
+   enum {
+   SMU_SENSOR_FANRPM,
+   SMU_SENSOR_FANPWM
+   } type;
+   u_int16_t   min_pwm;
+   u_int16_t   max_pwm;
+   u_int16_t   unmanaged_pwm;
u_int16_t   min_rpm;
u_int16_t   max_rpm;
u_int16_t   unmanaged_rpm;
@@ -144,6 +151,9 @@ int smu_time_read(time_t *);
 intsmu_time_write(time_t);
 intsmu_get_datablock(struct smu_softc *sc, u_int8_t, u_int8_t *, size_t);
 intsmu_fan_set_rpm(struct smu_softc *, struct smu_fan *, u_int16_t);
+intsmu_fan_set_pwm(struct smu_softc *, struct smu_fan *, u_int16_t);
+intsmu_fan_read_pwm(struct smu_softc *, struct smu_fan *, u_int16_t *,
+   u_int16_t *);
 intsmu_fan_refresh(struct smu_softc *, struct smu_fan *);
 intsmu_sensor_refresh(struct smu_softc *, struct smu_sensor *);
 void   smu_refresh_sensors(void *);
@@ -250,7 +260,7 @@ smu_attach(struct device *parent, struct
time_read = smu_time_read;
time_write = smu_time_write;
 
-   /* Fans */
+   /* RPM Fans */
node = OF_getnodebyname(ca->ca_node, "rpm-fans");
if (node == 0)
node = OF_getnodebyname(ca->ca_node, "fans");
@@ -260,7 +270,7 @@ smu_attach(struct device *parent, struct
continue;
 
if (strcmp(type, "fan-rpm-control") != 0) {
-   printf(": unsupported fan type: %s\n", type);
+   printf(": unsupported rpm-fan type: %s\n", type);
return;
}
 
@@ -273,6 +283,7 @@ smu_attach(struct device *parent, struct
fan->sensor.type = SENSOR_FANRPM;
fan->sensor.flags = SENSOR_FINVALID;
fan->reg = reg;
+   fan->type = SMU_SENSOR_FANRPM;
 
if (OF_getprop(node, "min-value", , sizeof val) <= 0)
val = 0;
@@ -299,6 +310,54 @@ smu_attach(struct device *parent, struct
 #endif
}
 
+   /* PWM Fans */
+   node = OF_getnodebyname(ca->ca_node, "pwm-fans");
+   for (node = OF_child(node); node; node = OF_peer(node)) {
+   if (OF_getprop(node, "reg", , sizeof reg) <= 0 ||
+   OF_getprop(node, "device_type", type, sizeof type) <= 0)
+   continue;
+
+   if (strcmp(type, "fan-pwm-control") != 0) {
+   printf(": unsupported pwm-fan type: %s\n", type);
+   return;
+   }
+
+   if (sc->sc_num_fans >= SMU_MAXFANS) {
+   printf(": too many fans\n");
+   return;
+   }
+
+   fan = >sc_fans[sc->sc_num_fans++];
+   fan->sensor.type = SENSOR_FANRPM;
+   fan->sensor.flags = SENSOR_FINVALID;
+   fan->reg = reg;
+   fan->type = SMU_SENSOR_FANPWM;
+
+   if (OF_getprop(node, "min-value", , sizeof val) <= 0)
+   val = 0;
+   fan->min_pwm = val;
+   if (OF_getprop(node, "max-value", , sizeof val) <= 0)
+   val = 0x;
+   fan->max_pwm = val;
+   if (OF_getprop(node, "unmanage-value", , sizeof val) > 0)
+   fan->unmanaged_pwm = val;
+   else if (OF_getprop(node, "safe-value", , sizeof val) > 0)
+   fan->unmanaged_pwm = val;
+   else
+

Re: sed/regcomp bug?

2016-05-10 Thread Todd C. Miller
On Tue, 10 May 2016 22:34:54 +0200, Martijn van Duren wrote:

> I reread the REG_STARTEND section again and it turns out I
> misinterpreted it's intention and I thought the current behaviour
> was wrong/incomplete. So the change was intentional, but for the
> wrong reasons.
> 
> I changed the diff to allow regexec to combine REG_NOTBOL and
> REG_STARTEND. This way the current syntax stays intact and we can
> use the extra flag to do lookbacks to verify that the last
> character was a word character or not, without risking going into
> unallocated memory.
> 
> Does this look better to you?

That looks much better to me.

 - todd



Re: malloc: add full delayed chunk double-free detection

2016-05-10 Thread Michael McConville
Daniel Micay wrote:
> This uses a hash table to maintain a set of delayed allocations,
> allowing full and efficient double-free detection. The current code
> can only catch it when the two pointers being swapped are equal, so
> double-frees that could be caught are missed. A naive loop over every
> delayed chunk would work fine with the current 16 slot array, but that
> would make scaling up the number of delayed allocations much more
> costly.
> 
> I'm using this with 2 other changes making the size configurable and
> adding a FIFO ring buffer in front of the randomized array of the same
> size, to get a minimum guaranteed delay more than the current 1 free
> cycle. The randomization still works fine and it ends up providing a
> nice balance. It's essentially equivalent to the quarantine feature in
> Valgrind/ASan, but suitable for production and with weaker
> use-after-free detection. It mixes well with the earlier change to
> detect write-after-free via junk validation here.

Seems valuable. Note, though, that you're developing on top of the
multi-pool malloc patches:

https://marc.info/?t=14587167622=1=2

http://www.drijf.net/openbsd/malloc/

So there are probably conflicts.

Thanks,
Mike


> diff --git a/stdlib/malloc.c b/stdlib/malloc.c
> index bc328d2..9e8bd16 100644
> --- a/stdlib/malloc.c
> +++ b/stdlib/malloc.c
> @@ -118,6 +118,7 @@ struct dir_info {
>   struct region_info free_regions[MALLOC_MAXCACHE];
>   /* delayed free chunk slots */
>   void *delayed_chunks[MALLOC_DELAYED_CHUNK_MASK + 1];
> + void *delayed_chunks_set[(MALLOC_DELAYED_CHUNK_MASK + 1) * 2];
>   size_t rbytesused;  /* random bytes used */
>   char *func; /* current function */
>   u_char rbytes[32];  /* random bytes */
> @@ -249,6 +250,22 @@ hash(void *p)
>   return sum;
>  }
>  
> +static inline size_t
> +hash_chunk(void *p)
> +{
> + size_t sum;
> + uintptr_t u;
> +
> + u = (uintptr_t)p >> MALLOC_MINSHIFT;
> + sum = u;
> + sum = (sum << 7) - sum + (u >> 16);
> +#ifdef __LP64__
> + sum = (sum << 7) - sum + (u >> 32);
> + sum = (sum << 7) - sum + (u >> 48);
> +#endif
> + return sum;
> +}
> +
>  static void
>  wrterror(struct dir_info *d, char *msg, void *p)
>  {
> @@ -864,6 +881,58 @@ delete(struct dir_info *d, struct region_info *ri)
>   }
>  }
>  
> +void delayed_chunks_insert(struct dir_info *d, void *p) {
> + size_t index;
> + size_t mask = sizeof(d->delayed_chunks_set) / sizeof(void *) - 1;
> + void *q;
> +
> + index = hash_chunk(p) & mask;
> + q = d->delayed_chunks_set[index];
> + while (q != NULL) {
> + if (p == q) {
> + wrterror(d, "double free", p);
> + return;
> + }
> + index = (index - 1) & mask;
> + q = d->delayed_chunks_set[index];
> + }
> + d->delayed_chunks_set[index] = p;
> +}
> +
> +void delayed_chunks_delete(struct dir_info *d, void *p) {
> + size_t mask = sizeof(d->delayed_chunks_set) / sizeof(void *) - 1;
> + size_t i, j, r;
> + void *q;
> +
> + i = hash_chunk(p) & mask;
> + q = d->delayed_chunks_set[i];
> + while (q != p) {
> + if (q == NULL) {
> + wrterror(d, "pointer missing from address tracking 
> table", p);
> + return;
> + }
> + i = (i - 1) & mask;
> + q = d->delayed_chunks_set[i];
> + }
> +
> + for (;;) {
> + d->delayed_chunks_set[i] = NULL;
> + j = i;
> + for (;;) {
> + i = (i - 1) & mask;
> + if (d->delayed_chunks_set[i] == NULL)
> + return;
> + r = hash_chunk(d->delayed_chunks_set[i]) & mask;
> + if ((i <= r && r < j) || (r < j && j < i) ||
> + (j < i && i <= r))
> + continue;
> + d->delayed_chunks_set[j] = d->delayed_chunks_set[i];
> + break;
> + }
> + }
> +}
> +
> +
>  /*
>   * Allocate a page of chunks
>   */
> @@ -1315,13 +1384,21 @@ ofree(struct dir_info *pool, void *p)
>   if (!mopts.malloc_freenow) {
>   if (find_chunknum(pool, r, p) == -1)
>   return;
> +
> + if (p == NULL)
> + return;
> +
> + delayed_chunks_insert(pool, p);
> +
>   i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK;
>   tmp = p;
>   p = pool->delayed_chunks[i];
> - if (tmp == p) {
> - wrterror(pool, "double free", p);
> +
> + if (p == NULL)
>   return;
> - }
> +
> + 

malloc: add full delayed chunk double-free detection

2016-05-10 Thread Daniel Micay
This uses a hash table to maintain a set of delayed allocations, allowing full
and efficient double-free detection. The current code can only catch it when
the two pointers being swapped are equal, so double-frees that could be caught
are missed. A naive loop over every delayed chunk would work fine with the
current 16 slot array, but that would make scaling up the number of delayed
allocations much more costly.

I'm using this with 2 other changes making the size configurable and adding a
FIFO ring buffer in front of the randomized array of the same size, to get a
minimum guaranteed delay more than the current 1 free cycle. The randomization
still works fine and it ends up providing a nice balance. It's essentially
equivalent to the quarantine feature in Valgrind/ASan, but suitable for
production and with weaker use-after-free detection. It mixes well with the
earlier change to detect write-after-free via junk validation here.

diff --git a/stdlib/malloc.c b/stdlib/malloc.c
index bc328d2..9e8bd16 100644
--- a/stdlib/malloc.c
+++ b/stdlib/malloc.c
@@ -118,6 +118,7 @@ struct dir_info {
struct region_info free_regions[MALLOC_MAXCACHE];
/* delayed free chunk slots */
void *delayed_chunks[MALLOC_DELAYED_CHUNK_MASK + 1];
+   void *delayed_chunks_set[(MALLOC_DELAYED_CHUNK_MASK + 1) * 2];
size_t rbytesused;  /* random bytes used */
char *func; /* current function */
u_char rbytes[32];  /* random bytes */
@@ -249,6 +250,22 @@ hash(void *p)
return sum;
 }
 
+static inline size_t
+hash_chunk(void *p)
+{
+   size_t sum;
+   uintptr_t u;
+
+   u = (uintptr_t)p >> MALLOC_MINSHIFT;
+   sum = u;
+   sum = (sum << 7) - sum + (u >> 16);
+#ifdef __LP64__
+   sum = (sum << 7) - sum + (u >> 32);
+   sum = (sum << 7) - sum + (u >> 48);
+#endif
+   return sum;
+}
+
 static void
 wrterror(struct dir_info *d, char *msg, void *p)
 {
@@ -864,6 +881,58 @@ delete(struct dir_info *d, struct region_info *ri)
}
 }
 
+void delayed_chunks_insert(struct dir_info *d, void *p) {
+   size_t index;
+   size_t mask = sizeof(d->delayed_chunks_set) / sizeof(void *) - 1;
+   void *q;
+
+   index = hash_chunk(p) & mask;
+   q = d->delayed_chunks_set[index];
+   while (q != NULL) {
+   if (p == q) {
+   wrterror(d, "double free", p);
+   return;
+   }
+   index = (index - 1) & mask;
+   q = d->delayed_chunks_set[index];
+   }
+   d->delayed_chunks_set[index] = p;
+}
+
+void delayed_chunks_delete(struct dir_info *d, void *p) {
+   size_t mask = sizeof(d->delayed_chunks_set) / sizeof(void *) - 1;
+   size_t i, j, r;
+   void *q;
+
+   i = hash_chunk(p) & mask;
+   q = d->delayed_chunks_set[i];
+   while (q != p) {
+   if (q == NULL) {
+   wrterror(d, "pointer missing from address tracking 
table", p);
+   return;
+   }
+   i = (i - 1) & mask;
+   q = d->delayed_chunks_set[i];
+   }
+
+   for (;;) {
+   d->delayed_chunks_set[i] = NULL;
+   j = i;
+   for (;;) {
+   i = (i - 1) & mask;
+   if (d->delayed_chunks_set[i] == NULL)
+   return;
+   r = hash_chunk(d->delayed_chunks_set[i]) & mask;
+   if ((i <= r && r < j) || (r < j && j < i) ||
+   (j < i && i <= r))
+   continue;
+   d->delayed_chunks_set[j] = d->delayed_chunks_set[i];
+   break;
+   }
+   }
+}
+
+
 /*
  * Allocate a page of chunks
  */
@@ -1315,13 +1384,21 @@ ofree(struct dir_info *pool, void *p)
if (!mopts.malloc_freenow) {
if (find_chunknum(pool, r, p) == -1)
return;
+
+   if (p == NULL)
+   return;
+
+   delayed_chunks_insert(pool, p);
+
i = getrbyte(pool) & MALLOC_DELAYED_CHUNK_MASK;
tmp = p;
p = pool->delayed_chunks[i];
-   if (tmp == p) {
-   wrterror(pool, "double free", p);
+
+   if (p == NULL)
return;
-   }
+
+   delayed_chunks_delete(pool, p);
+
if (mopts.malloc_junk)
validate_junk(pool, p);
pool->delayed_chunks[i] = tmp;
@@ -1950,6 +2027,7 @@ malloc_dump(int fd)
wrterror(pool, "bogus pointer in malloc_dump", p);
continue;
}
+ 

Re: malloc: fix setting errno on out-of-memory

2016-05-10 Thread Daniel Micay
Sorry, my mail client was being stupid. Lets try again in good old mutt:

diff --git a/stdlib/malloc.c b/stdlib/malloc.c
index bc328d2..aa6f0a3 100644
--- a/stdlib/malloc.c
+++ b/stdlib/malloc.c
@@ -1224,8 +1224,9 @@ malloc(size_t size)
r = omalloc(d, size, 0, CALLER);
d->active--;
_MALLOC_UNLOCK();
-   if (r == NULL && mopts.malloc_xmalloc) {
-   wrterror(d, "out of memory", NULL);
+   if (r == NULL) {
+   if (mopts.malloc_xmalloc)
+   wrterror(d, "out of memory", NULL);
errno = ENOMEM;
}
if (r != NULL)
@@ -1510,8 +1511,9 @@ realloc(void *ptr, size_t size)
 
d->active--;
_MALLOC_UNLOCK();
-   if (r == NULL && mopts.malloc_xmalloc) {
-   wrterror(d, "out of memory", NULL);
+   if (r == NULL) {
+   if (mopts.malloc_xmalloc)
+   wrterror(d, "out of memory", NULL);
errno = ENOMEM;
}
if (r != NULL)
@@ -1563,8 +1565,9 @@ calloc(size_t nmemb, size_t size)
 
d->active--;
_MALLOC_UNLOCK();
-   if (r == NULL && mopts.malloc_xmalloc) {
-   wrterror(d, "out of memory", NULL);
+   if (r == NULL) {
+   if (mopts.malloc_xmalloc)
+   wrterror(d, "out of memory", NULL);
errno = ENOMEM;
}
if (r != NULL)
@@ -1694,10 +1697,9 @@ posix_memalign(void **memptr, size_t alignment, size_t 
size)
d->active--;
_MALLOC_UNLOCK();
if (r == NULL) {
-   if (mopts.malloc_xmalloc) {
+   if (mopts.malloc_xmalloc)
wrterror(d, "out of memory", NULL);
-   errno = ENOMEM;
-   }
+   errno = ENOMEM;
goto err;
}
errno = saved_errno;



Re: sed/regcomp bug?

2016-05-10 Thread Ingo Schwarze
Hi Martijn,

Martijn van Duren wrote on Tue, May 10, 2016 at 08:08:34PM +0200:
> On 05/10/16 19:29, Ingo Schwarze wrote:
>> Martijn van Duren wrote on Tue, May 10, 2016 at 02:43:54PM +0200:

>>> Index: ./lib/libc/regex/engine.c
>>> ===
>>> RCS file: /cvs/src/lib/libc/regex/engine.c,v
>>> retrieving revision 1.19
>>> diff -u -p -r1.19 engine.c
>>> --- ./lib/libc/regex/engine.c   28 Dec 2015 23:01:22 -  1.19
>>> +++ ./lib/libc/regex/engine.c   2 May 2016 08:50:20 -
>>> @@ -674,7 +674,7 @@ fast(struct match *m, char *start, char 
>>> states fresh = m->fresh;
>>> states tmp = m->tmp;
>>> char *p = start;
>>> -   int c = (start == m->beginp) ? OUT : *(start-1);
>>> +   int c = (start == m->offp) ? OUT : *(start-1);
>>> int lastc;  /* previous c */
>>> int flagch;
>>> int i;
>>> @@ -758,7 +758,7 @@ slow(struct match *m, char *start, char 
>>> states empty = m->empty;
>>> states tmp = m->tmp;
>>> char *p = start;
>>> -   int c = (start == m->beginp) ? OUT : *(start-1);
>>> +   int c = (start == m->offp) ? OUT : *(start-1);
>>> int lastc;  /* previous c */
>>> int flagch;
>>> int i;

>> i hate to say that this change appears to cause a regression.
>> 
>> The regexec(3) manual explicitly says:
>> 
>>   REG_STARTEND   The string is considered to start at [...]
>>  Note that a non-zero rm_so does not imply REG_NOTBOL;
>>  REG_STARTEND affects only the location of the string,
>>  not how it is matched.
>> 
>> Right now, the library actually implements that.  The test program
>> appended below produces the following output, as documented:
>> 
>>   rt: regcomp: OK
>>   rt: mismatch: regexec() failed to match
>>   rt: BOL match: OK
>>   rt: ST match: OK
>> 
>> With your change, the library now fails to match:
>> 
>>   rt: regcomp: OK
>>   rt: mismatch: regexec() failed to match
>>   rt: BOL match: OK
>>   rt: ST match: regexec() failed to match
>> 
>> I don't think that change is intentional, or is it?

> This change is intentional.  You try to match y on the start of the
> string.  This falsely succeeds in the current library, but is fixed
> in my change.

Since this is an intentional change of the way the library works,
i think the following is needed:

 1. It ought to be separate from fixing sed(1).
Mixing interface changes of libraries with bug fixes
in programs using them seems like a bad idea to me.

 2. We need a rationale why the change is useful in general,
not just for sed(1), and why we think that nobody relies on the
current interface definition, or how programs that rely on the
current behaviour can be found and adjusted to work with the
new behaviour.

 3. There should be a list explaining how other implementations
behave in this respect, in particular FreeBSD, NetBSD,
DragonFly, glibc, illumos or Solaris, and maybe some other
commercial Unixes.

 4. The library must be kept consistent.  For example, you only
change the treatment of "^" and "\<", but leave "$" and "\>"
unchanged, see the test program below.  That is unlikely to
be the only inconsistency you introduce.  In the function
backref(), there are multiple references to beginp in the
immediate vicinity of REG_NOTBOL and ISWORD.  I did not
check the details, but i fear that your change introduces
a second inconsistency between the treatment of anchors
inside and outside of backreferences.  These are just two
examples of (potential) inconsistencies, we have to convince
ourselves there aren't more.

 5. The change needs to be documented.  It blantantly contradicts
what the manual currently says.  The regular expression
manuals are among the most precise we have, and we should
really keep that level of perfection.

I'm not saying we don't want such a change, nor am i saying we want
it, but as it stands, the patch is inconsistent, incomplete, and
mixed up with unrelated stuff, so it is not OK.

Yours,
  Ingo


#include 
#include 
#include 

static regex_t   re;

static int
report(int errcode, const char *msg)
{
const size_t errbuf_size = 2048;
char errbuf[errbuf_size];
size_t   sz;

if (errcode) {
sz = regerror(errcode, , errbuf, errbuf_size);
warnx("%s: %s%s", msg, errbuf,
sz > errbuf_size ? "[...]" : "");
} else
warnx("%s: OK", msg);
return errcode;
}

int
main(void)
{
regmatch_t   pmatch;

if (report(regcomp(, "y$", REG_EXTENDED), "regcomp"))
return 1;

report(regexec(, "yz", 0, NULL, 0), "mismatch");
report(regexec(, "xy", 0, NULL, 0), "EOL match");

pmatch.rm_so = 1;
pmatch.rm_eo = 2;

report(regexec(, "xyz", 0, , REG_STARTEND), "SE match");
return 0;
}



malloc: fix setting errno on out-of-memory

2016-05-10 Thread Daniel Micay
The ENOMEM errno wasn't being set in some code paths where it was gated
behind mopts.malloc_xmalloc:

diff --git a/stdlib/malloc.c b/stdlib/malloc.c
index bc328d2..aa6f0a3 100644
--- a/stdlib/malloc.c
+++ b/stdlib/malloc.c
@@ -1224,8 +1224,9 @@ malloc(size_t size)
r = omalloc(d, size, 0, CALLER);
d->active--;
_MALLOC_UNLOCK();
-   if (r == NULL && mopts.malloc_xmalloc) {
-   wrterror(d, "out of memory", NULL);
+   if (r == NULL) {
+   if (mopts.malloc_xmalloc)
+   wrterror(d, "out of memory", NULL);
errno = ENOMEM;
}
if (r != NULL)
@@ -1510,8 +1511,9 @@ realloc(void *ptr, size_t size)
 
d->active--;
_MALLOC_UNLOCK();
-   if (r == NULL && mopts.malloc_xmalloc) {
-   wrterror(d, "out of memory", NULL);
+   if (r == NULL) {
+   if (mopts.malloc_xmalloc)
+   wrterror(d, "out of memory", NULL);
errno = ENOMEM;
}
if (r != NULL)
@@ -1563,8 +1565,9 @@ calloc(size_t nmemb, size_t size)
 
d->active--;
_MALLOC_UNLOCK();
-   if (r == NULL && mopts.malloc_xmalloc) {
-   wrterror(d, "out of memory", NULL);
+   if (r == NULL) {
+   if (mopts.malloc_xmalloc)
+   wrterror(d, "out of memory", NULL);
errno = ENOMEM;
}
if (r != NULL)
@@ -1694,10 +1697,9 @@ posix_memalign(void **memptr, size_t alignment, size_t 
size)
d->active--;
_MALLOC_UNLOCK();
if (r == NULL) {
-   if (mopts.malloc_xmalloc) {
+   if (mopts.malloc_xmalloc)
wrterror(d, "out of memory", NULL);
-   errno = ENOMEM;
-   }
+   errno = ENOMEM;
goto err;
}
errno = saved_errno;
-- 
2.8.2



Re: sed/regcomp bug?

2016-05-10 Thread Martijn van Duren
On 05/10/16 19:29, Ingo Schwarze wrote:
> Hi Martijn,
> 
> Martijn van Duren wrote on Tue, May 10, 2016 at 02:43:54PM +0200:
> 
>> Index: ./lib/libc/regex/engine.c
>> ===
>> RCS file: /cvs/src/lib/libc/regex/engine.c,v
>> retrieving revision 1.19
>> diff -u -p -r1.19 engine.c
>> --- ./lib/libc/regex/engine.c28 Dec 2015 23:01:22 -  1.19
>> +++ ./lib/libc/regex/engine.c2 May 2016 08:50:20 -
>> @@ -674,7 +674,7 @@ fast(struct match *m, char *start, char 
>>  states fresh = m->fresh;
>>  states tmp = m->tmp;
>>  char *p = start;
>> -int c = (start == m->beginp) ? OUT : *(start-1);
>> +int c = (start == m->offp) ? OUT : *(start-1);
>>  int lastc;  /* previous c */
>>  int flagch;
>>  int i;
>> @@ -758,7 +758,7 @@ slow(struct match *m, char *start, char 
>>  states empty = m->empty;
>>  states tmp = m->tmp;
>>  char *p = start;
>> -int c = (start == m->beginp) ? OUT : *(start-1);
>> +int c = (start == m->offp) ? OUT : *(start-1);
>>  int lastc;  /* previous c */
>>  int flagch;
>>  int i;
> 
> i hate to say that this change appears to cause a regression.
> 
> The regexec(3) manual explicitly says:
> 
>   REG_STARTENDThe string is considered to start at [...]
>   Note that a non-zero rm_so does not imply REG_NOTBOL;
>   REG_STARTEND affects only the location of the string,
>   not how it is matched.
> 
> Right now, the library actually implements that.  The test program
> appended below produces the following output, as documented:
> 
>   rt: regcomp: OK
>   rt: mismatch: regexec() failed to match
>   rt: BOL match: OK
>   rt: ST match: OK
> 
> With your change, the library now fails to match:
> 
>   rt: regcomp: OK
>   rt: mismatch: regexec() failed to match
>   rt: BOL match: OK
>   rt: ST match: regexec() failed to match
> 
> I don't think that change is intentional, or is it?

This change is intentional. You try to match y on the start of the
string. This falsely succeeds in the current library, but is fixed in my
change.

This needs to be fixed for my sed change to work correctly.
> 
> I'll have a look whether it is possible to conditionally pass
> REG_NOTBOL from sed(1) to solve your original issue.  I didn't
> look into the sed(1) code yet because i wanted to report this
> regression as soon as i found it.
> 
> Yours,
>   Ingo
> 
> 
> #include 
> #include 
> #include 
> 
> static regex_t re;
> 
> static int
> report(int errcode, const char *msg)
> {
>   const size_t errbuf_size = 2048;
>   char errbuf[errbuf_size];
>   size_t   sz;
> 
>   if (errcode) {
>   sz = regerror(errcode, , errbuf, errbuf_size);
>   warnx("%s: %s%s", msg, errbuf,
>   sz > errbuf_size ? "[...]" : "");
>   } else
>   warnx("%s: OK", msg);
>   return errcode;
> }
> 
> int
> main(void)
> {
>   regmatch_t   pmatch;
> 
>   if (report(regcomp(, "^y", REG_EXTENDED), "regcomp"))
>   return 1;
> 
>   report(regexec(, "xy", 0, NULL, 0), "mismatch");
>   report(regexec(, "yz", 0, NULL, 0), "BOL match");
> 
>   pmatch.rm_so = 1;
>   pmatch.rm_eo = 2;
> 
>   report(regexec(, "xyz", 0, , REG_STARTEND), "ST match");
>   return 0;
> }
> 



Re: sed/regcomp bug?

2016-05-10 Thread Ingo Schwarze
Hi Martijn,

Martijn van Duren wrote on Tue, May 10, 2016 at 02:43:54PM +0200:

> Index: ./lib/libc/regex/engine.c
> ===
> RCS file: /cvs/src/lib/libc/regex/engine.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 engine.c
> --- ./lib/libc/regex/engine.c 28 Dec 2015 23:01:22 -  1.19
> +++ ./lib/libc/regex/engine.c 2 May 2016 08:50:20 -
> @@ -674,7 +674,7 @@ fast(struct match *m, char *start, char 
>   states fresh = m->fresh;
>   states tmp = m->tmp;
>   char *p = start;
> - int c = (start == m->beginp) ? OUT : *(start-1);
> + int c = (start == m->offp) ? OUT : *(start-1);
>   int lastc;  /* previous c */
>   int flagch;
>   int i;
> @@ -758,7 +758,7 @@ slow(struct match *m, char *start, char 
>   states empty = m->empty;
>   states tmp = m->tmp;
>   char *p = start;
> - int c = (start == m->beginp) ? OUT : *(start-1);
> + int c = (start == m->offp) ? OUT : *(start-1);
>   int lastc;  /* previous c */
>   int flagch;
>   int i;

i hate to say that this change appears to cause a regression.

The regexec(3) manual explicitly says:

  REG_STARTEND  The string is considered to start at [...]
Note that a non-zero rm_so does not imply REG_NOTBOL;
REG_STARTEND affects only the location of the string,
not how it is matched.

Right now, the library actually implements that.  The test program
appended below produces the following output, as documented:

  rt: regcomp: OK
  rt: mismatch: regexec() failed to match
  rt: BOL match: OK
  rt: ST match: OK

With your change, the library now fails to match:

  rt: regcomp: OK
  rt: mismatch: regexec() failed to match
  rt: BOL match: OK
  rt: ST match: regexec() failed to match

I don't think that change is intentional, or is it?

I'll have a look whether it is possible to conditionally pass
REG_NOTBOL from sed(1) to solve your original issue.  I didn't
look into the sed(1) code yet because i wanted to report this
regression as soon as i found it.

Yours,
  Ingo


#include 
#include 
#include 

static regex_t   re;

static int
report(int errcode, const char *msg)
{
const size_t errbuf_size = 2048;
char errbuf[errbuf_size];
size_t   sz;

if (errcode) {
sz = regerror(errcode, , errbuf, errbuf_size);
warnx("%s: %s%s", msg, errbuf,
sz > errbuf_size ? "[...]" : "");
} else
warnx("%s: OK", msg);
return errcode;
}

int
main(void)
{
regmatch_t   pmatch;

if (report(regcomp(, "^y", REG_EXTENDED), "regcomp"))
return 1;

report(regexec(, "xy", 0, NULL, 0), "mismatch");
report(regexec(, "yz", 0, NULL, 0), "BOL match");

pmatch.rm_so = 1;
pmatch.rm_eo = 2;

report(regexec(, "xyz", 0, , REG_STARTEND), "ST match");
return 0;
}



diff: httpd: add client side certificate checks + test

2016-05-10 Thread Jan Klemkow
Hi,

This diff adds client side certificate checks to httpd.  Most parts are
straight forward.  But, to transfer the whole certificate authority
store to the server process through the imsg infrastructure I had to
change this in an chunked transfer.

The Documentation of this feature is included in httpd.conf.5.

This time, I also extend an httpd tls regression tests to use a client
side certificate.  All tests pass :-)

If anything is wrong with this diff, just notify me, I will fix it.

Bye,
Jan

Index: config.c
===
RCS file: /cvs/src/usr.sbin/httpd/config.c,v
retrieving revision 1.45
diff -u -p -r1.45 config.c
--- config.c28 Apr 2016 14:20:11 -  1.45
+++ config.c3 May 2016 19:51:57 -
@@ -236,51 +236,59 @@ config_settls(struct httpd *env, struct 
struct server_config*srv_conf = >srv_conf;
struct tls_configtls;
struct iovec iov[2];
-   size_t   c;
+   size_t   n;
+   char*p;
 
if ((srv_conf->flags & SRVFLAG_TLS) == 0)
return (0);
 
log_debug("%s: configuring TLS for %s", __func__, srv_conf->name);
 
-   if (srv_conf->tls_cert_len != 0) {
-   DPRINTF("%s: sending TLS cert \"%s[%u]\" to %s fd %d", __func__,
-   srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
-   srv->srv_s);
-
-   memset(, 0, sizeof(tls));
-   tls.id = srv_conf->id;
-   tls.tls_cert_len = srv_conf->tls_cert_len;
-
-   c = 0;
-   iov[c].iov_base = 
-   iov[c++].iov_len = sizeof(tls);
-   iov[c].iov_base = srv_conf->tls_cert;
-   iov[c++].iov_len = srv_conf->tls_cert_len;
+   if ((p = malloc(srv_conf->tls_ca_len + srv_conf->tls_cert_len +
+   srv_conf->tls_key_len)) == NULL) {
+   log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
+   "`%s'", __func__, srv_conf->name);
+   return (-1);
+   }
 
-   if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
-   log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
-   "`%s'", __func__, srv_conf->name);
-   return (-1);
-   }
+   memcpy(p, srv_conf->tls_ca, srv_conf->tls_ca_len);
+   n = srv_conf->tls_ca_len;
+   memcpy(p + n, srv_conf->tls_cert, srv_conf->tls_cert_len);
+   n += srv_conf->tls_cert_len;
+   memcpy(p + n, srv_conf->tls_key, srv_conf->tls_key_len);
+   n += srv_conf->tls_key_len;
+
+   /* send tls_config structure */
+   memset(, 0, sizeof(tls));
+   tls.id = srv_conf->id;
+   tls.port = srv_conf->port;
+   memcpy(, _conf->ss, sizeof(tls.ss));
+   tls.tls_ca_optional = srv_conf->tls_ca_optional;
+   tls.tls_ca_len = srv_conf->tls_ca_len;
+   tls.tls_cert_len = srv_conf->tls_cert_len;
+   tls.tls_key_len = srv_conf->tls_key_len;
+
+   if (proc_compose(ps, PROC_SERVER, IMSG_CFG_TLS, , sizeof(tls)) != 
0) {
+   log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
+   "`%s'", __func__, srv_conf->name);
+   return (-1);
}
 
-   if (srv_conf->tls_key_len != 0) {
-   DPRINTF("%s: sending TLS key \"%s[%u]\" to %s fd %d", __func__,
-   srv_conf->name, srv_conf->id, ps->ps_title[PROC_SERVER],
-   srv->srv_s);
-
-   memset(, 0, sizeof(tls));
-   tls.id = srv_conf->id;
-   tls.tls_key_len = srv_conf->tls_key_len;
-
-   c = 0;
-   iov[c].iov_base = 
-   iov[c++].iov_len = sizeof(tls);
-   iov[c].iov_base = srv_conf->tls_key;
-   iov[c++].iov_len = srv_conf->tls_key_len;
+   iov[0].iov_base = 
+   iov[0].iov_len = sizeof(tls);
+
+#define MSG_CHUNK_SIZE (MAX_IMSGSIZE - (ssize_t)IMSG_HEADER_SIZE - 
iov[0].iov_len)
+
+   /* transfer in chunks */
+   for (; n > 0; p += MSG_CHUNK_SIZE) {
+   size_t len = n > MSG_CHUNK_SIZE ? MSG_CHUNK_SIZE : n;
+   n -= len;
 
-   if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS, iov, c) != 0) {
+   iov[1].iov_base = p;
+   iov[1].iov_len = len;
+
+   if (proc_composev(ps, PROC_SERVER, IMSG_CFG_TLS_CHNK, iov, 2)
+   != 0) {
log_warn("%s: failed to compose IMSG_CFG_TLS imsg for "
"`%s'", __func__, srv_conf->name);
return (-1);
@@ -555,6 +563,52 @@ config_getserver(struct httpd *env, stru
 }
 
 int
+config_gettls_chunk(struct httpd *env, struct imsg *imsg)
+{
+   struct server_config*srv_conf = NULL;
+   struct tls_configtls_conf;
+   uint8_t *p = imsg->data;
+   

Re: proot: why is it a bigger deal than you think

2016-05-10 Thread Marc Espie
On Tue, May 10, 2016 at 01:48:18PM +, Christian Weisgerber wrote:
> On 2016-05-09, Marc Espie  wrote:
> 
> > So far, I've been underwhelmed by the response to proot. Seems people don't
> > get the picture yet.
> 
> Probably because there has been no coherent explanation what proot
> is, how it works, and how to use it.

NAME
 proot - ports chroot builder

SYNOPSIS
 proot [-B chroot] [-c configfile] [-S srcroot] [key=value ...]

DESCRIPTION
 proot can fill up a chroot directory for ports building usage.  It will
 perform a set of actions that should fill up a destination -B chroot from
 the base system (or an optional -S srcroot).
[...]
 By default, proot will run check_mount, devs, ldconfig, ports_subdirs,
 resolv, write_mk.  It will also run snapshot if a snapshot location is
 provided, or locate otherwise.


(straight from the manpage, those actions are also explained)

Things are still moving a bit, but basically,
proot -B /directory_where_you_want_your_root
should do something reasonable.

I've actually been trimming my config files considerably these past
few days, as most options get sensible defaults.



make patch: more extensive sinclude support

2016-05-10 Thread Marc Espie
Both bmake and gmake support a list of files in include/sinclude 
"systemV style".

Adding this to our make would make us slightly more compatible.

It also allows modern dependency patterns a la

.sinclude ${SRC:R:=.d}

Just went thru a full make build.
could use a few eyes.

The change is straightforward, but the patch a bit long, because I have 
to move the location of Var_Substs... keep it simple in the bsd make case (we
don't want to create syntax by substituting variables). And so the handling
of string intervals trickles down the chain of function.

I refrained from also supporting gmake's glob extension, where they can do
.sinclude *.d

We have the match code in dir_expand.c, but this would be complicated to
mesh with the include directory lookup in resolve_include_filename.

Comments and okays welcome.

Index: parse.c
===
RCS file: /cvs/src/usr.bin/make/parse.c,v
retrieving revision 1.115
diff -u -p -r1.115 parse.c
--- parse.c 22 Dec 2015 21:50:54 -  1.115
+++ parse.c 10 May 2016 14:35:26 -
@@ -149,7 +149,7 @@ static bool handle_undef(const char *);
 #define ParseReadLoopLine(linebuf) Parse_ReadUnparsedLine(linebuf, "for loop")
 static bool handle_bsd_command(Buffer, Buffer, const char *);
 static char *strip_comments(Buffer, const char *);
-static char *resolve_include_filename(const char *, bool);
+static char *resolve_include_filename(const char *, const char *, bool);
 static void handle_include_file(const char *, const char *, bool, bool);
 static bool lookup_bsd_include(const char *);
 static void lookup_sysv_style_include(const char *, const char *, bool);
@@ -1081,13 +1081,13 @@ Parse_AddIncludeDir(const char  *dir)
 }
 
 static char *
-resolve_include_filename(const char *file, bool isSystem)
+resolve_include_filename(const char *file, const char *efile, bool isSystem)
 {
char *fullname;
 
/* Look up system files on the system path first */
if (isSystem) {
-   fullname = Dir_FindFileNoDot(file, systemIncludePath);
+   fullname = Dir_FindFileNoDoti(file, efile, systemIncludePath);
if (fullname)
return fullname;
}
@@ -1107,8 +1107,7 @@ resolve_include_filename(const char *fil
if (slash != NULL) {
char *newName;
 
-   newName = Str_concati(fname, slash, file,
-   strchr(file, '\0'), '/');
+   newName = Str_concati(fname, slash, file, efile, '/');
fullname = Dir_FindFile(newName, userIncludePath);
if (fullname == NULL)
fullname = Dir_FindFile(newName, defaultPath);
@@ -1121,10 +1120,10 @@ resolve_include_filename(const char *fil
/* Now look first on the -I search path, then on the .PATH
 * search path, if not found in a -I directory.
 * XXX: Suffix specific?  */
-   fullname = Dir_FindFile(file, userIncludePath);
+   fullname = Dir_FindFilei(file, efile, userIncludePath);
if (fullname)
return fullname;
-   fullname = Dir_FindFile(file, defaultPath);
+   fullname = Dir_FindFilei(file, efile, defaultPath);
if (fullname)
return fullname;
 
@@ -1133,25 +1132,19 @@ resolve_include_filename(const char *fil
if (isSystem)
return NULL;
else
-   return Dir_FindFile(file, systemIncludePath);
+   return Dir_FindFilei(file, efile, systemIncludePath);
 }
 
 static void
-handle_include_file(const char *name, const char *ename, bool isSystem,
+handle_include_file(const char *file, const char *efile, bool isSystem,
 bool errIfNotFound)
 {
-   char *file;
char *fullname;
 
-   /* Substitute for any variables in the file name before trying to
-* find the thing. */
-   file = Var_Substi(name, ename, NULL, false);
-
-   fullname = resolve_include_filename(file, isSystem);
+   fullname = resolve_include_filename(file, efile, isSystem);
if (fullname == NULL && errIfNotFound)
-   Parse_Error(PARSE_FATAL, "Could not find %s", file);
-   free(file);
-
+   Parse_Error(PARSE_FATAL, "Could not find %s", 
+   Str_dupi(file, efile));
 
if (fullname != NULL) {
FILE *f;
@@ -1170,6 +1163,7 @@ lookup_bsd_include(const char *file)
 {
char endc;
const char *efile;
+   char *file2;
bool isSystem;
 
/* find starting delimiter */
@@ -1197,30 +1191,48 @@ lookup_bsd_include(const char *file)
return false;
}
}
-   handle_include_file(file, efile, isSystem, true);
+   /* Substitute for any variables in the file name before trying to
+* find the thing. */
+   file2 = Var_Substi(file, efile, NULL, false);
+   

Re: proot: why is it a bigger deal than you think

2016-05-10 Thread Christian Weisgerber
On 2016-05-09, Marc Espie  wrote:

> So far, I've been underwhelmed by the response to proot. Seems people don't
> get the picture yet.

Probably because there has been no coherent explanation what proot
is, how it works, and how to use it.

-- 
Christian "naddy" Weisgerber  na...@mips.inka.de



Re: sed/regcomp bug?

2016-05-10 Thread Martijn van Duren
ping

any OKs?

On 05/05/16 00:17, Martijn van Duren wrote:
> Hello tech@,
> 
> On 04/23/16 07:21, Jonathan Gray wrote on bugs@:
>> $ cat foo.sh
>> #!/bin/sh
>>
>> $1 -r '
>> s/[[:space:]]//g
>> s/\> '
>> $ cat foo.csv
>> R32G32B32A32_FLOAT  , 128,  1,  1,  1, sf32, sf32, sf32, sf32, , 
>> ,, linear,
>> $ ./foo.sh sed < foo.csv 
>> R32G32B32A32_FLOAT,128,1,1,1,ISL_SFLOAT@32,sf32,ISL_SFLOAT@32,sf32linear,
>> $ ./foo.sh gsed < foo.csv
>> R32G32B32A32_FLOAT,128,1,1,1,ISL_SFLOAT@32,ISL_SFLOAT@32,ISL_SFLOAT@32,ISL_SFLOAT@32linear,
>>
>> Encountered with code that was recently added to Mesa:
>>
>> https://cgit.freedesktop.org/mesa/mesa/tree/src/intel/isl/isl_format_layout_gen.bash
>>
> 
> After a long discussion with several other developers I came up with
> the following diff. It fixes the bug and also passes both the
> regression tests and a full bulk build (thanks to ajacoutot@).
> 
> I'd like to post it here for wider exposure. Please test to as much sed
> scripts as you can find. Comments and OKs welcome.
> 
> Diff looks sane to jasper@
> 
> For those interested: The problem comes from the fact that the string
> pointer increments to the end of the previous match and is then called
> with the REG_NOTBOL. The REG_NOTBOL combined with a match at the begin
> of the string causes our regex library to treat the word as not begin of
> word.
> The TRE implementation does the reverse and treats this case as if it
> always is begin of word. This causes a similar bug under MacOS:
> $ echo 'foo foofoo' | sed -E 's/\ bar barbar
> 
> I've solved this problem by converting sed to use REG_STARTEND more
> explicitly. Although this isn't a POSIX specified flag, it is already
> used by sed and shouldn't be a problem.
> 
> The patch in engine.c from the library is because beginp is set in 
> matcher to start, so this one always results to true.
> 
> I also tried to set up a testcase with gnu regex, but it turned out that
> they don't set re_nsub after regcomp, so the sed compilation phase fails. 
> After examining gnu sed's code I found that it uses an own internal API 
> not specified by POSIX. 
> 
> Index: ./lib/libc/regex/engine.c
> ===
> RCS file: /cvs/src/lib/libc/regex/engine.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 engine.c
> --- ./lib/libc/regex/engine.c 28 Dec 2015 23:01:22 -  1.19
> +++ ./lib/libc/regex/engine.c 2 May 2016 08:50:20 -
> @@ -674,7 +674,7 @@ fast(struct match *m, char *start, char 
>   states fresh = m->fresh;
>   states tmp = m->tmp;
>   char *p = start;
> - int c = (start == m->beginp) ? OUT : *(start-1);
> + int c = (start == m->offp) ? OUT : *(start-1);
>   int lastc;  /* previous c */
>   int flagch;
>   int i;
> @@ -758,7 +758,7 @@ slow(struct match *m, char *start, char 
>   states empty = m->empty;
>   states tmp = m->tmp;
>   char *p = start;
> - int c = (start == m->beginp) ? OUT : *(start-1);
> + int c = (start == m->offp) ? OUT : *(start-1);
>   int lastc;  /* previous c */
>   int flagch;
>   int i;
> Index: ./usr.bin/sed/process.c
> ===
> RCS file: /cvs/src/usr.bin/sed/process.c,v
> retrieving revision 1.27
> diff -u -p -r1.27 process.c
> --- ./usr.bin/sed/process.c   26 Oct 2015 14:08:47 -  1.27
> +++ ./usr.bin/sed/process.c   2 May 2016 08:50:21 -
> @@ -61,7 +61,8 @@ static SPACE HS, PS, SS;
>  static inline int applies(struct s_command *);
>  static void   flush_appends(void);
>  static void   lputs(char *);
> -static inline int regexec_e(regex_t *, const char *, int, int, size_t);
> +static inline int regexec_e(regex_t *, const char *, int, int, size_t,
> +  size_t);
>  static void   regsub(SPACE *, char *, char *);
>  static intsubstitute(struct s_command *);
>  
> @@ -267,7 +268,7 @@ new:  if (!nflag && !pd)
>   * (lastline, linenumber, ps).
>   */
>  #define  MATCH(a)\
> - (a)->type == AT_RE ? regexec_e((a)->u.r, ps, 0, 1, psl) :   \
> + (a)->type == AT_RE ? regexec_e((a)->u.r, ps, 0, 1, 0, psl) :\
>   (a)->type == AT_LINE ? linenum == (a)->u.l : lastline()
>  
>  /*
> @@ -335,6 +336,7 @@ substitute(struct s_command *cp)
>   regex_t *re;
>   regoff_t slen;
>   int n, lastempty;
> + size_t le = 0;
>   char *s;
>  
>   s = ps;
> @@ -346,7 +348,7 @@ substitute(struct s_command *cp)
>   cp->u.s->maxbref);
>   }
>   }
> - if (!regexec_e(re, s, 0, 0, psl))
> + if (!regexec_e(re, s, 0, 0, 0, psl))
>   return (0);
>  
>   SS.len = 0; /* Clean substitute space. */
> @@ -356,28 +358,29 @@ substitute(struct s_command *cp)
>  
>   

make mbufs in bpf const

2016-05-10 Thread David Gwynne
bpf only reads packets, so we can claim theyre const.

now that we have the caller mark the packet as dropped based on the
return from the tap functions, it simplifies some of the internals
of the bpf code too.

ok?

Index: bpf.c
===
RCS file: /cvs/src/sys/net/bpf.c,v
retrieving revision 1.139
diff -u -p -r1.139 bpf.c
--- bpf.c   14 Apr 2016 08:27:24 -  1.139
+++ bpf.c   10 May 2016 06:42:37 -
@@ -93,7 +93,7 @@ LIST_HEAD(, bpf_d) bpf_d_list;
 void   bpf_allocbufs(struct bpf_d *);
 void   bpf_freed(struct bpf_d *);
 void   bpf_ifname(struct ifnet *, struct ifreq *);
-int_bpf_mtap(caddr_t, struct mbuf *, u_int,
+int_bpf_mtap(caddr_t, const struct mbuf *, u_int,
void (*)(const void *, void *, size_t));
 void   bpf_mcopy(const void *, void *, size_t);
 intbpf_movein(struct uio *, u_int, struct mbuf **,
@@ -1210,14 +1210,14 @@ bpf_mcopy(const void *src_arg, void *dst
  * like bpf_mtap, but copy fn can be given. used by various bpf_mtap*
  */
 int
-_bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction,
+_bpf_mtap(caddr_t arg, const struct mbuf *m, u_int direction,
 void (*cpfn)(const void *, void *, size_t))
 {
struct bpf_if *bp = (struct bpf_if *)arg;
struct srpl_iter i;
struct bpf_d *d;
size_t pktlen, slen;
-   struct mbuf *m0;
+   const struct mbuf *m0;
struct timeval tv;
int gottime = 0;
int drop = 0;
@@ -1271,9 +1271,6 @@ _bpf_mtap(caddr_t arg, struct mbuf *m, u
}
SRPL_LEAVE(, d);
 
-   if (drop)
-   m->m_flags |= M_FILDROP;
-
return (drop);
 }
 
@@ -1281,7 +1278,7 @@ _bpf_mtap(caddr_t arg, struct mbuf *m, u
  * Incoming linkage from device drivers, when packet is in an mbuf chain.
  */
 int
-bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction)
+bpf_mtap(caddr_t arg, const struct mbuf *m, u_int direction)
 {
return _bpf_mtap(arg, m, direction, NULL);
 }
@@ -1296,28 +1293,22 @@ bpf_mtap(caddr_t arg, struct mbuf *m, u_
  * it or keep a pointer to it.
  */
 int
-bpf_mtap_hdr(caddr_t arg, caddr_t data, u_int dlen, struct mbuf *m,
+bpf_mtap_hdr(caddr_t arg, caddr_t data, u_int dlen, const struct mbuf *m,
 u_int direction, void (*cpfn)(const void *, void *, size_t))
 {
-   struct m_hdr mh;
-   struct mbuf *m0;
-   int drop;
+   struct m_hdr mh;
+   const struct mbuf *m0;
 
if (dlen > 0) {
mh.mh_flags = 0;
-   mh.mh_next = m;
+   mh.mh_next = (struct mbuf *)m;
mh.mh_len = dlen;
mh.mh_data = data;
m0 = (struct mbuf *)
} else 
m0 = m;
 
-   drop = _bpf_mtap(arg, m0, direction, cpfn);
-
-   if (m0 != m)
-   m->m_flags |= m0->m_flags & M_FILDROP;
-
-   return (drop);
+   return _bpf_mtap(arg, m0, direction, cpfn);
 }
 
 /*
@@ -1330,7 +1321,7 @@ bpf_mtap_hdr(caddr_t arg, caddr_t data, 
  * it or keep a pointer to it.
  */
 int
-bpf_mtap_af(caddr_t arg, u_int32_t af, struct mbuf *m, u_int direction)
+bpf_mtap_af(caddr_t arg, u_int32_t af, const struct mbuf *m, u_int direction)
 {
u_int32_tafh;
 
@@ -1350,7 +1341,7 @@ bpf_mtap_af(caddr_t arg, u_int32_t af, s
  * it or keep a pointer to it.
  */
 int
-bpf_mtap_ether(caddr_t arg, struct mbuf *m, u_int direction)
+bpf_mtap_ether(caddr_t arg, const struct mbuf *m, u_int direction)
 {
 #if NVLAN > 0
struct ether_vlan_header evh;
Index: bpf.h
===
RCS file: /cvs/src/sys/net/bpf.h,v
retrieving revision 1.55
diff -u -p -r1.55 bpf.h
--- bpf.h   3 Apr 2016 01:37:26 -   1.55
+++ bpf.h   10 May 2016 06:42:37 -
@@ -289,11 +289,11 @@ struct mbuf;
 
 int bpf_validate(struct bpf_insn *, int);
 int bpf_tap(caddr_t, u_char *, u_int, u_int);
-int bpf_mtap(caddr_t, struct mbuf *, u_int);
-int bpf_mtap_hdr(caddr_t, caddr_t, u_int, struct mbuf *, u_int,
+int bpf_mtap(caddr_t, const struct mbuf *, u_int);
+int bpf_mtap_hdr(caddr_t, caddr_t, u_int, const struct mbuf *, u_int,
void (*)(const void *, void *, size_t));
-int bpf_mtap_af(caddr_t, u_int32_t, struct mbuf *, u_int);
-int bpf_mtap_ether(caddr_t, struct mbuf *, u_int);
+int bpf_mtap_af(caddr_t, u_int32_t, const struct mbuf *, u_int);
+int bpf_mtap_ether(caddr_t, const struct mbuf *, u_int);
 voidbpfattach(caddr_t *, struct ifnet *, u_int, u_int);
 voidbpfdetach(struct ifnet *);
 voidbpfilterattach(int);