aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/mysql/mariadb/CVE-2016-6664_p1.patch
blob: e8b0a84ce9bdfba1c1dce08a95006ea3f8d7ce4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
From af4f1bd59b38e3172b882107c49b8612537f4f4f Mon Sep 17 00:00:00 2001
From: Sergei Golubchik <serg@mariadb.org>
Date: Tue, 20 Dec 2016 15:17:59 +0100
Subject: [PATCH 1/3] move check_user/set_user from mysqld.cc to mysys

Upstream-Status: Backport

CVE: CVE-2016-6664 patch#1

Signed-off-by: Sunil Kumar <sukumar@mvista.com>
---
 include/my_sys.h     |  4 +++
 mysys/CMakeLists.txt |  4 +--
 mysys/my_setuser.c   | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++
 sql/mysqld.cc        | 83 +++++++---------------------------------------------
 4 files changed, 98 insertions(+), 74 deletions(-)
 create mode 100644 mysys/my_setuser.c

diff --git a/include/my_sys.h b/include/my_sys.h
index 7e37fe598bd..756a40c72f6 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -602,8 +602,12 @@ extern void *my_memmem(const void *haystack, size_t haystacklen,
 
 #ifdef _WIN32
 extern int      my_access(const char *path, int amode);
+#define my_check_user(A,B) (NULL)
+#define my_set_user(A,B,C) (0)
 #else
 #define my_access access
+struct passwd *my_check_user(const char *user, myf MyFlags);
+int my_set_user(const char *user, struct passwd *user_info, myf MyFlags);
 #endif
 
 extern int check_if_legal_filename(const char *path);
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 06a811f0994..cb86850c2de 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -34,7 +34,7 @@ SET(MYSYS_SOURCES  array.c charset-def.c charset.c checksum.c default.c
 				rijndael.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
 				thr_rwlock.c tree.c typelib.c base64.c my_memmem.c my_getpagesize.c
 				lf_alloc-pin.c lf_dynarray.c lf_hash.c
-                safemalloc.c my_new.cc
+                                safemalloc.c my_new.cc
 				my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
                                 my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c
 				my_rdtsc.c my_context.c file_logger.c)
@@ -44,7 +44,7 @@ IF (WIN32)
 ENDIF()
 
 IF(UNIX)
- SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_addr_resolve.c)
+ SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_addr_resolve.c my_setuser.c)
 ENDIF()
 
 IF(HAVE_ALARM)
