redmine

Added support of read()/write() signalling (not enabled by default)

@@ -155,3 +155,5 @@ filesz:1M\n\ @@ -155,3 +155,5 @@ filesz:1M\n\
155 #define DEFAULT_GID 65534 155 #define DEFAULT_GID 65534
156 #define DEFAULT_CAPS_INHERIT CI_EMPTY 156 #define DEFAULT_CAPS_INHERIT CI_EMPTY
157 157
  158 +//#define READWRITE_SIGNALLING
  159 +
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 #include "common.h" // ctx.h 20 #include "common.h" // ctx.h
21 #include "ctx.h" // ctx_t 21 #include "ctx.h" // ctx_t
22 #include "error.h" // debug() 22 #include "error.h" // debug()
  23 +#include "syscalls.h" // read_inf()/write_inf()
23 24
24 #ifdef CAPABILITIES_SUPPORT 25 #ifdef CAPABILITIES_SUPPORT
25 # include <pthread.h> // pthread_create() 26 # include <pthread.h> // pthread_create()
@@ -50,6 +51,13 @@ pthread_cond_t pthread_cond_privileged = PTHREAD_COND_INITIALIZER; @@ -50,6 +51,13 @@ pthread_cond_t pthread_cond_privileged = PTHREAD_COND_INITIALIZER;
50 pthread_cond_t pthread_cond_action = PTHREAD_COND_INITIALIZER; 51 pthread_cond_t pthread_cond_action = PTHREAD_COND_INITIALIZER;
51 pthread_cond_t pthread_cond_runner = PTHREAD_COND_INITIALIZER; 52 pthread_cond_t pthread_cond_runner = PTHREAD_COND_INITIALIZER;
52 53
  54 +#ifdef READWRITE_SIGNALLING
  55 +int priv_read_fd;
  56 +int priv_write_fd;
  57 +int nonp_read_fd;
  58 +int nonp_write_fd;
  59 +#endif
  60 +
53 enum privileged_action { 61 enum privileged_action {
54 PA_UNKNOWN = 0, 62 PA_UNKNOWN = 0,
55 63
@@ -326,6 +334,7 @@ int privileged_execvp_check_arguments(struct pa_options *opts, const char *u_fil @@ -326,6 +334,7 @@ int privileged_execvp_check_arguments(struct pa_options *opts, const char *u_fil
326 } 334 }
327 } 335 }
328 336
  337 + i = 0;
