28#ifdef CAPABILITIES_SUPPORT
30# include <sys/inotify.h>
31# include <sys/types.h>
35# include <sys/capability.h>
49# ifdef HL_LOCK_TRIES_AUTO
50# undef HL_LOCK_TRIES_AUTO
54#ifdef HL_LOCK_TRIES_AUTO
63# include <sys/prctl.h>
64# include <linux/filter.h>
65# include <linux/seccomp.h>
69# warning [security] Caution! __NR_shmdt is not defined. Setting it to -222.
70# define __NR_shmdt -222
75# define syscall_nr (offsetof(struct seccomp_data, nr))
78# define SECCOMP_COPY_SYSCALL_TO_ACCUM \
79 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr)
81# define SECCOMP_ALLOW \
82 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
84# define SECCOMP_DENY \
85 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP)
87# define SECCOMP_ALLOW_ACCUM_SYSCALL(syscall) \
88 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##syscall, 0, 1), \
91# define FILTER_TABLE_NONPRIV \
92 SECCOMP_ALLOW_ACCUM_SYSCALL(futex), \
93 SECCOMP_ALLOW_ACCUM_SYSCALL(inotify_init1), \
94 SECCOMP_ALLOW_ACCUM_SYSCALL(alarm), \
95 SECCOMP_ALLOW_ACCUM_SYSCALL(open), \
96 SECCOMP_ALLOW_ACCUM_SYSCALL(write), \
97 SECCOMP_ALLOW_ACCUM_SYSCALL(close), \
98 SECCOMP_ALLOW_ACCUM_SYSCALL(wait4), \
99 SECCOMP_ALLOW_ACCUM_SYSCALL(unlink), \
100 SECCOMP_ALLOW_ACCUM_SYSCALL(tgkill), \
101 SECCOMP_ALLOW_ACCUM_SYSCALL(rt_sigreturn), \
102 SECCOMP_ALLOW_ACCUM_SYSCALL(brk), \
103 SECCOMP_ALLOW_ACCUM_SYSCALL(munmap), \
104 SECCOMP_ALLOW_ACCUM_SYSCALL(wait4), \
105 SECCOMP_ALLOW_ACCUM_SYSCALL(rmdir), \
106 SECCOMP_ALLOW_ACCUM_SYSCALL(exit_group), \
107 SECCOMP_ALLOW_ACCUM_SYSCALL(select), \
108 SECCOMP_ALLOW_ACCUM_SYSCALL(read), \
109 SECCOMP_ALLOW_ACCUM_SYSCALL(rt_sigprocmask), \
110 SECCOMP_ALLOW_ACCUM_SYSCALL(rt_sigaction), \
111 SECCOMP_ALLOW_ACCUM_SYSCALL(nanosleep), \
112 SECCOMP_ALLOW_ACCUM_SYSCALL(shmdt), \
113 SECCOMP_ALLOW_ACCUM_SYSCALL(clone), \
114 SECCOMP_ALLOW_ACCUM_SYSCALL(set_robust_list), \
115 SECCOMP_ALLOW_ACCUM_SYSCALL(madvise), \
116 SECCOMP_ALLOW_ACCUM_SYSCALL(exit), \
117 SECCOMP_ALLOW_ACCUM_SYSCALL(clock_gettime), \
120# define FILTER_TABLE_ARCHDEPENDED \
121 SECCOMP_ALLOW_ACCUM_SYSCALL(fstat64), \
122 SECCOMP_ALLOW_ACCUM_SYSCALL(lstat64), \
123 SECCOMP_ALLOW_ACCUM_SYSCALL(stat64), \
124 SECCOMP_ALLOW_ACCUM_SYSCALL(time), \
125 SECCOMP_ALLOW_ACCUM_SYSCALL(mmap2), \
126 SECCOMP_ALLOW_ACCUM_SYSCALL(gettimeofday), \
127 SECCOMP_ALLOW_ACCUM_SYSCALL(_newselect), \
130# define FILTER_TABLE_ARCHDEPENDED \
131 SECCOMP_ALLOW_ACCUM_SYSCALL(fstat), \
132 SECCOMP_ALLOW_ACCUM_SYSCALL(lstat), \
133 SECCOMP_ALLOW_ACCUM_SYSCALL(stat), \
134 SECCOMP_ALLOW_ACCUM_SYSCALL(mmap), \
140static struct sock_filter filter_table[] = {
141 SECCOMP_COPY_SYSCALL_TO_ACCUM,
143 FILTER_TABLE_ARCHDEPENDED
146static struct sock_filter filter_w_mprotect_table[] = {
147 SECCOMP_COPY_SYSCALL_TO_ACCUM,
149 FILTER_TABLE_ARCHDEPENDED
150 SECCOMP_ALLOW_ACCUM_SYSCALL ( mprotect ),
154int nonprivileged_seccomp_init (
ctx_t *
ctx_p )
156 struct sock_fprog *filter_p;
157 struct sock_fprog filter = {
158 .len = (
unsigned short ) (
sizeof ( filter_table ) /
sizeof ( filter_table[0] ) ),
159 .filter = filter_table,
161 struct sock_fprog filter_w_mprotect = {
162 .len = (
unsigned short ) (
sizeof ( filter_w_mprotect_table ) /
sizeof ( filter_w_mprotect_table[0] ) ),
163 .filter = filter_w_mprotect_table,
165 debug ( 5,
"enabling the seccomp" );
167 SAFE ( prctl ( PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0 ),
return -1 );
168 SAFE ( prctl ( PR_SET_SECCOMP, SECCOMP_MODE_FILTER, filter_p ),
return -1 );
176#ifdef CAPABILITIES_SUPPORT
178pthread_t privileged_thread;
179pthread_mutex_t *pthread_mutex_privileged_p;
180pthread_mutex_t *pthread_mutex_action_signal_p;
181pthread_mutex_t *pthread_mutex_action_entrance_p;
182pthread_mutex_t *pthread_mutex_runner_p;
183pthread_cond_t *pthread_cond_privileged_p;
184pthread_cond_t *pthread_cond_action_p;
185pthread_cond_t *pthread_cond_runner_p;
187# ifdef READWRITE_SIGNALLING
194enum privileged_action {
209 PA_INOTIFY_ADD_WATCH,
216 PA_CLSYNC_CGROUP_DEINIT,
221struct pa_lstat64_arg {
222 char path_buf[PATH_MAX];
226struct pa_fts_open_arg {
229 char *
const *path_argv_p;
231 int ( *compar ) (
const FTSENT **,
const FTSENT ** );
234struct pa_inotify_add_watch_arg {
236 char pathname[PATH_MAX];
237 const char *pathname_p;
241struct pa_inotify_rm_watch_arg {
246struct pa_fork_execvp_arg {
254struct pa_kill_child_arg {
260struct pa_waitpid_arg {
267 struct pa_lstat64_arg lstat64;
268 struct pa_fts_open_arg fts_open;
269 struct pa_inotify_add_watch_arg inotify_add_watch;
270 struct pa_inotify_rm_watch_arg inotify_rm_watch;
271 struct pa_fork_execvp_arg fork_execvp;
272 struct pa_kill_child_arg kill_child;
273 struct pa_waitpid_arg waitpid;
280enum highload_lock_id {
285typedef enum highload_lock_id hllockid_t;
287enum highlock_lock_state {
290 HLLS_FALLBACK = 0x02,
292 HLLS_GOTSIGNAL = 0x08,
295typedef enum highlock_lock_state hllock_state_t;
298 volatile int locallock_hl_setstate_ifstate;
299 volatile int enabled;
300 volatile int count_wait[HLLOCK_MAX];
301 volatile int count_signal[HLLOCK_MAX];
302 volatile hllock_state_t state[HLLOCK_MAX];
303# ifdef HL_LOCK_TRIES_AUTO
304 volatile unsigned long tries[PC_MAX];
305 volatile unsigned long count[PC_MAX];
306 volatile unsigned long delay[PC_MAX];
307 volatile double tries_step[PC_MAX];
309# define tries_cur tries[callid]
311 volatile unsigned long tries;
312# define tries_cur tries
317struct pa_fts_read_ret {
319 char fts_accpath[PATH_MAX];
320 char fts_path[PATH_MAX];
321 char fts_name[PATH_MAX];
325 struct pa_fts_read_ret fts_read;
328 volatile struct pa_arg arg;
329 volatile enum privileged_action action;
331 volatile unsigned long hl_lock_tries;
335 volatile struct pa_ret ret_buf;
338 volatile int processing_longcmd;
340volatile struct cmd *cmd_p;
341volatile struct cmd_ret *cmd_ret_p;
343volatile struct hl_lock *hl_lock_p;
347static inline void hl_lock_init (
volatile struct hl_lock *hl_lock_p )
350 hl_lock_p->enabled = 1;
351 hl_lock_p->locallock_hl_setstate_ifstate = 1;
352# ifdef HL_LOCK_TRIES_AUTO
356 while ( i < PC_MAX ) {
358 hl_lock_p->delay[i] = ( (
unsigned long ) ~0 ) >> 2;
374 char *preexithookfile;
376 int permitted_hookfiles;
381int ( *_privileged_lstat64 ) (
383# ifdef HL_LOCK_TRIES_AUTO
388FTS * ( *_privileged_fts_open ) (
389 char *
const *path_argv,
391 int ( *compar ) (
const FTSENT **,
const FTSENT ** )
397FTSENT * ( *_privileged_fts_read ) (
399# ifdef HL_LOCK_TRIES_AUTO
404int ( *_privileged_fts_close ) (
406# ifdef HL_LOCK_TRIES_AUTO
411int ( *_privileged_inotify_init ) ();
412int ( *_privileged_inotify_init1 ) (
int flags );
414int ( *_privileged_inotify_add_watch ) (
416 const char *pathname,
418# ifdef HL_LOCK_TRIES_AUTO
423int ( *_privileged_inotify_rm_watch ) (
428int ( *_privileged_clsync_cgroup_deinit ) (
ctx_t *
ctx_p );
430pid_t ( *_privileged_waitpid ) ( pid_t pid,
int *status,
int options );
432int cap_enable ( __u32 caps )
434 debug ( 1,
"Enabling Linux capabilities 0x%x", caps );
435 struct __user_cap_header_struct cap_hdr = {0};
436 struct __user_cap_data_struct cap_dat = {0};
437 cap_hdr.version = _LINUX_CAPABILITY_VERSION;
439 if ( capget ( &cap_hdr, &cap_dat ) < 0 ) {
440 error (
"Cannot get capabilities with capget()" );
444 debug ( 3,
"old: cap.eff == 0x%04x; new: cap.eff == 0x%04x", cap_dat.effective, cap_dat.effective | caps );
445 cap_dat.effective |= caps;
447 if ( capset ( &cap_hdr, &cap_dat ) < 0 ) {
448 error (
"Cannot set capabilities with capset()." );
457 debug ( 1,
"Dropping all Linux capabilities but 0x%x", caps );
458 struct __user_cap_header_struct cap_hdr = {0};
459 struct __user_cap_data_struct cap_dat = {0};
460 cap_hdr.version = _LINUX_CAPABILITY_VERSION;
462 if ( capget ( &cap_hdr, &cap_dat ) < 0 ) {
467 debug ( 3,
"old: cap.eff == 0x%04x; cap.prm == 0x%04x; cap.inh == 0x%04x.",
468 cap_dat.effective, cap_dat.permitted, cap_dat.inheritable );
472 cap_dat.inheritable = cap_dat.permitted;
479 cap_dat.inheritable = caps;
483 cap_dat.inheritable = 0;
487 cap_dat.effective = caps;
488 cap_dat.permitted = caps;
489 debug ( 3,
"new: cap.eff == 0x%04x; cap.prm == 0x%04x; cap.inh == 0x%04x.",
490 cap_dat.effective, cap_dat.permitted, cap_dat.inheritable );
492 if ( capset ( &cap_hdr, &cap_dat ) < 0 ) {
504 if ( waitpid ( child_pid, NULL, WNOHANG ) >= 0 ) {
505 debug ( 3,
"Sending signal %u to child process with pid %u.",
508 if ( kill ( child_pid, signal ) ) {
510 error (
"Got error while kill(%u, %u)", child_pid, signal );
521#ifdef CAPABILITIES_SUPPORT
523int pa_strcmp (
const char *s1,
const char *s2,
int isexpanded )
526 return strcmp ( s1, s2 );
529 const char *s1_start = NULL;
530 const char *s2_start = NULL;
534 if ( !*s1 || !*s2 ) {
535 if ( !*s1 && s1_start != NULL )
544 while ( *s1 && *s1 !=
'%' ) s1++;
559 if ( s2_start == NULL )
571int privileged_execvp_check_arguments (
struct pa_options *opts,
const char *u_file,
char *
const *u_argv )
580 while ( u_argv[u_argc] != NULL ) u_argc++;
591 debug ( 8,
"Checking the number of arguments: %i <> %i",
argc, u_argc );
593 if (
argc != u_argc )
597 debug ( 8,
"Checking the execution file: \"%s\" <> \"%s\"; isexpanded == %i",
argv[0], u_file, isexpanded[0] );
599 if ( pa_strcmp (
argv[0], u_file, isexpanded[0] ) ) {
600 debug ( 1,
"The file to be executed didn't match (argv[0] != u_file): \"%s\" != \"%s\"",
argv[0], u_file );
604 debug ( 8,
"Checking arguments" );
608 if ( pa_strcmp (
argv[i], u_argv[i], isexpanded[i] ) ) {
609 debug ( 1,
"An argument #%i didn't match (argv[%i] != u_argv[%i]): \"%s\" != \"%s\"",
argv[i],
argv[i] );
629 if ( ( opts->exithookfile != NULL ) || ( opts->preexithookfile != NULL ) ) {
630 if ( !strcmp ( opts->label, u_argv[1] ) ) {
631 if ( opts->exithookfile != NULL )
632 if ( !strcmp ( opts->exithookfile, u_file ) )
635 if ( opts->preexithookfile != NULL )
636 if ( !strcmp ( opts->preexithookfile, u_file ) )
643 while ( i < opts->permitted_hookfiles ) {
644 if ( !strcmp ( opts->permitted_hookfile[i], u_file ) )
651 debug ( 1,
"a_i == %i; SHARGS_MAX == %i; u_argc == %i",
SHARGS_MAX, a_i, u_argc );
652 critical (
"Arguments are wrong. This should happen only on hacking attack." );
656int pa_setup (
struct pa_options *opts,
ctx_t *
ctx_p, uid_t *exec_uid_p, gid_t *exec_gid_p )
664 char **argv_s, **argv_d, *isex_s, *isex_d;
668 argv_d = args[a_i].
v;
680 while ( i < argc_s ) {
681 argv_d[i + 1] = strdup_protect ( argv_s[i], PROT_READ );
682 isex_d[i + 1] = isex_s[i];
694 opts->label = strdup_protect (
ctx_p->
label, PROT_READ );
705 while ( i < ctx_p->permitted_hookfiles ) {
706 opts->permitted_hookfile[i] = strdup_protect (
ctx_p->permitted_hookfile[i], PROT_READ );
710 opts->permitted_hookfile[i] = NULL;
711 opts->permitted_hookfiles = i;
716int pa_unsetup (
struct pa_options *opts )
721 free ( opts->exithookfile );
722 free ( opts->preexithookfile );
723 free ( opts->label );
731 while ( i < opts->args[a_i].c ) {
732 free ( opts->args[a_i].v[i] );
740 while ( i < opts->permitted_hookfiles ) {
741 free ( opts->permitted_hookfile[i] );
749static int helper_isalive_cache;
750static inline int helper_isalive_proc()
753 debug ( 12,
"helper_pid == %u", helper_pid );
755 if ( ( rc = waitpid ( helper_pid, NULL, WNOHANG ) ) >= 0 )
756 return helper_isalive_cache = 1;
758 debug ( 1,
"waitpid(%u, NULL, WNOHANG) => %i", helper_pid, rc );
759 return helper_isalive_cache = 0;
761static inline int helper_isalive_thread()
766 if ( ( rc = pthread_kill ( privileged_thread, 0 ) ) )
767 return helper_isalive_cache = 0;
769 debug ( 1,
"pthread_kill(privileged_thread, 0) => %i", helper_pid, rc );
770 return helper_isalive_cache = 1;
772static inline int helper_isalive()
774 return helper_pid ? helper_isalive_proc() : helper_isalive_thread();
787static inline int hl_isanswered (
int lockid )
789 return hl_lock_p->count_wait[lockid] == hl_lock_p->count_signal[lockid] + 1;
792static inline int hl_isready (
int lockid )
794 return hl_lock_p->count_wait[lockid] == hl_lock_p->count_signal[lockid];
797static inline void hl_setstate (
int lockid, hllock_state_t stateid )
799 g_atomic_int_set ( &hl_lock_p->state[lockid], stateid );
802int hl_setstate_ifstate (
int lockid, hllock_state_t stateid_new, hllock_state_t stateid_old_mask )
804 static long long counter = 0;
805 volatile int *local_lock_p = &hl_lock_p->locallock_hl_setstate_ifstate;
806 debug ( 90,
"%i, 0x%o, 0x%o", lockid, stateid_new, stateid_old_mask );
809 if ( ( ( ++counter ) & 0xffffff ) == 0 ) {
818 if ( !g_atomic_int_dec_and_test ( local_lock_p ) ) {
819 g_atomic_int_inc ( local_lock_p );
823 if ( ! ( hl_lock_p->state[lockid]&stateid_old_mask ) ) {
824 g_atomic_int_inc ( local_lock_p );
828 debug ( 50,
"success" );
829 g_atomic_int_set ( &hl_lock_p->state[lockid], stateid_new );
830 g_atomic_int_inc ( local_lock_p );
834static inline int hl_wait (
837 ,
unsigned long hl_lock_tries
842 volatile unsigned long try = 0;
846 while ( hl_lock_p->state[lockid] == HLLS_GOTSIGNAL );
848 while ( !hl_isready ( lockid ) );
850 hl_setstate ( lockid, HLLS_READY );
851 hl_lock_p->count_wait[lockid]++;
853 while (
try++ < hl_lock_tries )
854 if ( hl_lock_p->state[lockid] == HLLS_SIGNAL ) {
855 hl_setstate ( lockid, HLLS_GOTSIGNAL );
856 debug ( 15,
"got signal" );
860 while ( !hl_setstate_ifstate ( lockid, HLLS_FALLBACK, HLLS_READY | HLLS_SIGNAL ) );
862 debug ( 14,
"fallback: hl_lock_p->count_wait[%u] == %u; hl_lock_p->count_signal[%u] = %u", lockid, hl_lock_p->count_wait[lockid], lockid, hl_lock_p->count_signal[lockid] );
866static inline int hl_signal (
int lockid )
868 debug ( 15,
"%u", lockid );
869 hl_lock_p->count_signal[lockid]++;
871 if ( hl_setstate_ifstate ( lockid, HLLS_SIGNAL, HLLS_READY ) ) {
872 while ( hl_lock_p->state[lockid] != HLLS_GOTSIGNAL ) {
873 if ( hl_lock_p->state[lockid] == HLLS_FALLBACK ) {
874 debug ( 15,
"fallback" );
878 debug ( 95,
"state == %i != %i, %i", hl_lock_p->state[lockid], HLLS_GOTSIGNAL, HLLS_FALLBACK );
881 debug ( 15,
"the signal is sent" );
882 hl_setstate ( lockid, HLLS_WORKING );
886 debug ( 15,
"not ready" );
890void hl_shutdown (
int lockid )
895# ifdef HL_LOCK_TRIES_AUTO
896 memset ( (
void * ) hl_lock_p->tries, 0, sizeof ( hl_lock_p->tries ) );
898 hl_lock_p->tries = 0;
901 hl_lock_p->state[lockid] = HLLS_FALLBACK;
902 hl_lock_p->enabled = 0;
910# ifdef READWRITE_SIGNALLING
913 struct timespec wait_timeout = {0};
916 uid_t exec_uid = 65535;
917 gid_t exec_gid = 65535;
918 struct pa_options *opts;
919 int use_args_check = 0;
920 int helper_isrunning = 1;
921 opts = calloc_align ( 1,
sizeof ( *opts ) );
925 if ( opts->isprocsplitting ) {
927 sigemptyset ( &sigset );
938# error There's no automatical mechanism that guarantees handler closing on non-linux. Don't use process splitting!
941 sigaddset ( &sigset, SIGCHLD );
943 critical_on ( pthread_sigmask ( SIG_UNBLOCK, &sigset, NULL ) );
949 pthread_setname_np ( pthread_self(),
"clsync-helper" );
953 debug ( 2,
"Syncing with the runner" );
954 pthread_mutex_lock ( pthread_mutex_privileged_p );
956 pthread_mutex_lock ( pthread_mutex_runner_p );
957 pthread_mutex_unlock ( pthread_mutex_runner_p );
959 pthread_cond_signal ( pthread_cond_runner_p );
961 debug ( 2,
"Running the loop" );
963 while ( helper_isrunning ) {
966 debug ( 10,
"Waiting for command" );
968 if ( opts->shm_mprotect ) {
969 mprotect ( (
void * ) cmd_p,
sizeof ( *cmd_p ), PROT_WRITE );
970 mprotect ( (
void * ) cmd_ret_p,
sizeof ( *cmd_ret_p ), PROT_READ );
974 debug ( 25,
"hl_lock_p->enabled == %i", hl_lock_p->enabled );
976 if ( !hl_lock_p->enabled || !hl_wait (
979 , hl_lock_p->tries[HLLOCK_HANDLER]
982 if ( opts->isprocsplitting )
986# ifdef READWRITE_SIGNALLING
987# warning READWRITE_SIGNALLING can cause process hanging on clsync shutdown
993 rc = pthread_cond_timedwait ( pthread_cond_privileged_p, pthread_mutex_privileged_p, &wait_timeout );
998 if ( rc != ETIMEDOUT )
999 critical (
"Got error while pthread_cond_timedwait()" );
1001 debug ( 10,
"pthread_cond_timedwait() timed out" );
1003 if ( opts->isprocsplitting )
1007 debug ( 20,
"Resetting wait_timeout" );
1009 gettimeofday ( &now, NULL );
1011 wait_timeout.tv_nsec = now.tv_usec * 1000;
1018 if ( hl_lock_p->enabled )
1019 hl_setstate ( HLLOCK_HANDLER, HLLS_WORKING );
1024 if ( opts->shm_mprotect ) {
1025 mprotect ( (
void * ) cmd_p,
sizeof ( *cmd_p ), PROT_READ );
1026 mprotect ( (
void * ) cmd_ret_p,
sizeof ( *cmd_ret_p ), PROT_WRITE );
1029 debug ( 10,
"Got command %u (euid:egid => %i:%i)", cmd_p->action, geteuid(), getegid() );
1031 if ( !setup && cmd_p->action != PA_SETUP )
1032 critical (
"A try to use commands before PA_SETUP" );
1034 switch ( cmd_p->action ) {
1036 debug ( 20,
"PA_SETUP" );
1039 critical (
"Double privileged_handler setuping. It can be if somebody is trying to hack the clsync." );
1041 critical_on ( pa_setup ( opts, cmd_p->arg.ctx_p, &exec_uid, &exec_gid ) );
1042 mprotect ( opts,
sizeof ( *opts ), PROT_READ );
1051 debug ( 20,
"PA_DIE" );
1052 helper_isrunning = 0;
1056 volatile struct pa_lstat64_arg *arg_p = &cmd_p->arg.lstat64;
1057 stat64_t *ret_buf = (
void * ) &cmd_ret_p->ret_buf.stat64;
1058 volatile const char *path = opts->isprocsplitting ?
1061 debug ( 20,
"PA_LSTAT64 (%s)", path );
1062 cmd_ret_p->ret = (
void * ) (
long ) lstat64 ( (
const char * ) path, ret_buf );
1063 debug ( 21,
"/PA_LSTAT64 => %i", (
int ) (
long ) cmd_ret_p->ret );
1068 volatile struct pa_fts_open_arg *arg_p = &cmd_p->arg.fts_open;
1069 char *
const *path_argv_p = (
void * ) (
1070 opts->isprocsplitting ?
1074 debug ( 20,
"PA_FTS_OPEN (%s)", *path_argv_p );
1076 if ( arg_p->compar != NULL )
1077 critical (
"\"arg_p->compar != NULL\" (arg_p->compar == %p) is forbidden because may be used to run an arbitrary code in the privileged thread.", arg_p->compar );
1079 cmd_ret_p->ret = fts_open ( path_argv_p, arg_p->options, NULL );
1080 debug ( 21,
"/PA_FTS_OPEN => %p", cmd_ret_p->ret );
1085 debug ( 20,
"PA_FTS_READ(%p)", cmd_p->arg.void_v );
1086 FTSENT *ret = fts_read ( cmd_p->arg.void_v );
1088 if ( ret == NULL ) {
1089 cmd_ret_p->ret = NULL;
1090 debug ( 10,
"cmd_ret_p->ret == NULL" );
1094 if ( !opts->isprocsplitting ) {
1095 cmd_ret_p->ret = ret;
1101 struct pa_fts_read_ret *ret_buf = (
void * ) &cmd_ret_p->ret_buf.fts_read;
1102 memcpy ( &ret_buf->ftsent, ret, sizeof ( ret_buf->ftsent ) );
1103 cmd_ret_p->ret = &ret_buf->ftsent;
1104 debug ( 25,
"fts_path == <%s>", ret_buf->fts_path );
1105 xstrncpy ( ret_buf->fts_accpath, ret->fts_accpath, sizeof ( ret_buf->fts_accpath ) );
1106 xstrncpy ( ret_buf->fts_path, ret->fts_path, sizeof ( ret_buf->fts_path ) );
1107 ret_buf->ftsent.fts_accpath = ret_buf->fts_accpath;
1108 ret_buf->ftsent.fts_path = ret_buf->fts_path;
1115 debug ( 20,
"PA_FTS_CLOSE" );
1116 cmd_ret_p->ret = (
void * ) (
long ) fts_close ( cmd_p->arg.void_v );
1119 case PA_INOTIFY_INIT:
1120 debug ( 20,
"PA_INOTIFY_INIT" );
1121 cmd_ret_p->ret = (
void * ) (
long ) inotify_init();
1124 case PA_INOTIFY_INIT1:
1125 debug ( 20,
"PA_INOTIFY_INIT1" );
1126 cmd_ret_p->ret = (
void * ) (
long ) inotify_init1 ( cmd_p->arg.uint32_v );
1129 case PA_INOTIFY_ADD_WATCH: {
1130 struct pa_inotify_add_watch_arg *arg_p = (
void * ) &cmd_p->arg.inotify_add_watch;
1131 const char *pathname = ( opts->isprocsplitting ? arg_p->pathname : arg_p->pathname_p );
1132 debug ( 20,
"PA_INOTIFY_ADD_WATCH(%u, <%s>, 0x%o)", arg_p->fd, pathname, arg_p->mask );
1133 cmd_ret_p->ret = (
void * ) (
long ) inotify_add_watch ( arg_p->fd, pathname, arg_p->mask );
1137 case PA_INOTIFY_RM_WATCH: {
1138 debug ( 20,
"PA_INOTIFY_RM_WATCH" );
1139 struct pa_inotify_rm_watch_arg *arg_p = (
void * ) &cmd_p->arg.inotify_rm_watch;
1140 cmd_ret_p->ret = (
void * ) (
long ) inotify_rm_watch ( arg_p->fd, arg_p->wd );
1144 case PA_FORK_EXECVP: {
1145 struct pa_fork_execvp_arg *arg_p = (
void * ) &cmd_p->arg.fork_execvp;
1149 if ( opts->isprocsplitting ) {
1153 file = arg_p->file_p;
1154 argv = arg_p->argv_p;
1157 debug ( 20,
"PA_FORK_EXECVP (\"%s\", argv)", file );
1159 if ( use_args_check )
1160 privileged_execvp_check_arguments ( opts, file,
argv );
1166 error (
"Cannot fork()." );
1177 rc = setgid ( exec_gid );
1178 debug ( 4,
"setgid(%u) == %i", exec_gid, rc );
1186 rc = setuid ( exec_uid );
1187 debug ( 4,
"setuid(%u) == %i", exec_uid, rc );
1190 debug ( 3,
"execvp(\"%s\", argv)", file );
1191 exit ( execvp ( file,
argv ) );
1195 cmd_ret_p->ret = (
void * ) (
long ) pid;
1196 debug ( 21,
"/PA_FORK_EXECVP" );
1200 case PA_KILL_CHILD: {
1201 debug ( 20,
"PA_KILL_CHILD" );
1202 struct pa_kill_child_arg *arg_p = (
void * ) &cmd_p->arg.kill_child;
1207# ifdef CGROUP_SUPPORT
1209 case PA_CLSYNC_CGROUP_DEINIT: {
1210 debug ( 20,
"PA_CLSYNC_CGROUP_DEINIT" );
1223 error (
"Cannot fork()." );
1227 debug ( 4,
"setgid(0) == %i", setgid ( 0 ) );
1228 debug ( 4,
"setuid(0) == %i", setuid ( 0 ) );
1232 if ( waitpid ( pid, &status, 0 ) != pid ) {
1235 debug ( 2,
"Child %u has already died.", pid );
1239 error (
"Cannot waitid()." );
1240 cmd_ret_p->_errno = errno;
1241 cmd_ret_p->ret = (
void * ) (
long ) errno;
1246 int exitcode = WEXITSTATUS ( status );
1247 debug ( 3,
"execution completed with exitcode %i",
exitcode );
1249 cmd_ret_p->ret = (
void * ) (
long )
exitcode;
1256 struct pa_waitpid_arg *arg_p = (
void * ) &cmd_p->arg.waitpid;
1257 debug ( 20,
"PA_WAITPID(%u, 0x%o)", arg_p->pid, arg_p->options );
1258 cmd_ret_p->processing_longcmd = 1;
1259 cmd_ret_p->ret = (
void * ) (
long ) waitpid ( arg_p->pid, &arg_p->status, arg_p->options );
1260 cmd_ret_p->processing_longcmd = 0;
1265 critical (
"Unknown command type \"%u\". It's a buffer overflow (which means a security problem) or just an internal error." );
1268 cmd_ret_p->_errno = errno;
1269 debug ( 10,
"Result: %p, errno: %u. Sending the signal to non-privileged thread/process.", cmd_ret_p->ret, cmd_ret_p->_errno );
1272 if ( !hl_lock_p->enabled ) {
1277# ifdef READWRITE_SIGNALLING
1280 critical_on ( pthread_mutex_lock ( pthread_mutex_action_signal_p ) );
1281 critical_on ( pthread_mutex_unlock ( pthread_mutex_action_signal_p ) );
1282 critical_on ( pthread_cond_signal ( pthread_cond_action_p ) );
1290 pa_unsetup ( opts );
1292 hl_shutdown ( HLLOCK_HANDLER );
1294 pthread_mutex_unlock ( pthread_mutex_privileged_p );
1295 debug ( 2,
"Finished" );
1299static inline int privileged_action (
1303 enum privileged_action action,
1308# ifdef READWRITE_SIGNALLING
1311# ifdef HL_LOCK_TRIES_AUTO
1312 clock_t start_ticks;
1316 debug ( 10,
"(%u, %p): %i", action, ret_p, hl_lock_p->enabled );
1318 debug ( 10,
"(%u, %p)", action, ret_p );
1320 pthread_mutex_lock ( pthread_mutex_action_entrance_p );
1321# ifndef READWRITE_SIGNALLING
1322 debug ( 10,
"Waiting the privileged thread/process to get prepared for signal" );
1325 if ( hl_lock_p->enabled ) {
1326 long long counter = 0;
1328 while ( !hl_isanswered ( HLLOCK_HANDLER ) ) {
1329 if ( !helper_isalive_cache ) {
1330 debug ( 1,
"The privileged thread/process is dead (#0). Ignoring the command." );
1332 goto privileged_action_end;
1341 pthread_mutex_lock ( pthread_mutex_privileged_p );
1342 pthread_mutex_unlock ( pthread_mutex_privileged_p );
1349 if ( !helper_isalive_cache ) {
1350 debug ( 1,
"The privileged thread/process is dead (#1). Ignoring the command." );
1352 goto privileged_action_end;
1355 cmd_p->action = action;
1356 debug ( 10,
"Sending information (action == %i) to the privileged thread/process", action );
1357# ifdef HL_LOCK_TRIES_AUTO
1358 cmd_p->hl_lock_tries = hl_lock_p->tries[callid];
1360 if ( ( isadjusting = hl_lock_p->enabled ) ) {
1361 isadjusting = hl_lock_p->tries[callid];
1363 if ( isadjusting ) {
1364 isadjusting = ( ( double ) fabs ( hl_lock_p->tries_step[callid] - 1 ) > ( double )
HL_LOCK_AUTO_K_FINISH );
1366 if ( isadjusting ) {
1367 isadjusting = ! ( ( ++hl_lock_p->count[callid] ) << (
sizeof ( hl_lock_p->count[callid] ) * CHAR_BIT -
HL_LOCK_AUTO_INTERVAL ) );
1368 debug ( 11,
"isadjusting == %u; hl_lock_p->tries_step[%i] == %lf; hl_lock_p->count[%i] == %lu", isadjusting, callid, hl_lock_p->tries_step[callid], callid, hl_lock_p->count[callid] );
1371 start_ticks = clock();
1379 if ( action == PA_DIE )
1380 hl_lock_p->enabled = 0;
1382 if ( !hl_lock_p->enabled || !hl_signal ( HLLOCK_HANDLER ) ) {
1385# ifdef READWRITE_SIGNALLING
1390 if ( hl_lock_p->enabled ) {
1391 debug ( 10,
"Waiting the privileged thread/process to get prepared for signal (by fallback)" );
1392 critical_on ( pthread_mutex_lock ( pthread_mutex_privileged_p ) );
1393 critical_on ( pthread_mutex_unlock ( pthread_mutex_privileged_p ) );
1396 critical_on ( pthread_mutex_lock ( pthread_mutex_action_signal_p ) );
1398 critical_on ( pthread_cond_signal ( pthread_cond_privileged_p ) );
1405 if ( action == PA_DIE )
1406 goto privileged_action_end;
1408 debug ( 10,
"Waiting for the answer" );
1411 if ( hl_lock_p->enabled ) {
1412 long long counter = 0;
1414 while ( !hl_isanswered ( HLLOCK_HANDLER ) ) {
1415 if ( !helper_isalive_cache ) {
1416 debug ( 1,
"The privileged thread/process is dead (#2). Ignoring the command." );
1418 goto privileged_action_end;
1425# ifdef HL_LOCK_TRIES_AUTO
1427 if ( isadjusting ) {
1428 unsigned long delay = ( long ) clock() - ( long ) start_ticks;
1429 long diff = delay - hl_lock_p->delay[callid];
1430 debug ( 13,
"diff == %li; hl_lock_p->delay[%i] == %lu; delay == %lu; delay*HL_LOCK_AUTO_THREADHOLD == %lu", diff, callid, hl_lock_p->delay[callid], delay, delay *
HL_LOCK_AUTO_THREADHOLD )
1436 hl_lock_p->delay[callid] = delay;
1437 debug ( 12,
"diff == %li; hl_lock_p->tries_step[%i] == %lf; hl_lock_p->delay[%i] == %lu", diff, callid, hl_lock_p->tries_step[callid], callid, hl_lock_p->delay[callid] );
1440 hl_lock_p->tries[callid] *= hl_lock_p->tries_step[callid];
1445 debug ( 14,
"hl_lock_p->tries[%i] == %lu", callid, hl_lock_p->tries[callid] );
1452# ifdef READWRITE_SIGNALLING
1455 critical_on ( pthread_cond_wait ( pthread_cond_action_p, pthread_mutex_action_signal_p ) );
1462 if ( ret_p != NULL )
1463 *ret_p = (
void * ) cmd_ret_p->ret;
1465 errno = cmd_ret_p->_errno;
1466privileged_action_end:
1467 debug ( 10,
"Unlocking pthread_mutex_action_*" );
1468# ifndef READWRITE_SIGNALLING
1471 if ( !hl_lock_p->enabled )
1473 pthread_mutex_unlock ( pthread_mutex_action_signal_p );
1476 pthread_mutex_unlock ( pthread_mutex_action_entrance_p );
1480int __privileged_lstat64_procsplit (
1487 void *ret = (
void * ) (
long ) - 1;
1488 xstrncpy ( (
char * ) cmd_p->arg.lstat64.path_buf, path, PATH_MAX );
1496 memcpy ( buf, (
void * ) &cmd_ret_p->ret_buf.stat64, sizeof (
stat64_t ) );
1497 return (
long ) ret;
1500int __privileged_lstat64_threadsplit (
1507 void *ret = (
void * ) (
long ) - 1;
1508 cmd_p->arg.lstat64.path = path;
1516 memcpy ( buf, (
void * ) &cmd_ret_p->ret_buf.stat64, sizeof (
stat64_t ) );
1517 return (
long ) ret;
1520FTS *__privileged_fts_open_procsplit (
1521 char *
const *path_argv,
1523 int ( *compar ) (
const FTSENT **,
const FTSENT ** )
1533 while ( path_argv[i] != NULL ) {
1534 cmd_p->arg.fts_open.path_argv[i] = (
void * ) cmd_p->arg.fts_open._path_argv[i];
1535 debug ( 25,
"path_argv[%i] == <%s> (%p) -> %p", i, path_argv[i], path_argv[i], cmd_p->arg.fts_open.path_argv[i] );
1536 xstrncpy ( cmd_p->arg.fts_open.path_argv[i], path_argv[i], sizeof ( cmd_p->arg.fts_open._path_argv[i] ) );
1541 cmd_p->arg.fts_open.path_argv[i] = NULL;
1542 cmd_p->arg.fts_open.options = options;
1543 cmd_p->arg.fts_open.compar = compar;
1554FTS *__privileged_fts_open_threadsplit (
1555 char *
const *path_argv,
1557 int ( *compar ) (
const FTSENT **,
const FTSENT ** )
1564 cmd_p->arg.fts_open.path_argv_p = path_argv;
1565 cmd_p->arg.fts_open.options = options;
1566 cmd_p->arg.fts_open.compar = compar;
1577FTSENT *__privileged_fts_read (
1585 cmd_p->arg.void_v = ftsp;
1596int __privileged_fts_close (
1603 void *ret = (
void * ) (
long ) - 1;
1604 cmd_p->arg.void_v = ftsp;
1612 return (
long ) ret;
1615int __privileged_inotify_init()
1617 void *ret = (
void * ) (
long ) - 1;
1625 return (
long ) ret;
1628int __privileged_inotify_init1 (
int flags )
1630 void *ret = (
void * ) (
long ) - 1;
1631 cmd_p->arg.uint32_v = flags;
1639 return (
long ) ret;
1642int __privileged_inotify_add_watch_threadsplit (
1644 const char *pathname,
1651 debug ( 25,
"(%i, <%s>, o%o, ?)", fd, pathname, mask );
1652 void *ret = (
void * ) (
long ) - 1;
1653 cmd_p->arg.inotify_add_watch.pathname_p = pathname;
1654 cmd_p->arg.inotify_add_watch.fd = fd;
1655 cmd_p->arg.inotify_add_watch.mask = mask;
1660 PA_INOTIFY_ADD_WATCH,
1663 return (
long ) ret;
1666int __privileged_inotify_add_watch_procsplit (
1668 const char *pathname,
1675 debug ( 25,
"(%i, <%s>, o%o, ?)", fd, pathname, mask );
1676 void *ret = (
void * ) (
long ) - 1;
1677 xstrncpy ( (
void * ) cmd_p->arg.inotify_add_watch.pathname, pathname, sizeof ( cmd_p->arg.inotify_add_watch.pathname ) );
1678 cmd_p->arg.inotify_add_watch.fd = fd;
1679 cmd_p->arg.inotify_add_watch.mask = mask;
1684 PA_INOTIFY_ADD_WATCH,
1687 return (
long ) ret;
1690int __privileged_inotify_rm_watch (
1695 void *ret = (
void * ) (
long ) - 1;
1696 cmd_p->arg.inotify_rm_watch.fd = fd;
1697 cmd_p->arg.inotify_rm_watch.wd = wd;
1702 PA_INOTIFY_RM_WATCH,
1705 return (
long ) ret;
1708# ifdef CGROUP_SUPPORT
1709int __privileged_clsync_cgroup_deinit (
ctx_t *
ctx_p )
1711 void *ret = (
void * ) (
long ) - 1;
1712 cmd_p->arg.ctx_p =
ctx_p;
1717 PA_CLSYNC_CGROUP_DEINIT,
1720 return (
long ) ret;
1724int __privileged_fork_setuid_execvp_procsplit (
1730 void *ret = (
void * ) (
long ) - 1;
1731 xstrncpy ( (
void * ) cmd_p->arg.fork_execvp.file, file, sizeof ( cmd_p->arg.fork_execvp.file ) );
1734 while (
argv[i] != NULL ) {
1735 cmd_p->arg.fork_execvp.argv[i] = (
void * ) cmd_p->arg.fork_execvp._argv[i];
1736 xstrncpy ( cmd_p->arg.fork_execvp.argv[i],
argv[i], sizeof ( cmd_p->arg.fork_execvp._argv[i] ) );
1741 cmd_p->arg.fork_execvp.argv[i] = NULL;
1749 return (
long ) ret;
1752int __privileged_fork_setuid_execvp_threadsplit (
1757 void *ret = (
void * ) (
long ) - 1;
1758 cmd_p->arg.fork_execvp.file_p = file;
1759 cmd_p->arg.fork_execvp.argv_p =
argv;
1767 return (
long ) ret;
1770int __privileged_kill_child_wrapper ( pid_t pid,
int signal,
char ignoreerrors )
1772 void *ret = (
void * ) (
long ) - 1;
1773 cmd_p->arg.kill_child.pid = pid;
1774 cmd_p->arg.kill_child.signal = signal;
1775 cmd_p->arg.kill_child.ignoreerrors = ignoreerrors;
1782 return (
long ) ret;
1785pid_t __privileged_waitpid ( pid_t pid,
int *status,
int options )
1787 void *ret = (
void * ) (
long ) - 1;
1788 cmd_p->arg.waitpid.pid = pid;
1789 cmd_p->arg.waitpid.options = options;
1797 if ( status != NULL )
1798 *status = cmd_p->arg.waitpid.status;
1800 return (
long ) ret;
1814 error (
"Cannot fork()." );
1825 execvp ( file,
argv );
1833#ifdef CAPABILITIES_SUPPORT
1834#define pthread_mutex_init_smart(mutex_p) _pthread_mutex_init_smart(ctx_p->flags[SPLITTING]==SM_PROCESS, mutex_p)
1835static inline int _pthread_mutex_init_smart (
int isshared, pthread_mutex_t **mutex_p )
1838 pthread_mutex_t *mutex, initial = PTHREAD_MUTEX_INITIALIZER;
1843 mutex = xmalloc (
sizeof ( *mutex ) );
1844 memcpy ( mutex, &initial,
sizeof ( *mutex ) );
1845 rc = pthread_mutex_init ( mutex, NULL );
1854#define pthread_mutex_destroy_smart(mutex_p) _pthread_mutex_destroy_smart(ctx_p->flags[SPLITTING]==SM_PROCESS, mutex_p)
1855static inline int _pthread_mutex_destroy_smart (
int isshared, pthread_mutex_t *mutex_p )
1862 rc = pthread_mutex_destroy ( mutex_p );
1871#define pthread_cond_init_smart(cond_p) _pthread_cond_init_smart(ctx_p->flags[SPLITTING]==SM_PROCESS, cond_p)
1872static inline int _pthread_cond_init_smart (
int isshared, pthread_cond_t **cond_p )
1875 pthread_cond_t *cond, initial = PTHREAD_COND_INITIALIZER;
1880 cond = xmalloc (
sizeof ( *cond ) );
1881 memcpy ( cond, &initial,
sizeof ( *cond ) );
1882 rc = pthread_cond_init ( cond, NULL );
1891#define pthread_cond_destroy_smart(cond_p) _pthread_cond_destroy_smart(ctx_p->flags[SPLITTING]==SM_PROCESS, cond_p)
1892static inline int _pthread_cond_destroy_smart (
int isshared, pthread_cond_t *cond_p )
1899 rc = pthread_cond_destroy ( cond_p );
1911#ifdef READWRITE_SIGNALLING
1914#ifdef CAPABILITIES_SUPPORT
1923#ifdef CAPABILITIES_SUPPORT
1924 _privileged_lstat64 = ( typeof ( _privileged_lstat64 ) ) lstat64;
1925 _privileged_fts_open = ( typeof ( _privileged_fts_open ) ) fts_open;
1926 _privileged_fts_read = ( typeof ( _privileged_fts_read ) ) fts_read;
1927 _privileged_fts_close = ( typeof ( _privileged_fts_close ) ) fts_close;
1928 _privileged_inotify_init = ( typeof ( _privileged_inotify_init ) ) inotify_init;
1929 _privileged_inotify_init1 = ( typeof ( _privileged_inotify_init1 ) ) inotify_init1;
1930 _privileged_inotify_add_watch = ( typeof ( _privileged_inotify_add_watch ) ) inotify_add_watch;
1931 _privileged_inotify_rm_watch = ( typeof ( _privileged_inotify_rm_watch ) ) inotify_rm_watch;
1932# ifdef CGROUP_SUPPORT
1933 _privileged_clsync_cgroup_deinit = ( typeof ( _privileged_clsync_cgroup_deinit ) )
clsync_cgroup_deinit;
1935 _privileged_waitpid = ( typeof ( _privileged_waitpid ) ) waitpid;
1939#ifdef CAPABILITIES_SUPPORT
1942 _privileged_fts_read = __privileged_fts_read;
1943 _privileged_fts_close = __privileged_fts_close;
1944 _privileged_inotify_init = __privileged_inotify_init;
1945 _privileged_inotify_init1 = __privileged_inotify_init1;
1946 _privileged_inotify_rm_watch = __privileged_inotify_rm_watch;
1948# ifdef CGROUP_SUPPORT
1949 _privileged_clsync_cgroup_deinit = __privileged_clsync_cgroup_deinit;
1951 _privileged_waitpid = __privileged_waitpid;
1952 SAFE ( pthread_mutex_init_smart ( &pthread_mutex_privileged_p ),
return errno; );
1953 SAFE ( pthread_mutex_init_smart ( &pthread_mutex_action_entrance_p ),
return errno; );
1954 SAFE ( pthread_mutex_init_smart ( &pthread_mutex_action_signal_p ),
return errno; );
1955 SAFE ( pthread_mutex_init_smart ( &pthread_mutex_runner_p ),
return errno; );
1956 SAFE ( pthread_cond_init_smart ( &pthread_cond_privileged_p ),
return errno; );
1957 SAFE ( pthread_cond_init_smart ( &pthread_cond_action_p ),
return errno; );
1958 SAFE ( pthread_cond_init_smart ( &pthread_cond_runner_p ),
return errno; );
1959# ifdef READWRITE_SIGNALLING
1960 SAFE ( pipe2 ( pipefds, O_CLOEXEC ),
return errno; );
1961 priv_read_fd = pipefds[0];
1962 priv_write_fd = pipefds[1];
1963 SAFE ( pipe2 ( pipefds, O_CLOEXEC ),
return errno; );
1964 nonp_read_fd = pipefds[0];
1965 nonp_write_fd = pipefds[1];
1967 SAFE ( pthread_mutex_lock ( pthread_mutex_runner_p ),
return errno; );
1968# ifdef UNSHARE_SUPPORT
1969 unshare ( CLONE_NEWIPC );
1974 _privileged_lstat64 = __privileged_lstat64_threadsplit;
1975 _privileged_fts_open = __privileged_fts_open_threadsplit;
1976 _privileged_inotify_add_watch = __privileged_inotify_add_watch_threadsplit;
1978 cmd_p = calloc_align ( 1,
sizeof ( *cmd_p ) );
1979 cmd_ret_p = calloc_align ( 1,
sizeof ( *cmd_ret_p ) );
1981 hl_lock_p = calloc_align ( 1,
sizeof ( *hl_lock_p ) );
1982 hl_lock_init ( hl_lock_p );
1985 SAFE ( pthread_create ( &privileged_thread, NULL, (
void * ( * ) (
void * ) ) privileged_handler,
ctx_p ),
return errno );
1988 privileged_thread = 0;
1994 _privileged_lstat64 = __privileged_lstat64_procsplit;
1995 _privileged_fts_open = __privileged_fts_open_procsplit;
1996 _privileged_inotify_add_watch = __privileged_inotify_add_watch_procsplit;
1999 cmd_ret_p =
shm_calloc ( 1,
sizeof ( *cmd_ret_p ) );
2001 hl_lock_p =
shm_calloc ( 1,
sizeof ( *hl_lock_p ) );
2002 hl_lock_init ( hl_lock_p );
2007 if ( !helper_pid ) {
2020 exit ( privileged_handler (
ctx_p ) );
2031 SAFE ( seteuid ( 0 ), {
error (
"Not enough permission to start a privileged thread/fork" );
return errno;} );
2034 SAFE ( setegid ( 0 ),
return errno );
2035 debug ( 3,
"[non-privileged] Trying to drop real gid %i (ctx_p->gid)", getgid(),
ctx_p->
gid );
2040 debug ( 3,
"[non-privileged] Trying to drop real uid %i (ctx_p->uid)", getuid(),
ctx_p->
uid );
2047 hl_shutdown ( HLLOCK_HANDLER );
2051# ifdef UNSHARE_SUPPORT
2055 SAFE ( cap_enable ( CAP_TO_MASK ( CAP_SYS_ADMIN ) ),
return errno; );
2056 SAFE ( unshare ( CLONE_NEWNET ),
return errno; );
2060 SAFE ( cap_drop (
ctx_p, 0 ),
return errno; );
2061 debug ( 4,
"Waiting for the privileged thread to get prepared" );
2062 pthread_cond_wait ( pthread_cond_runner_p, pthread_mutex_runner_p );
2063 pthread_mutex_unlock ( pthread_mutex_runner_p );
2065 cmd_p->arg.ctx_p =
ctx_p;
2073 SAFE ( pthread_mutex_destroy_smart ( pthread_mutex_runner_p ),
return errno; );
2074 SAFE ( pthread_cond_destroy_smart ( pthread_cond_runner_p ),
return errno; );
2075# ifdef SECCOMP_SUPPORT
2078 nonprivileged_seccomp_init (
ctx_p );
2081 debug ( 5,
"Finish" );
2090#ifdef CAPABILITIES_SUPPORT
2095# ifdef HL_LOCK_TRIES_AUTO
2096# define ARGS PC_DEFAULT, PA_DIE, NULL
2098# define ARGS PA_DIE, NULL
2100 SAFE ( privileged_action ( ARGS ), ret = errno );
2101# ifdef HL_LOCK_TRIES_AUTO
2105 while ( i < PC_MAX ) {
2106 debug ( 1,
"hl_lock_p->tries[%i] == %lu", i, hl_lock_p->tries[i] );
2112 hl_shutdown ( HLLOCK_HANDLER );
2118 pthread_mutex_lock ( pthread_mutex_privileged_p );
2119 pthread_mutex_unlock ( pthread_mutex_privileged_p );
2121 SAFE ( pthread_join ( privileged_thread, NULL ), ret = errno );
2124 free ( (
void * ) cmd_p );
2125 free ( (
void * ) cmd_ret_p );
2127 free ( (
void * ) hl_lock_p );
2137 debug ( 9,
"waitpid(%u, ...)", helper_pid );
2138 waitpid ( helper_pid, &status, 0 );
2159 debug ( 2,
"endof privileged_deinit()" );
int clsync_cgroup_deinit(ctx_t *ctx_p)
#define HL_LOCK_AUTO_K_FINISH
#define HL_LOCK_TRIES_AUTO
#define HL_LOCK_NONPRIV_TRIES
#define HL_LOCK_TRIES_INITIAL
#define HL_LOCK_AUTO_LIMIT_HIGH
#define HL_LOCK_AUTO_THREADHOLD
#define MAXPERMITTEDHOOKFILES
#define HL_LOCK_AUTO_DECELERATION
#define HL_LOCK_AUTO_INTERVAL
#define register_blockthread(thread)
#define error_or_debug(debug_level,...)
#define debug(debug_level,...)
#define critical_on(cond)
#define SAFE(code, onfail)
pid_t waitpid_timed(pid_t child_pid, int *status_p, long sec, long nsec)
void * shm_calloc(size_t nmemb, size_t size)
char * xstrncpy(char *dest, const char *src, size_t n)
int(* _privileged_fork_execvp)(const char *file, char *const argv[])
int privileged_init(ctx_t *ctx_p)
int __privileged_fork_execvp(const char *file, char *const argv[])
int privileged_deinit(ctx_t *ctx_p)
gid_t __privileged_fork_execvp_gid
int(* _privileged_kill_child)(pid_t pid, int sig, char ignoreerrors)
uid_t __privileged_fork_execvp_uid
int __privileged_kill_child_itself(pid_t child_pid, int signal, char ignoreerrors)
#define privileged_check(...)
#define privileged_kill_child
#define privileged_fork_execvp
int pthread_mutex_init_shared(pthread_mutex_t **mutex_p)
int pthread_cond_destroy_shared(pthread_cond_t *cond_p)
int pthread_mutex_destroy_shared(pthread_mutex_t *mutex_p)
int pthread_cond_init_shared(pthread_cond_t **cond_p)
synchandler_args_t synchandler_args[SHARGS_MAX]
char isexpanded[MAXARGUMENTS]
static ssize_t read_inf(int fd, void *buf, size_t count)
static ssize_t write_inf(int fd, const void *buf, size_t count)