From 28fcbc589634cf68e233cbfb407a1eb19db32bcd Mon Sep 17 00:00:00 2001 From: erdgeist <> Date: Thu, 28 Mar 2013 18:29:47 +0000 Subject: Introduce -u switch to allow dropping the probes' uid to something non-root processes in the jail can send signals to --- jaildaemon.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/jaildaemon.c b/jaildaemon.c index a4e2d8d..62dcc51 100644 --- a/jaildaemon.c +++ b/jaildaemon.c @@ -42,6 +42,7 @@ static size_t g_probes_size; typedef struct { int m_jid; int m_flags; + uid_t m_uid; char *m_commandline; char *m_proctitle; } daemon_task; @@ -53,7 +54,7 @@ static void remove_files( void ); static int check_for_jail( int jid ); static int copy_daemontask( daemon_task ** out, daemon_task * const in ); static int add_task_to_kqueue( int kq, daemon_task * task_in ); -static pid_t fork_and_jail( int jid, char * proctitle ); +static pid_t fork_and_jail( int jid, uid_t uid, char * proctitle ); static void fork_and_execve( int kq, daemon_task * task ); static int fork_fork_slave( ); static void exerr( char * message, ... ); @@ -92,8 +93,9 @@ static void exerr( char * message, ... ) { /* Report syntax of command line arguments to the user */ static void usage( char * cmd ) { fprintf( stderr, - "%s -D [-ppidfile] [-fipcsockpath]\n" - "%s -c command -j jid [-t proctitle] [-rR] [-fipcsockpath]\n", + "%s -D [-p pidfile] [-f ipcsockpath]\n" + "%s -c command -j jid [-t proctitle] [-rR] [-u uid] -f ipcsockpath]" + "\n", cmd, cmd ); exit( 1 ); } @@ -122,7 +124,8 @@ static void fork_slave( int master_fd ) { case IPC_PACKETSIZE: /* Decode packet and throw a forked child */ *(pid_t*)g_ipc_packet = fork_and_jail( - g_ipc_packet_int[0], g_ipc_packet + sizeof(int) ); + g_ipc_packet_int[0], (uid_t)g_ipc_packet_int[1], + g_ipc_packet + 2 * sizeof(int) ); if( write( master_fd, g_ipc_packet, sizeof(pid_t) ) != sizeof(pid_t) ) exerr( "Error: Can not reply to master." ); @@ -188,7 +191,7 @@ static int check_for_jail( int jid ) { return -1; } -static pid_t fork_and_jail( int jid, char * proctitle ) { +static pid_t fork_and_jail( int jid, uid_t uid, char * proctitle ) { int sig; pid_t pid = fork(); if( !pid ) { @@ -204,6 +207,9 @@ static pid_t fork_and_jail( int jid, char * proctitle ) { if( jail_attach( jid ) ) exerr( "Error: Can not attach process to jail %d.", jid ); + /* If we're supposed to drop privileges, do it now */ + setuid( uid ); + /* wait for SIGHUP */ sigemptyset(&sigset); sigaddset(&sigset, SIGHUP); @@ -223,6 +229,7 @@ static int copy_daemontask( daemon_task ** out, daemon_task * const in ) { t->m_jid = in->m_jid; t->m_flags = in->m_flags; + t->m_uid = in->m_uid; t->m_commandline = in->m_commandline ? strdup( in->m_commandline ): 0; t->m_proctitle = in->m_proctitle ? strdup( in->m_proctitle ) : 0; @@ -329,9 +336,10 @@ static int add_task_to_kqueue( int kq, daemon_task * t_in ) { /* Forge a command packet for fork slave and send it via control socket */ memset( g_ipc_packet, 0, IPC_PACKETSIZE ); g_ipc_packet_int[0] = t->m_jid; + g_ipc_packet_int[1] = t->m_uid; if( t->m_proctitle ) - strncpy( g_ipc_packet + sizeof(int), t->m_proctitle, - IPC_PACKETSIZE - sizeof(int) ); + strncpy( g_ipc_packet + 2 * sizeof(int), t->m_proctitle, + IPC_PACKETSIZE - 2 * sizeof(int) ); if( write( g_fork_slave_fd, g_ipc_packet, IPC_PACKETSIZE ) != IPC_PACKETSIZE ) exerr( "Error: Can not send task to fork slave." ); @@ -389,7 +397,7 @@ static int add_task_to_kqueue( int kq, daemon_task * t_in ) { } /* jaildaemon -D [-ppidfile] [-fipcsockpath] - jaildaemon -c command -j jid -t proctitle [-rR] [-fipsockpath] + jaildaemon -c command -j jid [-t proctitle] [-rR] [-u uid] [-fipsockpath] */ int main( int argc, char **argv ) { pid_t second_pid; @@ -397,6 +405,7 @@ int main( int argc, char **argv ) { int o_force_daemon = 0; int o_daemonize = 0, o_jid = -1, o_respawn = TASK_SINGLESHOT; char *o_command = NULL, *o_pidfile = NULL, *o_proctitle = NULL; + uid_t o_uid = 0; struct kevent ke; struct sockaddr_un addr; struct sigaction sa; @@ -409,7 +418,7 @@ int main( int argc, char **argv ) { i=1; while(i) { - switch( getopt( argc, argv, "DFrRt:c:j:p:f:" ) ) { + switch( getopt( argc, argv, "DFrRt:c:j:p:u:f:" ) ) { case -1: i=0; break; case 'D': o_daemonize = 1; break; case 'r': o_respawn = TASK_RESPAWN; break; @@ -417,6 +426,7 @@ int main( int argc, char **argv ) { case 't': o_proctitle = optarg; break; case 'c': o_command = optarg; break; case 'j': o_jid = strtol( optarg, 0, 0 ); break; + case 'u': o_uid = strtol( optarg, 0, 0 ); break; case 'p': o_pidfile = optarg; break; case 'f': g_uds_path = optarg; break; case 'F': o_force_daemon = 1; break; @@ -447,6 +457,7 @@ int main( int argc, char **argv ) { Packed packet format: int m_flags: SINGLESHOT, RESPAWN, RESPAWN_IMMEDIATE, RESPAWNING int m_jid + int m_uid int m_commandline_length int m_proctitle_length char[] command_line \0 @@ -454,7 +465,7 @@ int main( int argc, char **argv ) { */ size_t o_command_len = strlen(o_command); size_t o_proctitle_len = o_proctitle ? strlen( o_proctitle ) : 0; - char *text_off = (char*)(g_ipc_packet_int + 4); + char *text_off = (char*)(g_ipc_packet_int + 5); if( text_off + 2 + o_command_len + o_proctitle_len > g_ipc_packet + IPC_PACKETSIZE ) @@ -462,8 +473,9 @@ int main( int argc, char **argv ) { g_ipc_packet_int[0] = o_respawn; g_ipc_packet_int[1] = o_jid; - g_ipc_packet_int[2] = o_command_len; - g_ipc_packet_int[3] = o_proctitle_len; + g_ipc_packet_int[2] = o_uid; + g_ipc_packet_int[3] = o_command_len; + g_ipc_packet_int[4] = o_proctitle_len; memcpy( text_off, o_command, o_command_len + 1 ); if( o_proctitle_len ) { text_off += o_command_len + 1; @@ -623,7 +635,7 @@ int main( int argc, char **argv ) { break; case EVFILT_READ: if( (int)ke.ident == g_uds ) { - char *text_off = (char*)(g_ipc_packet_int + 4); + char *text_off = (char*)(g_ipc_packet_int + 5); socklen_t fromlen; daemon_task task; @@ -641,8 +653,9 @@ int main( int argc, char **argv ) { task.m_flags = g_ipc_packet_int[0]; task.m_jid = g_ipc_packet_int[1]; + task.m_uid = g_ipc_packet_int[2]; task.m_commandline = text_off; - text_off += g_ipc_packet_int[2]; + text_off += g_ipc_packet_int[3]; /* Sanity check on string length, expect terminator */ if( text_off > (char *)( g_ipc_packet + IPC_PACKETSIZE ) || @@ -651,8 +664,8 @@ int main( int argc, char **argv ) { continue; } - task.m_proctitle = g_ipc_packet_int[3] ? ++text_off : 0; - text_off += g_ipc_packet_int[3]; + task.m_proctitle = g_ipc_packet_int[4] ? ++text_off : 0; + text_off += g_ipc_packet_int[4]; /* Sanity check on string length, expect terminator */ if( text_off > (char *)(g_ipc_packet + IPC_PACKETSIZE) || -- cgit v1.2.3