summaryrefslogtreecommitdiffstats
path: root/source/l/glibc/patches/glibc.CVE-2023-4911.patch
blob: a790a8305489e9952d662187ed94934f37d8e464 (plain) (blame)
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
From 1056e5b4c3f2d90ed2b4a55f96add28da2f4c8fa Mon Sep 17 00:00:00 2001
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Tue, 19 Sep 2023 18:39:32 -0400
Subject: [PATCH] tunables: Terminate if end of input is reached
 (CVE-2023-4911)

The string parsing routine may end up writing beyond bounds of tunestr
if the input tunable string is malformed, of the form name=name=val.
This gets processed twice, first as name=name=val and next as name=val,
resulting in tunestr being name=name=val:name=val, thus overflowing
tunestr.

Terminate the parsing loop at the first instance itself so that tunestr
does not overflow.

This also fixes up tst-env-setuid-tunables to actually handle failures
correct and add new tests to validate the fix for this CVE.

Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
---
 NEWS                          |  5 +++++
 elf/dl-tunables.c             | 17 +++++++++-------
 elf/tst-env-setuid-tunables.c | 37 +++++++++++++++++++++++++++--------
 3 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/NEWS b/NEWS
index a94650da64..cc4b81f0ac 100644
--- a/NEWS
+++ b/NEWS
@@ -64,6 +64,11 @@ Security related changes:
   an application calls getaddrinfo for AF_INET6 with AI_CANONNAME,
   AI_ALL and AI_V4MAPPED flags set.
 
+  CVE-2023-4911: If a tunable of the form NAME=NAME=VAL is passed in the
+  environment of a setuid program and NAME is valid, it may result in a
+  buffer overflow, which could be exploited to achieve escalated
+  privileges.  This flaw was introduced in glibc 2.34.
+
 The following bugs are resolved with this release:
 
   [The release manager will add the list generated by
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 62b7332d95..cae67efa0a 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -180,11 +180,7 @@ parse_tunables (char *tunestr, char *valstring)
       /* If we reach the end of the string before getting a valid name-value
 	 pair, bail out.  */
       if (p[len] == '\0')
-	{
-	  if (__libc_enable_secure)
-	    tunestr[off] = '\0';
-	  return;
-	}
+	break;
 
       /* We did not find a valid name-value pair before encountering the
 	 colon.  */
@@ -244,9 +240,16 @@ parse_tunables (char *tunestr, char *valstring)
 	    }
 	}
 
-      if (p[len] != '\0')
-	p += len + 1;
+      /* We reached the end while processing the tunable string.  */
+      if (p[len] == '\0')
+	break;
+
+      p += len + 1;
     }
+
+  /* Terminate tunestr before we leave.  */
+  if (__libc_enable_secure)
+    tunestr[off] = '\0';
 }
 
 /* Enable the glibc.malloc.check tunable in SETUID/SETGID programs only when
diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c
index 7dfb0e073a..f0b92c97e7 100644
--- a/elf/tst-env-setuid-tunables.c
+++ b/elf/tst-env-setuid-tunables.c
@@ -50,6 +50,8 @@ const char *teststrings[] =
   "glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
   "glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096",
   "not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
+  "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
+  "glibc.malloc.check=2",
   "glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2",
   "glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096",
   ":glibc.malloc.garbage=2:glibc.malloc.check=1",
@@ -68,6 +70,8 @@ const char *resultstrings[] =
   "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
   "glibc.malloc.mmap_threshold=4096",
   "glibc.malloc.mmap_threshold=4096",
+  "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
+  "",
   "",
   "",
   "",
@@ -81,11 +85,18 @@ test_child (int off)
 {
   const char *val = getenv ("GLIBC_TUNABLES");
 
+  printf ("    [%d] GLIBC_TUNABLES is %s\n", off, val);
+  fflush (stdout);
   if (val != NULL && strcmp (val, resultstrings[off]) == 0)
     return 0;
 
   if (val != NULL)
-    printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val);
+    printf ("    [%d] Unexpected GLIBC_TUNABLES VALUE %s, expected %s\n",
+	    off, val, resultstrings[off]);
+  else
+    printf ("    [%d] GLIBC_TUNABLES environment variable absent\n", off);
+
+  fflush (stdout);
 
   return 1;
 }
@@ -106,21 +117,26 @@ do_test (int argc, char **argv)
       if (ret != 0)
 	exit (1);
 
-      exit (EXIT_SUCCESS);
+      /* Special return code to make sure that the child executed all the way
+	 through.  */
+      exit (42);
     }
   else
     {
-      int ret = 0;
-
       /* Spawn tests.  */
       for (int i = 0; i < array_length (teststrings); i++)
 	{
 	  char buf[INT_BUFSIZE_BOUND (int)];
 
-	  printf ("Spawned test for %s (%d)\n", teststrings[i], i);
+	  printf ("[%d] Spawned test for %s\n", i, teststrings[i]);
 	  snprintf (buf, sizeof (buf), "%d\n", i);
+	  fflush (stdout);
 	  if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0)
-	    exit (1);
+	    {
+	      printf ("    [%d] Failed to set GLIBC_TUNABLES: %m", i);
+	      support_record_failure ();
+	      continue;
+	    }
 
 	  int status = support_capture_subprogram_self_sgid (buf);
 
@@ -128,9 +144,14 @@ do_test (int argc, char **argv)
 	  if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
 	    return EXIT_UNSUPPORTED;
 
-	  ret |= status;
+	  if (WEXITSTATUS (status) != 42)
+	    {
+	      printf ("    [%d] child failed with status %d\n", i,
+		      WEXITSTATUS (status));
+	      support_record_failure ();
+	    }
 	}
-      return ret;
+      return 0;
     }
 }
 
-- 
2.39.3