PM: extend srv_fork to set a specific UID
Currently, all servers and drivers run as root as they are forks of RS. srv_fork now tells PM with which credentials to run the resulting fork. Subsequently, PM lets VFS now as well. This patch also fixes the following bugs: - RS doesn't initialize the setugid variable during exec, causing the servers and drivers to run setuid rendering the srv_fork extension useless. - PM erroneously tells VFS to run processes setuid. This doesn't actually lead to setuid processes as VFS sets {r,e}uid and {r,e}gid properly before checking PM's approval.
This commit is contained in:
parent
4bee3cff2e
commit
0bd011affd
10 changed files with 55 additions and 28 deletions
|
@ -764,39 +764,41 @@
|
||||||
#define PM_SETGROUPS_REPLY (PM_RS_BASE + 11)
|
#define PM_SETGROUPS_REPLY (PM_RS_BASE + 11)
|
||||||
|
|
||||||
/* Standard parameters for all requests and replies, except PM_REBOOT */
|
/* Standard parameters for all requests and replies, except PM_REBOOT */
|
||||||
# define PM_PROC m1_i1 /* process endpoint */
|
# define PM_PROC m7_i1 /* process endpoint */
|
||||||
|
|
||||||
/* Additional parameters for PM_INIT */
|
/* Additional parameters for PM_INIT */
|
||||||
# define PM_SLOT m1_i2 /* process slot number */
|
# define PM_SLOT m7_i2 /* process slot number */
|
||||||
# define PM_PID m1_i3 /* process pid */
|
# define PM_PID m7_i3 /* process pid */
|
||||||
|
|
||||||
/* Additional parameters for PM_SETUID and PM_SETGID */
|
/* Additional parameters for PM_SETUID and PM_SETGID */
|
||||||
# define PM_EID m1_i2 /* effective user/group id */
|
# define PM_EID m7_i2 /* effective user/group id */
|
||||||
# define PM_RID m1_i3 /* real user/group id */
|
# define PM_RID m7_i3 /* real user/group id */
|
||||||
|
|
||||||
/* Additional parameter for PM_SETGROUPS */
|
/* Additional parameter for PM_SETGROUPS */
|
||||||
# define PM_GROUP_NO m1_i2 /* number of groups */
|
# define PM_GROUP_NO m7_i2 /* number of groups */
|
||||||
# define PM_GROUP_ADDR m1_p1 /* struct holding group data */
|
# define PM_GROUP_ADDR m7_p1 /* struct holding group data */
|
||||||
|
|
||||||
/* Additional parameters for PM_EXEC */
|
/* Additional parameters for PM_EXEC */
|
||||||
# define PM_PATH m1_p1 /* executable */
|
# define PM_PATH m7_p1 /* executable */
|
||||||
# define PM_PATH_LEN m1_i2 /* length of path including
|
# define PM_PATH_LEN m7_i2 /* length of path including
|
||||||
* terminating null character
|
* terminating null character
|
||||||
*/
|
*/
|
||||||
# define PM_FRAME m1_p2 /* arguments and environment */
|
# define PM_FRAME m7_p2 /* arguments and environment */
|
||||||
# define PM_FRAME_LEN m1_i3 /* size of frame */
|
# define PM_FRAME_LEN m7_i3 /* size of frame */
|
||||||
|
|
||||||
/* Additional parameters for PM_EXEC_REPLY and PM_CORE_REPLY */
|
/* Additional parameters for PM_EXEC_REPLY and PM_CORE_REPLY */
|
||||||
# define PM_STATUS m1_i2 /* OK or failure */
|
# define PM_STATUS m7_i2 /* OK or failure */
|
||||||
# define PM_PC m1_p1 /* program counter */
|
# define PM_PC m7_p1 /* program counter */
|
||||||
|
|
||||||
/* Additional parameters for PM_FORK and PM_SRV_FORK */
|
/* Additional parameters for PM_FORK and PM_SRV_FORK */
|
||||||
# define PM_PPROC m1_i2 /* parent process endpoint */
|
# define PM_PPROC m7_i2 /* parent process endpoint */
|
||||||
# define PM_CPID m1_i3 /* child pid */
|
# define PM_CPID m7_i3 /* child pid */
|
||||||
|
# define PM_REUID m7_i4 /* real and effective uid */
|
||||||
|
# define PM_REGID m7_i5 /* real and effective gid */
|
||||||
|
|
||||||
/* Additional parameters for PM_DUMPCORE */
|
/* Additional parameters for PM_DUMPCORE */
|
||||||
# define PM_TERM_SIG m1_i2 /* process's termination signal */
|
# define PM_TERM_SIG m7_i2 /* process's termination signal */
|
||||||
# define PM_TRACED_PROC m1_i3 /* required for T_DUMPCORE */
|
# define PM_TRACED_PROC m7_i3 /* required for T_DUMPCORE */
|
||||||
|
|
||||||
/* Parameters for the EXEC_NEWMEM call */
|
/* Parameters for the EXEC_NEWMEM call */
|
||||||
#define EXC_NM_PROC m1_i1 /* process that needs new map */
|
#define EXC_NM_PROC m1_i1 /* process that needs new map */
|
||||||
|
|
|
@ -104,7 +104,6 @@ service vfs
|
||||||
|
|
||||||
service mfs
|
service mfs
|
||||||
{
|
{
|
||||||
uid 0;
|
|
||||||
ipc ALL_SYS; # All system ipc targets allowed
|
ipc ALL_SYS; # All system ipc targets allowed
|
||||||
system BASIC; # Only basic kernel calls allowed
|
system BASIC; # Only basic kernel calls allowed
|
||||||
vm BASIC; # Only basic VM calls allowed
|
vm BASIC; # Only basic VM calls allowed
|
||||||
|
@ -144,7 +143,6 @@ service ext2
|
||||||
|
|
||||||
service pfs
|
service pfs
|
||||||
{
|
{
|
||||||
uid 0;
|
|
||||||
ipc ALL_SYS; # All system ipc targets allowed
|
ipc ALL_SYS; # All system ipc targets allowed
|
||||||
system BASIC; # Only basic kernel calls allowed
|
system BASIC; # Only basic kernel calls allowed
|
||||||
vm BASIC; # Only basic VM calls allowed
|
vm BASIC; # Only basic VM calls allowed
|
||||||
|
|
|
@ -908,8 +908,14 @@ PRIVATE void service_pm()
|
||||||
case PM_FORK:
|
case PM_FORK:
|
||||||
case PM_SRV_FORK:
|
case PM_SRV_FORK:
|
||||||
pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
|
pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
|
||||||
|
m_out.m_type = PM_FORK_REPLY;
|
||||||
|
|
||||||
|
if (call_nr == PM_SRV_FORK) {
|
||||||
|
m_out.m_type = PM_SRV_FORK_REPLY;
|
||||||
|
pm_setuid(m_in.PM_PROC, m_in.PM_REUID, m_in.PM_REUID);
|
||||||
|
pm_setgid(m_in.PM_PROC, m_in.PM_REGID, m_in.PM_REGID);
|
||||||
|
}
|
||||||
|
|
||||||
m_out.m_type = (call_nr == PM_FORK) ? PM_FORK_REPLY : PM_SRV_FORK_REPLY;
|
|
||||||
m_out.PM_PROC = m_in.PM_PROC;
|
m_out.PM_PROC = m_in.PM_PROC;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -89,7 +89,9 @@ PUBLIC int do_exec_newmem()
|
||||||
if (rmp->mp_tracer == NO_TRACER) {
|
if (rmp->mp_tracer == NO_TRACER) {
|
||||||
/* Okay, setuid execution is allowed */
|
/* Okay, setuid execution is allowed */
|
||||||
allow_setuid = 1;
|
allow_setuid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allow_setuid && args.setugid) {
|
||||||
rmp->mp_effuid = args.new_uid;
|
rmp->mp_effuid = args.new_uid;
|
||||||
rmp->mp_effgid = args.new_gid;
|
rmp->mp_effgid = args.new_gid;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +120,7 @@ PUBLIC int do_exec_newmem()
|
||||||
|
|
||||||
mp->mp_reply.reply_res2= (vir_bytes) stack_top;
|
mp->mp_reply.reply_res2= (vir_bytes) stack_top;
|
||||||
mp->mp_reply.reply_res3= flags;
|
mp->mp_reply.reply_res3= flags;
|
||||||
if (allow_setuid)
|
if (allow_setuid && args.setugid)
|
||||||
mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID;
|
mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID;
|
||||||
} else {
|
} else {
|
||||||
printf("PM: newmem failed for %s\n", args.progname);
|
printf("PM: newmem failed for %s\n", args.progname);
|
||||||
|
|
|
@ -120,6 +120,8 @@ PUBLIC int do_fork()
|
||||||
m.PM_PROC = rmc->mp_endpoint;
|
m.PM_PROC = rmc->mp_endpoint;
|
||||||
m.PM_PPROC = rmp->mp_endpoint;
|
m.PM_PPROC = rmp->mp_endpoint;
|
||||||
m.PM_CPID = rmc->mp_pid;
|
m.PM_CPID = rmc->mp_pid;
|
||||||
|
m.PM_REUID = -1; /* Not used by PM_FORK */
|
||||||
|
m.PM_REGID = -1; /* Not used by PM_FORK */
|
||||||
|
|
||||||
tell_vfs(rmc, &m);
|
tell_vfs(rmc, &m);
|
||||||
|
|
||||||
|
@ -198,6 +200,10 @@ PUBLIC int do_srv_fork()
|
||||||
rmc->mp_exitstatus = 0;
|
rmc->mp_exitstatus = 0;
|
||||||
rmc->mp_sigstatus = 0;
|
rmc->mp_sigstatus = 0;
|
||||||
rmc->mp_endpoint = child_ep; /* passed back by VM */
|
rmc->mp_endpoint = child_ep; /* passed back by VM */
|
||||||
|
rmc->mp_realuid = (uid_t) m_in.m1_i1;
|
||||||
|
rmc->mp_effuid = (uid_t) m_in.m1_i1;
|
||||||
|
rmc->mp_realgid = (uid_t) m_in.m1_i2;
|
||||||
|
rmc->mp_effgid = (uid_t) m_in.m1_i2;
|
||||||
for (i = 0; i < NR_ITIMERS; i++)
|
for (i = 0; i < NR_ITIMERS; i++)
|
||||||
rmc->mp_interval[i] = 0; /* reset timer intervals */
|
rmc->mp_interval[i] = 0; /* reset timer intervals */
|
||||||
|
|
||||||
|
@ -209,6 +215,8 @@ PUBLIC int do_srv_fork()
|
||||||
m.PM_PROC = rmc->mp_endpoint;
|
m.PM_PROC = rmc->mp_endpoint;
|
||||||
m.PM_PPROC = rmp->mp_endpoint;
|
m.PM_PPROC = rmp->mp_endpoint;
|
||||||
m.PM_CPID = rmc->mp_pid;
|
m.PM_CPID = rmc->mp_pid;
|
||||||
|
m.PM_REUID = m_in.m1_i1;
|
||||||
|
m.PM_REGID = m_in.m1_i2;
|
||||||
|
|
||||||
tell_vfs(rmc, &m);
|
tell_vfs(rmc, &m);
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,7 @@ static int load_aout(struct exec_info *execi)
|
||||||
|
|
||||||
new_uid= getuid();
|
new_uid= getuid();
|
||||||
new_gid= getgid();
|
new_gid= getgid();
|
||||||
|
allow_setuid = 0;
|
||||||
|
|
||||||
/* XXX what should we use to identify the executable? */
|
/* XXX what should we use to identify the executable? */
|
||||||
r= exec_newmem(proc_e, 0 /*text_addr*/, text_bytes,
|
r= exec_newmem(proc_e, 0 /*text_addr*/, text_bytes,
|
||||||
|
@ -263,6 +264,7 @@ static int load_elf(struct exec_info *execi)
|
||||||
|
|
||||||
new_uid= getuid();
|
new_uid= getuid();
|
||||||
new_gid= getgid();
|
new_gid= getgid();
|
||||||
|
allow_setuid = 0;
|
||||||
|
|
||||||
sep_id = 0;
|
sep_id = 0;
|
||||||
is_elf = 1;
|
is_elf = 1;
|
||||||
|
@ -347,6 +349,7 @@ static int exec_newmem(
|
||||||
e.enst_ctime= ctime;
|
e.enst_ctime= ctime;
|
||||||
e.new_uid= new_uid;
|
e.new_uid= new_uid;
|
||||||
e.new_gid= new_gid;
|
e.new_gid= new_gid;
|
||||||
|
e.setugid= *allow_setuidp;
|
||||||
strncpy(e.progname, progname, sizeof(e.progname)-1);
|
strncpy(e.progname, progname, sizeof(e.progname)-1);
|
||||||
e.progname[sizeof(e.progname)-1]= '\0';
|
e.progname[sizeof(e.progname)-1]= '\0';
|
||||||
|
|
||||||
|
|
|
@ -436,8 +436,8 @@ PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||||
panic("unable to clone current RS instance: %d", s);
|
panic("unable to clone current RS instance: %d", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fork a new RS instance. */
|
/* Fork a new RS instance with root:operator. */
|
||||||
pid = srv_fork();
|
pid = srv_fork(0, 0);
|
||||||
if(pid == -1) {
|
if(pid == -1) {
|
||||||
panic("unable to fork a new RS instance");
|
panic("unable to fork a new RS instance");
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,11 +211,13 @@ PUBLIC void build_cmd_dep(struct rproc *rp)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* srv_fork *
|
* srv_fork *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC pid_t srv_fork()
|
PUBLIC pid_t srv_fork(uid_t reuid, gid_t regid)
|
||||||
{
|
{
|
||||||
message m;
|
message m;
|
||||||
|
|
||||||
return(_syscall(PM_PROC_NR, SRV_FORK, &m));
|
m.m1_i1 = (int) reuid;
|
||||||
|
m.m1_i2 = (int) regid;
|
||||||
|
return _syscall(PM_PROC_NR, SRV_FORK, &m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -476,7 +478,7 @@ struct rproc *rp;
|
||||||
*/
|
*/
|
||||||
if(rs_verbose)
|
if(rs_verbose)
|
||||||
printf("RS: forking child with srv_fork()...\n");
|
printf("RS: forking child with srv_fork()...\n");
|
||||||
child_pid= srv_fork();
|
child_pid= srv_fork(rp->r_uid, 0); /* Force group to operator for now */
|
||||||
if(child_pid == -1) {
|
if(child_pid == -1) {
|
||||||
printf("RS: srv_fork() failed (error %d)\n", errno);
|
printf("RS: srv_fork() failed (error %d)\n", errno);
|
||||||
free_slot(rp);
|
free_slot(rp);
|
||||||
|
|
|
@ -34,7 +34,7 @@ _PROTOTYPE( int copy_rs_start, (endpoint_t src_e, char *src_rs_start,
|
||||||
_PROTOTYPE( int copy_label, (endpoint_t src_e, char *src_label, size_t src_len,
|
_PROTOTYPE( int copy_label, (endpoint_t src_e, char *src_label, size_t src_len,
|
||||||
char *dst_label, size_t dst_len) );
|
char *dst_label, size_t dst_len) );
|
||||||
_PROTOTYPE( void build_cmd_dep, (struct rproc *rp) );
|
_PROTOTYPE( void build_cmd_dep, (struct rproc *rp) );
|
||||||
_PROTOTYPE( int srv_fork, (void) );
|
_PROTOTYPE( int srv_fork, (uid_t reuid, gid_t regid) );
|
||||||
_PROTOTYPE( int srv_kill, (pid_t pid, int sig) );
|
_PROTOTYPE( int srv_kill, (pid_t pid, int sig) );
|
||||||
_PROTOTYPE( int srv_update, (endpoint_t src_e, endpoint_t dst_e) );
|
_PROTOTYPE( int srv_update, (endpoint_t src_e, endpoint_t dst_e) );
|
||||||
#define kill_service(rp, errstr, err) \
|
#define kill_service(rp, errstr, err) \
|
||||||
|
|
|
@ -566,8 +566,14 @@ PRIVATE void service_pm()
|
||||||
case PM_FORK:
|
case PM_FORK:
|
||||||
case PM_SRV_FORK:
|
case PM_SRV_FORK:
|
||||||
pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
|
pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
|
||||||
|
m_out.m_type = PM_FORK_REPLY;
|
||||||
|
|
||||||
|
if (call_nr == PM_SRV_FORK) {
|
||||||
|
m_out.m_type = PM_SRV_FORK_REPLY;
|
||||||
|
pm_setuid(m_in.PM_PROC, m_in.PM_REUID, m_in.PM_REUID);
|
||||||
|
pm_setgid(m_in.PM_PROC, m_in.PM_REGID, m_in.PM_REGID);
|
||||||
|
}
|
||||||
|
|
||||||
m_out.m_type = (call_nr == PM_FORK) ? PM_FORK_REPLY : PM_SRV_FORK_REPLY;
|
|
||||||
m_out.PM_PROC = m_in.PM_PROC;
|
m_out.PM_PROC = m_in.PM_PROC;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue