8197387: jcmd started by "root" must be allowed to access all VM processes

Reviewed-by: sspitsyn, stuefe
This commit is contained in:
Daniil Titov 2018-05-31 14:09:04 -07:00
parent dd3d24341b
commit a2a5e85195
10 changed files with 58 additions and 33 deletions

View File

@ -386,11 +386,10 @@ AixAttachOperation* AixAttachListener::dequeue() {
::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 @@ bool AttachListener::is_init_trigger() {
}
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;

View File

@ -357,11 +357,10 @@ BsdAttachOperation* BsdAttachListener::dequeue() {
::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 @@ bool AttachListener::is_init_trigger() {
}
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;

View File

@ -357,11 +357,10 @@ LinuxAttachOperation* LinuxAttachListener::dequeue() {
::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 @@ bool AttachListener::is_init_trigger() {
}
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;

View File

@ -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 @@ size_t os::Posix::get_initial_stack_size(ThreadType thr_type, size_t req_stack_s
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;

View File

@ -106,6 +106,16 @@ public:
// 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.

View File

@ -213,16 +213,12 @@ static int check_credentials() {
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 @@ bool AttachListener::is_init_trigger() {
}
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;

View File

@ -46,6 +46,8 @@
} while(0)
#define ROOT_UID 0
/*
* Class: sun_tools_attach_VirtualMachineImpl
* Method: socket
@ -153,11 +155,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
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;

View File

@ -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 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
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;

View File

@ -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 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
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;

View File

@ -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 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
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;