xorl %eax, %eax

CVE-2009-0663: DBD-Pg Heap Buffer Overflow

leave a comment »

DBD-Pg is a Perl library. Specifically, it is a PostgreSQL database driver for the DBI module. It is installed on Debian GNU/Linux as well as RedHat Enterprise Linux 5 desktop and server releases. This issue was published by the Debian project on 28 April 2009. Release 1.49 and probably others are vulnerable to this. The vulnerable function can be found at dbdimp.c:

3   $Id: dbdimp.c,v 1.183 2006/05/04 02:11:14 turnstep Exp $
4
5   Copyright (c) 2002-2006 PostgreSQL Global Development Group
    ...
2796 int
2797 pg_db_getline (dbh, buffer, length)
2798                 SV * dbh;
2799                 char * buffer;
2800                 int length;
2801 {
2802                 D_imp_dbh(dbh);
2803                 int copystatus;
2804                 char * tempbuf;
    ...
2829                 copystatus = PQgetCopyData(imp_dbh->conn, &tempbuf, 0);
2830
2831                 if (-1 == copystatus) {
2832                         *buffer = '';
2833                         imp_dbh->copystate=0;
2834                         PQendcopy(imp_dbh->conn); /* Can't hurt */
2835                         return -1;
2836                 }
    ...
2840                 else {
2841                         strncpy(buffer, tempbuf, strlen(tempbuf)+1);
2842                         buffer[strlen(tempbuf)] = '';
2843                         PQfreemem(tempbuf);
2844                 }
    ...
2848 }

This function is used to copy data but it is considered deprecated according to the documentation. The first mistake of the above code appears appears at line 2932 where it attempts to NULL terminate the buffer since the copy operation at line 2929 failed. This was removed simply like that:

         if (-1 == copystatus) {
-            *buffer = '';
             imp_dbh->copystate=0;

But the vulnerability, is between lines 2841-2842, as you can see it copies tempbuf to buffer and then NULL terminates this based on the size of tempbuf in both cases. This may be larger than the buffer‘s size. At line 2843 it frees the space allocated for tempbuf. This possible memory corruption was fixed by applying the following patch:

         else {
-            strncpy(buffer, tempbuf, strlen(tempbuf)+1);
-            buffer[strlen(tempbuf)] = '';
+            sv_setpv(buffer, tempbuf);
             PQfreemem(tempbuf);

This routine, sv_setpv() is provided by Perl’s API and it determines the length automatically to provide a copy functionality. However, since its prototype is:

void sv_setpv(SV*, char*);

So, variable buffer had to be updated to this type:

         SV * dbh;
-        char * buffer;
+        SV * buffer;
         int length;

Written by xorl

May 13, 2009 at 17:42

Posted in bugs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s