PM: add support for saved user/group IDs
This patch aims to synchronize the basic process user and group ID management, as well as the set[ug]id(2) and sete[ug]id(2) behavior, with NetBSD. As it turns out, the main issue was missing support for saved user and group IDs. This support is now added. Since NetBSD's userland, which we are importing, may rely on NetBSD specifics when it comes to security, we choose not to deviate from NetBSD's behavior in any way here. A new test, test89, verifies the correct behavior - it has been confirmed to pass on NetBSD as is. Change-Id: I023935546d97ed01ffd8090f7793d336cceb0f4a
This commit is contained in:
parent
30baa378c4
commit
1122b28691
@ -188,6 +188,7 @@
|
|||||||
./usr/tests/minix-posix/test86 minix-tests
|
./usr/tests/minix-posix/test86 minix-tests
|
||||||
./usr/tests/minix-posix/test87 minix-tests
|
./usr/tests/minix-posix/test87 minix-tests
|
||||||
./usr/tests/minix-posix/test88 minix-tests
|
./usr/tests/minix-posix/test88 minix-tests
|
||||||
|
./usr/tests/minix-posix/test89 minix-tests
|
||||||
./usr/tests/minix-posix/test9 minix-tests
|
./usr/tests/minix-posix/test9 minix-tests
|
||||||
./usr/tests/minix-posix/testinterp minix-tests
|
./usr/tests/minix-posix/testinterp minix-tests
|
||||||
./usr/tests/minix-posix/testisofs minix-tests
|
./usr/tests/minix-posix/testisofs minix-tests
|
||||||
|
@ -750,6 +750,8 @@ fill_proc2_user(struct kinfo_proc2 * p, int mslot)
|
|||||||
p->p_uctime_usec = tv.tv_usec;
|
p->p_uctime_usec = tv.tv_usec;
|
||||||
p->p_realflag = p->p_flag;
|
p->p_realflag = p->p_flag;
|
||||||
p->p_nlwps = (zombie) ? 0 : 1;
|
p->p_nlwps = (zombie) ? 0 : 1;
|
||||||
|
p->p_svuid = mp->mp_svuid;
|
||||||
|
p->p_svgid = mp->mp_svgid;
|
||||||
|
|
||||||
p->p_stat = get_lwp_stat(mslot, &p->p_wchan, p->p_wmesg,
|
p->p_stat = get_lwp_stat(mslot, &p->p_wchan, p->p_wmesg,
|
||||||
sizeof(p->p_wmesg), &p->p_flag);
|
sizeof(p->p_wmesg), &p->p_flag);
|
||||||
|
@ -92,6 +92,10 @@ int do_newexec(void)
|
|||||||
rmp->mp_effgid = args.new_gid;
|
rmp->mp_effgid = args.new_gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Always update the saved user and group ID at this point. */
|
||||||
|
rmp->mp_svuid = rmp->mp_effuid;
|
||||||
|
rmp->mp_svgid = rmp->mp_effgid;
|
||||||
|
|
||||||
/* A process is considered 'tainted' when it's executing with
|
/* A process is considered 'tainted' when it's executing with
|
||||||
* setuid or setgid bit set, or when the real{u,g}id doesn't
|
* setuid or setgid bit set, or when the real{u,g}id doesn't
|
||||||
* match the eff{u,g}id, respectively. */
|
* match the eff{u,g}id, respectively. */
|
||||||
|
@ -203,8 +203,10 @@ int do_srv_fork()
|
|||||||
rmc->mp_endpoint = child_ep; /* passed back by VM */
|
rmc->mp_endpoint = child_ep; /* passed back by VM */
|
||||||
rmc->mp_realuid = m_in.m_lsys_pm_srv_fork.uid;
|
rmc->mp_realuid = m_in.m_lsys_pm_srv_fork.uid;
|
||||||
rmc->mp_effuid = m_in.m_lsys_pm_srv_fork.uid;
|
rmc->mp_effuid = m_in.m_lsys_pm_srv_fork.uid;
|
||||||
|
rmc->mp_svuid = m_in.m_lsys_pm_srv_fork.uid;
|
||||||
rmc->mp_realgid = m_in.m_lsys_pm_srv_fork.gid;
|
rmc->mp_realgid = m_in.m_lsys_pm_srv_fork.gid;
|
||||||
rmc->mp_effgid = m_in.m_lsys_pm_srv_fork.gid;
|
rmc->mp_effgid = m_in.m_lsys_pm_srv_fork.gid;
|
||||||
|
rmc->mp_svgid = m_in.m_lsys_pm_srv_fork.gid;
|
||||||
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 */
|
||||||
rmc->mp_started = getticks(); /* remember start time, for ps(1) */
|
rmc->mp_started = getticks(); /* remember start time, for ps(1) */
|
||||||
|
@ -107,11 +107,28 @@ int do_set()
|
|||||||
|
|
||||||
switch(call_nr) {
|
switch(call_nr) {
|
||||||
case PM_SETUID:
|
case PM_SETUID:
|
||||||
case PM_SETEUID:
|
|
||||||
uid = m_in.m_lc_pm_setuid.uid;
|
uid = m_in.m_lc_pm_setuid.uid;
|
||||||
|
/* NetBSD specific semantics: setuid(geteuid()) may fail. */
|
||||||
if (rmp->mp_realuid != uid && rmp->mp_effuid != SUPER_USER)
|
if (rmp->mp_realuid != uid && rmp->mp_effuid != SUPER_USER)
|
||||||
return(EPERM);
|
return(EPERM);
|
||||||
if(call_nr == PM_SETUID) rmp->mp_realuid = uid;
|
/* BSD semantics: always update all three fields. */
|
||||||
|
rmp->mp_realuid = uid;
|
||||||
|
rmp->mp_effuid = uid;
|
||||||
|
rmp->mp_svuid = uid;
|
||||||
|
|
||||||
|
m.m_type = VFS_PM_SETUID;
|
||||||
|
m.VFS_PM_ENDPT = rmp->mp_endpoint;
|
||||||
|
m.VFS_PM_EID = rmp->mp_effuid;
|
||||||
|
m.VFS_PM_RID = rmp->mp_realuid;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_SETEUID:
|
||||||
|
uid = m_in.m_lc_pm_setuid.uid;
|
||||||
|
/* BSD semantics: seteuid(geteuid()) may fail. */
|
||||||
|
if (rmp->mp_realuid != uid && rmp->mp_svuid != uid &&
|
||||||
|
rmp->mp_effuid != SUPER_USER)
|
||||||
|
return(EPERM);
|
||||||
rmp->mp_effuid = uid;
|
rmp->mp_effuid = uid;
|
||||||
|
|
||||||
m.m_type = VFS_PM_SETUID;
|
m.m_type = VFS_PM_SETUID;
|
||||||
@ -122,11 +139,25 @@ int do_set()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_SETGID:
|
case PM_SETGID:
|
||||||
case PM_SETEGID:
|
|
||||||
gid = m_in.m_lc_pm_setgid.gid;
|
gid = m_in.m_lc_pm_setgid.gid;
|
||||||
if (rmp->mp_realgid != gid && rmp->mp_effuid != SUPER_USER)
|
if (rmp->mp_realgid != gid && rmp->mp_effuid != SUPER_USER)
|
||||||
return(EPERM);
|
return(EPERM);
|
||||||
if(call_nr == PM_SETGID) rmp->mp_realgid = gid;
|
rmp->mp_realgid = gid;
|
||||||
|
rmp->mp_effgid = gid;
|
||||||
|
rmp->mp_svgid = gid;
|
||||||
|
|
||||||
|
m.m_type = VFS_PM_SETGID;
|
||||||
|
m.VFS_PM_ENDPT = rmp->mp_endpoint;
|
||||||
|
m.VFS_PM_EID = rmp->mp_effgid;
|
||||||
|
m.VFS_PM_RID = rmp->mp_realgid;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_SETEGID:
|
||||||
|
gid = m_in.m_lc_pm_setgid.gid;
|
||||||
|
if (rmp->mp_realgid != gid && rmp->mp_svgid != gid &&
|
||||||
|
rmp->mp_effuid != SUPER_USER)
|
||||||
|
return(EPERM);
|
||||||
rmp->mp_effgid = gid;
|
rmp->mp_effgid = gid;
|
||||||
|
|
||||||
m.m_type = VFS_PM_SETGID;
|
m.m_type = VFS_PM_SETGID;
|
||||||
@ -135,6 +166,7 @@ int do_set()
|
|||||||
m.VFS_PM_RID = rmp->mp_realgid;
|
m.VFS_PM_RID = rmp->mp_realgid;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_SETGROUPS:
|
case PM_SETGROUPS:
|
||||||
if (rmp->mp_effuid != SUPER_USER)
|
if (rmp->mp_effuid != SUPER_USER)
|
||||||
return(EPERM);
|
return(EPERM);
|
||||||
|
@ -37,11 +37,13 @@ EXTERN struct mproc {
|
|||||||
clock_t mp_child_utime; /* cumulative user time of children */
|
clock_t mp_child_utime; /* cumulative user time of children */
|
||||||
clock_t mp_child_stime; /* cumulative sys time of children */
|
clock_t mp_child_stime; /* cumulative sys time of children */
|
||||||
|
|
||||||
/* Real and effective uids and gids. */
|
/* Real, effective, and saved user and group IDs. */
|
||||||
uid_t mp_realuid; /* process' real uid */
|
uid_t mp_realuid; /* process' real uid */
|
||||||
uid_t mp_effuid; /* process' effective uid */
|
uid_t mp_effuid; /* process' effective uid */
|
||||||
|
uid_t mp_svuid; /* process' saved uid */
|
||||||
gid_t mp_realgid; /* process' real gid */
|
gid_t mp_realgid; /* process' real gid */
|
||||||
gid_t mp_effgid; /* process' effective gid */
|
gid_t mp_effgid; /* process' effective gid */
|
||||||
|
gid_t mp_svgid; /* process' saved gid */
|
||||||
|
|
||||||
/* Supplemental groups. */
|
/* Supplemental groups. */
|
||||||
int mp_ngroups; /* number of supplemental groups */
|
int mp_ngroups; /* number of supplemental groups */
|
||||||
|
@ -59,7 +59,7 @@ MINIX_TESTS= \
|
|||||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||||
41 42 43 44 45 46 48 49 50 52 53 54 55 56 58 59 60 \
|
41 42 43 44 45 46 48 49 50 52 53 54 55 56 58 59 60 \
|
||||||
61 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
|
61 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
|
||||||
81 82 83 84 85 86 87 88
|
81 82 83 84 85 86 87 88 89
|
||||||
|
|
||||||
FILES += t84_h_nonexec.sh
|
FILES += t84_h_nonexec.sh
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ export USENETWORK # set to "yes" for test48+82 to use the network
|
|||||||
|
|
||||||
# Programs that require setuid
|
# Programs that require setuid
|
||||||
setuids="test11 test33 test43 test44 test46 test56 test60 test61 test65 \
|
setuids="test11 test33 test43 test44 test46 test56 test60 test61 test65 \
|
||||||
test69 test73 test74 test78 test83 test85 test87 test88"
|
test69 test73 test74 test78 test83 test85 test87 test88 test89"
|
||||||
# Scripts that require to be run as root
|
# Scripts that require to be run as root
|
||||||
rootscripts="testisofs testvnd testrelpol"
|
rootscripts="testisofs testvnd testrelpol"
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ alltests="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
|||||||
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
|
||||||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
|
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
|
||||||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
|
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
|
||||||
81 82 83 84 85 86 87 88 sh1 sh2 interp mfs isofs vnd"
|
81 82 83 84 85 86 87 88 89 sh1 sh2 interp mfs isofs vnd"
|
||||||
tests_no=`expr 0`
|
tests_no=`expr 0`
|
||||||
|
|
||||||
# If root, make sure the setuid tests have the correct permissions
|
# If root, make sure the setuid tests have the correct permissions
|
||||||
|
@ -43,9 +43,7 @@ test_nonroot(void (* proc)(void))
|
|||||||
|
|
||||||
if ((pw = getpwnam(NONROOT_USER)) == NULL) e(0);
|
if ((pw = getpwnam(NONROOT_USER)) == NULL) e(0);
|
||||||
|
|
||||||
/* FIXME: this may rely on a MINIXism. */
|
|
||||||
if (setuid(pw->pw_uid) != 0) e(0);
|
if (setuid(pw->pw_uid) != 0) e(0);
|
||||||
if (seteuid(pw->pw_uid) != 0) e(0);
|
|
||||||
|
|
||||||
proc();
|
proc();
|
||||||
|
|
||||||
|
@ -105,9 +105,7 @@ spawn(struct link * link, void (* proc)(), int drop)
|
|||||||
case DROP_USER:
|
case DROP_USER:
|
||||||
if ((pw = getpwnam(NONROOT_USER)) == NULL) e(0);
|
if ((pw = getpwnam(NONROOT_USER)) == NULL) e(0);
|
||||||
|
|
||||||
/* FIXME: this may rely on a MINIXism. */
|
|
||||||
if (setuid(pw->pw_uid) != 0) e(0);
|
if (setuid(pw->pw_uid) != 0) e(0);
|
||||||
if (seteuid(pw->pw_uid) != 0) e(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc(link);
|
proc(link);
|
||||||
|
1011
minix/tests/test89.c
Normal file
1011
minix/tests/test89.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user