8197387: jcmd started by "root" must be allowed to access all VM processes
authordtitov
Thu, 31 May 2018 14:09:04 -0700
changeset 50333 7cea35f78b50
parent 50332 d0d933d61610
child 50334 928a93482dd7
8197387: jcmd started by "root" must be allowed to access all VM processes Reviewed-by: sspitsyn, stuefe
src/hotspot/os/aix/attachListener_aix.cpp
src/hotspot/os/bsd/attachListener_bsd.cpp
src/hotspot/os/linux/attachListener_linux.cpp
src/hotspot/os/posix/os_posix.cpp
src/hotspot/os/posix/os_posix.hpp
src/hotspot/os/solaris/attachListener_solaris.cpp
src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c
src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c
src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c
src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c
--- 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;
--- 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;
--- 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;
--- 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;
--- 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.
--- 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;
--- 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;
--- 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;
--- 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;
--- 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;