NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/37957: non-critical buffer overflow in libbfd
>Number: 37957
>Category: lib
>Synopsis: non-critical buffer overflow in libbfd
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Feb 04 21:25:00 +0000 2008
>Originator: Yakovetsky Vladimir
>Release: NetBSD 4.99.51
>Organization:
>Environment:
System: NetBSD lrou.x.ua 4.99.51 NetBSD 4.99.51 (lrou-1.880) #0: Tue Jan 29
17:27:05 EET 2008 Yakovetsky Vladimir
<yx%x.ua@localhost>@lrou.x.ua:/sys/arch/i386/compile/lrou i386
Architecture: i386
Machine: i386
>Description:
for example - broken `ar' tool from fortified system
in result of non-critical buffer overflow in libbfd.
>How-To-Repeat:
1) build && install distribution with USE_FORT=yes
2) for example, try to use `ar' tool
example:
# cd /usr/src && ./build distribution
...
rm -f libnbcompat.a
ar cq libnbcompat.a atoll.lo basename.lo dirname.lo fgetln.lo flock.lo
fparseln.lo getmode.lo getopt_long.lo gettemp.lo heapsort.lo issetugid.lo
lchflags.lo lchmod.lo lchown.lo libyywrap.lo md2.lo md2hl.lo md4c.lo md4hl.lo
md5c.lo md5hl.lo mkdtemp.lo mkstemp.lo pread.lo putc_unlocked.lo pwcache.lo
pwrite.lo pw_scan.lo raise_default_signal.lo rmd160.lo rmd160hl.lo setenv.lo
setgroupent.lo setpassent.lo setprogname.lo sha1.lo sha1hl.lo sha2.lo
sha256hl.lo sha384hl.lo sha512hl.lo snprintf.lo stat_flags.lo strlcat.lo
strlcpy.lo strmode.lo strndup.lo strsep.lo strsuftoll.lo strtoll.lo unvis.lo
vis.lo err.lo errx.lo verr.lo verrx.lo vwarn.lo vwarnx.lo warn.lo warnx.lo
fts.lo glob.lo efun.lo bt_close.lo bt_conv.lo bt_debug.lo bt_delete.lo
bt_get.lo bt_open.lo bt_overflow.lo bt_page.lo bt_put.lo bt_search.lo bt_seq.lo
bt_split.lo bt_utils.lo db.lo hash.lo hash_bigkey.lo hash_buf.lo hash_func.lo
hash_log2.lo hash_page.lo mpool.lo rec_close.lo rec_delete.lo rec_get.lo
rec_open.lo rec_!
put.lo rec_search.lo rec_seq.lo rec_utils.lo
[1] Abort trap (core dumped) ar cq libnbcompa...
*** Failed target: libnbcompat.a
*** Failed command: ar cq libnbcompat.a atoll.lo basename.lo dirname.lo
fgetln.lo flock.lo fparseln.lo getmode.lo getopt_long.lo gettemp.lo heapsort.lo
issetugid.lo lchflags.lo lchmod.lo lchown.lo libyywrap.lo md2.lo md2hl.lo
md4c.lo md4hl.lo md5c.lo md5hl.lo mkdtemp.lo mkstemp.lo pread.lo
putc_unlocked.lo pwcache.lo pwrite.lo pw_scan.lo raise_default_signal.lo
rmd160.lo rmd160hl.lo setenv.lo setgroupent.lo setpassent.lo setprogname.lo
sha1.lo sha1hl.lo sha2.lo sha256hl.lo sha384hl.lo sha512hl.lo snprintf.lo
stat_flags.lo strlcat.lo strlcpy.lo strmode.lo strndup.lo strsep.lo
strsuftoll.lo strtoll.lo unvis.lo vis.lo err.lo errx.lo verr.lo verrx.lo
vwarn.lo vwarnx.lo warn.lo warnx.lo fts.lo glob.lo efun.lo bt_close.lo
bt_conv.lo bt_debug.lo bt_delete.lo bt_get.lo bt_open.lo bt_overflow.lo
bt_page.lo bt_put.lo bt_search.lo bt_seq.lo bt_split.lo bt_utils.lo db.lo
hash.lo hash_bigkey.lo hash_buf.lo hash_func.lo hash_log2.lo hash_page.lo
mpool.lo rec_close.lo rec_delete.lo rec_get!
.lo rec_open.lo rec_put.lo rec_search.lo rec_seq.lo rec_utils.lo
*** Error code 134
Stop.
nbmake: stopped in /usr/src/tools/compat
and message from kernel log:
Feb 4 18:51:44 lrou ar: buffer overflow detected; terminated
and log from debug session:
...
Breakpoint 3, coff_write_armap (arch=0xbb9191c0, elength=0, map=0xbb92c000,
symbol_count=0, stridx=0) at /usr/src/gnu/dist/binutils/bfd/archive.c:2088
2088 sprintf (hdr.ar_size, "%-10d", (int) mapsize);
(gdb) p sizeof(hdr.ar_size)
$1 = 10
(gdb) n
Program received signal SIGABRT, Aborted.
0xbbab1d47 in kill () from /usr/lib/libc.so.12
>Fix:
_bfd_ar_spacepad() instead sprintf() from bfd/archive.c,v 1.37 2005/03/11
(http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/archive.c.diff?r1=1.36&r2=1.37&cvsroot=src)
--- gnu/dist/binutils/bfd/archive.c.orig
+++ gnu/dist/binutils/bfd/archive.c
@@ -159,6 +159,22 @@
static const char * normalize (bfd *, const char *);
+void
+_bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val)
+{
+ static char buf[20];
+ size_t len;
+ snprintf (buf, sizeof (buf), fmt, val);
+ len = strlen (buf);
+ if (len < n)
+ {
+ memcpy (p, buf, len);
+ memset (p + len, ' ', n - len);
+ }
+ else
+ memcpy (p, buf, n);
+}
+
bfd_boolean
_bfd_generic_mkarchive (bfd *abfd)
{
@@ -1266,17 +1282,8 @@
strptr[thislen + 1] = '\012';
}
hdr->ar_name[0] = ar_padchar (current);
- /* We know there will always be enough room (one of the few
- cases where you may safely use sprintf). */
- sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc));
- /* Kinda Kludgy. We should just use the returned value of
- sprintf but not all implementations get this right. */
- {
- char *temp = hdr->ar_name + 2;
- for (; temp < hdr->ar_name + maxname; temp++)
- if (*temp == '\0')
- *temp = ' ';
- }
+ _bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld",
+ strptr - *tabloc);
strptr += thislen + 1;
if (trailing_slash)
++strptr;
@@ -1351,10 +1358,10 @@
/* ar headers are space padded, not null padded! */
memset (hdr, ' ', sizeof (struct ar_hdr));
- strncpy (hdr->ar_fmag, ARFMAG, 2);
+ memcpy (hdr->ar_fmag, ARFMAG, 2);
- /* Goddamned sprintf doesn't permit MAXIMUM field lengths. */
- sprintf ((hdr->ar_date), "%-12ld", (long) status.st_mtime);
+ _bfd_ar_spacepad (hdr->ar_date, sizeof (hdr->ar_date), "%-12ld",
+ status.st_mtime);
#ifdef HPUX_LARGE_AR_IDS
/* HP has a very "special" way to handle UID/GID's with numeric values
> 99999. */
@@ -1362,7 +1369,8 @@
hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_uid);
else
#endif
- sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid);
+ _bfd_ar_spacepad (hdr->ar_uid, sizeof (hdr->ar_uid), "%ld",
+ status.st_uid);
#ifdef HPUX_LARGE_AR_IDS
/* HP has a very "special" way to handle UID/GID's with numeric values
> 99999. */
@@ -1370,20 +1378,13 @@
hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_gid);
else
#endif
- sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid);
- sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode);
- sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size);
- /* Correct for a lossage in sprintf whereby it null-terminates. I cannot
- understand how these C losers could design such a ramshackle bunch of
- IO operations. */
- temp = (char *) hdr;
- temp1 = temp + sizeof (struct ar_hdr) - 2;
- for (; temp < temp1; temp++)
- {
- if (*temp == '\0')
- *temp = ' ';
- }
- strncpy (hdr->ar_fmag, ARFMAG, 2);
+ _bfd_ar_spacepad (hdr->ar_gid, sizeof (hdr->ar_gid), "%ld",
+ status.st_gid);
+ _bfd_ar_spacepad (hdr->ar_mode, sizeof (hdr->ar_mode), "%-8lo",
+ status.st_mode);
+ _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld",
+ status.st_size);
+ memcpy (hdr->ar_fmag, ARFMAG, 2);
ared->parsed_size = status.st_size;
ared->arch_header = (char *) hdr;
@@ -1661,15 +1662,12 @@
{
struct ar_hdr hdr;
- memset (&hdr, 0, sizeof (struct ar_hdr));
- strcpy (hdr.ar_name, ename);
+ memset (&hdr, ' ', sizeof (struct ar_hdr));
+ memcpy (hdr.ar_name, ename, strlen (ename));
/* Round size up to even number in archive header. */
- sprintf (&(hdr.ar_size[0]), "%-10d",
- (int) ((elength + 1) & ~(bfd_size_type) 1));
- strncpy (hdr.ar_fmag, ARFMAG, 2);
- for (i = 0; i < sizeof (struct ar_hdr); i++)
- if (((char *) (&hdr))[i] == '\0')
- (((char *) (&hdr))[i]) = ' ';
+ _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
+ (elength + 1) & ~(bfd_size_type) 1);
+ memcpy (hdr.ar_fmag, ARFMAG, 2);
if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
!= sizeof (struct ar_hdr))
|| bfd_bwrite (etable, elength, arch) != elength)
@@ -1918,20 +1916,18 @@
firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
stat (arch->filename, &statbuf);
- memset (&hdr, 0, sizeof (struct ar_hdr));
- sprintf (hdr.ar_name, RANLIBMAG);
+ memset (&hdr, ' ', sizeof (struct ar_hdr));
+ memcpy (hdr.ar_name, RANLIBMAG, strlen (RANLIBMAG));
/* Remember the timestamp, to keep it holy. But fudge it a little. */
bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET;
bfd_ardata (arch)->armap_datepos = (SARMAG
+ offsetof (struct ar_hdr, ar_date[0]));
- sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp);
- sprintf (hdr.ar_uid, "%ld", (long) getuid ());
- sprintf (hdr.ar_gid, "%ld", (long) getgid ());
- sprintf (hdr.ar_size, "%-10d", (int) mapsize);
- strncpy (hdr.ar_fmag, ARFMAG, 2);
- for (i = 0; i < sizeof (struct ar_hdr); i++)
- if (((char *) (&hdr))[i] == '\0')
- (((char *) (&hdr))[i]) = ' ';
+ _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
+ bfd_ardata (arch)->armap_timestamp);
+ _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", getuid ());
+ _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", getgid ());
+ _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize);
+ memcpy (hdr.ar_fmag, ARFMAG, 2);
if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
!= sizeof (struct ar_hdr))
return FALSE;
@@ -2019,11 +2015,9 @@
bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
/* Prepare an ASCII version suitable for writing. */
- memset (hdr.ar_date, 0, sizeof (hdr.ar_date));
- sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp);
- for (i = 0; i < sizeof (hdr.ar_date); i++)
- if (hdr.ar_date[i] == '\0')
- (hdr.ar_date)[i] = ' ';
+ memset (hdr.ar_date, ' ', sizeof (hdr.ar_date));
+ _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
+ bfd_ardata (arch)->armap_timestamp);
/* Write it into the file. */
bfd_ardata (arch)->armap_datepos = (SARMAG
@@ -2083,19 +2077,17 @@
+ sizeof (struct ar_hdr)
+ SARMAG);
- memset (&hdr, 0, sizeof (struct ar_hdr));
+ memset (&hdr, ' ', sizeof (struct ar_hdr));
hdr.ar_name[0] = '/';
- sprintf (hdr.ar_size, "%-10d", (int) mapsize);
- sprintf (hdr.ar_date, "%ld", (long) time (NULL));
+ _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
+ mapsize);
+ _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
+ time (NULL));
/* This, at least, is what Intel coff sets the values to. */
- sprintf ((hdr.ar_uid), "%d", 0);
- sprintf ((hdr.ar_gid), "%d", 0);
- sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
- strncpy (hdr.ar_fmag, ARFMAG, 2);
-
- for (i = 0; i < sizeof (struct ar_hdr); i++)
- if (((char *) (&hdr))[i] == '\0')
- (((char *) (&hdr))[i]) = ' ';
+ _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
+ _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
+ _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
+ memcpy (hdr.ar_fmag, ARFMAG, 2);
/* Write the ar header for this item and the number of symbols. */
if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
Home |
Main Index |
Thread Index |
Old Index