Path: blob/master/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c
40941 views
/*1* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "jni_util.h"2627#include <sys/socket.h>28#include <sys/stat.h>29#include <sys/types.h>30#include <sys/un.h>31#include <errno.h>32#include <signal.h>33#include <stdio.h>34#include <stdlib.h>35#include <string.h>36#include <unistd.h>3738#include "sun_tools_attach_VirtualMachineImpl.h"3940#define RESTARTABLE(_cmd, _result) do { \41do { \42_result = _cmd; \43} while((_result == -1) && (errno == EINTR)); \44} while(0)4546#define ROOT_UID 04748/*49* Declare library specific JNI_Onload entry if static build50*/51DEF_STATIC_JNI_OnLoad5253/*54* Class: sun_tools_attach_VirtualMachineImpl55* Method: socket56* Signature: ()I57*/58JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket59(JNIEnv *env, jclass cls)60{61int fd = socket(PF_UNIX, SOCK_STREAM, 0);62if (fd == -1) {63JNU_ThrowIOExceptionWithLastError(env, "socket");64}65return (jint)fd;66}6768/*69* Class: sun_tools_attach_VirtualMachineImpl70* Method: connect71* Signature: (ILjava/lang/String;)I72*/73JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connect74(JNIEnv *env, jclass cls, jint fd, jstring path)75{76jboolean isCopy;77const char* p = GetStringPlatformChars(env, path, &isCopy);78if (p != NULL) {79struct sockaddr_un addr;80int err = 0;8182memset(&addr, 0, sizeof(addr));83addr.sun_family = AF_UNIX;84/* strncpy is safe because addr.sun_path was zero-initialized before. */85strncpy(addr.sun_path, p, sizeof(addr.sun_path) - 1);8687if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {88err = errno;89}9091if (isCopy) {92JNU_ReleaseStringPlatformChars(env, path, p);93}9495/*96* If the connect failed then we throw the appropriate exception97* here (can't throw it before releasing the string as can't call98* JNI with pending exception)99*/100if (err != 0) {101if (err == ENOENT) {102JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);103} else {104char* msg = strdup(strerror(err));105JNU_ThrowIOException(env, msg);106if (msg != NULL) {107free(msg);108}109}110}111}112}113114/*115* Class: sun_tools_attach_VirtualMachineImpl116* Method: sendQuitTo117* Signature: (I)V118*/119JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo120(JNIEnv *env, jclass cls, jint pid)121{122if (kill((pid_t)pid, SIGQUIT)) {123JNU_ThrowIOExceptionWithLastError(env, "kill");124}125}126127/*128* Class: sun_tools_attach_VirtualMachineImpl129* Method: checkPermissions130* Signature: (Ljava/lang/String;)V131*/132JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions133(JNIEnv *env, jclass cls, jstring path)134{135jboolean isCopy;136const char* p = GetStringPlatformChars(env, path, &isCopy);137if (p != NULL) {138struct stat64 sb;139uid_t uid, gid;140int res;141142memset(&sb, 0, sizeof(struct stat64));143144/*145* Check that the path is owned by the effective uid/gid of this146* process. Also check that group/other access is not allowed.147*/148uid = geteuid();149gid = getegid();150151res = stat64(p, &sb);152if (res != 0) {153/* save errno */154res = errno;155}156157if (res == 0) {158char msg[100];159jboolean isError = JNI_FALSE;160if (sb.st_uid != uid && uid != ROOT_UID) {161snprintf(msg, sizeof(msg),162"file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);163isError = JNI_TRUE;164} else if (sb.st_gid != gid && uid != ROOT_UID) {165snprintf(msg, sizeof(msg),166"file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);167isError = JNI_TRUE;168} else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {169snprintf(msg, sizeof(msg),170"file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);171isError = JNI_TRUE;172}173if (isError) {174char buf[256];175snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);176JNU_ThrowIOException(env, buf);177}178} else {179char* msg = strdup(strerror(res));180JNU_ThrowIOException(env, msg);181if (msg != NULL) {182free(msg);183}184}185186if (isCopy) {187JNU_ReleaseStringPlatformChars(env, path, p);188}189}190}191192/*193* Class: sun_tools_attach_VirtualMachineImpl194* Method: close195* Signature: (I)V196*/197JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close198(JNIEnv *env, jclass cls, jint fd)199{200int res;201shutdown(fd, SHUT_RDWR);202RESTARTABLE(close(fd), res);203}204205/*206* Class: sun_tools_attach_VirtualMachineImpl207* Method: read208* Signature: (I[BI)I209*/210JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read211(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)212{213unsigned char buf[128];214size_t len = sizeof(buf);215ssize_t n;216217size_t remaining = (size_t)(baLen - off);218if (len > remaining) {219len = remaining;220}221222RESTARTABLE(read(fd, buf, len), n);223if (n == -1) {224JNU_ThrowIOExceptionWithLastError(env, "read");225} else {226if (n == 0) {227n = -1; // EOF228} else {229(*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));230}231}232return n;233}234235/*236* Class: sun_tools_attach_VirtualMachineImpl237* Method: write238* Signature: (I[B)V239*/240JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_write241(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen)242{243size_t remaining = bufLen;244do {245unsigned char buf[128];246size_t len = sizeof(buf);247int n;248249if (len > remaining) {250len = remaining;251}252(*env)->GetByteArrayRegion(env, ba, off, len, (jbyte *)buf);253254RESTARTABLE(write(fd, buf, len), n);255if (n > 0) {256off += n;257remaining -= n;258} else {259JNU_ThrowIOExceptionWithLastError(env, "write");260return;261}262263} while (remaining > 0);264}265266267