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
					
				| @ -764,39 +764,41 @@ | ||||
| #define PM_SETGROUPS_REPLY	(PM_RS_BASE + 11) | ||||
| 
 | ||||
| /* 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 */ | ||||
| #  define PM_SLOT		m1_i2	/* process slot number */ | ||||
| #  define PM_PID		m1_i3	/* process pid */ | ||||
| #  define PM_SLOT		m7_i2	/* process slot number */ | ||||
| #  define PM_PID		m7_i3	/* process pid */ | ||||
| 
 | ||||
| /* Additional parameters for PM_SETUID and PM_SETGID */ | ||||
| #  define PM_EID		m1_i2	/* effective user/group id */ | ||||
| #  define PM_RID		m1_i3	/* real user/group id */ | ||||
| #  define PM_EID		m7_i2	/* effective user/group id */ | ||||
| #  define PM_RID		m7_i3	/* real user/group id */ | ||||
| 
 | ||||
| /* Additional parameter for PM_SETGROUPS */ | ||||
| #  define PM_GROUP_NO		m1_i2	/* number of groups */ | ||||
| #  define PM_GROUP_ADDR		m1_p1	/* struct holding group data */ | ||||
| #  define PM_GROUP_NO		m7_i2	/* number of groups */ | ||||
| #  define PM_GROUP_ADDR		m7_p1	/* struct holding group data */ | ||||
| 
 | ||||
| /* Additional parameters for PM_EXEC */ | ||||
| #  define PM_PATH		m1_p1	/* executable */ | ||||
| #  define PM_PATH_LEN		m1_i2	/* length of path including | ||||
| #  define PM_PATH		m7_p1	/* executable */ | ||||
| #  define PM_PATH_LEN		m7_i2	/* length of path including | ||||
| 					 * terminating null character | ||||
| 					 */ | ||||
| #  define PM_FRAME		m1_p2	/* arguments and environment */ | ||||
| #  define PM_FRAME_LEN		m1_i3	/* size of frame */ | ||||
| #  define PM_FRAME		m7_p2	/* arguments and environment */ | ||||
| #  define PM_FRAME_LEN		m7_i3	/* size of frame */ | ||||
| 
 | ||||
| /* Additional parameters for PM_EXEC_REPLY and PM_CORE_REPLY */ | ||||
| #  define PM_STATUS		m1_i2	/* OK or failure */ | ||||
| #  define PM_PC	        m1_p1	/* program counter */ | ||||
| #  define PM_STATUS		m7_i2	/* OK or failure */ | ||||
| #  define PM_PC			m7_p1	/* program counter */ | ||||
| 
 | ||||
| /* Additional parameters for PM_FORK and PM_SRV_FORK */ | ||||
| #  define PM_PPROC		m1_i2	/* parent process endpoint */ | ||||
| #  define PM_CPID		m1_i3	/* child pid */ | ||||
| #  define PM_PPROC		m7_i2	/* parent process endpoint */ | ||||
| #  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 */ | ||||
| #  define PM_TERM_SIG		m1_i2	/* process's termination signal */ | ||||
| #  define PM_TRACED_PROC	m1_i3	/* required for T_DUMPCORE */ | ||||
| #  define PM_TERM_SIG		m7_i2	/* process's termination signal */ | ||||
| #  define PM_TRACED_PROC	m7_i3	/* required for T_DUMPCORE */ | ||||
| 
 | ||||
| /* Parameters for the EXEC_NEWMEM call */ | ||||
| #define EXC_NM_PROC	m1_i1		/* process that needs new map */ | ||||
|  | ||||
| @ -104,7 +104,6 @@ service vfs | ||||
| 
 | ||||
