-
Notifications
You must be signed in to change notification settings - Fork 567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CVE-2018-6913] heap-buffer-overflow in S_pack_rec #16098
Comments
From gy741.kim@gmail.comHi. I found a heap-buffer-overflow bug in perl. Please confirm. Thanks. Version: This is perl 5, version 27, subversion 2 (v5.27.2) built for ```==2895==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb610081c 0xb610081c is located 2 bytes to the right of 10-byte region SUMMARY: AddressSanitizer: heap-buffer-overflow |
From @tonycozOn Sat, 05 Aug 2017 05:55:33 -0700, gy741.kim@gmail.com wrote:
As written this only reproduces on 32-bit systems. This is caused by a pointer wrap when calculating (cur)+glen in: if ((cur) + glen >= (start) + SvLEN(cat)) { since in this case glen is ~3GB, and the new pointer ends up less than (start), let alone (start)+SvLEN(cat). Going through the code I found three other issues, and added tests and Note that the first case results in a panic with the fix - since the test case attempts to allocate a large amount of memory, which fails, resulting in a call to croak_no_mem(), which triggers a my_exit(), which the constant folding code doesn't know how to handle. The issues here could result in an exploit in code that accepts either large blocks of data from untrusted sources and/or duplicates such blocks. The supplied case is a compile-time failure while constant folding, but the same issue could be triggered during runtime with attacker supplied data. Such code is already subject to denial-of-service attacks (the code can be made to allocate large amounts of memory, as it does on 64-bit systems), but this expands such an attack to a malloced buffer overflow, which is Tony |
From @tonycoz0001-perl-131844-fix-various-space-calculation-issues-in-.patchFrom 5a66253379c8be70130f8d4e5961e8d26c3a9efc Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@debian9-x32.tony.develop-help.com>
Date: Tue, 8 Aug 2017 09:32:58 +1000
Subject: (perl #131844) fix various space calculation issues in pp_pack.c
- for the originally reported case, if the start/cur pointer is in the
top 75% of the address space the add (cur) + glen addition would
overflow, resulting in the condition failing incorrectly.
- the addition of the existing space used to the space needed could
overflow, resulting in too small an allocation and a buffer overflow.
- the scaling for UTF8 could overflow.
- the multiply to calculate the space needed for many items could
overflow.
For the first case, do a space calculation without making new pointers.
For the other cases, detect the overflow and croak if there's an
overflow.
---
pp_pack.c | 25 +++++++++++++++++++++----
t/op/pack.t | 24 +++++++++++++++++++++++-
2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/pp_pack.c b/pp_pack.c
index 86d138bb05..53f74c82f5 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -361,11 +361,28 @@ STMT_START { \
} \
} STMT_END
+#define SAFE_UTF8_EXPAND(var) \
+STMT_START { \
+ if ((var) > Size_t_MAX / UTF8_EXPAND) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ (var) = (var) * UTF8_EXPAND; \
+} STMT_END
+
+#define GROWING2(utf8, cat, start, cur, item_size, item_count) \
+STMT_START { \
+ if (Size_t_MAX / (item_size) < (item_count)) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ GROWING((utf8), (cat), (start), (cur), (item_size) * (item_count)); \
+} STMT_END
+
#define GROWING(utf8, cat, start, cur, in_len) \
STMT_START { \
STRLEN glen = (in_len); \
- if (utf8) glen *= UTF8_EXPAND; \
- if ((cur) + glen >= (start) + SvLEN(cat)) { \
+ STRLEN catcur = (STRLEN)((cur) - (start)); \
+ if (utf8) SAFE_UTF8_EXPAND(glen); \
+ if (Size_t_MAX - glen < catcur) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ if (catcur + glen >= SvLEN(cat)) { \
(start) = sv_exp_grow(cat, glen); \
(cur) = (start) + SvCUR(cat); \
} \
@@ -375,7 +392,7 @@ STMT_START { \
STMT_START { \
const STRLEN glen = (in_len); \
STRLEN gl = glen; \
- if (utf8) gl *= UTF8_EXPAND; \
+ if (utf8) SAFE_UTF8_EXPAND(gl); \
if ((cur) + gl >= (start) + SvLEN(cat)) { \
*cur = '\0'; \
SvCUR_set((cat), (cur) - (start)); \
@@ -2135,7 +2152,7 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
if (props && !(props & PACK_SIZE_UNPREDICTABLE)) {
/* We can process this letter. */
STRLEN size = props & PACK_SIZE_MASK;
- GROWING(utf8, cat, start, cur, (STRLEN) len * size);
+ GROWING2(utf8, cat, start, cur, size, (STRLEN)len);
}
}
diff --git a/t/op/pack.t b/t/op/pack.t
index 919e4c55c6..6e025b4741 100644
--- a/t/op/pack.t
+++ b/t/op/pack.t
@@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' :
my $no_signedness = $] > 5.009 ? '' :
"Signed/unsigned pack modifiers not available on this perl";
-plan tests => 14713;
+plan tests => 14717;
use strict;
use warnings qw(FATAL all);
@@ -2059,3 +2059,25 @@ print pack("ucW", "0000", 0, 140737488355327) eq "\$,#`P,```\n\0\x{7fffffffffff}
? "ok\n" : "not ok\n";
EOS
}
+
+SKIP:
+{
+ # [perl #131844] pointer addition overflow
+ $Config{ptrsize} == 4
+ or skip "[perl $131844] need 32-bit build for this test", 1;
+ # prevent ASAN just crashing on the allocation failure
+ local $ENV{ASAN_OPTIONS} = $ENV{ASAN_OPTIONS};
+ $ENV{ASAN_OPTIONS} .= ",allocator_may_return_null=1";
+ fresh_perl_like('pack "f999999999"', qr/Out of memory!/, { stderr => 1 },
+ "pointer addition overflow");
+
+ # integer (STRLEN) overflow from addition of glen to current length
+ fresh_perl_like('pack "c10f1073741823"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (addition)");
+
+ fresh_perl_like('pack "W10f536870913", 256', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (utf8)");
+
+ fresh_perl_like('pack "c10f1073741824"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (multiply)");
+}
--
2.11.0
|
The RT System itself - Status changed from 'new' to 'open' |
From @iabynOn Sat, Aug 05, 2017 at 05:55:33AM -0700, GwanYeong Kim wrote:
Tony, any reason you haven't applied your proposed pp_pack.c fix from back -- |
From @tonycozOn Wed, 29 Nov 2017 01:08:14 -0800, davem wrote:
Do we treat it as a security issue? Tony |
From @tonycozOn Wed, 24 Jan 2018 20:49:53 -0800, tonyc wrote:
After reviewing it, I think this is a security issue. Tony |
From @tonycozOn Tue, 30 Jan 2018 16:28:44 -0800, tonyc wrote:
I plan to request a CVE ID for this one too, since it's a buffer overflow and an attacker may have control over the data written. Vulnerability type: Vendor of the product: Product: Version: Has vendor confirmed or acknowledged the vulnerability? Attack vector: Impact: - the other choices for Impact are: Affected Components: Attack vector Suggested description of the vulnerability for use in the CVE pack() may cause a heap buffer write overflow with a large item count Discoverer(s)/Credits GwanYeong Kim <gy741.kim@gmail.com> Reference(s) https://rt.perl.org/Public/Bug/Display.html?id=131844 Additional Information (blank) I don't plan to supply the suggested description until issue is public. Tony |
From @tonycozOn Wed, 07 Feb 2018 18:15:16 -0800, tonyc wrote:
I've requested a CVE id for this issue. Tony |
From @tonycozOn Sun, 11 Feb 2018 19:31:18 -0800, tonyc wrote:
This is CVE-2018-6913. There are no other tickets I'm planning on requesting a CVE id for, if you think any need one please speak up. Tony |
From @tonycozOn Mon, 07 Aug 2017 18:34:44 -0700, tonyc wrote:
There were two problems (the email address and the skip count), fixed in the attached. The non-5.24 patch applies to both blead and maint-5.26, the other to 5.24. Tony |
From @tonycoz0001-perl-131844-5.24-fix-various-space-calculation-issue.patchFrom 8a34d2c1718e7cd9ca9d88b71d5932b4e931276d Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 8 Aug 2017 09:32:58 +1000
Subject: (perl #131844) 5.24: fix various space calculation issues in
pp_pack.c
- for the originally reported case, if the start/cur pointer is in the
top 75% of the address space the add (cur) + glen addition would
overflow, resulting in the condition failing incorrectly.
- the addition of the existing space used to the space needed could
overflow, resulting in too small an allocation and a buffer overflow.
- the scaling for UTF8 could overflow.
- the multiply to calculate the space needed for many items could
overflow.
For the first case, do a space calculation without making new pointers.
For the other cases, detect the overflow and croak if there's an
overflow.
---
pp_pack.c | 25 +++++++++++++++++++++----
t/op/pack.t | 24 +++++++++++++++++++++++-
2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/pp_pack.c b/pp_pack.c
index f6964c3f30..c35525aae9 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -358,11 +358,28 @@ STMT_START { \
} \
} STMT_END
+#define SAFE_UTF8_EXPAND(var) \
+STMT_START { \
+ if ((var) > Size_t_MAX / UTF8_EXPAND) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ (var) = (var) * UTF8_EXPAND; \
+} STMT_END
+
+#define GROWING2(utf8, cat, start, cur, item_size, item_count) \
+STMT_START { \
+ if (Size_t_MAX / (item_size) < (item_count)) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ GROWING((utf8), (cat), (start), (cur), (item_size) * (item_count)); \
+} STMT_END
+
#define GROWING(utf8, cat, start, cur, in_len) \
STMT_START { \
STRLEN glen = (in_len); \
- if (utf8) glen *= UTF8_EXPAND; \
- if ((cur) + glen >= (start) + SvLEN(cat)) { \
+ STRLEN catcur = (STRLEN)((cur) - (start)); \
+ if (utf8) SAFE_UTF8_EXPAND(glen); \
+ if (Size_t_MAX - glen < catcur) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ if (catcur + glen >= SvLEN(cat)) { \
(start) = sv_exp_grow(cat, glen); \
(cur) = (start) + SvCUR(cat); \
} \
@@ -372,7 +389,7 @@ STMT_START { \
STMT_START { \
const STRLEN glen = (in_len); \
STRLEN gl = glen; \
- if (utf8) gl *= UTF8_EXPAND; \
+ if (utf8) SAFE_UTF8_EXPAND(gl); \
if ((cur) + gl >= (start) + SvLEN(cat)) { \
*cur = '\0'; \
SvCUR_set((cat), (cur) - (start)); \
@@ -2126,7 +2143,7 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
if (props && !(props & PACK_SIZE_UNPREDICTABLE)) {
/* We can process this letter. */
STRLEN size = props & PACK_SIZE_MASK;
- GROWING(utf8, cat, start, cur, (STRLEN) len * size);
+ GROWING2(utf8, cat, start, cur, size, (STRLEN)len);
}
}
diff --git a/t/op/pack.t b/t/op/pack.t
index a2da63689b..0b640fb6eb 100644
--- a/t/op/pack.t
+++ b/t/op/pack.t
@@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' :
my $no_signedness = $] > 5.009 ? '' :
"Signed/unsigned pack modifiers not available on this perl";
-plan tests => 14712;
+plan tests => 14716;
use strict;
use warnings qw(FATAL all);
@@ -2044,3 +2044,25 @@ ok(1, "argument underflow did not crash");
is(pack("H40", $up_nul), $twenty_nuls,
"check pack H zero fills (utf8 source)");
}
+
+SKIP:
+{
+ # [perl #131844] pointer addition overflow
+ $Config{ptrsize} == 4
+ or skip "[perl #131844] need 32-bit build for this test", 4;
+ # prevent ASAN just crashing on the allocation failure
+ local $ENV{ASAN_OPTIONS} = $ENV{ASAN_OPTIONS};
+ $ENV{ASAN_OPTIONS} .= ",allocator_may_return_null=1";
+ fresh_perl_like('pack "f999999999"', qr/Out of memory!/, { stderr => 1 },
+ "pointer addition overflow");
+
+ # integer (STRLEN) overflow from addition of glen to current length
+ fresh_perl_like('pack "c10f1073741823"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (addition)");
+
+ fresh_perl_like('pack "W10f536870913", 256', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (utf8)");
+
+ fresh_perl_like('pack "c10f1073741824"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (multiply)");
+}
--
2.11.0
|
From @tonycoz0001-perl-131844-fix-various-space-calculation-issues-in-.patchFrom 14451983c134d2390238d8e77b15e90873c5b596 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 8 Aug 2017 09:32:58 +1000
Subject: [PATCH] (perl #131844) fix various space calculation issues in
pp_pack.c
- for the originally reported case, if the start/cur pointer is in the
top 75% of the address space the add (cur) + glen addition would
overflow, resulting in the condition failing incorrectly.
- the addition of the existing space used to the space needed could
overflow, resulting in too small an allocation and a buffer overflow.
- the scaling for UTF8 could overflow.
- the multiply to calculate the space needed for many items could
overflow.
For the first case, do a space calculation without making new pointers.
For the other cases, detect the overflow and croak if there's an
overflow.
---
pp_pack.c | 25 +++++++++++++++++++++----
t/op/pack.t | 24 +++++++++++++++++++++++-
2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/pp_pack.c b/pp_pack.c
index 8937d6d715..12a850284d 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -357,11 +357,28 @@ STMT_START { \
} \
} STMT_END
+#define SAFE_UTF8_EXPAND(var) \
+STMT_START { \
+ if ((var) > Size_t_MAX / UTF8_EXPAND) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ (var) = (var) * UTF8_EXPAND; \
+} STMT_END
+
+#define GROWING2(utf8, cat, start, cur, item_size, item_count) \
+STMT_START { \
+ if (Size_t_MAX / (item_size) < (item_count)) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ GROWING((utf8), (cat), (start), (cur), (item_size) * (item_count)); \
+} STMT_END
+
#define GROWING(utf8, cat, start, cur, in_len) \
STMT_START { \
STRLEN glen = (in_len); \
- if (utf8) glen *= UTF8_EXPAND; \
- if ((cur) + glen >= (start) + SvLEN(cat)) { \
+ STRLEN catcur = (STRLEN)((cur) - (start)); \
+ if (utf8) SAFE_UTF8_EXPAND(glen); \
+ if (Size_t_MAX - glen < catcur) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ if (catcur + glen >= SvLEN(cat)) { \
(start) = sv_exp_grow(cat, glen); \
(cur) = (start) + SvCUR(cat); \
} \
@@ -371,7 +388,7 @@ STMT_START { \
STMT_START { \
const STRLEN glen = (in_len); \
STRLEN gl = glen; \
- if (utf8) gl *= UTF8_EXPAND; \
+ if (utf8) SAFE_UTF8_EXPAND(gl); \
if ((cur) + gl >= (start) + SvLEN(cat)) { \
*cur = '\0'; \
SvCUR_set((cat), (cur) - (start)); \
@@ -2131,7 +2148,7 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
if (props && !(props & PACK_SIZE_UNPREDICTABLE)) {
/* We can process this letter. */
STRLEN size = props & PACK_SIZE_MASK;
- GROWING(utf8, cat, start, cur, (STRLEN) len * size);
+ GROWING2(utf8, cat, start, cur, size, (STRLEN)len);
}
}
diff --git a/t/op/pack.t b/t/op/pack.t
index 664aaaf1b0..439e74ee17 100644
--- a/t/op/pack.t
+++ b/t/op/pack.t
@@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' :
my $no_signedness = $] > 5.009 ? '' :
"Signed/unsigned pack modifiers not available on this perl";
-plan tests => 14713;
+plan tests => 14717;
use strict;
use warnings qw(FATAL all);
@@ -2059,3 +2059,25 @@ print pack("ucW", "0000", 0, 140737488355327) eq "\$,#`P,```\n\0\x{7fffffffffff}
? "ok\n" : "not ok\n";
EOS
}
+
+SKIP:
+{
+ # [perl #131844] pointer addition overflow
+ $Config{ptrsize} == 4
+ or skip "[perl #131844] need 32-bit build for this test", 4;
+ # prevent ASAN just crashing on the allocation failure
+ local $ENV{ASAN_OPTIONS} = $ENV{ASAN_OPTIONS};
+ $ENV{ASAN_OPTIONS} .= ",allocator_may_return_null=1";
+ fresh_perl_like('pack "f999999999"', qr/Out of memory!/, { stderr => 1 },
+ "pointer addition overflow");
+
+ # integer (STRLEN) overflow from addition of glen to current length
+ fresh_perl_like('pack "c10f1073741823"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (addition)");
+
+ fresh_perl_like('pack "W10f536870913", 256', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (utf8)");
+
+ fresh_perl_like('pack "c10f1073741824"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (multiply)");
+}
--
2.11.0
|
From @xsawyerxThe public disclosure date is set for March 15th. |
From @khwilliamsonOn 02/24/2018 09:56 AM, Sawyer X wrote:
I believe this indicates that we are committing to put out maintenance Correct? |
From @xsawyerxOn 25 February 2018 at 19:49, Karl Williamson <public@khwilliamson.com>
I believe so. Steve? |
From @TuxOn Sun, 25 Feb 2018 20:16:25 +0200, Sawyer X <xsawyerx@gmail.com> wrote:
Are CVE's not exempt from voting? -- |
From @xsawyerxCVEs should be back-ported. I don't know of any objection to this in the On 25 February 2018 at 20:24, H.Merijn Brand <h.m.brand@xs4all.nl> wrote:
|
From @steve-m-hayOn 25 February 2018 at 18:16, Sawyer X <xsawyerx@gmail.com> wrote:
Yes. I will start committing things that are already voted on soon |
From @steve-m-hayOn 26 February 2018 at 16:01, Steve Hay <steve.m.hay@googlemail.com> wrote:
This is a very tight timescale for a release which we also hope will I normally wait a fortnight after an RC before making a release final, We could shorten the waiting period to maybe a week, but any less than The other approach might be to release RC1s on 15th March, but I don't |
From @xsawyerxI was contacted by a vendor requesting postponement. I will update once I On Mar 1, 2018 15:46, "Steve Hay" <steve.m.hay@googlemail.com> wrote:
|
From @khwilliamsonOn 03/01/2018 06:49 AM, Sawyer X wrote:
We should go through the security queue to see what else could be made No one has responded to my query about what makes some things security
|
From @tonycozOn Thu, Mar 01, 2018 at 11:13:36AM -0700, Karl Williamson wrote:
We don't really define what we consider security bugs all that well. If your web server crashed (with no other security implications) every It would be nice to document what is and isn't a security issue, both Note that treating denial of service attacks as security issues The other side of the problem is whether to treat potential security From my own point of view, dealing with security issues is a massive However if an issue has been reported as such, I think we owe it to The three issues in the current batch I think are ambiguously security As to the rest of the tickets in the security list, they're hard to Tony |
From @tonycozOn Thu, 01 Mar 2018 15:01:01 -0800, tonyc wrote:
Urr, *un*-ambiguously.
Tony |
From @tonycozOn Thu, 01 Mar 2018 05:46:45 -0800, shay wrote:
An alternative, which might be safer, might be to release 5.26.2 as 5.26.1 plus only the security related fixes, and similarly for 5.24.4. This would mean that we're (or mostly you) aren't rushing to integrate all of the voted on changes. It would mean that 5.26.2 and 5.24.4 wouldn't be on their corresponding maint-* branches, but I think it would be less risky and stressful than setting a fixed target date for 5.26.1 + various changes + security fixes. It does mean the maint releaser is going through an extra release process for each branch, but it should be relatively simpler than a release with a more extensive set of changes. If we do separate security releases, we might treat them as outside the maint releaser's (volunteer anyway) responsibility, so that doing a security release might be done by someone else (probably me in this case.) Of course, the changes in the security releases would still need to be merged into the maint-* branches, but it would reduce the time stress for normal maint releases. Tony |
From @tonycozOn Tue, 13 Feb 2018 15:47:49 -0800, tonyc wrote:
Niko Tyni pointed out the first test fails on -DDEBUGGING builts on 32-bit systems, since realloc() (in this case) panics on allocations over 2GB (on 32-bit systems) rather than failing, changing the error message. To prevent this the macros in pp_pack.c in the attached patches limit the allocation size to half the address space, rather than all of the address space. Tony |
From @tonycoz5.24-0001-perl-131844-fix-various-space-calculation-issues-in-.patchFrom c3d9db7eb4dc1747fff423ebaf0c1bcd62c2e8a9 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 8 Aug 2017 09:32:58 +1000
Subject: (perl #131844) fix various space calculation issues in pp_pack.c
- for the originally reported case, if the start/cur pointer is in the
top 75% of the address space the add (cur) + glen addition would
overflow, resulting in the condition failing incorrectly.
- the addition of the existing space used to the space needed could
overflow, resulting in too small an allocation and a buffer overflow.
- the scaling for UTF8 could overflow.
- the multiply to calculate the space needed for many items could
overflow.
For the first case, do a space calculation without making new pointers.
For the other cases, detect the overflow and croak if there's an
overflow.
Originally this used Size_t_MAX as the maximum size of a memory
allocation, but for -DDEBUGGING builds realloc() throws a panic for
allocations over half the address space in size, changing the error
reported for the allocation.
For non-DEBUGGING builds the Size_t_MAX limit has the small chance
of finding a system that has 3GB of contiguous space available, and
allocating that space, which could be a denial of servce in some cases.
Unfortunately changing the limit to half the address space means that
the exact case with the original issue can no longer occur, so the
test is no longer testing against the address + length issue that
caused the original problem, since the allocation is failing earlier.
One option would be to change the test so the size request by pack is
just under 2GB, but this has a higher (but still low) probability that
the system has the address space available, and will actually try to
allocate the memory, so let's not do that.
---
pp_pack.c | 25 +++++++++++++++++++++----
t/op/pack.t | 24 +++++++++++++++++++++++-
2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/pp_pack.c b/pp_pack.c
index f6964c3f30..c0de5ab82b 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -358,11 +358,28 @@ STMT_START { \
} \
} STMT_END
+#define SAFE_UTF8_EXPAND(var) \
+STMT_START { \
+ if ((var) > SSize_t_MAX / UTF8_EXPAND) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ (var) = (var) * UTF8_EXPAND; \
+} STMT_END
+
+#define GROWING2(utf8, cat, start, cur, item_size, item_count) \
+STMT_START { \
+ if (SSize_t_MAX / (item_size) < (item_count)) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ GROWING((utf8), (cat), (start), (cur), (item_size) * (item_count)); \
+} STMT_END
+
#define GROWING(utf8, cat, start, cur, in_len) \
STMT_START { \
STRLEN glen = (in_len); \
- if (utf8) glen *= UTF8_EXPAND; \
- if ((cur) + glen >= (start) + SvLEN(cat)) { \
+ STRLEN catcur = (STRLEN)((cur) - (start)); \
+ if (utf8) SAFE_UTF8_EXPAND(glen); \
+ if (SSize_t_MAX - glen < catcur) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ if (catcur + glen >= SvLEN(cat)) { \
(start) = sv_exp_grow(cat, glen); \
(cur) = (start) + SvCUR(cat); \
} \
@@ -372,7 +389,7 @@ STMT_START { \
STMT_START { \
const STRLEN glen = (in_len); \
STRLEN gl = glen; \
- if (utf8) gl *= UTF8_EXPAND; \
+ if (utf8) SAFE_UTF8_EXPAND(gl); \
if ((cur) + gl >= (start) + SvLEN(cat)) { \
*cur = '\0'; \
SvCUR_set((cat), (cur) - (start)); \
@@ -2126,7 +2143,7 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
if (props && !(props & PACK_SIZE_UNPREDICTABLE)) {
/* We can process this letter. */
STRLEN size = props & PACK_SIZE_MASK;
- GROWING(utf8, cat, start, cur, (STRLEN) len * size);
+ GROWING2(utf8, cat, start, cur, size, (STRLEN)len);
}
}
diff --git a/t/op/pack.t b/t/op/pack.t
index a2da63689b..a480c3ad7f 100644
--- a/t/op/pack.t
+++ b/t/op/pack.t
@@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' :
my $no_signedness = $] > 5.009 ? '' :
"Signed/unsigned pack modifiers not available on this perl";
-plan tests => 14712;
+plan tests => 14716;
use strict;
use warnings qw(FATAL all);
@@ -2044,3 +2044,25 @@ ok(1, "argument underflow did not crash");
is(pack("H40", $up_nul), $twenty_nuls,
"check pack H zero fills (utf8 source)");
}
+
+SKIP:
+{
+ # [perl #131844] pointer addition overflow
+ $Config{ptrsize} == 4
+ or skip "[perl #131844] need 32-bit build for this test", 4;
+ # prevent ASAN just crashing on the allocation failure
+ local $ENV{ASAN_OPTIONS} = $ENV{ASAN_OPTIONS};
+ $ENV{ASAN_OPTIONS} .= ",allocator_may_return_null=1";
+ fresh_perl_like('pack "f999999999"', qr/Out of memory during pack/, { stderr => 1 },
+ "pointer addition overflow");
+
+ # integer (STRLEN) overflow from addition of glen to current length
+ fresh_perl_like('pack "c10f1073741823"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (addition)");
+
+ fresh_perl_like('pack "W10f536870913", 256', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (utf8)");
+
+ fresh_perl_like('pack "c10f1073741824"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (multiply)");
+}
--
2.11.0
|
From @tonycozblead-0001-perl-131844-fix-various-space-calculation-issues-in-.patchFrom 4fe5c257e1cc53bec43f8dffea6f93c7e2597b37 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Tue, 8 Aug 2017 09:32:58 +1000
Subject: (perl #131844) fix various space calculation issues in pp_pack.c
- for the originally reported case, if the start/cur pointer is in the
top 75% of the address space the add (cur) + glen addition would
overflow, resulting in the condition failing incorrectly.
- the addition of the existing space used to the space needed could
overflow, resulting in too small an allocation and a buffer overflow.
- the scaling for UTF8 could overflow.
- the multiply to calculate the space needed for many items could
overflow.
For the first case, do a space calculation without making new pointers.
For the other cases, detect the overflow and croak if there's an
overflow.
Originally this used Size_t_MAX as the maximum size of a memory
allocation, but for -DDEBUGGING builds realloc() throws a panic for
allocations over half the address space in size, changing the error
reported for the allocation.
For non-DEBUGGING builds the Size_t_MAX limit has the small chance
of finding a system that has 3GB of contiguous space available, and
allocating that space, which could be a denial of servce in some cases.
Unfortunately changing the limit to half the address space means that
the exact case with the original issue can no longer occur, so the
test is no longer testing against the address + length issue that
caused the original problem, since the allocation is failing earlier.
One option would be to change the test so the size request by pack is
just under 2GB, but this has a higher (but still low) probability that
the system has the address space available, and will actually try to
allocate the memory, so let's not do that.
---
pp_pack.c | 25 +++++++++++++++++++++----
t/op/pack.t | 24 +++++++++++++++++++++++-
2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/pp_pack.c b/pp_pack.c
index 8937d6d715..5e9cc64301 100644
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -357,11 +357,28 @@ STMT_START { \
} \
} STMT_END
+#define SAFE_UTF8_EXPAND(var) \
+STMT_START { \
+ if ((var) > SSize_t_MAX / UTF8_EXPAND) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ (var) = (var) * UTF8_EXPAND; \
+} STMT_END
+
+#define GROWING2(utf8, cat, start, cur, item_size, item_count) \
+STMT_START { \
+ if (SSize_t_MAX / (item_size) < (item_count)) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ GROWING((utf8), (cat), (start), (cur), (item_size) * (item_count)); \
+} STMT_END
+
#define GROWING(utf8, cat, start, cur, in_len) \
STMT_START { \
STRLEN glen = (in_len); \
- if (utf8) glen *= UTF8_EXPAND; \
- if ((cur) + glen >= (start) + SvLEN(cat)) { \
+ STRLEN catcur = (STRLEN)((cur) - (start)); \
+ if (utf8) SAFE_UTF8_EXPAND(glen); \
+ if (SSize_t_MAX - glen < catcur) \
+ Perl_croak(aTHX_ "%s", "Out of memory during pack()"); \
+ if (catcur + glen >= SvLEN(cat)) { \
(start) = sv_exp_grow(cat, glen); \
(cur) = (start) + SvCUR(cat); \
} \
@@ -371,7 +388,7 @@ STMT_START { \
STMT_START { \
const STRLEN glen = (in_len); \
STRLEN gl = glen; \
- if (utf8) gl *= UTF8_EXPAND; \
+ if (utf8) SAFE_UTF8_EXPAND(gl); \
if ((cur) + gl >= (start) + SvLEN(cat)) { \
*cur = '\0'; \
SvCUR_set((cat), (cur) - (start)); \
@@ -2131,7 +2148,7 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
if (props && !(props & PACK_SIZE_UNPREDICTABLE)) {
/* We can process this letter. */
STRLEN size = props & PACK_SIZE_MASK;
- GROWING(utf8, cat, start, cur, (STRLEN) len * size);
+ GROWING2(utf8, cat, start, cur, size, (STRLEN)len);
}
}
diff --git a/t/op/pack.t b/t/op/pack.t
index 664aaaf1b0..cf0e286509 100644
--- a/t/op/pack.t
+++ b/t/op/pack.t
@@ -12,7 +12,7 @@ my $no_endianness = $] > 5.009 ? '' :
my $no_signedness = $] > 5.009 ? '' :
"Signed/unsigned pack modifiers not available on this perl";
-plan tests => 14713;
+plan tests => 14717;
use strict;
use warnings qw(FATAL all);
@@ -2059,3 +2059,25 @@ print pack("ucW", "0000", 0, 140737488355327) eq "\$,#`P,```\n\0\x{7fffffffffff}
? "ok\n" : "not ok\n";
EOS
}
+
+SKIP:
+{
+ # [perl #131844] pointer addition overflow
+ $Config{ptrsize} == 4
+ or skip "[perl #131844] need 32-bit build for this test", 4;
+ # prevent ASAN just crashing on the allocation failure
+ local $ENV{ASAN_OPTIONS} = $ENV{ASAN_OPTIONS};
+ $ENV{ASAN_OPTIONS} .= ",allocator_may_return_null=1";
+ fresh_perl_like('pack "f999999999"', qr/Out of memory during pack/, { stderr => 1 },
+ "pointer addition overflow");
+
+ # integer (STRLEN) overflow from addition of glen to current length
+ fresh_perl_like('pack "c10f1073741823"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (addition)");
+
+ fresh_perl_like('pack "W10f536870913", 256', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (utf8)");
+
+ fresh_perl_like('pack "c10f1073741824"', qr/Out of memory during pack/, { stderr => 1 },
+ "integer overflow calculating allocation (multiply)");
+}
--
2.11.0
|
From @steve-m-hayOn 5 March 2018 at 05:25, Tony Cook via RT
I asked perl5-security on 6 Feb whether to do security-only releases But then a proposed release date of 15 Mar came up, making that look However, unless it's quite a long postponement then a full 5.26.2 is So I'd be happy with largely security-only 5.26.2/5.24.4 releases, but The main problem is that we'll have no time left after this to get a So then we'll have gone through the entire 5.26 cycle with no full It seems like every time I plan on doing a maint release it gets |
From @xsawyerxOn 5 March 2018 at 10:51, Steve Hay via perl5-security-report
I'm still waiting to hear from the vendor on their proposed date. I I will postpone it anyway. I'm just not sure for how long. See next comment.
Security tickets will come up. I think the answer is for me to not Please accept my apology, and with this next set of patches, once I |
From @steve-m-hayOn 5 March 2018 at 13:02, Sawyer X <xsawyerx@gmail.com> wrote:
Sorry for not replying sooner. Yes, that sounds good to me. I've now pushed an update to the 5.26 voting file containing my list Hopefully the list is sufficiently short that we can get these done, |
From @xsawyerxThe disclosure date has been postponed officially to April 14th. On 7 March 2018 at 20:10, Steve Hay <steve.m.hay@googlemail.com> wrote:
|
@xsawyerx - Status changed from 'open' to 'pending release' |
From @xsawyerxOn Mon, 19 Mar 2018 15:26:25 -0700, xsawyerx@gmail.com wrote:
Moved to public queue. |
From @khwilliamsonThank you for filing this report. You have helped make Perl better. With the release yesterday of Perl 5.28.0, this and 185 other issues have been Perl 5.28.0 may be downloaded via: If you find that the problem persists, feel free to reopen this ticket. |
@khwilliamson - Status changed from 'pending release' to 'resolved' |
Migrated from rt.perl.org#131844 (status was 'resolved')
Searchable as RT131844$
The text was updated successfully, but these errors were encountered: