aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux
diff options
context:
space:
mode:
authorGabriele Svelto <gsvelto@mozilla.com>2017-04-11 11:51:28 +0200
committerMike Frysinger <vapier@chromium.org>2017-04-12 18:51:24 +0000
commita9fca58305afcb16a7ae539d87d672c702aba3f1 (patch)
tree06ef59d420b0168a301e27a56dd2bc8e7702a432 /src/common/linux
parentDump MH_DYLINKER images in upload_system_symbols. (diff)
downloadbreakpad-a9fca58305afcb16a7ae539d87d672c702aba3f1.tar.xz
Make minidump name generation on Linux as random as possible
This patch ensures that two crashes taken within the same second have different minidump names. The random characters used in the minidump filename are now read from /dev/urandom where possible or generated via arc4random(). If neither is available we fall back to regular rand() but mixing the address of an object to the current time when generating the random seed to make it slightly less predictable. BUG=681 Change-Id: I2e97454859ed386e199b2628d6b7e87e16481b75 Reviewed-on: https://chromium-review.googlesource.com/445784 Reviewed-by: Mike Frysinger <vapier@chromium.org>
Diffstat (limited to 'src/common/linux')
-rw-r--r--src/common/linux/guid_creator.cc94
1 files changed, 87 insertions, 7 deletions
diff --git a/src/common/linux/guid_creator.cc b/src/common/linux/guid_creator.cc
index bfb308ee..c92e69f4 100644
--- a/src/common/linux/guid_creator.cc
+++ b/src/common/linux/guid_creator.cc
@@ -27,15 +27,22 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include "common/linux/eintr_wrapper.h"
#include "common/linux/guid_creator.h"
#include <assert.h>
+#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
+#if defined(HAVE_SYS_RANDOM_H)
+#include <sys/random.h>
+#endif
+
//
// GUIDGenerator
//
@@ -61,28 +68,101 @@ class GUIDGenerator {
}
static bool CreateGUID(GUID *guid) {
- InitOnce();
- guid->data1 = random();
- guid->data2 = (uint16_t)(random());
- guid->data3 = (uint16_t)(random());
- UInt32ToBytes(&guid->data4[0], random());
- UInt32ToBytes(&guid->data4[4], random());
+#if defined(HAVE_ARC4RANDOM) // Android, BSD, ...
+ CreateGuidFromArc4Random(guid);
+#else // Linux
+ bool success = false;
+
+#if defined(HAVE_SYS_RANDOM_H) && defined(HAVE_GETRANDOM)
+ success = CreateGUIDFromGetrandom(guid);
+#endif // HAVE_SYS_RANDOM_H && HAVE_GETRANDOM
+ if (!success) {
+ success = CreateGUIDFromDevUrandom(guid);
+ }
+
+ if (!success) {
+ CreateGUIDFromRand(guid);
+ success = true;
+ }
+#endif
+
+ // Put in the version according to RFC 4122.
+ guid->data3 &= 0x0fff;
+ guid->data3 |= 0x4000;
+
+ // Put in the variant according to RFC 4122.
+ guid->data4[0] &= 0x3f;
+ guid->data4[0] |= 0x80;
+
return true;
}
private:
+#ifdef HAVE_ARC4RANDOM
+ static void CreateGuidFromArc4Random(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+
+ for (size_t i = 0; i < sizeof(GUID); i += sizeof(uint32_t)) {
+ uint32_t random_data = arc4random();
+
+ memcpy(buf + i, &random_data, sizeof(uint32_t));
+ }
+ }
+#else
static void InitOnce() {
pthread_once(&once_control, &InitOnceImpl);
}
static void InitOnceImpl() {
- srandom(time(NULL));
+ // time(NULL) is a very poor seed, so lacking anything better mix an
+ // address into it. We drop the four rightmost bits as they're likely to
+ // be 0 on almost all architectures.
+ srand(time(NULL) | ((uintptr_t)&once_control >> 4));
}
static pthread_once_t once_control;
+
+#if defined(HAVE_SYS_RANDOM_H) && defined(HAVE_GETRANDOM)
+ static bool CreateGUIDFromGetrandom(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+ int read_bytes = getrandom(buf, sizeof(GUID), GRND_NONBLOCK);
+
+ return (read_bytes == static_cast<int>(sizeof(GUID)));
+ }
+#endif // HAVE_SYS_RANDOM_H && HAVE_GETRANDOM
+
+ // Populate the GUID using random bytes read from /dev/urandom, returns false
+ // if the GUID wasn't fully populated with random data.
+ static bool CreateGUIDFromDevUrandom(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+ int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+
+ if (fd == -1) {
+ return false;
+ }
+
+ ssize_t read_bytes = HANDLE_EINTR(read(fd, buf, sizeof(GUID)));
+ close(fd);
+
+ return (read_bytes == static_cast<ssize_t>(sizeof(GUID)));
+ }
+
+ // Populate the GUID using a stream of random bytes obtained from rand().
+ static void CreateGUIDFromRand(GUID *guid) {
+ char *buf = reinterpret_cast<char *>(guid);
+
+ InitOnce();
+
+ for (size_t i = 0; i < sizeof(GUID); i++) {
+ buf[i] = rand();
+ }
+ }
+#endif
};
+#ifndef HAVE_ARC4RANDOM
pthread_once_t GUIDGenerator::once_control = PTHREAD_ONCE_INIT;
+#endif
bool CreateGUID(GUID *guid) {
return GUIDGenerator::CreateGUID(guid);