MDEV-11902 mi_open race condition
TOCTOU bug. The path is checked to be valid, symlinks are resolved. Then the resolved path is opened. Between the check and the open, there's a window when one can replace some path component with a symlink, bypassing validity checks. Fix: after we resolved all symlinks in the path, don't allow open() to resolve symlinks, there should be none. Compared to the old MyISAM/Aria code: * fastpath. Opening of not-symlinked files is just one open(), no fn_format() and lstat() anymore. * opening of symlinked tables doesn't do fn_format() and lstat() either. it also doesn't to realpath() (which was lstat-ing every path component), instead if opens every path component with O_PATH. * share->data_file_name stores realpath(path) not readlink(path). So, SHOW CREATE TABLE needs to do lstat/readlink() now (see ::info()), and certain error messages (cannot open file "XXX") show the real file path with all symlinks resolved.
This commit is contained in:
parent
d78d0d459d
commit
b27fd90ad3
@ -63,9 +63,9 @@ typedef struct my_aio_result {
|
|||||||
#define MY_FAE 8 /* Fatal if any error */
|
#define MY_FAE 8 /* Fatal if any error */
|
||||||
#define MY_WME 16 /* Write message on error */
|
#define MY_WME 16 /* Write message on error */
|
||||||
#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */
|
#define MY_WAIT_IF_FULL 32 /* Wait and try again if disk full error */
|
||||||
#define MY_IGNORE_BADFD 32 /* my_sync: ignore 'bad descriptor' errors */
|
#define MY_IGNORE_BADFD 32 /* my_sync(): ignore 'bad descriptor' errors */
|
||||||
#define MY_UNUSED 64 /* Unused (was support for RAID) */
|
#define MY_NOSYMLINKS 512 /* my_open(): don't follow symlinks */
|
||||||
#define MY_FULL_IO 512 /* For my_read - loop intil I/O is complete */
|
#define MY_FULL_IO 512 /* my_read(): loop intil I/O is complete */
|
||||||
#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
|
#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
|
||||||
#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */
|
#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */
|
||||||
#define MY_COPYTIME 64 /* my_redel() copys time */
|
#define MY_COPYTIME 64 /* my_redel() copys time */
|
||||||
|
39
mysql-test/r/symlink-aria-11902.result
Normal file
39
mysql-test/r/symlink-aria-11902.result
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
set default_storage_engine=Aria;
|
||||||
|
call mtr.add_suppression("File.*t1.* not found");
|
||||||
|
create table mysql.t1 (a int, b char(16), index(a));
|
||||||
|
insert mysql.t1 values (100, 'test'),(101,'test');
|
||||||
|
create table t1 (a int, b char(16), index(a))
|
||||||
|
data directory="MYSQLTEST_VARDIR/tmp/foo";
|
||||||
|
insert t1 values (200, 'some'),(201,'some');
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
200 some
|
||||||
|
201 some
|
||||||
|
flush tables;
|
||||||
|
set debug_sync='mi_open_datafile SIGNAL ok WAIT_FOR go';
|
||||||
|
select * from t1;
|
||||||
|
set debug_sync='now WAIT_FOR ok';
|
||||||
|
set debug_sync='now SIGNAL go';
|
||||||
|
ERROR HY000: File 'MYSQLTEST_VARDIR/tmp/foo/t1.MAD' not found (Errcode: 20)
|
||||||
|
flush tables;
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int, b char(16), index (a))
|
||||||
|
index directory="MYSQLTEST_VARDIR/tmp/foo";
|
||||||
|
insert t1 values (200, 'some'),(201,'some');
|
||||||
|
explain select a from t1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL a 5 NULL 2 Using index
|
||||||
|
select a from t1;
|
||||||
|
a
|
||||||
|
200
|
||||||
|
201
|
||||||
|
flush tables;
|
||||||
|
set debug_sync='mi_open_kfile SIGNAL waiting WAIT_FOR run';
|
||||||
|
select a from t1;
|
||||||
|
set debug_sync='now WAIT_FOR waiting';
|
||||||
|
set debug_sync='now SIGNAL run';
|
||||||
|
ERROR HY000: Can't find file: 't1' (errno: 20)
|
||||||
|
flush tables;
|
||||||
|
drop table if exists t1;
|
||||||
|
drop table mysql.t1;
|
||||||
|
set debug_sync='RESET';
|
38
mysql-test/r/symlink-myisam-11902.result
Normal file
38
mysql-test/r/symlink-myisam-11902.result
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
call mtr.add_suppression("File.*t1.* not found");
|
||||||
|
create table mysql.t1 (a int, b char(16), index(a));
|
||||||
|
insert mysql.t1 values (100, 'test'),(101,'test');
|
||||||
|
create table t1 (a int, b char(16), index(a))
|
||||||
|
data directory="MYSQLTEST_VARDIR/tmp/foo";
|
||||||
|
insert t1 values (200, 'some'),(201,'some');
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
200 some
|
||||||
|
201 some
|
||||||
|
flush tables;
|
||||||
|
set debug_sync='mi_open_datafile SIGNAL ok WAIT_FOR go';
|
||||||
|
select * from t1;
|
||||||
|
set debug_sync='now WAIT_FOR ok';
|
||||||
|
set debug_sync='now SIGNAL go';
|
||||||
|
ERROR HY000: File 'MYSQLTEST_VARDIR/tmp/foo/t1.MYD' not found (Errcode: 20)
|
||||||
|
flush tables;
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (a int, b char(16), index (a))
|
||||||
|
index directory="MYSQLTEST_VARDIR/tmp/foo";
|
||||||
|
insert t1 values (200, 'some'),(201,'some');
|
||||||
|
explain select a from t1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 index NULL a 5 NULL 2 Using index
|
||||||
|
select a from t1;
|
||||||
|
a
|
||||||
|
200
|
||||||
|
201
|
||||||
|
flush tables;
|
||||||
|
set debug_sync='mi_open_kfile SIGNAL waiting WAIT_FOR run';
|
||||||
|
select a from t1;
|
||||||
|
set debug_sync='now WAIT_FOR waiting';
|
||||||
|
set debug_sync='now SIGNAL run';
|
||||||
|
ERROR HY000: Can't find file: 't1' (errno: 20)
|
||||||
|
flush tables;
|
||||||
|
drop table if exists t1;
|
||||||
|
drop table mysql.t1;
|
||||||
|
set debug_sync='RESET';
|
@ -27,9 +27,6 @@ TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE ROW_FORMAT TABLE_ROWS DATA_LENGTH TABL
|
|||||||
test t1 BASE TABLE NULL NULL NULL NULL Can't find file: 't1' (errno: 2)
|
test t1 BASE TABLE NULL NULL NULL NULL Can't find file: 't1' (errno: 2)
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1017 Can't find file: 't1' (errno: 2)
|
Warning 1017 Can't find file: 't1' (errno: 2)
|
||||||
SHOW WARNINGS;
|
|
||||||
Level Code Message
|
|
||||||
Warning 1017 Can't find file: 't1' (errno: 2)
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
ERROR 42S02: Unknown table 't1'
|
ERROR 42S02: Unknown table 't1'
|
||||||
#
|
#
|
||||||
|
@ -61,10 +61,10 @@ let $MYSQLD_DATADIR= `SELECT @@datadir`;
|
|||||||
--echo #
|
--echo #
|
||||||
--echo # Trigger a MyISAM system error during an INFORMATION_SCHEMA.TABLES query
|
--echo # Trigger a MyISAM system error during an INFORMATION_SCHEMA.TABLES query
|
||||||
--echo #
|
--echo #
|
||||||
|
--replace_result 20 2
|
||||||
SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, TABLE_ROWS, DATA_LENGTH, TABLE_COMMENT
|
SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, TABLE_ROWS, DATA_LENGTH, TABLE_COMMENT
|
||||||
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
|
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
|
||||||
|
|
||||||
SHOW WARNINGS;
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
--error 1051
|
--error 1051
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
eval create table t1 (a int) engine=myisam data directory='$MYSQL_TMP_DIR';
|
eval create table t1 (a int) engine=myisam data directory='$MYSQL_TMP_DIR';
|
||||||
insert t1 values (1);
|
insert t1 values (1);
|
||||||
--system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t1.TMD
|
--system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t1.TMD
|
||||||
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
--replace_regex / '.*\/t1/ 'MYSQL_TMP_DIR\/t1/
|
||||||
repair table t1;
|
repair table t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ drop table t1;
|
|||||||
eval create table t2 (a int) engine=aria data directory='$MYSQL_TMP_DIR';
|
eval create table t2 (a int) engine=aria data directory='$MYSQL_TMP_DIR';
|
||||||
insert t2 values (1);
|
insert t2 values (1);
|
||||||
--system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t2.TMD
|
--system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t2.TMD
|
||||||
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
--replace_regex / '.*\/t2/ 'MYSQL_TMP_DIR\/t2/
|
||||||
repair table t2;
|
repair table t2;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
|
||||||
|
6
mysql-test/t/symlink-aria-11902.test
Normal file
6
mysql-test/t/symlink-aria-11902.test
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#
|
||||||
|
# MDEV-11902 mi_open race condition
|
||||||
|
#
|
||||||
|
source include/have_maria.inc;
|
||||||
|
set default_storage_engine=Aria;
|
||||||
|
source symlink-myisam-11902.test;
|
60
mysql-test/t/symlink-myisam-11902.test
Normal file
60
mysql-test/t/symlink-myisam-11902.test
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#
|
||||||
|
# MDEV-11902 mi_open race condition
|
||||||
|
#
|
||||||
|
source include/have_debug_sync.inc;
|
||||||
|
source include/have_symlink.inc;
|
||||||
|
source include/not_windows.inc;
|
||||||
|
call mtr.add_suppression("File.*t1.* not found");
|
||||||
|
|
||||||
|
create table mysql.t1 (a int, b char(16), index(a));
|
||||||
|
insert mysql.t1 values (100, 'test'),(101,'test');
|
||||||
|
let $datadir=`select @@datadir`;
|
||||||
|
|
||||||
|
exec mkdir $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR;
|
||||||
|
eval create table t1 (a int, b char(16), index(a))
|
||||||
|
data directory="$MYSQLTEST_VARDIR/tmp/foo";
|
||||||
|
insert t1 values (200, 'some'),(201,'some');
|
||||||
|
select * from t1;
|
||||||
|
flush tables;
|
||||||
|
set debug_sync='mi_open_datafile SIGNAL ok WAIT_FOR go';
|
||||||
|
send select * from t1;
|
||||||
|
connect con1, localhost, root;
|
||||||
|
set debug_sync='now WAIT_FOR ok';
|
||||||
|
exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
exec ln -s $datadir/mysql $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
set debug_sync='now SIGNAL go';
|
||||||
|
connection default;
|
||||||
|
replace_regex / '.*\/tmp\// 'MYSQLTEST_VARDIR\/tmp\// /31/20/;
|
||||||
|
error 29;
|
||||||
|
reap;
|
||||||
|
flush tables;
|
||||||
|
drop table if exists t1;
|
||||||
|
exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
|
||||||
|
# same with INDEX DIRECTORY
|
||||||
|
exec mkdir $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR;
|
||||||
|
eval create table t1 (a int, b char(16), index (a))
|
||||||
|
index directory="$MYSQLTEST_VARDIR/tmp/foo";
|
||||||
|
insert t1 values (200, 'some'),(201,'some');
|
||||||
|
explain select a from t1;
|
||||||
|
select a from t1;
|
||||||
|
flush tables;
|
||||||
|
set debug_sync='mi_open_kfile SIGNAL waiting WAIT_FOR run';
|
||||||
|
send select a from t1;
|
||||||
|
connection con1;
|
||||||
|
set debug_sync='now WAIT_FOR waiting';
|
||||||
|
exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
exec ln -s $datadir/mysql $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
set debug_sync='now SIGNAL run';
|
||||||
|
connection default;
|
||||||
|
replace_regex / '.*\/tmp\// 'MYSQLTEST_VARDIR\/tmp\// /31/20/;
|
||||||
|
error ER_FILE_NOT_FOUND;
|
||||||
|
reap;
|
||||||
|
flush tables;
|
||||||
|
drop table if exists t1;
|
||||||
|
exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
|
||||||
|
|
||||||
|
drop table mysql.t1;
|
||||||
|
set debug_sync='RESET';
|
@ -15,9 +15,14 @@
|
|||||||
|
|
||||||
#include "mysys_priv.h"
|
#include "mysys_priv.h"
|
||||||
#include "mysys_err.h"
|
#include "mysys_err.h"
|
||||||
#include <my_dir.h>
|
#include <m_string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if !defined(O_PATH) && defined(O_EXEC) /* FreeBSD */
|
||||||
|
#define O_PATH O_EXEC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int open_nosymlinks(const char *pathname, int flags, int mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Open a file
|
Open a file
|
||||||
@ -46,7 +51,10 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
fd= my_win_open(FileName, Flags);
|
fd= my_win_open(FileName, Flags);
|
||||||
#else
|
#else
|
||||||
fd = open(FileName, Flags, my_umask);
|
if (MyFlags & MY_NOSYMLINKS)
|
||||||
|
fd = open_nosymlinks(FileName, Flags, my_umask);
|
||||||
|
else
|
||||||
|
fd = open(FileName, Flags, my_umask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fd= my_register_filename(fd, FileName, FILE_BY_OPEN,
|
fd= my_register_filename(fd, FileName, FILE_BY_OPEN,
|
||||||
@ -174,3 +182,81 @@ void my_print_open_files(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
like open(), but with symlinks are not accepted anywhere in the path
|
||||||
|
|
||||||
|
This is used for opening symlinked tables for DATA/INDEX DIRECTORY.
|
||||||
|
The paths there have been realpath()-ed. So, we can assume here that
|
||||||
|
|
||||||
|
* `pathname` is an absolute path
|
||||||
|
* no '.', '..', and '//' in the path
|
||||||
|
* file exists
|
||||||
|
*/
|
||||||
|
static int open_nosymlinks(const char *pathname, int flags, int mode)
|
||||||
|
{
|
||||||
|
#ifndef O_PATH
|
||||||
|
#ifdef HAVE_REALPATH
|
||||||
|
char buf[PATH_MAX+1];
|
||||||
|
if (realpath(pathname, buf) == NULL)
|
||||||
|
return -1;
|
||||||
|
if (strcmp(pathname, buf))
|
||||||
|
{
|
||||||
|
errno= ENOTDIR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return open(pathname, flags, mode | O_NOFOLLOW);
|
||||||
|
#else
|
||||||
|
|
||||||
|
char buf[PATH_MAX+1];
|
||||||
|
char *s= buf, *e= buf+1, *end= strnmov(buf, pathname, sizeof(buf));
|
||||||
|
int fd, dfd= -1;
|
||||||
|
|
||||||
|
if (*end)
|
||||||
|
{
|
||||||
|
errno= ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*s != '/') /* not an absolute path */
|
||||||
|
{
|
||||||
|
errno= ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (*e == '/') /* '//' in the path */
|
||||||
|
{
|
||||||
|
errno= ENOENT;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
while (*e && *e != '/')
|
||||||
|
e++;
|
||||||
|
*e= 0;
|
||||||
|
if (!memcmp(s, ".", 2) || !memcmp(s, "..", 3))
|
||||||
|
{
|
||||||
|
errno= ENOENT;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = openat(dfd, s, O_NOFOLLOW | (e < end ? O_PATH : flags), mode);
|
||||||
|
if (fd < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (dfd >= 0)
|
||||||
|
close(dfd);
|
||||||
|
|
||||||
|
dfd= fd;
|
||||||
|
s= ++e;
|
||||||
|
|
||||||
|
if (e >= end)
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
err:
|
||||||
|
if (dfd >= 0)
|
||||||
|
close(dfd);
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -2908,6 +2908,7 @@ void handler::print_error(int error, myf errflag)
|
|||||||
textno=ER_FILE_USED;
|
textno=ER_FILE_USED;
|
||||||
break;
|
break;
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
|
case ENOTDIR:
|
||||||
textno=ER_FILE_NOT_FOUND;
|
textno=ER_FILE_NOT_FOUND;
|
||||||
break;
|
break;
|
||||||
case ENOSPC:
|
case ENOSPC:
|
||||||
|
@ -312,13 +312,16 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||||||
my_errno= HA_ERR_CRASHED;
|
my_errno= HA_ERR_CRASHED;
|
||||||
goto err;
|
goto err;
|
||||||
});
|
});
|
||||||
|
DEBUG_SYNC_C("mi_open_kfile");
|
||||||
if ((kfile=mysql_file_open(key_file_kfile, name_buff,
|
if ((kfile=mysql_file_open(key_file_kfile, name_buff,
|
||||||
(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
|
(open_mode=O_RDWR) | O_SHARE | O_NOFOLLOW,
|
||||||
|
MYF(MY_NOSYMLINKS))) < 0)
|
||||||
{
|
{
|
||||||
if ((errno != EROFS && errno != EACCES) ||
|
if ((errno != EROFS && errno != EACCES) ||
|
||||||
mode != O_RDONLY ||
|
mode != O_RDONLY ||
|
||||||
(kfile=mysql_file_open(key_file_kfile, name_buff,
|
(kfile=mysql_file_open(key_file_kfile, name_buff,
|
||||||
(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
|
(open_mode=O_RDONLY) | O_SHARE | O_NOFOLLOW,
|
||||||
|
MYF(MY_NOSYMLINKS))) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
share->mode=open_mode;
|
share->mode=open_mode;
|
||||||
@ -363,7 +366,18 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
|||||||
(void) strmov(index_name, org_name);
|
(void) strmov(index_name, org_name);
|
||||||
*strrchr(org_name, FN_EXTCHAR)= '\0';
|
*strrchr(org_name, FN_EXTCHAR)= '\0';
|
||||||
(void) fn_format(data_name,org_name,"",MARIA_NAME_DEXT,
|
(void) fn_format(data_name,org_name,"",MARIA_NAME_DEXT,
|
||||||
MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
|
MY_APPEND_EXT|MY_UNPACK_FILENAME);
|
||||||
|
if (my_is_symlink(data_name))
|
||||||
|
{
|
||||||
|
if (my_realpath(data_name, data_name, MYF(0)))
|
||||||
|
goto err;
|
||||||
|
if (mysys_test_invalid_symlink(data_name))
|
||||||
|
{
|
||||||
|
my_errno= HA_WRONG_CREATE_OPTION;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
share->mode|= O_NOFOLLOW; /* all symlinks are resolved by realpath() */
|
||||||
|
}
|
||||||
|
|
||||||
info_length=mi_uint2korr(share->state.header.header_length);
|
info_length=mi_uint2korr(share->state.header.header_length);
|
||||||
base_pos= mi_uint2korr(share->state.header.base_pos);
|
base_pos= mi_uint2korr(share->state.header.base_pos);
|
||||||
@ -1867,27 +1881,11 @@ void _ma_set_index_pagecache_callbacks(PAGECACHE_FILE *file,
|
|||||||
|
|
||||||
int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share, const char *org_name)
|
int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share, const char *org_name)
|
||||||
{
|
{
|
||||||
char *data_name= share->data_file_name.str;
|
myf flags= MY_WME | (share->mode & O_NOFOLLOW ? MY_NOSYMLINKS : 0);
|
||||||
char real_data_name[FN_REFLEN];
|
DEBUG_SYNC_C("mi_open_datafile");
|
||||||
|
|
||||||
if (org_name)
|
|
||||||
{
|
|
||||||
fn_format(real_data_name, org_name, "", MARIA_NAME_DEXT, 4);
|
|
||||||
if (my_is_symlink(real_data_name))
|
|
||||||
{
|
|
||||||
if (my_realpath(real_data_name, real_data_name, MYF(0)) ||
|
|
||||||
mysys_test_invalid_symlink(real_data_name))
|
|
||||||
{
|
|
||||||
my_errno= HA_WRONG_CREATE_OPTION;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
data_name= real_data_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info->dfile.file= share->bitmap.file.file=
|
info->dfile.file= share->bitmap.file.file=
|
||||||
mysql_file_open(key_file_dfile, data_name,
|
mysql_file_open(key_file_dfile, share->data_file_name.str,
|
||||||
share->mode | O_SHARE, MYF(MY_WME));
|
share->mode | O_SHARE, MYF(flags));
|
||||||
return info->dfile.file >= 0 ? 0 : 1;
|
return info->dfile.file >= 0 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1901,8 +1899,8 @@ int _ma_open_keyfile(MARIA_SHARE *share)
|
|||||||
mysql_mutex_lock(&share->intern_lock);
|
mysql_mutex_lock(&share->intern_lock);
|
||||||
share->kfile.file= mysql_file_open(key_file_kfile,
|
share->kfile.file= mysql_file_open(key_file_kfile,
|
||||||
share->unique_file_name.str,
|
share->unique_file_name.str,
|
||||||
share->mode | O_SHARE,
|
share->mode | O_SHARE | O_NOFOLLOW,
|
||||||
MYF(MY_WME));
|
MYF(MY_WME | MY_NOSYMLINKS));
|
||||||
mysql_mutex_unlock(&share->intern_lock);
|
mysql_mutex_unlock(&share->intern_lock);
|
||||||
return (share->kfile.file < 0);
|
return (share->kfile.file < 0);
|
||||||
}
|
}
|
||||||
|
@ -1874,15 +1874,22 @@ int ha_myisam::info(uint flag)
|
|||||||
Set data_file_name and index_file_name to point at the symlink value
|
Set data_file_name and index_file_name to point at the symlink value
|
||||||
if table is symlinked (Ie; Real name is not same as generated name)
|
if table is symlinked (Ie; Real name is not same as generated name)
|
||||||
*/
|
*/
|
||||||
|
char buf[FN_REFLEN];
|
||||||
data_file_name= index_file_name= 0;
|
data_file_name= index_file_name= 0;
|
||||||
fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
|
fn_format(name_buff, file->filename, "", MI_NAME_DEXT,
|
||||||
MY_APPEND_EXT | MY_UNPACK_FILENAME);
|
MY_APPEND_EXT | MY_UNPACK_FILENAME);
|
||||||
if (strcmp(name_buff, misam_info.data_file_name))
|
if (my_is_symlink(name_buff))
|
||||||
data_file_name=misam_info.data_file_name;
|
{
|
||||||
|
my_readlink(buf, name_buff, MYF(0));
|
||||||
|
data_file_name= ha_thd()->strdup(buf);
|
||||||
|
}
|
||||||
fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
|
fn_format(name_buff, file->filename, "", MI_NAME_IEXT,
|
||||||
MY_APPEND_EXT | MY_UNPACK_FILENAME);
|
MY_APPEND_EXT | MY_UNPACK_FILENAME);
|
||||||
if (strcmp(name_buff, misam_info.index_file_name))
|
if (my_is_symlink(name_buff))
|
||||||
index_file_name=misam_info.index_file_name;
|
{
|
||||||
|
my_readlink(buf, name_buff, MYF(0));
|
||||||
|
index_file_name= ha_thd()->strdup(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (flag & HA_STATUS_ERRKEY)
|
if (flag & HA_STATUS_ERRKEY)
|
||||||
{
|
{
|
||||||
|
@ -114,15 +114,17 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||||||
my_errno= HA_ERR_CRASHED;
|
my_errno= HA_ERR_CRASHED;
|
||||||
goto err;
|
goto err;
|
||||||
});
|
});
|
||||||
if ((kfile= mysql_file_open(mi_key_file_kfile,
|
|
||||||
name_buff,
|
DEBUG_SYNC_C("mi_open_kfile");
|
||||||
(open_mode= O_RDWR) | O_SHARE, MYF(0))) < 0)
|
if ((kfile= mysql_file_open(mi_key_file_kfile, name_buff,
|
||||||
|
(open_mode= O_RDWR) | O_SHARE | O_NOFOLLOW,
|
||||||
|
MYF(MY_NOSYMLINKS))) < 0)
|
||||||
{
|
{
|
||||||
if ((errno != EROFS && errno != EACCES) ||
|
if ((errno != EROFS && errno != EACCES) ||
|
||||||
mode != O_RDONLY ||
|
mode != O_RDONLY ||
|
||||||
(kfile= mysql_file_open(mi_key_file_kfile,
|
(kfile= mysql_file_open(mi_key_file_kfile, name_buff,
|
||||||
name_buff,
|
(open_mode= O_RDONLY) | O_SHARE| O_NOFOLLOW,
|
||||||
(open_mode= O_RDONLY) | O_SHARE, MYF(0))) < 0)
|
MYF(MY_NOSYMLINKS))) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
share->mode=open_mode;
|
share->mode=open_mode;
|
||||||
@ -166,7 +168,18 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
|
|||||||
(void) strmov(index_name, org_name);
|
(void) strmov(index_name, org_name);
|
||||||
*strrchr(org_name, '.')= '\0';
|
*strrchr(org_name, '.')= '\0';
|
||||||
(void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
|
(void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
|
||||||
MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
|
MY_APPEND_EXT|MY_UNPACK_FILENAME);
|
||||||
|
if (my_is_symlink(data_name))
|
||||||
|
{
|
||||||
|
if (my_realpath(data_name, data_name, MYF(0)))
|
||||||
|
goto err;
|
||||||
|
if (mysys_test_invalid_symlink(data_name))
|
||||||
|
{
|
||||||
|
my_errno= HA_WRONG_CREATE_OPTION;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
share->mode|= O_NOFOLLOW; /* all symlinks are resolved by realpath() */
|
||||||
|
}
|
||||||
|
|
||||||
info_length=mi_uint2korr(share->state.header.header_length);
|
info_length=mi_uint2korr(share->state.header.header_length);
|
||||||
base_pos=mi_uint2korr(share->state.header.base_pos);
|
base_pos=mi_uint2korr(share->state.header.base_pos);
|
||||||
@ -1233,25 +1246,10 @@ active seek-positions.
|
|||||||
|
|
||||||
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *org_name)
|
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *org_name)
|
||||||
{
|
{
|
||||||
char *data_name= share->data_file_name;
|
myf flags= MY_WME | (share->mode & O_NOFOLLOW ? MY_NOSYMLINKS: 0);
|
||||||
char real_data_name[FN_REFLEN];
|
DEBUG_SYNC_C("mi_open_datafile");
|
||||||
|
info->dfile= mysql_file_open(mi_key_file_dfile, share->data_file_name,
|
||||||
if (org_name)
|
share->mode | O_SHARE, MYF(flags));
|
||||||
{
|
|
||||||
fn_format(real_data_name,org_name,"",MI_NAME_DEXT,4);
|
|
||||||
if (my_is_symlink(real_data_name))
|
|
||||||
{
|
|
||||||
if (my_realpath(real_data_name, real_data_name, MYF(0)) ||
|
|
||||||
mysys_test_invalid_symlink(real_data_name))
|
|
||||||
{
|
|
||||||
my_errno= HA_WRONG_CREATE_OPTION;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
data_name= real_data_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info->dfile= mysql_file_open(mi_key_file_dfile,
|
|
||||||
data_name, share->mode | O_SHARE, MYF(MY_WME));
|
|
||||||
return info->dfile >= 0 ? 0 : 1;
|
return info->dfile >= 0 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1260,8 +1258,8 @@ int mi_open_keyfile(MYISAM_SHARE *share)
|
|||||||
{
|
{
|
||||||
if ((share->kfile= mysql_file_open(mi_key_file_kfile,
|
if ((share->kfile= mysql_file_open(mi_key_file_kfile,
|
||||||
share->unique_file_name,
|
share->unique_file_name,
|
||||||
share->mode | O_SHARE,
|
share->mode | O_SHARE | O_NOFOLLOW,
|
||||||
MYF(MY_WME))) < 0)
|
MYF(MY_NOSYMLINKS | MY_WME))) < 0)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user