| service mfs | ||||
| { | ||||
| 	uid     0; | ||||
| 	ipc	ALL_SYS;	# All system ipc targets allowed | ||||
| 	system	BASIC;		# Only basic kernel calls allowed | ||||
| 	vm	BASIC;		# Only basic VM calls allowed | ||||
| @ -144,7 +143,6 @@ service ext2 | ||||
| 
 | ||||
| service pfs | ||||
| { | ||||
| 	uid     0; | ||||
| 	ipc	ALL_SYS;	# All system ipc targets allowed | ||||
| 	system	BASIC;		# Only basic kernel calls allowed | ||||
| 	vm	BASIC;		# Only basic VM calls allowed | ||||
|  | ||||
| @ -908,8 +908,14 @@ PRIVATE void service_pm() | ||||
|     case PM_FORK: | ||||
|     case PM_SRV_FORK: | ||||
| 	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; | ||||
| 
 | ||||
| 	break; | ||||
|  | ||||
| @ -89,7 +89,9 @@ PUBLIC int do_exec_newmem() | ||||
| 		if (rmp->mp_tracer == NO_TRACER) { | ||||
| 			/* Okay, setuid execution is allowed */ | ||||
| 			allow_setuid = 1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (allow_setuid && args.setugid) { | ||||
| 			rmp->mp_effuid = args.new_uid; | ||||
| 			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_res3= flags; | ||||
| 		if (allow_setuid) | ||||
| 		if (allow_setuid && args.setugid) | ||||
| 			mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID; | ||||
| 	} else { | ||||
| 		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_PPROC = rmp->mp_endpoint; | ||||
|   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); | ||||
| 
 | ||||
| @ -198,6 +200,10 @@ PUBLIC int do_srv_fork() | ||||
|   rmc->mp_exitstatus = 0; | ||||
|   rmc->mp_sigstatus = 0; | ||||
|   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++) | ||||
| 	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_PPROC = rmp->mp_endpoint; | ||||
|   m.PM_CPID = rmc->mp_pid; | ||||
|   m.PM_REUID = m_in.m1_i1; | ||||
|   m.PM_REGID = m_in.m1_i2; | ||||
| 
 | ||||
|   tell_vfs(rmc, &m); | ||||
| 
 | ||||
|  | ||||
| @ -193,6 +193,7 @@ static int load_aout(struct exec_info *execi) | ||||
| 
 | ||||
| 	new_uid= getuid(); | ||||
| 	new_gid= getgid(); | ||||
| 	allow_setuid = 0; | ||||
| 
 | ||||
| 	/* XXX what should we use to identify the executable? */ | ||||
| 	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_gid= getgid(); | ||||
|   allow_setuid = 0; | ||||
| 
 | ||||
|   sep_id = 0; | ||||
|   is_elf = 1; | ||||
| @ -347,6 +349,7 @@ static int exec_newmem( | ||||
| 	e.enst_ctime= ctime; | ||||
| 	e.new_uid= new_uid; | ||||
| 	e.new_gid= new_gid; | ||||
| 	e.setugid= *allow_setuidp; | ||||
| 	strncpy(e.progname, progname, sizeof(e.progname)-1); | ||||
| 	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); | ||||
|   } | ||||
| 
 | ||||
|   /* Fork a new RS instance. */ | ||||
|   pid = srv_fork(); | ||||
|   /* Fork a new RS instance with root:operator. */ | ||||
|   pid = srv_fork(0, 0); | ||||
|   if(pid == -1) { | ||||
|       panic("unable to fork a new RS instance"); | ||||
|   } | ||||
|  | ||||
| @ -211,11 +211,13 @@ PUBLIC void build_cmd_dep(struct rproc *rp) | ||||
| /*===========================================================================*
 | ||||
|  *				 srv_fork				     * | ||||
|  *===========================================================================*/ | ||||
| PUBLIC pid_t srv_fork() | ||||
| PUBLIC pid_t srv_fork(uid_t reuid, gid_t regid) | ||||
| { | ||||
|   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) | ||||
|       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) { | ||||
|       printf("RS: srv_fork() failed (error %d)\n", errno); | ||||
|       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, | ||||
| 	char *dst_label, size_t dst_len) ); | ||||
| _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_update, (endpoint_t src_e, endpoint_t dst_e) ); | ||||
| #define kill_service(rp, errstr, err) \ | ||||
|  | ||||
| @ -566,8 +566,14 @@ PRIVATE void service_pm() | ||||
|   case PM_FORK: | ||||
|   case PM_SRV_FORK: | ||||
| 	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; | ||||
| 
 | ||||
| 	break; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Thomas Veerman
						Thomas Veerman