Skip to content

Commit

Permalink
MDEV-7021 Pass directory security descriptor from mysql_install_db.ex…
Browse files Browse the repository at this point in the history
…e 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.
  • Loading branch information
vaintroub committed May 18, 2020
1 parent d9b8121 commit e2bc029
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 42 deletions.
26 changes: 4 additions & 22 deletions extra/mariabackup/backup_copy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -688,7 +672,6 @@ mkdirp(const char *pathname, int Flags, myf MyFlags)
free(parent);
return(0);
}
#endif

free(parent);
return(-1);
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 4 additions & 0 deletions include/my_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 9 additions & 4 deletions mysys/my_mkdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 3 additions & 1 deletion mysys/my_static.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 20 additions & 5 deletions mysys/my_winfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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");

Expand All @@ -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)) {
Expand Down Expand Up @@ -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)
{
/*
Expand Down
23 changes: 22 additions & 1 deletion sql/mysql_install_db.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <accctrl.h>
#include <aclapi.h>
#include <ntsecapi.h>
#include <sddl.h>
struct IUnknown;
#include <shlwapi.h>

Expand Down Expand Up @@ -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));

Expand Down Expand Up @@ -843,7 +864,7 @@ static int create_db_instance()

/*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);
}
Expand Down
18 changes: 18 additions & 0 deletions sql/mysqld.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@

#ifdef _WIN32
#include <handle_connections_win.h>
#include <sddl.h>
#endif

#include <my_service_manager.h>
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions storage/innobase/buf/buf0dump.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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",
Expand Down
19 changes: 12 additions & 7 deletions storage/innobase/os/os0file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit e2bc029

Please sign in to comment.