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
|
||||
#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
|
||||
|
||||
|
||||
#define ROCKSDB_BACKUP_DIR "#rocksdb"
|
||||
|
||||
/* list of files to sync for --rsync mode */
|
||||
@ -664,19 +661,6 @@ mkdirp(const char *pathname, int Flags, myf MyFlags)
|
||||
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 */
|
||||
if (my_mkdir(pathname, Flags, MyFlags) == 0) {
|
||||
free(parent);
|
||||
@ -688,7 +672,6 @@ mkdirp(const char *pathname, int Flags, myf MyFlags)
|
||||
free(parent);
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
free(parent);
|
||||
return(-1);
|
||||
@ -1757,13 +1740,12 @@ copy_back()
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* If we create paths for DATA DIRECTORY, they need
|
||||
the same permissions as the datadir, or service won't
|
||||
be able to access the files. */
|
||||
/* Initialize security descriptor for the new directories
|
||||
to be the same as for datadir */
|
||||
DWORD res = GetNamedSecurityInfoA(mysql_data_home,
|
||||
SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
|
||||
NULL, NULL, NULL, NULL,
|
||||
&datadir_security_descriptor);
|
||||
&my_dir_security_attributes.lpSecurityDescriptor);
|
||||
if (res != ERROR_SUCCESS) {
|
||||
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_safe_to_handle_signal, /* Set when allowed to SIGTSTP */
|
||||
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 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_PRINT("enter",("dir: %s",dir));
|
||||
|
||||
#if defined(__WIN__)
|
||||
if (mkdir((char*) dir))
|
||||
#ifdef _WIN32
|
||||
LPSECURITY_ATTRIBUTES attr =
|
||||
my_dir_security_attributes.lpSecurityDescriptor?
|
||||
&my_dir_security_attributes : NULL;
|
||||
BOOL ok = CreateDirectory(dir, attr);
|
||||
if (!ok)
|
||||
{
|
||||
my_osmaperr(GetLastError());
|
||||
#else
|
||||
if (mkdir((char*) dir, Flags & my_umask_dir))
|
||||
#endif
|
||||
{
|
||||
#endif
|
||||
my_errno=errno;
|
||||
DBUG_PRINT("error",("error %d when creating direcory %s",my_errno,dir));
|
||||
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_file_total_opened= 0;
|
||||
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;
|
||||
#ifndef DBUG_OFF
|
||||
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
|
||||
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 filecreate; /* OS method of opening/creating */
|
||||
DWORD fileattrib; /* OS file attribute flags */
|
||||
SECURITY_ATTRIBUTES SecurityAttributes;
|
||||
|
||||
DBUG_ENTER("my_win_sopen");
|
||||
|
||||
@ -137,9 +155,6 @@ File my_win_sopen(const char *path, int oflag, int shflag, int pmode)
|
||||
errno= EACCES;
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
SecurityAttributes.nLength= sizeof(SecurityAttributes);
|
||||
SecurityAttributes.lpSecurityDescriptor= NULL;
|
||||
SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
|
||||
|
||||
/* decode the access flags */
|
||||
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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/*
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <accctrl.h>
|
||||
#include <aclapi.h>
|
||||
#include <ntsecapi.h>
|
||||
#include <sddl.h>
|
||||
struct IUnknown;
|
||||
#include <shlwapi.h>
|
||||
|
||||
@ -729,6 +730,26 @@ static int create_db_instance()
|
||||
set_directory_permissions(opt_datadir, 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. */
|
||||
init_bootstrap_command_line(cmdline, sizeof(cmdline));
|
||||
|
||||
@ -843,7 +864,7 @@ end:
|
||||
|
||||
/*Remove all service user privileges for the user.*/
|
||||
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);
|
||||
}
|
||||
|
@ -123,6 +123,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <handle_connections_win.h>
|
||||
#include <sddl.h>
|
||||
#endif
|
||||
|
||||
#include <my_service_manager.h>
|
||||
@ -8166,6 +8167,23 @@ mysqld_get_one_option(const struct my_option *opt, char *argument,
|
||||
break;
|
||||
case OPT_BOOTSTRAP:
|
||||
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;
|
||||
case OPT_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
|
||||
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",
|
||||
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);
|
||||
#else
|
||||
{
|
||||
@ -375,7 +379,7 @@ buf_dump(
|
||||
ut_free(dump);
|
||||
|
||||
done:
|
||||
ret = fclose(f);
|
||||
ret = IF_WIN(my_fclose(f,0),fclose(f));
|
||||
if (ret != 0) {
|
||||
buf_dump_status(STATUS_ERR,
|
||||
"Cannot close '%s': %s",
|
||||
|
@ -73,11 +73,11 @@ Created 10/21/1995 Heikki Tuuri
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winioctl.h>
|
||||
#else
|
||||
// my_test_if_atomic_write()
|
||||
#include <my_sys.h>
|
||||
#endif
|
||||
|
||||
// my_test_if_atomic_write() , my_win_secattr()
|
||||
#include <my_sys.h>
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
@ -2005,6 +2005,10 @@ os_file_get_last_error_low(
|
||||
" because of either a thread exit"
|
||||
" or an application request."
|
||||
" 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 {
|
||||
|
||||
ib::info() << OPERATING_SYSTEM_ERROR_MSG;
|
||||
@ -2137,7 +2141,7 @@ os_file_create_simple_func(
|
||||
file = CreateFile(
|
||||
(LPCTSTR) name, access,
|
||||
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
NULL, create_flag, attributes, NULL);
|
||||
my_win_file_secattr(), create_flag, attributes, NULL);
|
||||
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
|
||||
@ -2543,7 +2547,7 @@ os_file_create_func(
|
||||
|
||||
/* Use default security attributes and no template file. */
|
||||
file = CreateFile(
|
||||
name, access, share_mode, NULL,
|
||||
name, access, share_mode, my_win_file_secattr(),
|
||||
create_flag, attributes, NULL);
|
||||
|
||||
/* 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
|
||||
@return own: handle to the file, not defined if error, error number
|
||||
can be retrieved with os_file_get_last_error */
|
||||
|
||||
pfs_os_file_t
|
||||
os_file_create_simple_no_error_handling_func(
|
||||
const char* name,
|
||||
@ -2678,7 +2683,7 @@ os_file_create_simple_no_error_handling_func(
|
||||
file = CreateFile((LPCTSTR) name,
|
||||
access,
|
||||
share_mode,
|
||||
NULL, // Security attributes
|
||||
my_win_file_secattr(),
|
||||
create_flag,
|
||||
attributes,
|
||||
NULL); // No template file
|
||||
@ -2968,7 +2973,7 @@ os_file_get_status_win32(
|
||||
access,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE
|
||||
| FILE_SHARE_DELETE, // Full sharing
|
||||
NULL, // Default security
|
||||
my_win_file_secattr(),
|
||||
OPEN_EXISTING, // Existing file only
|
||||
FILE_ATTRIBUTE_NORMAL, // Normal file
|
||||
NULL); // No attr. template
|
||||
|
Loading…
x
Reference in New Issue
Block a user