| 1 | /* | 
|---|
| 2 | * Copyright (c) 2005, 2018, Oracle and/or its affiliates. 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 it | 
|---|
| 6 | * under the terms of the GNU General Public License version 2 only, as | 
|---|
| 7 | * published by the Free Software Foundation. | 
|---|
| 8 | * | 
|---|
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT | 
|---|
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|---|
| 11 | * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|---|
| 12 | * version 2 for more details (a copy is included in the LICENSE file that | 
|---|
| 13 | * accompanied this code). | 
|---|
| 14 | * | 
|---|
| 15 | * You should have received a copy of the GNU General Public License version | 
|---|
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, | 
|---|
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|---|
| 18 | * | 
|---|
| 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|---|
| 20 | * or visit www.oracle.com if you need additional information or have any | 
|---|
| 21 | * questions. | 
|---|
| 22 | * | 
|---|
| 23 | */ | 
|---|
| 24 |  | 
|---|
| 25 | #include "precompiled.hpp" | 
|---|
| 26 | #include "logging/log.hpp" | 
|---|
| 27 | #include "memory/allocation.inline.hpp" | 
|---|
| 28 | #include "runtime/interfaceSupport.inline.hpp" | 
|---|
| 29 | #include "runtime/os.inline.hpp" | 
|---|
| 30 | #include "services/attachListener.hpp" | 
|---|
| 31 | #include "services/dtraceAttacher.hpp" | 
|---|
| 32 |  | 
|---|
| 33 | #include <unistd.h> | 
|---|
| 34 | #include <signal.h> | 
|---|
| 35 | #include <sys/types.h> | 
|---|
| 36 | #include <sys/socket.h> | 
|---|
| 37 | #include <sys/un.h> | 
|---|
| 38 | #include <sys/stat.h> | 
|---|
| 39 |  | 
|---|
| 40 | #ifndef UNIX_PATH_MAX | 
|---|
| 41 | #define UNIX_PATH_MAX   sizeof(((struct sockaddr_un *)0)->sun_path) | 
|---|
| 42 | #endif | 
|---|
| 43 |  | 
|---|
| 44 | // The attach mechanism on Linux uses a UNIX domain socket. An attach listener | 
|---|
| 45 | // thread is created at startup or is created on-demand via a signal from | 
|---|
| 46 | // the client tool. The attach listener creates a socket and binds it to a file | 
|---|
| 47 | // in the filesystem. The attach listener then acts as a simple (single- | 
|---|
| 48 | // threaded) server - it waits for a client to connect, reads the request, | 
|---|
| 49 | // executes it, and returns the response to the client via the socket | 
|---|
| 50 | // connection. | 
|---|
| 51 | // | 
|---|
| 52 | // As the socket is a UNIX domain socket it means that only clients on the | 
|---|
| 53 | // local machine can connect. In addition there are two other aspects to | 
|---|
| 54 | // the security: | 
|---|
| 55 | // 1. The well known file that the socket is bound to has permission 400 | 
|---|
| 56 | // 2. When a client connect, the SO_PEERCRED socket option is used to | 
|---|
| 57 | //    obtain the credentials of client. We check that the effective uid | 
|---|
| 58 | //    of the client matches this process. | 
|---|
| 59 |  | 
|---|
| 60 | // forward reference | 
|---|
| 61 | class LinuxAttachOperation; | 
|---|
| 62 |  | 
|---|
| 63 | class LinuxAttachListener: AllStatic { | 
|---|
| 64 | private: | 
|---|
| 65 | // the path to which we bind the UNIX domain socket | 
|---|
| 66 | static char _path[UNIX_PATH_MAX]; | 
|---|
| 67 | static bool _has_path; | 
|---|
| 68 |  | 
|---|
| 69 | // the file descriptor for the listening socket | 
|---|
| 70 | static int _listener; | 
|---|
| 71 |  | 
|---|
| 72 | static void set_path(char* path) { | 
|---|
| 73 | if (path == NULL) { | 
|---|
| 74 | _has_path = false; | 
|---|
| 75 | } else { | 
|---|
| 76 | strncpy(_path, path, UNIX_PATH_MAX); | 
|---|
| 77 | _path[UNIX_PATH_MAX-1] = '\0'; | 
|---|
| 78 | _has_path = true; | 
|---|
| 79 | } | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | static void set_listener(int s)               { _listener = s; } | 
|---|
| 83 |  | 
|---|
| 84 | // reads a request from the given connected socket | 
|---|
| 85 | static LinuxAttachOperation* read_request(int s); | 
|---|
| 86 |  | 
|---|
| 87 | public: | 
|---|
| 88 | enum { | 
|---|
| 89 | ATTACH_PROTOCOL_VER = 1                     // protocol version | 
|---|
| 90 | }; | 
|---|
| 91 | enum { | 
|---|
| 92 | ATTACH_ERROR_BADVERSION     = 101           // error codes | 
|---|
| 93 | }; | 
|---|
| 94 |  | 
|---|
| 95 | // initialize the listener, returns 0 if okay | 
|---|
| 96 | static int init(); | 
|---|
| 97 |  | 
|---|
| 98 | static char* path()                   { return _path; } | 
|---|
| 99 | static bool has_path()                { return _has_path; } | 
|---|
| 100 | static int listener()                 { return _listener; } | 
|---|
| 101 |  | 
|---|
| 102 | // write the given buffer to a socket | 
|---|
| 103 | static int write_fully(int s, char* buf, int len); | 
|---|
| 104 |  | 
|---|
| 105 | static LinuxAttachOperation* dequeue(); | 
|---|
| 106 | }; | 
|---|
| 107 |  | 
|---|
| 108 | class LinuxAttachOperation: public AttachOperation { | 
|---|
| 109 | private: | 
|---|
| 110 | // the connection to the client | 
|---|
| 111 | int _socket; | 
|---|
| 112 |  | 
|---|
| 113 | public: | 
|---|
| 114 | void complete(jint res, bufferedStream* st); | 
|---|
| 115 |  | 
|---|
| 116 | void set_socket(int s)                                { _socket = s; } | 
|---|
| 117 | int socket() const                                    { return _socket; } | 
|---|
| 118 |  | 
|---|
| 119 | LinuxAttachOperation(char* name) : AttachOperation(name) { | 
|---|
| 120 | set_socket(-1); | 
|---|
| 121 | } | 
|---|
| 122 | }; | 
|---|
| 123 |  | 
|---|
| 124 | // statics | 
|---|
| 125 | char LinuxAttachListener::_path[UNIX_PATH_MAX]; | 
|---|
| 126 | bool LinuxAttachListener::_has_path; | 
|---|
| 127 | int LinuxAttachListener::_listener = -1; | 
|---|
| 128 |  | 
|---|
| 129 | // Supporting class to help split a buffer into individual components | 
|---|
| 130 | class ArgumentIterator : public StackObj { | 
|---|
| 131 | private: | 
|---|
| 132 | char* _pos; | 
|---|
| 133 | char* _end; | 
|---|
| 134 | public: | 
|---|
| 135 | ArgumentIterator(char* arg_buffer, size_t arg_size) { | 
|---|
| 136 | _pos = arg_buffer; | 
|---|
| 137 | _end = _pos + arg_size - 1; | 
|---|
| 138 | } | 
|---|
| 139 | char* next() { | 
|---|
| 140 | if (*_pos == '\0') { | 
|---|
| 141 | // advance the iterator if possible (null arguments) | 
|---|
| 142 | if (_pos < _end) { | 
|---|
| 143 | _pos += 1; | 
|---|
| 144 | } | 
|---|
| 145 | return NULL; | 
|---|
| 146 | } | 
|---|
| 147 | char* res = _pos; | 
|---|
| 148 | char* next_pos = strchr(_pos, '\0'); | 
|---|
| 149 | if (next_pos < _end)  { | 
|---|
| 150 | next_pos++; | 
|---|
| 151 | } | 
|---|
| 152 | _pos = next_pos; | 
|---|
| 153 | return res; | 
|---|
| 154 | } | 
|---|
| 155 | }; | 
|---|
| 156 |  | 
|---|
| 157 |  | 
|---|
| 158 | // atexit hook to stop listener and unlink the file that it is | 
|---|
| 159 | // bound too. | 
|---|
| 160 | extern "C"{ | 
|---|
| 161 | static void listener_cleanup() { | 
|---|
| 162 | static int cleanup_done; | 
|---|
| 163 | if (!cleanup_done) { | 
|---|
| 164 | cleanup_done = 1; | 
|---|
| 165 | int s = LinuxAttachListener::listener(); | 
|---|
| 166 | if (s != -1) { | 
|---|
| 167 | ::close(s); | 
|---|
| 168 | } | 
|---|
| 169 | if (LinuxAttachListener::has_path()) { | 
|---|
| 170 | ::unlink(LinuxAttachListener::path()); | 
|---|
| 171 | } | 
|---|
| 172 | } | 
|---|
| 173 | } | 
|---|
| 174 | } | 
|---|
| 175 |  | 
|---|
| 176 | // Initialization - create a listener socket and bind it to a file | 
|---|
| 177 |  | 
|---|
| 178 | int LinuxAttachListener::init() { | 
|---|
| 179 | char path[UNIX_PATH_MAX];          // socket file | 
|---|
| 180 | char initial_path[UNIX_PATH_MAX];  // socket file during setup | 
|---|
| 181 | int listener;                      // listener socket (file descriptor) | 
|---|
| 182 |  | 
|---|
| 183 | // register function to cleanup | 
|---|
| 184 | ::atexit(listener_cleanup); | 
|---|
| 185 |  | 
|---|
| 186 | int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d", | 
|---|
| 187 | os::get_temp_directory(), os::current_process_id()); | 
|---|
| 188 | if (n < (int)UNIX_PATH_MAX) { | 
|---|
| 189 | n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path); | 
|---|
| 190 | } | 
|---|
| 191 | if (n >= (int)UNIX_PATH_MAX) { | 
|---|
| 192 | return -1; | 
|---|
| 193 | } | 
|---|
| 194 |  | 
|---|
| 195 | // create the listener socket | 
|---|
| 196 | listener = ::socket(PF_UNIX, SOCK_STREAM, 0); | 
|---|
| 197 | if (listener == -1) { | 
|---|
| 198 | return -1; | 
|---|
| 199 | } | 
|---|
| 200 |  | 
|---|
| 201 | // bind socket | 
|---|
| 202 | struct sockaddr_un addr; | 
|---|
| 203 | memset((void *)&addr, 0, sizeof(addr)); | 
|---|
| 204 | addr.sun_family = AF_UNIX; | 
|---|
| 205 | strcpy(addr.sun_path, initial_path); | 
|---|
| 206 | ::unlink(initial_path); | 
|---|
| 207 | int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr)); | 
|---|
| 208 | if (res == -1) { | 
|---|
| 209 | ::close(listener); | 
|---|
| 210 | return -1; | 
|---|
| 211 | } | 
|---|
| 212 |  | 
|---|
| 213 | // put in listen mode, set permissions, and rename into place | 
|---|
| 214 | res = ::listen(listener, 5); | 
|---|
| 215 | if (res == 0) { | 
|---|
| 216 | RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res); | 
|---|
| 217 | if (res == 0) { | 
|---|
| 218 | // make sure the file is owned by the effective user and effective group | 
|---|
| 219 | // e.g. the group could be inherited from the directory in case the s bit is set | 
|---|
| 220 | RESTARTABLE(::chown(initial_path, geteuid(), getegid()), res); | 
|---|
| 221 | if (res == 0) { | 
|---|
| 222 | res = ::rename(initial_path, path); | 
|---|
| 223 | } | 
|---|
| 224 | } | 
|---|
| 225 | } | 
|---|
| 226 | if (res == -1) { | 
|---|
| 227 | ::close(listener); | 
|---|
| 228 | ::unlink(initial_path); | 
|---|
| 229 | return -1; | 
|---|
| 230 | } | 
|---|
| 231 | set_path(path); | 
|---|
| 232 | set_listener(listener); | 
|---|
| 233 |  | 
|---|
| 234 | return 0; | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | // Given a socket that is connected to a peer we read the request and | 
|---|
| 238 | // create an AttachOperation. As the socket is blocking there is potential | 
|---|
| 239 | // for a denial-of-service if the peer does not response. However this happens | 
|---|
| 240 | // after the peer credentials have been checked and in the worst case it just | 
|---|
| 241 | // means that the attach listener thread is blocked. | 
|---|
| 242 | // | 
|---|
| 243 | LinuxAttachOperation* LinuxAttachListener::read_request(int s) { | 
|---|
| 244 | char ver_str[8]; | 
|---|
| 245 | sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); | 
|---|
| 246 |  | 
|---|
| 247 | // The request is a sequence of strings so we first figure out the | 
|---|
| 248 | // expected count and the maximum possible length of the request. | 
|---|
| 249 | // The request is: | 
|---|
| 250 | //   <ver>0<cmd>0<arg>0<arg>0<arg>0 | 
|---|
| 251 | // where <ver> is the protocol version (1), <cmd> is the command | 
|---|
| 252 | // name ("load", "datadump", ...), and <arg> is an argument | 
|---|
| 253 | int expected_str_count = 2 + AttachOperation::arg_count_max; | 
|---|
| 254 | const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) + | 
|---|
| 255 | AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1); | 
|---|
| 256 |  | 
|---|
| 257 | char buf[max_len]; | 
|---|
| 258 | int str_count = 0; | 
|---|
| 259 |  | 
|---|
| 260 | // Read until all (expected) strings have been read, the buffer is | 
|---|
| 261 | // full, or EOF. | 
|---|
| 262 |  | 
|---|
| 263 | int off = 0; | 
|---|
| 264 | int left = max_len; | 
|---|
| 265 |  | 
|---|
| 266 | do { | 
|---|
| 267 | int n; | 
|---|
| 268 | RESTARTABLE(read(s, buf+off, left), n); | 
|---|
| 269 | assert(n <= left, "buffer was too small, impossible!"); | 
|---|
| 270 | buf[max_len - 1] = '\0'; | 
|---|
| 271 | if (n == -1) { | 
|---|
| 272 | return NULL;      // reset by peer or other error | 
|---|
| 273 | } | 
|---|
| 274 | if (n == 0) { | 
|---|
| 275 | break; | 
|---|
| 276 | } | 
|---|
| 277 | for (int i=0; i<n; i++) { | 
|---|
| 278 | if (buf[off+i] == 0) { | 
|---|
| 279 | // EOS found | 
|---|
| 280 | str_count++; | 
|---|
| 281 |  | 
|---|
| 282 | // The first string is <ver> so check it now to | 
|---|
| 283 | // check for protocol mis-match | 
|---|
| 284 | if (str_count == 1) { | 
|---|
| 285 | if ((strlen(buf) != strlen(ver_str)) || | 
|---|
| 286 | (atoi(buf) != ATTACH_PROTOCOL_VER)) { | 
|---|
| 287 | char msg[32]; | 
|---|
| 288 | sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION); | 
|---|
| 289 | write_fully(s, msg, strlen(msg)); | 
|---|
| 290 | return NULL; | 
|---|
| 291 | } | 
|---|
| 292 | } | 
|---|
| 293 | } | 
|---|
| 294 | } | 
|---|
| 295 | off += n; | 
|---|
| 296 | left -= n; | 
|---|
| 297 | } while (left > 0 && str_count < expected_str_count); | 
|---|
| 298 |  | 
|---|
| 299 | if (str_count != expected_str_count) { | 
|---|
| 300 | return NULL;        // incomplete request | 
|---|
| 301 | } | 
|---|
| 302 |  | 
|---|
| 303 | // parse request | 
|---|
| 304 |  | 
|---|
| 305 | ArgumentIterator args(buf, (max_len)-left); | 
|---|
| 306 |  | 
|---|
| 307 | // version already checked | 
|---|
| 308 | char* v = args.next(); | 
|---|
| 309 |  | 
|---|
| 310 | char* name = args.next(); | 
|---|
| 311 | if (name == NULL || strlen(name) > AttachOperation::name_length_max) { | 
|---|
| 312 | return NULL; | 
|---|
| 313 | } | 
|---|
| 314 |  | 
|---|
| 315 | LinuxAttachOperation* op = new LinuxAttachOperation(name); | 
|---|
| 316 |  | 
|---|
| 317 | for (int i=0; i<AttachOperation::arg_count_max; i++) { | 
|---|
| 318 | char* arg = args.next(); | 
|---|
| 319 | if (arg == NULL) { | 
|---|
| 320 | op->set_arg(i, NULL); | 
|---|
| 321 | } else { | 
|---|
| 322 | if (strlen(arg) > AttachOperation::arg_length_max) { | 
|---|
| 323 | delete op; | 
|---|
| 324 | return NULL; | 
|---|
| 325 | } | 
|---|
| 326 | op->set_arg(i, arg); | 
|---|
| 327 | } | 
|---|
| 328 | } | 
|---|
| 329 |  | 
|---|
| 330 | op->set_socket(s); | 
|---|
| 331 | return op; | 
|---|
| 332 | } | 
|---|
| 333 |  | 
|---|
| 334 |  | 
|---|
| 335 | // Dequeue an operation | 
|---|
| 336 | // | 
|---|
| 337 | // In the Linux implementation there is only a single operation and clients | 
|---|
| 338 | // cannot queue commands (except at the socket level). | 
|---|
| 339 | // | 
|---|
| 340 | LinuxAttachOperation* LinuxAttachListener::dequeue() { | 
|---|
| 341 | for (;;) { | 
|---|
| 342 | int s; | 
|---|
| 343 |  | 
|---|
| 344 | // wait for client to connect | 
|---|
| 345 | struct sockaddr addr; | 
|---|
| 346 | socklen_t len = sizeof(addr); | 
|---|
| 347 | RESTARTABLE(::accept(listener(), &addr, &len), s); | 
|---|
| 348 | if (s == -1) { | 
|---|
| 349 | return NULL;      // log a warning? | 
|---|
| 350 | } | 
|---|
| 351 |  | 
|---|
| 352 | // get the credentials of the peer and check the effective uid/guid | 
|---|
| 353 | struct ucred cred_info; | 
|---|
| 354 | socklen_t optlen = sizeof(cred_info); | 
|---|
| 355 | if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) { | 
|---|
| 356 | log_debug(attach)( "Failed to get socket option SO_PEERCRED"); | 
|---|
| 357 | ::close(s); | 
|---|
| 358 | continue; | 
|---|
| 359 | } | 
|---|
| 360 |  | 
|---|
| 361 | if (!os::Posix::matches_effective_uid_and_gid_or_root(cred_info.uid, cred_info.gid)) { | 
|---|
| 362 | log_debug(attach)( "euid/egid check failed (%d/%d vs %d/%d)", | 
|---|
| 363 | cred_info.uid, cred_info.gid, geteuid(), getegid()); | 
|---|
| 364 | ::close(s); | 
|---|
| 365 | continue; | 
|---|
| 366 | } | 
|---|
| 367 |  | 
|---|
| 368 | // peer credential look okay so we read the request | 
|---|
| 369 | LinuxAttachOperation* op = read_request(s); | 
|---|
| 370 | if (op == NULL) { | 
|---|
| 371 | ::close(s); | 
|---|
| 372 | continue; | 
|---|
| 373 | } else { | 
|---|
| 374 | return op; | 
|---|
| 375 | } | 
|---|
| 376 | } | 
|---|
| 377 | } | 
|---|
| 378 |  | 
|---|
| 379 | // write the given buffer to the socket | 
|---|
| 380 | int LinuxAttachListener::write_fully(int s, char* buf, int len) { | 
|---|
| 381 | do { | 
|---|
| 382 | int n = ::write(s, buf, len); | 
|---|
| 383 | if (n == -1) { | 
|---|
| 384 | if (errno != EINTR) return -1; | 
|---|
| 385 | } else { | 
|---|
| 386 | buf += n; | 
|---|
| 387 | len -= n; | 
|---|
| 388 | } | 
|---|
| 389 | } | 
|---|
| 390 | while (len > 0); | 
|---|
| 391 | return 0; | 
|---|
| 392 | } | 
|---|
| 393 |  | 
|---|
| 394 | // Complete an operation by sending the operation result and any result | 
|---|
| 395 | // output to the client. At this time the socket is in blocking mode so | 
|---|
| 396 | // potentially we can block if there is a lot of data and the client is | 
|---|
| 397 | // non-responsive. For most operations this is a non-issue because the | 
|---|
| 398 | // default send buffer is sufficient to buffer everything. In the future | 
|---|
| 399 | // if there are operations that involves a very big reply then it the | 
|---|
| 400 | // socket could be made non-blocking and a timeout could be used. | 
|---|
| 401 |  | 
|---|
| 402 | void LinuxAttachOperation::complete(jint result, bufferedStream* st) { | 
|---|
| 403 | JavaThread* thread = JavaThread::current(); | 
|---|
| 404 | ThreadBlockInVM tbivm(thread); | 
|---|
| 405 |  | 
|---|
| 406 | thread->set_suspend_equivalent(); | 
|---|
| 407 | // cleared by handle_special_suspend_equivalent_condition() or | 
|---|
| 408 | // java_suspend_self() via check_and_wait_while_suspended() | 
|---|
| 409 |  | 
|---|
| 410 | // write operation result | 
|---|
| 411 | char msg[32]; | 
|---|
| 412 | sprintf(msg, "%d\n", result); | 
|---|
| 413 | int rc = LinuxAttachListener::write_fully(this->socket(), msg, strlen(msg)); | 
|---|
| 414 |  | 
|---|
| 415 | // write any result data | 
|---|
| 416 | if (rc == 0) { | 
|---|
| 417 | LinuxAttachListener::write_fully(this->socket(), (char*) st->base(), st->size()); | 
|---|
| 418 | ::shutdown(this->socket(), 2); | 
|---|
| 419 | } | 
|---|
| 420 |  | 
|---|
| 421 | // done | 
|---|
| 422 | ::close(this->socket()); | 
|---|
| 423 |  | 
|---|
| 424 | // were we externally suspended while we were waiting? | 
|---|
| 425 | thread->check_and_wait_while_suspended(); | 
|---|
| 426 |  | 
|---|
| 427 | delete this; | 
|---|
| 428 | } | 
|---|
| 429 |  | 
|---|
| 430 |  | 
|---|
| 431 | // AttachListener functions | 
|---|
| 432 |  | 
|---|
| 433 | AttachOperation* AttachListener::dequeue() { | 
|---|
| 434 | JavaThread* thread = JavaThread::current(); | 
|---|
| 435 | ThreadBlockInVM tbivm(thread); | 
|---|
| 436 |  | 
|---|
| 437 | thread->set_suspend_equivalent(); | 
|---|
| 438 | // cleared by handle_special_suspend_equivalent_condition() or | 
|---|
| 439 | // java_suspend_self() via check_and_wait_while_suspended() | 
|---|
| 440 |  | 
|---|
| 441 | AttachOperation* op = LinuxAttachListener::dequeue(); | 
|---|
| 442 |  | 
|---|
| 443 | // were we externally suspended while we were waiting? | 
|---|
| 444 | thread->check_and_wait_while_suspended(); | 
|---|
| 445 |  | 
|---|
| 446 | return op; | 
|---|
| 447 | } | 
|---|
| 448 |  | 
|---|
| 449 | // Performs initialization at vm startup | 
|---|
| 450 | // For Linux we remove any stale .java_pid file which could cause | 
|---|
| 451 | // an attaching process to think we are ready to receive on the | 
|---|
| 452 | // domain socket before we are properly initialized | 
|---|
| 453 |  | 
|---|
| 454 | void AttachListener::vm_start() { | 
|---|
| 455 | char fn[UNIX_PATH_MAX]; | 
|---|
| 456 | struct stat64 st; | 
|---|
| 457 | int ret; | 
|---|
| 458 |  | 
|---|
| 459 | int n = snprintf(fn, UNIX_PATH_MAX, "%s/.java_pid%d", | 
|---|
| 460 | os::get_temp_directory(), os::current_process_id()); | 
|---|
| 461 | assert(n < (int)UNIX_PATH_MAX, "java_pid file name buffer overflow"); | 
|---|
| 462 |  | 
|---|
| 463 | RESTARTABLE(::stat64(fn, &st), ret); | 
|---|
| 464 | if (ret == 0) { | 
|---|
| 465 | ret = ::unlink(fn); | 
|---|
| 466 | if (ret == -1) { | 
|---|
| 467 | log_debug(attach)( "Failed to remove stale attach pid file at %s", fn); | 
|---|
| 468 | } | 
|---|
| 469 | } | 
|---|
| 470 | } | 
|---|
| 471 |  | 
|---|
| 472 | int AttachListener::pd_init() { | 
|---|
| 473 | JavaThread* thread = JavaThread::current(); | 
|---|
| 474 | ThreadBlockInVM tbivm(thread); | 
|---|
| 475 |  | 
|---|
| 476 | thread->set_suspend_equivalent(); | 
|---|
| 477 | // cleared by handle_special_suspend_equivalent_condition() or | 
|---|
| 478 | // java_suspend_self() via check_and_wait_while_suspended() | 
|---|
| 479 |  | 
|---|
| 480 | int ret_code = LinuxAttachListener::init(); | 
|---|
| 481 |  | 
|---|
| 482 | // were we externally suspended while we were waiting? | 
|---|
| 483 | thread->check_and_wait_while_suspended(); | 
|---|
| 484 |  | 
|---|
| 485 | return ret_code; | 
|---|
| 486 | } | 
|---|
| 487 |  | 
|---|
| 488 | // Attach Listener is started lazily except in the case when | 
|---|
| 489 | // +ReduseSignalUsage is used | 
|---|
| 490 | bool AttachListener::init_at_startup() { | 
|---|
| 491 | if (ReduceSignalUsage) { | 
|---|
| 492 | return true; | 
|---|
| 493 | } else { | 
|---|
| 494 | return false; | 
|---|
| 495 | } | 
|---|
| 496 | } | 
|---|
| 497 |  | 
|---|
| 498 | // If the file .attach_pid<pid> exists in the working directory | 
|---|
| 499 | // or /tmp then this is the trigger to start the attach mechanism | 
|---|
| 500 | bool AttachListener::is_init_trigger() { | 
|---|
| 501 | if (init_at_startup() || is_initialized()) { | 
|---|
| 502 | return false;               // initialized at startup or already initialized | 
|---|
| 503 | } | 
|---|
| 504 | char fn[PATH_MAX + 1]; | 
|---|
| 505 | int ret; | 
|---|
| 506 | struct stat64 st; | 
|---|
| 507 | sprintf(fn, ".attach_pid%d", os::current_process_id()); | 
|---|
| 508 | RESTARTABLE(::stat64(fn, &st), ret); | 
|---|
| 509 | if (ret == -1) { | 
|---|
| 510 | log_trace(attach)( "Failed to find attach file: %s, trying alternate", fn); | 
|---|
| 511 | snprintf(fn, sizeof(fn), "%s/.attach_pid%d", | 
|---|
| 512 | os::get_temp_directory(), os::current_process_id()); | 
|---|
| 513 | RESTARTABLE(::stat64(fn, &st), ret); | 
|---|
| 514 | if (ret == -1) { | 
|---|
| 515 | log_debug(attach)( "Failed to find attach file: %s", fn); | 
|---|
| 516 | } | 
|---|
| 517 | } | 
|---|
| 518 | if (ret == 0) { | 
|---|
| 519 | // simple check to avoid starting the attach mechanism when | 
|---|
| 520 | // a bogus non-root user creates the file | 
|---|
| 521 | if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { | 
|---|
| 522 | init(); | 
|---|
| 523 | log_trace(attach)( "Attach triggered by %s", fn); | 
|---|
| 524 | return true; | 
|---|
| 525 | } else { | 
|---|
| 526 | log_debug(attach)( "File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid()); | 
|---|
| 527 | } | 
|---|
| 528 | } | 
|---|
| 529 | return false; | 
|---|
| 530 | } | 
|---|
| 531 |  | 
|---|
| 532 | // if VM aborts then remove listener | 
|---|
| 533 | void AttachListener::abort() { | 
|---|
| 534 | listener_cleanup(); | 
|---|
| 535 | } | 
|---|
| 536 |  | 
|---|
| 537 | void AttachListener::pd_data_dump() { | 
|---|
| 538 | os::signal_notify(SIGQUIT); | 
|---|
| 539 | } | 
|---|
| 540 |  | 
|---|
| 541 | AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) { | 
|---|
| 542 | return NULL; | 
|---|
| 543 | } | 
|---|
| 544 |  | 
|---|
| 545 | jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) { | 
|---|
| 546 | out->print_cr( "flag '%s' cannot be changed", op->arg(0)); | 
|---|
| 547 | return JNI_ERR; | 
|---|
| 548 | } | 
|---|
| 549 |  | 
|---|
| 550 | void AttachListener::pd_detachall() { | 
|---|
| 551 | // do nothing for now | 
|---|
| 552 | } | 
|---|
| 553 |  | 
|---|