1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

BUG#47598 - MyISAM may write uninitialized data to disk

When MyISAM writes newly created index page it may be
initialized partially. In other words some bytes of
sensible data and uninitialized tail of the page may
go into index file.

Under certain rare circumstances these hunks of memory
may contain data that would be otherwise inaccessible
to user, like passwords or data from other tables.

Fixed by initializing memory for temporary MyISAM key
buffer to '\0'.

No test case for this fix as it is heavily covered by
existing tests.

storage/myisam/mi_open.c:
  When creating new MI_INFO object, initialize MI_INFO::buff.
  This is done to ensure that we never write uninitialized
  memory hunks to index file.
storage/myisam/mi_page.c:
  No need to silence memory error detector anymore,
  page buffer is always initialized.
storage/myisam/mi_write.c:
  Fixed invalid memory read of 2 bytes. new_right_length
  is length of data on a page, including first 2 bytes
  that store this length itself. pos + k_length is pure
  data excluding these 2 bytes containing length.
storage/myisam/rt_index.c:
  To avoid uninitialized data write, create new page
  on info->buff, instead of locally allocated buffer.
  
  Note: second key block on info->buff is used here,
  because first block is used by called functions.
storage/myisam/rt_split.c:
  To avoid uninitialized data write, create new page
  on info->buff, instead of locally allocated buffer.
This commit is contained in:
Sergey Vojtovich
2010-03-25 15:18:14 +04:00
parent 0ed4684547
commit 85094f3cc1
5 changed files with 7 additions and 26 deletions

View File

@@ -652,6 +652,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
myisam_open_list=list_add(myisam_open_list,&m_info->open_list); myisam_open_list=list_add(myisam_open_list,&m_info->open_list);
pthread_mutex_unlock(&THR_LOCK_myisam); pthread_mutex_unlock(&THR_LOCK_myisam);
bzero(info.buff, share->base.max_key_block_length * 2);
if (myisam_log_file >= 0) if (myisam_log_file >= 0)
{ {
intern_filename(name_buff,share->index_file_name); intern_filename(name_buff,share->index_file_name);

View File

@@ -86,13 +86,6 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if ((length=keyinfo->block_length) > IO_SIZE*2 && if ((length=keyinfo->block_length) > IO_SIZE*2 &&
info->state->key_file_length != page+length) info->state->key_file_length != page+length)
length= ((mi_getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1)); length= ((mi_getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1));
#ifdef HAVE_purify
{
length=mi_getint(buff);
bzero((uchar*) buff+length,keyinfo->block_length-length);
length=keyinfo->block_length;
}
#endif
DBUG_RETURN((key_cache_write(info->s->key_cache, DBUG_RETURN((key_cache_write(info->s->key_cache,
info->s->kfile,page, level, (uchar*) buff,length, info->s->kfile,page, level, (uchar*) buff,length,
(uint) keyinfo->block_length, (uint) keyinfo->block_length,

View File

@@ -825,7 +825,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
(size_t) (length=new_left_length - left_length - k_length)); (size_t) (length=new_left_length - left_length - k_length));
pos=buff+2+length; pos=buff+2+length;
memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length); memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length);
bmove((uchar*) buff+2,(uchar*) pos+k_length,new_right_length); bmove((uchar*) buff + 2, (uchar*) pos + k_length, new_right_length - 2);
} }
else else
{ /* Move keys -> buff */ { /* Move keys -> buff */

View File

@@ -641,18 +641,12 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
} }
case 1: /* root was split, grow a new root */ case 1: /* root was split, grow a new root */
{ {
uchar *new_root_buf; uchar *new_root_buf= info->buff + info->s->base.max_key_block_length;
my_off_t new_root; my_off_t new_root;
uchar *new_key; uchar *new_key;
uint nod_flag = info->s->base.key_reflength; uint nod_flag = info->s->base.key_reflength;
DBUG_PRINT("rtree", ("root was split, grow a new root")); DBUG_PRINT("rtree", ("root was split, grow a new root"));
if (!(new_root_buf = (uchar*)my_alloca((uint)keyinfo->block_length +
MI_MAX_KEY_BUFF)))
{
my_errno = HA_ERR_OUT_OF_MEM;
DBUG_RETURN(-1); /* purecov: inspected */
}
mi_putint(new_root_buf, 2, nod_flag); mi_putint(new_root_buf, 2, nod_flag);
if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) == if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) ==
@@ -680,10 +674,8 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key,
DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u", DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u",
(ulong) new_root, 0, mi_test_if_nod(new_root_buf))); (ulong) new_root, 0, mi_test_if_nod(new_root_buf)));
my_afree((uchar*)new_root_buf);
break; break;
err1: err1:
my_afree((uchar*)new_root_buf);
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
} }
default: default:

View File

@@ -258,7 +258,7 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
double *old_coord; double *old_coord;
int n_dim; int n_dim;
uchar *source_cur, *cur1, *cur2; uchar *source_cur, *cur1, *cur2;
uchar *new_page; uchar *new_page= info->buff;
int err_code= 0; int err_code= 0;
uint nod_flag= mi_test_if_nod(page); uint nod_flag= mi_test_if_nod(page);
uint full_length= key_length + (nod_flag ? nod_flag : uint full_length= key_length + (nod_flag ? nod_flag :
@@ -304,12 +304,7 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
goto split_err; goto split_err;
} }
if (!(new_page = (uchar*)my_alloca((uint)keyinfo->block_length))) info->buff_used= 1;
{
err_code= -1;
goto split_err;
}
stop = task + (max_keys + 1); stop = task + (max_keys + 1);
cur1 = rt_PAGE_FIRST_KEY(page, nod_flag); cur1 = rt_PAGE_FIRST_KEY(page, nod_flag);
cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag); cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag);
@@ -345,8 +340,6 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key,
DFLT_INIT_HITS, new_page); DFLT_INIT_HITS, new_page);
DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs)); DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs));
my_afree((uchar*)new_page);
split_err: split_err:
my_afree((uchar*) coord_buf); my_afree((uchar*) coord_buf);
DBUG_RETURN(err_code); DBUG_RETURN(err_code);