Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : process model: standard (1 process per client connection)
5 :
6 : Copyright (C) Andrew Tridgell 1992-2005
7 : Copyright (C) James J Myers 2003 <myersjj@samba.org>
8 : Copyright (C) Stefan (metze) Metzmacher 2004
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include "lib/events/events.h"
26 : #include "samba/process_model.h"
27 : #include "system/filesys.h"
28 : #include "cluster/cluster.h"
29 : #include "param/param.h"
30 : #include "ldb_wrap.h"
31 : #include "lib/messaging/messaging.h"
32 : #include "lib/util/debug.h"
33 : #include "lib/messaging/messages_dgm.h"
34 : #include "lib/util/util_process.h"
35 :
36 : static unsigned connections_active = 0;
37 : static unsigned smbd_max_processes = 0;
38 :
39 : struct standard_child_state {
40 : const char *name;
41 : pid_t pid;
42 : int to_parent_fd;
43 : int from_child_fd;
44 : struct tevent_fd *from_child_fde;
45 : };
46 :
47 : NTSTATUS process_model_standard_init(TALLOC_CTX *);
48 : struct process_context {
49 : char *name;
50 : int from_parent_fd;
51 : bool inhibit_fork_on_accept;
52 : bool forked_on_accept;
53 : };
54 :
55 : /*
56 : called when the process model is selected
57 : */
58 30 : static void standard_model_init(void)
59 : {
60 30 : }
61 :
62 0 : static void sighup_signal_handler(struct tevent_context *ev,
63 : struct tevent_signal *se,
64 : int signum, int count, void *siginfo,
65 : void *private_data)
66 : {
67 0 : debug_schedule_reopen_logs();
68 0 : }
69 :
70 0 : static void sigterm_signal_handler(struct tevent_context *ev,
71 : struct tevent_signal *se,
72 : int signum, int count, void *siginfo,
73 : void *private_data)
74 : {
75 : #ifdef HAVE_GETPGRP
76 0 : if (getpgrp() == getpid()) {
77 : /*
78 : * We're the process group leader, send
79 : * SIGTERM to our process group.
80 : */
81 0 : DBG_ERR("SIGTERM: killing children\n");
82 0 : kill(-getpgrp(), SIGTERM);
83 : }
84 : #endif
85 0 : DBG_ERR("Exiting pid %u on SIGTERM\n", (unsigned int)getpid());
86 0 : talloc_free(ev);
87 0 : exit(127);
88 : }
89 :
90 : /*
91 : handle EOF on the parent-to-all-children pipe in the child
92 : */
93 386 : static void standard_pipe_handler(struct tevent_context *event_ctx, struct tevent_fd *fde,
94 : uint16_t flags, void *private_data)
95 : {
96 386 : DBG_DEBUG("Child %d exiting\n", (int)getpid());
97 386 : talloc_free(event_ctx);
98 386 : exit(0);
99 : }
100 :
101 : /*
102 : handle EOF on the child pipe in the parent, so we know when a
103 : process terminates without using SIGCHLD or waiting on all possible pids.
104 :
105 : We need to ensure we do not ignore SIGCHLD because we need it to
106 : work to get a valid error code from samba_runcmd_*().
107 : */
108 12858 : static void standard_child_pipe_handler(struct tevent_context *ev,
109 : struct tevent_fd *fde,
110 : uint16_t flags,
111 : void *private_data)
112 : {
113 8248 : struct standard_child_state *state
114 4610 : = talloc_get_type_abort(private_data, struct standard_child_state);
115 12858 : int status = 0;
116 : pid_t pid;
117 :
118 12858 : messaging_dgm_cleanup(state->pid);
119 :
120 : /* the child has closed the pipe, assume its dead */
121 12858 : errno = 0;
122 12858 : pid = waitpid(state->pid, &status, 0);
123 :
124 12858 : if (pid != state->pid) {
125 0 : if (errno == ECHILD) {
126 : /*
127 : * this happens when the
128 : * parent has set SIGCHLD to
129 : * SIG_IGN. In that case we
130 : * can only get error
131 : * information for the child
132 : * via its logging. We should
133 : * stop using SIG_IGN on
134 : * SIGCHLD in the standard
135 : * process model.
136 : */
137 0 : DBG_ERR("Error in waitpid() unexpectedly got ECHILD "
138 : "for child %d (%s) - %s, someone has set SIGCHLD "
139 : "to SIG_IGN!\n",
140 : (int)state->pid, state->name,
141 : strerror(errno));
142 0 : TALLOC_FREE(state);
143 0 : return;
144 : }
145 0 : DBG_ERR("Error in waitpid() for child %d (%s) - %s \n",
146 : (int)state->pid, state->name, strerror(errno));
147 0 : if (errno == 0) {
148 0 : errno = ECHILD;
149 : }
150 0 : goto done;
151 : }
152 12858 : if (WIFEXITED(status)) {
153 12858 : status = WEXITSTATUS(status);
154 12858 : if (status != 0) {
155 0 : DBG_ERR("Child %d (%s) exited with status %d\n",
156 : (int)state->pid, state->name, status);
157 : }
158 0 : } else if (WIFSIGNALED(status)) {
159 0 : status = WTERMSIG(status);
160 0 : DBG_ERR("Child %d (%s) terminated with signal %d\n",
161 : (int)state->pid, state->name, status);
162 : }
163 8248 : done:
164 12858 : TALLOC_FREE(state);
165 12858 : if (smbd_max_processes > 0) {
166 21 : if (connections_active < 1) {
167 0 : DBG_ERR("Number of active connections "
168 : "less than 1 (%d)\n",
169 : connections_active);
170 0 : connections_active = 1;
171 : }
172 21 : connections_active--;
173 : }
174 12858 : return;
175 : }
176 :
177 13265 : static struct standard_child_state *setup_standard_child_pipe(struct tevent_context *ev,
178 : const char *name)
179 : {
180 : struct standard_child_state *state;
181 : int parent_child_pipe[2];
182 : int ret;
183 :
184 : /*
185 : * Prepare a pipe to allow us to know when the child exits,
186 : * because it will trigger a read event on this private
187 : * pipe.
188 : *
189 : * We do all this before the accept and fork(), so we can
190 : * clean up if it fails.
191 : */
192 13265 : state = talloc_zero(ev, struct standard_child_state);
193 13265 : if (state == NULL) {
194 0 : return NULL;
195 : }
196 :
197 13265 : if (name == NULL) {
198 12845 : name = "";
199 : }
200 :
201 13265 : state->name = talloc_strdup(state, name);
202 13265 : if (state->name == NULL) {
203 0 : TALLOC_FREE(state);
204 0 : return NULL;
205 : }
206 :
207 13265 : ret = pipe(parent_child_pipe);
208 13265 : if (ret == -1) {
209 0 : DBG_ERR("Failed to create parent-child pipe to handle "
210 : "SIGCHLD to track new process for socket\n");
211 0 : TALLOC_FREE(state);
212 0 : return NULL;
213 : }
214 :
215 13265 : smb_set_close_on_exec(parent_child_pipe[0]);
216 13265 : smb_set_close_on_exec(parent_child_pipe[1]);
217 :
218 13265 : state->from_child_fd = parent_child_pipe[0];
219 13265 : state->to_parent_fd = parent_child_pipe[1];
220 :
221 : /*
222 : * The basic purpose of calling this handler is to ensure we
223 : * call waitpid() and so avoid zombies (now that we no longer
224 : * user SIGIGN on for SIGCHLD), but it also allows us to clean
225 : * up other resources in the future.
226 : */
227 13265 : state->from_child_fde = tevent_add_fd(ev, state,
228 : state->from_child_fd,
229 : TEVENT_FD_READ,
230 : standard_child_pipe_handler,
231 : state);
232 13265 : if (state->from_child_fde == NULL) {
233 0 : TALLOC_FREE(state);
234 0 : return NULL;
235 : }
236 13265 : tevent_fd_set_auto_close(state->from_child_fde);
237 :
238 13265 : return state;
239 : }
240 :
241 : /*
242 : called when a listening socket becomes readable.
243 : */
244 49842 : static void standard_accept_connection(
245 : struct tevent_context *ev,
246 : struct loadparm_context *lp_ctx,
247 : struct socket_context *sock,
248 : void (*new_conn)(struct tevent_context *,
249 : struct loadparm_context *,
250 : struct socket_context *,
251 : struct server_id,
252 : void *,
253 : void *),
254 : void *private_data,
255 : void *process_context)
256 : {
257 : NTSTATUS status;
258 : struct socket_context *sock2;
259 : pid_t pid;
260 : struct socket_address *c, *s;
261 : struct standard_child_state *state;
262 49842 : struct tevent_fd *fde = NULL;
263 49842 : struct tevent_signal *se = NULL;
264 49842 : struct process_context *proc_ctx = NULL;
265 :
266 :
267 : /* accept an incoming connection. */
268 49842 : status = socket_accept(sock, &sock2);
269 49842 : if (!NT_STATUS_IS_OK(status)) {
270 0 : DBG_DEBUG("standard_accept_connection: accept: %s\n",
271 : nt_errstr(status));
272 : /* this looks strange, but is correct. We need to throttle
273 : * things until the system clears enough resources to handle
274 : * this new socket
275 : */
276 0 : sleep(1);
277 0 : return;
278 : }
279 :
280 49842 : proc_ctx = talloc_get_type_abort(process_context,
281 : struct process_context);
282 :
283 49842 : if (proc_ctx->inhibit_fork_on_accept) {
284 36996 : pid = getpid();
285 : /*
286 : * Service does not support forking a new process on a
287 : * new connection, either it's maintaining shared
288 : * state or the overhead of forking a new process is a
289 : * significant fraction of the response time.
290 : */
291 36996 : talloc_steal(private_data, sock2);
292 36996 : new_conn(ev, lp_ctx, sock2,
293 36996 : cluster_id(pid, socket_get_fd(sock2)), private_data,
294 : process_context);
295 36996 : return;
296 : }
297 :
298 12846 : if (smbd_max_processes > 0) {
299 22 : if (connections_active >= smbd_max_processes) {
300 1 : DBG_ERR("(%d) connections already active, "
301 : "maximum is (%d). Dropping request\n",
302 : connections_active,
303 : smbd_max_processes);
304 : /*
305 : * Drop the connection as we're overloaded at the moment
306 : */
307 1 : talloc_free(sock2);
308 1 : return;
309 : }
310 21 : connections_active++;
311 : }
312 :
313 12845 : state = setup_standard_child_pipe(ev, NULL);
314 12845 : if (state == NULL) {
315 0 : return;
316 : }
317 12845 : pid = fork();
318 :
319 25690 : if (pid != 0) {
320 12845 : close(state->to_parent_fd);
321 12845 : state->to_parent_fd = -1;
322 :
323 12845 : if (pid > 0) {
324 12845 : state->pid = pid;
325 : } else {
326 0 : TALLOC_FREE(state);
327 : }
328 :
329 : /* parent or error code ... */
330 12845 : talloc_free(sock2);
331 : /* go back to the event loop */
332 12845 : return;
333 : }
334 :
335 : /* this leaves state->to_parent_fd open */
336 12845 : TALLOC_FREE(state);
337 :
338 : /* Now in the child code so indicate that we forked
339 : * so the terminate code knows what to do
340 : */
341 12845 : proc_ctx->forked_on_accept = true;
342 :
343 12845 : pid = getpid();
344 12845 : setproctitle("task[%s] standard worker", proc_ctx->name);
345 :
346 : /*
347 : * We must fit within 15 chars of text or we will truncate, so
348 : * we put the constant part last
349 : */
350 12845 : prctl_set_comment("%s[work]", proc_ctx->name);
351 :
352 : /* This is now the child code. We need a completely new event_context to work with */
353 :
354 12845 : if (tevent_re_initialise(ev) != 0) {
355 0 : smb_panic("Failed to re-initialise tevent after fork");
356 : }
357 :
358 : /* this will free all the listening sockets and all state that
359 : is not associated with this new connection */
360 12845 : talloc_free(sock);
361 :
362 : /* we don't care if the dup fails, as its only a select()
363 : speed optimisation */
364 12845 : socket_dup(sock2);
365 :
366 : /* tdb needs special fork handling */
367 12845 : ldb_wrap_fork_hook();
368 :
369 : /* Must be done after a fork() to reset messaging contexts. */
370 12845 : status = imessaging_reinit_all();
371 12845 : if (!NT_STATUS_IS_OK(status)) {
372 0 : smb_panic("Failed to re-initialise imessaging after fork");
373 : }
374 :
375 12845 : fde = tevent_add_fd(ev, ev, proc_ctx->from_parent_fd, TEVENT_FD_READ,
376 : standard_pipe_handler, NULL);
377 12845 : if (fde == NULL) {
378 0 : smb_panic("Failed to add fd handler after fork");
379 : }
380 :
381 12845 : se = tevent_add_signal(ev,
382 : ev,
383 : SIGHUP,
384 : 0,
385 : sighup_signal_handler,
386 : NULL);
387 12845 : if (se == NULL) {
388 0 : smb_panic("Failed to add SIGHUP handler after fork");
389 : }
390 :
391 12845 : se = tevent_add_signal(ev,
392 : ev,
393 : SIGTERM,
394 : 0,
395 : sigterm_signal_handler,
396 : NULL);
397 12845 : if (se == NULL) {
398 0 : smb_panic("Failed to add SIGTERM handler after fork");
399 : }
400 :
401 : /* setup the process title */
402 12845 : c = socket_get_peer_addr(sock2, ev);
403 12845 : s = socket_get_my_addr(sock2, ev);
404 12845 : if (s && c) {
405 12845 : setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]",
406 : c->addr, c->port, s->addr, s->port, (int)pid);
407 : }
408 12845 : talloc_free(c);
409 12845 : talloc_free(s);
410 :
411 12845 : force_check_log_size();
412 :
413 : /* setup this new connection. Cluster ID is PID based for this process model */
414 12845 : new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data,
415 : process_context);
416 :
417 : /* we can't return to the top level here, as that event context is gone,
418 : so we now process events in the new event context until there are no
419 : more to process */
420 12845 : tevent_loop_wait(ev);
421 :
422 0 : talloc_free(ev);
423 0 : exit(0);
424 : }
425 :
426 : /*
427 : called to create a new server task
428 : */
429 420 : static void standard_new_task(struct tevent_context *ev,
430 : struct loadparm_context *lp_ctx,
431 : const char *service_name,
432 : struct task_server *(*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *, void *),
433 : void *private_data,
434 : const struct service_details *service_details,
435 : int from_parent_fd)
436 : {
437 : pid_t pid;
438 : NTSTATUS status;
439 : struct standard_child_state *state;
440 420 : struct tevent_fd *fde = NULL;
441 420 : struct tevent_signal *se = NULL;
442 420 : struct process_context *proc_ctx = NULL;
443 420 : struct task_server* task = NULL;
444 :
445 420 : state = setup_standard_child_pipe(ev, service_name);
446 420 : if (state == NULL) {
447 0 : return;
448 : }
449 :
450 420 : pid = fork();
451 :
452 840 : if (pid != 0) {
453 420 : close(state->to_parent_fd);
454 420 : state->to_parent_fd = -1;
455 :
456 420 : if (pid > 0) {
457 420 : state->pid = pid;
458 : } else {
459 0 : TALLOC_FREE(state);
460 : }
461 :
462 : /* parent or error code ... go back to the event loop */
463 420 : return;
464 : }
465 :
466 : /* this leaves state->to_parent_fd open */
467 420 : TALLOC_FREE(state);
468 :
469 420 : pid = getpid();
470 :
471 : /* this will free all the listening sockets and all state that
472 : is not associated with this new connection */
473 420 : if (tevent_re_initialise(ev) != 0) {
474 0 : smb_panic("Failed to re-initialise tevent after fork");
475 : }
476 :
477 : /* ldb/tdb need special fork handling */
478 420 : ldb_wrap_fork_hook();
479 :
480 : /* Must be done after a fork() to reset messaging contexts. */
481 420 : status = imessaging_reinit_all();
482 420 : if (!NT_STATUS_IS_OK(status)) {
483 0 : smb_panic("Failed to re-initialise imessaging after fork");
484 : }
485 :
486 420 : fde = tevent_add_fd(ev, ev, from_parent_fd, TEVENT_FD_READ,
487 : standard_pipe_handler, NULL);
488 420 : if (fde == NULL) {
489 0 : smb_panic("Failed to add fd handler after fork");
490 : }
491 :
492 420 : se = tevent_add_signal(ev,
493 : ev,
494 : SIGHUP,
495 : 0,
496 : sighup_signal_handler,
497 : NULL);
498 420 : if (se == NULL) {
499 0 : smb_panic("Failed to add SIGHUP handler after fork");
500 : }
501 :
502 420 : se = tevent_add_signal(ev,
503 : ev,
504 : SIGTERM,
505 : 0,
506 : sigterm_signal_handler,
507 : NULL);
508 420 : if (se == NULL) {
509 0 : smb_panic("Failed to add SIGTERM handler after fork");
510 : }
511 :
512 420 : setproctitle("task[%s]", service_name);
513 : /*
514 : * We must fit within 15 chars of text or we will truncate, so
515 : * we put the constant part last
516 : */
517 420 : prctl_set_comment("%s[task]", service_name);
518 :
519 420 : force_check_log_size();
520 :
521 : /*
522 : * Set up the process context to be passed through to the terminate
523 : * and accept_connection functions
524 : */
525 420 : proc_ctx = talloc(ev, struct process_context);
526 420 : proc_ctx->name = talloc_strdup(ev, service_name);
527 420 : proc_ctx->from_parent_fd = from_parent_fd;
528 420 : proc_ctx->inhibit_fork_on_accept =
529 420 : service_details->inhibit_fork_on_accept;
530 420 : proc_ctx->forked_on_accept = false;
531 :
532 420 : smbd_max_processes = lpcfg_max_smbd_processes(lp_ctx);
533 :
534 : /* setup this new task. Cluster ID is PID based for this process model */
535 420 : task = new_task(ev, lp_ctx, cluster_id(pid, 0), private_data, proc_ctx);
536 : /*
537 : * Currently we don't support the post_fork functionality in the
538 : * standard model, i.e. it is only called here not after a new process
539 : * is forked in standard_accept_connection.
540 : */
541 378 : if (task != NULL && service_details->post_fork != NULL) {
542 70 : struct process_details pd = initial_process_details;
543 70 : service_details->post_fork(task, &pd);
544 : }
545 :
546 :
547 : /* we can't return to the top level here, as that event context is gone,
548 : so we now process events in the new event context until there are no
549 : more to process */
550 378 : tevent_loop_wait(ev);
551 :
552 0 : talloc_free(ev);
553 0 : exit(0);
554 : }
555 :
556 :
557 : /* called when a task goes down */
558 42 : static void standard_terminate_task(struct tevent_context *ev,
559 : struct loadparm_context *lp_ctx,
560 : const char *reason,
561 : bool fatal,
562 : void *process_context)
563 : {
564 42 : if (fatal == true) {
565 0 : exit(127);
566 : }
567 42 : exit(0);
568 : }
569 :
570 : /* called when a connection terminates*/
571 49830 : static void standard_terminate_connection(struct tevent_context *ev,
572 : struct loadparm_context *lp_ctx,
573 : const char *reason,
574 : void *process_context)
575 : {
576 49830 : struct process_context *proc_ctx = NULL;
577 :
578 49830 : DBG_DEBUG("connection terminating reason[%s]\n", reason);
579 49830 : if (process_context == NULL) {
580 0 : smb_panic("Panicking process_context is NULL");
581 : }
582 :
583 49830 : proc_ctx = talloc_get_type(process_context, struct process_context);
584 49830 : if (proc_ctx->forked_on_accept == false) {
585 : /*
586 : * The current task was not forked on accept, so it needs to
587 : * keep running and process requests from other connections
588 : */
589 73591 : return;
590 : }
591 : /*
592 : * The current process was forked on accept to handle a single
593 : * connection/request. That request has now finished and the process
594 : * should terminate
595 : */
596 :
597 : /* this reload_charcnv() has the effect of freeing the iconv context memory,
598 : which makes leak checking easier */
599 12837 : reload_charcnv(lp_ctx);
600 :
601 : /* Always free event context last before exit. */
602 12837 : talloc_free(ev);
603 :
604 : /* terminate this process */
605 12837 : exit(0);
606 : }
607 : /* called to set a title of a task or connection */
608 50216 : static void standard_set_title(struct tevent_context *ev, const char *title)
609 : {
610 50216 : if (title) {
611 50216 : setproctitle("%s", title);
612 : } else {
613 0 : setproctitle(NULL);
614 : }
615 50216 : }
616 :
617 : static const struct model_ops standard_ops = {
618 : .name = "standard",
619 : .model_init = standard_model_init,
620 : .accept_connection = standard_accept_connection,
621 : .new_task = standard_new_task,
622 : .terminate_task = standard_terminate_task,
623 : .terminate_connection = standard_terminate_connection,
624 : .set_title = standard_set_title,
625 : };
626 :
627 : /*
628 : initialise the standard process model, registering ourselves with the process model subsystem
629 : */
630 55 : NTSTATUS process_model_standard_init(TALLOC_CTX *ctx)
631 : {
632 55 : return register_process_model(&standard_ops);
633 : }
|