8173848: realpath is unsafe
Fix occurrences of realpath in hotspot to use safe POSIX.1-2008 form. Reviewed-by: dsamersoff, dholmes, clanger
This commit is contained in:
parent
4b9562288f
commit
35d5d1c53d
@ -1576,7 +1576,7 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
Dl_info dlinfo;
|
||||
int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
|
||||
assert(ret != 0, "cannot locate libjvm");
|
||||
char* rp = realpath((char *)dlinfo.dli_fname, buf);
|
||||
char* rp = os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen);
|
||||
assert(rp != NULL, "error in realpath(): maybe the 'path' argument is too long?");
|
||||
|
||||
strncpy(saved_jvm_path, buf, sizeof(saved_jvm_path));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -1754,7 +1754,7 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
assert(ret, "cannot locate libjvm");
|
||||
char *rp = NULL;
|
||||
if (ret && dli_fname[0] != '\0') {
|
||||
rp = realpath(dli_fname, buf);
|
||||
rp = os::Posix::realpath(dli_fname, buf, buflen);
|
||||
}
|
||||
if (rp == NULL) {
|
||||
return;
|
||||
@ -1786,7 +1786,7 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
p = strrchr(buf, '/');
|
||||
assert(strstr(p, "/libjvm") == p, "invalid library name");
|
||||
|
||||
rp = realpath(java_home_var, buf);
|
||||
rp = os::Posix::realpath(java_home_var, buf, buflen);
|
||||
if (rp == NULL) {
|
||||
return;
|
||||
}
|
||||
@ -1820,7 +1820,7 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
snprintf(buf + len, buflen-len, "/libjvm%s", JNI_LIB_SUFFIX);
|
||||
} else {
|
||||
// Fall back to path of current library
|
||||
rp = realpath(dli_fname, buf);
|
||||
rp = os::Posix::realpath(dli_fname, buf, buflen);
|
||||
if (rp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -2318,7 +2318,7 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
assert(ret, "cannot locate libjvm");
|
||||
char *rp = NULL;
|
||||
if (ret && dli_fname[0] != '\0') {
|
||||
rp = realpath(dli_fname, buf);
|
||||
rp = os::Posix::realpath(dli_fname, buf, buflen);
|
||||
}
|
||||
if (rp == NULL) {
|
||||
return;
|
||||
@ -2352,7 +2352,7 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
}
|
||||
assert(strstr(p, "/libjvm") == p, "invalid library name");
|
||||
|
||||
rp = realpath(java_home_var, buf);
|
||||
rp = os::Posix::realpath(java_home_var, buf, buflen);
|
||||
if (rp == NULL) {
|
||||
return;
|
||||
}
|
||||
@ -2373,7 +2373,7 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
|
||||
} else {
|
||||
// Go back to path of .so
|
||||
rp = realpath(dli_fname, buf);
|
||||
rp = os::Posix::realpath(dli_fname, buf, buflen);
|
||||
if (rp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -1105,6 +1105,48 @@ char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_a
|
||||
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.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -96,6 +96,13 @@ public:
|
||||
// to buf with len buflen; buf is returned.
|
||||
static char* describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr);
|
||||
|
||||
// A safe implementation of realpath which will not cause a buffer overflow if the resolved path
|
||||
// is longer than PATH_MAX.
|
||||
// On success, returns 'outbuf', which now contains the path.
|
||||
// On error, it will return NULL and set errno. The content of 'outbuf' is undefined.
|
||||
// On truncation error ('outbuf' too small), it will return NULL and set errno to ENAMETOOLONG.
|
||||
static char* realpath(const char* filename, char* outbuf, size_t outbuflen);
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2034,7 +2034,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
|
||||
assert(ret != 0, "cannot locate libjvm");
|
||||
if (ret != 0 && dlinfo.dli_fname != NULL) {
|
||||
realpath((char *)dlinfo.dli_fname, buf);
|
||||
if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
buf[0] = '\0';
|
||||
return;
|
||||
@ -2065,7 +2067,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
p = strrchr(buf, '/');
|
||||
assert(strstr(p, "/libjvm") == p, "invalid library name");
|
||||
|
||||
realpath(java_home_var, buf);
|
||||
if (os::Posix::realpath(java_home_var, buf, buflen) == NULL) {
|
||||
return;
|
||||
}
|
||||
// determine if this is a legacy image or modules image
|
||||
// modules image doesn't have "jre" subdirectory
|
||||
len = strlen(buf);
|
||||
@ -2082,7 +2086,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
|
||||
} else {
|
||||
// Go back to path of .so
|
||||
realpath((char *)dlinfo.dli_fname, buf);
|
||||
if (os::Posix::realpath((char *)dlinfo.dli_fname, buf, buflen) == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user