Skip to content

Commit ecc5a07

Browse files
author
Shishir Jaiswal
committed
Bug#26585560 - MYSQL DAEMON SHOULD CREATE ITS PID FILE AS
ROOT DESCRIPTION =========== If the .pid file is created at a world-writable location, it can be compromised by replacing the server's pid with another running server's (or some other non-mysql process) PID causing abnormal behaviour. ANALYSIS ======== In such a case, user should be warned that .pid file is being created at a world-writable location. FIX === A new function is_file_or_dir_world_writable() is defined and it is called in create_pid_file() before .pid file creation. If the location is world-writable, a relevant warning is thrown. NOTE ==== 1. PID file is always created with permission bit 0664, so for outside world its read-only. 2. Ignoring the case when permission is denied to get the dir stats since the .pid file creation would fail anyway in such a case.
1 parent 8bc828b commit ecc5a07

File tree

5 files changed

+98
-3
lines changed

5 files changed

+98
-3
lines changed

include/sql_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ void mysql_client_plugin_deinit();
107107
struct st_mysql_client_plugin;
108108
extern struct st_mysql_client_plugin *mysql_client_builtins[];
109109
extern my_bool libmysql_cleartext_plugin_enabled;
110+
int is_file_or_dir_world_writable(const char *filepath);
110111

111112
#ifdef __cplusplus
112113
}

mysql-test/include/mtr_warnings.sql

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-- Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
1+
-- Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
22
--
33
-- This program is free software; you can redistribute it and/or modify
44
-- it under the terms of the GNU General Public License as published by
@@ -209,6 +209,12 @@ INSERT INTO global_suppressions VALUES
209209
*/
210210
("Insecure configuration for --secure-file-priv:*"),
211211

212+
/*
213+
Bug#26585560, warning related to --pid-file
214+
*/
215+
("Insecure configuration for --pid-file:*"),
216+
("Few location(s) are inaccessible while checking PID filepath"),
217+
212218
("THE_LAST_SUPPRESSION")||
213219

214220

sql-common/my_path_permissions.cc

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
2+
3+
This program is free software; you can redistribute it and/or modify it
4+
under the terms of the GNU General Public License as published by the
5+
Free Software Foundation; version 2 of the License.
6+
7+
This program is distributed in the hope that it will be useful, but
8+
WITHOUT ANY WARRANTY; without even the implied warranty of
9+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10+
General Public License for more details.
11+
12+
You should have received a copy of the GNU General Public License
13+
along with this program; if not, write to the Free Software
14+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15+
02110-1301, USA */
16+
17+
#include "my_dir.h"
18+
19+
#ifdef __cplusplus
20+
extern "C" {
21+
#endif
22+
23+
/**
24+
Check if a file/dir is world-writable (only on non-Windows platforms)
25+
26+
@param [in] Path of the file/dir to be checked
27+
28+
@returns Status of the file/dir check
29+
@retval -2 Permission denied to check attributes of file/dir
30+
@retval -1 Error in reading file/dir
31+
@retval 0 File/dir is not world-writable
32+
@retval 1 File/dir is world-writable
33+
*/
34+
35+
int is_file_or_dir_world_writable(const char *path)
36+
{
37+
MY_STAT stat_info;
38+
(void)path; // avoid unused param warning when built on Windows
39+
#ifndef _WIN32
40+
if (!my_stat(path, &stat_info, MYF(0)))
41+
{
42+
return (errno == EACCES) ? -2 : -1;
43+
}
44+
if ((stat_info.st_mode & S_IWOTH) &&
45+
((stat_info.st_mode & S_IFMT) == S_IFREG || /* file */
46+
(stat_info.st_mode & S_IFMT) == S_IFDIR)) /* or dir */
47+
return 1;
48+
#endif
49+
return 0;
50+
}
51+
52+
#ifdef __cplusplus
53+
}
54+
#endif

sql/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ SET (SQL_SOURCE
7878
sql_profile.cc event_parse_data.cc sql_alter.cc
7979
sql_signal.cc rpl_handler.cc mdl.cc sql_admin.cc
8080
transaction.cc sys_vars.cc sql_truncate.cc datadict.cc
81-
sql_reload.cc
81+
sql_reload.cc ../sql-common/my_path_permissions.cc
8282
${GEN_SOURCES}
8383
${CONF_SOURCES}
8484
${MYSYS_LIBWRAP_SOURCE})

sql/mysqld.cc

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights
1+
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights
22
reserved.
33
44
This program is free software; you can redistribute it and/or modify
@@ -7996,6 +7996,40 @@ static int test_if_case_insensitive(const char *dir_name)
79967996
static void create_pid_file()
79977997
{
79987998
File file;
7999+
bool check_parent_path= 1, is_path_accessible= 1;
8000+
char pid_filepath[FN_REFLEN], *pos= NULL;
8001+
/* Copy pid file name to get pid file path */
8002+
strcpy(pid_filepath, pidfile_name);
8003+
8004+
/* Iterate through the entire path to check if even one of the sub-dirs
8005+
is world-writable */
8006+
while (check_parent_path && (pos= strrchr(pid_filepath, FN_LIBCHAR))
8007+
&& (pos != pid_filepath)) /* shouldn't check root */
8008+
{
8009+
*pos= '\0'; /* Trim the inner-most dir */
8010+
switch (is_file_or_dir_world_writable(pid_filepath))
8011+
{
8012+
case -2:
8013+
is_path_accessible= 0;
8014+
break;
8015+
case -1:
8016+
sql_perror("Can't start server: can't check PID filepath");
8017+
exit(1);
8018+
case 1:
8019+
sql_print_warning("Insecure configuration for --pid-file: Location "
8020+
"'%s' in the path is accessible to all OS users. "
8021+
"Consider choosing a different directory.",
8022+
pid_filepath);
8023+
check_parent_path= 0;
8024+
break;
8025+
case 0:
8026+
continue; /* Keep checking the parent dir */
8027+
}
8028+
}
8029+
if (!is_path_accessible)
8030+
{
8031+
sql_print_warning("Few location(s) are inaccessible while checking PID filepath.");
8032+
}
79998033
if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
80008034
O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
80018035
{

0 commit comments

Comments
 (0)