MDEV-7021 Pass directory security descriptor from mysql_install_db.exe to bootstrap
This ensures that directory permissions are correct in all cases, even if boostrap is passed non-standard locations for innodb. Directory permissions are copied from the datadir.
This commit is contained in:
parent
d9b81210fd
commit
e2bc029211
@ -60,12 +60,9 @@ Street, Fifth Floor, Boston, MA 02110-1335 USA
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <aclapi.h>
|
#include <aclapi.h>
|
||||||
/* During copyback, store datadir permissions,
|
|
||||||
use them to create paths for tables specified
|
|
||||||
with DATA DIRECTORY.*/
|
|
||||||
PSECURITY_DESCRIPTOR datadir_security_descriptor;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define ROCKSDB_BACKUP_DIR "#rocksdb"
|
#define ROCKSDB_BACKUP_DIR "#rocksdb"
|
||||||
|
|
||||||
/* list of files to sync for --rsync mode */
|
/* list of files to sync for --rsync mode */
|
||||||
@ -664,19 +661,6 @@ mkdirp(const char *pathname, int Flags, myf MyFlags)
|
|||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
SECURITY_ATTRIBUTES sa{};
|
|
||||||
sa.lpSecurityDescriptor= datadir_security_descriptor;
|
|
||||||
sa.nLength= sizeof(sa);
|
|
||||||
if (CreateDirectory(pathname, datadir_security_descriptor?&sa : NULL)
|
|
||||||
|| GetLastError() == ERROR_ALREADY_EXISTS
|
|
||||||
|| GetLastError() == ERROR_ACCESS_DENIED && strlen(pathname) == 2 && pathname[1]==':')
|
|
||||||
{
|
|
||||||
free(parent);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
#else
|
|
||||||
/* make this one if parent has been made */
|
/* make this one if parent has been made */
|
||||||
if (my_mkdir(pathname, Flags, MyFlags) == 0) {
|
if (my_mkdir(pathname, Flags, MyFlags) == 0) {
|
||||||
free(parent);
|
free(parent);
|
||||||
@ -688,7 +672,6 @@ mkdirp(const char *pathname, int Flags, myf MyFlags)
|
|||||||
free(parent);
|
free(parent);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
free(parent);
|
free(parent);
|
||||||
return(-1);
|
return(-1);
|
||||||
@ -1757,13 +1740,12 @@ copy_back()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* If we create paths for DATA DIRECTORY, they need
|
/* Initialize security descriptor for the new directories
|
||||||
the same permissions as the datadir, or service won't
|
to be the same as for datadir */
|
||||||
be able to access the files. */
|
|
||||||
DWORD res = GetNamedSecurityInfoA(mysql_data_home,
|
DWORD res = GetNamedSecurityInfoA(mysql_data_home,
|
||||||
SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
|
SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
&datadir_security_descriptor);
|
&my_dir_security_attributes.lpSecurityDescriptor);
|
||||||
if (res != ERROR_SUCCESS) {
|
if (res != ERROR_SUCCESS) {
|
||||||
msg("Unable to read security descriptor of %s",mysql_data_home);
|
msg("Unable to read security descriptor of %s",mysql_data_home);
|
||||||
}
|
}
|
||||||
|
@ -271,6 +271,10 @@ extern int my_umask_dir,
|
|||||||
my_recived_signals, /* Signals we have got */
|
my_recived_signals, /* Signals we have got */
|
||||||
my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */
|
my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */
|
||||||
my_dont_interrupt; /* call remember_intr when set */
|
my_dont_interrupt; /* call remember_intr when set */
|
||||||
|
#ifdef _WIN32
|
||||||
|
extern SECURITY_ATTRIBUTES my_dir_security_attributes;
|
||||||
|
LPSECURITY_ATTRIBUTES my_win_file_secattr();
|
||||||
|
#endif
|
||||||
extern my_bool my_use_symdir;
|
extern my_bool my_use_symdir;
|
||||||
|
|
||||||
extern ulong my_default_record_cache_size;
|
extern ulong my_default_record_cache_size;
|
||||||
|
@ -26,13 +26,18 @@ int my_mkdir(const char *dir, int Flags, myf MyFlags)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("my_dir");
|
DBUG_ENTER("my_dir");
|
||||||
DBUG_PRINT("enter",("dir: %s",dir));
|
DBUG_PRINT("enter",("dir: %s",dir));
|
||||||
|
#ifdef _WIN32
|
||||||
#if defined(__WIN__)
|
LPSECURITY_ATTRIBUTES attr =
|
||||||
if (mkdir((char*) dir))
|
my_dir_security_attributes.lpSecurityDescriptor?
|
||||||
|
&my_dir_security_attributes : NULL;
|
||||||
|
BOOL ok = CreateDirectory(dir, attr);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
my_osmaperr(GetLastError());
|
||||||
#else
|
#else
|
||||||
if (mkdir((char*) dir, Flags & my_umask_dir))
|
if (mkdir((char*) dir, Flags & my_umask_dir))
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
|
#endif
|
||||||
my_errno=errno;
|
my_errno=errno;
|
||||||
DBUG_PRINT("error",("error %d when creating direcory %s",my_errno,dir));
|
DBUG_PRINT("error",("error %d when creating direcory %s",my_errno,dir));
|
||||||
if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
|
if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
|
||||||
|
@ -63,7 +63,9 @@ char curr_dir[FN_REFLEN]= {0},
|
|||||||
ulong my_stream_opened=0,my_tmp_file_created=0;
|
ulong my_stream_opened=0,my_tmp_file_created=0;
|
||||||
ulong my_file_total_opened= 0;
|
ulong my_file_total_opened= 0;
|
||||||
int my_umask=0664, my_umask_dir=0777;
|
int my_umask=0664, my_umask_dir=0777;
|
||||||
|
#ifdef _WIN32
|
||||||
|
SECURITY_ATTRIBUTES my_dir_security_attributes= {sizeof(SECURITY_ATTRIBUTES),NULL,FALSE};
|
||||||
|
#endif
|
||||||
myf my_global_flags= 0;
|
myf my_global_flags= 0;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
my_bool my_assert= 1;
|
my_bool my_assert= 1;
|
||||||
|
@ -103,6 +103,25 @@ static int my_get_open_flags(File fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Default security attributes for files and directories
|
||||||
|
Usually NULL, but can be set
|
||||||
|
- by either mysqld --bootstrap when started from
|
||||||
|
mysql_install_db.exe, and creating windows service
|
||||||
|
- or by mariabackup --copy-back.
|
||||||
|
|
||||||
|
The objective in both cases is to fix file or directory
|
||||||
|
privileges for those files that are outside of the usual
|
||||||
|
datadir, so that unprivileged service account has full
|
||||||
|
access to the files.
|
||||||
|
*/
|
||||||
|
LPSECURITY_ATTRIBUTES my_win_file_secattr()
|
||||||
|
{
|
||||||
|
return my_dir_security_attributes.lpSecurityDescriptor?
|
||||||
|
&my_dir_security_attributes : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Open a file with sharing. Similar to _sopen() from libc, but allows managing
|
Open a file with sharing. Similar to _sopen() from libc, but allows managing
|
||||||
share delete on win32
|
share delete on win32
|
||||||
@ -128,7 +147,6 @@ File my_win_sopen(const char *path, int oflag, int shflag, int pmode)
|
|||||||
DWORD fileshare; /* OS file sharing mode */
|
DWORD fileshare; /* OS file sharing mode */
|
||||||
DWORD filecreate; /* OS method of opening/creating */
|
DWORD filecreate; /* OS method of opening/creating */
|
||||||
DWORD fileattrib; /* OS file attribute flags */
|
DWORD fileattrib; /* OS file attribute flags */
|
||||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
|
||||||
|
|
||||||
DBUG_ENTER("my_win_sopen");
|
DBUG_ENTER("my_win_sopen");
|
||||||
|
|
||||||
@ -137,9 +155,6 @@ File my_win_sopen(const char *path, int oflag, int shflag, int pmode)
|
|||||||
errno= EACCES;
|
errno= EACCES;
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
SecurityAttributes.nLength= sizeof(SecurityAttributes);
|
|
||||||
SecurityAttributes.lpSecurityDescriptor= NULL;
|
|
||||||
SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
|
|
||||||
|
|
||||||
/* decode the access flags */
|
/* decode the access flags */
|
||||||
switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
|
switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
|
||||||
@ -247,7 +262,7 @@ File my_win_sopen(const char *path, int oflag, int shflag, int pmode)
|
|||||||
fileattrib|= FILE_FLAG_RANDOM_ACCESS;
|
fileattrib|= FILE_FLAG_RANDOM_ACCESS;
|
||||||
|
|
||||||
/* try to open/create the file */
|
/* try to open/create the file */
|
||||||
if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
|
if ((osfh= CreateFile(path, fileaccess, fileshare,my_win_file_secattr(),
|
||||||
filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
|
filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <accctrl.h>
|
#include <accctrl.h>
|
||||||
#include <aclapi.h>
|
#include <aclapi.h>
|
||||||
#include <ntsecapi.h>
|
#include <ntsecapi.h>
|
||||||
|
#include <sddl.h>
|
||||||
struct IUnknown;
|
struct IUnknown;
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
|
||||||
@ -729,6 +730,26 @@ static int create_db_instance()
|
|||||||
set_directory_permissions(opt_datadir, service_user.c_str());
|
set_directory_permissions(opt_datadir, service_user.c_str());
|
||||||
set_directory_permissions("mysql",service_user.c_str());
|
set_directory_permissions("mysql",service_user.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get security descriptor for the new directory.
|
||||||
|
It will be passed, as SDDL text, to the mysqld bootstrap subprocess,
|
||||||
|
to allow for correct subdirectory permissions.
|
||||||
|
*/
|
||||||
|
PSECURITY_DESCRIPTOR pSD;
|
||||||
|
if (GetNamedSecurityInfoA(opt_datadir,SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
|
||||||
|
0,0,0,0,&pSD) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
char* string_sd = NULL;
|
||||||
|
if (ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1,
|
||||||
|
DACL_SECURITY_INFORMATION,&string_sd,0))
|
||||||
|
{
|
||||||
|
_putenv_s("MARIADB_NEW_DIRECTORY_SDDL",string_sd);
|
||||||
|
LocalFree(string_sd);
|
||||||
|
}
|
||||||
|
LocalFree(pSD);
|
||||||
|
}
|
||||||
|
|
||||||
/* Do mysqld --bootstrap. */
|
/* Do mysqld --bootstrap. */
|
||||||
init_bootstrap_command_line(cmdline, sizeof(cmdline));
|
init_bootstrap_command_line(cmdline, sizeof(cmdline));
|
||||||
|
|
||||||
@ -843,7 +864,7 @@ end:
|
|||||||
|
|
||||||
/*Remove all service user privileges for the user.*/
|
/*Remove all service user privileges for the user.*/
|
||||||
if(strncmp(service_user.c_str(), "NT SERVICE\\",
|
if(strncmp(service_user.c_str(), "NT SERVICE\\",
|
||||||
sizeof("NT SERVICE\\")-1)
|
sizeof("NT SERVICE\\")-1))
|
||||||
{
|
{
|
||||||
handle_user_privileges(service_user.c_str(), 0, false);
|
handle_user_privileges(service_user.c_str(), 0, false);
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,7 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <handle_connections_win.h>
|
#include <handle_connections_win.h>
|
||||||
|
#include <sddl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <my_service_manager.h>
|
#include <my_service_manager.h>
|
||||||
@ -8166,6 +8167,23 @@ mysqld_get_one_option(const struct my_option *opt, char *argument,
|
|||||||
break;
|
break;
|
||||||
case OPT_BOOTSTRAP:
|
case OPT_BOOTSTRAP:
|
||||||
opt_noacl=opt_bootstrap=1;
|
opt_noacl=opt_bootstrap=1;
|
||||||
|
#ifdef _WIN32
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Check if security descriptor is passed from
|
||||||
|
mysql_install_db.exe.
|
||||||
|
Used by Windows installer to correctly setup
|
||||||
|
privileges on the new directories.
|
||||||
|
*/
|
||||||
|
char* dir_sddl = getenv("MARIADB_NEW_DIRECTORY_SDDL");
|
||||||
|
if (dir_sddl)
|
||||||
|
{
|
||||||
|
ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||||||
|
dir_sddl, SDDL_REVISION_1, &my_dir_security_attributes.lpSecurityDescriptor, NULL);
|
||||||
|
DBUG_ASSERT(my_dir_security_attributes.lpSecurityDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case OPT_SERVER_ID:
|
case OPT_SERVER_ID:
|
||||||
::server_id= global_system_variables.server_id;
|
::server_id= global_system_variables.server_id;
|
||||||
|
@ -233,6 +233,7 @@ static void buf_dump_generate_path(char *path, size_t path_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
Perform a buffer pool dump into the file specified by
|
Perform a buffer pool dump into the file specified by
|
||||||
innodb_buffer_pool_filename. If any errors occur then the value of
|
innodb_buffer_pool_filename. If any errors occur then the value of
|
||||||
@ -262,7 +263,10 @@ buf_dump(
|
|||||||
buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) to %s",
|
buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) to %s",
|
||||||
full_filename);
|
full_filename);
|
||||||
|
|
||||||
#if defined(__GLIBC__) || defined(__WIN__) || O_CLOEXEC == 0
|
#ifdef _WIN32
|
||||||
|
/* use my_fopen() for correct permissions during bootstrap*/
|
||||||
|
f = my_fopen(tmp_filename, O_RDWR|O_TRUNC|O_CREAT, 0);
|
||||||
|
#elif defined(__GLIBC__) || defined(__WIN__) || O_CLOEXEC == 0
|
||||||
f = fopen(tmp_filename, "w" STR_O_CLOEXEC);
|
f = fopen(tmp_filename, "w" STR_O_CLOEXEC);
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
@ -375,7 +379,7 @@ buf_dump(
|
|||||||
ut_free(dump);
|
ut_free(dump);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
ret = fclose(f);
|
ret = IF_WIN(my_fclose(f,0),fclose(f));
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
buf_dump_status(STATUS_ERR,
|
buf_dump_status(STATUS_ERR,
|
||||||
"Cannot close '%s': %s",
|
"Cannot close '%s': %s",
|
||||||
|
@ -73,11 +73,11 @@ Created 10/21/1995 Heikki Tuuri
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winioctl.h>
|
#include <winioctl.h>
|
||||||
#else
|
|
||||||
// my_test_if_atomic_write()
|
|
||||||
#include <my_sys.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// my_test_if_atomic_write() , my_win_secattr()
|
||||||
|
#include <my_sys.h>
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@ -2005,6 +2005,10 @@ os_file_get_last_error_low(
|
|||||||
" because of either a thread exit"
|
" because of either a thread exit"
|
||||||
" or an application request."
|
" or an application request."
|
||||||
" Retry attempt is made.";
|
" Retry attempt is made.";
|
||||||
|
} else if (err == ERROR_PATH_NOT_FOUND) {
|
||||||
|
ib::error()
|
||||||
|
<< "This error means that directory did not exist"
|
||||||
|
" during file creation.";
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ib::info() << OPERATING_SYSTEM_ERROR_MSG;
|
ib::info() << OPERATING_SYSTEM_ERROR_MSG;
|
||||||
@ -2137,7 +2141,7 @@ os_file_create_simple_func(
|
|||||||
file = CreateFile(
|
file = CreateFile(
|
||||||
(LPCTSTR) name, access,
|
(LPCTSTR) name, access,
|
||||||
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||||
NULL, create_flag, attributes, NULL);
|
my_win_file_secattr(), create_flag, attributes, NULL);
|
||||||
|
|
||||||
if (file == INVALID_HANDLE_VALUE) {
|
if (file == INVALID_HANDLE_VALUE) {
|
||||||
|
|
||||||
@ -2543,7 +2547,7 @@ os_file_create_func(
|
|||||||
|
|
||||||
/* Use default security attributes and no template file. */
|
/* Use default security attributes and no template file. */
|
||||||
file = CreateFile(
|
file = CreateFile(
|
||||||
name, access, share_mode, NULL,
|
name, access, share_mode, my_win_file_secattr(),
|
||||||
create_flag, attributes, NULL);
|
create_flag, attributes, NULL);
|
||||||
|
|
||||||
/* If FILE_FLAG_NO_BUFFERING was set, check if this can work at all,
|
/* If FILE_FLAG_NO_BUFFERING was set, check if this can work at all,
|
||||||
@ -2597,6 +2601,7 @@ A simple function to open or create a file.
|
|||||||
@param[out] success true if succeeded
|
@param[out] success true if succeeded
|
||||||
@return own: handle to the file, not defined if error, error number
|
@return own: handle to the file, not defined if error, error number
|
||||||
can be retrieved with os_file_get_last_error */
|
can be retrieved with os_file_get_last_error */
|
||||||
|
|
||||||
pfs_os_file_t
|
pfs_os_file_t
|
||||||
os_file_create_simple_no_error_handling_func(
|
os_file_create_simple_no_error_handling_func(
|
||||||
const char* name,
|
const char* name,
|
||||||
@ -2678,7 +2683,7 @@ os_file_create_simple_no_error_handling_func(
|
|||||||
file = CreateFile((LPCTSTR) name,
|
file = CreateFile((LPCTSTR) name,
|
||||||
access,
|
access,
|
||||||
share_mode,
|
share_mode,
|
||||||
NULL, // Security attributes
|
my_win_file_secattr(),
|
||||||
create_flag,
|
create_flag,
|
||||||
attributes,
|
attributes,
|
||||||
NULL); // No template file
|
NULL); // No template file
|
||||||
@ -2968,7 +2973,7 @@ os_file_get_status_win32(
|
|||||||
access,
|
access,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE
|
FILE_SHARE_READ | FILE_SHARE_WRITE
|
||||||
| FILE_SHARE_DELETE, // Full sharing
|
| FILE_SHARE_DELETE, // Full sharing
|
||||||
NULL, // Default security
|
my_win_file_secattr(),
|
||||||
OPEN_EXISTING, // Existing file only
|
OPEN_EXISTING, // Existing file only
|
||||||
FILE_ATTRIBUTE_NORMAL, // Normal file
|
FILE_ATTRIBUTE_NORMAL, // Normal file
|
||||||
NULL); // No attr. template
|
NULL); // No attr. template
|
||||||
|
Loading…
x
Reference in New Issue
Block a user