< prev index next >

src/os/posix/vm/os_posix.cpp

Print this page
rev 12741 : 8173848: realpath is unsafe
Summary: Fix occurrences of realpath in hotspot to use safe POSIX.1-2008 form.
Reviewed-by: dsamersoff, dholmes, clanger

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -1103,10 +1103,52 @@
     stack_size / 1024, guard_size / 1024,
     (detachstate == PTHREAD_CREATE_DETACHED ? "detached" : "joinable"));
   return buf;
 }
 
+char* os::Posix::realpath(const char* filename, char* outbuf, size_t outbuflen) {
+
+  if (filename == NULL || outbuf == NULL || outbuflen < 1) {
+    assert(false, "os::Posix::realpath: invalid arguments.");
+    errno = EINVAL;
+    return NULL;
+  }
+
+  char* result = NULL;
+
+  // This assumes platform realpath() is implemented according to POSIX.1-2008.
+  // POSIX.1-2008 allows to specify NULL for the output buffer, in which case
+  // output buffer is dynamically allocated and must be ::free()'d by the caller.
+  char* p = ::realpath(filename, NULL);
+  if (p != NULL) {
+    if (strlen(p) < outbuflen) {
+      strcpy(outbuf, p);
+      result = outbuf;
+    } else {
+      errno = ENAMETOOLONG;
+    }
+    ::free(p); // *not* os::free
+  } else {
+    // Fallback for platforms struggling with modern Posix standards (AIX 5.3, 6.1). If realpath
+    // returns EINVAL, this may indicate that realpath is not POSIX.1-2008 compatible and
+    // that it complains about the NULL we handed down as user buffer.
+    // In this case, use the user provided buffer but at least check whether realpath caused
+    // a memory overwrite.
+    if (errno == EINVAL) {
+      outbuf[outbuflen - 1] = '\0';
+      p = ::realpath(filename, outbuf);
+      if (p != NULL) {
+        guarantee(outbuf[outbuflen - 1] == '\0', "realpath buffer overwrite detected.");
+        result = p;
+      }
+    }
+  }
+  return result;
+
+}
+
+
 // Check minimum allowable stack sizes for thread creation and to initialize
 // the java system classes, including StackOverflowError - depends on page
 // size.
 // The space needed for frames during startup is platform dependent. It
 // depends on word size, platform calling conventions, C frame layout and
< prev index next >