# HG changeset patch # User dtitov # Date 1527800944 25200 # Node ID 7cea35f78b50f13235a9cd177c3067efc1b823af # Parent d0d933d616105f3cd482f97658af1826fd4f2c0c 8197387: jcmd started by "root" must be allowed to access all VM processes Reviewed-by: sspitsyn, stuefe diff -r d0d933d61610 -r 7cea35f78b50 src/hotspot/os/aix/attachListener_aix.cpp --- a/src/hotspot/os/aix/attachListener_aix.cpp Thu May 31 15:37:18 2018 -0400 +++ b/src/hotspot/os/aix/attachListener_aix.cpp Thu May 31 14:09:04 2018 -0700 @@ -386,11 +386,10 @@ ::close(s); continue; } - uid_t euid = geteuid(); - gid_t egid = getegid(); - if (cred_info.euid != euid || cred_info.egid != egid) { - log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", cred_info.euid, cred_info.egid, euid, egid); + if (!os::Posix::matches_effective_uid_and_gid_or_root(cred_info.euid, cred_info.egid)) { + log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", + cred_info.euid, cred_info.egid, geteuid(), getegid()); ::close(s); continue; } @@ -548,8 +547,8 @@ } if (ret == 0) { // simple check to avoid starting the attach mechanism when - // a bogus user creates the file - if (st.st_uid == geteuid()) { + // a bogus non-root user creates the file + if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { init(); log_trace(attach)("Attach triggered by %s", fn); return true; diff -r d0d933d61610 -r 7cea35f78b50 src/hotspot/os/bsd/attachListener_bsd.cpp --- a/src/hotspot/os/bsd/attachListener_bsd.cpp Thu May 31 15:37:18 2018 -0400 +++ b/src/hotspot/os/bsd/attachListener_bsd.cpp Thu May 31 14:09:04 2018 -0700 @@ -357,11 +357,10 @@ ::close(s); continue; } - uid_t euid = geteuid(); - gid_t egid = getegid(); - if (puid != euid || pgid != egid) { - log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", puid, pgid, euid, egid); + if (!os::Posix::matches_effective_uid_and_gid_or_root(puid, pgid)) { + log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", puid, pgid, + geteuid(), getegid()); ::close(s); continue; } @@ -513,8 +512,8 @@ } if (ret == 0) { // simple check to avoid starting the attach mechanism when - // a bogus user creates the file - if (st.st_uid == geteuid()) { + // a bogus non-root user creates the file + if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { init(); log_trace(attach)("Attach triggered by %s", fn); return true; diff -r d0d933d61610 -r 7cea35f78b50 src/hotspot/os/linux/attachListener_linux.cpp --- a/src/hotspot/os/linux/attachListener_linux.cpp Thu May 31 15:37:18 2018 -0400 +++ b/src/hotspot/os/linux/attachListener_linux.cpp Thu May 31 14:09:04 2018 -0700 @@ -357,11 +357,10 @@ ::close(s); continue; } - uid_t euid = geteuid(); - gid_t egid = getegid(); - if (cred_info.uid != euid || cred_info.gid != egid) { - log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", cred_info.uid, cred_info.gid, euid, egid); + if (!os::Posix::matches_effective_uid_and_gid_or_root(cred_info.uid, cred_info.gid)) { + log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", + cred_info.uid, cred_info.gid, geteuid(), getegid()); ::close(s); continue; } @@ -518,8 +517,8 @@ } if (ret == 0) { // simple check to avoid starting the attach mechanism when - // a bogus user creates the file - if (st.st_uid == geteuid()) { + // a bogus non-root user creates the file + if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { init(); log_trace(attach)("Attach triggered by %s", fn); return true; diff -r d0d933d61610 -r 7cea35f78b50 src/hotspot/os/posix/os_posix.cpp --- a/src/hotspot/os/posix/os_posix.cpp Thu May 31 15:37:18 2018 -0400 +++ b/src/hotspot/os/posix/os_posix.cpp Thu May 31 14:09:04 2018 -0700 @@ -51,6 +51,8 @@ #endif #define IS_VALID_PID(p) (p > 0 && p < MAX_PID) +#define ROOT_UID 0 + #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif @@ -1454,6 +1456,18 @@ return stack_size; } +bool os::Posix::is_root(uid_t uid){ + return ROOT_UID == uid; +} + +bool os::Posix::matches_effective_uid_or_root(uid_t uid) { + return is_root(uid) || geteuid() == uid; +} + +bool os::Posix::matches_effective_uid_and_gid_or_root(uid_t uid, gid_t gid) { + return is_root(uid) || (geteuid() == uid && getegid() == gid); +} + Thread* os::ThreadCrashProtection::_protected_thread = NULL; os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL; volatile intptr_t os::ThreadCrashProtection::_crash_mux = 0; diff -r d0d933d61610 -r 7cea35f78b50 src/hotspot/os/posix/os_posix.hpp --- a/src/hotspot/os/posix/os_posix.hpp Thu May 31 15:37:18 2018 -0400 +++ b/src/hotspot/os/posix/os_posix.hpp Thu May 31 14:09:04 2018 -0700 @@ -106,6 +106,16 @@ // 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); + + // Returns true if given uid is root. + static bool is_root(uid_t uid); + + // Returns true if given uid is effective or root uid. + static bool matches_effective_uid_or_root(uid_t uid); + + // Returns true if either given uid is effective uid and given gid is + // effective gid, or if given uid is root. + static bool matches_effective_uid_and_gid_or_root(uid_t uid, gid_t gid); }; // On POSIX platforms the signal handler is global so we just do the write. diff -r d0d933d61610 -r 7cea35f78b50 src/hotspot/os/solaris/attachListener_solaris.cpp --- a/src/hotspot/os/solaris/attachListener_solaris.cpp Thu May 31 15:37:18 2018 -0400 +++ b/src/hotspot/os/solaris/attachListener_solaris.cpp Thu May 31 14:09:04 2018 -0700 @@ -213,16 +213,12 @@ return -1; // unable to get them, deny } - // get our euid/eguid (probably could cache these) - uid_t euid = geteuid(); - gid_t egid = getegid(); - // get euid/egid from ucred_free uid_t ucred_euid = ucred_geteuid(cred_info); gid_t ucred_egid = ucred_getegid(cred_info); // check that the effective uid/gid matches - if (ucred_euid == euid && ucred_egid == egid) { + if (os::Posix::matches_effective_uid_and_gid_or_root(ucred_euid, ucred_egid)) { ret = 0; // allow } @@ -664,8 +660,8 @@ } if (ret == 0) { // simple check to avoid starting the attach mechanism when - // a bogus user creates the file - if (st.st_uid == geteuid()) { + // a bogus non-root user creates the file + if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { init(); log_trace(attach)("Attach triggered by %s", fn); return true; diff -r d0d933d61610 -r 7cea35f78b50 src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c --- a/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c Thu May 31 15:37:18 2018 -0400 +++ b/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c Thu May 31 14:09:04 2018 -0700 @@ -46,6 +46,8 @@ } while(0) +#define ROOT_UID 0 + /* * Class: sun_tools_attach_VirtualMachineImpl * Method: socket @@ -153,11 +155,11 @@ if (res == 0) { char msg[100]; jboolean isError = JNI_FALSE; - if (sb.st_uid != uid) { + if (sb.st_uid != uid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); isError = JNI_TRUE; - } else if (sb.st_gid != gid) { + } else if (sb.st_gid != gid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); isError = JNI_TRUE; diff -r d0d933d61610 -r 7cea35f78b50 src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c --- a/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c Thu May 31 15:37:18 2018 -0400 +++ b/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c Thu May 31 14:09:04 2018 -0700 @@ -44,6 +44,8 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +#define ROOT_UID 0 + /* * Declare library specific JNI_Onload entry if static build */ @@ -156,11 +158,11 @@ if (res == 0) { char msg[100]; jboolean isError = JNI_FALSE; - if (sb.st_uid != uid) { + if (sb.st_uid != uid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); isError = JNI_TRUE; - } else if (sb.st_gid != gid) { + } else if (sb.st_gid != gid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); isError = JNI_TRUE; diff -r d0d933d61610 -r 7cea35f78b50 src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c --- a/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c Thu May 31 15:37:18 2018 -0400 +++ b/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c Thu May 31 14:09:04 2018 -0700 @@ -46,6 +46,8 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +#define ROOT_UID 0 + /* * Declare library specific JNI_Onload entry if static build */ @@ -158,11 +160,11 @@ if (res == 0) { char msg[100]; jboolean isError = JNI_FALSE; - if (sb.st_uid != uid) { + if (sb.st_uid != uid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); isError = JNI_TRUE; - } else if (sb.st_gid != gid) { + } else if (sb.st_gid != gid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); isError = JNI_TRUE; diff -r d0d933d61610 -r 7cea35f78b50 src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c --- a/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c Thu May 31 15:37:18 2018 -0400 +++ b/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c Thu May 31 14:09:04 2018 -0700 @@ -38,6 +38,8 @@ #include "sun_tools_attach_VirtualMachineImpl.h" +#define ROOT_UID 0 + #define RESTARTABLE(_cmd, _result) do { \ do { \ _result = _cmd; \ @@ -122,11 +124,11 @@ if (res == 0) { char msg[100]; jboolean isError = JNI_FALSE; - if (sb.st_uid != uid) { + if (sb.st_uid != uid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); isError = JNI_TRUE; - } else if (sb.st_gid != gid) { + } else if (sb.st_gid != gid && uid != ROOT_UID) { snprintf(msg, sizeof(msg), "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); isError = JNI_TRUE;