List:Commits« Previous MessageNext Message »
From:Magnus Svensson Date:October 22 2007 2:36pm
Subject:Re: bk commit into 5.0 tree (davi:1.2543) BUG#31669
View as plain text  
mån 2007-10-22 klockan 10:08 -0300 skrev Davi Arnaut:
> Magnus Svensson wrote:
> > fre 2007-10-19 klockan 12:32 -0300 skrev Davi Arnaut:
> >> Below is the list of changes that have just been committed into a local
> >> 5.0 repository of davi. When davi does a push these changes will
> >> be propagated to the main repository and, within 24 hours after the
> >> push, to the public repository.
> >> For information on how to access the public repository
> >> see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
> >>
> >> ChangeSet@stripped, 2007-10-19 12:32:33-03:00, davi@stripped +2 -0
> >>   Bug#31669 Buffer overflow in mysql_change_user()
> >>   
> >>   The problem is that when copying the supplied username and
> >>   database, no bounds checking is performed on the fixed-length
> >>   buffer. A sufficiently large (> 512) user string can easily
> >>   cause stack corruption. Since this API can be used from PHP
> >>   and other programs, this is a serious problem.
> >>   
> >>   The solution is to increase the buffer size to the accepted
> >>   size in similar functions and perform bounds checking when
> >>   copying the username and database.
> >>
> >>   libmysql/libmysql.c@stripped, 2007-10-19 12:32:30-03:00, davi@stripped
> +5 -3
> >>     Increase the buffer size and perform bounds checking when copying
> >>     the supplied arguments.
> >>
> >>   tests/mysql_client_test.c@stripped, 2007-10-19 12:32:30-03:00,
> davi@stripped +31 -0
> >>     Add test case for Bug#31669
> >>
> >> diff -Nrup a/libmysql/libmysql.c b/libmysql/libmysql.c
> >> --- a/libmysql/libmysql.c	2007-10-17 14:22:40 -03:00
> >> +++ b/libmysql/libmysql.c	2007-10-19 12:32:30 -03:00
> >> @@ -706,7 +706,8 @@ int cli_read_change_user_result(MYSQL *m
> >>  my_bool	STDCALL mysql_change_user(MYSQL *mysql, const char *user,
> >>  				  const char *passwd, const char *db)
> >>  {
> >> -  char buff[512],*end=buff;
> >> +  char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+100];
> > 
> > magnus: Hmm, how large does that get? Looking at
> > 'client_mysql_real_connect' we use "NAME_LEN+USER_NAME_LENGTH+100" and
> > maybe that is actually enough?
> 
> I prefer to explicitly count the scrambled password length.
> 
> > Isn't the +100 supposed to take care of
> > allocating some extra space for "password and stuff" ;)
> > 
> > Please think a little more about size of this buffer. Maybe we should
> > reserve the proper size for "db" that we also put in there? Then we can
> > probably skip the +100 "magic constant".
> 
> I think I should have skipped it.. we won't copy more then
> USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH + NAME_LEN anyway.
> 
> Checking just in case:
> 
> USERNAME_LENGTH is 16.
> SCRAMBLED_PASSWORD_CHAR_LENGTH is 20*2+1.
> NAME_LEN is 64.
> NUL's + 2.
> 
> Well, dunno where that magic +100 comes from. I think we can safely just
> use: USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH + NAME_LEN + 2

That will be fine.

> 
> >> +  char *end=buff;
> > magnus:        ^ space between = and buff
> 
> Ok.
> 
> >>    int rc;
> >>    DBUG_ENTER("mysql_change_user");
> >>  
> >> @@ -716,7 +717,8 @@ my_bool	STDCALL mysql_change_user(MYSQL 
> >>      passwd="";
> >>  
> >>    /* Store user into the buffer */
> >> -  end=strmov(end,user)+1;
> >> +  strmake(end, user, USERNAME_LENGTH);
> >> +  end= strend(end) + 1;
> > 
> > magnus:     "strmake() returns pointer to closing null" according to
> > comment in strings/strmake.c - I guess you could skip the strend call as
> > you do in the next call to 'strmake'
> 
> Ok.
> 
> >>  
> >>    /* write scrambled password according to server capabilities */
> >>    if (passwd[0])
> >> @@ -736,7 +738,7 @@ my_bool	STDCALL mysql_change_user(MYSQL 
> >>    else
> >>      *end++= '\0';                               /* empty password */
> >>    /* Add database if needed */
> >> -  end= strmov(end, db ? db : "") + 1;
> >> +  end= strmake(end, db ? db : "", NAME_LEN) + 1;
> > 
> > magnus: ok.
> > 
> >>  
> >>    /* Write authentication package */
> >>    simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1);
> >> diff -Nrup a/tests/mysql_client_test.c b/tests/mysql_client_test.c
> >> --- a/tests/mysql_client_test.c	2007-09-14 23:45:13 -03:00
> >> +++ b/tests/mysql_client_test.c	2007-10-19 12:32:30 -03:00
> >> @@ -15857,6 +15857,36 @@ static void test_bug29306()
> >>    DBUG_VOID_RETURN;
> >>  }
> >>  
> >> +
> >> +/**
> >> +  Bug#31669 Buffer overflow in mysql_change_user()
> >> +*/
> >> +
> >> +static void test_bug31669()
> >> +{
> >> +  int rc;
> >> +  char buff[4096];
> >> +
> >> +  DBUG_ENTER("test_bug31669");
> >> +  myheader("test_bug31669");
> >> +
> >> +  rc= mysql_change_user(mysql, NULL, NULL, NULL);
> >> +  DIE_UNLESS(rc);
> >> +
> >> +  rc= mysql_change_user(mysql, "", "", "");
> >> +  DIE_UNLESS(rc);
> >> +
> >> +  memset(buff, 'a', sizeof(buff));
> >> +
> >> +  rc= mysql_change_user(mysql, buff, buff, buff);
> >> +  DIE_UNLESS(rc);
> >> +
> >> +  rc = mysql_change_user(mysql, opt_user, opt_password, current_db);
> >> +  DIE_UNLESS(!rc);
> > 
> > magnus: Maybe add a test that checks the function succeeds when using
> > the max allowed value of user, password and db?
> 
> Will do.
> 
> Thanks,
> 
> -- 
> Davi Arnaut, Software Engineer
> MySQL Inc, www.mysql.com
> 
> Are you MySQL certified?  www.mysql.com/certification
> 
-- 
Magnus Svensson
Senior Software Engineer
msvensson@stripped
+46709164491

Thread
bk commit into 5.0 tree (davi:1.2543) BUG#31669Davi Arnaut19 Oct
  • Re: bk commit into 5.0 tree (davi:1.2543) BUG#31669Magnus Svensson22 Oct
    • Re: bk commit into 5.0 tree (davi:1.2543) BUG#31669Davi Arnaut22 Oct
      • Re: bk commit into 5.0 tree (davi:1.2543) BUG#31669Magnus Svensson22 Oct