]> Zhao Yanbai Git Server - minix.git/commitdiff
PM: extend srv_fork to set a specific UID
authorThomas Veerman <thomas@minix3.org>
Fri, 27 Jan 2012 11:50:11 +0000 (11:50 +0000)
committerThomas Veerman <thomas@minix3.org>
Mon, 30 Jan 2012 15:16:19 +0000 (15:16 +0000)
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.

common/include/minix/com.h
etc/system.conf
servers/avfs/main.c
servers/pm/exec.c
servers/pm/forkexit.c
servers/rs/exec.c
servers/rs/main.c
servers/rs/manager.c
servers/rs/proto.h
servers/vfs/main.c

index 1278c6018e7855c959110a9113a0010853099287..c1c4f6f40c516709ac8d7008adebc2b8c22e0c30 100644 (file)
 #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 */
index efa65b714068b10cf8b25cc5d34c10ec72d244d9..7a021b8120147901701ebd2ca10c28d04557e724 100644 (file)
@@ -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
index 85ac294b8bd04d091e6e3df54c47d0e14fe9d7df..bca40234a339ac236478bad28326bbd327b87af0 100644 (file)
@@ -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;
index 2b03018a8fafdacd96791ec7f583e44c1b2708b3..0942b997091fb7cdadaa82ccc980a18f1b0aa253 100644 (file)
@@ -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);
index 020bc6e7ff1f03391d3f9e645fbbd12774520bf5..49ea34585b2a1e227f048c2c778149a8e87631f2 100644 (file)
@@ -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);
 
index 1e5556b54335361dc5739704a7a667e2df9ce756..a706d0d9df24e5dacd46fde2b9698215520bdad4 100644 (file)
@@ -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';
 
index 34b376b22e833a37f8031d6f360d9673e00ca6a7..ebbf3ead373074f6148dbad4a9e66a8c085dffdb 100644 (file)
@@ -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");
   }
index d9dd58075e4b6f0b4fd52f5845609e260fa5af72..b524a06de990b808989170c9ee2249e3dbf9e9bc 100644 (file)
@@ -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);
index 1a0fe047ef4890ca6863e4301d78807588280029..3f9ba4a0a523e56444d1c60aee42dc0933e8aafb 100644 (file)
@@ -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) \
index 53a631b15172146abe4a2d146fb7a64b4105b760..34165898a0e8b23954b393adfbca2391c4673eb0 100644 (file)
@@ -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;