psss / rpms / libguestfs

Forked from rpms/libguestfs 5 years ago
Clone
Blob Blame History Raw
From b9a5f430a7bc11b2e2b3aa38e07c44c4c6a75e31 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 14 Nov 2013 10:09:52 +0000
Subject: [PATCH] mllib: Add a utility function for safely reading from
 /dev/urandom.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

OCaml's buffered 'in_channel' has a 64k buffer, so using it to read a
few bytes from /dev/urandom removes a lot of the system's entropy (for
example /proc/sys/kernel/random/entropy_avail goes from ~3000 to 128).

This patch was originally by Edwin Török for builder.ml.  I
generalized it because there are two other places where we did
over-sized reads from /dev/urandom.

(cherry picked from commit f013b15fa1daf623cbf39007182c44c734e9bc79)
---
 builder/Makefile.am  |  1 +
 mllib/Makefile.am    |  3 +++
 mllib/random_seed.ml |  9 ++-------
 mllib/urandom.ml     | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 mllib/urandom.mli    | 22 ++++++++++++++++++++++
 po/POTFILES-ml       |  1 +
 sysprep/Makefile.am  |  1 +
 7 files changed, 78 insertions(+), 7 deletions(-)
 create mode 100644 mllib/urandom.ml
 create mode 100644 mllib/urandom.mli

diff --git a/builder/Makefile.am b/builder/Makefile.am
index a828ffd..30ada87 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -65,6 +65,7 @@ OBJECTS = \
 	$(top_builddir)/mllib/libdir.cmx \
 	$(top_builddir)/mllib/common_gettext.cmx \
 	$(top_builddir)/mllib/common_utils.cmx \
+	$(top_builddir)/mllib/urandom.cmx \
 	$(top_builddir)/mllib/random_seed.cmx \
 	$(top_builddir)/mllib/hostname.cmx \
 	$(top_builddir)/mllib/firstboot.cmx \
diff --git a/mllib/Makefile.am b/mllib/Makefile.am
index 32e0ddf..bacd2bc 100644
--- a/mllib/Makefile.am
+++ b/mllib/Makefile.am
@@ -48,6 +48,8 @@ SOURCES = \
 	tty-c.c \
 	tTY.mli \
 	tTY.ml \
+	urandom.mli \
+	urandom.ml \
 	uri-c.c \
 	uRI.mli \
 	uRI.ml
@@ -70,6 +72,7 @@ OBJECTS = \
 	libdir.cmx \
 	common_gettext.cmx \
 	common_utils.cmx \
+	urandom.cmx \
 	random_seed.cmx \
 	hostname.cmx \
 	firstboot.cmx \
diff --git a/mllib/random_seed.ml b/mllib/random_seed.ml
index f90c833..9ac20eb 100644
--- a/mllib/random_seed.ml
+++ b/mllib/random_seed.ml
@@ -78,13 +78,8 @@ and make_random_seed_file g file =
       (* Default to 512 bytes of randomness. *)
       512 in
 
-  let entropy =
-    (* Get n bytes of randomness from the host. *)
-    let chan = open_in "/dev/urandom" in
-    let buf = String.create n in
-    really_input chan buf 0 n;
-    close_in chan;
-    buf in
+  (* Get n bytes of randomness from the host. *)
+  let entropy = Urandom.urandom_bytes n in
 
   if file_exists then (
     (* Truncate the original file and append, in order to
diff --git a/mllib/urandom.ml b/mllib/urandom.ml
new file mode 100644
index 0000000..3df9b7a
--- /dev/null
+++ b/mllib/urandom.ml
@@ -0,0 +1,48 @@
+(* Read /dev/urandom.
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(* Read and return N bytes (only) from /dev/urandom.
+ *
+ * As pointed out by Edwin Török, previous versions of this had a big
+ * problem.  They used the OCaml buffered I/O library which would read
+ * a lot more data than requested.  This version uses unbuffered I/O
+ * from the Unix module.
+ *)
+
+open Unix
+
+let open_urandom_fd () = openfile "/dev/urandom" [O_RDONLY] 0
+
+let read_byte fd =
+  let s = String.make 1 ' ' in
+  fun () ->
+    if read fd s 0 1 = 0 then (
+      close fd;
+      raise End_of_file
+    );
+    Char.code s.[0]
+
+let urandom_bytes n =
+  assert (n > 0);
+  let ret = String.make n ' ' in
+  let fd = open_urandom_fd () in
+  for i = 0 to n-1 do
+    ret.[i] <- Char.chr (read_byte fd ())
+  done;
+  close fd;
+  ret
diff --git a/mllib/urandom.mli b/mllib/urandom.mli
new file mode 100644
index 0000000..a7d7808
--- /dev/null
+++ b/mllib/urandom.mli
@@ -0,0 +1,22 @@
+(* Read /dev/urandom.
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(** Read and return N bytes (only) from /dev/urandom. *)
+
+val urandom_bytes : int -> string
+(** Read N bytes from /dev/urandom and return it as a binary string. *)
diff --git a/po/POTFILES-ml b/po/POTFILES-ml
index 39ca2a0..efeb75d 100644
--- a/po/POTFILES-ml
+++ b/po/POTFILES-ml
@@ -21,6 +21,7 @@ mllib/progress.ml
 mllib/random_seed.ml
 mllib/tTY.ml
 mllib/uRI.ml
+mllib/urandom.ml
 resize/resize.ml
 sparsify/sparsify.ml
 sysprep/main.ml
diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am
index a74d455..c42fd7d 100644
--- a/sysprep/Makefile.am
+++ b/sysprep/Makefile.am
@@ -88,6 +88,7 @@ OBJECTS = \
 	$(top_builddir)/mllib/uRI.cmx \
 	$(top_builddir)/mllib/crypt-c.o \
 	$(top_builddir)/mllib/crypt.cmx \
+	$(top_builddir)/mllib/urandom.cmx \
 	$(top_builddir)/mllib/password.cmx \
 	$(top_builddir)/mllib/random_seed.cmx \
 	$(top_builddir)/mllib/hostname.cmx \
-- 
1.8.3.1