Bug#904749: make: patch of arscan.c fails dependency testing

2018-07-28 Thread Philipp Wolski

Hi,


the new patch looks good.

It also passes the se_main compile and an entire rebuilt of the project.

Thank you !


> Although alloca(INT_MAX) is not going to well!

Reminds me of a popular song: "(Don't) Fear the OOM-Reaper" with the 
background vocals singing "just add more hardware"...



Philipp Wolski



Bug#904749: make: patch of arscan.c fails dependency testing

2018-07-27 Thread Ben Hutchings
On Fri, 2018-07-27 at 20:26 +0200, Philipp Wolski wrote:
> (I hope this mail is sent as text, the corporate mailserver is kinda wonky 
> and the signatures are applied by administrative rule, though I do my best 
> to tinker with the clients settings to remove it.)
> 
> Hi,
> 
> I tested your patch and although it looks logically fine it would not 
> work.
> 
> I'm sorry for not including an example but I frankly don't know how to 
> reproduce this but I suspect you need to create an a file with 
> filenames>16 chars and get ar to map them.
> It happens only with one of eight libraries and the whole built system is 
> ancient legacy stuff. The lib is the largest of course, 252 objects with 
> an average filename length of 20 chars.
> 
> Actually I tinkered around and finally added a printf and got this in your 
> name_len check (line 678):
> 
> name_len=18
> name=DlfRemoveControl.o
> name_off=18
> ARNAME_MAX=16
> 
> name_off is probably a coincidence.
> ARNAME_MAX is 16 due to ar_hdr.ar_name[16] in ar.h (strangely on Android 
> ARNAME_MAX is hardcoded to 255 by the original patch in arscan.c)

Sorry, I thought it was 255.  All the #ifdefs make it so hard to
understand what's going on.  And my test case happened to use a 16-
character name, which is long enough for GNU ar to store it as a long
name, but still within what make considers the maximum length of a
short name.

[...]
> I don't believe (yeah "believe", no idea how this works) namebuf nor 
> ar_name are actually used for those mapped names.
> 
> Therefore I question that name_len should check against  the max size a 
> "mapped name" is allowed to be instead of ar_hdr size.
[...]

I agree.  I'll go with INT_MAX as the maximum size (since offsets and
sizes are mostly stored as ints here).  Although alloca(INT_MAX) is not
going to well!

New patch attached.

Ben.

-- 
Ben Hutchings
The two most common things in the universe are hydrogen and stupidity.

From dd759110a1914d9325bf57a9a83b3a61eac5420e Mon Sep 17 00:00:00 2001
From: Ben Hutchings 
Date: Sat, 28 Jul 2018 10:31:11 +0800
Subject: [PATCH] Fix validation of long names in archives

Commit bc9d72beb0cb "Resolve issues discovered by static code
analysis." added range checks on archive member name length.  However,
on non-AIX systems it also checked BSD-style long names against the
short name limits and and checked the *offset* for GNU-style long
names against the short name limits.  This caused valid long names to
be rejected.

* Record the size of the GNU name map, and validate offsets against that
* Ensure that the last entry in the name map is null-terminated
* Apply a maximum length of INT_MAX for long names

Reported-by: Philipp Wolski 
---
 arscan.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/arscan.c b/arscan.c
index 6bc5af2467c2..d63872f66ca2 100644
--- a/arscan.c
+++ b/arscan.c
@@ -414,6 +414,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
 # endif
 #endif
   char *namemap = 0;
+  int namemap_size = 0;
   int desc = open (archive, O_RDONLY, 0);
   if (desc < 0)
 return -1;