329 while (i < opts->permitted_hookfiles) { 338 while (i < opts->permitted_hookfiles) {
330 if (!strcmp(opts->permitted_hookfile[i], u_file)) 339 if (!strcmp(opts->permitted_hookfile[i], u_file))
331 return 0; 340 return 0;
@@ -398,6 +407,9 @@ int pa_setup(struct pa_options *opts, ctx_t *ctx_p, uid_t *exec_uid_p, gid_t *ex @@ -398,6 +407,9 @@ int pa_setup(struct pa_options *opts, ctx_t *ctx_p, uid_t *exec_uid_p, gid_t *ex
398 static int privileged_handler_running = 1; 407 static int privileged_handler_running = 1;
399 void *privileged_handler(void *_ctx_p) 408 void *privileged_handler(void *_ctx_p)
400 { 409 {
  410 +#ifdef READWRITE_SIGNALLING
  411 + char buf[1] = {0};
  412 +#endif
401 int setup = 0; 413 int setup = 0;
402 ctx_t *ctx_p = _ctx_p; 414 ctx_t *ctx_p = _ctx_p;
403 uid_t exec_uid = 65535; 415 uid_t exec_uid = 65535;
@@ -421,10 +433,18 @@ void *privileged_handler(void *_ctx_p) @@ -421,10 +433,18 @@ void *privileged_handler(void *_ctx_p)
421 debug(2, "Running the loop"); 433 debug(2, "Running the loop");
422 while (privileged_handler_running) { 434 while (privileged_handler_running) {
423 // Waiting for command 435 // Waiting for command
  436 +#ifdef _DEBUG_FORCE
424 debug(3, "Waiting for command", cmd.action); 437 debug(3, "Waiting for command", cmd.action);
  438 +#endif
  439 +#ifdef READWRITE_SIGNALLING
  440 + read_inf(priv_read_fd, buf, 1);
  441 +#else
425 pthread_cond_wait(&pthread_cond_privileged, &pthread_mutex_privileged); 442 pthread_cond_wait(&pthread_cond_privileged, &pthread_mutex_privileged);
  443 +#endif
426 444
  445 +#ifdef _DEBUG_FORCE
427 debug(3, "Got command %u", cmd.action); 446 debug(3, "Got command %u", cmd.action);
  447 +#endif
428 448
429 if (!setup && cmd.action != PA_SETUP) 449 if (!setup && cmd.action != PA_SETUP)
430 critical("A try to use commands before PA_SETUP"); 450 critical("A try to use commands before PA_SETUP");
@@ -501,10 +521,16 @@ void *privileged_handler(void *_ctx_p) @@ -501,10 +521,16 @@ void *privileged_handler(void *_ctx_p)
501 } 521 }
502 522
503 cmd._errno = errno; 523 cmd._errno = errno;
  524 +#ifdef _DEBUG_FORCE
504 debug(3, "Result: %p, errno: %u. Sending the signal to non-privileged thread.", cmd.ret, cmd._errno); 525 debug(3, "Result: %p, errno: %u. Sending the signal to non-privileged thread.", cmd.ret, cmd._errno);
  526 +#endif
  527 +#ifdef READWRITE_SIGNALLING
  528 + write_inf(nonp_write_fd, buf, 1);
  529 +#else
505 pthread_mutex_lock(&pthread_mutex_action_signal); 530 pthread_mutex_lock(&pthread_mutex_action_signal);
506 pthread_mutex_unlock(&pthread_mutex_action_signal); 531 pthread_mutex_unlock(&pthread_mutex_action_signal);
507 pthread_cond_signal(&pthread_cond_action); 532 pthread_cond_signal(&pthread_cond_action);
  533 +#endif
508 } 534 }
509 535
510 pthread_mutex_unlock(&pthread_mutex_privileged); 536 pthread_mutex_unlock(&pthread_mutex_privileged);
@@ -512,39 +538,62 @@ void *privileged_handler(void *_ctx_p) @@ -512,39 +538,62 @@ void *privileged_handler(void *_ctx_p)
512 return 0; 538 return 0;
513 } 539 }
514 540
515 -int privileged_action( 541 +static inline int privileged_action(
516 enum privileged_action action, 542 enum privileged_action action,
517 void *arg, 543 void *arg,
518 void **ret_p 544 void **ret_p
519 ) 545 )
520 { 546 {
  547 +#ifdef READWRITE_SIGNALLING
  548 + char buf[1] = {0};
  549 +#endif
  550 +#ifdef _DEBUG_FORCE
521 debug(3, "(%u, %p, %p)", action, arg, ret_p); 551 debug(3, "(%u, %p, %p)", action, arg, ret_p);
  552 +#endif
522 553
523 pthread_mutex_lock(&pthread_mutex_action_entrance); 554 pthread_mutex_lock(&pthread_mutex_action_entrance);
  555 +#ifndef READWRITE_SIGNALLING
524 pthread_mutex_lock(&pthread_mutex_action_signal); 556 pthread_mutex_lock(&pthread_mutex_action_signal);
525 557
526 debug(4, "Waiting the privileged thread to get prepared for signal"); 558 debug(4, "Waiting the privileged thread to get prepared for signal");
527 pthread_mutex_lock(&pthread_mutex_privileged); 559 pthread_mutex_lock(&pthread_mutex_privileged);
528 pthread_mutex_unlock(&pthread_mutex_privileged); 560 pthread_mutex_unlock(&pthread_mutex_privileged);
529 - 561 +#endif
530 if (!privileged_handler_running) { 562 if (!privileged_handler_running) {
531 debug(1, "The privileged thread is dead. Ignoring the command."); 563 debug(1, "The privileged thread is dead. Ignoring the command.");
532 return ENOENT; 564 return ENOENT;
533 } 565 }
534 566
  567 +#ifdef _DEBUG_FORCE
535 debug(4, "Sending information to the privileged thread"); 568 debug(4, "Sending information to the privileged thread");
  569 +#endif
536 cmd.action = action; 570 cmd.action = action;
537 cmd.arg = arg; 571 cmd.arg = arg;
  572 +#ifdef READWRITE_SIGNALLING
  573 + write_inf(priv_write_fd, buf, 1);
  574 +#else
538 pthread_cond_signal(&pthread_cond_privileged); 575 pthread_cond_signal(&pthread_cond_privileged);
  576 +#endif
539 577
  578 +#ifdef _DEBUG_FORCE
540 debug(4, "Waiting for the answer"); 579 debug(4, "Waiting for the answer");
  580 +#endif
  581 +#ifdef READWRITE_SIGNALLING
  582 + read_inf(nonp_read_fd, buf, 1);
  583 +#else
541 pthread_cond_wait (&pthread_cond_action, &pthread_mutex_action_signal); 584 pthread_cond_wait (&pthread_cond_action, &pthread_mutex_action_signal);
  585 +#endif
  586 +
542 if (ret_p != NULL) 587 if (ret_p != NULL)
543 *ret_p = cmd.ret; 588 *ret_p = cmd.ret;
544 errno = cmd._errno; 589 errno = cmd._errno;
545 590
  591 +#ifdef _DEBUG_FORCE
546 debug(4, "Unlocking pthread_mutex_action_*"); 592 debug(4, "Unlocking pthread_mutex_action_*");
  593 +#endif
  594 +#ifndef READWRITE_SIGNALLING
547 pthread_mutex_unlock(&pthread_mutex_action_signal); 595 pthread_mutex_unlock(&pthread_mutex_action_signal);
  596 +#endif
548 pthread_mutex_unlock(&pthread_mutex_action_entrance); 597 pthread_mutex_unlock(&pthread_mutex_action_entrance);
549 598
550 return 0; 599 return 0;
@@ -677,7 +726,9 @@ int _privileged_fork_execvp(const char *file, char *const argv[]) @@ -677,7 +726,9 @@ int _privileged_fork_execvp(const char *file, char *const argv[])
677 726
678 int privileged_init(ctx_t *ctx_p) 727 int privileged_init(ctx_t *ctx_p)
679 { 728 {
  729 +#ifdef READWRITE_SIGNALLING
680 int pipefds[2]; 730 int pipefds[2];
  731 +#endif
681 732
682 #ifdef CAPABILITIES_SUPPORT 733 #ifdef CAPABILITIES_SUPPORT
683 if (!ctx_p->flags[THREADSPLITTING]) { 734 if (!ctx_p->flags[THREADSPLITTING]) {
@@ -725,17 +776,25 @@ int privileged_init(ctx_t *ctx_p) @@ -725,17 +776,25 @@ int privileged_init(ctx_t *ctx_p)
725 SAFE ( pthread_cond_init (&pthread_cond_action, NULL), return errno;); 776 SAFE ( pthread_cond_init (&pthread_cond_action, NULL), return errno;);
726 SAFE ( pthread_cond_init (&pthread_cond_runner, NULL), return errno;); 777 SAFE ( pthread_cond_init (&pthread_cond_runner, NULL), return errno;);
727 778
  779 +#ifdef READWRITE_SIGNALLING
728 SAFE ( pipe2(pipefds, O_CLOEXEC), return errno;); 780 SAFE ( pipe2(pipefds, O_CLOEXEC), return errno;);
  781 + priv_read_fd = pipefds[0];
  782 + priv_write_fd = pipefds[1];
  783 +
  784 + SAFE ( pipe2(pipefds, O_CLOEXEC), return errno;);
  785 + nonp_read_fd = pipefds[0];
  786 + nonp_write_fd = pipefds[1];
  787 +#endif
729 788
730 SAFE ( pthread_mutex_lock(&pthread_mutex_runner), return errno;); 789 SAFE ( pthread_mutex_lock(&pthread_mutex_runner), return errno;);
731 790
732 SAFE ( pthread_create(&pthread_thread, NULL, (void *(*)(void *))privileged_handler, ctx_p), return errno); 791 SAFE ( pthread_create(&pthread_thread, NULL, (void *(*)(void *))privileged_handler, ctx_p), return errno);
733 792
734 if (ctx_p->flags[DETACH_NETWORK] == DN_NONPRIVILEGED) { 793 if (ctx_p->flags[DETACH_NETWORK] == DN_NONPRIVILEGED) {
735 - cap_enable(CAP_TO_MASK(CAP_SYS_ADMIN)); 794 + SAFE ( cap_enable(CAP_TO_MASK(CAP_SYS_ADMIN)), return errno; );
736 - SAFE (unshare(CLONE_NEWNET), return errno); 795 + SAFE ( unshare(CLONE_NEWNET), return errno; );
737 } 796 }
738 - cap_drop(ctx_p, 0); 797 + SAFE ( cap_drop(ctx_p, 0), return errno; );
739 798
740 debug(4, "Waiting for the privileged thread to get prepared"); 799 debug(4, "Waiting for the privileged thread to get prepared");
741 pthread_cond_wait(&pthread_cond_runner, &pthread_mutex_runner); 800 pthread_cond_wait(&pthread_cond_runner, &pthread_mutex_runner);
@@ -19,3 +19,25 @@ @@ -19,3 +19,25 @@
19 19
20 extern int pivot_root(const char *new_root, const char *old_root); 20 extern int pivot_root(const char *new_root, const char *old_root);
21 21
  22 +static inline ssize_t read_inf(int fd, void *buf, size_t count) {
  23 + ssize_t ret;
  24 +
  25 + errno = 0;
  26 + do {
  27 + ret = read(fd, buf, count);
  28 + } while ((ret == -1) && (errno == EINTR));
  29 +
  30 + return ret;
  31 +}
  32 +
  33 +static inline ssize_t write_inf(int fd, const void *buf, size_t count) {
  34 + ssize_t ret;
  35 +
  36 + errno = 0;
  37 + do {
  38 + ret = write(fd, buf, count);
  39 + } while ((ret == -1) && (errno == EINTR));
  40 +
  41 + return ret;
  42 +}
  43 +