Re: [PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Kenneth R Westerback
On Wed, Aug 28, 2013 at 09:43:24PM +0200, Maxime Villard wrote:
> On 08/28/13 20:57, Matthew Dempsky wrote:
> > On Wed, Aug 28, 2013 at 5:54 AM, Maxime Villard  wrote:
> >> +   /* Ensure interp is a valid, NUL-terminated string 
> >> */
> >> +   for (n = 0; n < pp->p_filesz; n++) {
> >> +   if (interp[n] == '\0')
> >> +   break;
> >> +   }
> >> +   if (n != pp->p_filesz - 1) {
> >> +   error = ENOEXEC;
> >>  goto bad;
> >>  }
> > 
> > A more concise test would be:
> > 
> >  if (strnlen(interp, pp->p_filesz) != pp->p_filesz - 1) {
> >  error = ENOEXEC;
> >  goto bad;
> >  }
> > 
> 
> Hum you're right, it's better that way
> 
> 
> Index: exec_elf.c
> ===
> RCS file: /cvs/src/sys/kern/exec_elf.c,v
> retrieving revision 1.93
> diff -u -p -r1.93 exec_elf.c
> --- exec_elf.c4 Jul 2013 17:37:05 -   1.93
> +++ exec_elf.c28 Aug 2013 21:14:22 -
> @@ -552,11 +552,16 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
>  
>   for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
>   if (pp->p_type == PT_INTERP && !interp) {
> - if (pp->p_filesz >= MAXPATHLEN)
> + if (pp->p_filesz < 2 || pp->p_filesz >= MAXPATHLEN)

Still think you're depriving yourself of one character out by using
">=" instead of ">".

 Ken

>   goto bad;
>   interp = pool_get(&namei_pool, PR_WAITOK);
>   if ((error = ELFNAME(read_from)(p, epp->ep_vp,
>   pp->p_offset, interp, pp->p_filesz)) != 0) {
> + goto bad;
> + }
> + /* Ensure interp is NUL-terminated and of the expected 
> length */
> + if (strnlen(interp, pp->p_filesz) != pp->p_filesz - 1) {
> + error = ENOEXEC;
>   goto bad;
>   }
>   } else if (pp->p_type == PT_LOAD) {
> 
> 
> It no longer looks like my patch...
> 



Re: [PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Kenneth R Westerback
On Wed, Aug 28, 2013 at 08:44:26PM +0200, Maxime Villard wrote:
> On 08/28/13 16:30, Kenneth R Westerback wrote:
> > On Wed, Aug 28, 2013 at 02:54:11PM +0200, Maxime Villard wrote:
> >> Updated diff, with small tweaks from Andres Perera,
> >>   * int -> size_t, signedness issue, even if it can't be >INT_MAX
> >>   * NULL -> NUL
> >>
> >>
> >> Index: exec_elf.c
> >> ===
> >> RCS file: /cvs/src/sys/kern/exec_elf.c,v
> >> retrieving revision 1.93
> >> diff -u -p -r1.93 exec_elf.c
> >> --- exec_elf.c 4 Jul 2013 17:37:05 -   1.93
> >> +++ exec_elf.c 28 Aug 2013 14:36:58 -
> >> @@ -516,7 +516,7 @@ ELFNAME2(exec,makecmds)(struct proc *p,
> >>int error, i;
> >>char *interp = NULL;
> >>u_long pos = 0, phsize;
> >> -  size_t randomizequota = ELF_RANDOMIZE_LIMIT;
> >> +  size_t n, randomizequota = ELF_RANDOMIZE_LIMIT;
> >>   
> >>if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
> >>return (ENOEXEC);
> >> @@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct proc *p,
> >>   
> >>for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
> >>if (pp->p_type == PT_INTERP && !interp) {
> >> -  if (pp->p_filesz >= MAXPATHLEN)
> >> +  if (pp->p_filesz >= MAXPATHLEN ||
> >> +  pp->p_filesz < 2)
> > 
> > Since p_filesz includes the NUL and MAXPATHLEN includes the NUL as
> > far as I know, could the comparison not be simply '> MAXPATHLEN'?
> > 
> > In passing I note that 37 out of 749 declarations using MAXPATHLEN in the
> > tree use 'char blah[MAXPATHLEN + 1]'. No idea if it is worth looking at
> > making them do without the '+ 1'. :-)
> > 
> > I also note in passing several "#define PATH_MAX (MAXPATHLEN + 1)'
> > declarations, which strike me as odd since MAXPATHLEN is defined
> > in sys/param.h by '#define MAXPATHEN PATH_MAX'.
> > 
> > Let the POSIX lawyers apply any necessary cluebats please.
> > 
> >>goto bad;
> >>interp = pool_get(&namei_pool, PR_WAITOK);
> >>if ((error = ELFNAME(read_from)(p, epp->ep_vp,
> >>pp->p_offset, interp, pp->p_filesz)) != 0) {
> >> +  goto bad;
> >> +  }
> >> +  /* Ensure interp is a valid, NUL-terminated string */
> > 
> > The condition is not that the string is NUL terminated ("aaa\0aaa\0" is 
> > after
> > all NUL terminated and valid as far as any function reading strings would be
> > concerned. It just has trailing garbage.) Perhaps the comment should refer
> > to making sure the string is spec compliant by being of the expected length.
> 
> 
> By 'valid string' I actually meant 'without trailing garbage'... but ok
> if it's not clear
>   /* Ensure interp is NUL-terminated and of the expected length */

That would be clear to me.

 Ken

> 
> 
> > 
> >  Ken
> > 
> >> +  for (n = 0; n < pp->p_filesz; n++) {
> >> +  if (interp[n] == '\0')
> >> +  break;
> >> +  }
> >> +  if (n != pp->p_filesz - 1) {
> >> +  error = ENOEXEC;
> >>goto bad;
> >>}
> >>} else if (pp->p_type == PT_LOAD) {
> >>
> >>
> >>
> >> On 08/28/13 08:44, Maxime Villard wrote:
> >>> Hi,
> >>> in the ELF format, the PT_INTERP segment contains the path of the
> >>> interpreter which must be loaded. For this segment, the kernel looks
> >>> at these values in the program header:
> >>>
> >>>p_offset: offset of the path string
> >>>p_filesz: size of the path string, including the \0
> >>>
> >>> The path string must be a valid string, or the binary won't be loaded.
> >>>
> >>> The kernel actually doesn't check the string, it just reads p_filesz
> >>> bytes from p_offset, and later it checks if it can be loaded. Malformed
> >>> binaries which have paths like:
> >>>
> >>>   "a"
> >>> or
> >>>   "aaa\0aaa\0aaa\0aaa\0"
> >>>
> >>> are parsed, loaded, and then the kernel figures out that the path is
> >>> not valid, and aborts.
> >>>
> >>> When the kernel reads the path from the file, it should check directly
> >>> the string to ensure it is at least a valid string.
> >>>
> >>> Here is a patch for this. For pp->p_filesz, I could have put
> >>>   if (pp->p_filesz == 0)
> >>> but values of 1 also don't make sense; "\0" can't be a valid path.
> >>>
> >>>
> >>>
> >>> Index: exec_elf.c
> >>> ===
> >>> RCS file: /cvs/src/sys/kern/exec_elf.c,v
> >>> retrieving revision 1.93
> >>> diff -u -p -r1.93 exec_elf.c
> >>> --- exec_elf.c4 Jul 2013 17:37:05 -   1.93
> >>> +++ exec_elf.c27 Aug 2013 22:59:21 -
> >>> @@ -513,7 +513,7 @@ ELFNAME2(exec,makecmds)(struct proc *p,
> >>>   Elf_Ehdr *eh = epp->ep_hdr;
> >>>   Elf_Phdr *ph

Re: [PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Maxime Villard
On 08/28/13 20:57, Matthew Dempsky wrote:
> On Wed, Aug 28, 2013 at 5:54 AM, Maxime Villard  wrote:
>> +   /* Ensure interp is a valid, NUL-terminated string */
>> +   for (n = 0; n < pp->p_filesz; n++) {
>> +   if (interp[n] == '\0')
>> +   break;
>> +   }
>> +   if (n != pp->p_filesz - 1) {
>> +   error = ENOEXEC;
>>  goto bad;
>>  }
> 
> A more concise test would be:
> 
>  if (strnlen(interp, pp->p_filesz) != pp->p_filesz - 1) {
>  error = ENOEXEC;
>  goto bad;
>  }
> 

Hum you're right, it's better that way


Index: exec_elf.c
===
RCS file: /cvs/src/sys/kern/exec_elf.c,v
retrieving revision 1.93
diff -u -p -r1.93 exec_elf.c
--- exec_elf.c  4 Jul 2013 17:37:05 -   1.93
+++ exec_elf.c  28 Aug 2013 21:14:22 -
@@ -552,11 +552,16 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
 
for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
if (pp->p_type == PT_INTERP && !interp) {
-   if (pp->p_filesz >= MAXPATHLEN)
+   if (pp->p_filesz < 2 || pp->p_filesz >= MAXPATHLEN)
goto bad;
interp = pool_get(&namei_pool, PR_WAITOK);
if ((error = ELFNAME(read_from)(p, epp->ep_vp,
pp->p_offset, interp, pp->p_filesz)) != 0) {
+   goto bad;
+   }
+   /* Ensure interp is NUL-terminated and of the expected 
length */
+   if (strnlen(interp, pp->p_filesz) != pp->p_filesz - 1) {
+   error = ENOEXEC;
goto bad;
}
} else if (pp->p_type == PT_LOAD) {


It no longer looks like my patch...



Re: Don't iterate on the global list in arp_{request,input}

2013-08-28 Thread Alexander Bluhm
On Wed, Aug 28, 2013 at 03:28:18PM +0200, Martin Pieuchot wrote:
> Like the previous diffs, when we already have the ifp and want one of
> its addresses, iterate on the ifp list instead of the global one.
> 
> Tested with carp here. I appreciate any comment and oks.

I think the code is nicer and does the same.  OK bluhm@

> 
> Index: netinet/if_ether.c
> ===
> RCS file: /cvs/src/sys/netinet/if_ether.c,v
> retrieving revision 1.105
> diff -u -p -r1.105 if_ether.c
> --- netinet/if_ether.c28 Aug 2013 06:58:57 -  1.105
> +++ netinet/if_ether.c28 Aug 2013 07:57:01 -
> @@ -145,7 +145,6 @@ arp_rtrequest(int req, struct rtentry *r
>  {
>   struct sockaddr *gate = rt->rt_gateway;
>   struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
> - struct in_ifaddr *ia;
>   struct ifaddr *ifa;
>   struct mbuf *m;
>  
> @@ -259,13 +258,13 @@ arp_rtrequest(int req, struct rtentry *r
>   rt->rt_flags |= RTF_LLINFO;
>   LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
>  
> - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
> - if (ia->ia_ifp == rt->rt_ifp &&
> - SIN(rt_key(rt))->sin_addr.s_addr ==
> - (IA_SIN(ia))->sin_addr.s_addr)
> + TAILQ_FOREACH(ifa, &rt->rt_ifp->if_addrlist, ifa_list) {
> + if ((ifa->ifa_addr->sa_family == AF_INET) &&
> + ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
> + satosin(rt_key(rt))->sin_addr.s_addr)
>   break;
>   }
> - if (ia) {
> + if (ifa) {
>   /*
>* This test used to be
>*  if (lo0ifp->if_flags & IFF_UP)
> @@ -294,7 +293,6 @@ arp_rtrequest(int req, struct rtentry *r
>* address we are using, otherwise we will have trouble
>* with source address selection.
>*/
> - ifa = &ia->ia_ifa;
>   if (ifa != rt->rt_ifa) {
>   ifafree(rt->rt_ifa);
>   ifa->ifa_refcnt++;
> @@ -562,11 +560,12 @@ void
>  in_arpinput(struct mbuf *m)
>  {
>   struct ether_arp *ea;
> - struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
> + struct ifnet *ifp = m->m_pkthdr.rcvif;
> + struct arpcom *ac = (struct arpcom *)ifp;
>   struct ether_header *eh;
>   struct llinfo_arp *la = 0;
>   struct rtentry *rt;
> - struct in_ifaddr *ia;
> + struct ifaddr *ifa;
>   struct sockaddr_dl *sdl;
>   struct sockaddr sa;
>   struct in_addr isaddr, itaddr, myaddr;
> @@ -593,57 +592,55 @@ in_arpinput(struct mbuf *m)
>   bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof(isaddr));
>  
>   /* First try: check target against our addresses */
> - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
> - if (itaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
> + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
> + if (ifa->ifa_addr->sa_family != AF_INET)
> + continue;
> +
> + if (itaddr.s_addr != ifatoia(ifa)->ia_addr.sin_addr.s_addr)
>   continue;
>  
>  #if NCARP > 0
> - if (ia->ia_ifp->if_type == IFT_CARP &&
> - ((ia->ia_ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
> + if (ifp->if_type == IFT_CARP &&
> + ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
>   (IFF_UP|IFF_RUNNING))) {
> - if (ia->ia_ifp == m->m_pkthdr.rcvif) {
> - if (op == ARPOP_REPLY)
> - break;
> - if (carp_iamatch(ia, ea->arp_sha,
> - &enaddr, ðer_shost))
> - break;
> - else
> - goto out;
> - }
> - } else
> -#endif
> - if (ia->ia_ifp == m->m_pkthdr.rcvif)
> + if (op == ARPOP_REPLY)
> + break;
> + if (carp_iamatch(ifatoia(ifa), ea->arp_sha,
> + &enaddr, ðer_shost))
>   break;
> + else
> + goto out;
> + }
> +#endif
> + break;
>   }
>  
>   /* Second try: check source against our addresses */
> - if (ia == NULL) {
> - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
> - if (isaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
> + if (ifa == NULL) {
> + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
> + if (ifa->ifa_addr->sa_family != AF_INET)
>   

Re: [PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Matthew Dempsky
On Wed, Aug 28, 2013 at 5:54 AM, Maxime Villard  wrote:
> +   /* Ensure interp is a valid, NUL-terminated string */
> +   for (n = 0; n < pp->p_filesz; n++) {
> +   if (interp[n] == '\0')
> +   break;
> +   }
> +   if (n != pp->p_filesz - 1) {
> +   error = ENOEXEC;
> goto bad;
> }

A more concise test would be:

if (strnlen(interp, pp->p_filesz) != pp->p_filesz - 1) {
error = ENOEXEC;
goto bad;
}



Re: [PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Maxime Villard
On 08/28/13 16:30, Kenneth R Westerback wrote:
> On Wed, Aug 28, 2013 at 02:54:11PM +0200, Maxime Villard wrote:
>> Updated diff, with small tweaks from Andres Perera,
>>   * int -> size_t, signedness issue, even if it can't be >INT_MAX
>>   * NULL -> NUL
>>
>>
>> Index: exec_elf.c
>> ===
>> RCS file: /cvs/src/sys/kern/exec_elf.c,v
>> retrieving revision 1.93
>> diff -u -p -r1.93 exec_elf.c
>> --- exec_elf.c   4 Jul 2013 17:37:05 -   1.93
>> +++ exec_elf.c   28 Aug 2013 14:36:58 -
>> @@ -516,7 +516,7 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>>  int error, i;
>>  char *interp = NULL;
>>  u_long pos = 0, phsize;
>> -size_t randomizequota = ELF_RANDOMIZE_LIMIT;
>> +size_t n, randomizequota = ELF_RANDOMIZE_LIMIT;
>>   
>>  if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
>>  return (ENOEXEC);
>> @@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>>   
>>  for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
>>  if (pp->p_type == PT_INTERP && !interp) {
>> -if (pp->p_filesz >= MAXPATHLEN)
>> +if (pp->p_filesz >= MAXPATHLEN ||
>> +pp->p_filesz < 2)
> 
> Since p_filesz includes the NUL and MAXPATHLEN includes the NUL as
> far as I know, could the comparison not be simply '> MAXPATHLEN'?
> 
> In passing I note that 37 out of 749 declarations using MAXPATHLEN in the
> tree use 'char blah[MAXPATHLEN + 1]'. No idea if it is worth looking at
> making them do without the '+ 1'. :-)
> 
> I also note in passing several "#define PATH_MAX (MAXPATHLEN + 1)'
> declarations, which strike me as odd since MAXPATHLEN is defined
> in sys/param.h by '#define MAXPATHEN PATH_MAX'.
> 
> Let the POSIX lawyers apply any necessary cluebats please.
> 
>>  goto bad;
>>  interp = pool_get(&namei_pool, PR_WAITOK);
>>  if ((error = ELFNAME(read_from)(p, epp->ep_vp,
>>  pp->p_offset, interp, pp->p_filesz)) != 0) {
>> +goto bad;
>> +}
>> +/* Ensure interp is a valid, NUL-terminated string */
> 
> The condition is not that the string is NUL terminated ("aaa\0aaa\0" is after
> all NUL terminated and valid as far as any function reading strings would be
> concerned. It just has trailing garbage.) Perhaps the comment should refer
> to making sure the string is spec compliant by being of the expected length.


By 'valid string' I actually meant 'without trailing garbage'... but ok
if it's not clear
/* Ensure interp is NUL-terminated and of the expected length */


> 
>  Ken
> 
>> +for (n = 0; n < pp->p_filesz; n++) {
>> +if (interp[n] == '\0')
>> +break;
>> +}
>> +if (n != pp->p_filesz - 1) {
>> +error = ENOEXEC;
>>  goto bad;
>>  }
>>  } else if (pp->p_type == PT_LOAD) {
>>
>>
>>
>> On 08/28/13 08:44, Maxime Villard wrote:
>>> Hi,
>>> in the ELF format, the PT_INTERP segment contains the path of the
>>> interpreter which must be loaded. For this segment, the kernel looks
>>> at these values in the program header:
>>>
>>>p_offset: offset of the path string
>>>p_filesz: size of the path string, including the \0
>>>
>>> The path string must be a valid string, or the binary won't be loaded.
>>>
>>> The kernel actually doesn't check the string, it just reads p_filesz
>>> bytes from p_offset, and later it checks if it can be loaded. Malformed
>>> binaries which have paths like:
>>>
>>> "a"
>>> or
>>> "aaa\0aaa\0aaa\0aaa\0"
>>>
>>> are parsed, loaded, and then the kernel figures out that the path is
>>> not valid, and aborts.
>>>
>>> When the kernel reads the path from the file, it should check directly
>>> the string to ensure it is at least a valid string.
>>>
>>> Here is a patch for this. For pp->p_filesz, I could have put
>>> if (pp->p_filesz == 0)
>>> but values of 1 also don't make sense; "\0" can't be a valid path.
>>>
>>>
>>>
>>> Index: exec_elf.c
>>> ===
>>> RCS file: /cvs/src/sys/kern/exec_elf.c,v
>>> retrieving revision 1.93
>>> diff -u -p -r1.93 exec_elf.c
>>> --- exec_elf.c  4 Jul 2013 17:37:05 -   1.93
>>> +++ exec_elf.c  27 Aug 2013 22:59:21 -
>>> @@ -513,7 +513,7 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>>> Elf_Ehdr *eh = epp->ep_hdr;
>>> Elf_Phdr *ph, *pp, *base_ph = NULL;
>>> Elf_Addr phdr = 0, exe_base = 0;
>>> -   int error, i;
>>> +   int error, i, n;
>>> char *interp = NULL;
>>> u_long pos = 0, phsize;
>>> size_t randomizequota = ELF_RANDOMIZE_LIMIT;
>>> @@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct pro

games/trek: fix for tournament mode

2013-08-28 Thread Christian Weisgerber
trek(6)'s tournament mode is intended to have deterministic "random"
numbers based on a password.  This was broken 15 years ago when
rand() was changed to random(), but the initial srand() was forgotten.

ok?

Index: setup.c
===
RCS file: /cvs/src/games/trek/setup.c,v
retrieving revision 1.8
diff -u -p -r1.8 setup.c
--- setup.c 27 Oct 2009 23:59:27 -  1.8
+++ setup.c 28 Aug 2013 17:43:54 -
@@ -105,7 +105,7 @@ setup()
d = 0;
for (i = 0; Game.passwd[i]; i++)
d += Game.passwd[i] << i;
-   srand(d);
+   srandom(d);
}
Param.bases = Now.bases = ranf(6 - Game.skill) + 2;
if (Game.skill == 6)
-- 
Christian "naddy" Weisgerber  na...@mips.inka.de



arc4random for src/games

2013-08-28 Thread Christian Weisgerber
This replaces srandomdev()+random() with calls to arc4random*() in
src/games.  There isn't much practical benefit to this.  Consider
it a style fix.

I have NOT touched the games that call srandom() with a particular seed
for deterministic gameplay.

Index: arithmetic/arithmetic.c
===
RCS file: /cvs/src/games/arithmetic/arithmetic.c,v
retrieving revision 1.17
diff -u -p -r1.17 arithmetic.c
--- arithmetic/arithmetic.c 27 Oct 2009 23:59:23 -  1.17
+++ arithmetic/arithmetic.c 28 Aug 2013 14:30:16 -
@@ -124,9 +124,6 @@ main(int argc, char *argv[])
if (argc -= optind)
usage();
 
-   /* Seed the random-number generator. */
-   srandomdev();
-
(void)signal(SIGINT, intr);
 
/* Now ask the questions. */
@@ -177,7 +174,7 @@ problem(void)
int left, op, right, result;
char line[80];
 
-   op = keys[random() % nkeys];
+   op = keys[arc4random_uniform(nkeys)];
if (op != '/')
right = getrandom(rangemax + 1, op, 1);
 retry:
@@ -198,7 +195,7 @@ retry:
case '/':
right = getrandom(rangemax, op, 1) + 1;
result = getrandom(rangemax + 1, op, 0);
-   left = right * result + random() % right;
+   left = right * result + arc4random_uniform(right);
break;
}
 
@@ -308,7 +305,7 @@ getrandom(int maxval, int op, int operan
struct penalty **pp, *p;
 
op = opnum(op);
-   value = random() % (maxval + penalty[op][operand]);
+   value = arc4random_uniform(maxval + penalty[op][operand]);
 
/*
 * 0 to maxval - 1 is a number to be used directly; bigger values
Index: backgammon/backgammon/main.c
===
RCS file: /cvs/src/games/backgammon/backgammon/main.c,v
retrieving revision 1.16
diff -u -p -r1.16 main.c
--- backgammon/backgammon/main.c27 Oct 2009 23:59:23 -  1.16
+++ backgammon/backgammon/main.c28 Aug 2013 14:34:54 -
@@ -100,7 +100,6 @@ main (argc,argv)
 
/* use whole screen for text */
begscr = 0;
-   srandomdev();   /* seed random number generator */
 
getarg(argc, argv);
args[acnt] = '\0';
Index: backgammon/common_source/back.h
===
RCS file: /cvs/src/games/backgammon/common_source/back.h,v
retrieving revision 1.11
diff -u -p -r1.11 back.h
--- backgammon/common_source/back.h 14 Dec 2006 10:14:05 -  1.11
+++ backgammon/common_source/back.h 28 Aug 2013 14:35:11 -
@@ -43,7 +43,7 @@
 #include 
 #include 
 
-#define rnum(r)(random()%r)
+#define rnum(r)arc4random_uniform(r)
 #define D0 dice[0]
 #define D1 dice[1]
 #define swap   {D0 ^= D1; D1 ^= D0; D0 ^= D1; d0 = 1-d0;}
Index: battlestar/extern.h
===
RCS file: /cvs/src/games/battlestar/extern.h,v
retrieving revision 1.14
diff -u -p -r1.14 extern.h
--- battlestar/extern.h 5 Apr 2013 01:28:27 -   1.14
+++ battlestar/extern.h 28 Aug 2013 14:36:46 -
@@ -49,7 +49,7 @@
 #define BITS (8 * sizeof (int))
 
 #define OUTSIDE(position > 68 && position < 246 && position != 
218)
-#define rnd(x) (random() % (x))
+#define rnd(x) arc4random_uniform(x)
 #define max(a,b)   ((a) < (b) ? (b) : (a))
  /* avoid name collision with sys/param.h */
 #define TestBit(array, index)  (array[index/BITS] & (1 << (index % BITS)))
Index: battlestar/init.c
===
RCS file: /cvs/src/games/battlestar/init.c,v
retrieving revision 1.13
diff -u -p -r1.13 init.c
--- battlestar/init.c   27 Oct 2009 23:59:24 -  1.13
+++ battlestar/init.c   28 Aug 2013 14:37:03 -
@@ -46,7 +46,6 @@ initialize(const char *filename)
puts("First Adventure game written by His Lordship, the honorable");
puts("Admiral D.W. Riggle\n");
location = dayfile;
-   srandomdev();
username = getutmp();
if (username == NULL)
errx(1, "Don't know who you are.");
Index: bs/bs.c
===
RCS file: /cvs/src/games/bs/bs.c,v
retrieving revision 1.23
diff -u -p -r1.23 bs.c
--- bs/bs.c 14 Nov 2009 02:20:43 -  1.23
+++ bs/bs.c 28 Aug 2013 14:39:39 -
@@ -39,8 +39,6 @@
  * v2.2 with bugfixes and strategical improvements, March 1998.
  */
 
-/* #define _POSIX_SOURCE  */  /* ( random() ) */
-
 #include 
 #include 
 #include 
@@ -235,8 +233,6 @@ static void intro(void)
 {
 char *tmpname;
 
-srandomdev();  /* Kick the random number generator */
-
 (void) signal(SIGINT,uninitgame);
 (void) signal(SIGINT,uninitgame);
 if(signal(SIGQUIT,SIG_IGN) != SIG_IGN)
@@ -344,7 +340,7 @@ static void placeship(int b, shi

Re: missing bit in audio.4 ?

2013-08-28 Thread Jason McIntyre
On Wed, Aug 28, 2013 at 09:27:59AM +0200, Remco wrote:
> Index: audio.4
> ===
> RCS file: /home/cvs/src/share/man/man4/audio.4,v
> retrieving revision 1.62
> diff -u -r1.62 audio.4
> --- audio.4   15 Jul 2010 03:43:11 -  1.62
> +++ audio.4   28 Aug 2013 07:22:57 -
> @@ -154,7 +154,7 @@
>  .Va buffer_size
>  (as available via
>  .Dv AUDIO_GETINFO ) .
> -The device driver will continuously move data from this buffer
> +The device driver will continuously move data to/from this buffer
>  from/to the audio hardware, wrapping around at the end of the buffer.
>  To find out where the hardware is currently accessing data in the buffer the
>  .Dv AUDIO_GETIOFFS
> 

i've fixed this by rewording it a bit, so that it reads better. i sat
there thinking 2xto/from is a weird construction...there's gotta be a
better way ;)

jmc

Index: audio.4
===
RCS file: /cvs/src/share/man/man4/audio.4,v
retrieving revision 1.62
diff -u -r1.62 audio.4
--- audio.4 15 Jul 2010 03:43:11 -  1.62
+++ audio.4 28 Aug 2013 16:18:35 -
@@ -154,8 +154,8 @@
 .Va buffer_size
 (as available via
 .Dv AUDIO_GETINFO ) .
-The device driver will continuously move data from this buffer
-from/to the audio hardware, wrapping around at the end of the buffer.
+The device driver will continuously move data between this buffer
+and the audio hardware, wrapping around at the end of the buffer.
 To find out where the hardware is currently accessing data in the buffer the
 .Dv AUDIO_GETIOFFS
 and



Re: threaded prof signals

2013-08-28 Thread Ted Unangst
On Fri, Aug 16, 2013 at 02:12, Ted Unangst wrote:
> As per http://research.swtch.com/macpprof
> 
> We deliver all prof signals to the main thread, which is unlikely to
> result in accurate profiling info. I think the diff below fixes things.

floating this again. note that it's not the clock being made per
thread, just the timeout, which is only used to move signal delivery
from hardclock to softclock.

> 
> Index: kern/kern_clock.c
> ===
> RCS file: /cvs/src/sys/kern/kern_clock.c,v
> retrieving revision 1.81
> diff -u -p -r1.81 kern_clock.c
> --- kern/kern_clock.c 24 Apr 2013 17:29:02 -  1.81
> +++ kern/kern_clock.c 16 Aug 2013 05:57:27 -
> @@ -173,9 +173,9 @@ virttimer_trampoline(void *v)
> void
> proftimer_trampoline(void *v)
> {
> - struct process *pr = v;
> + struct proc *p = v;
> 
> - psignal(pr->ps_mainproc, SIGPROF);
> + psignal(p, SIGPROF);
> }
> 
> /*
> @@ -200,7 +200,7 @@ hardclock(struct clockframe *frame)
> timeout_add(&pr->ps_virt_to, 1);
> if (timerisset(&pr->ps_timer[ITIMER_PROF].it_value) &&
> itimerdecr(&pr->ps_timer[ITIMER_PROF], tick) == 0)
> - timeout_add(&pr->ps_prof_to, 1);
> + timeout_add(&p->p_prof_to, 1);
> }
> 
> /*
> Index: kern/kern_exit.c
> ===
> RCS file: /cvs/src/sys/kern/kern_exit.c,v
> retrieving revision 1.125
> diff -u -p -r1.125 kern_exit.c
> --- kern/kern_exit.c  5 Jun 2013 00:53:26 -   1.125
> +++ kern/kern_exit.c  16 Aug 2013 05:57:27 -
> @@ -183,10 +183,10 @@ exit1(struct proc *p, int rv, int flags)
> */
> fdfree(p);
> 
> + timeout_del(&p->p_prof_to);
> if ((p->p_flag & P_THREAD) == 0) {
> timeout_del(&pr->ps_realit_to);
> timeout_del(&pr->ps_virt_to);
> - timeout_del(&pr->ps_prof_to);
> #ifdef SYSVSEM
> semexit(pr);
> #endif
> Index: kern/kern_fork.c
> ===
> RCS file: /cvs/src/sys/kern/kern_fork.c,v
> retrieving revision 1.152
> diff -u -p -r1.152 kern_fork.c
> --- kern/kern_fork.c  11 Jun 2013 13:00:31 -  1.152
> +++ kern/kern_fork.c  16 Aug 2013 05:57:27 -
> @@ -209,7 +209,6 @@ process_new(struct proc *p, struct proce
> 
> timeout_set(&pr->ps_realit_to, realitexpire, pr);
> timeout_set(&pr->ps_virt_to, virttimer_trampoline, pr);
> - timeout_set(&pr->ps_prof_to, proftimer_trampoline, pr);
> 
> pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC);
> if (parent->ps_session->s_ttyvp != NULL &&
> @@ -342,6 +341,7 @@ fork1(struct proc *curp, int exitsig, in
> * Initialize the timeouts.
> */
> timeout_set(&p->p_sleep_to, endtsleep, p);
> + timeout_set(&p->p_prof_to, proftimer_trampoline, p);
> 
> /*
> * Duplicate sub-structures as needed.
> Index: kern/kern_time.c
> ===
> RCS file: /cvs/src/sys/kern/kern_time.c,v
> retrieving revision 1.80
> diff -u -p -r1.80 kern_time.c
> --- kern/kern_time.c  17 Jun 2013 19:11:54 -  1.80
> +++ kern/kern_time.c  16 Aug 2013 05:57:27 -
> @@ -568,7 +568,7 @@ sys_setitimer(struct proc *p, void *v, r
> if (which == ITIMER_VIRTUAL)
> timeout_del(&pr->ps_virt_to);
> if (which == ITIMER_PROF)
> - timeout_del(&pr->ps_prof_to);
> + timeout_del(&p->p_prof_to);
> splx(s);
> }
> 
> Index: sys/proc.h
> ===
> RCS file: /cvs/src/sys/sys/proc.h,v
> retrieving revision 1.168
> diff -u -p -r1.168 proc.h
> --- sys/proc.h6 Jun 2013 13:09:37 -   1.168
> +++ sys/proc.h16 Aug 2013 05:57:28 -
> @@ -210,7 +210,6 @@ struct process {
> structtimespec ps_start;  /* starting time. */
> structtimeout ps_realit_to;   /* real-time itimer trampoline. */
> structtimeout ps_virt_to; /* virtual itimer trampoline. */
> - struct  timeout ps_prof_to; /* prof itimer trampoline. */
> 
> int   ps_refcnt;  /* Number of references. */
> };
> @@ -337,6 +336,7 @@ struct proc {
> /* End area that is copied on creation. */
> #define   p_endcopy   p_addr
> 
> + struct  timeout p_prof_to;  /* prof itimer trampoline. */
> structuser *p_addr;   /* Kernel virtual addr of u-area */
> structmdproc p_md;/* Any machine-dependent fields. */



Re: [PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Kenneth R Westerback
On Wed, Aug 28, 2013 at 02:54:11PM +0200, Maxime Villard wrote:
> Updated diff, with small tweaks from Andres Perera,
>  * int -> size_t, signedness issue, even if it can't be >INT_MAX
>  * NULL -> NUL
> 
> 
> Index: exec_elf.c
> ===
> RCS file: /cvs/src/sys/kern/exec_elf.c,v
> retrieving revision 1.93
> diff -u -p -r1.93 exec_elf.c
> --- exec_elf.c4 Jul 2013 17:37:05 -   1.93
> +++ exec_elf.c28 Aug 2013 14:36:58 -
> @@ -516,7 +516,7 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
>   int error, i;
>   char *interp = NULL;
>   u_long pos = 0, phsize;
> - size_t randomizequota = ELF_RANDOMIZE_LIMIT;
> + size_t n, randomizequota = ELF_RANDOMIZE_LIMIT;
>  
>   if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
>   return (ENOEXEC);
> @@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
>  
>   for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
>   if (pp->p_type == PT_INTERP && !interp) {
> - if (pp->p_filesz >= MAXPATHLEN)
> + if (pp->p_filesz >= MAXPATHLEN ||
> + pp->p_filesz < 2)

Since p_filesz includes the NUL and MAXPATHLEN includes the NUL as
far as I know, could the comparison not be simply '> MAXPATHLEN'?

In passing I note that 37 out of 749 declarations using MAXPATHLEN in the
tree use 'char blah[MAXPATHLEN + 1]'. No idea if it is worth looking at
making them do without the '+ 1'. :-)

I also note in passing several "#define PATH_MAX (MAXPATHLEN + 1)'
declarations, which strike me as odd since MAXPATHLEN is defined
in sys/param.h by '#define MAXPATHEN PATH_MAX'.

Let the POSIX lawyers apply any necessary cluebats please.

>   goto bad;
>   interp = pool_get(&namei_pool, PR_WAITOK);
>   if ((error = ELFNAME(read_from)(p, epp->ep_vp,
>   pp->p_offset, interp, pp->p_filesz)) != 0) {
> + goto bad;
> + }
> + /* Ensure interp is a valid, NUL-terminated string */

The condition is not that the string is NUL terminated ("aaa\0aaa\0" is after
all NUL terminated and valid as far as any function reading strings would be
concerned. It just has trailing garbage.) Perhaps the comment should refer
to making sure the string is spec compliant by being of the expected length.

 Ken

> + for (n = 0; n < pp->p_filesz; n++) {
> + if (interp[n] == '\0')
> + break;
> + }
> + if (n != pp->p_filesz - 1) {
> + error = ENOEXEC;
>   goto bad;
>   }
>   } else if (pp->p_type == PT_LOAD) {
> 
> 
> 
> On 08/28/13 08:44, Maxime Villard wrote:
> > Hi,
> > in the ELF format, the PT_INTERP segment contains the path of the
> > interpreter which must be loaded. For this segment, the kernel looks
> > at these values in the program header:
> > 
> >   p_offset: offset of the path string
> >   p_filesz: size of the path string, including the \0
> > 
> > The path string must be a valid string, or the binary won't be loaded.
> > 
> > The kernel actually doesn't check the string, it just reads p_filesz
> > bytes from p_offset, and later it checks if it can be loaded. Malformed
> > binaries which have paths like:
> > 
> > "a"
> > or
> > "aaa\0aaa\0aaa\0aaa\0"
> > 
> > are parsed, loaded, and then the kernel figures out that the path is
> > not valid, and aborts.
> > 
> > When the kernel reads the path from the file, it should check directly
> > the string to ensure it is at least a valid string.
> > 
> > Here is a patch for this. For pp->p_filesz, I could have put
> > if (pp->p_filesz == 0)
> > but values of 1 also don't make sense; "\0" can't be a valid path.
> > 
> > 
> > 
> > Index: exec_elf.c
> > ===
> > RCS file: /cvs/src/sys/kern/exec_elf.c,v
> > retrieving revision 1.93
> > diff -u -p -r1.93 exec_elf.c
> > --- exec_elf.c  4 Jul 2013 17:37:05 -   1.93
> > +++ exec_elf.c  27 Aug 2013 22:59:21 -
> > @@ -513,7 +513,7 @@ ELFNAME2(exec,makecmds)(struct proc *p,
> > Elf_Ehdr *eh = epp->ep_hdr;
> > Elf_Phdr *ph, *pp, *base_ph = NULL;
> > Elf_Addr phdr = 0, exe_base = 0;
> > -   int error, i;
> > +   int error, i, n;
> > char *interp = NULL;
> > u_long pos = 0, phsize;
> > size_t randomizequota = ELF_RANDOMIZE_LIMIT;
> > @@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct proc *p,
> >   
> > for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
> > if (pp->p_type == PT_INTERP && !interp) {
> > -   if (pp->p_filesz >= MAXPATHLEN)
> > +   if (pp->p_filesz >= MAXPATHLEN ||
> > +  

Don't iterate on the global list in arp_{request,input}

2013-08-28 Thread Martin Pieuchot
Like the previous diffs, when we already have the ifp and want one of
its addresses, iterate on the ifp list instead of the global one.

Tested with carp here. I appreciate any comment and oks.

Index: netinet/if_ether.c
===
RCS file: /cvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.105
diff -u -p -r1.105 if_ether.c
--- netinet/if_ether.c  28 Aug 2013 06:58:57 -  1.105
+++ netinet/if_ether.c  28 Aug 2013 07:57:01 -
@@ -145,7 +145,6 @@ arp_rtrequest(int req, struct rtentry *r
 {
struct sockaddr *gate = rt->rt_gateway;
struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
-   struct in_ifaddr *ia;
struct ifaddr *ifa;
struct mbuf *m;
 
@@ -259,13 +258,13 @@ arp_rtrequest(int req, struct rtentry *r
rt->rt_flags |= RTF_LLINFO;
LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
 
-   TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
-   if (ia->ia_ifp == rt->rt_ifp &&
-   SIN(rt_key(rt))->sin_addr.s_addr ==
-   (IA_SIN(ia))->sin_addr.s_addr)
+   TAILQ_FOREACH(ifa, &rt->rt_ifp->if_addrlist, ifa_list) {
+   if ((ifa->ifa_addr->sa_family == AF_INET) &&
+   ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
+   satosin(rt_key(rt))->sin_addr.s_addr)
break;
}
-   if (ia) {
+   if (ifa) {
/*
 * This test used to be
 *  if (lo0ifp->if_flags & IFF_UP)
@@ -294,7 +293,6 @@ arp_rtrequest(int req, struct rtentry *r
 * address we are using, otherwise we will have trouble
 * with source address selection.
 */
-   ifa = &ia->ia_ifa;
if (ifa != rt->rt_ifa) {
ifafree(rt->rt_ifa);
ifa->ifa_refcnt++;
@@ -562,11 +560,12 @@ void
 in_arpinput(struct mbuf *m)
 {
struct ether_arp *ea;
-   struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
+   struct ifnet *ifp = m->m_pkthdr.rcvif;
+   struct arpcom *ac = (struct arpcom *)ifp;
struct ether_header *eh;
struct llinfo_arp *la = 0;
struct rtentry *rt;
-   struct in_ifaddr *ia;
+   struct ifaddr *ifa;
struct sockaddr_dl *sdl;
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
@@ -593,57 +592,55 @@ in_arpinput(struct mbuf *m)
bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof(isaddr));
 
/* First try: check target against our addresses */
-   TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
-   if (itaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
+   TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+   if (ifa->ifa_addr->sa_family != AF_INET)
+   continue;
+
+   if (itaddr.s_addr != ifatoia(ifa)->ia_addr.sin_addr.s_addr)
continue;
 
 #if NCARP > 0
-   if (ia->ia_ifp->if_type == IFT_CARP &&
-   ((ia->ia_ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
+   if (ifp->if_type == IFT_CARP &&
+   ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
(IFF_UP|IFF_RUNNING))) {
-   if (ia->ia_ifp == m->m_pkthdr.rcvif) {
-   if (op == ARPOP_REPLY)
-   break;
-   if (carp_iamatch(ia, ea->arp_sha,
-   &enaddr, ðer_shost))
-   break;
-   else
-   goto out;
-   }
-   } else
-#endif
-   if (ia->ia_ifp == m->m_pkthdr.rcvif)
+   if (op == ARPOP_REPLY)
+   break;
+   if (carp_iamatch(ifatoia(ifa), ea->arp_sha,
+   &enaddr, ðer_shost))
break;
+   else
+   goto out;
+   }
+#endif
+   break;
}
 
/* Second try: check source against our addresses */
-   if (ia == NULL) {
-   TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
-   if (isaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
+   if (ifa == NULL) {
+   TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+   if (ifa->ifa_addr->sa_family != AF_INET)
continue;
-   if (ia->ia_ifp == m->m_pkthdr.rcvif)
+
+   if (isaddr.s_addr ==
+   ifatoia(ifa)->ia_addr.sin_addr.s_addr)

Re: [PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Maxime Villard
Updated diff, with small tweaks from Andres Perera,
 * int -> size_t, signedness issue, even if it can't be >INT_MAX
 * NULL -> NUL


Index: exec_elf.c
===
RCS file: /cvs/src/sys/kern/exec_elf.c,v
retrieving revision 1.93
diff -u -p -r1.93 exec_elf.c
--- exec_elf.c  4 Jul 2013 17:37:05 -   1.93
+++ exec_elf.c  28 Aug 2013 14:36:58 -
@@ -516,7 +516,7 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
int error, i;
char *interp = NULL;
u_long pos = 0, phsize;
-   size_t randomizequota = ELF_RANDOMIZE_LIMIT;
+   size_t n, randomizequota = ELF_RANDOMIZE_LIMIT;
 
if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
return (ENOEXEC);
@@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
 
for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
if (pp->p_type == PT_INTERP && !interp) {
-   if (pp->p_filesz >= MAXPATHLEN)
+   if (pp->p_filesz >= MAXPATHLEN ||
+   pp->p_filesz < 2)
goto bad;
interp = pool_get(&namei_pool, PR_WAITOK);
if ((error = ELFNAME(read_from)(p, epp->ep_vp,
pp->p_offset, interp, pp->p_filesz)) != 0) {
+   goto bad;
+   }
+   /* Ensure interp is a valid, NUL-terminated string */
+   for (n = 0; n < pp->p_filesz; n++) {
+   if (interp[n] == '\0')
+   break;
+   }
+   if (n != pp->p_filesz - 1) {
+   error = ENOEXEC;
goto bad;
}
} else if (pp->p_type == PT_LOAD) {



On 08/28/13 08:44, Maxime Villard wrote:
> Hi,
> in the ELF format, the PT_INTERP segment contains the path of the
> interpreter which must be loaded. For this segment, the kernel looks
> at these values in the program header:
> 
>   p_offset: offset of the path string
>   p_filesz: size of the path string, including the \0
> 
> The path string must be a valid string, or the binary won't be loaded.
> 
> The kernel actually doesn't check the string, it just reads p_filesz
> bytes from p_offset, and later it checks if it can be loaded. Malformed
> binaries which have paths like:
> 
>   "a"
> or
>   "aaa\0aaa\0aaa\0aaa\0"
> 
> are parsed, loaded, and then the kernel figures out that the path is
> not valid, and aborts.
> 
> When the kernel reads the path from the file, it should check directly
> the string to ensure it is at least a valid string.
> 
> Here is a patch for this. For pp->p_filesz, I could have put
>   if (pp->p_filesz == 0)
> but values of 1 also don't make sense; "\0" can't be a valid path.
> 
> 
> 
> Index: exec_elf.c
> ===
> RCS file: /cvs/src/sys/kern/exec_elf.c,v
> retrieving revision 1.93
> diff -u -p -r1.93 exec_elf.c
> --- exec_elf.c4 Jul 2013 17:37:05 -   1.93
> +++ exec_elf.c27 Aug 2013 22:59:21 -
> @@ -513,7 +513,7 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>   Elf_Ehdr *eh = epp->ep_hdr;
>   Elf_Phdr *ph, *pp, *base_ph = NULL;
>   Elf_Addr phdr = 0, exe_base = 0;
> - int error, i;
> + int error, i, n;
>   char *interp = NULL;
>   u_long pos = 0, phsize;
>   size_t randomizequota = ELF_RANDOMIZE_LIMIT;
> @@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct proc *p,
>   
>   for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
>   if (pp->p_type == PT_INTERP && !interp) {
> - if (pp->p_filesz >= MAXPATHLEN)
> + if (pp->p_filesz >= MAXPATHLEN ||
> + pp->p_filesz < 2)
>   goto bad;
>   interp = pool_get(&namei_pool, PR_WAITOK);
>   if ((error = ELFNAME(read_from)(p, epp->ep_vp,
>   pp->p_offset, interp, pp->p_filesz)) != 0) {
> + goto bad;
> + }
> + /* Ensure interp is a valid, NULL-terminated string */
> + for (n = 0; n < pp->p_filesz; n++) {
> + if (interp[n] == '\0')
> + break;
> + }
> + if (n != pp->p_filesz - 1) {
> + error = ENOEXEC;
>   goto bad;
>   }
>   } else if (pp->p_type == PT_LOAD) {
> 
> 
> 
> If you want to test
>   * Before patching
> take whatever binary you have, open it with a text/hex editor, at the
> beginning of the file there should be a string like "/usr/libexec/ld.so",
> just add a charac

Re: OpenBSD on a Nokia IP380

2013-08-28 Thread Alexey E. Suslikov
  charter.net> writes:

> installed.  Guess I'll have to live with the 4 onboard NICs for the time 
> being.

If you have no plans to forward full-blown 100Mbps between fxps
and there's a dot1q-aware switch near you, using vlans may be a
workaround for a limited number of physical ports.



missing bit in audio.4 ?

2013-08-28 Thread Remco
Index: audio.4
===
RCS file: /home/cvs/src/share/man/man4/audio.4,v
retrieving revision 1.62
diff -u -r1.62 audio.4
--- audio.4 15 Jul 2010 03:43:11 -  1.62
+++ audio.4 28 Aug 2013 07:22:57 -
@@ -154,7 +154,7 @@
 .Va buffer_size
 (as available via
 .Dv AUDIO_GETINFO ) .
-The device driver will continuously move data from this buffer
+The device driver will continuously move data to/from this buffer
 from/to the audio hardware, wrapping around at the end of the buffer.
 To find out where the hardware is currently accessing data in the buffer the
 .Dv AUDIO_GETIOFFS



[PATCH] ELF: ensure PT_INTERP strings are NULL-terminated

2013-08-28 Thread Maxime Villard
Hi,
in the ELF format, the PT_INTERP segment contains the path of the
interpreter which must be loaded. For this segment, the kernel looks
at these values in the program header:

 p_offset: offset of the path string
 p_filesz: size of the path string, including the \0

The path string must be a valid string, or the binary won't be loaded.

The kernel actually doesn't check the string, it just reads p_filesz
bytes from p_offset, and later it checks if it can be loaded. Malformed
binaries which have paths like:

"a"
or
"aaa\0aaa\0aaa\0aaa\0"

are parsed, loaded, and then the kernel figures out that the path is
not valid, and aborts.

When the kernel reads the path from the file, it should check directly
the string to ensure it is at least a valid string.

Here is a patch for this. For pp->p_filesz, I could have put
if (pp->p_filesz == 0)
but values of 1 also don't make sense; "\0" can't be a valid path.



Index: exec_elf.c
===
RCS file: /cvs/src/sys/kern/exec_elf.c,v
retrieving revision 1.93
diff -u -p -r1.93 exec_elf.c
--- exec_elf.c  4 Jul 2013 17:37:05 -   1.93
+++ exec_elf.c  27 Aug 2013 22:59:21 -
@@ -513,7 +513,7 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
Elf_Ehdr *eh = epp->ep_hdr;
Elf_Phdr *ph, *pp, *base_ph = NULL;
Elf_Addr phdr = 0, exe_base = 0;
-   int error, i;
+   int error, i, n;
char *interp = NULL;
u_long pos = 0, phsize;
size_t randomizequota = ELF_RANDOMIZE_LIMIT;
@@ -552,11 +552,21 @@ ELFNAME2(exec,makecmds)(struct proc *p, 
 
for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
if (pp->p_type == PT_INTERP && !interp) {
-   if (pp->p_filesz >= MAXPATHLEN)
+   if (pp->p_filesz >= MAXPATHLEN ||
+   pp->p_filesz < 2)
goto bad;
interp = pool_get(&namei_pool, PR_WAITOK);
if ((error = ELFNAME(read_from)(p, epp->ep_vp,
pp->p_offset, interp, pp->p_filesz)) != 0) {
+   goto bad;
+   }
+   /* Ensure interp is a valid, NULL-terminated string */
+   for (n = 0; n < pp->p_filesz; n++) {
+   if (interp[n] == '\0')
+   break;
+   }
+   if (n != pp->p_filesz - 1) {
+   error = ENOEXEC;
goto bad;
}
} else if (pp->p_type == PT_LOAD) {



If you want to test
 * Before patching
   take whatever binary you have, open it with a text/hex editor, at the
   beginning of the file there should be a string like "/usr/libexec/ld.so",
   just add a character to it, then run the binary with execv(): you will
   get abort traps.
 * After patching
   execv() now returns -1, and errno is set to ENOEXEC.

There should not be any regression; if there is, it means that the binary
is not spec compliant.


Ok/Comments?