@@ -667,10 +668,15 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
   && namemap != 0)
 {
   int name_off = atoi (name + 1);
-  if (name_off < 1 || name_off > ARNAME_MAX)
+  int name_len;
+
+  if (name_off < 0 || name_off >= namemap_size)
 goto invalid;
 
   name = namemap + name_off;
+  name_len = strlen (name);
+  if (name_len < 1)
+goto invalid;
   long_name = 1;
 }
   else if (name[0] == '#'
@@ -678,7 +684,8 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
&& name[2] == '/')
 {
   int name_len = atoi (name + 3);
-  if (name_len < 1 || name_len > ARNAME_MAX)
+
+  if (name_len < 1 || name_len > INT_MAX)
 goto invalid;
 
   name = alloca (name_len + 1);
@@ -747,10 +754,13 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
 char *clear;
 char *limit;
 
-namemap = alloca (eltsize);
+if (eltsize > INT_MAX)
+  goto invalid;
+namemap = alloca (eltsize + 1);
 EINTRLOOP (nread, read (desc, namemap, eltsize));
 if (nread != eltsize)
   goto invalid;
+namemap_size = eltsize;
 
 /* The names are separated by newlines.  Some formats have
a trailing slash.  Null terminate the strings for
@@ -765,6 +775,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
   clear[-1] = '\0';
   }
   }
+*limit = '\0';
 
 is_namemap = 0;
   }


signature.asc
Description: This is 

Bug#904749: make: patch of arscan.c fails dependency testing

2018-07-27 Thread Philipp Wolski

(pulled the gmail joker to get rid of the signature)


Sorry me again,

It just so came to me: name_len notwithstanding, name_off==0 might 
actually be valid as a pointer offset (since the if is denying name_off<1)



Philipp Wolski



Bug#904749: make: patch of arscan.c fails dependency testing

2018-07-27 Thread Philipp Wolski
(I hope this mail is sent as text, the corporate mailserver is kinda wonky 
and the signatures are applied by administrative rule, though I do my best 
to tinker with the clients settings to remove it.)

Hi,

I tested your patch and although it looks logically fine it would not 
work.

I'm sorry for not including an example but I frankly don't know how to 
reproduce this but I suspect you need to create an a file with 
filenames>16 chars and get ar to map them.
It happens only with one of eight libraries and the whole built system is 
ancient legacy stuff. The lib is the largest of course, 252 objects with 
an average filename length of 20 chars.

Actually I tinkered around and finally added a printf and got this in your 
name_len check (line 678):

name_len=18
name=DlfRemoveControl.o
name_off=18
ARNAME_MAX=16

name_off is probably a coincidence.
ARNAME_MAX is 16 due to ar_hdr.ar_name[16] in ar.h (strangely on Android 
ARNAME_MAX is hardcoded to 255 by the original patch in arscan.c)

After reading the comments in this ifdef riddled code I'm not convinced 
that checking the name_len againt ARNAME_MAX ist correct in the is_mapped 
part.
An earlier part above line 652 comments how traditionally the names are 
only 14 characters, while the namemap part sets long_name=1
and the comment hints to a GNU addition.
This goes for the later(BSD?) code as well where name is actually alloc'ed 
to a potentially larger size than namebuf can hold.

I don't believe (yeah "believe", no idea how this works) namebuf nor 
ar_name are actually used for those mapped names.

Therefore I question that name_len should check against  the max size a 
"mapped name" is allowed to be instead of ar_hdr size.

Any idea where this can be found? Or am I completely off? (can't find any 
reference to ar being limited to 16 chars per se though, and removing the 
name_len check still works without segfault)

I admit I haven't looked up the cause for the original name_len check 
patch since the upstream tar does not check it, so I might be noisy, 
sorry.

Fun fact, make actually quits with "no rule to make target 
../gen/gnmt.a(EnMeasOrig.o)" right after the above printf,
These are the first lines of the dep file:
se_main: //usr/lib/x86_64-linux-gnu/libm-2.27.a
se_main: ../gen/gnmt.a(EnMeasOrig.o)
se_main: ../gen/gnmt.a(EnMeasType.o)
se_main: ../gen/gnmt.a(EnTapType.o)
se_main: ../gen/gnmt.a(gnmt.o)
[this goes on for a lot more .o, though se_main does not even use the A to 
D files like DlfRemoveControl ]

 Philipp Wolski - KISTERS AG - Haselriege 13 - 26125 Oldenburg - Germany
Handelsregister Aachen, HRB-Nr. 7838 | Vorstand: Klaus Kisters, Hanns Kisters | 
Aufsichtsratsvorsitzender: Dr. Thomas Klevers
Phone: +49 441 93602 -158 | Fax: +49 441 93602 -222 | E-Mail: 
philipp.wol...@kisters.de | WWW: http://www.kisters.de

Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. 
Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten 
haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. 
Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht 
gestattet. 
This e-mail may contain confidential and/or privileged information. If you are 
not the intended recipient (or have received this e-mail in error) please 
notify the sender immediately and destroy this e-mail. Any unauthorised 
copying, disclosure or distribution of the material in this e-mail is strictly 
forbidden.

Bug#904749: make: patch of arscan.c fails dependency testing

2018-07-27 Thread Ben Hutchings
On Fri, 2018-07-27 at 23:41 +0800, Ben Hutchings wrote:
[...]
> Sorry about this.  You didn't give an example to reproduce this, but I
> was able to construct one.  Please could you test that the attached
> patch also works for your real usage?
[...]

Really attached this time.

Ben.

-- 
Ben Hutchings
Power corrupts.  Absolute power is kind of neat. - John Lehman

From 9f15821377ec57bd36ae28eb3d430a66b87c9906 Mon Sep 17 00:00:00 2001
From: Ben Hutchings 
Date: Fri, 27 Jul 2018 22:40:49 +0800
Subject: [PATCH] Fix validation of GNU-style long names in archives

Commit bc9d72beb0cb "Resolve issues discovered by static code
analysis." added range checks on archive member name length.  However,
in the case of GNU-style long names, it range-checked the *offset* in
the name map as if it was a length.  This caused valid long names to
be rejected.

* Record the size of the name map, and validate offsets against that
* Ensure that the last entry in the name map is null-terminated
* Check the length after finding the name in the name map

Reported-by: Philipp Wolski 
---
 arscan.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arscan.c b/arscan.c
index 6bc5af2467c2..f424128c2a8b 100644
--- a/arscan.c
+++ b/arscan.c
@@ -414,6 +414,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
 # endif
 #endif
   char *namemap = 0;
+  int namemap_size = 0;
   int desc = open (archive, O_RDONLY, 0);
   if (desc < 0)
 return -1;
@@ -667,10 +668,15 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
   && namemap != 0)
 {
   int name_off = atoi (name + 1);
-  if (name_off < 1 || name_off > ARNAME_MAX)
+  int name_len;
+
+  if (name_off < 0 || name_off >= namemap_size)
 goto invalid;
 
   name = namemap + name_off;
+  name_len = strlen(name);
+  if (name_len < 1 || name_len > ARNAME_MAX)
+goto invalid;
   long_name = 1;
 }
   else if (name[0] == '#'
@@ -747,10 +753,11 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
 char *clear;
 char *limit;
 
-namemap = alloca (eltsize);
+namemap = alloca (eltsize + 1);
 EINTRLOOP (nread, read (desc, namemap, eltsize));
 if (nread != eltsize)
   goto invalid;
+namemap_size = eltsize;
 
 /* The names are separated by newlines.  Some formats have
a trailing slash.  Null terminate the strings for
@@ -765,6 +772,7 @@ ar_scan (const char *archive, ar_member_func_t function, const void *arg)
   clear[-1] = '\0';
   }
   }
+*limit = '\0';
 
 is_namemap = 0;
   }


signature.asc
Description: This is a digitally signed message part


Bug#904749: make: patch of arscan.c fails dependency testing

2018-07-27 Thread Ben Hutchings
Control: tag -1 upstream patch
Control: forwarded -1 https://savannah.gnu.org/bugs/index.php?54395

On Fri, 2018-07-27 at 15:31 +0200, Philipp Wolski wrote:
> Package: make
> Version: 4.2.1-1.1
> Severity: important
> 
> Dear Maintainer,
> 
> we are using dependency files when static linking .a file build with ar -U.
> 
> I noticed that some libraries failed with "no rule to make target 
> xxx.a(yyy.o)"
> which would change when I moved the o-files around within the lib.
> 
> It did not happen with the upstream make-4.2.1 tar-ball
> 
> By bisecting the patches applied I found a patch to arscan.c to be the 
> culprit.
> 
> Around line 669 of the patched arscan.c file it reads:
> 
>   int name_off = atoi (name + 1);
>   if (name_off < 1 || name_off > ARNAME_MAX)
> goto invalid;
> 
>   name = namemap + name_off;
> 
> I recon name_off is a pointer index which is added to the namemap pointer.
> In this case, the check for name length violation does/should not apply here, 
> or must
> be safeguarded differently.
> 
> Removing the if let us compile again.

Sorry about this.  You didn't give an example to reproduce this, but I
was able to construct one.  Please could you test that the attached
patch also works for your real usage?

I also uploaded a new source package with this patch to:
https://people.debian.org/~benh/packages/make-dfsg_4.2.1-1.2.dsc

Ben.

-- 
Ben Hutchings
Power corrupts.  Absolute power is kind of neat. - John Lehman


signature.asc
Description: This is a digitally signed message part


Bug#904749: make: patch of arscan.c fails dependency testing

2018-07-27 Thread Philipp Wolski
Package: make
Version: 4.2.1-1.1
Severity: important

Dear Maintainer,

we are using dependency files when static linking .a file build with ar -U.

I noticed that some libraries failed with "no rule to make target xxx.a(yyy.o)"
which would change when I moved the o-files around within the lib.

It did not happen with the upstream make-4.2.1 tar-ball

By bisecting the patches applied I found a patch to arscan.c to be the culprit.

Around line 669 of the patched arscan.c file it reads:

  int name_off = atoi (name + 1);
  if (name_off < 1 || name_off > ARNAME_MAX)
goto invalid;

  name = namemap + name_off;

I recon name_off is a pointer index which is added to the namemap pointer.
In this case, the check for name length violation does/should not apply here, 
or must
be safeguarded differently.

Removing the if let us compile again.


-- System Information:
Debian Release: buster/sid
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'unstable'), (500, 'testing'), 
(500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.17.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.utf8, LC_CTYPE=de_DE.utf8 (charmap=UTF-8), 
LANGUAGE=de_DE.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Init: systemd (via /run/systemd/system)

Versions of packages make depends on:
ii  libc6  2.27-5

make recommends no packages.

Versions of packages make suggests:
pn  make-doc  

-- no debconf information

 Philipp Wolski - KISTERS AG - Haselriege 13 - 26125 Oldenburg - Germany
Handelsregister Aachen, HRB-Nr. 7838 | Vorstand: Klaus Kisters, Hanns Kisters | 
Aufsichtsratsvorsitzender: Dr. Thomas Klevers
Phone: +49 441 93602 -158 | Fax: +49 441 93602 -222 | E-Mail: 
philipp.wol...@kisters.de | WWW: http://www.kisters.de

Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. 
Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten 
haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. 
Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht 
gestattet. 
This e-mail may contain confidential and/or privileged information. If you are 
not the intended recipient (or have received this e-mail in error) please 
notify the sender immediately and destroy this e-mail. Any unauthorised 
copying, disclosure or distribution of the material in this e-mail is strictly 
forbidden.