< prev index next >

src/hotspot/os/linux/attachListener_linux.cpp

Print this page


   1 /*
   2  * Copyright (c) 2005, 2019, 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  *


  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 bool _atexit_registered;
  73 
  74   // reads a request from the given connected socket
  75   static LinuxAttachOperation* read_request(int s);
  76 
  77  public:
  78   enum {
  79     ATTACH_PROTOCOL_VER = 1                     // protocol version
  80   };
  81   enum {
  82     ATTACH_ERROR_BADVERSION     = 101           // error codes
  83   };
  84 
  85   static void set_path(char* path) {
  86     if (path == NULL) {
  87       _path[0] = '\0';
  88       _has_path = false;
  89     } else {
  90       strncpy(_path, path, UNIX_PATH_MAX);
  91       _path[UNIX_PATH_MAX-1] = '\0';
  92       _has_path = true;
  93     }
  94   }
  95 
  96   static void set_listener(int s)               { _listener = s; }
  97 











  98   // initialize the listener, returns 0 if okay
  99   static int init();
 100 
 101   static char* path()                   { return _path; }
 102   static bool has_path()                { return _has_path; }
 103   static int listener()                 { return _listener; }
 104 
 105   // write the given buffer to a socket
 106   static int write_fully(int s, char* buf, int len);
 107 
 108   static LinuxAttachOperation* dequeue();
 109 };
 110 
 111 class LinuxAttachOperation: public AttachOperation {
 112  private:
 113   // the connection to the client
 114   int _socket;
 115 
 116  public:
 117   void complete(jint res, bufferedStream* st);
 118 
 119   void set_socket(int s)                                { _socket = s; }
 120   int socket() const                                    { return _socket; }
 121 
 122   LinuxAttachOperation(char* name) : AttachOperation(name) {
 123     set_socket(-1);
 124   }
 125 };
 126 
 127 // statics
 128 char LinuxAttachListener::_path[UNIX_PATH_MAX];
 129 bool LinuxAttachListener::_has_path;
 130 int LinuxAttachListener::_listener = -1;
 131 bool LinuxAttachListener::_atexit_registered = false;
 132 
 133 // Supporting class to help split a buffer into individual components
 134 class ArgumentIterator : public StackObj {
 135  private:
 136   char* _pos;
 137   char* _end;
 138  public:
 139   ArgumentIterator(char* arg_buffer, size_t arg_size) {
 140     _pos = arg_buffer;
 141     _end = _pos + arg_size - 1;
 142   }
 143   char* next() {
 144     if (*_pos == '\0') {
 145       // advance the iterator if possible (null arguments)
 146       if (_pos < _end) {
 147         _pos += 1;
 148       }
 149       return NULL;
 150     }
 151     char* res = _pos;
 152     char* next_pos = strchr(_pos, '\0');
 153     if (next_pos < _end)  {
 154       next_pos++;
 155     }
 156     _pos = next_pos;
 157     return res;
 158   }
 159 };
 160 
 161 
 162 // atexit hook to stop listener and unlink the file that it is
 163 // bound too.
 164 extern "C" {
 165   static void listener_cleanup() {
 166     int s = LinuxAttachListener::listener();
 167     if (s != -1) {
 168       LinuxAttachListener::set_listener(-1);
 169       ::shutdown(s, SHUT_RDWR);
 170       ::close(s);
 171     }
 172     if (LinuxAttachListener::has_path()) {
 173       ::unlink(LinuxAttachListener::path());
 174       LinuxAttachListener::set_path(NULL);

 175     }
 176   }
 177 }
 178 
 179 // Initialization - create a listener socket and bind it to a file
 180 
 181 int LinuxAttachListener::init() {
 182   char path[UNIX_PATH_MAX];          // socket file
 183   char initial_path[UNIX_PATH_MAX];  // socket file during setup
 184   int listener;                      // listener socket (file descriptor)
 185 
 186   // register function to cleanup
 187   if (!_atexit_registered) {
 188     _atexit_registered = true;
 189     ::atexit(listener_cleanup);
 190   }
 191 
 192   int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
 193                    os::get_temp_directory(), os::current_process_id());
 194   if (n < (int)UNIX_PATH_MAX) {
 195     n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
 196   }
 197   if (n >= (int)UNIX_PATH_MAX) {
 198     return -1;
 199   }
 200 
 201   // create the listener socket
 202   listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
 203   if (listener == -1) {
 204     return -1;
 205   }
 206 
 207   // bind socket
 208   struct sockaddr_un addr;
 209   memset((void *)&addr, 0, sizeof(addr));
 210   addr.sun_family = AF_UNIX;


 472     if (ret == -1) {
 473       log_debug(attach)("Failed to remove stale attach pid file at %s", fn);
 474     }
 475   }
 476 }
 477 
 478 int AttachListener::pd_init() {
 479   JavaThread* thread = JavaThread::current();
 480   ThreadBlockInVM tbivm(thread);
 481 
 482   thread->set_suspend_equivalent();
 483   // cleared by handle_special_suspend_equivalent_condition() or
 484   // java_suspend_self() via check_and_wait_while_suspended()
 485 
 486   int ret_code = LinuxAttachListener::init();
 487 
 488   // were we externally suspended while we were waiting?
 489   thread->check_and_wait_while_suspended();
 490 
 491   return ret_code;
 492 }
 493 
 494 bool AttachListener::check_socket_file() {
 495   int ret;
 496   struct stat64 st;
 497   ret = stat64(LinuxAttachListener::path(), &st);
 498   if (ret == -1) { // need to restart attach listener.
 499     log_debug(attach)("Socket file %s does not exist - Restart Attach Listener",
 500                       LinuxAttachListener::path());
 501 
 502     listener_cleanup();
 503 
 504     // wait to terminate current attach listener instance...
 505     while (AttachListener::transit_state(AL_INITIALIZING,
 506                                          AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
 507       os::naked_yield();
 508     }
 509     return is_init_trigger();
 510   }
 511   return false;
 512 }
 513 
 514 // Attach Listener is started lazily except in the case when
 515 // +ReduseSignalUsage is used
 516 bool AttachListener::init_at_startup() {
 517   if (ReduceSignalUsage) {
 518     return true;
 519   } else {
 520     return false;
 521   }
 522 }
 523 
 524 // If the file .attach_pid<pid> exists in the working directory
 525 // or /tmp then this is the trigger to start the attach mechanism
 526 bool AttachListener::is_init_trigger() {
 527   if (init_at_startup() || is_initialized()) {
 528     return false;               // initialized at startup or already initialized
 529   }
 530   char fn[PATH_MAX + 1];
 531   int ret;


   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  *


  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;


 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;


< prev index next >