Path: blob/master/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c
40957 views
/*1* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2015, 2018 SAP SE. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation. Oracle designates this8* particular file as subject to the "Classpath" exception as provided9* by Oracle in the LICENSE file that accompanied this code.10*11* This code is distributed in the hope that it will be useful, but WITHOUT12* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or13* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License14* version 2 for more details (a copy is included in the LICENSE file that15* accompanied this code).16*17* You should have received a copy of the GNU General Public License version18* 2 along with this work; if not, write to the Free Software Foundation,19* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.20*21* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA22* or visit www.oracle.com if you need additional information or have any23* questions.24*/2526#include "jni_util.h"2728#include <sys/socket.h>29#include <sys/stat.h>30#include <sys/types.h>31#include <sys/un.h>32#include <errno.h>33#include <signal.h>34#include <stdio.h>35#include <stdlib.h>36#include <string.h>37#include <unistd.h>3839#include "sun_tools_attach_VirtualMachineImpl.h"4041#define RESTARTABLE(_cmd, _result) do { \42do { \43_result = _cmd; \44} while((_result == -1) && (errno == EINTR)); \45} while(0)464748#define ROOT_UID 04950/*51* Class: sun_tools_attach_VirtualMachineImpl52* Method: socket53* Signature: ()I54*/55JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket56(JNIEnv *env, jclass cls)57{58int fd = socket(PF_UNIX, SOCK_STREAM, 0);59if (fd == -1) {60JNU_ThrowIOExceptionWithLastError(env, "socket");61}62return (jint)fd;63}6465/*66* Class: sun_tools_attach_VirtualMachineImpl67* Method: connect68* Signature: (ILjava/lang/String;)I69*/70JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connect71(JNIEnv *env, jclass cls, jint fd, jstring path)72{73jboolean isCopy;74const char* p = GetStringPlatformChars(env, path, &isCopy);75if (p != NULL) {76struct sockaddr_un addr;77int err = 0;7879memset(&addr, 0, sizeof(addr));80addr.sun_family = AF_UNIX;81/* strncpy is safe because addr.sun_path was zero-initialized before. */82strncpy(addr.sun_path, p, sizeof(addr.sun_path) - 1);83/* We must call bind with the actual socketaddr length. This is obligatory for AS400. */84if (connect(fd, (struct sockaddr*)&addr, SUN_LEN(&addr)) == -1) {85err = errno;86}8788if (isCopy) {89JNU_ReleaseStringPlatformChars(env, path, p);90}9192/*93* If the connect failed then we throw the appropriate exception94* here (can't throw it before releasing the string as can't call95* JNI with pending exception)96*/97if (err != 0) {98if (err == ENOENT) {99JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);100} else {101char* msg = strdup(strerror(err));102JNU_ThrowIOException(env, msg);103if (msg != NULL) {104free(msg);105}106}107}108}109}110111/*112* Class: sun_tools_attach_VirtualMachineImpl113* Method: sendQuitTo114* Signature: (I)V115*/116JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo117(JNIEnv *env, jclass cls, jint pid)118{119if (kill((pid_t)pid, SIGQUIT)) {120JNU_ThrowIOExceptionWithLastError(env, "kill");121}122}123124/*125* Class: sun_tools_attach_VirtualMachineImpl126* Method: checkPermissions127* Signature: (Ljava/lang/String;)V128*/129JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions130(JNIEnv *env, jclass cls, jstring path)131{132jboolean isCopy;133const char* p = GetStringPlatformChars(env, path, &isCopy);134if (p != NULL) {135struct stat64 sb;136uid_t uid, gid;137int res;138139memset(&sb, 0, sizeof(struct stat64));140141/*142* Check that the path is owned by the effective uid/gid of this143* process. Also check that group/other access is not allowed.144*/145uid = geteuid();146gid = getegid();147148res = stat64(p, &sb);149if (res != 0) {150/* save errno */151res = errno;152}153154if (res == 0) {155char msg[100];156jboolean isError = JNI_FALSE;157if (sb.st_uid != uid && uid != ROOT_UID) {158snprintf(msg, sizeof(msg),159"file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);160isError = JNI_TRUE;161} else if (sb.st_gid != gid && uid != ROOT_UID) {162snprintf(msg, sizeof(msg),163"file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);164isError = JNI_TRUE;165} else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {166snprintf(msg, sizeof(msg),167"file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);168isError = JNI_TRUE;169}170if (isError) {171char buf[256];172snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);173JNU_ThrowIOException(env, buf);174}175} else {176char* msg = strdup(strerror(res));177JNU_ThrowIOException(env, msg);178if (msg != NULL) {179free(msg);180}181}182183if (isCopy) {184JNU_ReleaseStringPlatformChars(env, path, p);185}186}187}188189/*190* Class: sun_tools_attach_VirtualMachineImpl191* Method: close192* Signature: (I)V193*/194JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close195(JNIEnv *env, jclass cls, jint fd)196{197int res;198shutdown(fd, SHUT_RDWR);199RESTARTABLE(close(fd), res);200}201202/*203* Class: sun_tools_attach_VirtualMachineImpl204* Method: read205* Signature: (I[BI)I206*/207JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read208(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)209{210unsigned char buf[128];211size_t len = sizeof(buf);212ssize_t n;213214size_t remaining = (size_t)(baLen - off);215if (len > remaining) {216len = remaining;217}218219RESTARTABLE(read(fd, buf, len), n);220if (n == -1) {221JNU_ThrowIOExceptionWithLastError(env, "read");222} else {223if (n == 0) {224n = -1; // EOF225} else {226(*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));227}228}229return n;230}231232/*233* Class: sun_tools_attach_VirtualMachineImpl234* Method: write235* Signature: (I[B)V236*/237JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_write238(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen)239{240size_t remaining = bufLen;241do {242unsigned char buf[128];243size_t len = sizeof(buf);244int n;245246if (len > remaining) {247len = remaining;248}249(*env)->GetByteArrayRegion(env, ba, off, len, (jbyte *)buf);250251RESTARTABLE(write(fd, buf, len), n);252if (n > 0) {253off += n;254remaining -= n;255} else {256JNU_ThrowIOExceptionWithLastError(env, "write");257return;258}259260} while (remaining > 0);261}262263264