diff options
author | Hitendra Prajapati <hprajapati@mvista.com> | 2023-07-04 12:18:24 +0530 |
---|---|---|
committer | Armin Kuster <akuster808@gmail.com> | 2023-07-14 07:08:54 -0400 |
commit | fbe2d05a159aa95f81de89bd0ae6401f036d31d6 (patch) | |
tree | 31baf23c43bafb0bb9d5d24576e703b70eef7113 | |
parent | 7ca27d5cf3ec147ec933a8660b252cf57d107a27 (diff) | |
download | meta-openembedded-fbe2d05a159aa95f81de89bd0ae6401f036d31d6.tar.gz |
ntp: backport patch for 5 CVEs CVE-2023-26551/2/3/4/5
Upstream-Status: Backport from https://archive.ntp.org/ntp4/ntp-4.2/ntp-4.2.8p15-3806-3807.patch
Patch taken from https://archive.ntp.org/ntp4/ntp-4.2/ntp-4.2.8p15-3806-3807.patch
It is linked as official patch for p15 in:
- https://www.ntp.org/support/securitynotice/ntpbug3807/
- https://www.ntp.org/support/securitynotice/ntpbug3806/
Small adaptation to build is needed because of how tests are built.
Backport fixes for:
CVE: CVE-2023-26551
CVE: CVE-2023-26552
CVE: CVE-2023-26553
CVE: CVE-2023-26554
CVE: CVE-2023-26555
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r-- | meta-networking/recipes-support/ntp/ntp/CVE-2023-2655x.patch | 340 | ||||
-rw-r--r-- | meta-networking/recipes-support/ntp/ntp_4.2.8p15.bb | 10 |
2 files changed, 349 insertions, 1 deletions
diff --git a/meta-networking/recipes-support/ntp/ntp/CVE-2023-2655x.patch b/meta-networking/recipes-support/ntp/ntp/CVE-2023-2655x.patch new file mode 100644 index 0000000000..734c6f197b --- /dev/null +++ b/meta-networking/recipes-support/ntp/ntp/CVE-2023-2655x.patch | |||
@@ -0,0 +1,340 @@ | |||
1 | ntp: backport patch for 5 CVEs CVE-2023-26551/2/3/4/5 | ||
2 | |||
3 | Upstream-Status: Backport [https://archive.ntp.org/ntp4/ntp-4.2/ntp-4.2.8p15-3806-3807.patch] | ||
4 | CVE: CVE-2023-26551 | ||
5 | CVE: CVE-2023-26552 | ||
6 | CVE: CVE-2023-26553 | ||
7 | CVE: CVE-2023-26554 | ||
8 | CVE: CVE-2023-26555 | ||
9 | |||
10 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
11 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
12 | --- | ||
13 | include/ntp_fp.h | 4 +- | ||
14 | libntp/mstolfp.c | 108 +++++++++++++++------------------------ | ||
15 | ntpd/refclock_palisade.c | 50 +++++++++++++++--- | ||
16 | tests/libntp/strtolfp.c | 33 +++++++----- | ||
17 | 4 files changed, 104 insertions(+), 91 deletions(-) | ||
18 | |||
19 | diff --git a/include/ntp_fp.h b/include/ntp_fp.h | ||
20 | index afd1f82..fe6e390 100644 | ||
21 | --- a/include/ntp_fp.h | ||
22 | +++ b/include/ntp_fp.h | ||
23 | @@ -195,9 +195,9 @@ typedef u_int32 u_fp; | ||
24 | do { \ | ||
25 | int32 add_f = (int32)(f); \ | ||
26 | if (add_f >= 0) \ | ||
27 | - M_ADD((r_i), (r_f), 0, (uint32)( add_f)); \ | ||
28 | + M_ADD((r_i), (r_f), 0, (u_int32)( add_f)); \ | ||
29 | else \ | ||
30 | - M_SUB((r_i), (r_f), 0, (uint32)(-add_f)); \ | ||
31 | + M_SUB((r_i), (r_f), 0, (u_int32)(-add_f)); \ | ||
32 | } while(0) | ||
33 | |||
34 | #define M_ISNEG(v_i) /* v < 0 */ \ | ||
35 | diff --git a/libntp/mstolfp.c b/libntp/mstolfp.c | ||
36 | index 3dfc4ef..a906d76 100644 | ||
37 | --- a/libntp/mstolfp.c | ||
38 | +++ b/libntp/mstolfp.c | ||
39 | @@ -14,86 +14,58 @@ mstolfp( | ||
40 | l_fp *lfp | ||
41 | ) | ||
42 | { | ||
43 | - register const char *cp; | ||
44 | - register char *bp; | ||
45 | - register const char *cpdec; | ||
46 | - char buf[100]; | ||
47 | + int ch, neg = 0; | ||
48 | + u_int32 q, r; | ||
49 | |||
50 | /* | ||
51 | * We understand numbers of the form: | ||
52 | * | ||
53 | * [spaces][-|+][digits][.][digits][spaces|\n|\0] | ||
54 | * | ||
55 | - * This is one enormous hack. Since I didn't feel like | ||
56 | - * rewriting the decoding routine for milliseconds, what | ||
57 | - * is essentially done here is to make a copy of the string | ||
58 | - * with the decimal moved over three places so the seconds | ||
59 | - * decoding routine can be used. | ||
60 | + * This is kinda hack. We use 'atolfp' to do the basic parsing | ||
61 | + * (after some initial checks) and then divide the result by | ||
62 | + * 1000. The original implementation avoided that by | ||
63 | + * hacking up the input string to move the decimal point, but | ||
64 | + * that needed string manipulations prone to buffer overruns. | ||
65 | + * To avoid that trouble we do the conversion first and adjust | ||
66 | + * the result. | ||
67 | */ | ||
68 | - bp = buf; | ||
69 | - cp = str; | ||
70 | - while (isspace((unsigned char)*cp)) | ||
71 | - cp++; | ||
72 | |||
73 | - if (*cp == '-' || *cp == '+') { | ||
74 | - *bp++ = *cp++; | ||
75 | - } | ||
76 | - | ||
77 | - if (*cp != '.' && !isdigit((unsigned char)*cp)) | ||
78 | - return 0; | ||
79 | - | ||
80 | + while (isspace(ch = *(const unsigned char*)str)) | ||
81 | + ++str; | ||
82 | |||
83 | - /* | ||
84 | - * Search forward for the decimal point or the end of the string. | ||
85 | - */ | ||
86 | - cpdec = cp; | ||
87 | - while (isdigit((unsigned char)*cpdec)) | ||
88 | - cpdec++; | ||
89 | - | ||
90 | - /* | ||
91 | - * Found something. If we have more than three digits copy the | ||
92 | - * excess over, else insert a leading 0. | ||
93 | - */ | ||
94 | - if ((cpdec - cp) > 3) { | ||
95 | - do { | ||
96 | - *bp++ = (char)*cp++; | ||
97 | - } while ((cpdec - cp) > 3); | ||
98 | - } else { | ||
99 | - *bp++ = '0'; | ||
100 | + switch (ch) { | ||
101 | + case '-': neg = TRUE; | ||
102 | + case '+': ++str; | ||
103 | + default : break; | ||
104 | } | ||
105 | |||
106 | - /* | ||
107 | - * Stick the decimal in. If we've got less than three digits in | ||
108 | - * front of the millisecond decimal we insert the appropriate number | ||
109 | - * of zeros. | ||
110 | - */ | ||
111 | - *bp++ = '.'; | ||
112 | - if ((cpdec - cp) < 3) { | ||
113 | - size_t i = 3 - (cpdec - cp); | ||
114 | - do { | ||
115 | - *bp++ = '0'; | ||
116 | - } while (--i > 0); | ||
117 | - } | ||
118 | + if (!isdigit(ch = *(const unsigned char*)str) && (ch != '.')) | ||
119 | + return 0; | ||
120 | + if (!atolfp(str, lfp)) | ||
121 | + return 0; | ||
122 | |||
123 | - /* | ||
124 | - * Copy the remainder up to the millisecond decimal. If cpdec | ||
125 | - * is pointing at a decimal point, copy in the trailing number too. | ||
126 | + /* now do a chained/overlapping division by 1000 to get from | ||
127 | + * seconds to msec. 1000 is small enough to go with temporary | ||
128 | + * 32bit accus for Q and R. | ||
129 | */ | ||
130 | - while (cp < cpdec) | ||
131 | - *bp++ = (char)*cp++; | ||
132 | - | ||
133 | - if (*cp == '.') { | ||
134 | - cp++; | ||
135 | - while (isdigit((unsigned char)*cp)) | ||
136 | - *bp++ = (char)*cp++; | ||
137 | - } | ||
138 | - *bp = '\0'; | ||
139 | + q = lfp->l_ui / 1000u; | ||
140 | + r = lfp->l_ui - (q * 1000u); | ||
141 | + lfp->l_ui = q; | ||
142 | |||
143 | - /* | ||
144 | - * Check to make sure the string is properly terminated. If | ||
145 | - * so, give the buffer to the decoding routine. | ||
146 | - */ | ||
147 | - if (*cp != '\0' && !isspace((unsigned char)*cp)) | ||
148 | - return 0; | ||
149 | - return atolfp(buf, lfp); | ||
150 | + r = (r << 16) | (lfp->l_uf >> 16); | ||
151 | + q = r / 1000u; | ||
152 | + r = ((r - q * 1000) << 16) | (lfp->l_uf & 0x0FFFFu); | ||
153 | + lfp->l_uf = q << 16; | ||
154 | + q = r / 1000; | ||
155 | + lfp->l_uf |= q; | ||
156 | + r -= q * 1000u; | ||
157 | + | ||
158 | + /* fix sign */ | ||
159 | + if (neg) | ||
160 | + L_NEG(lfp); | ||
161 | + /* round */ | ||
162 | + if (r >= 500) | ||
163 | + L_ADDF(lfp, (neg ? -1 : 1)); | ||
164 | + return 1; | ||
165 | } | ||
166 | diff --git a/ntpd/refclock_palisade.c b/ntpd/refclock_palisade.c | ||
167 | index cb68255..15c21d8 100644 | ||
168 | --- a/ntpd/refclock_palisade.c | ||
169 | +++ b/ntpd/refclock_palisade.c | ||
170 | @@ -1225,9 +1225,9 @@ palisade_poll ( | ||
171 | return; /* using synchronous packet input */ | ||
172 | |||
173 | if(up->type == CLK_PRAECIS) { | ||
174 | - if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0) | ||
175 | + if (write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0) { | ||
176 | msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit); | ||
177 | - else { | ||
178 | + } else { | ||
179 | praecis_msg = 1; | ||
180 | return; | ||
181 | } | ||
182 | @@ -1249,20 +1249,53 @@ praecis_parse ( | ||
183 | |||
184 | pp = peer->procptr; | ||
185 | |||
186 | - memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length); | ||
187 | + if (p + rbufp->recv_length >= sizeof buf) { | ||
188 | + struct palisade_unit *up; | ||
189 | + up = pp->unitptr; | ||
190 | + | ||
191 | + /* | ||
192 | + * We COULD see if there is a \r\n in the incoming | ||
193 | + * buffer before it overflows, and then process the | ||
194 | + * current line. | ||
195 | + * | ||
196 | + * Similarly, if we already have a hunk of data that | ||
197 | + * we're now flushing, that will cause the line of | ||
198 | + * data we're in the process of collecting to be garbage. | ||
199 | + * | ||
200 | + * Since we now check for this overflow and log when it | ||
201 | + * happens, we're now in a better place to easily see | ||
202 | + * what's going on and perhaps better choices can be made. | ||
203 | + */ | ||
204 | + | ||
205 | + /* Do we need to log the size of the overflow? */ | ||
206 | + msyslog(LOG_ERR, "Palisade(%d) praecis_parse(): input buffer overflow", | ||
207 | + up->unit); | ||
208 | + | ||
209 | + p = 0; | ||
210 | + praecis_msg = 0; | ||
211 | + | ||
212 | + refclock_report(peer, CEVNT_BADREPLY); | ||
213 | + | ||
214 | + return; | ||
215 | + } | ||
216 | + | ||
217 | + memcpy(buf+p, rbufp->recv_buffer, rbufp->recv_length); | ||
218 | p += rbufp->recv_length; | ||
219 | |||
220 | - if(buf[p-2] == '\r' && buf[p-1] == '\n') { | ||
221 | + if ( p >= 2 | ||
222 | + && buf[p-2] == '\r' | ||
223 | + && buf[p-1] == '\n') { | ||
224 | buf[p-2] = '\0'; | ||
225 | record_clock_stats(&peer->srcadr, buf); | ||
226 | |||
227 | p = 0; | ||
228 | praecis_msg = 0; | ||
229 | |||
230 | - if (HW_poll(pp) < 0) | ||
231 | + if (HW_poll(pp) < 0) { | ||
232 | refclock_report(peer, CEVNT_FAULT); | ||
233 | - | ||
234 | + } | ||
235 | } | ||
236 | + return; | ||
237 | } | ||
238 | |||
239 | static void | ||
240 | @@ -1407,7 +1440,10 @@ HW_poll ( | ||
241 | |||
242 | /* Edge trigger */ | ||
243 | if (up->type == CLK_ACUTIME) | ||
244 | - write (pp->io.fd, "", 1); | ||
245 | + if (write (pp->io.fd, "", 1) != 1) | ||
246 | + msyslog(LOG_WARNING, | ||
247 | + "Palisade(%d) HW_poll: failed to send trigger: %m", | ||
248 | + up->unit); | ||
249 | |||
250 | if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { | ||
251 | #ifdef DEBUG | ||
252 | diff --git a/tests/libntp/strtolfp.c b/tests/libntp/strtolfp.c | ||
253 | index 6855d9b..9090159 100644 | ||
254 | --- a/tests/libntp/strtolfp.c | ||
255 | +++ b/tests/libntp/strtolfp.c | ||
256 | @@ -26,6 +26,13 @@ setUp(void) | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | +static const char* fmtLFP(const l_fp *e, const l_fp *a) | ||
261 | +{ | ||
262 | + static char buf[100]; | ||
263 | + snprintf(buf, sizeof(buf), "e=$%08x.%08x, a=$%08x.%08x", | ||
264 | + e->l_ui, e->l_uf, a->l_ui, a->l_uf); | ||
265 | + return buf; | ||
266 | +} | ||
267 | |||
268 | void test_PositiveInteger(void) { | ||
269 | const char *str = "500"; | ||
270 | @@ -37,8 +44,8 @@ void test_PositiveInteger(void) { | ||
271 | TEST_ASSERT_TRUE(atolfp(str, &actual)); | ||
272 | TEST_ASSERT_TRUE(mstolfp(str_ms, &actual_ms)); | ||
273 | |||
274 | - TEST_ASSERT_TRUE(IsEqual(expected, actual)); | ||
275 | - TEST_ASSERT_TRUE(IsEqual(expected, actual_ms)); | ||
276 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual), fmtLFP(&expected, &actual)); | ||
277 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual_ms), fmtLFP(&expected, &actual_ms)); | ||
278 | } | ||
279 | |||
280 | void test_NegativeInteger(void) { | ||
281 | @@ -54,8 +61,8 @@ void test_NegativeInteger(void) { | ||
282 | TEST_ASSERT_TRUE(atolfp(str, &actual)); | ||
283 | TEST_ASSERT_TRUE(mstolfp(str_ms, &actual_ms)); | ||
284 | |||
285 | - TEST_ASSERT_TRUE(IsEqual(expected, actual)); | ||
286 | - TEST_ASSERT_TRUE(IsEqual(expected, actual_ms)); | ||
287 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual), fmtLFP(&expected, &actual)); | ||
288 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual_ms), fmtLFP(&expected, &actual_ms)); | ||
289 | } | ||
290 | |||
291 | void test_PositiveFraction(void) { | ||
292 | @@ -68,8 +75,8 @@ void test_PositiveFraction(void) { | ||
293 | TEST_ASSERT_TRUE(atolfp(str, &actual)); | ||
294 | TEST_ASSERT_TRUE(mstolfp(str_ms, &actual_ms)); | ||
295 | |||
296 | - TEST_ASSERT_TRUE(IsEqual(expected, actual)); | ||
297 | - TEST_ASSERT_TRUE(IsEqual(expected, actual_ms)); | ||
298 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual), fmtLFP(&expected, &actual)); | ||
299 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual_ms), fmtLFP(&expected, &actual_ms)); | ||
300 | } | ||
301 | |||
302 | void test_NegativeFraction(void) { | ||
303 | @@ -85,8 +92,8 @@ void test_NegativeFraction(void) { | ||
304 | TEST_ASSERT_TRUE(atolfp(str, &actual)); | ||
305 | TEST_ASSERT_TRUE(mstolfp(str_ms, &actual_ms)); | ||
306 | |||
307 | - TEST_ASSERT_TRUE(IsEqual(expected, actual)); | ||
308 | - TEST_ASSERT_TRUE(IsEqual(expected, actual_ms)); | ||
309 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual), fmtLFP(&expected, &actual)); | ||
310 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual_ms), fmtLFP(&expected, &actual_ms)); | ||
311 | } | ||
312 | |||
313 | void test_PositiveMsFraction(void) { | ||
314 | @@ -100,9 +107,8 @@ void test_PositiveMsFraction(void) { | ||
315 | TEST_ASSERT_TRUE(atolfp(str, &actual)); | ||
316 | TEST_ASSERT_TRUE(mstolfp(str_ms, &actual_ms)); | ||
317 | |||
318 | - TEST_ASSERT_TRUE(IsEqual(expected, actual)); | ||
319 | - TEST_ASSERT_TRUE(IsEqual(expected, actual_ms)); | ||
320 | - | ||
321 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual), fmtLFP(&expected, &actual)); | ||
322 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual_ms), fmtLFP(&expected, &actual_ms)); | ||
323 | } | ||
324 | |||
325 | void test_NegativeMsFraction(void) { | ||
326 | @@ -118,9 +124,8 @@ void test_NegativeMsFraction(void) { | ||
327 | TEST_ASSERT_TRUE(atolfp(str, &actual)); | ||
328 | TEST_ASSERT_TRUE(mstolfp(str_ms, &actual_ms)); | ||
329 | |||
330 | - TEST_ASSERT_TRUE(IsEqual(expected, actual)); | ||
331 | - TEST_ASSERT_TRUE(IsEqual(expected, actual_ms)); | ||
332 | - | ||
333 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual), fmtLFP(&expected, &actual)); | ||
334 | + TEST_ASSERT_TRUE_MESSAGE(IsEqual(expected, actual_ms), fmtLFP(&expected, &actual_ms)); | ||
335 | } | ||
336 | |||
337 | void test_InvalidChars(void) { | ||
338 | -- | ||
339 | 2.25.1 | ||
340 | |||
diff --git a/meta-networking/recipes-support/ntp/ntp_4.2.8p15.bb b/meta-networking/recipes-support/ntp/ntp_4.2.8p15.bb index 7e168825e0..1a223db6fa 100644 --- a/meta-networking/recipes-support/ntp/ntp_4.2.8p15.bb +++ b/meta-networking/recipes-support/ntp/ntp_4.2.8p15.bb | |||
@@ -22,8 +22,8 @@ SRC_URI = "http://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-${PV}.tar.g | |||
22 | file://sntp.service \ | 22 | file://sntp.service \ |
23 | file://sntp \ | 23 | file://sntp \ |
24 | file://ntpd.list \ | 24 | file://ntpd.list \ |
25 | file://CVE-2023-2655x.patch \ | ||
25 | " | 26 | " |
26 | |||
27 | SRC_URI[sha256sum] = "f65840deab68614d5d7ceb2d0bb9304ff70dcdedd09abb79754a87536b849c19" | 27 | SRC_URI[sha256sum] = "f65840deab68614d5d7ceb2d0bb9304ff70dcdedd09abb79754a87536b849c19" |
28 | 28 | ||
29 | inherit autotools update-rc.d useradd systemd pkgconfig | 29 | inherit autotools update-rc.d useradd systemd pkgconfig |
@@ -61,6 +61,14 @@ PACKAGECONFIG[debug] = "--enable-debugging,--disable-debugging" | |||
61 | PACKAGECONFIG[mdns] = "ac_cv_header_dns_sd_h=yes,ac_cv_header_dns_sd_h=no,mdns" | 61 | PACKAGECONFIG[mdns] = "ac_cv_header_dns_sd_h=yes,ac_cv_header_dns_sd_h=no,mdns" |
62 | PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," | 62 | PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," |
63 | 63 | ||
64 | do_configure_append() { | ||
65 | # tests are generated but also checked-in to source control | ||
66 | # when CVE-2023-2655x.patch changes timestamp of test source file, Makefile detects it and tries to regenerate it | ||
67 | # however it fails because of missing ruby interpretter; adding ruby-native as dependency fixes it | ||
68 | # since the regenerated file is identical to the one from source control, touch the generated file instead of adding heavy dependency | ||
69 | touch ${S}/tests/libntp/run-strtolfp.c | ||
70 | } | ||
71 | |||
64 | do_install_append() { | 72 | do_install_append() { |
65 | install -d ${D}${sysconfdir}/init.d | 73 | install -d ${D}${sysconfdir}/init.d |
66 | install -m 644 ${WORKDIR}/ntp.conf ${D}${sysconfdir} | 74 | install -m 644 ${WORKDIR}/ntp.conf ${D}${sysconfdir} |