Skip to content

[PATCH] handle SIGBUS on shrinked Bigarray mapped files #5471

@vicuna

Description

@vicuna

Original bug ID: 5471
Reporter: @edwintorok
Assigned to: @protz
Status: closed (set by @xavierleroy on 2013-08-31T10:44:26Z)
Resolution: fixed
Priority: normal
Severity: minor
Platform: Linux
OS: Debian GNU/Linux
OS Version: Linux 3.2.0
Version: 3.12.1
Fixed in version: 3.13.0+dev
Category: ~DO NOT USE (was: OCaml general)
Monitored by: mehdi

Bug description

Accesses to bigarrays are bounds-checked, but the bounds for Bigarray.*.map_file
is established when the file is mapped.
Later the file may shrink or grow, if another (or the same) process modifies it.
If the file shrinks, and you attempt to read/write past the new end-of-file
the OS may raise SIGBUS (for example Linux does).

It is not possible to handle SIGBUS purely on OCaml side, because
attempting to set an OCaml signal handler would cause SIGBUS to be
re-delivered infinitely.

Attached patch (for ocaml trunk) implements SIGBUS handling in the byterun/asmrun runtimes.
It also introduces a new page flag In_mapped_area, that is set by bigarray.
This way we know the SIGBUS came from our mapping, and not from some other
native code mapping.

Patch note: The stdlib/printexc.ml change require an 'make coreboot' run.
If you 'git apply attachedpatch.patch' then it'll update boot/ for you.

Steps to reproduce

  1. Compile the below code with ocamlc and ocamlopt

  2. Run xbyte and xnat

  3. Current results: both crash
    $ ./xbyte (or ./xnat)
    trying to read invalid mem area
    Bus error

  4. Uncomment the Sys.set_signal line, and run again. Now you got an infinite loop (SIGBUS delivered over and over again and the OCaml signal handle never reached).

  5. Expected result: no crash, an OCaml exception is raised (like with stack overflow, bounds errors, etc.):

Expected xbyte output:

trying to read invalid mem area
exception caught: Bus error
Raised by primitive operation at unknown location
trying to write invalid mem area
Raised by primitive operation at unknown location
exception caught: Bus error

Expected xnat output:
trying to read invalid mem area
exception caught: Bus error
Raised by primitive operation at file "pervasives.ml", line 250, characters 21-28
trying to write invalid mem area
Raised by primitive operation at file "pervasives.ml", line 250, characters 21-28
exception caught: Bus error

Additional information

(* test code

  • ocamlc bigarray.cma unix.cma x.ml -o xbyte; ./xbyte
  • ocamlopt bigarray.cmxa unix.cmxa x.ml -o xnat; ./xnat
    *)

open Bigarray
open Unix

exception Sigbus

let sigbus_handler _ =
raise Sigbus;;

let _ =
Printexc.record_backtrace true;
(* Sys.set_signal 7 (Sys.Signal_handle sigbus_handler);*)
close (openfile "/tmp/x" [O_CREAT] 0o644);
truncate "/tmp/x" 1024;
let fd = openfile "/tmp/x" [ O_RDWR ] 0 in
let m = Array1.map_file fd char c_layout false (-1) in
Printf.printf "%c" m.{0};
ftruncate fd 0;
begin try
Printf.printf "trying to read invalid mem area\n";
flush_all ();
Printf.printf "%c" m.{0}
with
| e ->
Printf.printf "exception caught: %s\n" (Printexc.to_string e);
Printexc.print_backtrace Pervasives.stdout;
flush_all ();
end;
begin try
Printf.printf "trying to write invalid mem area\n";
Printexc.print_backtrace Pervasives.stdout;
flush_all ();
m.{0} <- 'a';
with
| e ->
Printf.printf "exception caught: %s\n" (Printexc.to_string e);
flush_all ();
end;;

File attachments

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions