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 *
51 // As the socket is a UNIX domain socket it means that only clients on the
52 // local machine can connect. In addition there are two other aspects to
53 // the security:
54 // 1. The well known file that the socket is bound to has permission 400
55 // 2. When a client connect, the SO_PEERCRED socket option is used to
56 // obtain the credentials of client. We check that the effective uid
57 // of the client matches this process.
58
59 // forward reference
60 class BsdAttachOperation;
61
62 class BsdAttachListener: AllStatic {
63 private:
64 // the path to which we bind the UNIX domain socket
65 static char _path[UNIX_PATH_MAX];
66 static bool _has_path;
67
68 // the file descriptor for the listening socket
69 static int _listener;
70
71 static void set_path(char* path) {
72 if (path == NULL) {
73 _has_path = false;
74 } else {
75 strncpy(_path, path, UNIX_PATH_MAX);
76 _path[UNIX_PATH_MAX-1] = '\0';
77 _has_path = true;
78 }
79 }
80
81 static void set_listener(int s) { _listener = s; }
82
83 // reads a request from the given connected socket
84 static BsdAttachOperation* read_request(int s);
85
86 public:
87 enum {
88 ATTACH_PROTOCOL_VER = 1 // protocol version
89 };
90 enum {
91 ATTACH_ERROR_BADVERSION = 101 // error codes
92 };
93
94 // initialize the listener, returns 0 if okay
95 static int init();
96
97 static char* path() { return _path; }
98 static bool has_path() { return _has_path; }
99 static int listener() { return _listener; }
100
101 // write the given buffer to a socket
102 static int write_fully(int s, char* buf, int len);
103
104 static BsdAttachOperation* dequeue();
105 };
106
107 class BsdAttachOperation: public AttachOperation {
108 private:
109 // the connection to the client
110 int _socket;
111
112 public:
113 void complete(jint res, bufferedStream* st);
114
115 void set_socket(int s) { _socket = s; }
116 int socket() const { return _socket; }
117
118 BsdAttachOperation(char* name) : AttachOperation(name) {
119 set_socket(-1);
120 }
121 };
122
123 // statics
124 char BsdAttachListener::_path[UNIX_PATH_MAX];
125 bool BsdAttachListener::_has_path;
126 int BsdAttachListener::_listener = -1;
127
128 // Supporting class to help split a buffer into individual components
129 class ArgumentIterator : public StackObj {
130 private:
131 char* _pos;
132 char* _end;
133 public:
134 ArgumentIterator(char* arg_buffer, size_t arg_size) {
135 _pos = arg_buffer;
136 _end = _pos + arg_size - 1;
137 }
138 char* next() {
139 if (*_pos == '\0') {
140 // advance the iterator if possible (null arguments)
141 if (_pos < _end) {
142 _pos += 1;
143 }
144 return NULL;
145 }
146 char* res = _pos;
147 char* next_pos = strchr(_pos, '\0');
148 if (next_pos < _end) {
149 next_pos++;
150 }
151 _pos = next_pos;
152 return res;
153 }
154 };
155
156
157 // atexit hook to stop listener and unlink the file that it is
158 // bound too.
159 extern "C" {
160 static void listener_cleanup() {
161 static int cleanup_done;
162 if (!cleanup_done) {
163 cleanup_done = 1;
164 int s = BsdAttachListener::listener();
165 if (s != -1) {
166 ::close(s);
167 }
168 if (BsdAttachListener::has_path()) {
169 ::unlink(BsdAttachListener::path());
170 }
171 }
172 }
173 }
174
175 // Initialization - create a listener socket and bind it to a file
176
177 int BsdAttachListener::init() {
178 char path[UNIX_PATH_MAX]; // socket file
179 char initial_path[UNIX_PATH_MAX]; // socket file during setup
180 int listener; // listener socket (file descriptor)
181
182 // register function to cleanup
183 ::atexit(listener_cleanup);
184
185 int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
186 os::get_temp_directory(), os::current_process_id());
187 if (n < (int)UNIX_PATH_MAX) {
188 n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
189 }
190 if (n >= (int)UNIX_PATH_MAX) {
191 return -1;
192 }
193
194 // create the listener socket
195 listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
196 if (listener == -1) {
197 return -1;
198 }
199
200 // bind socket
201 struct sockaddr_un addr;
202 memset((void *)&addr, 0, sizeof(addr));
203 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 = BsdAttachListener::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;
|
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 *
51 // As the socket is a UNIX domain socket it means that only clients on the
52 // local machine can connect. In addition there are two other aspects to
53 // the security:
54 // 1. The well known file that the socket is bound to has permission 400
55 // 2. When a client connect, the SO_PEERCRED socket option is used to
56 // obtain the credentials of client. We check that the effective uid
57 // of the client matches this process.
58
59 // forward reference
60 class BsdAttachOperation;
61
62 class BsdAttachListener: AllStatic {
63 private:
64 // the path to which we bind the UNIX domain socket
65 static char _path[UNIX_PATH_MAX];
66 static bool _has_path;
67
68 // the file descriptor for the listening socket
69 static int _listener;
70
71 static bool _atexit_registered;
72
73 // reads a request from the given connected socket
74 static BsdAttachOperation* read_request(int s);
75
76 public:
77 enum {
78 ATTACH_PROTOCOL_VER = 1 // protocol version
79 };
80 enum {
81 ATTACH_ERROR_BADVERSION = 101 // error codes
82 };
83
84 static void set_path(char* path) {
85 if (path == NULL) {
86 _path[0] = '\0';
87 _has_path = false;
88 } else {
89 strncpy(_path, path, UNIX_PATH_MAX);
90 _path[UNIX_PATH_MAX-1] = '\0';
91 _has_path = true;
92 }
93 }
94
95 static void set_listener(int s) { _listener = s; }
96
97 // initialize the listener, returns 0 if okay
98 static int init();
99
100 static char* path() { return _path; }
101 static bool has_path() { return _has_path; }
102 static int listener() { return _listener; }
103
104 // write the given buffer to a socket
105 static int write_fully(int s, char* buf, int len);
106
107 static BsdAttachOperation* dequeue();
108 };
109
110 class BsdAttachOperation: public AttachOperation {
111 private:
112 // the connection to the client
113 int _socket;
114
115 public:
116 void complete(jint res, bufferedStream* st);
117
118 void set_socket(int s) { _socket = s; }
119 int socket() const { return _socket; }
120
121 BsdAttachOperation(char* name) : AttachOperation(name) {
122 set_socket(-1);
123 }
124 };
125
126 // statics
127 char BsdAttachListener::_path[UNIX_PATH_MAX];
128 bool BsdAttachListener::_has_path;
129 int BsdAttachListener::_listener = -1;
130 bool BsdAttachListener::_atexit_registered = false;
131
132 // Supporting class to help split a buffer into individual components
133 class ArgumentIterator : public StackObj {
134 private:
135 char* _pos;
136 char* _end;
137 public:
138 ArgumentIterator(char* arg_buffer, size_t arg_size) {
139 _pos = arg_buffer;
140 _end = _pos + arg_size - 1;
141 }
142 char* next() {
143 if (*_pos == '\0') {
144 // advance the iterator if possible (null arguments)
145 if (_pos < _end) {
146 _pos += 1;
147 }
148 return NULL;
149 }
150 char* res = _pos;
151 char* next_pos = strchr(_pos, '\0');
152 if (next_pos < _end) {
153 next_pos++;
154 }
155 _pos = next_pos;
156 return res;
157 }
158 };
159
160
161 // atexit hook to stop listener and unlink the file that it is
162 // bound too.
163 extern "C" {
164 static void listener_cleanup() {
165 int s = BsdAttachListener::listener();
166 if (s != -1) {
167 BsdAttachListener::set_listener(-1);
168 ::shutdown(s, SHUT_RDWR);
169 ::close(s);
170 }
171 if (BsdAttachListener::has_path()) {
172 ::unlink(BsdAttachListener::path());
173 BsdAttachListener::set_path(NULL);
174 }
175 }
176 }
177
178 // Initialization - create a listener socket and bind it to a file
179
180 int BsdAttachListener::init() {
181 char path[UNIX_PATH_MAX]; // socket file
182 char initial_path[UNIX_PATH_MAX]; // socket file during setup
183 int listener; // listener socket (file descriptor)
184
185 // register function to cleanup
186 if (!_atexit_registered) {
187 _atexit_registered = true;
188 ::atexit(listener_cleanup);
189 }
190
191 int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
192 os::get_temp_directory(), os::current_process_id());
193 if (n < (int)UNIX_PATH_MAX) {
194 n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
195 }
196 if (n >= (int)UNIX_PATH_MAX) {
197 return -1;
198 }
199
200 // create the listener socket
201 listener = ::socket(PF_UNIX, SOCK_STREAM, 0);
202 if (listener == -1) {
203 return -1;
204 }
205
206 // bind socket
207 struct sockaddr_un addr;
208 memset((void *)&addr, 0, sizeof(addr));
209 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 = BsdAttachListener::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 stat st;
497 ret = stat(BsdAttachListener::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 BsdAttachListener::path());
501
502 listener_cleanup();
503
504 // wait to terminate current attach listener instance...
505
506 while (AttachListener::transit_state(AL_INITIALIZING,
507
508 AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
509 os::naked_yield();
510 }
511 return is_init_trigger();
512 }
513 return false;
514 }
515
516 // Attach Listener is started lazily except in the case when
517 // +ReduseSignalUsage is used
518 bool AttachListener::init_at_startup() {
519 if (ReduceSignalUsage) {
520 return true;
521 } else {
522 return false;
523 }
524 }
525
526 // If the file .attach_pid<pid> exists in the working directory
527 // or /tmp then this is the trigger to start the attach mechanism
528 bool AttachListener::is_init_trigger() {
529 if (init_at_startup() || is_initialized()) {
530 return false; // initialized at startup or already initialized
531 }
532 char fn[PATH_MAX + 1];
533 int ret;
|