src/os/bsd/vm/attachListener_bsd.cpp

Mon, 19 Mar 2012 20:13:17 +0100

author
sla
date
Mon, 19 Mar 2012 20:13:17 +0100
changeset 3648
77591ef8983a
parent 3156
f08d439fab8c
child 4229
0af5da0c9d9d
permissions
-rw-r--r--

7152800: All tests using the attach API fail with "well-known file is not secure" on Mac OS X
Summary: Create well-known file with effective group of the current process
Reviewed-by: kamg, dcubed

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

mercurial