1/*
2 * Copyright (c) 2005, 2017, 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 "runtime/interfaceSupport.hpp"
27#include "runtime/os.inline.hpp"
28#include "services/attachListener.hpp"
29#include "services/dtraceAttacher.hpp"
30#include "utilities/vmError.hpp"
31
32#include <door.h>
33#include <limits.h>
34#include <string.h>
35#include <signal.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <sys/stat.h>
39
40// stropts.h uses STR in stream ioctl defines
41#undef STR
42#include <stropts.h>
43#undef STR
44#define STR(a) #a
45
46// The attach mechanism on Solaris is implemented using the Doors IPC
47// mechanism. The first tool to attempt to attach causes the attach
48// listener thread to startup. This thread creats a door that is
49// associated with a function that enqueues an operation to the attach
50// listener. The door is attached to a file in the file system so that
51// client (tools) can locate it. To enqueue an operation to the VM the
52// client calls through the door which invokes the enqueue function in
53// this process. The credentials of the client are checked and if the
54// effective uid matches this process then the operation is enqueued.
55// When an operation completes the attach listener is required to send the
56// operation result and any result data to the client. In this implementation
57// the result is returned via a UNIX domain socket. A pair of connected
58// sockets (socketpair) is created in the enqueue function and the file
59// descriptor for one of the sockets is returned to the client as the
60// return from the door call. The other end is retained in this process.
61// When the operation completes the result is sent to the client and
62// the socket is closed.
63
64// forward reference
65class SolarisAttachOperation;
66
67class SolarisAttachListener: AllStatic {
68 private:
69
70  // the path to which we attach the door file descriptor
71  static char _door_path[PATH_MAX+1];
72  static volatile bool _has_door_path;
73
74  // door descriptor returned by door_create
75  static int _door_descriptor;
76
77  static void set_door_path(char* path) {
78    if (path == NULL) {
79      _has_door_path = false;
80    } else {
81      strncpy(_door_path, path, PATH_MAX);
82      _door_path[PATH_MAX] = '\0';      // ensure it's nul terminated
83      _has_door_path = true;
84    }
85  }
86
87  static void set_door_descriptor(int dd)               { _door_descriptor = dd; }
88
89  // mutex to protect operation list
90  static mutex_t _mutex;
91
92  // semaphore to wakeup listener thread
93  static sema_t _wakeup;
94
95  static mutex_t* mutex()                               { return &_mutex; }
96  static sema_t* wakeup()                               { return &_wakeup; }
97
98  // enqueued operation list
99  static SolarisAttachOperation* _head;
100  static SolarisAttachOperation* _tail;
101
102  static SolarisAttachOperation* head()                 { return _head; }
103  static void set_head(SolarisAttachOperation* head)    { _head = head; }
104
105  static SolarisAttachOperation* tail()                 { return _tail; }
106  static void set_tail(SolarisAttachOperation* tail)    { _tail = tail; }
107
108  // create the door
109  static int create_door();
110
111 public:
112  enum {
113    ATTACH_PROTOCOL_VER = 1                             // protocol version
114  };
115  enum {
116    ATTACH_ERROR_BADREQUEST     = 100,                  // error code returned by
117    ATTACH_ERROR_BADVERSION     = 101,                  // the door call
118    ATTACH_ERROR_RESOURCE       = 102,
119    ATTACH_ERROR_INTERNAL       = 103,
120    ATTACH_ERROR_DENIED         = 104
121  };
122
123  // initialize the listener
124  static int init();
125
126  static bool has_door_path()                           { return _has_door_path; }
127  static char* door_path()                              { return _door_path; }
128  static int door_descriptor()                          { return _door_descriptor; }
129
130  // enqueue an operation
131  static void enqueue(SolarisAttachOperation* op);
132
133  // dequeue an operation
134  static SolarisAttachOperation* dequeue();
135};
136
137
138// SolarisAttachOperation is an AttachOperation that additionally encapsulates
139// a socket connection to the requesting client/tool. SolarisAttachOperation
140// can additionally be held in a linked list.
141
142class SolarisAttachOperation: public AttachOperation {
143 private:
144  friend class SolarisAttachListener;
145
146  // connection to client
147  int _socket;
148
149  // linked list support
150  SolarisAttachOperation* _next;
151
152  SolarisAttachOperation* next()                         { return _next; }
153  void set_next(SolarisAttachOperation* next)            { _next = next; }
154
155 public:
156  void complete(jint res, bufferedStream* st);
157
158  int socket() const                                     { return _socket; }
159  void set_socket(int s)                                 { _socket = s; }
160
161  SolarisAttachOperation(char* name) : AttachOperation(name) {
162    set_socket(-1);
163    set_next(NULL);
164  }
165};
166
167// statics
168char SolarisAttachListener::_door_path[PATH_MAX+1];
169volatile bool SolarisAttachListener::_has_door_path;
170int SolarisAttachListener::_door_descriptor = -1;
171mutex_t SolarisAttachListener::_mutex;
172sema_t SolarisAttachListener::_wakeup;
173SolarisAttachOperation* SolarisAttachListener::_head = NULL;
174SolarisAttachOperation* SolarisAttachListener::_tail = NULL;
175
176// Supporting class to help split a buffer into individual components
177class ArgumentIterator : public StackObj {
178 private:
179  char* _pos;
180  char* _end;
181 public:
182  ArgumentIterator(char* arg_buffer, size_t arg_size) {
183    _pos = arg_buffer;
184    _end = _pos + arg_size - 1;
185  }
186  char* next() {
187    if (*_pos == '\0') {
188      return NULL;
189    }
190    char* res = _pos;
191    char* next_pos = strchr(_pos, '\0');
192    if (next_pos < _end)  {
193      next_pos++;
194    }
195    _pos = next_pos;
196    return res;
197  }
198};
199
200// Calls from the door function to check that the client credentials
201// match this process. Returns 0 if credentials okay, otherwise -1.
202static int check_credentials() {
203  ucred_t *cred_info = NULL;
204  int ret = -1; // deny by default
205
206  // get client credentials
207  if (door_ucred(&cred_info) == -1) {
208    return -1; // unable to get them, deny
209  }
210
211  // get our euid/eguid (probably could cache these)
212  uid_t euid = geteuid();
213  gid_t egid = getegid();
214
215  // get euid/egid from ucred_free
216  uid_t ucred_euid = ucred_geteuid(cred_info);
217  gid_t ucred_egid = ucred_getegid(cred_info);
218
219  // check that the effective uid/gid matches
220  if (ucred_euid == euid && ucred_egid == egid) {
221    ret =  0;  // allow
222  }
223
224  ucred_free(cred_info);
225  return ret;
226}
227
228
229// Parses the argument buffer to create an AttachOperation that we should
230// enqueue to the attach listener.
231// The buffer is expected to be formatted as follows:
232// <ver>0<cmd>0<arg>0<arg>0<arg>0
233// where <ver> is the version number (must be "1"), <cmd> is the command
234// name ("load, "datadump", ...) and <arg> is an argument.
235//
236static SolarisAttachOperation* create_operation(char* argp, size_t arg_size, int* err) {
237  // assume bad request until parsed
238  *err = SolarisAttachListener::ATTACH_ERROR_BADREQUEST;
239
240  if (arg_size < 2 || argp[arg_size-1] != '\0') {
241    return NULL;   // no ver or not null terminated
242  }
243
244  // Use supporting class to iterate over the buffer
245  ArgumentIterator args(argp, arg_size);
246
247  // First check the protocol version
248  char* ver = args.next();
249  if (ver == NULL) {
250    return NULL;
251  }
252  if (atoi(ver) != SolarisAttachListener::ATTACH_PROTOCOL_VER) {
253    *err = SolarisAttachListener::ATTACH_ERROR_BADVERSION;
254    return NULL;
255  }
256
257  // Get command name and create the operation
258  char* name = args.next();
259  if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
260    return NULL;
261  }
262  SolarisAttachOperation* op = new SolarisAttachOperation(name);
263
264  // Iterate over the arguments
265  for (int i=0; i<AttachOperation::arg_count_max; i++) {
266    char* arg = args.next();
267    if (arg == NULL) {
268      op->set_arg(i, NULL);
269    } else {
270      if (strlen(arg) > AttachOperation::arg_length_max) {
271        delete op;
272        return NULL;
273      }
274      op->set_arg(i, arg);
275    }
276  }
277
278  // return operation
279  *err = 0;
280  return op;
281}
282
283// create special operation to indicate all clients have detached
284static SolarisAttachOperation* create_detachall_operation() {
285  return new SolarisAttachOperation(AttachOperation::detachall_operation_name());
286}
287
288// This is door function which the client executes via a door_call.
289extern "C" {
290  static void enqueue_proc(void* cookie, char* argp, size_t arg_size,
291                           door_desc_t* dt, uint_t n_desc)
292  {
293    int return_fd = -1;
294    SolarisAttachOperation* op = NULL;
295
296    // no listener
297    jint res = 0;
298    if (!AttachListener::is_initialized()) {
299      // how did we get here?
300      debug_only(warning("door_call when not enabled"));
301      res = (jint)SolarisAttachListener::ATTACH_ERROR_INTERNAL;
302    }
303
304    // check client credentials
305    if (res == 0) {
306      if (check_credentials() != 0) {
307        res = (jint)SolarisAttachListener::ATTACH_ERROR_DENIED;
308      }
309    }
310
311    // if we are stopped at ShowMessageBoxOnError then maybe we can
312    // load a diagnostic library
313    if (res == 0 && VMError::is_error_reported()) {
314      if (ShowMessageBoxOnError) {
315        // TBD - support loading of diagnostic library here
316      }
317
318      // can't enqueue operation after fatal error
319      res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
320    }
321
322    // create the operation
323    if (res == 0) {
324      int err;
325      op = create_operation(argp, arg_size, &err);
326      res = (op == NULL) ? (jint)err : 0;
327    }
328
329    // create a pair of connected sockets. Store the file descriptor
330    // for one end in the operation and enqueue the operation. The
331    // file descriptor for the other end wil be returned to the client.
332    if (res == 0) {
333      int s[2];
334      if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) < 0) {
335        delete op;
336        res = (jint)SolarisAttachListener::ATTACH_ERROR_RESOURCE;
337      } else {
338        op->set_socket(s[0]);
339        return_fd = s[1];
340        SolarisAttachListener::enqueue(op);
341      }
342    }
343
344    // Return 0 (success) + file descriptor, or non-0 (error)
345    if (res == 0) {
346      door_desc_t desc;
347      // DOOR_RELEASE flag makes sure fd is closed after passing it to
348      // the client.  See door_return(3DOOR) man page.
349      desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
350      desc.d_data.d_desc.d_descriptor = return_fd;
351      door_return((char*)&res, sizeof(res), &desc, 1);
352    } else {
353      door_return((char*)&res, sizeof(res), NULL, 0);
354    }
355  }
356}
357
358// atexit hook to detach the door and remove the file
359extern "C" {
360  static void listener_cleanup() {
361    static int cleanup_done;
362    if (!cleanup_done) {
363      cleanup_done = 1;
364      int dd = SolarisAttachListener::door_descriptor();
365      if (dd >= 0) {
366        ::close(dd);
367      }
368      if (SolarisAttachListener::has_door_path()) {
369        char* path = SolarisAttachListener::door_path();
370        ::fdetach(path);
371        ::unlink(path);
372      }
373    }
374  }
375}
376
377// Create the door
378int SolarisAttachListener::create_door() {
379  char door_path[PATH_MAX+1];
380  char initial_path[PATH_MAX+1];
381  int fd, res;
382
383  // register exit function
384  ::atexit(listener_cleanup);
385
386  // create the door descriptor
387  int dd = ::door_create(enqueue_proc, NULL, 0);
388  if (dd < 0) {
389    return -1;
390  }
391
392  // create initial file to attach door descriptor
393  snprintf(door_path, sizeof(door_path), "%s/.java_pid%d",
394           os::get_temp_directory(), os::current_process_id());
395  snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path);
396  RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
397  if (fd == -1) {
398    log_debug(attach)("attempt to create door file %s failed (%d)", initial_path, errno);
399    ::door_revoke(dd);
400    return -1;
401  }
402  assert(fd >= 0, "bad file descriptor");
403  ::close(fd);
404
405  // attach the door descriptor to the file
406  if ((res = ::fattach(dd, initial_path)) == -1) {
407    // if busy then detach and try again
408    if (errno == EBUSY) {
409      ::fdetach(initial_path);
410      res = ::fattach(dd, initial_path);
411    }
412    if (res == -1) {
413      log_debug(attach)("unable to create door - fattach failed (%d)", errno);
414      ::door_revoke(dd);
415      dd = -1;
416    }
417  }
418
419  // rename file so that clients can attach
420  if (dd >= 0) {
421    if (::rename(initial_path, door_path) == -1) {
422        ::close(dd);
423        ::fdetach(initial_path);
424        log_debug(attach)("unable to create door - rename %s to %s failed (%d)", errno);
425        dd = -1;
426    }
427  }
428  if (dd >= 0) {
429    set_door_descriptor(dd);
430    set_door_path(door_path);
431    log_trace(attach)("door file %s created succesfully", door_path);
432  } else {
433    // unable to create door, attach it to file, or rename file into place
434    ::unlink(initial_path);
435    return -1;
436  }
437
438  return 0;
439}
440
441// Initialization - create the door, locks, and other initialization
442int SolarisAttachListener::init() {
443  if (create_door()) {
444    return -1;
445  }
446
447  int status = os::Solaris::mutex_init(&_mutex);
448  assert_status(status==0, status, "mutex_init");
449
450  status = ::sema_init(&_wakeup, 0, NULL, NULL);
451  assert_status(status==0, status, "sema_init");
452
453  set_head(NULL);
454  set_tail(NULL);
455
456  return 0;
457}
458
459// Dequeue an operation
460SolarisAttachOperation* SolarisAttachListener::dequeue() {
461  for (;;) {
462    int res;
463
464    // wait for somebody to enqueue something
465    while ((res = ::sema_wait(wakeup())) == EINTR)
466      ;
467    if (res) {
468      warning("sema_wait failed: %s", os::strerror(res));
469      return NULL;
470    }
471
472    // lock the list
473    res = os::Solaris::mutex_lock(mutex());
474    assert(res == 0, "mutex_lock failed");
475
476    // remove the head of the list
477    SolarisAttachOperation* op = head();
478    if (op != NULL) {
479      set_head(op->next());
480      if (head() == NULL) {
481        set_tail(NULL);
482      }
483    }
484
485    // unlock
486    os::Solaris::mutex_unlock(mutex());
487
488    // if we got an operation when return it.
489    if (op != NULL) {
490      return op;
491    }
492  }
493}
494
495// Enqueue an operation
496void SolarisAttachListener::enqueue(SolarisAttachOperation* op) {
497  // lock list
498  int res = os::Solaris::mutex_lock(mutex());
499  assert(res == 0, "mutex_lock failed");
500
501  // enqueue at tail
502  op->set_next(NULL);
503  if (head() == NULL) {
504    set_head(op);
505  } else {
506    tail()->set_next(op);
507  }
508  set_tail(op);
509
510  // wakeup the attach listener
511  RESTARTABLE(::sema_post(wakeup()), res);
512  assert(res == 0, "sema_post failed");
513
514  // unlock
515  os::Solaris::mutex_unlock(mutex());
516}
517
518
519// support function - writes the (entire) buffer to a socket
520static int write_fully(int s, char* buf, int len) {
521  do {
522    int n = ::write(s, buf, len);
523    if (n == -1) {
524      if (errno != EINTR) return -1;
525    } else {
526      buf += n;
527      len -= n;
528    }
529  }
530  while (len > 0);
531  return 0;
532}
533
534// Complete an operation by sending the operation result and any result
535// output to the client. At this time the socket is in blocking mode so
536// potentially we can block if there is a lot of data and the client is
537// non-responsive. For most operations this is a non-issue because the
538// default send buffer is sufficient to buffer everything. In the future
539// if there are operations that involves a very big reply then it the
540// socket could be made non-blocking and a timeout could be used.
541
542void SolarisAttachOperation::complete(jint res, bufferedStream* st) {
543  if (this->socket() >= 0) {
544    JavaThread* thread = JavaThread::current();
545    ThreadBlockInVM tbivm(thread);
546
547    thread->set_suspend_equivalent();
548    // cleared by handle_special_suspend_equivalent_condition() or
549    // java_suspend_self() via check_and_wait_while_suspended()
550
551    // write operation result
552    char msg[32];
553    sprintf(msg, "%d\n", res);
554    int rc = write_fully(this->socket(), msg, strlen(msg));
555
556    // write any result data
557    if (rc == 0) {
558      write_fully(this->socket(), (char*) st->base(), st->size());
559      ::shutdown(this->socket(), 2);
560    }
561
562    // close socket and we're done
563    ::close(this->socket());
564
565    // were we externally suspended while we were waiting?
566    thread->check_and_wait_while_suspended();
567  }
568  delete this;
569}
570
571
572// AttachListener functions
573
574AttachOperation* AttachListener::dequeue() {
575  JavaThread* thread = JavaThread::current();
576  ThreadBlockInVM tbivm(thread);
577
578  thread->set_suspend_equivalent();
579  // cleared by handle_special_suspend_equivalent_condition() or
580  // java_suspend_self() via check_and_wait_while_suspended()
581
582  AttachOperation* op = SolarisAttachListener::dequeue();
583
584  // were we externally suspended while we were waiting?
585  thread->check_and_wait_while_suspended();
586
587  return op;
588}
589
590
591// Performs initialization at vm startup
592// For Solaris we remove any stale .java_pid file which could cause
593// an attaching process to think we are ready to receive a door_call
594// before we are properly initialized
595
596void AttachListener::vm_start() {
597  char fn[PATH_MAX+1];
598  struct stat64 st;
599  int ret;
600
601  int n = snprintf(fn, sizeof(fn), "%s/.java_pid%d",
602           os::get_temp_directory(), os::current_process_id());
603  assert(n < sizeof(fn), "java_pid file name buffer overflow");
604
605  RESTARTABLE(::stat64(fn, &st), ret);
606  if (ret == 0) {
607    ret = ::unlink(fn);
608    if (ret == -1) {
609      log_debug(attach)("Failed to remove stale attach pid file at %s", fn);
610    }
611  }
612}
613
614int AttachListener::pd_init() {
615  JavaThread* thread = JavaThread::current();
616  ThreadBlockInVM tbivm(thread);
617
618  thread->set_suspend_equivalent();
619  // cleared by handle_special_suspend_equivalent_condition() or
620  // java_suspend_self()
621
622  int ret_code = SolarisAttachListener::init();
623
624  // were we externally suspended while we were waiting?
625  thread->check_and_wait_while_suspended();
626
627  return ret_code;
628}
629
630// Attach Listener is started lazily except in the case when
631// +ReduseSignalUsage is used
632bool AttachListener::init_at_startup() {
633  if (ReduceSignalUsage) {
634    return true;
635  } else {
636    return false;
637  }
638}
639
640// If the file .attach_pid<pid> exists in the working directory
641// or /tmp then this is the trigger to start the attach mechanism
642bool AttachListener::is_init_trigger() {
643  if (init_at_startup() || is_initialized()) {
644    return false;               // initialized at startup or already initialized
645  }
646  char fn[PATH_MAX+1];
647  sprintf(fn, ".attach_pid%d", os::current_process_id());
648  int ret;
649  struct stat64 st;
650  RESTARTABLE(::stat64(fn, &st), ret);
651  if (ret == -1) {
652    log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
653    snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
654             os::get_temp_directory(), os::current_process_id());
655    RESTARTABLE(::stat64(fn, &st), ret);
656    if (ret == -1) {
657      log_debug(attach)("Failed to find attach file: %s", fn);
658    }
659  }
660  if (ret == 0) {
661    // simple check to avoid starting the attach mechanism when
662    // a bogus user creates the file
663    if (st.st_uid == geteuid()) {
664      init();
665      return true;
666    }
667  }
668  return false;
669}
670
671// if VM aborts then detach/cleanup
672void AttachListener::abort() {
673  listener_cleanup();
674}
675
676void AttachListener::pd_data_dump() {
677  os::signal_notify(SIGQUIT);
678}
679
680static jint enable_dprobes(AttachOperation* op, outputStream* out) {
681  const char* probe = op->arg(0);
682  if (probe == NULL || probe[0] == '\0') {
683    out->print_cr("No probe specified");
684    return JNI_ERR;
685  } else {
686    char *end;
687    long val = strtol(probe, &end, 10);
688    if (end == probe || val < 0 || val > INT_MAX) {
689      out->print_cr("invalid probe type");
690      return JNI_ERR;
691    } else {
692      int probe_typess = (int) val;
693      DTrace::enable_dprobes(probe_typess);
694      return JNI_OK;
695    }
696  }
697}
698
699// platform specific operations table
700static AttachOperationFunctionInfo funcs[] = {
701  { "enabledprobes", enable_dprobes },
702  { NULL, NULL }
703};
704
705AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* name) {
706  int i;
707  for (i = 0; funcs[i].name != NULL; i++) {
708    if (strcmp(funcs[i].name, name) == 0) {
709      return &funcs[i];
710    }
711  }
712  return NULL;
713}
714
715// Solaris specific global flag set. Currently, we support only
716// changing ExtendedDTraceProbes flag.
717jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
718  const char* name = op->arg(0);
719  assert(name != NULL, "flag name should not be null");
720  bool flag = true;
721  const char* arg1;
722  if ((arg1 = op->arg(1)) != NULL) {
723    char *end;
724    flag = (strtol(arg1, &end, 10) != 0);
725    if (arg1 == end) {
726      out->print_cr("flag value has to be an integer");
727      return JNI_ERR;
728    }
729  }
730
731  if (strcmp(name, "ExtendedDTraceProbes") == 0) {
732    DTrace::set_extended_dprobes(flag);
733    return JNI_OK;
734  }
735
736  if (strcmp(name, "DTraceMonitorProbes") == 0) {
737    DTrace::set_monitor_dprobes(flag);
738    return JNI_OK;
739  }
740
741  out->print_cr("flag '%s' cannot be changed", name);
742  return JNI_ERR;
743}
744
745void AttachListener::pd_detachall() {
746  DTrace::detach_all_clients();
747}
748