summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <>2013-03-13 12:48:43 +0000
committererdgeist <>2013-03-13 12:48:43 +0000
commitd170c239211b5d19b222627b7ee476c1e851895d (patch)
tree400088d45f6d30d4c3ea9e877b5423f20c2a8981
parent84994f9fde1a1e88eeca2d9cb2cebd9160a71d55 (diff)
Make m_flags an enum, set a neutral proctitle if none given, remove ipc pipe atexit() and add an immediate respawn option
-rw-r--r--jaildaemon.c103
1 files changed, 56 insertions, 47 deletions
diff --git a/jaildaemon.c b/jaildaemon.c
index b903fb2..b15a253 100644
--- a/jaildaemon.c
+++ b/jaildaemon.c
@@ -24,13 +24,14 @@
24#define IPC_PACKETSIZE 4096 24#define IPC_PACKETSIZE 4096
25#define MAGIC_EXIT_CODE 42 25#define MAGIC_EXIT_CODE 42
26enum { IAM_DAEMON, IAM_CLIENT, IAM_FORKSLAVE }; 26enum { IAM_DAEMON, IAM_CLIENT, IAM_FORKSLAVE };
27enum { TASK_RESPAWN }; 27enum { TASK_SINGLESHOT, TASK_RESPAWN, TASK_RESPAWN_IMMEDIATE, TASK_RESPAWNING };
28static int g_uds; 28static int g_uds;
29static int g_whoami = IAM_CLIENT; 29static int g_whoami = IAM_CLIENT;
30static int g_fork_slave_fd; 30static int g_fork_slave_fd;
31static char g_ipc_packet[IPC_PACKETSIZE]; 31static char g_ipc_packet[IPC_PACKETSIZE];
32static int * const g_ipc_packet_int = (int*)g_ipc_packet; 32static int * const g_ipc_packet_int = (int*)g_ipc_packet;
33static struct pidfh * g_pidfilehandle; 33static struct pidfh * g_pidfilehandle;
34static char * g_uds_path = "/var/run/jaildaemon.pipe";
34 35
35/* For house keeping a list of all processes we attach to jails (probes), with 36/* For house keeping a list of all processes we attach to jails (probes), with
36 an initial vector size of 128. The vector never shrinks. */ 37 an initial vector size of 128. The vector never shrinks. */
@@ -48,7 +49,7 @@ typedef struct {
48/* Forward declarations */ 49/* Forward declarations */
49static void term_handler( int signal ); 50static void term_handler( int signal );
50static void kill_all_probes( void ); 51static void kill_all_probes( void );
51static void remove_pidfile( void ); 52static void remove_files( void );
52static int check_for_jail( int jid ); 53static int check_for_jail( int jid );
53static int copy_daemontask( daemon_task ** out, daemon_task * const in ); 54static int copy_daemontask( daemon_task ** out, daemon_task * const in );
54static int add_task_to_kqueue( int kq, daemon_task * task_in ); 55static int add_task_to_kqueue( int kq, daemon_task * task_in );
@@ -92,7 +93,8 @@ static void exerr( char * message, ... ) {
92static void usage( char * cmd ) { 93static void usage( char * cmd ) {
93 fprintf( stderr, 94 fprintf( stderr,
94 "%s -D [-ppidfile] [-fipcsockpath]\n" 95 "%s -D [-ppidfile] [-fipcsockpath]\n"
95 "%s -c command -j jid [-t proctitle] [-r]\n", cmd, cmd ); 96 "%s -c command -j jid [-t proctitle] [-rR] [-fipcsockpath]\n",
97 cmd, cmd );
96 exit( 1 ); 98 exit( 1 );
97} 99}
98 100
@@ -195,6 +197,8 @@ static pid_t fork_and_jail( int jid, char * proctitle ) {
195 /* Set proctitle so that jail's pgrep -f can identify the process */ 197 /* Set proctitle so that jail's pgrep -f can identify the process */
196 if( proctitle && *proctitle ) 198 if( proctitle && *proctitle )
197 setproctitle( "%s", proctitle ); 199 setproctitle( "%s", proctitle );
200 else
201 setproctitle( "PROBE" );
198 202
199 /* Throw ourself into the jail */ 203 /* Throw ourself into the jail */
200 if( jail_attach( jid ) ) 204 if( jail_attach( jid ) )
@@ -239,9 +243,9 @@ static int copy_daemontask( daemon_task ** out, daemon_task * const in ) {
239static void fork_and_execve( int kq, daemon_task * t_in ) { 243static void fork_and_execve( int kq, daemon_task * t_in ) {
240 char * shell = "/bin/sh"; 244 char * shell = "/bin/sh";
241 char * envp[] = { "PATH=/bin:/sbin:/usr/bin:/usr/sbin", NULL }; 245 char * envp[] = { "PATH=/bin:/sbin:/usr/bin:/usr/sbin", NULL };
242 pid_t pid; 246 struct kevent ke;
243 247 daemon_task * t;
244 pid = fork(); 248 pid_t pid = fork();
245 249
246 switch( pid ) { 250 switch( pid ) {
247 case -1: 251 case -1:
@@ -259,33 +263,34 @@ static void fork_and_execve( int kq, daemon_task * t_in ) {
259 break; 263 break;
260 default: 264 default:
261 /* If no respawn requested, just let the command finish */ 265 /* If no respawn requested, just let the command finish */
262 if( !(t_in->m_flags & 0x01) ) 266 switch( t_in->m_flags ) {
263 return; 267 case TASK_SINGLESHOT:
264
265 /* else add process to our process watch list, so we get notified,
266 once it finishes to be able to respawn. ("else" to open block) */
267 else {
268 struct kevent ke;
269 daemon_task * t;
270
271 /* Try to take a copy of task struct. If this fails, then only
272 respawn fails. */
273 if( copy_daemontask( &t, t_in ) )
274 return; 268 return;
275 269 case TASK_RESPAWN:
276 /* Signal that this is a process that shall respawn the task 270 /* Try to take a copy of task struct. If this fails,
277 in jail */ 271 then only respawn fails. */
278 t->m_flags |= 0x02; 272 if( copy_daemontask( &t, t_in ) )
279 273 return;
280 memset( &ke, 0, sizeof ke ); 274
281 EV_SET( &ke, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, t ); 275 /* Signal that this is a process that shall respawn
282 if( kevent( kq, &ke, 1, NULL, 0, NULL ) == -1 ) { 276 the task in jail */
283 /* If adding the event fails, get rid of struct */ 277 t->m_flags = TASK_RESPAWNING;
284 warn( "Can not put respawn watcher pid on the kqueue" ); 278
285 free( t->m_commandline ); 279 /* add process to our process watch list, so we get
286 free( t->m_proctitle ); 280 notified, once it finishes to be able to respawn. */
287 free( t ); 281 memset( &ke, 0, sizeof ke );
288 } 282 EV_SET( &ke, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, t );
283 if( kevent( kq, &ke, 1, NULL, 0, NULL ) == -1 ) {
284 /* If adding the event fails, get rid of struct */
285 warn( "Can not put respawn watcher pid on the kqueue" );
286 free( t->m_commandline );
287 free( t->m_proctitle );
288 free( t );
289 }
290 break;
291 case TASK_RESPAWN_IMMEDIATE:
292 add_task_to_kqueue( kq, t_in );
293 break;
289 } 294 }
290 break; 295 break;
291 } 296 }
@@ -302,8 +307,9 @@ static void kill_all_probes( void ) {
302 g_probes = 0; 307 g_probes = 0;
303} 308}
304 309
305static void remove_pidfile( void ) { 310static void remove_files( void ) {
306 pidfile_remove( g_pidfilehandle ); 311 pidfile_remove( g_pidfilehandle );
312 unlink(g_uds_path);
307} 313}
308 314
309static int add_task_to_kqueue( int kq, daemon_task * t_in ) { 315static int add_task_to_kqueue( int kq, daemon_task * t_in ) {
@@ -347,6 +353,7 @@ static int add_task_to_kqueue( int kq, daemon_task * t_in ) {
347 for( i = 0; i < g_probes_size; ++i ) 353 for( i = 0; i < g_probes_size; ++i )
348 if( !g_probes[i] ) { 354 if( !g_probes[i] ) {
349 g_probes[i] = pid; 355 g_probes[i] = pid;
356 /* SUCCESS */
350 return 0; 357 return 0;
351 } 358 }
352 359
@@ -360,10 +367,11 @@ static int add_task_to_kqueue( int kq, daemon_task * t_in ) {
360 probes[g_probes_size] = pid; 367 probes[g_probes_size] = pid;
361 g_probes_size *= 4; 368 g_probes_size *= 4;
362 g_probes = probes; 369 g_probes = probes;
370 /* SUCCESS */
363 return 0; 371 return 0;
364 } 372 }
365 } 373 }
366 374 /* FAIL branch */
367 /* If we added a kevent filter but failed to store the pid for our 375 /* If we added a kevent filter but failed to store the pid for our
368 house keeping, remove the kqueuei filter again (and kill probe) */ 376 house keeping, remove the kqueuei filter again (and kill probe) */
369 EV_SET( &ke, pid, EVFILT_PROC, EV_DELETE, NOTE_EXIT, 0, t ); 377 EV_SET( &ke, pid, EVFILT_PROC, EV_DELETE, NOTE_EXIT, 0, t );
@@ -380,15 +388,15 @@ static int add_task_to_kqueue( int kq, daemon_task * t_in ) {
380 return -1; 388 return -1;
381} 389}
382 390
383/* jaildaemon -D <-ppidfile> <-fipcsockpath> -c command -j jid -t proctitle <-r> 391/* jaildaemon -D [-ppidfile] [-fipcsockpath]
392 jaildaemon -c command -j jid -t proctitle [-rR] [-fipsockpath]
384 */ 393 */
385int main( int argc, char **argv ) { 394int main( int argc, char **argv ) {
386 pid_t second_pid; 395 pid_t second_pid;
387 int kq, i; 396 int kq, i;
388 int o_force_daemon = 0; 397 int o_force_daemon = 0;
389 int o_daemonize = 0, o_jid = -1, o_respawn = 0; 398 int o_daemonize = 0, o_jid = -1, o_respawn = TASK_SINGLESHOT;
390 char *o_command = NULL, *o_pidfile = NULL, *o_proctitle = NULL; 399 char *o_command = NULL, *o_pidfile = NULL, *o_proctitle = NULL;
391 char *o_uds_path = "/var/run/jaildaemon.pipe";
392 struct kevent ke; 400 struct kevent ke;
393 struct sockaddr_un addr; 401 struct sockaddr_un addr;
394 struct sigaction sa; 402 struct sigaction sa;
@@ -401,15 +409,16 @@ int main( int argc, char **argv ) {
401 409
402 i=1; 410 i=1;
403 while(i) { 411 while(i) {
404 switch( getopt( argc, argv, "DFrt:c:j:p:f:" ) ) { 412 switch( getopt( argc, argv, "DFrRt:c:j:p:f:" ) ) {
405 case -1: i=0; break; 413 case -1: i=0; break;
406 case 'D': o_daemonize = 1; break; 414 case 'D': o_daemonize = 1; break;
407 case 'r': o_respawn = 1; break; 415 case 'r': o_respawn = TASK_RESPAWN; break;
416 case 'R': o_respawn = TASK_RESPAWN_IMMEDIATE; break;
408 case 't': o_proctitle = optarg; break; 417 case 't': o_proctitle = optarg; break;
409 case 'c': o_command = optarg; break; 418 case 'c': o_command = optarg; break;
410 case 'j': o_jid = strtol( optarg, 0, 0 ); break; 419 case 'j': o_jid = strtol( optarg, 0, 0 ); break;
411 case 'p': o_pidfile = optarg; break; 420 case 'p': o_pidfile = optarg; break;
412 case 'f': o_uds_path = optarg; break; 421 case 'f': g_uds_path = optarg; break;
413 case 'F': o_force_daemon = 1; break; 422 case 'F': o_force_daemon = 1; break;
414 case '?': usage( argv[0]); exit(0); break; 423 case '?': usage( argv[0]); exit(0); break;
415 } 424 }
@@ -429,14 +438,14 @@ int main( int argc, char **argv ) {
429 438
430 memset(&addr, 0, sizeof(addr)); 439 memset(&addr, 0, sizeof(addr));
431 addr.sun_family = AF_UNIX; 440 addr.sun_family = AF_UNIX;
432 strncpy(addr.sun_path, o_uds_path, sizeof(addr.sun_path)-1); 441 strncpy(addr.sun_path, g_uds_path, sizeof(addr.sun_path)-1);
433 442
434 if( !o_daemonize ) { 443 if( !o_daemonize ) {
435 /* In utility mode try to pipe the request to the daemon already running 444 /* In utility mode try to pipe the request to the daemon already running
436 and exit 445 and exit
437 446
438 Packed packet format: 447 Packed packet format:
439 int m_flags ( 0x01 respawn, 0x02 executing, to be respawned ) 448 int m_flags: SINGLESHOT, RESPAWN, RESPAWN_IMMEDIATE, RESPAWNING
440 int m_jid 449 int m_jid
441 int m_commandline_length 450 int m_commandline_length
442 int m_proctitle_length 451 int m_proctitle_length
@@ -504,8 +513,8 @@ int main( int argc, char **argv ) {
504 g_fork_slave_fd = fork_fork_slave( ); 513 g_fork_slave_fd = fork_fork_slave( );
505 514
506 /* Register pid file remover after fork() so that fork slave wont remove our 515 /* Register pid file remover after fork() so that fork slave wont remove our
507 pid file*/ 516 pid file, also unlink our pipe at exit */
508 atexit( remove_pidfile ); 517 atexit( remove_files );
509 518
510 /* Initialize syslog facilities */ 519 /* Initialize syslog facilities */
511 openlog( "jaildaemon", 0, LOG_DAEMON ); 520 openlog( "jaildaemon", 0, LOG_DAEMON );
@@ -516,7 +525,7 @@ int main( int argc, char **argv ) {
516 525
517 /* Create the unix domain socket to receive commands on, N.B. error goes to 526 /* Create the unix domain socket to receive commands on, N.B. error goes to
518 syslog, now */ 527 syslog, now */
519 unlink(o_uds_path); 528 unlink(g_uds_path);
520 if (bind(g_uds, (struct sockaddr*)&addr, sizeof(addr)) == -1) 529 if (bind(g_uds, (struct sockaddr*)&addr, sizeof(addr)) == -1)
521 exerr( "binding to command channel. Maybe another daemon is running?" ); 530 exerr( "binding to command channel. Maybe another daemon is running?" );
522 531
@@ -585,8 +594,8 @@ int main( int argc, char **argv ) {
585 594
586 /* If this task was watched to respawn a daemon in the jail, 595 /* If this task was watched to respawn a daemon in the jail,
587 do it now */ 596 do it now */
588 if( task->m_flags & 0x02 ) { 597 if( task->m_flags == TASK_RESPAWNING ) {
589 task->m_flags &= ~0x02; 598 task->m_flags = TASK_RESPAWN;
590 add_task_to_kqueue( kq, task ); 599 add_task_to_kqueue( kq, task );
591 600
592 /* If the process exited with the correct magic code, 601 /* If the process exited with the correct magic code,