@(#)Mordre Labs advisory 0x0005: Several buffer overruns in PostgreSQL
//@(#) Mordred Labs advisory 0x0005
Release data: 23/08/02
Name: Several buffer overruns in PostgreSQL
Versions affected: all versions
Risk: from average to low
--[ Description:
PostgreSQL provides you with several builint geo types
(circle,polygon,box...etc).
Unfortunately the code for geo functions written in a very insecure style
and should be totally rewritten, as a quick search revealed this:
---[ Details:
1)
Upon invoking a polygon(integer, circle) function
a src/backend/utils/adt/geo_ops.c:circle_poly() function will gets called,
which suffers from a buffer overflow.
2) A src/backend/adt/utils/geo_ops.c:path_encode() fails to detect a buffer
overrun condition. It is called in multiple places, the most
interesting are path_out() and poly_out() functions.
3) Upon converting a char string to a path object, a
src/backend/utils/adt/geo_ops.c:path_in() function will gets called,
which suffers from a buffer overrun, caused by a very long argument.
4) A src/backend/utils/adt/geo_ops.c:poly_in() function fails to detect a
buffer
overrun condition caused by a very long argument.
5) A src/backend/utils/adt/geo_ops.c:path_add() also fails to detect a
simple buffer
overrun.
6)
And finally, a truly dumb feature (not a security related though) in
postmaster:
$ postmaster -o `perl -e 'print "\x66" x 1200'`
Segmentation fault (core dumped)
--[ How to reproduce:
I only show how to reproduce a first buffer overrun condition, as the others
too memory consuming :-)
1)
template1=# select polygon(268435455,'((1,2),3)'::circle);
pqReadData() -- backend closed the channel unexpectedly.
This probably means the backend terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
!#
--[ Solution
Drop the vulnerable functions.
________________________________________________________________________
This letter has been delivered unencrypted. We'd like to remind you that
the full protection of e-mail correspondence is provided by S-mail
encryption mechanisms if only both, Sender and Recipient use S-mail.
Register at S-mail.com: http://www.s-mail.com/inf/en
Sir Mordred The Traitor <mordred@s-mail.com> writes:
Upon invoking a polygon(integer, circle) function a
src/backend/utils/adt/geo_ops.c:circle_poly() function will gets
called, which suffers from a buffer overflow.2) A src/backend/adt/utils/geo_ops.c:path_encode() fails to detect a
buffer overrun condition. It is called in multiple places, the most
interesting are path_out() and poly_out() functions.
5) A src/backend/utils/adt/geo_ops.c:path_add() also fails to detect
a simple buffer overrun.
I've attached a patch which should fix these problems.
3) Upon converting a char string to a path object, a
src/backend/utils/adt/geo_ops.c:path_in() function will gets called,
which suffers from a buffer overrun, caused by a very long argument.
4) A src/backend/utils/adt/geo_ops.c:poly_in() function fails to
detect a buffer overrun condition caused by a very long argument.
I wasn't able to reproduce either of these (wouldn't it require an
input string with several hundred thousand commas?), can you give me a
test-case?
Cheers,
Neil
--
Neil Conway <neilc@samurai.com> || PGP Key ID: DB3C29FC
Attachments:
geo_fixes-1.patchtext/x-patchDownload
Index: src/backend/utils/adt/geo_ops.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/adt/geo_ops.c,v
retrieving revision 1.63
diff -c -r1.63 geo_ops.c
*** src/backend/utils/adt/geo_ops.c 16 Jul 2002 03:30:27 -0000 1.63
--- src/backend/utils/adt/geo_ops.c 28 Aug 2002 19:07:01 -0000
***************
*** 269,279 ****
static char *
path_encode(bool closed, int npts, Point *pt)
{
! char *result = palloc(npts * (P_MAXLEN + 3) + 2);
!
char *cp;
int i;
cp = result;
switch (closed)
{
--- 269,285 ----
static char *
path_encode(bool closed, int npts, Point *pt)
{
! int size = npts * (P_MAXLEN + 3) + 2;
! char *result;
char *cp;
int i;
+ /* Check for integer overflow */
+ if ((size - 2) / npts != (P_MAXLEN + 3))
+ elog(ERROR, "Too many points requested");
+
+ result = palloc(size);
+
cp = result;
switch (closed)
{
***************
*** 1230,1236 ****
depth++;
}
! size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;
path = (PATH *) palloc(size);
path->size = size;
--- 1236,1242 ----
depth++;
}
! size = offsetof(PATH, p[0]) + sizeof(path->p[0]) * npts;
path = (PATH *) palloc(size);
path->size = size;
***************
*** 3596,3608 ****
PATH *p1 = PG_GETARG_PATH_P(0);
PATH *p2 = PG_GETARG_PATH_P(1);
PATH *result;
! int size;
int i;
if (p1->closed || p2->closed)
PG_RETURN_NULL();
! size = offsetof(PATH, p[0]) +sizeof(p1->p[0]) * (p1->npts + p2->npts);
result = (PATH *) palloc(size);
result->size = size;
--- 3602,3622 ----
PATH *p1 = PG_GETARG_PATH_P(0);
PATH *p2 = PG_GETARG_PATH_P(1);
PATH *result;
! int size,
! base_size;
int i;
if (p1->closed || p2->closed)
PG_RETURN_NULL();
! base_size = sizeof(p1->p[0]) * (p1->npts + p2->npts);
! size = offsetof(PATH, p[0]) + base_size;
!
! /* Check for integer overflow */
! if (base_size / sizeof(p1->p[0]) != (p1->npts + p2->npts) ||
! size <= base_size)
! elog(ERROR, "too many points requested.");
!
result = (PATH *) palloc(size);
result->size = size;
***************
*** 4413,4429 ****
int32 npts = PG_GETARG_INT32(0);
CIRCLE *circle = PG_GETARG_CIRCLE_P(1);
POLYGON *poly;
! int size;
int i;
double angle;
if (FPzero(circle->radius) || (npts < 2))
elog(ERROR, "Unable to convert circle to polygon");
! size = offsetof(POLYGON, p[0]) +(sizeof(poly->p[0]) * npts);
poly = (POLYGON *) palloc(size);
! MemSet((char *) poly, 0, size); /* zero any holes */
poly->size = size;
poly->npts = npts;
--- 4427,4450 ----
int32 npts = PG_GETARG_INT32(0);
CIRCLE *circle = PG_GETARG_CIRCLE_P(1);
POLYGON *poly;
! int base_size,
! size;
int i;
double angle;
if (FPzero(circle->radius) || (npts < 2))
elog(ERROR, "Unable to convert circle to polygon");
! base_size = sizeof(poly->p[0]) * npts;
! size = offsetof(POLYGON, p[0]) + base_size;
!
! /* Check for integer overflow */
! if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
! elog(ERROR, "too many points requested");
!
poly = (POLYGON *) palloc(size);
! MemSet(poly, 0, size); /* zero any holes */
poly->size = size;
poly->npts = npts;
Your patch has been added to the PostgreSQL unapplied patches list at:
http://candle.pha.pa.us/cgi-bin/pgpatches
I will try to apply it within the next 48 hours.
---------------------------------------------------------------------------
Neil Conway wrote:
Sir Mordred The Traitor <mordred@s-mail.com> writes:
Upon invoking a polygon(integer, circle) function a
src/backend/utils/adt/geo_ops.c:circle_poly() function will gets
called, which suffers from a buffer overflow.2) A src/backend/adt/utils/geo_ops.c:path_encode() fails to detect a
buffer overrun condition. It is called in multiple places, the most
interesting are path_out() and poly_out() functions.5) A src/backend/utils/adt/geo_ops.c:path_add() also fails to detect
a simple buffer overrun.I've attached a patch which should fix these problems.
3) Upon converting a char string to a path object, a
src/backend/utils/adt/geo_ops.c:path_in() function will gets called,
which suffers from a buffer overrun, caused by a very long argument.4) A src/backend/utils/adt/geo_ops.c:poly_in() function fails to
detect a buffer overrun condition caused by a very long argument.I wasn't able to reproduce either of these (wouldn't it require an
input string with several hundred thousand commas?), can you give me a
test-case?Cheers,
Neil
--
Neil Conway <neilc@samurai.com> || PGP Key ID: DB3C29FC
[ Attachment, skipping... ]
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Patch applied. Thanks.
---------------------------------------------------------------------------
Neil Conway wrote:
Sir Mordred The Traitor <mordred@s-mail.com> writes:
Upon invoking a polygon(integer, circle) function a
src/backend/utils/adt/geo_ops.c:circle_poly() function will gets
called, which suffers from a buffer overflow.2) A src/backend/adt/utils/geo_ops.c:path_encode() fails to detect a
buffer overrun condition. It is called in multiple places, the most
interesting are path_out() and poly_out() functions.5) A src/backend/utils/adt/geo_ops.c:path_add() also fails to detect
a simple buffer overrun.I've attached a patch which should fix these problems.
3) Upon converting a char string to a path object, a
src/backend/utils/adt/geo_ops.c:path_in() function will gets called,
which suffers from a buffer overrun, caused by a very long argument.4) A src/backend/utils/adt/geo_ops.c:poly_in() function fails to
detect a buffer overrun condition caused by a very long argument.I wasn't able to reproduce either of these (wouldn't it require an
input string with several hundred thousand commas?), can you give me a
test-case?Cheers,
Neil
--
Neil Conway <neilc@samurai.com> || PGP Key ID: DB3C29FC
[ Attachment, skipping... ]
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073