src/os/linux/vm/attachListener_linux.cpp

Fri, 16 Jul 2010 13:14:03 +0100

author
alanb
date
Fri, 16 Jul 2010 13:14:03 +0100
changeset 2030
a81afd9c293c
parent 1907
c18cbe5936b8
child 2223
3dc12ef8735e
permissions
-rw-r--r--

6649594: Intermittent IOExceptions during dynamic attach on linux and solaris
Reviewed-by: dcubed, dholmes

     1 /*
     2  * Copyright (c) 2005, 2008, 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  */
    25 # include "incls/_precompiled.incl"
    26 # include "incls/_attachListener_linux.cpp.incl"
    28 #include <unistd.h>
    29 #include <signal.h>
    30 #include <sys/types.h>
    31 #include <sys/socket.h>
    32 #include <sys/un.h>
    33 #include <sys/stat.h>
    35 #ifndef UNIX_PATH_MAX
    36 #define UNIX_PATH_MAX   sizeof(((struct sockaddr_un *)0)->sun_path)
    37 #endif
    39 // The attach mechanism on Linux uses a UNIX domain socket. An attach listener
    40 // thread is created at startup or is created on-demand via a signal from
    41 // the client tool. The attach listener creates a socket and binds it to a file
    42 // in the filesystem. The attach listener then acts as a simple (single-
    43 // threaded) server - it waits for a client to connect, reads the request,
    44 // executes it, and returns the response to the client via the socket
    45 // connection.
    46 //
    47 // As the socket is a UNIX domain socket it means that only clients on the
    48 // local machine can connect. In addition there are two other aspects to
    49 // the security:
    50 // 1. The well known file that the socket is bound to has permission 400
    51 // 2. When a client connect, the SO_PEERCRED socket option is used to
    52 //    obtain the credentials of client. We check that the effective uid
    53 //    of the client matches this process.
    55 // forward reference
    56 class LinuxAttachOperation;
    58 class LinuxAttachListener: AllStatic {
    59  private:
    60   // the path to which we bind the UNIX domain socket
    61   static char _path[UNIX_PATH_MAX];
    62   static bool _has_path;
    64   // the file descriptor for the listening socket
    65   static int _listener;
    67   static void set_path(char* path) {
    68     if (path == NULL) {
    69       _has_path = false;
    70     } else {
    71       strncpy(_path, path, UNIX_PATH_MAX);
    72       _path[UNIX_PATH_MAX-1] = '\0';
    73       _has_path = true;
    74     }
    75   }
    77   static void set_listener(int s)               { _listener = s; }
    79   // reads a request from the given connected socket
    80   static LinuxAttachOperation* read_request(int s);
    82  public:
    83   enum {
    84     ATTACH_PROTOCOL_VER = 1                     // protocol version
    85   };
    86   enum {
    87     ATTACH_ERROR_BADVERSION     = 101           // error codes
    88   };
    90   // initialize the listener, returns 0 if okay
    91   static int init();
    93   static char* path()                   { return _path; }
    94   static bool has_path()                { return _has_path; }
    95   static int listener()                 { return _listener; }
    97   // write the given buffer to a socket
    98   static int write_fully(int s, char* buf, int len);
   100   static LinuxAttachOperation* dequeue();
   101 };
   103 class LinuxAttachOperation: public AttachOperation {
   104  private:
   105   // the connection to the client
   106   int _socket;
   108  public:
   109   void complete(jint res, bufferedStream* st);
   111   void set_socket(int s)                                { _socket = s; }
   112   int socket() const                                    { return _socket; }
   114   LinuxAttachOperation(char* name) : AttachOperation(name) {
   115     set_socket(-1);
   116   }
   117 };
   119 // statics
   120 char LinuxAttachListener::_path[UNIX_PATH_MAX];
   121 bool LinuxAttachListener::_has_path;
   122 int LinuxAttachListener::_listener = -1;
   124 // Supporting class to help split a buffer into individual components
   125 class ArgumentIterator : public StackObj {
   126  private:
   127   char* _pos;
   128   char* _end;
   129  public:
   130   ArgumentIterator(char* arg_buffer, size_t arg_size) {
   131     _pos = arg_buffer;
   132     _end = _pos + arg_size - 1;
   133   }
   134   char* next() {
   135     if (*_pos == '\0') {
   136       return NULL;
   137     }
   138     char* res = _pos;
   139     char* next_pos = strchr(_pos, '\0');
   140     if (next_pos < _end)  {
   141       next_pos++;
   142     }
   143     _pos = next_pos;
   144     return res;
   145   }
   146 };
   149 // atexit hook to stop listener and unlink the file that it is
   150 // bound too.
   151 extern "C" {
   152   static void listener_cleanup() {
   153     static int cleanup_done;
   154     if (!cleanup_done) {
   155       cleanup_done = 1;
   156       int s = LinuxAttachListener::listener();
   157       if (s != -1) {
   158         ::close(s);
   159       }
   160       if (LinuxAttachListener::has_path()) {
   161         ::unlink(LinuxAttachListener::path());
   162       }
   163     }
   164   }
   165 }
   167 // Initialization - create a listener socket and bind it to a file
   169 int LinuxAttachListener::init() {
   170   char path[UNIX_PATH_MAX];          // socket file
   171   char initial_path[UNIX_PATH_MAX];  // socket file during setup
   172   int listener;                      // listener socket (file descriptor)
   174   // register function to cleanup
   175   ::atexit(listener_cleanup);
   177   int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
   178                    os::get_temp_directory(), os::current_process_id());
   179   if (n <= (int)UNIX_PATH_MAX) {
   180     n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
   181   }
   182   if (n > (int)UNIX_PATH_MAX) {
   183     return -1;
   184   }
   186   // create the listener socket
   187   listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
   188   if (listener == -1) {
   189     return -1;
   190   }
   192   // bind socket
   193   struct sockaddr_un addr;
   194   addr.sun_family = AF_UNIX;
   195   strcpy(addr.sun_path, initial_path);
   196   ::unlink(initial_path);
   197   int res = ::bind(listener, (struct sockaddr*)&addr, sizeof(addr));
   198   if (res == -1) {
   199     RESTARTABLE(::close(listener), res);
   200     return -1;
   201   }
   203   // put in listen mode, set permissions, and rename into place
   204   res = ::listen(listener, 5);
   205   if (res == 0) {
   206       RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
   207       if (res == 0) {
   208           res = ::rename(initial_path, path);
   209       }
   210   }
   211   if (res == -1) {
   212     RESTARTABLE(::close(listener), res);
   213     ::unlink(initial_path);
   214     return -1;
   215   }
   216   set_path(path);
   217   set_listener(listener);
   219   return 0;
   220 }
   222 // Given a socket that is connected to a peer we read the request and
   223 // create an AttachOperation. As the socket is blocking there is potential
   224 // for a denial-of-service if the peer does not response. However this happens
   225 // after the peer credentials have been checked and in the worst case it just
   226 // means that the attach listener thread is blocked.
   227 //
   228 LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
   229   char ver_str[8];
   230   sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER);
   232   // The request is a sequence of strings so we first figure out the
   233   // expected count and the maximum possible length of the request.
   234   // The request is:
   235   //   <ver>0<cmd>0<arg>0<arg>0<arg>0
   236   // where <ver> is the protocol version (1), <cmd> is the command
   237   // name ("load", "datadump", ...), and <arg> is an argument
   238   int expected_str_count = 2 + AttachOperation::arg_count_max;
   239   const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
   240     AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
   242   char buf[max_len];
   243   int str_count = 0;
   245   // Read until all (expected) strings have been read, the buffer is
   246   // full, or EOF.
   248   int off = 0;
   249   int left = max_len;
   251   do {
   252     int n;
   253     RESTARTABLE(read(s, buf+off, left), n);
   254     if (n == -1) {
   255       return NULL;      // reset by peer or other error
   256     }
   257     if (n == 0) {
   258       break;
   259     }
   260     for (int i=0; i<n; i++) {
   261       if (buf[off+i] == 0) {
   262         // EOS found
   263         str_count++;
   265         // The first string is <ver> so check it now to
   266         // check for protocol mis-match
   267         if (str_count == 1) {
   268           if ((strlen(buf) != strlen(ver_str)) ||
   269               (atoi(buf) != ATTACH_PROTOCOL_VER)) {
   270             char msg[32];
   271             sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION);
   272             write_fully(s, msg, strlen(msg));
   273             return NULL;
   274           }
   275         }
   276       }
   277     }
   278     off += n;
   279     left -= n;
   280   } while (left > 0 && str_count < expected_str_count);
   282   if (str_count != expected_str_count) {
   283     return NULL;        // incomplete request
   284   }
   286   // parse request
   288   ArgumentIterator args(buf, (max_len)-left);
   290   // version already checked
   291   char* v = args.next();
   293   char* name = args.next();
   294   if (name == NULL || strlen(name) > AttachOperation::name_length_max) {
   295     return NULL;
   296   }
   298   LinuxAttachOperation* op = new LinuxAttachOperation(name);
   300   for (int i=0; i<AttachOperation::arg_count_max; i++) {
   301     char* arg = args.next();
   302     if (arg == NULL) {
   303       op->set_arg(i, NULL);
   304     } else {
   305       if (strlen(arg) > AttachOperation::arg_length_max) {
   306         delete op;
   307         return NULL;
   308       }
   309       op->set_arg(i, arg);
   310     }
   311   }
   313   op->set_socket(s);
   314   return op;
   315 }
   318 // Dequeue an operation
   319 //
   320 // In the Linux implementation there is only a single operation and clients
   321 // cannot queue commands (except at the socket level).
   322 //
   323 LinuxAttachOperation* LinuxAttachListener::dequeue() {
   324   for (;;) {
   325     int s;
   327     // wait for client to connect
   328     struct sockaddr addr;
   329     socklen_t len = sizeof(addr);
   330     RESTARTABLE(::accept(listener(), &addr, &len), s);
   331     if (s == -1) {
   332       return NULL;      // log a warning?
   333     }
   335     // get the credentials of the peer and check the effective uid/guid
   336     // - check with jeff on this.
   337     struct ucred cred_info;
   338     socklen_t optlen = sizeof(cred_info);
   339     if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) {
   340       int res;
   341       RESTARTABLE(::close(s), res);
   342       continue;
   343     }
   344     uid_t euid = geteuid();
   345     gid_t egid = getegid();
   347     if (cred_info.uid != euid || cred_info.gid != egid) {
   348       int res;
   349       RESTARTABLE(::close(s), res);
   350       continue;
   351     }
   353     // peer credential look okay so we read the request
   354     LinuxAttachOperation* op = read_request(s);
   355     if (op == NULL) {
   356       int res;
   357       RESTARTABLE(::close(s), res);
   358       continue;
   359     } else {
   360       return op;
   361     }
   362   }
   363 }
   365 // write the given buffer to the socket
   366 int LinuxAttachListener::write_fully(int s, char* buf, int len) {
   367   do {
   368     int n = ::write(s, buf, len);
   369     if (n == -1) {
   370       if (errno != EINTR) return -1;
   371     } else {
   372       buf += n;
   373       len -= n;
   374     }
   375   }
   376   while (len > 0);
   377   return 0;
   378 }
   380 // Complete an operation by sending the operation result and any result
   381 // output to the client. At this time the socket is in blocking mode so
   382 // potentially we can block if there is a lot of data and the client is
   383 // non-responsive. For most operations this is a non-issue because the
   384 // default send buffer is sufficient to buffer everything. In the future
   385 // if there are operations that involves a very big reply then it the
   386 // socket could be made non-blocking and a timeout could be used.
   388 void LinuxAttachOperation::complete(jint result, bufferedStream* st) {
   389   JavaThread* thread = JavaThread::current();
   390   ThreadBlockInVM tbivm(thread);
   392   thread->set_suspend_equivalent();
   393   // cleared by handle_special_suspend_equivalent_condition() or
   394   // java_suspend_self() via check_and_wait_while_suspended()
   396   // write operation result
   397   char msg[32];
   398   sprintf(msg, "%d\n", result);
   399   int rc = LinuxAttachListener::write_fully(this->socket(), msg, strlen(msg));
   401   // write any result data
   402   if (rc == 0) {
   403     LinuxAttachListener::write_fully(this->socket(), (char*) st->base(), st->size());
   404     ::shutdown(this->socket(), 2);
   405   }
   407   // done
   408   RESTARTABLE(::close(this->socket()), rc);
   410   // were we externally suspended while we were waiting?
   411   thread->check_and_wait_while_suspended();
   413   delete this;
   414 }
   417 // AttachListener functions
   419 AttachOperation* AttachListener::dequeue() {
   420   JavaThread* thread = JavaThread::current();
   421   ThreadBlockInVM tbivm(thread);
   423   thread->set_suspend_equivalent();
   424   // cleared by handle_special_suspend_equivalent_condition() or
   425   // java_suspend_self() via check_and_wait_while_suspended()
   427   AttachOperation* op = LinuxAttachListener::dequeue();
   429   // were we externally suspended while we were waiting?
   430   thread->check_and_wait_while_suspended();
   432   return op;
   433 }
   435 int AttachListener::pd_init() {
   436   JavaThread* thread = JavaThread::current();
   437   ThreadBlockInVM tbivm(thread);
   439   thread->set_suspend_equivalent();
   440   // cleared by handle_special_suspend_equivalent_condition() or
   441   // java_suspend_self() via check_and_wait_while_suspended()
   443   int ret_code = LinuxAttachListener::init();
   445   // were we externally suspended while we were waiting?
   446   thread->check_and_wait_while_suspended();
   448   return ret_code;
   449 }
   451 // Attach Listener is started lazily except in the case when
   452 // +ReduseSignalUsage is used
   453 bool AttachListener::init_at_startup() {
   454   if (ReduceSignalUsage) {
   455     return true;
   456   } else {
   457     return false;
   458   }
   459 }
   461 // If the file .attach_pid<pid> exists in the working directory
   462 // or /tmp then this is the trigger to start the attach mechanism
   463 bool AttachListener::is_init_trigger() {
   464   if (init_at_startup() || is_initialized()) {
   465     return false;               // initialized at startup or already initialized
   466   }
   467   char fn[PATH_MAX+1];
   468   sprintf(fn, ".attach_pid%d", os::current_process_id());
   469   int ret;
   470   struct stat64 st;
   471   RESTARTABLE(::stat64(fn, &st), ret);
   472   if (ret == -1) {
   473     snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
   474              os::get_temp_directory(), os::current_process_id());
   475     RESTARTABLE(::stat64(fn, &st), ret);
   476   }
   477   if (ret == 0) {
   478     // simple check to avoid starting the attach mechanism when
   479     // a bogus user creates the file
   480     if (st.st_uid == geteuid()) {
   481       init();
   482       return true;
   483     }
   484   }
   485   return false;
   486 }
   488 // if VM aborts then remove listener
   489 void AttachListener::abort() {
   490   listener_cleanup();
   491 }
   493 void AttachListener::pd_data_dump() {
   494   os::signal_notify(SIGQUIT);
   495 }
   497 AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
   498   return NULL;
   499 }
   501 jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
   502   out->print_cr("flag '%s' cannot be changed", op->arg(0));
   503   return JNI_ERR;
   504 }
   506 void AttachListener::pd_detachall() {
   507   // do nothing for now
   508 }

mercurial