diff --git a/mysys/my_setuser.c b/mysys/my_setuser.c
new file mode 100644
index 00000000000..1f3e7770d4c
--- /dev/null
+++ b/mysys/my_setuser.c
@@ -0,0 +1,81 @@
+#include <my_global.h>
+#include <m_string.h>
+#include <my_sys.h>
+#include <my_pthread.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+struct passwd *my_check_user(const char *user, myf MyFlags)
+{
+  struct passwd *user_info;
+  uid_t user_id= geteuid();
+  DBUG_ENTER("my_check_user");
+
+  // Don't bother if we aren't superuser
+  if (user_id)
+  {
+    if (user)
+    {
+      /* Don't give a warning, if real user is same as given with --user */
+      user_info= getpwnam(user);
+      if (!user_info || user_id != user_info->pw_uid)
+      {
+        my_errno= EPERM;
+        if (MyFlags & MY_WME)
+          my_printf_error(my_errno, "One can only use the --user switch if "
+                         "running as root", MYF(ME_JUST_WARNING|ME_NOREFRESH));
+      }
+    }
+    DBUG_RETURN(NULL);
+  }
+  if (!user)
+  {
+    if (MyFlags & MY_FAE)
+    {
+      my_errno= EINVAL;
+      my_printf_error(my_errno, "Please consult the Knowledge Base to find "
+                      "out how to run mysqld as root!", MYF(ME_NOREFRESH));
+    }
+    DBUG_RETURN(NULL);
+  }
+  if (!strcmp(user,"root"))
+    DBUG_RETURN(NULL);
+
+  if (!(user_info= getpwnam(user)))
+  {
+    // Allow a numeric uid to be used
+    int err= 0;
+    user_id= my_strtoll10(user, NULL, &err);
+    if (err || !(user_info= getpwuid(user_id)))
+    {
+      my_errno= EINVAL;
+      my_printf_error(my_errno, "Can't change to run as user '%s'.  Please "
+                      "check that the user exists!", MYF(ME_NOREFRESH), user);
+      DBUG_RETURN(NULL);
+    }
+  }
+  DBUG_ASSERT(user_info);
+  DBUG_RETURN(user_info);
+}
+
+int my_set_user(const char *user, struct passwd *user_info, myf MyFlags)
+{
+  DBUG_ENTER("my_set_user");
+
+  DBUG_ASSERT(user_info != 0);
+#ifdef HAVE_INITGROUPS
+  initgroups(user, user_info->pw_gid);
+#endif
+  if (setgid(user_info->pw_gid) == -1 || setuid(user_info->pw_uid) == -1)
+  {
+    my_errno= errno;
+    if (MyFlags & MY_WME)
+      my_error(my_errno, MYF(ME_NOREFRESH));
+    DBUG_RETURN(my_errno);
+  }
+  DBUG_RETURN(0);
+}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 3ad7b84829d..dd961ec20f0 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -121,10 +121,7 @@ extern "C" {					// Because of SCO 3.2V4.2
 #include <sysent.h>
 #endif
 #ifdef HAVE_PWD_H
-#include <pwd.h>				// For getpwent
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h>
+#include <pwd.h>				// For struct passwd
 #endif
 #include <my_net.h>
 
@@ -455,9 +452,7 @@ ulong opt_binlog_rows_event_max_size;
 my_bool opt_master_verify_checksum= 0;
 my_bool opt_slave_sql_verify_checksum= 1;
 const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
-#ifdef HAVE_INITGROUPS
 volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
-#endif
 uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
 uint mysqld_extra_port;
 uint mysqld_port_timeout;
@@ -2007,59 +2002,18 @@ static void set_ports()
 
 static struct passwd *check_user(const char *user)
 {
-#if !defined(__WIN__)
-  struct passwd *tmp_user_info;
-  uid_t user_id= geteuid();
+  myf flags= 0;
+  if (global_system_variables.log_warnings)
+    flags|= MY_WME;
+  if (!opt_bootstrap && !opt_help)
+    flags|= MY_FAE;
 
-  // Don't bother if we aren't superuser
-  if (user_id)
-  {
-    if (user)
-    {
-      /* Don't give a warning, if real user is same as given with --user */
-      /* purecov: begin tested */
-      tmp_user_info= getpwnam(user);
-      if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
-	  global_system_variables.log_warnings)
-        sql_print_warning(
-                    "One can only use the --user switch if running as root\n");
-      /* purecov: end */
-    }
-    return NULL;
-  }
-  if (!user)
-  {
-    if (!opt_bootstrap && !opt_help)
-    {
-      sql_print_error("Fatal error: Please consult the Knowledge Base "
-                      "to find out how to run mysqld as root!\n");
-      unireg_abort(1);
-    }
-    return NULL;
-  }
-  /* purecov: begin tested */
-  if (!strcmp(user,"root"))
-    return NULL;                        // Avoid problem with dynamic libraries
+  struct passwd *tmp_user_info= my_check_user(user, MYF(flags));
 
-  if (!(tmp_user_info= getpwnam(user)))
-  {
-    // Allow a numeric uid to be used
-    const char *pos;
-    for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
-    if (*pos)                                   // Not numeric id
-      goto err;
-    if (!(tmp_user_info= getpwuid(atoi(user))))
-      goto err;
-  }
+  if (!tmp_user_info && my_errno==EINVAL && (flags & MY_FAE))
+    unireg_abort(1);
 
   return tmp_user_info;
-  /* purecov: end */
-
-err:
-  sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
-  unireg_abort(1);
-#endif
-  return NULL;
 }
 
 static inline void allow_coredumps()
@@ -2076,10 +2030,6 @@ static inline void allow_coredumps()
 
 static void set_user(const char *user, struct passwd *user_info_arg)
 {
-  /* purecov: begin tested */
-#if !defined(__WIN__)
-  DBUG_ASSERT(user_info_arg != 0);
-#ifdef HAVE_INITGROUPS
   /*
     We can get a SIGSEGV when calling initgroups() on some systems when NSS
     is configured to use LDAP and the server is statically linked.  We set
@@ -2087,22 +2037,11 @@ static void set_user(const char *user, struct passwd *user_info_arg)
     output a specific message to help the user resolve this problem.
   */
   calling_initgroups= 1;
-  initgroups((char*) user, user_info_arg->pw_gid);
+  int res= my_set_user(user, user_info_arg, MYF(MY_WME));
   calling_initgroups= 0;
-#endif
-  if (setgid(user_info_arg->pw_gid) == -1)
-  {
-    sql_perror("setgid");
-    unireg_abort(1);
-  }
-  if (setuid(user_info_arg->pw_uid) == -1)
-  {
-    sql_perror("setuid");
+  if (res)
     unireg_abort(1);
-  }
   allow_coredumps();
-#endif
-  /* purecov: end */
 }
 
 
-- 
2.11.1