NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/42636: [dM] t_getstr potential memory overrun
>Number: 42636
>Category: lib
>Synopsis: [dM] t_getstr potential memory overrun
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jan 18 07:30:00 +0000 2010
>Originator: der Mouse
>Release: NetBSD 4.0.1
>Organization:
Dis-
>Environment:
System: NetBSD iMac-backup.Rodents-Montreal.ORG 4.0.1 NetBSD 4.0.1
(IMAC-BACKUP) #2: Thu Dec 31 09:47:34 EST 2009
mouse%iMac-backup.Rodents-Montreal.ORG@localhost:/home/mouse/kbuild/IMAC-BACKUP
i386
Architecture: i386
Machine: i386
>Description:
The manpage description of t_getstr describes the area and
limit parameters saying that the "limit parameter that gives
the number of characters that can be inserted in to the array
pointed to by area", adding that it "is updated [...] to give
the number of characters that remain available in area", and
that if area is nil then "the size required to hold the
capability string will be returned in limit".
However, this is not quite the reality. The area pointer is
advanced by one more than the limit parameter is decreased by,
leading to a potential buffer overrun by as many bytes as there
are string capabilities involved - the limit advance does not
take the \0 into account, while the area pointer advance does.
Also, the returned limit value for a nil-pointer area call is
the amount the limit value would have been decreased by, not
the number of bytes that would have been copied if the area
pointer had been non-nil, thus inviting the caller to allocate
one byte too few. (Fortunately, the buffer overrun is more
difficult to exploit than most buffer overruns, since the
overrun data is not very controllable by the attacker in most
scenarios.)
It's possible there's actually a standard somewhere that
specifies this bizarre bug-inviting behaviour. This is serious
enough that I would actually recommend ignoring any such
standard; if NetBSD does not want to do that, this should then
be reclassified as a doc-bug and warnings splashed all over the
manpage that the behaviour is severely counterintuitive and the
pointer and limit variables must be treated very carefully to
avoid buffer overrun bugs.
>How-To-Repeat:
% cat z.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <termcap.h>
extern const char *__progname;
static void fail(const char *why)
{
fprintf(stderr,"%s: %s\n",__progname,why);
exit(1);
}
int main(void);
int main(void)
{
struct tinfo *inf;
char area[64];
char *ap;
size_t lim;
char *cap;
if (t_getent(&inf,"vt100") != 1) fail("can't look up vt100");
ap = &area[0];
lim = sizeof(area);
cap = t_getstr(inf,"bl",&ap,&lim);
if (cap == 0) fail("can't look up bl capability");
printf("area pointer advanced by %d\n",(int)(ap-&area[0]));
printf("limit reduced by %d\n",(int)(sizeof(area)-lim));
errno = 0;
lim = 0;
t_getstr(inf,"bl",0,&lim);
if (errno) fail("can't nil-pointer check bl capability");
printf("nil-pointer length is %d\n",(int)lim);
return(0);
}
% cc -o z z.c
% ./z
area pointer advanced by 2
limit reduced by 1
nil-pointer length is 1
%
>Fix:
Relative to termcap.c,v 1.49:
--- termcap.c.orig 2010-01-17 11:56:50.000000000 -0500
+++ termcap.c 2010-01-17 11:58:22.000000000 -0500
@@ -384,6 +384,7 @@
return NULL;
}
+ i ++; /* account for the NUL */
if (area != NULL) {
/*
* check if there is room for the new entry to be put
into
@@ -398,7 +399,7 @@
(void)strcpy(*area, s);
free(s);
s = *area;
- *area += i + 1;
+ *area += i;
if (limit != NULL) *limit -= i;
return (s);
/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML mouse%rodents-montreal.org@localhost
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
>Unformatted:
Also believed present as far back as 1.4T - probably anything
with the t_* termcap routines. May be present in more recent
versions too; I don't have anything newer at ready hand.
Home |
Main Index |
Thread Index |
Old Index