summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/bash/bash/bash-CVE-2019-18276.patch
blob: 78dcc1b636b54edda5c0390ffe4d50b0f3e244f8 (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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
From 951bdaad7a18cc0dc1036bba86b18b90874d39ff Mon Sep 17 00:00:00 2001
From: Chet Ramey <chet.ramey@case.edu>
Date: Mon, 1 Jul 2019 09:03:53 -0400
Subject: [PATCH] commit bash-20190628 snapshot

An issue was discovered in disable_priv_mode in shell.c in GNU Bash through 5.0 patch 11.
By default, if Bash is run with its effective UID not equal to its real UID,
it will drop privileges by setting its effective UID to its real UID.
However, it does so incorrectly. On Linux and other systems that support "saved UID" functionality,
the saved UID is not dropped. An attacker with command execution in the shell can use "enable -f" for
runtime loading of a new builtin, which can be a shared object that calls setuid() and therefore
regains privileges. However, binaries running with an effective UID of 0 are unaffected.

Upstream-Status: Backport [https://github.com/bminor/bash/commit/951bdaad7a18cc0dc1036bba86b18b90874d39ff]
CVE: CVE-2019-18276
Signed-off-by: Chet Ramey <chet.ramey@case.edu>
Signed-off-by: De Huo <De.Huo@windriver.com>
---
 MANIFEST          |  2 ++
 bashline.c        | 50 +-------------------------------------------------
 builtins/help.def |  2 +-
 config.h.in       | 10 +++++++++-
 configure         | 11 +++++++++++
 configure.ac      |  1 +
 doc/bash.1        |  3 ++-
 doc/bashref.texi  |  3 ++-
 lib/glob/glob.c   |  5 ++++-
 pathexp.c         | 16 ++++++++++++++--
 shell.c           |  8 ++++++++
 tests/glob.tests  |  2 ++
 tests/glob6.sub   | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/glob7.sub   | 11 +++++++++++
 14 files changed, 122 insertions(+), 56 deletions(-)
 create mode 100644 tests/glob6.sub
 create mode 100644 tests/glob7.sub

diff --git a/MANIFEST b/MANIFEST
index 03de221..f9ccad7 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1037,6 +1037,8 @@ tests/extglob3.tests	f
 tests/extglob3.right	f
 tests/extglob4.sub	f
 tests/extglob5.sub	f
+tests/glob6.sub		f
+tests/glob7.sub		f
 tests/func.tests	f
 tests/func.right	f
 tests/func1.sub		f
diff --git a/bashline.c b/bashline.c
index 824ea9d..d86b47d 100644
--- a/bashline.c
+++ b/bashline.c
@@ -3718,55 +3718,7 @@ static int
 completion_glob_pattern (string)
      char *string;
 {
-  register int c;
-  char *send;
-  int open;
-
-  DECLARE_MBSTATE;
-
-  open = 0;
-  send = string + strlen (string);
-
-  while (c = *string++)
-    {
-      switch (c)
-	{
-	case '?':
-	case '*':
-	  return (1);
-
-	case '[':
-	  open++;
-	  continue;
-
-	case ']':
-	  if (open)
-	    return (1);
-	  continue;
-
-	case '+':
-	case '@':
-	case '!':
-	  if (*string == '(')	/*)*/
-	    return (1);
-	  continue;
-
-	case '\\':
-	  if (*string++ == 0)
-	    return (0);	 	  
-	}
-
-      /* Advance one fewer byte than an entire multibyte character to
-	 account for the auto-increment in the loop above. */
-#ifdef HANDLE_MULTIBYTE
-      string--;
-      ADVANCE_CHAR_P (string, send - string);
-      string++;
-#else
-      ADVANCE_CHAR_P (string, send - string);
-#endif
-    }
-  return (0);
+  return (glob_pattern_p (string) == 1);
 }
 
 static char *globtext;
diff --git a/builtins/help.def b/builtins/help.def
index 006c4b5..92f9b38 100644
--- a/builtins/help.def
+++ b/builtins/help.def
@@ -128,7 +128,7 @@ help_builtin (list)
 
   /* We should consider making `help bash' do something. */
 
-  if (glob_pattern_p (list->word->word))
+  if (glob_pattern_p (list->word->word) == 1)
     {
       printf ("%s", ngettext ("Shell commands matching keyword `", "Shell commands matching keywords `", (list->next ? 2 : 1)));
       print_word_list (list, ", ");
diff --git a/config.h.in b/config.h.in
index 8554aec..ad4b1e8 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,6 +1,6 @@
 /* config.h -- Configuration file for bash. */
 
-/* Copyright (C) 1987-2009,2011-2012 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2009,2011-2012,2013-2019 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -807,6 +807,14 @@
 #undef HAVE_SETREGID
 #undef HAVE_DECL_SETREGID
 
+/* Define if you have the setregid function.  */
+#undef HAVE_SETRESGID
+#undef HAVE_DECL_SETRESGID
+
+/* Define if you have the setresuid function.  */
+#undef HAVE_SETRESUID
+#undef HAVE_DECL_SETRESUID
+
 /* Define if you have the setvbuf function.  */
 #undef HAVE_SETVBUF
 
diff --git a/configure b/configure
index 2f62662..b3321c9 100755
--- a/configure
+++ b/configure
@@ -10281,6 +10281,17 @@ cat >>confdefs.h <<_ACEOF
 #define HAVE_DECL_SETREGID $ac_have_decl
 _ACEOF
 
+ac_fn_c_check_decl "$LINENO" "" "ac_cv_have_decl_" "$ac_includes_default"
+if test "x$ac_cv_have_decl_" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_ $ac_have_decl
+_ACEOF
+(setresuid, setresgid)
 ac_fn_c_check_decl "$LINENO" "strcpy" "ac_cv_have_decl_strcpy" "$ac_includes_default"
 if test "x$ac_cv_have_decl_strcpy" = xyes; then :
   ac_have_decl=1
diff --git a/configure.ac b/configure.ac
index 52b4cdb..549adef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -810,6 +810,7 @@ AC_CHECK_DECLS([confstr])
 AC_CHECK_DECLS([printf])
 AC_CHECK_DECLS([sbrk])
 AC_CHECK_DECLS([setregid])
+AC_CHECK_DECLS[(setresuid, setresgid])
 AC_CHECK_DECLS([strcpy])
 AC_CHECK_DECLS([strsignal])
 
diff --git a/doc/bash.1 b/doc/bash.1
index e6cd08d..9e58a0b 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -4681,7 +4681,8 @@ above).
 .PD
 .SH "SIMPLE COMMAND EXPANSION"
 When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
+expansions, assignments, and redirections, from left to right, in
+the following order.
 .IP 1.
 The words that the parser has marked as variable assignments (those
 preceding the command name) and redirections are saved for later
diff --git a/doc/bashref.texi b/doc/bashref.texi
index d33cd57..3065126 100644
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -2964,7 +2964,8 @@ is not specified.  If the file does not exist, it is created.
 @cindex command expansion
 
 When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
+expansions, assignments, and redirections, from left to right, in
+the following order.
 
 @enumerate
 @item
diff --git a/lib/glob/glob.c b/lib/glob/glob.c
index 398253b..2eaa33e 100644
--- a/lib/glob/glob.c
+++ b/lib/glob/glob.c
@@ -607,6 +607,7 @@ glob_vector (pat, dir, flags)
   register unsigned int i;
   int mflags;		/* Flags passed to strmatch (). */
   int pflags;		/* flags passed to sh_makepath () */
+  int hasglob;		/* return value from glob_pattern_p */
   int nalloca;
   struct globval *firstmalloc, *tmplink;
   char *convfn;
@@ -648,10 +649,12 @@ glob_vector (pat, dir, flags)
   patlen = (pat && *pat) ? strlen (pat) : 0;
 
   /* If the filename pattern (PAT) does not contain any globbing characters,
+     or contains a pattern with only backslash escapes (hasglob == 2),
      we can dispense with reading the directory, and just see if there is
      a filename `DIR/PAT'.  If there is, and we can access it, just make the
      vector to return and bail immediately. */
-  if (skip == 0 && glob_pattern_p (pat) == 0)
+  hasglob = 0;
+  if (skip == 0 && (hasglob = glob_pattern_p (pat)) == 0 || hasglob == 2)
     {
       int dirlen;
       struct stat finfo;
diff --git a/pathexp.c b/pathexp.c
index c1bf2d8..e6c5392 100644
--- a/pathexp.c
+++ b/pathexp.c
@@ -58,7 +58,10 @@ int extended_glob = EXTGLOB_DEFAULT;
 /* Control enabling special handling of `**' */
 int glob_star = 0;
 
-/* Return nonzero if STRING has any unquoted special globbing chars in it.  */
+/* Return nonzero if STRING has any unquoted special globbing chars in it.
+   This is supposed to be called when pathname expansion is performed, so
+   it implements the rules in Posix 2.13.3, specifically that an unquoted
+   slash cannot appear in a bracket expression. */
 int
 unquoted_glob_pattern_p (string)
      register char *string;
@@ -85,10 +88,14 @@ unquoted_glob_pattern_p (string)
 	  continue;
 
 	case ']':
-	  if (open)
+	  if (open)		/* XXX - if --open == 0? */
 	    return (1);
 	  continue;
 
+	case '/':
+	  if (open)
+	    open = 0;
+
 	case '+':
 	case '@':
 	case '!':
@@ -106,6 +113,11 @@ unquoted_glob_pattern_p (string)
 	      string++;
 	      continue;
 	    }
+	  else if (open && *string == '/')
+	    {
+	      string++;		/* quoted slashes in bracket expressions are ok */
+	      continue;
+	    }
 	  else if (*string == 0)
 	    return (0);
 	 	  
diff --git a/shell.c b/shell.c
index a2b2a55..6adabc8 100644
--- a/shell.c
+++ b/shell.c
@@ -1293,7 +1293,11 @@ disable_priv_mode ()
 {
   int e;
 
+#if HAVE_DECL_SETRESUID
+  if (setresuid (current_user.uid, current_user.uid, current_user.uid) < 0)
+#else
   if (setuid (current_user.uid) < 0)
+#endif
     {
       e = errno;
       sys_error (_("cannot set uid to %d: effective uid %d"), current_user.uid, current_user.euid);
@@ -1302,7 +1306,11 @@ disable_priv_mode ()
 	exit (e);
 #endif
     }
+#if HAVE_DECL_SETRESGID
+  if (setresgid (current_user.gid, current_user.gid, current_user.gid) < 0)
+#else
   if (setgid (current_user.gid) < 0)
+#endif
     sys_error (_("cannot set gid to %d: effective gid %d"), current_user.gid, current_user.egid);
 
   current_user.euid = current_user.uid;
diff --git a/tests/glob.tests b/tests/glob.tests
index 01913bb..fb012f7 100644
--- a/tests/glob.tests
+++ b/tests/glob.tests
@@ -12,6 +12,8 @@ ${THIS_SH} ./glob1.sub
 ${THIS_SH} ./glob2.sub
 ${THIS_SH} ./glob3.sub
 ${THIS_SH} ./glob4.sub
+${THIS_SH} ./glob6.sub
+${THIS_SH} ./glob7.sub
 
 MYDIR=$PWD	# save where we are
 
diff --git a/tests/glob6.sub b/tests/glob6.sub
new file mode 100644
index 0000000..b099811
--- /dev/null
+++ b/tests/glob6.sub
@@ -0,0 +1,54 @@
+# tests of the backslash-in-glob-patterns discussion on the austin-group ML
+
+: ${TMPDIR:=/var/tmp}
+
+ORIG=$PWD
+GLOBDIR=$TMPDIR/bash-glob-$$
+mkdir $GLOBDIR && cd $GLOBDIR
+
+# does the pattern matcher allow backslashes as escape characters and remove
+# them as part of matching?
+touch abcdefg
+pat='ab\cd*'
+printf '<%s>\n' $pat
+pat='\.'
+printf '<%s>\n' $pat
+rm abcdefg
+
+# how about when escaping pattern characters?
+touch '*abc.c'
+a='\**.c'
+printf '%s\n' $a
+rm -f '*abc.c'
+
+# how about when making the distinction between readable and searchable path
+# components?
+mkdir -m a=x searchable
+mkdir -m a=r readable
+
+p='searchable/\.'
+printf "%s\n" $p
+
+p='searchable/\./.'
+printf "%s\n" $p
+
+p='readable/\.'
+printf "%s\n" $p
+
+p='readable/\./.'
+printf "%s\n" $p
+
+printf "%s\n" 'searchable/\.'
+printf "%s\n" 'readable/\.'
+
+echo */.
+
+p='*/\.'
+echo $p
+
+echo */'.'
+
+rmdir searchable readable
+
+cd $ORIG
+rmdir $GLOBDIR
diff --git a/tests/glob7.sub b/tests/glob7.sub
new file mode 100644
index 0000000..0212b8e
--- /dev/null
+++ b/tests/glob7.sub
@@ -0,0 +1,11 @@
+# according to Posix 2.13.3, a slash in a bracket expression renders that
+# bracket expression invalid
+shopt -s nullglob
+
+echo 1: [qwe/qwe]
+echo 2: [qwe/
+echo 3: [qwe/]
+
+echo 4: [qwe\/qwe]
+echo 5: [qwe\/
+echo 6: [qwe\/]
-- 
1.9.1