[erlang-bugs] Buffer overflow in etrs_save_mb[]

Bjorn Gustavsson <>
Thu Dec 21 15:21:15 CET 2006


Thanks for your bug report!

R11B has new instructions for bit syntax matching, so the
problem doesn't exist there, unless you load code compiled
by an R10B compiler. For R11B-3, I have changed the loader
to reject bs_save/bs_restore instruction with an index greater
than 1023 if you load code compiled by R10B. I have also
changed beam_validator to reject those instructions (in case
it is used for validating R10B code).

/Bjorn

Matthew Reilly <> writes:

> Erlang/OTP team,
> 
> There is a buffer overflow that can occur in the beam interpreter in
> the etrs_save_mb[] array. This can occur if a module contains a large
> number of binary matches. This buffer overflow is known to exist for all
> Erlang/OTP versions between R10B-6 and R11B-2. Sample code is attached
> that causes a SEGV (at least on Linux systems).
> 
> The source of the overflow is the opcode "bs_save".
> 
> The code in BEAM that interprets this opcode is in
> erts/emulator/beam/beam_emu.c:process_main():
>  OpCase(bs_save_I): {
>      Eterm* next;
> 
>      PreFetch(1, next);
>      erts_save_mb[Arg(0)] = erts_mb;
>      NextPF(1, next);
>  }
> 
> This saves the current value of "erts_mb" into the array
> "erts_save_mb[1024]" at an offset of "Arg(0)". This code does not do
> any bounds checking on this array. If a compiled ".beam" file has an
> opcode such as "{bs_save,1040}", then the beam interpreter's memory will
> be corrupted.
> 
> The erlang byte-code compiler can easily generate arguments to "bs_save"
> that are greater than 1024. If a module contains matching to static 
> binary values, the compiler generates code for each byte in the binaries
> such as:
> ...
>     {bs_save,1040}.
>     {test,is_eq_exact,{f,1},[{x,12},{integer,21}]}.
>     {bs_restore,1040}.
> ...
>     {bs_save,1041}.
>     {test,is_eq_exact,{f,1},[{x,13},{integer,182}]}.
>     {bs_restore,1041}.
> ...
> 
> Even though the saved value is never referenced again, the compiler
> increments the arg to "bs_save" and it does so without checking if the
> argument exceeds the size of the "erts_save_mb[]" array.
> 
> I have not tried this code with HiPE, but since HiPE uses the function
> erts/emulator/beam/erl_bits.c:erts_bs_save() (which also does not check
> the bounds of erts_save_mb), it most likely has the same bug:
> void erts_bs_save(ERL_BITS_PROTO_1(int index))
> {
>     erts_save_mb[index] = erts_mb;
> }
> 
> 
> Most likely, to avoid this bug:
> 
> - the compiler should re-use args to "bs_save" (especially where it
> immediately does a "bs_restore") instead of just incremented it each
> byte.
> 
> - the beam runtime should check the offsets for "bs_save" at beam file
> load time to make sure it is < MAX_REG (perhaps in beam_validator?)
> 
> 
> Thank you,
> Matt Reilly
> SIPphone Inc.
> 
> %%%%%%%%%%%% Begin buffer_overflow.erl %%%%%%%%%%%%%
> %% Test with:
> %% $ erlc buffer_overflow.erl
> %% $ erl -s buffer_overflow crash
> -module(buffer_overflow).
> 
> -export([
>     crash/0
> ]).
> 
> m(<<196,202,66,56,160,185,35,130,13,204,80,154,111,117,132,155>>) -> 1;
> m(<<200,30,114,141,157,76,47,99,111,6,127,137,204,20,134,44>>) -> 2;
> m(<<236,203,200,126,75,92,226,254,40,48,143,217,242,167,186,243>>) -> 3;
> m(<<168,127,246,121,162,243,231,29,145,129,166,123,117,66,18,44>>) -> 4;
> m(<<228,218,59,127,187,206,35,69,215,119,43,6,116,163,24,213>>) -> 5;
> m(<<22,121,9,28,90,136,15,175,111,181,230,8,126,177,178,220>>) -> 6;
> m(<<143,20,228,95,206,234,22,122,90,54,222,221,75,234,37,67>>) -> 7;
> m(<<201,240,248,149,251,152,171,145,89,245,31,208,41,126,35,109>>) -> 8;
> m(<<69,196,140,206,46,45,127,189,234,26,252,81,199,198,173,38>>) -> 9;
> m(<<211,217,68,104,2,164,66,89,117,93,56,230,209,99,232,32>>) -> 10;
> m(<<101,18,189,67,217,202,166,224,44,153,11,10,130,101,45,202>>) -> 11;
> m(<<194,10,212,215,111,233,119,89,170,39,160,201,155,255,103,16>>) ->12;
> m(<<197,28,228,16,193,36,161,14,13,181,228,185,127,194,175,57>>) -> 13;
> m(<<170,179,35,137,34,188,194,90,111,96,110,181,37,255,220,86>>) -> 14;
> m(<<155,243,28,127,240,98,147,106,150,211,200,189,31,143,47,243>>) ->15;
> m(<<199,77,151,176,30,174,37,126,68,170,157,91,173,233,123,175>>) -> 16;
> m(<<112,239,223,46,201,176,134,7,151,149,196,66,99,107,85,251>>) -> 17;
> m(<<111,73,34,244,85,104,22,26,140,223,74,210,41,159,109,35>>) -> 18;
> m(<<31,14,61,173,153,144,131,69,247,67,159,143,250,189,255,196>>) -> 19;
> m(<<152,241,55,8,33,1,148,196,117,104,123,230,16,106,59,132>>) -> 20;
> m(<<60,89,220,4,142,136,80,36,59,232,7,154,92,116,208,121>>) -> 21;
> m(<<182,215,103,210,248,237,93,33,164,75,14,88,134,104,12,185>>) -> 22;
> m(<<55,105,60,252,116,128,73,228,93,135,184,199,216,185,170,205>>) ->23;
> m(<<31,241,222,119,64,5,248,218,19,244,41,67,136,28,101,95>>) -> 24;
> m(<<142,41,106,6,122,55,86,51,112,222,208,95,90,59,243,236>>) -> 25;
> m(<<78,115,44,237,52,99,208,109,224,202,154,21,182,21,54,119>>) -> 26;
> m(<<2,231,79,16,224,50,122,216,104,209,56,242,180,253,214,240>>) -> 27;
> m(<<51,231,95,240,157,214,1,187,230,159,53,16,57,21,33,137>>) -> 28;
> m(<<110,169,171,27,170,14,251,158,25,9,68,64,195,23,226,27>>) -> 29;
> m(<<52,23,60,179,143,7,248,157,219,235,194,172,145,40,48,63>>) -> 30;
> m(<<193,106,83,32,250,71,85,48,217,88,60,52,253,53,110,245>>) -> 31;
> m(<<99,100,211,240,244,149,182,171,157,207,141,59,92,110,11,1>>) -> 32;
> m(<<24,43,224,197,205,205,80,114,187,24,100,205,238,77,61,110>>) -> 33;
> m(<<227,105,133,61,247,102,250,68,225,237,15,246,19,245,99,189>>) -> 34;
> m(<<28,56,60,211,11,124,41,138,181,2,147,173,254,203,123,24>>) -> 35;
> m(<<25,202,20,231,234,99,40,164,46,14,177,61,88,94,76,34>>) -> 36;
> m(<<165,191,201,224,121,100,248,221,222,185,95,197,132,205,150,93>>)->37;
> m(<<165,119,27,206,147,226,0,195,111,124,217,223,208,229,222,170>>)->38;
> m(<<214,125,138,180,244,193,11,242,42,163,83,226,120,121,19,60>>) -> 39;
> m(<<214,69,146,14,57,95,237,173,123,187,237,14,202,63,226,224>>) -> 40;
> m(<<52,22,167,95,76,234,145,9,80,124,172,216,226,242,174,252>>) -> 41;
> m(<<161,208,198,232,63,2,115,39,216,70,16,99,244,172,88,166>>) -> 42;
> m(<<23,230,33,102,252,133,134,223,164,209,188,14,23,66,192,139>>) -> 43;
> m(<<247,23,113,99,200,51,223,244,179,143,200,210,135,47,30,198>>) -> 44;
> m(<<108,131,73,204,114,96,174,98,227,177,57,104,49,168,57,143>>) -> 45;
> m(<<217,212,244,149,232,117,162,224,117,161,164,166,225,185,119,15>>)->46;
> m(<<103,198,161,231,206,86,211,214,250,116,138,182,217,175,63,215>>)->47;
> m(<<100,46,146,239,183,148,33,115,72,129,181,62,30,27,24,182>>) -> 48;
> m(<<244,87,197,69,169,222,216,143,24,236,238,71,20,90,114,192>>) -> 49;
> m(<<192,199,199,109,48,189,61,202,239,201,111,64,39,91,220,10>>) -> 50;
> m(<<40,56,2,58,119,141,250,236,220,33,39,8,247,33,183,136>>) -> 51;
> m(<<154,17,88,21,77,250,66,202,221,189,6,148,164,233,189,200>>) -> 52;
> m(<<216,44,141,22,25,173,129,118,214,101,69,60,251,46,85,240>>) -> 53;
> m(<<166,132,236,238,231,111,197,34,119,50,134,168,149,188,132,54>>)->54;
> m(<<181,59,58,61,106,185,12,224,38,130,41,21,28,155,222,17>>) -> 55;
> m(<<159,97,64,142,58,251,99,62,80,205,241,178,13,230,244,102>>) -> 56;
> m(<<114,179,42,31,117,75,161,192,155,54,149,224,203,108,222,127>>) ->57;
> m(<<102,240,65,225,106,96,146,139,5,167,226,40,168,156,55,153>>) -> 58;
> m(<<9,63,101,224,128,162,149,248,7,107,28,87,34,164,106,162>>) -> 59;
> m(<<7,43,3,11,161,38,178,244,178,55,79,52,43,233,237,68>>) -> 60;
> m(<<127,57,248,49,127,189,177,152,142,244,198,40,235,160,37,145>>) ->61;
> m(<<68,246,131,168,65,99,179,82,58,254,87,194,224,8,188,140>>) -> 62;
> m(<<3,175,219,214,110,121,41,177,37,248,89,120,52,250,131,164>>) -> 63;
> m(<<234,93,47,28,70,8,35,46,7,211,170,61,153,142,81,53>>) -> 64;
> m(<<252,73,12,164,92,0,177,36,155,190,53,84,164,253,246,251>>) -> 65;
> m(<<50,149,199,106,203,244,202,174,211,60,54,177,181,252,44,177>>) ->66;
> m(<<115,91,144,180,86,129,37,237,108,63,103,136,25,182,224,88>>) -> 67;
> m(<<163,243,144,216,142,76,65,242,116,123,250,47,27,95,135,219>>) -> 68;
> m(<<20,191,166,187,20,135,94,69,187,160,40,162,30,211,128,70>>) -> 69;
> m(<<124,187,196,9,236,153,15,25,199,140,117,189,30,6,242,21>>) -> 70;
> m(<<226,196,32,217,40,212,191,140,224,255,46,193,155,55,21,20>>) -> 71;
> m(<<50,187,144,232,151,106,171,82,152,213,218,16,254,102,242,29>>) ->72;
> m(<<210,221,234,24,240,6,101,206,134,35,227,107,212,227,199,197>>) ->73;
> m(<<173,97,171,20,50,35,239,188,36,199,210,88,59,230,146,81>>) -> 74;
> m(<<208,155,244,21,68,163,54,90,70,201,7,126,187,94,53,195>>) -> 75;
> m(<<251,215,147,157,103,73,151,205,180,105,45,52,222,134,51,196>>) ->76;
> m(<<40,221,44,121,85,206,146,100,86,36,11,47,240,16,11,222>>) -> 77;
> m(<<53,244,168,212,101,230,225,237,192,95,61,138,182,88,197,81>>) -> 78;
> m(<<209,254,23,61,8,233,89,57,122,223,52,177,215,126,136,215>>) -> 79;
> m(<<240,51,171,55,195,2,1,247,63,20,36,73,208,55,2,141>>) -> 80;
> m(<<67,236,81,125,104,182,237,211,1,91,62,220,154,17,54,123>>) -> 81;
> m(<<151,120,213,210,25,197,8,11,154,106,23,190,240,41,51,28>>) -> 82;
> m(<<254,159,194,137,195,255,10,241,66,182,211,190,173,152,169,35>>)->83;
> m(<<104,211,10,149,148,114,139,195,154,162,75,233,75,49,157,33>>) -> 84;
> m(<<62,248,21,65,111,119,80,152,254,151,112,4,1,92,97,147>>) -> 85;
> m(<<147,219,133,237,144,156,19,131,143,249,92,207,169,76,235,217>>)->86;
> m(<<199,225,36,159,252,3,235,157,237,144,140,35,107,209,153,109>>) ->87;
> m(<<42,56,164,169,49,108,73,229,168,51,81,124,69,211,16,112>>) -> 88;
> m(<<118,71,150,107,115,67,194,144,72,103,50,82,228,144,247,54>>) -> 89;
> m(<<134,19,152,94,196,158,184,247,87,174,100,57,232,121,187,42>>) -> 90;
> m(<<84,34,154,191,207,165,100,158,112,3,184,61,212,117,82,148>>) -> 91;
> m(<<146,204,34,117,50,209,126,86,224,121,2,178,84,223,173,16>>) -> 92;
> m(<<152,220,232,61,165,123,3,149,225,99,70,124,157,174,82,27>>) -> 93;
> m(<<244,185,236,48,173,159,104,248,155,41,99,151,134,203,98,239>>) ->94;
> m(<<129,43,75,162,135,245,238,11,201,212,59,191,91,190,135,251>>) -> 95;
> m(<<38,101,125,95,249,2,13,42,190,254,85,135,150,185,149,132>>) -> 96;
> m(<<226,239,82,79,191,61,159,230,17,213,168,233,15,239,220,156>>) -> 97;
> m(<<237,61,44,33,153,30,59,239,94,6,151,19,175,159,166,202>>) -> 98;
> m(<<172,98,122,177,204,189,182,46,201,110,112,47,7,246,66,91>>) -> 99;
> m(<<248,153,19,157,245,225,5,147,150,67,20,21,231,112,198,221>>) -> 100.
> 
> crash() ->
>     lists:foreach(
>         fun(N) ->
>             io:format("Trying to match md5(~B)~n",[N]),
>             BinaryToMatch = erlang:md5(integer_to_list(N)),
> 
>             %% The pattern matching on binaries for this call
>             %% will cause buffer overflow.
>             m(BinaryToMatch)
>         end,
>         lists:seq(1,100)
>     ).
> %%%%%%%%%%%% End buffer_overflow.erl %%%%%%%%%%%%%
> 
> -- 
> Matthew Reilly
> SIPphone Inc.
> 
> Gizmo Project name: matt 
> 
> _______________________________________________
> erlang-bugs mailing list
> 
> http://www.erlang.org/mailman/listinfo/erlang-bugs
> 

-- 
Björn Gustavsson, Erlang/OTP, Ericsson AB




More information about the erlang-bugs mailing list