diff --git a/sys/amd64/amd64/io.c b/sys/amd64/amd64/io.c index 1aaf2ef63282..02d9c8dab230 100644 --- a/sys/amd64/amd64/io.c +++ b/sys/amd64/amd64/io.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -54,7 +55,7 @@ ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, { int error; - error = suser(td); + error = priv_check(td, PRIV_IO); if (error != 0) return (error); error = securelevel_gt(td->td_ucred, 0); diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 962e94fc69b7..cab95c7470dd 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1020,7 +1021,8 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) * Keep cr_groups[0] unchanged to prevent that. */ - if ((error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) { + if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, + SUSER_ALLOWJAIL)) != 0) { PROC_UNLOCK(p); crfree(newcred); return (error); @@ -1341,7 +1343,7 @@ linux_reboot(struct thread *td, struct linux_reboot_args *args) switch (args->cmd) { case REBOOT_CAD_ON: case REBOOT_CAD_OFF: - return suser(td); + return (priv_check(td, PRIV_REBOOT)); case REBOOT_HALT: bsd_args.opt = RB_HALT; break; diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c index ba01aef427ea..ec15826d8145 100644 --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -123,7 +124,8 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) * Keep cr_groups[0] unchanged to prevent that. */ - if ((error = suser_cred(oldcred, SUSER_ALLOWJAIL)) != 0) { + if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, + SUSER_ALLOWJAIL)) != 0) { PROC_UNLOCK(p); crfree(newcred); return (error); diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c index ca135f0c00c5..6073e0d5d5ae 100644 --- a/sys/compat/svr4/svr4_fcntl.c +++ b/sys/compat/svr4/svr4_fcntl.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -280,7 +281,8 @@ fd_revoke(td, fd) goto out; if (td->td_ucred->cr_uid != vattr.va_uid && - (error = suser(td)) != 0) + (error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN, + SUSER_ALLOWJAIL)) != 0) goto out; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index 9ed5bb34c461..f1f44eac4353 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -611,7 +612,8 @@ svr4_sys_fchroot(td, uap) struct file *fp; int error, vfslocked; - if ((error = suser(td)) != 0) + if ((error = priv_check_cred(td->td_ucred, PRIV_VFS_FCHROOT, + SUSER_ALLOWJAIL)) != 0) return error; if ((error = getvnode(fdp, uap->fd, &fp)) != 0) return error; diff --git a/sys/contrib/altq/altq/altq_cbq.c b/sys/contrib/altq/altq/altq_cbq.c index ef759165805e..aafa5c8fdd43 100644 --- a/sys/contrib/altq/altq/altq_cbq.c +++ b/sys/contrib/altq/altq/altq_cbq.c @@ -1062,7 +1062,9 @@ cbqioctl(dev, cmd, addr, flag, p) /* currently only command that an ordinary user can call */ break; default: -#if (__FreeBSD_version > 400000) +#if (__FreeBSD_version > 700000) + error = priv_check(p, PRIV_ALTQ_MANAGE); +#elsif (__FreeBSD_version > 400000) error = suser(p); #else error = suser(p->p_ucred, &p->p_acflag); diff --git a/sys/contrib/altq/altq/altq_cdnr.c b/sys/contrib/altq/altq/altq_cdnr.c index d0a1313f4fb9..3139d51d95b5 100644 --- a/sys/contrib/altq/altq/altq_cdnr.c +++ b/sys/contrib/altq/altq/altq_cdnr.c @@ -1262,7 +1262,9 @@ cdnrioctl(dev, cmd, addr, flag, p) case CDNR_GETSTATS: break; default: -#if (__FreeBSD_version > 400000) +#if (__FreeBSD_version > 700000) + if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0) +#elsif (__FreeBSD_version > 400000) if ((error = suser(p)) != 0) #else if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) diff --git a/sys/contrib/altq/altq/altq_hfsc.c b/sys/contrib/altq/altq/altq_hfsc.c index 7eea5c7e54e4..8fea4dda41ad 100644 --- a/sys/contrib/altq/altq/altq_hfsc.c +++ b/sys/contrib/altq/altq/altq_hfsc.c @@ -1975,7 +1975,10 @@ hfscioctl(dev, cmd, addr, flag, p) case HFSC_GETSTATS: break; default: -#if (__FreeBSD_version > 400000) +#if (__FreeBSD_version > 700000) + if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0) + return (error); +#elsif (__FreeBSD_version > 400000) if ((error = suser(p)) != 0) return (error); #else diff --git a/sys/contrib/altq/altq/altq_priq.c b/sys/contrib/altq/altq/altq_priq.c index e4e84e6e524b..28b0ddb2e30c 100644 --- a/sys/contrib/altq/altq/altq_priq.c +++ b/sys/contrib/altq/altq/altq_priq.c @@ -772,7 +772,10 @@ priqioctl(dev, cmd, addr, flag, p) case PRIQ_GETSTATS: break; default: -#if (__FreeBSD_version > 400000) +#if (__FreeBSD_version > 700000) + if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0) + return (error); +#elsif (__FreeBSD_version > 400000) if ((error = suser(p)) != 0) return (error); #else diff --git a/sys/contrib/altq/altq/altq_red.c b/sys/contrib/altq/altq/altq_red.c index ff6d83260c7e..6010033527ae 100644 --- a/sys/contrib/altq/altq/altq_red.c +++ b/sys/contrib/altq/altq/altq_red.c @@ -781,7 +781,9 @@ redioctl(dev, cmd, addr, flag, p) case RED_GETSTATS: break; default: -#if (__FreeBSD_version > 400000) +#if (__FreeBSD_version > 700000) + if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0) +#elsif (__FreeBSD_version > 400000) if ((error = suser(p)) != 0) #else if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) diff --git a/sys/contrib/altq/altq/altq_rio.c b/sys/contrib/altq/altq/altq_rio.c index 2acf87e65944..a05dba712520 100644 --- a/sys/contrib/altq/altq/altq_rio.c +++ b/sys/contrib/altq/altq/altq_rio.c @@ -531,7 +531,10 @@ rioioctl(dev, cmd, addr, flag, p) case RIO_GETSTATS: break; default: -#if (__FreeBSD_version > 400000) +#if (__FreeBSD_version > 700000) + if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0) + return (error); +#elsif (__FreeBSD_version > 400000) if ((error = suser(p)) != 0) return (error); #else diff --git a/sys/contrib/pf/net/if_pfsync.c b/sys/contrib/pf/net/if_pfsync.c index 957bc7eb2755..bec33e480449 100644 --- a/sys/contrib/pf/net/if_pfsync.c +++ b/sys/contrib/pf/net/if_pfsync.c @@ -54,6 +54,9 @@ #endif #include +#ifdef __FreeBSD__ +#include +#endif #include #include #include @@ -1057,7 +1060,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSETPFSYNC: #ifdef __FreeBSD__ - if ((error = suser(curthread)) != 0) + if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0) #else if ((error = suser(p, p->p_acflag)) != 0) #endif diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c index 0dc49b4584c8..224d51fffea3 100644 --- a/sys/dev/an/if_an.c +++ b/sys/dev/an/if_an.c @@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1920,7 +1921,7 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) break; #ifdef ANCACHE if (sc->areq.an_type == AN_RID_ZERO_CACHE) { - error = suser(td); + error = priv_check(td, PRIV_DRIVER); if (error) break; sc->an_sigitems = sc->an_nextitem = 0; @@ -1944,7 +1945,7 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = copyout(&sc->areq, ifr->ifr_data, sizeof(sc->areq)); break; case SIOCSAIRONET: - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) goto out; error = copyin(ifr->ifr_data, &sc->areq, sizeof(sc->areq)); if (error != 0) @@ -1952,7 +1953,7 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) an_setdef(sc, &sc->areq); break; case SIOCGPRIVATE_0: /* used by Cisco client utility */ - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) goto out; error = copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl)); if (error) @@ -1974,7 +1975,7 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } break; case SIOCGPRIVATE_1: /* used by Cisco client utility */ - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) goto out; error = copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl)); if (error) @@ -2226,7 +2227,7 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } break; case SIOCS80211: - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_NET80211_MANAGE))) goto out; sc->areq.an_len = sizeof(sc->areq); /* diff --git a/sys/dev/arl/if_arl.c b/sys/dev/arl/if_arl.c index 75ab4fd2932b..62d9afae4b2b 100644 --- a/sys/dev/arl/if_arl.c +++ b/sys/dev/arl/if_arl.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -504,7 +505,7 @@ arl_ioctl(ifp, cmd, data) break; case SIOCS80211: - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_NET80211_MANAGE))) break; switch (ireq->i_type) { case IEEE80211_IOC_SSID: @@ -577,7 +578,7 @@ arl_ioctl(ifp, cmd, data) } case SIOCGARLALL: bzero(&arlan_io, sizeof(arlan_io)); - if (!suser(td)) { + if (!priv_check(td, PRIV_DRIVER)) { bcopy(ar->systemId, arlan_io.cfg.sid, 4); } @@ -616,7 +617,7 @@ arl_ioctl(ifp, cmd, data) } while (0) case SIOCSARLALL: - if (suser(td)) + if (priv_check(td, PRIV_DRIVER)) break; user = (void *)ifr->ifr_data; diff --git a/sys/dev/asr/asr.c b/sys/dev/asr/asr.c index 85cd848b9c9c..2d5e062c796b 100644 --- a/sys/dev/asr/asr.c +++ b/sys/dev/asr/asr.c @@ -117,6 +117,7 @@ #include #include #include +#include #include #include #include @@ -3125,7 +3126,7 @@ asr_open(struct cdev *dev, int32_t flags, int32_t ifmt, struct thread *td) s = splcam (); if (ASR_ctlr_held) { error = EBUSY; - } else if ((error = suser(td)) == 0) { + } else if ((error = priv_check(td, PRIV_DRIVER)) == 0) { ++ASR_ctlr_held; } splx(s); diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index 1fd092984f07..cca16232a3f7 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -257,8 +258,11 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct cdp->flags |= F_LOCKED; break; + /* + * XXXRW: Why does this require privilege? + */ case CDIOCRESET: - error = suser(td); + error = priv_check(td, PRIV_DRIVER); if (error) break; error = acd_test_ready(dev); diff --git a/sys/dev/ce/if_ce.c b/sys/dev/ce/if_ce.c index d072179a0671..b81d226a02c6 100644 --- a/sys/dev/ce/if_ce.c +++ b/sys/dev/ce/if_ce.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #if NPCI > 0 #include +#include #include #include #include @@ -1341,9 +1342,11 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else /* __FreeBSD_version >= 500000 */ +#elsif __FreeBSD_version < 700000 error = suser (td); -#endif /* __FreeBSD_version >= 500000 */ +#else + error = priv_check (td, PRIV_DRIVER); +#endif if (error) return error; #if __FreeBSD_version >= 600034 @@ -1380,8 +1383,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1408,8 +1413,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1426,8 +1433,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc CE_DEBUG2 (d, ("ioctl: setcfg\n")); #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1526,8 +1535,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1560,8 +1571,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1586,8 +1599,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1608,8 +1623,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1634,8 +1651,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1658,8 +1677,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1686,8 +1707,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1708,8 +1731,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1734,8 +1759,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1758,8 +1785,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1784,8 +1813,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1810,8 +1841,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1836,8 +1869,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1867,8 +1902,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1892,8 +1929,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1909,8 +1948,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; @@ -1945,8 +1986,10 @@ static int ce_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc /* Only for superuser! */ #if __FreeBSD_version < 500000 error = suser (p); -#else +#elsif __FreeBSD_version < 700000 error = suser (td); +#else + error = priv_check (td, PRIV_DRIVER); #endif if (error) return error; diff --git a/sys/dev/cnw/if_cnw.c b/sys/dev/cnw/if_cnw.c index 2d97c36f69e6..cbc86f0851a3 100644 --- a/sys/dev/cnw/if_cnw.c +++ b/sys/dev/cnw/if_cnw.c @@ -236,6 +236,7 @@ struct cfattach cnw_ca = { #include #include #include +#include #include #include #include @@ -1339,7 +1340,7 @@ cnw_ioctl(ifp, cmd, data) #if !defined(__FreeBSD__) error = suser(p->p_ucred, &p->p_acflag); #else - error = suser(td); + error = priv_check(td, PRIV_DRIVER); #endif if (error) break; @@ -1350,7 +1351,7 @@ cnw_ioctl(ifp, cmd, data) #if !defined(__FreeBSD__) error = suser(p->p_ucred, &p->p_acflag); #else - error = suser(td); + error = priv_check(td, PRIV_DRIVER); #endif if (error) break; @@ -1361,7 +1362,7 @@ cnw_ioctl(ifp, cmd, data) #if !defined(__FreeBSD__) error = suser(p->p_ucred, &p->p_acflag); #else - error = suser(td); + error = priv_check(td, PRIV_DRIVER); #endif if (error) break; diff --git a/sys/dev/cp/if_cp.c b/sys/dev/cp/if_cp.c index d995c01964ec..fefe9e609166 100644 --- a/sys/dev/cp/if_cp.c +++ b/sys/dev/cp/if_cp.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1071,7 +1072,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETPROTO: CP_DEBUG2 (d, ("ioctl: setproto\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -1102,7 +1103,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETKEEPALIVE: CP_DEBUG2 (d, ("ioctl: setkeepalive\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || @@ -1126,7 +1127,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETMODE: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (*(int*)data != SERIAL_HDLC) @@ -1142,7 +1143,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETCFG: CP_DEBUG2 (d, ("ioctl: setcfg\n")); - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1) @@ -1239,7 +1240,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_CLRSTAT: CP_DEBUG2 (d, ("ioctl: clrstat\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; c->rintr = 0; @@ -1268,7 +1269,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETBAUD: CP_DEBUG2 (d, ("ioctl: setbaud\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1286,7 +1287,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETLOOP: CP_DEBUG2 (d, ("ioctl: setloop\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1306,7 +1307,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETDPLL: CP_DEBUG2 (d, ("ioctl: setdpll\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_SERIAL) @@ -1328,7 +1329,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETNRZI: CP_DEBUG2 (d, ("ioctl: setnrzi\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_SERIAL) @@ -1348,7 +1349,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETDEBUG: CP_DEBUG2 (d, ("ioctl: setdebug\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; d->chan->debug = *(int*)data; @@ -1370,7 +1371,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETHIGAIN: CP_DEBUG2 (d, ("ioctl: sethigain\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1) @@ -1392,7 +1393,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETPHONY: CP_DEBUG2 (d, ("ioctl: setphony\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1) @@ -1414,7 +1415,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETUNFRAM: CP_DEBUG2 (d, ("ioctl: setunfram\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1) @@ -1436,7 +1437,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETSCRAMBLER: CP_DEBUG2 (d, ("ioctl: setscrambler\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_G703 && !c->unfram) @@ -1461,7 +1462,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETMONITOR: CP_DEBUG2 (d, ("ioctl: setmonitor\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1) @@ -1483,7 +1484,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETUSE16: CP_DEBUG2 (d, ("ioctl: setuse16\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1) @@ -1505,7 +1506,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETCRC4: CP_DEBUG2 (d, ("ioctl: setcrc4\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1) @@ -1538,7 +1539,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETCLK: CP_DEBUG2 (d, ("ioctl: setclk\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_E1 && @@ -1571,7 +1572,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETTIMESLOTS: CP_DEBUG2 (d, ("ioctl: settimeslots\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if ((c->type != T_E1 || c->unfram) && c->type != T_DATA) @@ -1597,7 +1598,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETINVCLK: CP_DEBUG2 (d, ("ioctl: setinvclk\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_SERIAL) @@ -1620,7 +1621,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETINVTCLK: CP_DEBUG2 (d, ("ioctl: setinvtclk\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_SERIAL) @@ -1642,7 +1643,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETINVRCLK: CP_DEBUG2 (d, ("ioctl: setinvrclk\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->type != T_SERIAL) @@ -1669,7 +1670,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_RESET: CP_DEBUG2 (d, ("ioctl: reset\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1682,7 +1683,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_HARDRESET: CP_DEBUG2 (d, ("ioctl: hardreset\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1714,7 +1715,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETDIR: CP_DEBUG2 (d, ("ioctl: setdir\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1739,7 +1740,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc if (c->type != T_E3 && c->type != T_T3 && c->type != T_STS1) return EINVAL; /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1761,7 +1762,7 @@ static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc if (c->type != T_T3 && c->type != T_STS1) return EINVAL; /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c index 4d22f4922abf..d46ef8982201 100644 --- a/sys/dev/ctau/if_ct.c +++ b/sys/dev/ctau/if_ct.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1300,7 +1301,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETPROTO: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (d->ifp->if_drv_flags & IFF_DRV_RUNNING) @@ -1328,7 +1329,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETKEEPALIVE: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || @@ -1357,7 +1358,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETCFG: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_HDLC) @@ -1435,7 +1436,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_CLRSTAT: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; c->rintr = 0; @@ -1458,7 +1459,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETBAUD: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1474,7 +1475,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETLOOP: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1492,7 +1493,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETDPLL: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_E1 || c->mode == M_G703) @@ -1512,7 +1513,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETNRZI: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_E1 || c->mode == M_G703) @@ -1530,7 +1531,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETDEBUG: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; c->debug = *(int*)data; @@ -1550,7 +1551,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETHIGAIN: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1572,7 +1573,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc if (c->mode != M_E1) return EINVAL; /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1595,7 +1596,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETCLK: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1619,7 +1620,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETTIMESLOTS: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1637,7 +1638,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETSUBCHAN: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splimp (); @@ -1663,7 +1664,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETINVCLK: case SERIAL_SETINVTCLK: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_E1 || c->mode == M_G703) @@ -1677,7 +1678,7 @@ static int ct_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETINVRCLK: /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_E1 || c->mode == M_G703) diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c index a48f76b09b67..be136b3b2dc5 100644 --- a/sys/dev/cx/if_cx.c +++ b/sys/dev/cx/if_cx.c @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1632,7 +1633,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETPORT: CX_DEBUG2 (d, ("ioctl: setproto\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; @@ -1658,7 +1659,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETPROTO: CX_DEBUG2 (d, ("ioctl: setproto\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_ASYNC) @@ -1695,7 +1696,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETKEEPALIVE: CX_DEBUG2 (d, ("ioctl: setkeepalive\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if ((IFP2SP(d->ifp)->pp_flags & PP_FR) || @@ -1725,7 +1726,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETMODE: CX_DEBUG2 (d, ("ioctl: setmode\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; @@ -1778,7 +1779,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_CLRSTAT: CX_DEBUG2 (d, ("ioctl: clrstat\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splhigh (); @@ -1810,7 +1811,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETBAUD: CX_DEBUG2 (d, ("ioctl: setbaud\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_ASYNC) @@ -1836,7 +1837,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETLOOP: CX_DEBUG2 (d, ("ioctl: setloop\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_ASYNC) @@ -1862,7 +1863,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETDPLL: CX_DEBUG2 (d, ("ioctl: setdpll\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_ASYNC) @@ -1888,7 +1889,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETNRZI: CX_DEBUG2 (d, ("ioctl: setnrzi\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; if (c->mode == M_ASYNC) @@ -1912,7 +1913,7 @@ static int cx_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struc case SERIAL_SETDEBUG: CX_DEBUG2 (d, ("ioctl: setdebug\n")); /* Only for superuser! */ - error = suser (td); + error = priv_check (td, PRIV_DRIVER); if (error) return error; s = splhigh (); diff --git a/sys/dev/dcons/dcons_os.c b/sys/dev/dcons/dcons_os.c index 38803acc7422..a6d78aabd508 100644 --- a/sys/dev/dcons/dcons_os.c +++ b/sys/dev/dcons/dcons_os.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -293,7 +294,8 @@ dcons_open(DEV dev, int flag, int mode, THREAD *td) if ((tp->t_state & TS_ISOPEN) == 0) { tp->t_state |= TS_CARR_ON; ttyconsolemode(tp, 0); - } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { + } else if ((tp->t_state & TS_XCLUDE) && + priv_check(td, PRIV_TTY_EXCLUSIVE)) { splx(s); return (EBUSY); } diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h index 11714254dac5..8e2855ad6a79 100644 --- a/sys/dev/drm/drmP.h +++ b/sys/dev/drm/drmP.h @@ -50,6 +50,9 @@ typedef struct drm_file drm_file_t; #include #include #include +#if __FreeBSD_version >= 700000 +#include +#endif #include #include #include @@ -233,7 +236,11 @@ enum { #define PAGE_ALIGN(addr) round_page(addr) /* DRM_SUSER returns true if the user is superuser */ +#if __FreeBSD_version >= 700000 +#define DRM_SUSER(p) (priv_check(p, PRIV_DRIVER) == 0) +#else #define DRM_SUSER(p) (suser(p) == 0) +#endif #define DRM_AGP_FIND_DEVICE() agp_find_device() #define DRM_MTRR_WC MDF_WRITECOMBINE #define jiffies ticks diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 0ee2deb89050..4f48ead6432f 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1489,8 +1490,9 @@ fd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread return (0); case FD_CLRERR: - if (suser(td) != 0) - return (EPERM); + error = priv_check(td, PRIV_DRIVER); + if (error) + return (error); fd->fdc->fdc_errs = 0; return (0); diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 37d272a36051..c61314c58044 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -2782,10 +2783,9 @@ pmc_syscall_handler(struct thread *td, void *syscall_args) KASSERT(td == curthread, ("[pmc,%d] td != curthread", __LINE__)); - if (suser(td) || jailed(td->td_ucred)) { - error = EPERM; + error = priv_check(td, PRIV_PMC_MANAGE); + if (error) break; - } if ((error = copyin(arg, &pma, sizeof(pma))) != 0) break; @@ -2918,11 +2918,16 @@ pmc_syscall_handler(struct thread *td, void *syscall_args) */ if (PMC_IS_SYSTEM_MODE(mode)) { - if (jailed(curthread->td_ucred)) - error = EPERM; - else if (suser(curthread) && - (pmc_unprivileged_syspmcs == 0)) + if (jailed(curthread->td_ucred)) { error = EPERM; + break; + } + if (!pmc_unprivileged_syspmcs) { + error = priv_check(curthread, + PRIV_PMC_SYSTEM); + if (error) + break; + } } if (error) diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index 65329788fed9..d90bd70fd9a9 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -2836,7 +2837,7 @@ ndis_ioctl(ifp, command, data) error = ENOTTY; break; case SIOCGDRVSPEC: - if ((error = suser(curthread))) + if ((error = priv_check(curthread, PRIV_DRIVER))) break; error = copyin(ifr->ifr_data, &oid, sizeof(oid)); if (error) @@ -2865,7 +2866,7 @@ ndis_ioctl(ifp, command, data) free(oidbuf, M_TEMP); break; case SIOCSDRVSPEC: - if ((error = suser(curthread))) + if ((error = priv_check(curthread, PRIV_DRIVER))) break; error = copyin(ifr->ifr_data, &oid, sizeof(oid)); if (error) @@ -2894,7 +2895,7 @@ ndis_ioctl(ifp, command, data) free(oidbuf, M_TEMP); break; case SIOCGPRIVATE_0: - if ((error = suser(curthread))) + if ((error = priv_check(curthread, PRIV_DRIVER))) break; NDIS_LOCK(sc); if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) { @@ -3062,7 +3063,7 @@ ndis_wi_ioctl_set(ifp, command, data) uint32_t foo; int error, len; - error = suser(curthread); + error = priv_check(curthread, PRIV_DRIVER); if (error) return (error); @@ -3370,7 +3371,7 @@ ndis_80211_ioctl_set(struct ifnet *ifp, u_long command, caddr_t data) break; #endif case IEEE80211_IOC_STATIONNAME: - error = suser(curthread); + error = priv_check(curthread, PRIV_NET80211_MANAGE); if (error) break; if (ireq->i_val != 0 || diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c index 1c004c3fd8a2..462983fecca7 100644 --- a/sys/dev/kbd/kbd.c +++ b/sys/dev/kbd/kbd.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -972,11 +973,11 @@ key_change_ok(struct keyent_t *oldkey, struct keyent_t *newkey, struct thread *t if (keymap_restrict_change >= 2) { for (i = 0; i < NUM_STATES; i++) if (oldkey->map[i] != newkey->map[i]) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); if (oldkey->spcl != newkey->spcl) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); if (oldkey->flgs != newkey->flgs) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); return (0); } @@ -991,7 +992,7 @@ key_change_ok(struct keyent_t *oldkey, struct keyent_t *newkey, struct thread *t if ((oldkey->spcl & (0x80 >> i)) == (newkey->spcl & (0x80 >> i)) && oldkey->map[i] == newkey->map[i]) continue; - return suser(td); + return priv_check(td, PRIV_KEYBOARD); } return (0); @@ -1020,20 +1021,20 @@ accent_change_ok(accentmap_t *oldmap, accentmap_t *newmap, struct thread *td) return (0); if (oldmap->n_accs != newmap->n_accs) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); for (accent = 0; accent < oldmap->n_accs; accent++) { oldacc = &oldmap->acc[accent]; newacc = &newmap->acc[accent]; if (oldacc->accchar != newacc->accchar) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); for (i = 0; i < NUM_ACCENTCHARS; ++i) { if (oldacc->map[i][0] != newacc->map[i][0]) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); if (oldacc->map[i][0] == 0) /* end of table */ break; if (oldacc->map[i][1] != newacc->map[i][1]) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); } } @@ -1048,7 +1049,7 @@ fkey_change_ok(fkeytab_t *oldkey, fkeyarg_t *newkey, struct thread *td) if (oldkey->len != newkey->flen || bcmp(oldkey->str, newkey->keydef, oldkey->len) != 0) - return suser(td); + return priv_check(td, PRIV_KEYBOARD); return (0); } diff --git a/sys/dev/lmc/if_lmc.c b/sys/dev/lmc/if_lmc.c index 35ce7a92ce3c..f970d3175b81 100644 --- a/sys/dev/lmc/if_lmc.c +++ b/sys/dev/lmc/if_lmc.c @@ -113,6 +113,9 @@ # include # include # include +# if (__FreeBSD_version >= 700000) +# include +# endif # if (__FreeBSD_version >= 500000) # include # include diff --git a/sys/dev/lmc/if_lmc.h b/sys/dev/lmc/if_lmc.h index 85dfc55bf2d3..140750d86b1c 100644 --- a/sys/dev/lmc/if_lmc.h +++ b/sys/dev/lmc/if_lmc.h @@ -1223,7 +1223,11 @@ struct softc # define TOP_UNLOCK mtx_unlock (&sc->top_mtx) # define BOTTOM_TRYLOCK mtx_trylock(&sc->bottom_mtx) # define BOTTOM_UNLOCK mtx_unlock (&sc->bottom_mtx) -# define CHECK_CAP suser(curthread) +# if (__FreeBSD_version >= 700000) +# define CHECK_CAP priv_check(curthread, PRIV_DRIVER) +# else +# define CHECK_CAP suser(curthread) +# endif # else /* FreeBSD-4 */ # define TOP_TRYLOCK (sc->top_spl = splimp()) # define TOP_UNLOCK splx(sc->top_spl) diff --git a/sys/dev/nmdm/nmdm.c b/sys/dev/nmdm/nmdm.c index fb9648b8954a..31b18053e9dc 100644 --- a/sys/dev/nmdm/nmdm.c +++ b/sys/dev/nmdm/nmdm.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -286,7 +287,8 @@ nmdmopen(struct cdev *dev, int flag, int devtype, struct thread *td) if ((tp->t_state & TS_ISOPEN) == 0) { ttyinitmode(tp, 0, 0); ttsetwater(tp); /* XXX ? */ - } else if (tp->t_state & TS_XCLUDE && suser(td)) { + } else if (tp->t_state & TS_XCLUDE && + priv_check(td, PRIV_TTY_EXCLUSIVE)) { return (EBUSY); } diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c index ee42a1cdb462..0b94eb7aa865 100644 --- a/sys/dev/null/null.c +++ b/sys/dev/null/null.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -87,7 +88,7 @@ null_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused, if (cmd != DIOCSKERNELDUMP) return (ENOIOCTL); - error = suser(td); + error = priv_check(td, PRIV_SETDUMPER); if (error) return (error); return (set_dumper(NULL)); diff --git a/sys/dev/ofw/ofw_console.c b/sys/dev/ofw/ofw_console.c index e305e7bef648..33ee0d6f7690 100644 --- a/sys/dev/ofw/ofw_console.c +++ b/sys/dev/ofw/ofw_console.c @@ -140,7 +140,8 @@ ofw_dev_open(struct cdev *dev, int flag, int mode, struct thread *td) ttyconsolemode(tp, 0); setuptimeout = 1; - } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { + } else if ((tp->t_state & TS_XCLUDE) && + priv_check(td, PRIV_TTY_EXCLUSIVE)) { return (EBUSY); } diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index 4d2b1bbffe6d..7cc78e61e8c2 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -85,7 +86,7 @@ static int random_close(struct cdev *dev __unused, int flags, int fmt __unused, struct thread *td) { - if ((flags & FWRITE) && (suser(td) == 0) + if ((flags & FWRITE) && (priv_check(td, PRIV_RANDOM_RESEED) == 0) && (securelevel_gt(td->td_ucred, 0) == 0)) { (*random_systat.reseed)(); random_systat.seeded = 1; diff --git a/sys/dev/sbni/if_sbni.c b/sys/dev/sbni/if_sbni.c index 282a5eada9e2..3e1296f2e650 100644 --- a/sys/dev/sbni/if_sbni.c +++ b/sys/dev/sbni/if_sbni.c @@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1110,7 +1111,7 @@ sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data) case SIOCSHWFLAGS: /* set flags */ /* root only */ - error = suser(td); + error = priv_check(td, PRIV_DRIVER); if (error) break; flags = *(struct sbni_flags*)&ifr->ifr_data; @@ -1132,7 +1133,7 @@ sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data) break; case SIOCRINSTATS: - if (!(error = suser(td))) /* root only */ + if (!(error = priv_check(td, PRIV_DRIVER))) /* root only */ bzero(&sc->in_stats, sizeof(struct sbni_in_stats)); break; diff --git a/sys/dev/sbsh/if_sbsh.c b/sys/dev/sbsh/if_sbsh.c index 2970474087a8..c23f88941e52 100644 --- a/sys/dev/sbsh/if_sbsh.c +++ b/sys/dev/sbsh/if_sbsh.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -424,7 +425,7 @@ sbsh_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch(cmd) { case SIOCLOADFIRMW: - if ((error = suser(curthread)) != 0) + if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) break; if (ifp->if_flags & IFF_UP) error = EBUSY; @@ -444,7 +445,7 @@ sbsh_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCGETSTATS : - if ((error = suser(curthread)) != 0) + if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) break; t = 0; @@ -478,7 +479,7 @@ sbsh_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCCLRSTATS : - if (!(error = suser(curthread))) { + if (!(error = priv_check(curthread, PRIV_DRIVER))) { bzero(&sc->in_stats, sizeof(struct sbni16_stats)); t = 2; if (issue_cx28975_cmd(sc, _DSL_CLEAR_ERROR_CTRS, &t, 1)) diff --git a/sys/dev/si/si.c b/sys/dev/si/si.c index e821a9e684ad..584e851ac609 100644 --- a/sys/dev/si/si.c +++ b/sys/dev/si/si.c @@ -53,6 +53,7 @@ static const char si_copyright1[] = "@(#) Copyright (C) Specialix International #include #include #include +#include #include #include #include @@ -650,7 +651,7 @@ si_Sioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t ip = (int *)data; -#define SUCHECK if ((error = suser(td))) goto out +#define SUCHECK if ((error = priv_check(td, PRIV_DRIVER))) goto out switch (cmd) { case TCSIPORTS: diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 49768960e788..87ada19ff4aa 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -517,7 +518,7 @@ scopen(struct cdev *dev, int flag, int mode, struct thread *td) ttyld_modem(tp, 1); } else - if (tp->t_state & TS_XCLUDE && suser(td)) + if (tp->t_state & TS_XCLUDE && priv_check(td, PRIV_TTY_EXCLUSIVE)) return(EBUSY); error = ttyld_open(tp, dev); @@ -1092,7 +1093,7 @@ scioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) return 0; case KDENABIO: /* allow io operations */ - error = suser(td); + error = priv_check(td, PRIV_IO); if (error != 0) return error; error = securelevel_gt(td->td_ucred, 0); diff --git a/sys/dev/syscons/sysmouse.c b/sys/dev/syscons/sysmouse.c index 394351e5db09..fa89a23f521b 100644 --- a/sys/dev/syscons/sysmouse.c +++ b/sys/dev/syscons/sysmouse.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -83,7 +84,8 @@ smopen(struct cdev *dev, int flag, int mode, struct thread *td) ttyinitmode(tp, 0, 0); smparam(tp, &tp->t_termios); ttyld_modem(tp, 1); - } else if (tp->t_state & TS_XCLUDE && suser(td)) { + } else if (tp->t_state & TS_XCLUDE && + priv_check(td, PRIV_TTY_EXCLUSIVE)) { return EBUSY; } diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 5a52a5f0e0d6..2b767a3846d4 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #endif #include #include +#include #include #include #include @@ -1273,7 +1274,7 @@ wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) WI_UNLOCK(sc); break; case SIOCSIFGENERIC: - error = suser(td); + error = priv_check(td, PRIV_DRIVER); if (error == 0) error = wi_set_cfg(ifp, cmd, data); break; @@ -1291,7 +1292,7 @@ wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); break; case SIOCSPRISM2DEBUG: - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) return (error); error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); if (error) @@ -1312,7 +1313,7 @@ wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCS80211: ireq = (struct ieee80211req *) data; if (ireq->i_type == IEEE80211_IOC_STATIONNAME) { - error = suser(td); + error = priv_check(td, PRIV_NET80211_MANAGE); if (error) break; if (ireq->i_val != 0 || diff --git a/sys/dev/wl/if_wl.c b/sys/dev/wl/if_wl.c index 81cef7b9786f..cf131f848781 100644 --- a/sys/dev/wl/if_wl.c +++ b/sys/dev/wl/if_wl.c @@ -197,6 +197,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1310,7 +1311,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) /* pointer to buffer in user space */ up = (void *)ifr->ifr_data; /* work out if they're root */ - isroot = (suser(td) == 0); + isroot = (priv_check(td, PRIV_NET80211_GETKEY) == 0); for (i = 0; i < 0x40; i++) { /* don't hand the DES key out to non-root users */ @@ -1327,7 +1328,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) /* copy the PSA in from the caller; we only copy _some_ values */ case SIOCSWLPSA: /* root only */ - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) break; error = EINVAL; /* assume the worst */ /* pointer to buffer in user space containing data */ @@ -1383,7 +1384,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) */ case SIOCSWLCNWID: /* root only */ - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) break; if (!(ifp->if_flags & IFF_UP)) { error = EIO; /* only allowed while up */ @@ -1401,7 +1402,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) /* copy the EEPROM in 2.4 Gz WaveMODEM out to the caller */ case SIOCGWLEEPROM: /* root only */ - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) break; /* pointer to buffer in user space */ up = (void *)ifr->ifr_data; @@ -1428,7 +1429,7 @@ wlioctl(struct ifnet *ifp, u_long cmd, caddr_t data) /* zero (Delete) the wl cache */ case SIOCDWLCACHE: /* root only */ - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_DRIVER))) break; wl_cache_zero(sc); break; diff --git a/sys/dev/zs/zs.c b/sys/dev/zs/zs.c index 199a26e5ff13..21195a233b4a 100644 --- a/sys/dev/zs/zs.c +++ b/sys/dev/zs/zs.c @@ -453,7 +453,7 @@ zsttyopen(struct cdev *dev, int flags, int mode, struct thread *td) if ((tp->t_state & TS_ISOPEN) != 0 && (tp->t_state & TS_XCLUDE) != 0 && - suser(td) != 0) + priv_check(td, PRIV_TTY_EXCLUSIVE) != 0) return (EBUSY); if ((tp->t_state & TS_ISOPEN) == 0) { diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index 9a5e8364eed5..58f2addc657b 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -174,7 +175,7 @@ cd9660_mount(struct mount *mp, struct thread *td) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); if (error) - error = suser(td); + error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { vput(devvp); return (error); diff --git a/sys/fs/devfs/devfs_rule.c b/sys/fs/devfs/devfs_rule.c index a0caad9cfb8b..f6aef0370bfd 100644 --- a/sys/fs/devfs/devfs_rule.c +++ b/sys/fs/devfs/devfs_rule.c @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -164,11 +165,13 @@ devfs_rules_ioctl(struct devfs_mount *dm, u_long cmd, caddr_t data, struct threa sx_assert(&dm->dm_lock, SX_XLOCKED); /* - * XXX: This returns an error regardless of whether we - * actually support the cmd or not. + * XXX: This returns an error regardless of whether we actually + * support the cmd or not. + * + * We could make this privileges finer grained if desired. */ - error = suser(td); - if (error != 0) + error = priv_check(td, PRIV_DEVFS_RULE); + if (error) return (error); sx_xlock(&sx_rules); diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 6ae446761bdb..47cc01cfbbe7 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -1145,19 +1146,25 @@ devfs_setattr(struct vop_setattr_args *ap) else gid = vap->va_gid; if (uid != de->de_uid || gid != de->de_gid) { - if (((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid || - (gid != de->de_gid && !groupmember(gid, ap->a_cred))) && - (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)) != 0) - return (error); + if ((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid || + (gid != de->de_gid && !groupmember(gid, ap->a_cred))) { + error = priv_check_cred(ap->a_td->td_ucred, + PRIV_VFS_CHOWN, SUSER_ALLOWJAIL); + if (error) + return (error); + } de->de_uid = uid; de->de_gid = gid; c = 1; } if (vap->va_mode != (mode_t)VNOVAL) { - if ((ap->a_cred->cr_uid != de->de_uid) && - (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL))) - return (error); + if (ap->a_cred->cr_uid != de->de_uid) { + error = priv_check_cred(ap->a_td->td_ucred, + PRIV_VFS_ADMIN, SUSER_ALLOWJAIL); + if (error) + return (error); + } de->de_mode = vap->va_mode; c = 1; } @@ -1227,7 +1234,8 @@ devfs_symlink(struct vop_symlink_args *ap) td = ap->a_cnp->cn_thread; KASSERT(td == curthread, ("devfs_symlink: td != curthread")); - error = suser(td); + + error = priv_check(td, PRIV_DEVFS_SYMLINK); if (error) return(error); dmp = VFSTODEVFS(ap->a_dvp->v_mount); diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c index 4c73fe4d3968..550f613d5bf9 100644 --- a/sys/fs/hpfs/hpfs_vnops.c +++ b/sys/fs/hpfs/hpfs_vnops.c @@ -501,11 +501,12 @@ hpfs_setattr(ap) if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - if (cred->cr_uid != hp->h_uid && - (error = suser_cred(cred, SUSER_ALLOWJAIL)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(vp, VWRITE, cred, td)))) - return (error); + if (vap->va_vaflags & VA_UTIMES_NULL) { + error = VOP_ACCESS(vp, VADMIN, cred, td); + if (error) + error = VOP_ACCESS(vp, VWRITE, cred, td); + } else + error = VOP_ACCESS(vp, VADMIN, cred, td); if (vap->va_atime.tv_sec != VNOVAL) hp->h_atime = vap->va_atime.tv_sec; if (vap->va_mtime.tv_sec != VNOVAL) diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c index c0963cbbe520..b6d81f400f60 100644 --- a/sys/fs/msdosfs/msdosfs_vfsops.c +++ b/sys/fs/msdosfs/msdosfs_vfsops.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -293,17 +294,17 @@ msdosfs_mount(struct mount *mp, struct thread *td) * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ - if (suser(td)) { - devvp = pmp->pm_devvp; - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); - error = VOP_ACCESS(devvp, VREAD | VWRITE, - td->td_ucred, td); - if (error) { - VOP_UNLOCK(devvp, 0, td); - return (error); - } + devvp = pmp->pm_devvp; + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); + error = VOP_ACCESS(devvp, VREAD | VWRITE, + td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { VOP_UNLOCK(devvp, 0, td); + return (error); } + VOP_UNLOCK(devvp, 0, td); DROP_GIANT(); g_topology_lock(); error = g_access(pmp->pm_cp, 0, 1, 0); @@ -353,15 +354,15 @@ msdosfs_mount(struct mount *mp, struct thread *td) * If mount by non-root, then verify that user has necessary * permissions on the device. */ - if (suser(td)) { - accessmode = VREAD; - if ((mp->mnt_flag & MNT_RDONLY) == 0) - accessmode |= VWRITE; - error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); - if (error) { - vput(devvp); - return (error); - } + accessmode = VREAD; + if ((mp->mnt_flag & MNT_RDONLY) == 0) + accessmode |= VWRITE; + error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { + vput(devvp); + return (error); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = mountmsdosfs(devvp, mp, td); diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index e7a64e7132fb..ae17f897961c 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -404,9 +405,12 @@ msdosfs_setattr(ap) if (vap->va_flags != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - if (cred->cr_uid != pmp->pm_uid && - (error = suser_cred(cred, SUSER_ALLOWJAIL))) - return (error); + if (cred->cr_uid != pmp->pm_uid) { + error = priv_check_cred(cred, PRIV_VFS_ADMIN, + SUSER_ALLOWJAIL); + if (error) + return (error); + } /* * We are very inconsistent about handling unsupported * attributes. We ignored the access time and the @@ -419,9 +423,11 @@ msdosfs_setattr(ap) * set ATTR_ARCHIVE for directories `cp -pr' from a more * sensible filesystem attempts it a lot. */ - if (suser_cred(cred, SUSER_ALLOWJAIL)) { - if (vap->va_flags & SF_SETTABLE) - return EPERM; + if (vap->va_flags & SF_SETTABLE) { + error = priv_check_cred(cred, PRIV_VFS_SYSFLAGS, + SUSER_ALLOWJAIL); + if (error) + return (error); } if (vap->va_flags & ~SF_ARCHIVED) return EOPNOTSUPP; @@ -444,10 +450,13 @@ msdosfs_setattr(ap) gid = vap->va_gid; if (gid == (gid_t)VNOVAL) gid = pmp->pm_gid; - if ((cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid || - (gid != pmp->pm_gid && !groupmember(gid, cred))) && - (error = suser_cred(cred, SUSER_ALLOWJAIL))) - return error; + if (cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid || + (gid != pmp->pm_gid && !groupmember(gid, cred))) { + error = priv_check_cred(cred, PRIV_VFS_CHOWN, + SUSER_ALLOWJAIL); + if (error) + return (error); + } if (uid != pmp->pm_uid || gid != pmp->pm_gid) return EINVAL; } @@ -477,11 +486,13 @@ msdosfs_setattr(ap) if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - if (cred->cr_uid != pmp->pm_uid && - (error = suser_cred(cred, SUSER_ALLOWJAIL)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_td)))) - return (error); + if (vap->va_vaflags & VA_UTIMES_NULL) { + error = VOP_ACCESS(vp, VADMIN, cred, ap->a_td); + if (error) + error = VOP_ACCESS(vp, VWRITE, cred, + ap->a_td); + } else + error = VOP_ACCESS(vp, VADMIN, cred, ap->a_td); if (vp->v_type != VDIR) { if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && vap->va_atime.tv_sec != VNOVAL) { @@ -506,9 +517,12 @@ msdosfs_setattr(ap) if (vap->va_mode != (mode_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); - if (cred->cr_uid != pmp->pm_uid && - (error = suser_cred(cred, SUSER_ALLOWJAIL))) - return (error); + if (cred->cr_uid != pmp->pm_uid) { + error = priv_check_cred(cred, PRIV_VFS_ADMIN, + SUSER_ALLOWJAIL); + if (error) + return (error); + } if (vp->v_type != VDIR) { /* We ignore the read and execute bits. */ if (vap->va_mode & VWRITE) diff --git a/sys/fs/procfs/procfs_ioctl.c b/sys/fs/procfs/procfs_ioctl.c index 3808a2b166d6..04fe603297be 100644 --- a/sys/fs/procfs/procfs_ioctl.c +++ b/sys/fs/procfs/procfs_ioctl.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -104,8 +105,19 @@ procfs_ioctl(PFS_IOCTL_ARGS) #endif case PIOCSFL: flags = *(unsigned int *)data; - if (flags & PF_ISUGID && (error = suser(td)) != 0) - break; + if (flags & PF_ISUGID) { + /* + * XXXRW: Is this specific check required here, as + * p_candebug() should implement it, or other checks + * are missing. + * + * XXXRW: Other debugging privileges are granted in + * jail, why isn't this? + */ + error = priv_check(td, PRIV_DEBUG_SUGID); + if (error) + break; + } p->p_pfsflags = flags; break; case PIOCGFL: diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c index f65d2e04f55f..bfac2aa33bc5 100644 --- a/sys/fs/smbfs/smbfs_vnops.c +++ b/sys/fs/smbfs/smbfs_vnops.c @@ -366,11 +366,13 @@ smbfs_setattr(ap) if (vap->va_atime.tv_sec != VNOVAL) atime = &vap->va_atime; if (mtime != atime) { - if (ap->a_cred->cr_uid != VTOSMBFS(vp)->sm_uid && - (error = suser_cred(ap->a_cred, SUSER_ALLOWJAIL)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td)))) - return (error); + if (vap->va_vaflags & VA_UTIMES_NULL) { + error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td); + if (error) + error = VOP_ACCESS(vp, VWRITE, ap->a_cred, + ap->a_td); + } else + error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td); #if 0 if (mtime == NULL) mtime = &np->n_mtime; diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index 672bdebe102b..d21301ea91f0 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -84,6 +84,7 @@ #include #include #include +#include #include #include #include @@ -238,7 +239,7 @@ udf_mount(struct mount *mp, struct thread *td) /* Check the access rights on the mount device */ error = VOP_ACCESS(devvp, VREAD, td->td_ucred, td); if (error) - error = suser(td); + error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { vput(devvp); return (error); diff --git a/sys/fs/umapfs/umap_vfsops.c b/sys/fs/umapfs/umap_vfsops.c index a69299845ce7..694ce3334afd 100644 --- a/sys/fs/umapfs/umap_vfsops.c +++ b/sys/fs/umapfs/umap_vfsops.c @@ -88,7 +88,8 @@ umapfs_omount(mp, path, data, ndp, td) /* * Only for root */ - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_VFS_MOUNT); + if (error) return (error); #ifdef DEBUG diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c index 4fdc72739c60..c1b58cb23353 100644 --- a/sys/gnu/fs/ext2fs/ext2_vfsops.c +++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -197,15 +198,16 @@ ext2_mount(mp, td) * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ - if (suser(td)) { - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); - if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, - td->td_ucred, td)) != 0) { - VOP_UNLOCK(devvp, 0, td); - return (error); - } + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); + error = VOP_ACCESS(devvp, VREAD | VWRITE, + td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { VOP_UNLOCK(devvp, 0, td); + return (error); } + VOP_UNLOCK(devvp, 0, td); DROP_GIANT(); g_topology_lock(); error = g_access(ump->um_cp, 0, 1, 0); @@ -259,15 +261,18 @@ ext2_mount(mp, td) /* * If mount by non-root, then verify that user has necessary * permissions on the device. + * + * XXXRW: VOP_ACCESS() enough? */ - if (suser(td)) { - accessmode = VREAD; - if ((mp->mnt_flag & MNT_RDONLY) == 0) - accessmode |= VWRITE; - if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td)) != 0) { - vput(devvp); - return (error); - } + accessmode = VREAD; + if ((mp->mnt_flag & MNT_RDONLY) == 0) + accessmode |= VWRITE; + error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { + vput(devvp); + return (error); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c index c755f66ed2f6..4ea62c6f6ba6 100644 --- a/sys/gnu/fs/ext2fs/ext2_vnops.c +++ b/sys/gnu/fs/ext2fs/ext2_vnops.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -411,7 +412,8 @@ ext2_setattr(ap) * Privileged non-jail processes may not modify system flags * if securelevel > 0 and any existing system flags are set. */ - if (!suser_cred(cred, SUSER_ALLOWJAIL)) { + if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, + SUSER_ALLOWJAIL)) { if (ip->i_flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { error = securelevel_gt(cred, 0); @@ -529,11 +531,17 @@ ext2_chmod(vp, mode, cred, td) * as well as set the setgid bit on a file with a group that the * process is not a member of. */ - if (suser_cred(cred, SUSER_ALLOWJAIL)) { - if (vp->v_type != VDIR && (mode & S_ISTXT)) + if (vp->v_type != VDIR && (mode & S_ISTXT)) { + error = priv_check_cred(cred, PRIV_VFS_STICKYFILE, + SUSER_ALLOWJAIL); + if (error) return (EFTYPE); - if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) - return (EPERM); + } + if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) { + error = priv_check_cred(cred, PRIV_VFS_SETGID, + SUSER_ALLOWJAIL); + if (error) + return (error); } ip->i_mode &= ~ALLPERMS; ip->i_mode |= (mode & ALLPERMS); @@ -573,17 +581,23 @@ ext2_chown(vp, uid, gid, cred, td) * to a group of which we are not a member, the caller must * have privilege. */ - if ((uid != ip->i_uid || - (gid != ip->i_gid && !groupmember(gid, cred))) && - (error = suser_cred(cred, SUSER_ALLOWJAIL))) - return (error); + if (uid != ip->i_uid || (gid != ip->i_gid && + !groupmember(gid, cred))) { + error = priv_check_cred(cred, PRIV_VFS_CHOWN, + SUSER_ALLOWJAIL); + if (error) + return (error); + } ogid = ip->i_gid; ouid = ip->i_uid; ip->i_gid = gid; ip->i_uid = uid; ip->i_flag |= IN_CHANGE; - if (suser_cred(cred, SUSER_ALLOWJAIL) && (ouid != uid || ogid != gid)) - ip->i_mode &= ~(ISUID | ISGID); + if (ouid != uid || ogid != gid) { + if (priv_check_cred(cred, PRIV_VFS_CLEARSUGID, + SUSER_ALLOWJAIL) != 0) + ip->i_mode &= ~(ISUID | ISGID); + } return (0); } @@ -1608,9 +1622,11 @@ ext2_makeinode(mode, dvp, vpp, cnp) ip->i_mode = mode; tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ ip->i_nlink = 1; - if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && - suser_cred(cnp->cn_cred, SUSER_ALLOWJAIL)) - ip->i_mode &= ~ISGID; + if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred)) { + if (priv_check_cred(cnp->cn_cred, PRIV_VFS_CLEARSUGID, + SUSER_ALLOWJAIL)) + ip->i_mode &= ~ISGID; + } if (cnp->cn_flags & ISWHITEOUT) ip->i_flags |= UF_OPAQUE; diff --git a/sys/gnu/fs/reiserfs/reiserfs_fs.h b/sys/gnu/fs/reiserfs/reiserfs_fs.h index 691f612a7305..b33995fa9fdd 100644 --- a/sys/gnu/fs/reiserfs/reiserfs_fs.h +++ b/sys/gnu/fs/reiserfs/reiserfs_fs.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/sys/gnu/fs/reiserfs/reiserfs_vfsops.c b/sys/gnu/fs/reiserfs/reiserfs_vfsops.c index 066d5b21b0ba..4ace2da62aee 100644 --- a/sys/gnu/fs/reiserfs/reiserfs_vfsops.c +++ b/sys/gnu/fs/reiserfs/reiserfs_vfsops.c @@ -125,15 +125,15 @@ reiserfs_mount(struct mount *mp, struct thread *td) /* If mount by non-root, then verify that user has necessary * permissions on the device. */ - if (suser(td)) { - accessmode = VREAD; - if ((mp->mnt_flag & MNT_RDONLY) == 0) - accessmode |= VWRITE; - if ((error = VOP_ACCESS(devvp, - accessmode, td->td_ucred, td)) != 0) { - vput(devvp); - return (error); - } + accessmode = VREAD; + if ((mp->mnt_flag & MNT_RDONLY) == 0) + accessmode |= VWRITE; + error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { + vput(devvp); + return (error); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_super.c b/sys/gnu/fs/xfs/FreeBSD/xfs_super.c index f840297e409f..97c65864a22f 100644 --- a/sys/gnu/fs/xfs/FreeBSD/xfs_super.c +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_super.c @@ -53,6 +53,8 @@ #include "xfs_version.h" #include "xfs_buf.h" +#include + #include #include @@ -149,14 +151,15 @@ xfs_blkdev_get( vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); ronly = ((XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) != 0); - if (suser(td)) { - accessmode = VREAD; - if (!ronly) - accessmode |= VWRITE; - if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td))!= 0){ - vput(devvp); - return (error); - } + accessmode = VREAD; + if (!ronly) + accessmode |= VWRITE; + error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { + vput(devvp); + return (error); } DROP_GIANT(); diff --git a/sys/i386/i386/io.c b/sys/i386/i386/io.c index 1c0866d30fde..eb0deb67c5f4 100644 --- a/sys/i386/i386/io.c +++ b/sys/i386/i386/io.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -54,7 +55,7 @@ ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, { int error; - error = suser(td); + error = priv_check(td, PRIV_IO); if (error != 0) return (error); error = securelevel_gt(td->td_ucred, 0); diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c index d63373676d97..f53f49aaedfc 100644 --- a/sys/i386/i386/sys_machdep.c +++ b/sys/i386/i386/sys_machdep.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -292,7 +293,7 @@ i386_set_ioperm(td, uap) if ((error = mac_check_sysarch_ioperm(td->td_ucred)) != 0) return (error); #endif - if ((error = suser(td)) != 0) + if ((error = priv_check(td, PRIV_IO)) != 0) return (error); if ((error = securelevel_gt(td->td_ucred, 0)) != 0) return (error); diff --git a/sys/i386/i386/vm86.c b/sys/i386/i386/vm86.c index e22929b5d5b3..875b775308a7 100644 --- a/sys/i386/i386/vm86.c +++ b/sys/i386/i386/vm86.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -724,7 +725,7 @@ vm86_sysarch(td, args) case VM86_INTCALL: { struct vm86_intcall_args sa; - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_VM86_INTCALL))) return (error); if ((error = copyin(ua.sub_args, &sa, sizeof(sa)))) return (error); diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c index 164c369aafe1..46542ba1143b 100644 --- a/sys/i386/ibcs2/ibcs2_misc.c +++ b/sys/i386/ibcs2/ibcs2_misc.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include #include /* Must come after sys/malloc.h */ #include +#include #include #include #include @@ -1008,14 +1009,22 @@ ibcs2_plock(td, uap) #define IBCS2_DATALOCK 4 - if ((error = suser(td)) != 0) - return EPERM; switch(uap->cmd) { case IBCS2_UNLOCK: + error = priv_check(td, PRIV_VM_MUNLOCK); + if (error) + return (error); + /* XXX - TODO */ + return (0); + case IBCS2_PROCLOCK: case IBCS2_TEXTLOCK: case IBCS2_DATALOCK: - return 0; /* XXX - TODO */ + error = priv_check(td, PRIV_VM_MLOCK); + if (error) + return (error); + /* XXX - TODO */ + return 0; } return EINVAL; } @@ -1043,9 +1052,6 @@ ibcs2_uadmin(td, uap) #define SCO_AD_GETBMAJ 0 #define SCO_AD_GETCMAJ 1 - if (suser(td)) - return EPERM; - switch(uap->cmd) { case SCO_A_REBOOT: case SCO_A_SHUTDOWN: @@ -1055,11 +1061,11 @@ ibcs2_uadmin(td, uap) case SCO_AD_PWRDOWN: case SCO_AD_PWRNAP: r.opt = RB_HALT; - reboot(td, &r); + return (reboot(td, &r)); case SCO_AD_BOOT: case SCO_AD_IBOOT: r.opt = RB_AUTOBOOT; - reboot(td, &r); + return (reboot(td, &r)); } return EINVAL; case SCO_A_REMOUNT: diff --git a/sys/i386/ibcs2/ibcs2_socksys.c b/sys/i386/ibcs2/ibcs2_socksys.c index 515f318cd4b8..f4939cf49efb 100644 --- a/sys/i386/ibcs2/ibcs2_socksys.c +++ b/sys/i386/ibcs2/ibcs2_socksys.c @@ -174,9 +174,6 @@ ibcs2_setipdomainname(td, uap) char hname[MAXHOSTNAMELEN], *ptr; int error, sctl[2], hlen; - if ((error = suser(td))) - return (error); - /* W/out a hostname a domain-name is nonsense */ if ( strlen(hostname) == 0 ) return EINVAL; diff --git a/sys/i386/ibcs2/ibcs2_sysi86.c b/sys/i386/ibcs2/ibcs2_sysi86.c index 12321d1ea0e0..4d762186141c 100644 --- a/sys/i386/ibcs2/ibcs2_sysi86.c +++ b/sys/i386/ibcs2/ibcs2_sysi86.c @@ -76,8 +76,6 @@ ibcs2_sysi86(struct thread *td, struct ibcs2_sysi86_args *args) int name[2]; int error; - if ((error = suser(td))) - return (error); name[0] = CTL_KERN; name[1] = KERN_HOSTNAME; mtx_lock(&Giant); diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index 5839411acdf7..0129bd07092a 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -812,7 +813,7 @@ linux_iopl(struct thread *td, struct linux_iopl_args *args) if (args->level < 0 || args->level > 3) return (EINVAL); - if ((error = suser(td)) != 0) + if ((error = priv_check(td, PRIV_IO)) != 0) return (error); if ((error = securelevel_gt(td->td_ucred, 0)) != 0) return (error); diff --git a/sys/i4b/driver/i4b_ipr.c b/sys/i4b/driver/i4b_ipr.c index 7fbebc82ea3e..537ef3d263bb 100644 --- a/sys/i4b/driver/i4b_ipr.c +++ b/sys/i4b/driver/i4b_ipr.c @@ -490,7 +490,7 @@ i4biprioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct thread *td = curthread; /* XXX */ - if((error = suser(td))) + if((error = priv_check(td, PRIV_DRIVER))) return (error); sl_compress_setup(sc->sc_compr, *(int *)data); } diff --git a/sys/ia64/ia64/ssc.c b/sys/ia64/ia64/ssc.c index d5e6d97745d0..42a995c22180 100644 --- a/sys/ia64/ia64/ssc.c +++ b/sys/ia64/ia64/ssc.c @@ -147,7 +147,8 @@ ssc_open(struct cdev *dev, int flag, int mode, struct thread *td) ttyconsolemode(tp, 0); setuptimeout = 1; - } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { + } else if ((tp->t_state & TS_XCLUDE) && + priv_check(td, PRIV_TTY_EXCLUSIVE)) { splx(s); return EBUSY; } diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c index 9a5e8364eed5..58f2addc657b 100644 --- a/sys/isofs/cd9660/cd9660_vfsops.c +++ b/sys/isofs/cd9660/cd9660_vfsops.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -174,7 +175,7 @@ cd9660_mount(struct mount *mp, struct thread *td) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); if (error) - error = suser(td); + error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { vput(devvp); return (error); diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c index ec7289f9d620..e3b108c2ce17 100644 --- a/sys/kern/kern_acct.c +++ b/sys/kern/kern_acct.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -166,8 +167,7 @@ acct(struct thread *td, struct acct_args *uap) struct nameidata nd; int error, flags, vfslocked; - /* Make sure that the caller is root. */ - error = suser(td); + error = priv_check(td, PRIV_ACCT); if (error) return (error); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index b62c977326e2..685222c7893f 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1351,7 +1352,7 @@ falloc(struct thread *td, struct file **resultfp, int *resultfd) sx_xlock(&filelist_lock); if ((openfiles >= maxuserfiles && - suser_cred(td->td_ucred, SUSER_RUID) != 0) || + priv_check_cred(td->td_ucred, PRIV_MAXFILES, SUSER_RUID) != 0) || openfiles >= maxfiles) { if (ppsratecheck(&lastfail, &curfail, 1)) { printf("kern.maxfiles limit exceeded by uid %i, please see tuning(7).\n", diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c index ff26529578b0..1d3362630ae8 100644 --- a/sys/kern/kern_environment.c +++ b/sys/kern/kern_environment.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -125,11 +126,18 @@ kenv(td, uap) return (error); } - if ((uap->what == KENV_SET) || - (uap->what == KENV_UNSET)) { - error = suser(td); + switch (uap->what) { + case KENV_SET: + error = priv_check(td, PRIV_KENV_SET); if (error) return (error); + break; + + case KENV_UNSET: + error = priv_check(td, PRIV_KENV_UNSET); + if (error) + return (error); + break; } name = malloc(KENV_MNAMELEN, M_TEMP, M_WAITOK); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index e513908bafcf..75843eb0a86b 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -571,8 +572,11 @@ do_execve(td, args, mac_p) * we do not regain any tracing during a possible block. */ setsugid(p); + #ifdef KTRACE - if (p->p_tracevp != NULL && suser_cred(oldcred, SUSER_ALLOWJAIL)) { + if (p->p_tracevp != NULL && + priv_check_cred(oldcred, PRIV_DEBUG_DIFFCRED, + SUSER_ALLOWJAIL)) { mtx_lock(&ktrace_mtx); p->p_traceflag = 0; tracevp = p->p_tracevp; diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index e92720bd7c10..9c5597ec60c0 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -310,7 +311,7 @@ fork1(td, flags, pages, procp) */ sx_xlock(&allproc_lock); if ((nprocs >= maxproc - 10 && - suser_cred(td->td_ucred, SUSER_RUID) != 0) || + priv_check_cred(td->td_ucred, PRIV_MAXPROC, SUSER_RUID) != 0) || nprocs >= maxproc) { error = EAGAIN; goto fail; @@ -319,8 +320,11 @@ fork1(td, flags, pages, procp) /* * Increment the count of procs running with this uid. Don't allow * a nonprivileged user to exceed their current limit. + * + * XXXRW: Can we avoid privilege here if it's not needed? */ - error = suser_cred(td->td_ucred, SUSER_RUID | SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_PROC_LIMIT, SUSER_RUID | + SUSER_ALLOWJAIL); if (error == 0) ok = chgproccnt(td->td_ucred->cr_ruidinfo, 1, 0); else { diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index e79fa7ca7149..b5a44564205d 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -807,7 +808,8 @@ ktrops(td, p, ops, facs, vp) p->p_tracecred = crhold(td->td_ucred); } p->p_traceflag |= facs; - if (suser_cred(td->td_ucred, SUSER_ALLOWJAIL) == 0) + if (priv_check_cred(td->td_ucred, PRIV_KTRACE, + SUSER_ALLOWJAIL) == 0) p->p_traceflag |= KTRFAC_ROOT; } else { /* KTROP_CLEAR */ @@ -1013,7 +1015,7 @@ ktrcanset(td, targetp) PROC_LOCK_ASSERT(targetp, MA_OWNED); if (targetp->p_traceflag & KTRFAC_ROOT && - suser_cred(td->td_ucred, SUSER_ALLOWJAIL)) + priv_check_cred(td->td_ucred, PRIV_KTRACE, SUSER_ALLOWJAIL)) return (0); if (p_candebug(td, targetp) != 0) diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 0bdd9f852c83..6d0dd0f78c8c 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -854,7 +855,7 @@ kern_kldload(struct thread *td, const char *file, int *fileid) if ((error = securelevel_gt(td->td_ucred, 0)) != 0) return (error); - if ((error = suser(td)) != 0) + if ((error = priv_check(td, PRIV_KLD_LOAD)) != 0) return (error); /* @@ -921,7 +922,7 @@ kern_kldunload(struct thread *td, int fileid, int flags) if ((error = securelevel_gt(td->td_ucred, 0)) != 0) return (error); - if ((error = suser(td)) != 0) + if ((error = priv_check(td, PRIV_KLD_UNLOAD)) != 0) return (error); KLD_LOCK(); diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c index 53deb9fc7994..87d10d773d33 100644 --- a/sys/kern/kern_ntptime.c +++ b/sys/kern/kern_ntptime.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -333,7 +334,7 @@ ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap) mtx_lock(&Giant); modes = ntv.modes; if (modes) - error = suser(td); + error = priv_check(td, PRIV_NTP_ADJTIME); if (error) goto done2; s = splclock(); @@ -954,7 +955,7 @@ kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta) struct timeval atv; int error; - if ((error = suser(td))) + if ((error = priv_check(td, PRIV_ADJTIME))) return (error); mtx_lock(&Giant); diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 524631f99379..3ba110f38dae 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -264,7 +265,7 @@ donice(struct thread *td, struct proc *p, int n) n = PRIO_MAX; if (n < PRIO_MIN) n = PRIO_MIN; - if (n < p->p_nice && suser(td) != 0) + if (n < p->p_nice && priv_check(td, PRIV_SCHED_SETPRIORITY) != 0) return (EACCES); mtx_lock_spin(&sched_lock); sched_nice(p, n); @@ -468,7 +469,7 @@ rtprio(td, uap) break; /* Disallow setting rtprio in most cases if not superuser. */ - if (suser(td) != 0) { + if (priv_check(td, PRIV_SCHED_RTPRIO) != 0) { /* can't set someone else's */ if (uap->pid) { error = EPERM; @@ -754,7 +755,8 @@ kern_setrlimit(td, which, limp) alimp = &oldlim->pl_rlimit[which]; if (limp->rlim_cur > alimp->rlim_max || limp->rlim_max > alimp->rlim_max) - if ((error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL))) { + if ((error = priv_check_cred(td->td_ucred, + PRIV_PROC_SETRLIMIT, SUSER_ALLOWJAIL))) { PROC_UNLOCK(p); lim_free(newlim); return (error); diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index a5bcfa8019af..a20daa772633 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -164,7 +165,7 @@ reboot(struct thread *td, struct reboot_args *uap) error = mac_check_system_reboot(td->td_ucred, uap->opt); #endif if (error == 0) - error = suser(td); + error = priv_check(td, PRIV_REBOOT); if (error == 0) { mtx_lock(&Giant); boot(uap->opt); diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index a9292913aea2..60155514f206 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -512,7 +513,7 @@ sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS) { int error; - error = suser(req->td); + error = priv_check(req->td, PRIV_SYSCTL_DEBUG); if (error) return (error); sysctl_sysctl_debug_dump_node(&sysctl__children, 0); @@ -1253,13 +1254,11 @@ sysctl_root(SYSCTL_HANDLER_ARGS) /* Is this sysctl writable by only privileged users? */ if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) { - int flags; - if (oid->oid_kind & CTLFLAG_PRISON) - flags = SUSER_ALLOWJAIL; + error = priv_check_cred(req->td->td_ucred, + PRIV_SYSCTL_WRITEJAIL, SUSER_ALLOWJAIL); else - flags = 0; - error = suser_cred(req->td->td_ucred, flags); + error = priv_check(req->td, PRIV_SYSCTL_WRITE); if (error) return (error); } diff --git a/sys/kern/kern_thr.c b/sys/kern/kern_thr.c index bfa1e2ba8e6b..72798accc995 100644 --- a/sys/kern/kern_thr.c +++ b/sys/kern/kern_thr.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -164,7 +165,7 @@ create_thread(struct thread *td, mcontext_t *ctx, case RTP_PRIO_REALTIME: case RTP_PRIO_FIFO: /* Only root can set scheduler policy */ - if (suser(td) != 0) + if (priv_check(td, PRIV_SCHED_SETPOLICY) != 0) return (EPERM); if (rtp->prio > RTP_PRIO_MAX) return (EINVAL); diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 479348e14276..53ce9e455520 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -286,7 +287,7 @@ kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) if (error) return (error); #endif - if ((error = suser(td)) != 0) + if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) return (error); if (clock_id != CLOCK_REALTIME) return (EINVAL); @@ -504,7 +505,7 @@ kern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp) if (error) return (error); #endif - error = suser(td); + error = priv_check(td, PRIV_SETTIMEOFDAY); if (error) return (error); /* Verify all parameters before changing time. */ diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index d6c8c2d326a1..e9513c871b94 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1813,7 +1814,7 @@ _do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags, int timo, if ((error = umtx_key_get(m, TYPE_PP_UMUTEX, GET_SHARE(flags), &uq->uq_key)) != 0) return (error); - su = (suser(td) == 0); + su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0); for (;;) { old_inherited_pri = uq->uq_inherited_pri; umtxq_lock(&uq->uq_key); @@ -1934,7 +1935,7 @@ do_unlock_pp(struct thread *td, struct umutex *m, uint32_t flags) id = td->td_tid; uq = td->td_umtxq; - su = (suser(td) == 0); + su = (priv_check(td, PRIV_SCHED_RTPRIO) == 0); /* * Make sure we own this mtx. diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c index d93ba37b67ae..81c2df4608cc 100644 --- a/sys/kern/kern_xxx.c +++ b/sys/kern/kern_xxx.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -139,7 +140,8 @@ osethostid(td, uap) { int error; - if ((error = suser(td))) + error = priv_check(td, PRIV_SETHOSTID); + if (error) return (error); mtx_lock(&Giant); hostid = uap->hostid; @@ -295,9 +297,10 @@ setdomainname(td, uap) { int error, domainnamelen; + error = priv_check(td, PRIV_SETDOMAINNAME); + if (error) + return (error); mtx_lock(&Giant); - if ((error = suser(td))) - goto done2; if ((u_int)uap->len > sizeof (domainname) - 1) { error = EINVAL; goto done2; @@ -309,4 +312,3 @@ setdomainname(td, uap) mtx_unlock(&Giant); return (error); } - diff --git a/sys/kern/p1003_1b.c b/sys/kern/p1003_1b.c index 189f5934421a..8ed0de53af10 100644 --- a/sys/kern/p1003_1b.c +++ b/sys/kern/p1003_1b.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -186,9 +187,10 @@ sched_setscheduler(struct thread *td, struct sched_setscheduler_args *uap) struct thread *targettd; struct proc *targetp; - /* Don't allow non root user to set a scheduler policy */ - if (suser(td) != 0) - return (EPERM); + /* Don't allow non root user to set a scheduler policy. */ + e = priv_check(td, PRIV_SCHED_SET); + if (e) + return (e); e = copyin(uap->param, &sched_param, sizeof(sched_param)); if (e) diff --git a/sys/kern/subr_acl_posix1e.c b/sys/kern/subr_acl_posix1e.c index a3ea7032b401..94c612f2a0f7 100644 --- a/sys/kern/subr_acl_posix1e.c +++ b/sys/kern/subr_acl_posix1e.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -46,9 +47,9 @@ __FBSDID("$FreeBSD$"); /* * Implement a version of vaccess() that understands POSIX.1e ACL semantics; - * the access ACL has already been prepared for evaluation by the file - * system and is passed via 'uid', 'gid', and 'acl'. Return 0 on success, - * else an errno value. + * the access ACL has already been prepared for evaluation by the file system + * and is passed via 'uid', 'gid', and 'acl'. Return 0 on success, else an + * errno value. */ int vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, @@ -56,14 +57,14 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, { struct acl_entry *acl_other, *acl_mask; mode_t dac_granted; - mode_t cap_granted; + mode_t priv_granted; mode_t acl_mask_granted; int group_matched, i; /* * Look for a normal, non-privileged way to access the file/directory * as requested. If it exists, go with that. Otherwise, attempt to - * use privileges granted via cap_granted. In some cases, which + * use privileges granted via priv_granted. In some cases, which * privileges to use may be ambiguous due to "best match", in which * case fall back on first match for the time being. */ @@ -72,40 +73,34 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, /* * Determine privileges now, but don't apply until we've found a DAC - * entry that matches but has failed to allow access. POSIX.1e - * capabilities are not implemented, but we document how they would - * behave here if implemented. + * entry that matches but has failed to allow access. + * + * XXXRW: Ideally, we'd determine the privileges required before + * asking for them. */ -#ifndef CAPABILITIES - if (suser_cred(cred, SUSER_ALLOWJAIL) == 0) - cap_granted = VALLPERM; - else - cap_granted = 0; -#else - cap_granted = 0; + priv_granted = 0; if (type == VDIR) { - if ((acc_mode & VEXEC) && !cap_check(cred, NULL, - CAP_DAC_READ_SEARCH, SUSER_ALLOWJAIL)) - cap_granted |= VEXEC; + if ((acc_mode & VEXEC) && !priv_check_cred(cred, + PRIV_VFS_LOOKUP, SUSER_ALLOWJAIL)) + priv_granted |= VEXEC; } else { - if ((acc_mode & VEXEC) && !cap_check(cred, NULL, - CAP_DAC_EXECUTE, SUSER_ALLOWJAIL)) - cap_granted |= VEXEC; + if ((acc_mode & VEXEC) && !priv_check_cred(cred, + PRIV_VFS_EXEC, SUSER_ALLOWJAIL)) + priv_granted |= VEXEC; } - if ((acc_mode & VREAD) && !cap_check(cred, NULL, CAP_DAC_READ_SEARCH, + if ((acc_mode & VREAD) && !priv_check_cred(cred, PRIV_VFS_READ, SUSER_ALLOWJAIL)) - cap_granted |= VREAD; + priv_granted |= VREAD; if (((acc_mode & VWRITE) || (acc_mode & VAPPEND)) && - !cap_check(cred, NULL, CAP_DAC_WRITE, SUSER_ALLOWJAIL)) - cap_granted |= (VWRITE | VAPPEND); + !priv_check_cred(cred, PRIV_VFS_WRITE, SUSER_ALLOWJAIL)) + priv_granted |= (VWRITE | VAPPEND); - if ((acc_mode & VADMIN) && !cap_check(cred, NULL, CAP_FOWNER, + if ((acc_mode & VADMIN) && !priv_check_cred(cred, PRIV_VFS_ADMIN, SUSER_ALLOWJAIL)) - cap_granted |= VADMIN; -#endif /* CAPABILITIES */ + priv_granted |= VADMIN; /* * The owner matches if the effective uid associated with the @@ -129,7 +124,11 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, dac_granted |= (VWRITE | VAPPEND); if ((acc_mode & dac_granted) == acc_mode) return (0); - if ((acc_mode & (dac_granted | cap_granted)) == + + /* + * XXXRW: Do privilege lookup here. + */ + if ((acc_mode & (dac_granted | priv_granted)) == acc_mode) { if (privused != NULL) *privused = 1; @@ -183,13 +182,9 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, acl_mask_granted = VEXEC | VREAD | VWRITE | VAPPEND; /* - * Iterate through user ACL entries. Do checks twice, first without - * privilege, and then if a match is found but failed, a second time - * with privilege. - */ - - /* - * Check ACL_USER ACL entries. + * Check ACL_USER ACL entries. There will either be one or no + * matches; if there is one, we accept or rejected based on the + * match; otherwise, we continue on to groups. */ for (i = 0; i < acl->acl_cnt; i++) { switch (acl->acl_entry[i].ae_tag) { @@ -206,7 +201,10 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, dac_granted &= acl_mask_granted; if ((acc_mode & dac_granted) == acc_mode) return (0); - if ((acc_mode & (dac_granted | cap_granted)) != + /* + * XXXRW: Do privilege lookup here. + */ + if ((acc_mode & (dac_granted | priv_granted)) != acc_mode) goto error; @@ -286,8 +284,11 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, dac_granted |= (VWRITE | VAPPEND); dac_granted &= acl_mask_granted; - if ((acc_mode & (dac_granted | cap_granted)) != - acc_mode) + /* + * XXXRW: Do privilege lookup here. + */ + if ((acc_mode & (dac_granted | priv_granted)) + != acc_mode) break; if (privused != NULL) @@ -307,8 +308,11 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, dac_granted |= (VWRITE | VAPPEND); dac_granted &= acl_mask_granted; - if ((acc_mode & (dac_granted | cap_granted)) != - acc_mode) + /* + * XXXRW: Do privilege lookup here. + */ + if ((acc_mode & (dac_granted | priv_granted)) + != acc_mode) break; if (privused != NULL) @@ -339,7 +343,10 @@ vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid, if ((acc_mode & dac_granted) == acc_mode) return (0); - if ((acc_mode & (dac_granted | cap_granted)) == acc_mode) { + /* + * XXXRW: Do privilege lookup here. + */ + if ((acc_mode & (dac_granted | priv_granted)) == acc_mode) { if (privused != NULL) *privused = 1; return (0); diff --git a/sys/kern/subr_firmware.c b/sys/kern/subr_firmware.c index 6de4fa455104..a83e567e9b3e 100644 --- a/sys/kern/subr_firmware.c +++ b/sys/kern/subr_firmware.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -190,7 +191,8 @@ firmware_get(const char *imagename) return NULL; } td = curthread; - if (suser(td) != 0 || securelevel_gt(td->td_ucred, 0) != 0) { + if (priv_check(td, PRIV_FIRMWARE_LOAD) != 0 || + securelevel_gt(td->td_ucred, 0) != 0) { printf("%s: insufficient privileges to " "load firmware image %s\n", __func__, imagename); return NULL; diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c index b6ffc91fc1ac..c53bf9897d97 100644 --- a/sys/kern/subr_prf.c +++ b/sys/kern/subr_prf.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -925,7 +926,7 @@ sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) int error, len; if (!unprivileged_read_msgbuf) { - error = suser(req->td); + error = priv_check(req->td, PRIV_MSGBUF); if (error) return (error); } diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index 4018d3f7e1ec..a99172e93c31 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -533,7 +534,10 @@ sysctl_debug_witness_watch(SYSCTL_HANDLER_ARGS) error = sysctl_handle_int(oidp, &value, 0, req); if (error != 0 || req->newptr == NULL) return (error); - error = suser(req->td); + /* + * XXXRW: Why a priv check here? + */ + error = priv_check(req->td, PRIV_WITNESS); if (error != 0) return (error); if (value == witness_watch) diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c index 8fec1da00a64..0cbb4bbe8c42 100644 --- a/sys/kern/sysv_ipc.c +++ b/sys/kern/sysv_ipc.c @@ -1,8 +1,12 @@ /* $NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $ */ /*- * Copyright (c) 1994 Herb Peyerl + * Copyright (c) 2006 nCircle Network Security, Inc. * All rights reserved. * + * This software was developed by Robert N. M. Watson for the TrustedBSD + * Project under contract to nCircle Network Security, Inc. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -72,50 +77,73 @@ shmexit(struct vmspace *vm) * Note: The MAC Framework does not require any modifications to the * ipcperm() function, as access control checks are performed throughout the * implementation of each primitive. Those entry point calls complement the - * ipcperm() discertionary checks. + * ipcperm() discertionary checks. Unlike file system discretionary access + * control, the original create of an object is given the same rights as the + * current owner. */ int -ipcperm(td, perm, mode) - struct thread *td; - struct ipc_perm *perm; - int mode; +ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode) { struct ucred *cred = td->td_ucred; - int error; + int error, obj_mode, dac_granted, priv_granted; - if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) { - /* - * For a non-create/owner, we require privilege to - * modify the object protections. Note: some other - * implementations permit IPC_M to be delegated to - * unprivileged non-creator/owner uids/gids. - */ - if (mode & IPC_M) { - error = suser(td); - if (error) - return (error); - } - /* - * Try to match against creator/owner group; if not, fall - * back on other. - */ - mode >>= 3; - if (!groupmember(perm->gid, cred) && - !groupmember(perm->cgid, cred)) - mode >>= 3; + dac_granted = 0; + if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) { + obj_mode = perm->mode; + dac_granted |= IPC_M; + } else if (groupmember(perm->gid, cred) || + groupmember(perm->cgid, cred)) { + obj_mode = perm->mode; + obj_mode <<= 3; } else { - /* - * Always permit the creator/owner to update the object - * protections regardless of whether the object mode - * permits it. - */ - if (mode & IPC_M) - return (0); + obj_mode = perm->mode; + obj_mode <<= 6; } - if ((mode & perm->mode) != mode) { - if (suser(td) != 0) - return (EACCES); + /* + * While the System V IPC permission model allows IPC_M to be + * granted, as part of the mode, our implementation requires + * privilege to adminster the object if not the owner or creator. + */ +#if 0 + if (obj_mode & IPC_M) + dac_granted |= IPC_M; +#endif + if (obj_mode & IPC_R) + dac_granted |= IPC_R; + if (obj_mode & IPC_W) + dac_granted |= IPC_W; + + /* + * Simple case: all required rights are granted by DAC. + */ + if ((dac_granted & acc_mode) == acc_mode) + return (0); + + /* + * Privilege is required to satisfy the request. + */ + priv_granted = 0; + if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) { + error = priv_check(td, PRIV_IPC_ADMIN); + if (error == 0) + priv_granted |= IPC_M; } - return (0); + + if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) { + error = priv_check(td, PRIV_IPC_READ); + if (error == 0) + priv_granted |= IPC_R; + } + + if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) { + error = priv_check(td, PRIV_IPC_WRITE); + if (error == 0) + priv_granted |= IPC_W; + } + + if (((dac_granted | priv_granted) & acc_mode) == acc_mode) + return (0); + else + return (EACCES); } diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index 464a7e520c92..a3db14c3d797 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -507,7 +508,7 @@ kern_msgctl(td, msqid, cmd, msqbuf) if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M))) goto done2; if (msqbuf->msg_qbytes > msqkptr->u.msg_qbytes) { - error = suser(td); + error = priv_check(td, PRIV_IPC_MSGSIZE); if (error) goto done2; } diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 29ddde31dc1f..17205f2acea6 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -86,6 +86,7 @@ __FBSDID("$FreeBSD$"); #if defined(COMPAT_43TTY) #include #endif +#include #include #define TTYDEFCHARS #include @@ -1020,7 +1021,7 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag) break; case TIOCMSDTRWAIT: /* must be root since the wait applies to following logins */ - error = suser(td); + error = priv_check(td, PRIV_TTY_DTRWAIT); if (error) return (error); tp->t_dtr_wait = *(int *)data * hz / 100; @@ -1169,9 +1170,9 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag) splx(s); break; case TIOCSTI: /* simulate terminal input */ - if ((flag & FREAD) == 0 && suser(td)) + if ((flag & FREAD) == 0 && priv_check(td, PRIV_TTY_STI)) return (EPERM); - if (!isctty(p, tp) && suser(td)) + if (!isctty(p, tp) && priv_check(td, PRIV_TTY_STI)) return (EACCES); s = spltty(); ttyld_rint(tp, *(u_char *)data); @@ -1244,7 +1245,7 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag) } break; case TIOCSDRAINWAIT: - error = suser(td); + error = priv_check(td, PRIV_TTY_DRAINWAIT); if (error) return (error); tp->t_timeout = *(int *)data * hz; @@ -3114,7 +3115,8 @@ ttyopen(struct cdev *dev, int flag, int mode, struct thread *td) goto out; goto open_top; } - if (tp->t_state & TS_XCLUDE && suser(td)) + if (tp->t_state & TS_XCLUDE && priv_check(td, + PRIV_TTY_EXCLUSIVE)) return (EBUSY); } else { /* @@ -3340,7 +3342,7 @@ ttysioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t ct = dev->si_drv2; switch (cmd) { case TIOCSETA: - error = suser(td); + error = priv_check(td, PRIV_TTY_SETA); if (error != 0) return (error); *ct = *(struct termios *)data; diff --git a/sys/kern/tty_cons.c b/sys/kern/tty_cons.c index 4472470e088a..8e9e2a544e71 100644 --- a/sys/kern/tty_cons.c +++ b/sys/kern/tty_cons.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -510,7 +511,7 @@ cnioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) * output from the "virtual" console. */ if (cmd == TIOCCONS && constty) { - error = suser(td); + error = priv_check(td, PRIV_TTY_CONSOLE); if (error) return (error); constty = NULL; diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index d5880a2183c9..205cf5756eb7 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #if defined(COMPAT_43TTY) #include #endif +#include #include #include #include @@ -268,9 +269,11 @@ ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td) tp = dev->si_tty; if ((tp->t_state & TS_ISOPEN) == 0) ttyinitmode(tp, 1, 0); - else if (tp->t_state & TS_XCLUDE && suser(td)) { + else if (tp->t_state & TS_XCLUDE && priv_check(td, + PRIV_TTY_EXCLUSIVE)) { return (EBUSY); - } else if (pt->pt_prison != td->td_ucred->cr_prison && suser(td)) { + } else if (pt->pt_prison != td->td_ucred->cr_prison && + priv_check(td, PRIV_TTY_PRISON)) { return (EBUSY); } if (tp->t_oproc) /* Ctrlr still around. */ diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index a973f6a51119..a59430f381ea 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #if defined(COMPAT_43TTY) #include #endif +#include #include #include #include @@ -207,9 +208,11 @@ ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td) if ((tp->t_state & TS_ISOPEN) == 0) { ttyinitmode(tp, 1, 0); - } else if (tp->t_state & TS_XCLUDE && suser(td)) + } else if (tp->t_state & TS_XCLUDE && priv_check(td, + PRIV_TTY_EXCLUSIVE)) return (EBUSY); - else if (pt->pt_prison != td->td_ucred->cr_prison && suser(td)) + else if (pt->pt_prison != td->td_ucred->cr_prison && + priv_check(td, PRIV_TTY_PRISON)) return (EBUSY); if (tp->t_oproc) /* Ctrlr still around. */ (void)ttyld_modem(tp, 1); diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index d6cf2e5234cc..9185c0ed9113 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -955,8 +956,12 @@ int do_unlink(struct mqfs_node *pn, struct ucred *ucred) sx_assert(&pn->mn_info->mi_lock, SX_LOCKED); + /* + * XXXRW: Other instances of the message queue primitive are + * allowed in jail? + */ if (ucred->cr_uid != pn->mn_uid && - (error = suser_cred(ucred, 0)) != 0) + (error = priv_check_cred(ucred, PRIV_MQ_ADMIN, 0)) != 0) error = EACCES; else if (!pn->mn_deleted) { parent = pn->mn_parent; @@ -1207,10 +1212,16 @@ mqfs_setattr(struct vop_setattr_args *ap) */ if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td))) return (error); + + /* + * XXXRW: Why is there a privilege check here: shouldn't the + * check in VOP_ACCESS() be enough? Also, are the group bits + * below definitely right? + */ if (((ap->a_cred->cr_uid != pn->mn_uid) || uid != pn->mn_uid || (gid != pn->mn_gid && !groupmember(gid, ap->a_cred))) && - (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)) - != 0) + (error = priv_check_cred(ap->a_td->td_ucred, + PRIV_MQ_ADMIN, SUSER_ALLOWJAIL)) != 0) return (error); pn->mn_uid = uid; pn->mn_gid = gid; @@ -1219,7 +1230,8 @@ mqfs_setattr(struct vop_setattr_args *ap) if (vap->va_mode != (mode_t)VNOVAL) { if ((ap->a_cred->cr_uid != pn->mn_uid) && - (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL))) + (error = priv_check_cred(ap->a_td->td_ucred, + PRIV_MQ_ADMIN, SUSER_ALLOWJAIL))) return (error); pn->mn_mode = vap->va_mode; c = 1; diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index 8de7d8f27162..340c1a6831b0 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -419,15 +420,23 @@ sem_perm(struct thread *td, struct ksem *ks) { struct ucred *uc; + /* + * XXXRW: This permission routine appears to be incorrect. If the + * user matches, we shouldn't go on to the group if the user + * permissions don't allow the action? Not changed for now. To fix, + * change from a series of if (); if (); to if () else if () else... + */ uc = td->td_ucred; DP(("sem_perm: uc(%d,%d) ks(%d,%d,%o)\n", uc->cr_uid, uc->cr_gid, ks->ks_uid, ks->ks_gid, ks->ks_mode)); - if ((uc->cr_uid == ks->ks_uid && (ks->ks_mode & S_IWUSR) != 0) || - (uc->cr_gid == ks->ks_gid && (ks->ks_mode & S_IWGRP) != 0) || - (ks->ks_mode & S_IWOTH) != 0 || suser(td) == 0) + if ((uc->cr_uid == ks->ks_uid) && (ks->ks_mode & S_IWUSR) != 0) return (0); - return (EPERM); + if ((uc->cr_gid == ks->ks_gid) && (ks->ks_mode & S_IWGRP) != 0) + return (0); + if ((ks->ks_mode & S_IWOTH) != 0) + return (0); + return (priv_check(td, PRIV_SEM_WRITE)); } static void diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 8a57786fba3f..bb51d010727b 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -272,7 +273,7 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, error = VFS_STATFS(mp, sp, td); if (error) goto out; - if (suser(td)) { + if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); @@ -357,7 +358,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) error = VFS_STATFS(mp, sp, td); if (error) goto out; - if (suser(td)) { + if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); @@ -468,7 +469,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, vfs_unbusy(mp, td); continue; } - if (suser(td)) { + if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); @@ -842,7 +843,8 @@ chroot(td, uap) struct nameidata nd; int vfslocked; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, + SUSER_ALLOWJAIL); if (error) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, @@ -896,8 +898,8 @@ change_dir(vp, td) /* * Common routine for kern_chroot() and jail_attach(). The caller is - * responsible for invoking suser() and mac_check_chroot() to authorize this - * operation. + * responsible for invoking priv_check() and mac_check_chroot() to authorize + * this operation. */ int change_root(vp, td) @@ -1186,10 +1188,16 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: - error = suser(td); + error = priv_check(td, PRIV_VFS_MKNOD_DEV); + break; + case S_IFMT: + error = priv_check(td, PRIV_VFS_MKNOD_BAD); + break; + case S_IFWHT: + error = priv_check(td, PRIV_VFS_MKNOD_WHT); break; default: - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = EINVAL; break; } if (error) @@ -1234,8 +1242,7 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, whiteout = 1; break; default: - error = EINVAL; - break; + panic("kern_mknod: invalid mode"); } } if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { @@ -1390,9 +1397,6 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) struct vattr va; int error; - if (suser_cred(cred, SUSER_ALLOWJAIL) == 0) - return (0); - if (!hardlink_check_uid && !hardlink_check_gid) return (0); @@ -1400,14 +1404,18 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) if (error != 0) return (error); - if (hardlink_check_uid) { - if (cred->cr_uid != va.va_uid) - return (EPERM); + if (hardlink_check_uid && cred->cr_uid != va.va_uid) { + error = priv_check_cred(cred, PRIV_VFS_LINK, + SUSER_ALLOWJAIL); + if (error) + return (error); } - if (hardlink_check_gid) { - if (!groupmember(va.va_gid, cred)) - return (EPERM); + if (hardlink_check_gid && !groupmember(va.va_gid, cred)) { + error = priv_check_cred(cred, PRIV_VFS_LINK, + SUSER_ALLOWJAIL); + if (error) + return (error); } return (0); @@ -2361,7 +2369,8 @@ setfflags(td, vp, flags) * chown can't fail when done as root. */ if (vp->v_type == VCHR || vp->v_type == VBLK) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV, + SUSER_ALLOWJAIL); if (error) return (error); } @@ -3894,7 +3903,8 @@ revoke(td, uap) if (error) goto out; if (td->td_ucred->cr_uid != vattr.va_uid) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN, + SUSER_ALLOWJAIL); if (error) goto out; } @@ -3960,7 +3970,7 @@ lgetfh(td, uap) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_GETFH); if (error) return (error); NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, @@ -3999,7 +4009,7 @@ getfh(td, uap) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_GETFH); if (error) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, @@ -4022,10 +4032,10 @@ getfh(td, uap) } /* - * syscall for the rpc.lockd to use to translate a NFS file handle into - * an open descriptor. + * syscall for the rpc.lockd to use to translate a NFS file handle into an + * open descriptor. * - * warning: do not remove the suser() call or this becomes one giant + * warning: do not remove the priv_check() call or this becomes one giant * security hole. * * MP SAFE @@ -4058,7 +4068,7 @@ fhopen(td, uap) int vfslocked; int indx; - error = suser(td); + error = priv_check(td, PRIV_VFS_FHOPEN); if (error) return (error); fmode = FFLAGS(uap->flags); @@ -4242,7 +4252,7 @@ fhstat(td, uap) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_FHSTAT); if (error) return (error); error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); @@ -4307,7 +4317,7 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_FHSTATFS); if (error) return (error); if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index af07f443a2ae..ef757b825bab 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -808,23 +809,31 @@ vfs_domount( if (jailed(td->td_ucred)) return (EPERM); if (usermount == 0) { - if ((error = suser(td)) != 0) + if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0) return (error); } /* * Do not allow NFS export or MNT_SUIDDIR by unprivileged users. */ - if (fsflags & (MNT_EXPORTED | MNT_SUIDDIR)) { - if ((error = suser(td)) != 0) + if (fsflags & MNT_EXPORTED) { + error = priv_check(td, PRIV_VFS_MOUNT_EXPORTED); + if (error) return (error); } + if (fsflags & MNT_SUIDDIR) { + error = priv_check(td, PRIV_VFS_MOUNT_SUIDDIR); + if (error) + return (error); + + } /* - * Silently enforce MNT_NOSUID and MNT_USER for - * unprivileged users. + * Silently enforce MNT_NOSUID and MNT_USER for unprivileged users. */ - if (suser(td) != 0) - fsflags |= MNT_NOSUID | MNT_USER; + if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) { + if (priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0) + fsflags |= MNT_NOSUID | MNT_USER; + } /* Load KLDs before we lock the covered vnode to avoid reversals. */ vfsp = NULL; @@ -906,7 +915,9 @@ vfs_domount( return (error); } if (va.va_uid != td->td_ucred->cr_uid) { - if ((error = suser(td)) != 0) { + error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN, + SUSER_ALLOWJAIL); + if (error) { vput(vp); return (error); } @@ -1078,7 +1089,8 @@ unmount(td, uap) if (jailed(td->td_ucred)) return (EPERM); if (usermount == 0) { - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_VFS_UNMOUNT); + if (error) return (error); } diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 46ffd8f6a245..d584606408a7 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -412,7 +413,7 @@ vfs_suser(struct mount *mp, struct thread *td) if ((mp->mnt_flag & MNT_USER) == 0 || mp->mnt_cred->cr_uid != td->td_ucred->cr_uid) { - if ((error = suser(td)) != 0) + if ((error = priv_check(td, PRIV_VFS_MOUNT_OWNER)) != 0) return (error); } return (0); @@ -3178,9 +3179,7 @@ vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid, mode_t acc_mode, struct ucred *cred, int *privused) { mode_t dac_granted; -#ifdef CAPABILITIES - mode_t cap_granted; -#endif + mode_t priv_granted; /* * Look for a normal, non-privileged way to access the file/directory @@ -3234,59 +3233,46 @@ vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid, return (0); privcheck: - if (!suser_cred(cred, SUSER_ALLOWJAIL)) { - /* XXX audit: privilege used */ - if (privused != NULL) - *privused = 1; - return (0); - } - -#ifdef CAPABILITIES /* - * Build a capability mask to determine if the set of capabilities + * Build a privilege mask to determine if the set of privileges * satisfies the requirements when combined with the granted mask - * from above. For each capability, if the capability is required, - * bitwise or the request type onto the cap_granted mask. - * - * Note: This is never actually used, but is here for reference - * purposes. + * from above. For each privilege, if the privilege is required, + * bitwise or the request type onto the priv_granted mask. */ - cap_granted = 0; + priv_granted = 0; if (type == VDIR) { /* - * For directories, use CAP_DAC_READ_SEARCH to satisfy - * VEXEC requests, instead of CAP_DAC_EXECUTE. + * For directories, use PRIV_VFS_LOOKUP to satisfy VEXEC + * requests, instead of PRIV_VFS_EXEC. */ if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) && - !cap_check(cred, NULL, CAP_DAC_READ_SEARCH, - SUSER_ALLOWJAIL)) - cap_granted |= VEXEC; + !priv_check_cred(cred, PRIV_VFS_LOOKUP, SUSER_ALLOWJAIL)) + priv_granted |= VEXEC; } else { if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) && - !cap_check(cred, NULL, CAP_DAC_EXECUTE, SUSER_ALLOWJAIL)) - cap_granted |= VEXEC; + !priv_check_cred(cred, PRIV_VFS_EXEC, SUSER_ALLOWJAIL)) + priv_granted |= VEXEC; } if ((acc_mode & VREAD) && ((dac_granted & VREAD) == 0) && - !cap_check(cred, NULL, CAP_DAC_READ_SEARCH, SUSER_ALLOWJAIL)) - cap_granted |= VREAD; + !priv_check_cred(cred, PRIV_VFS_READ, SUSER_ALLOWJAIL)) + priv_granted |= VREAD; if ((acc_mode & VWRITE) && ((dac_granted & VWRITE) == 0) && - !cap_check(cred, NULL, CAP_DAC_WRITE, SUSER_ALLOWJAIL)) - cap_granted |= (VWRITE | VAPPEND); + !priv_check_cred(cred, PRIV_VFS_WRITE, SUSER_ALLOWJAIL)) + priv_granted |= (VWRITE | VAPPEND); if ((acc_mode & VADMIN) && ((dac_granted & VADMIN) == 0) && - !cap_check(cred, NULL, CAP_FOWNER, SUSER_ALLOWJAIL)) - cap_granted |= VADMIN; + !priv_check_cred(cred, PRIV_VFS_ADMIN, SUSER_ALLOWJAIL)) + priv_granted |= VADMIN; - if ((acc_mode & (cap_granted | dac_granted)) == acc_mode) { + if ((acc_mode & (priv_granted | dac_granted)) == acc_mode) { /* XXX audit: privilege used */ if (privused != NULL) *privused = 1; return (0); } -#endif return ((acc_mode & VADMIN) ? EPERM : EACCES); } @@ -3307,16 +3293,13 @@ extattr_check_cred(struct vnode *vp, int attrnamespace, struct ucred *cred, return (0); /* - * Do not allow privileged processes in jail to directly - * manipulate system attributes. - * - * XXX What capability should apply here? - * Probably CAP_SYS_SETFFLAG. + * Do not allow privileged processes in jail to directly manipulate + * system attributes. */ switch (attrnamespace) { case EXTATTR_NAMESPACE_SYSTEM: /* Potentially should be: return (EPERM); */ - return (suser_cred(cred, 0)); + return (priv_check_cred(cred, PRIV_VFS_EXTATTR_SYSTEM, 0)); case EXTATTR_NAMESPACE_USER: return (VOP_ACCESS(vp, access, cred, td)); default: diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 8a57786fba3f..bb51d010727b 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -272,7 +273,7 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg, error = VFS_STATFS(mp, sp, td); if (error) goto out; - if (suser(td)) { + if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); @@ -357,7 +358,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf) error = VFS_STATFS(mp, sp, td); if (error) goto out; - if (suser(td)) { + if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); @@ -468,7 +469,7 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, vfs_unbusy(mp, td); continue; } - if (suser(td)) { + if (priv_check(td, PRIV_VFS_GENERATION)) { bcopy(sp, &sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; prison_enforce_statfs(td->td_ucred, mp, &sb); @@ -842,7 +843,8 @@ chroot(td, uap) struct nameidata nd; int vfslocked; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, + SUSER_ALLOWJAIL); if (error) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, @@ -896,8 +898,8 @@ change_dir(vp, td) /* * Common routine for kern_chroot() and jail_attach(). The caller is - * responsible for invoking suser() and mac_check_chroot() to authorize this - * operation. + * responsible for invoking priv_check() and mac_check_chroot() to authorize + * this operation. */ int change_root(vp, td) @@ -1186,10 +1188,16 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: - error = suser(td); + error = priv_check(td, PRIV_VFS_MKNOD_DEV); + break; + case S_IFMT: + error = priv_check(td, PRIV_VFS_MKNOD_BAD); + break; + case S_IFWHT: + error = priv_check(td, PRIV_VFS_MKNOD_WHT); break; default: - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = EINVAL; break; } if (error) @@ -1234,8 +1242,7 @@ kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode, whiteout = 1; break; default: - error = EINVAL; - break; + panic("kern_mknod: invalid mode"); } } if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { @@ -1390,9 +1397,6 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) struct vattr va; int error; - if (suser_cred(cred, SUSER_ALLOWJAIL) == 0) - return (0); - if (!hardlink_check_uid && !hardlink_check_gid) return (0); @@ -1400,14 +1404,18 @@ can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred) if (error != 0) return (error); - if (hardlink_check_uid) { - if (cred->cr_uid != va.va_uid) - return (EPERM); + if (hardlink_check_uid && cred->cr_uid != va.va_uid) { + error = priv_check_cred(cred, PRIV_VFS_LINK, + SUSER_ALLOWJAIL); + if (error) + return (error); } - if (hardlink_check_gid) { - if (!groupmember(va.va_gid, cred)) - return (EPERM); + if (hardlink_check_gid && !groupmember(va.va_gid, cred)) { + error = priv_check_cred(cred, PRIV_VFS_LINK, + SUSER_ALLOWJAIL); + if (error) + return (error); } return (0); @@ -2361,7 +2369,8 @@ setfflags(td, vp, flags) * chown can't fail when done as root. */ if (vp->v_type == VCHR || vp->v_type == VBLK) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV, + SUSER_ALLOWJAIL); if (error) return (error); } @@ -3894,7 +3903,8 @@ revoke(td, uap) if (error) goto out; if (td->td_ucred->cr_uid != vattr.va_uid) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN, + SUSER_ALLOWJAIL); if (error) goto out; } @@ -3960,7 +3970,7 @@ lgetfh(td, uap) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_GETFH); if (error) return (error); NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, @@ -3999,7 +4009,7 @@ getfh(td, uap) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_GETFH); if (error) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, @@ -4022,10 +4032,10 @@ getfh(td, uap) } /* - * syscall for the rpc.lockd to use to translate a NFS file handle into - * an open descriptor. + * syscall for the rpc.lockd to use to translate a NFS file handle into an + * open descriptor. * - * warning: do not remove the suser() call or this becomes one giant + * warning: do not remove the priv_check() call or this becomes one giant * security hole. * * MP SAFE @@ -4058,7 +4068,7 @@ fhopen(td, uap) int vfslocked; int indx; - error = suser(td); + error = priv_check(td, PRIV_VFS_FHOPEN); if (error) return (error); fmode = FFLAGS(uap->flags); @@ -4242,7 +4252,7 @@ fhstat(td, uap) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_FHSTAT); if (error) return (error); error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t)); @@ -4307,7 +4317,7 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf) int vfslocked; int error; - error = suser(td); + error = priv_check(td, PRIV_VFS_FHSTATFS); if (error) return (error); if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 4a516a79bde4..35110449a8e9 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -709,7 +710,7 @@ vn_stat(vp, sb, active_cred, file_cred, td) sb->st_blksize = PAGE_SIZE; sb->st_flags = vap->va_flags; - if (suser(td)) + if (priv_check(td, PRIV_VFS_GENERATION)) sb->st_gen = 0; else sb->st_gen = vap->va_gen; diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 571d730a9af6..3389e1f9c7ce 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -1724,7 +1725,7 @@ bpf_stats_sysctl(SYSCTL_HANDLER_ARGS) * if the users who opened the devices were able to retrieve * the statistics for them, too. */ - error = suser(req->td); + error = priv_check(req->td, PRIV_NET_BPF); if (error) return (error); if (req->oldptr == NULL) diff --git a/sys/net/if.c b/sys/net/if.c index ba981d417ce4..ad32a443b5c0 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -1489,7 +1490,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) break; case SIOCSIFFLAGS: - error = suser(td); + error = priv_check(td, PRIV_NET_SETIFFLAGS); if (error) return (error); /* @@ -1532,7 +1533,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) break; case SIOCSIFCAP: - error = suser(td); + error = priv_check(td, PRIV_NET_SETIFCAP); if (error) return (error); if (ifp->if_ioctl == NULL) @@ -1553,8 +1554,8 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) #endif case SIOCSIFNAME: - error = suser(td); - if (error != 0) + error = priv_check(td, PRIV_NET_SETIFNAME); + if (error) return (error); error = copyinstr(ifr->ifr_data, new_name, IFNAMSIZ, NULL); if (error != 0) @@ -1600,7 +1601,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) break; case SIOCSIFMETRIC: - error = suser(td); + error = priv_check(td, PRIV_NET_SETIFMETRIC); if (error) return (error); ifp->if_metric = ifr->ifr_metric; @@ -1608,7 +1609,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) break; case SIOCSIFPHYS: - error = suser(td); + error = priv_check(td, PRIV_NET_SETIFPHYS); if (error) return (error); if (ifp->if_ioctl == NULL) @@ -1624,7 +1625,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) { u_long oldmtu = ifp->if_mtu; - error = suser(td); + error = priv_check(td, PRIV_NET_SETIFMTU); if (error) return (error); if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) @@ -1651,7 +1652,10 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) case SIOCADDMULTI: case SIOCDELMULTI: - error = suser(td); + if (cmd == SIOCADDMULTI) + error = priv_check(td, PRIV_NET_ADDMULTI); + else + error = priv_check(td, PRIV_NET_DELMULTI); if (error) return (error); @@ -1681,7 +1685,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) case SIOCSLIFPHYADDR: case SIOCSIFMEDIA: case SIOCSIFGENERIC: - error = suser(td); + error = priv_check(td, PRIV_NET_HWIOCTL); if (error) return (error); if (ifp->if_ioctl == NULL) @@ -1710,7 +1714,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) break; case SIOCSIFLLADDR: - error = suser(td); + error = priv_check(td, PRIV_NET_SETLLADDR); if (error) return (error); error = if_setlladdr(ifp, @@ -1721,7 +1725,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) { struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr; - error = suser(td); + error = priv_check(td, PRIV_NET_ADDIFGROUP); if (error) return (error); if ((error = if_addgroup(ifp, ifgr->ifgr_group))) @@ -1738,7 +1742,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) { struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr; - error = suser(td); + error = priv_check(td, PRIV_NET_DELIFGROUP); if (error) return (error); if ((error = if_delgroup(ifp, ifgr->ifgr_group))) @@ -1777,12 +1781,14 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) switch (cmd) { case SIOCIFCREATE: case SIOCIFCREATE2: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_IFCREATE); + if (error) return (error); return (if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name), cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL)); case SIOCIFDESTROY: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_IFDESTROY); + if (error) return (error); return if_clone_destroy(ifr->ifr_name); diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 35bbfa4dbaa3..83866eea081a 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -101,6 +101,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -694,7 +695,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } if (bc->bc_flags & BC_F_SUSER) { - error = suser(td); + error = priv_check(td, PRIV_NET_BRIDGE); if (error) break; } diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 2aa7b5249f63..ebd022693634 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -452,7 +453,11 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCSIFDSTADDR: break; case SIOCSIFFLAGS: - if ((error = suser(curthread)) != 0) + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_SETIFFLAGS)) != 0) break; if ((ifr->ifr_flags & IFF_LINK0) != 0) sc->g_proto = IPPROTO_GRE; @@ -464,7 +469,11 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->wccp_ver = WCCP_V1; goto recompute; case SIOCSIFMTU: - if ((error = suser(curthread)) != 0) + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_SETIFMTU)) != 0) break; if (ifr->ifr_mtu < 576) { error = EINVAL; @@ -476,8 +485,36 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ifr->ifr_mtu = GRE2IFP(sc)->if_mtu; break; case SIOCADDMULTI: + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_ADDMULTI)) != 0) + break; + if (ifr == 0) { + error = EAFNOSUPPORT; + break; + } + switch (ifr->ifr_addr.sa_family) { +#ifdef INET + case AF_INET: + break; +#endif +#ifdef INET6 + case AF_INET6: + break; +#endif + default: + error = EAFNOSUPPORT; + break; + } + break; case SIOCDELMULTI: - if ((error = suser(curthread)) != 0) + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_DELIFGROUP)) != 0) break; if (ifr == 0) { error = EAFNOSUPPORT; @@ -498,7 +535,11 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } break; case GRESPROTO: - if ((error = suser(curthread)) != 0) + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0) break; sc->g_proto = ifr->ifr_flags; switch (sc->g_proto) { @@ -518,8 +559,9 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case GRESADDRS: case GRESADDRD: - if ((error = suser(curthread)) != 0) - break; + error = priv_check(curthread, PRIV_NET_GRE); + if (error) + return (error); /* * set tunnel endpoints, compute a less specific route * to the remote end and mark if as up @@ -584,7 +626,11 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ifr->ifr_addr = *sa; break; case SIOCSIFPHYADDR: - if ((error = suser(curthread)) != 0) + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0) break; if (aifr->ifra_addr.sin_family != AF_INET || aifr->ifra_dstaddr.sin_family != AF_INET) { @@ -600,7 +646,11 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) sc->g_dst = aifr->ifra_dstaddr.sin_addr; goto recompute; case SIOCSLIFPHYADDR: - if ((error = suser(curthread)) != 0) + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0) break; if (lifr->addr.ss_family != AF_INET || lifr->dstaddr.ss_family != AF_INET) { @@ -617,7 +667,11 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) (satosin(&lifr->dstaddr))->sin_addr; goto recompute; case SIOCDIFPHYADDR: - if ((error = suser(curthread)) != 0) + /* + * XXXRW: Isn't this suser() redundant to the ifnet layer + * check? + */ + if ((error = priv_check(curthread, PRIV_NET_SETIFPHYS)) != 0) break; sc->g_src.s_addr = INADDR_ANY; sc->g_dst.s_addr = INADDR_ANY; diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index 87f9a4106c98..d01ed8f4aaed 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -87,6 +87,7 @@ #include #include +#include #include #include #include @@ -451,7 +452,8 @@ pppioctl(sc, cmd, data, flag, td) break; case PPPIOCSFLAGS: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; flags = *(int *)data & SC_MASK; s = splsoftnet(); @@ -465,8 +467,9 @@ pppioctl(sc, cmd, data, flag, td) break; case PPPIOCSMRU: - if ((error = suser(td)) != 0) - return (error); + error = priv_check(td, PRIV_NET_PPP); + if (error) + return (error); mru = *(int *)data; if (mru >= PPP_MRU && mru <= PPP_MAXMRU) sc->sc_mru = mru; @@ -478,7 +481,8 @@ pppioctl(sc, cmd, data, flag, td) #ifdef VJC case PPPIOCSMAXCID: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; if (sc->sc_comp) { s = splsoftnet(); @@ -489,14 +493,16 @@ pppioctl(sc, cmd, data, flag, td) #endif case PPPIOCXFERUNIT: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; sc->sc_xfer = p->p_pid; break; #ifdef PPP_COMPRESS case PPPIOCSCOMPRESS: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; odp = (struct ppp_option_data *) data; nb = odp->length; @@ -569,7 +575,8 @@ pppioctl(sc, cmd, data, flag, td) if (cmd == PPPIOCGNPMODE) { npi->mode = sc->sc_npmode[npx]; } else { - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; if (npi->mode != sc->sc_npmode[npx]) { s = splsoftnet(); @@ -695,6 +702,10 @@ pppsioctl(ifp, cmd, data) break; case SIOCSIFMTU: + /* + * XXXRW: Isn't this suser() check redundant to the one at the ifnet + * layer? + */ if ((error = suser(td)) != 0) break; if (ifr->ifr_mtu > PPP_MAXMTU) diff --git a/sys/net/if_sl.c b/sys/net/if_sl.c index d33e08152374..3e339706d394 100644 --- a/sys/net/if_sl.c +++ b/sys/net/if_sl.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -366,7 +367,7 @@ slopen(struct cdev *dev, register struct tty *tp) register struct sl_softc *sc; int s, error; - error = suser(curthread); + error = priv_check(curthread, PRIV_NET_SLIP); if (error) return (error); diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c index 05b39d070998..ddb14cdb59b4 100644 --- a/sys/net/if_tap.c +++ b/sys/net/if_tap.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -373,10 +374,13 @@ tapopen(struct cdev *dev, int flag, int mode, struct thread *td) { struct tap_softc *tp = NULL; struct ifnet *ifp = NULL; - int s; + int error, s; - if (tapuopen == 0 && suser(td) != 0) - return (EPERM); + if (tapuopen == 0) { + error = priv_check(td, PRIV_NET_TAP); + if (error) + return (error); + } if ((dev2unit(dev) & CLONE_UNITMASK) > TAPMAXUNIT) return (ENXIO); diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 610c4b53f6e0..b313b18b18e0 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -23,6 +23,7 @@ #include "opt_mac.h" #include +#include #include #include #include @@ -597,9 +598,11 @@ tunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td tunp = (struct tuninfo *)data; if (tunp->mtu < IF_MINMTU) return (EINVAL); - if (TUN2IFP(tp)->if_mtu != tunp->mtu - && (error = suser(td)) != 0) - return (error); + if (TUN2IFP(tp)->if_mtu != tunp->mtu) { + error = priv_check(td, PRIV_NET_SETIFMTU); + if (error) + return (error); + } TUN2IFP(tp)->if_mtu = tunp->mtu; TUN2IFP(tp)->if_type = tunp->type; TUN2IFP(tp)->if_baudrate = tunp->baudrate; diff --git a/sys/net/ppp_tty.c b/sys/net/ppp_tty.c index a90bfc8107dc..6e79985e6eb8 100644 --- a/sys/net/ppp_tty.c +++ b/sys/net/ppp_tty.c @@ -79,6 +79,7 @@ #include #include +#include #include #include #include @@ -179,7 +180,8 @@ pppopen(dev, tp) register struct ppp_softc *sc; int error, s; - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) return (error); s = spltty(); @@ -423,7 +425,8 @@ ppptioctl(tp, cmd, data, flag, td) error = 0; switch (cmd) { case PPPIOCSASYNCMAP: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; sc->sc_asyncmap[0] = *(u_int *)data; break; @@ -433,7 +436,8 @@ ppptioctl(tp, cmd, data, flag, td) break; case PPPIOCSRASYNCMAP: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; sc->sc_rasyncmap = *(u_int *)data; break; @@ -443,7 +447,8 @@ ppptioctl(tp, cmd, data, flag, td) break; case PPPIOCSXASYNCMAP: - if ((error = suser(td)) != 0) + error = priv_check(td, PRIV_NET_PPP); + if (error) break; s = spltty(); bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c index b584860e3d62..22f3e7b8adf1 100644 --- a/sys/net/raw_usrreq.c +++ b/sys/net/raw_usrreq.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -171,8 +172,11 @@ raw_uattach(struct socket *so, int proto, struct thread *td) */ KASSERT(sotorawcb(so) != NULL, ("raw_uattach: so_pcb == NULL")); - if (td && (error = suser(td)) != 0) - return error; + if (td != NULL) { + error = priv_check(td, PRIV_NET_RAW); + if (error) + return error; + } return raw_attach(so, proto); } diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index c4eebf79f15e..c13f4ecd1993 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -372,8 +373,11 @@ route_output(struct mbuf *m, struct socket *so) * Verify that the caller has the appropriate privilege; RTM_GET * is the only operation the non-superuser is allowed. */ - if (rtm->rtm_type != RTM_GET && (error = suser(curthread)) != 0) - senderr(error); + if (rtm->rtm_type != RTM_GET) { + error = priv_check(curthread, PRIV_NET_ROUTE); + if (error) + senderr(error); + } switch (rtm->rtm_type) { struct rtentry *saved_nrt; diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index e73648f9f894..e5e6f421b7be 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -344,7 +345,7 @@ ieee80211_cfgget(struct ieee80211com *ic, u_long cmd, caddr_t data) case WI_RID_DEFLT_CRYPT_KEYS: keys = (struct wi_ltv_keys *)&wreq; /* do not show keys to non-root user */ - error = suser(curthread); + error = priv_check(curthread, PRIV_NET80211_GETKEY); if (error) { memset(keys, 0, sizeof(*keys)); error = 0; @@ -861,7 +862,7 @@ ieee80211_ioctl_getkey(struct ieee80211com *ic, struct ieee80211req *ireq) ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); if (wk->wk_keyix == ic->ic_def_txkey) ik.ik_flags |= IEEE80211_KEY_DEFAULT; - if (suser(curthread) == 0) { + if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { /* NB: only root can read key data */ ik.ik_keyrsc = wk->wk_keyrsc; ik.ik_keytsc = wk->wk_keytsc; @@ -1510,7 +1511,7 @@ ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re return EINVAL; len = (u_int) ic->ic_nw_keys[kid].wk_keylen; /* NB: only root can read WEP keys */ - if (suser(curthread) == 0) { + if (priv_check(curthread, PRIV_NET80211_GETKEY) == 0) { bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len); } else { bzero(tmpkey, len); @@ -2692,7 +2693,7 @@ ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) (struct ieee80211req *) data); break; case SIOCS80211: - error = suser(curthread); + error = priv_check(curthread, PRIV_NET80211_MANAGE); if (error == 0) error = ieee80211_ioctl_set80211(ic, cmd, (struct ieee80211req *) data); @@ -2701,7 +2702,7 @@ ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) error = ieee80211_cfgget(ic, cmd, data); break; case SIOCSIFGENERIC: - error = suser(curthread); + error = priv_check(curthread, PRIV_NET80211_MANAGE); if (error) break; error = ieee80211_cfgset(ic, cmd, data); diff --git a/sys/netatalk/at_control.c b/sys/netatalk/at_control.c index 4dc0a716a80f..a5dbe93abf38 100644 --- a/sys/netatalk/at_control.c +++ b/sys/netatalk/at_control.c @@ -118,6 +118,8 @@ at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, case SIOCSIFADDR: /* * If we are not superuser, then we don't get to do these ops. + * + * XXXRW: Layering? */ if (suser(td)) return (EPERM); diff --git a/sys/netatalk/ddp_pcb.c b/sys/netatalk/ddp_pcb.c index 66ece43bb639..e51d5758ffb5 100644 --- a/sys/netatalk/ddp_pcb.c +++ b/sys/netatalk/ddp_pcb.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -100,7 +101,7 @@ at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td) return (EINVAL); } if (sat->sat_port < ATPORT_RESERVED && - suser(td)) { + priv_check(td, PRIV_NETATALK_RESERVEDPORT)) { return (EACCES); } } diff --git a/sys/netatm/atm_usrreq.c b/sys/netatm/atm_usrreq.c index ad14e84a366f..6f40a4651227 100644 --- a/sys/netatm/atm_usrreq.c +++ b/sys/netatm/atm_usrreq.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -181,8 +182,11 @@ atm_dgram_control(so, cmd, data, ifp, td) struct atmcfgreq *acp = (struct atmcfgreq *)data; struct atm_pif *pip; - if (td && (suser(td) != 0)) - ATM_RETERR(EPERM); + if (td != NULL) { + err = priv_check(td, PRIV_NETATM_CFG); + if (err) + ATM_RETERR(err); + } switch (acp->acr_opcode) { @@ -214,8 +218,11 @@ atm_dgram_control(so, cmd, data, ifp, td) struct atmaddreq *aap = (struct atmaddreq *)data; Atm_endpoint *epp; - if (td && (suser(td) != 0)) - ATM_RETERR(EPERM); + if (td != NULL) { + err = priv_check(td, PRIV_NETATM_ADD); + if (err) + ATM_RETERR(err); + } switch (aap->aar_opcode) { @@ -264,8 +271,11 @@ atm_dgram_control(so, cmd, data, ifp, td) struct sigmgr *smp; Atm_endpoint *epp; - if (td && (suser(td) != 0)) - ATM_RETERR(EPERM); + if (td != NULL) { + err = priv_check(td, PRIV_NETATM_DEL); + if (err) + ATM_RETERR(err); + } switch (adp->adr_opcode) { @@ -317,8 +327,11 @@ atm_dgram_control(so, cmd, data, ifp, td) struct sigmgr *smp; struct ifnet *ifp2; - if (td && (suser(td) != 0)) - ATM_RETERR(EPERM); + if (td != NULL) { + err = priv_check(td, PRIV_NETATM_SET); + if (err) + ATM_RETERR(err); + } switch (asp->asr_opcode) { diff --git a/sys/netgraph/bluetooth/drivers/h4/ng_h4.c b/sys/netgraph/bluetooth/drivers/h4/ng_h4.c index 0aaf37f73015..cf26468ee0e5 100644 --- a/sys/netgraph/bluetooth/drivers/h4/ng_h4.c +++ b/sys/netgraph/bluetooth/drivers/h4/ng_h4.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -156,7 +157,7 @@ ng_h4_open(struct cdev *dev, struct tty *tp) int s, error; /* Super-user only */ - error = suser(curthread); /* XXX */ + error = priv_check(curthread, PRIV_NETGRAPH_TTY); /* XXX */ if (error != 0) return (error); diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c index 6513757181e1..fc951c4cd0b4 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -916,7 +917,7 @@ ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td) so->so_pcb = (caddr_t) pcb; pcb->so = so; - if (suser(td) == 0) + if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0) pcb->flags |= NG_BTSOCKET_HCI_RAW_PRIVILEGED; /* diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c index 1bac6d916d55..d3d14179a5ae 100644 --- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -620,7 +621,7 @@ ng_btsocket_l2cap_raw_attach(struct socket *so, int proto, struct thread *td) so->so_pcb = (caddr_t) pcb; pcb->so = so; - if (suser(td) == 0) + if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0) pcb->flags |= NG_BTSOCKET_L2CAP_RAW_PRIVILEGED; mtx_init(&pcb->pcb_mtx, "btsocks_l2cap_raw_pcb_mtx", NULL, MTX_DEF); diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c index 028999b8b52b..2a0327503378 100644 --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -167,9 +168,11 @@ static int ngc_attach(struct socket *so, int proto, struct thread *td) { struct ngpcb *const pcbp = sotongpcb(so); + int error; - if (suser(td)) - return (EPERM); + error = priv_check(td, PRIV_NETGRAPH_CONTROL); + if (error) + return (error); if (pcbp != NULL) return (EISCONN); return (ng_attach_cntl(so)); diff --git a/sys/netgraph/ng_tty.c b/sys/netgraph/ng_tty.c index 7b8eceb789e6..2e8d7aa6d72d 100644 --- a/sys/netgraph/ng_tty.c +++ b/sys/netgraph/ng_tty.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -189,7 +190,8 @@ ngt_open(struct cdev *dev, struct tty *tp) int error; /* Super-user only */ - if ((error = suser(td))) + error = priv_check(td, PRIV_NETGRAPH_TTY); + if (error) return (error); /* Initialize private struct */ diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 64e1ba1f4c41..4af8f06415c5 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -232,10 +233,25 @@ in_control(so, cmd, data, ifp, td) switch (cmd) { case SIOCALIFADDR: + if (td != NULL) { + error = priv_check(td, PRIV_NET_ADDIFADDR); + if (error) + return (error); + } + if (!ifp) + return EINVAL; + return in_lifaddr_ioctl(so, cmd, data, ifp, td); + case SIOCDLIFADDR: - if (td && (error = suser(td)) != 0) - return error; - /*fall through*/ + if (td != NULL) { + error = priv_check(td, PRIV_NET_DELIFADDR); + if (error) + return (error); + } + if (!ifp) + return EINVAL; + return in_lifaddr_ioctl(so, cmd, data, ifp, td); + case SIOCGLIFADDR: if (!ifp) return EINVAL; @@ -292,8 +308,11 @@ in_control(so, cmd, data, ifp, td) case SIOCSIFADDR: case SIOCSIFNETMASK: case SIOCSIFDSTADDR: - if (td && (error = suser(td)) != 0) - return error; + if (td != NULL) { + error = priv_check(td, PRIV_NET_ADDIFADDR); + if (error) + return (error); + } if (ifp == 0) return (EADDRNOTAVAIL); @@ -330,8 +349,11 @@ in_control(so, cmd, data, ifp, td) break; case SIOCSIFBRDADDR: - if (td && (error = suser(td)) != 0) - return error; + if (td != NULL) { + error = priv_check(td, PRIV_NET_ADDIFADDR); + if (error) + return (error); + } /* FALLTHROUGH */ case SIOCGIFADDR: diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 60e7bf09191f..9028712d12d9 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -331,7 +332,8 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, /* GROSS */ if (ntohs(lport) <= ipport_reservedhigh && ntohs(lport) >= ipport_reservedlow && - suser_cred(cred, SUSER_ALLOWJAIL)) + priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, + SUSER_ALLOWJAIL)) return (EACCES); if (jailed(cred)) prison = 1; @@ -400,7 +402,9 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, last = ipport_hilastauto; lastport = &pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { - if ((error = suser_cred(cred, SUSER_ALLOWJAIL)) != 0) + error = priv_check_cred(cred, + PRIV_NETINET_RESERVEDPORT, SUSER_ALLOWJAIL); + if (error) return error; first = ipport_lowfirstauto; /* 1023 */ last = ipport_lowlastauto; /* 600 */ diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index a9cc4995c171..1aa0e99f5cc4 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -1853,7 +1854,8 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) break; case SIOCSVH: - if ((error = suser(curthread)) != 0) + error = priv_check(curthread, PRIV_NETINET_CARP); + if (error) break; if ((error = copyin(ifr->ifr_data, &carpr, sizeof carpr))) break; @@ -1928,7 +1930,8 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) carpr.carpr_vhid = sc->sc_vhid; carpr.carpr_advbase = sc->sc_advbase; carpr.carpr_advskew = sc->sc_advskew; - if (suser(curthread) == 0) + error = priv_check(curthread, PRIV_NETINET_CARP); + if (error == 0) bcopy(sc->sc_key, carpr.carpr_key, sizeof(carpr.carpr_key)); error = copyout(&carpr, ifr->ifr_data, sizeof(carpr)); diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index d416b0e821c9..c9c469444a6d 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -420,8 +421,11 @@ div_attach(struct socket *so, int proto, struct thread *td) inp = sotoinpcb(so); KASSERT(inp == NULL, ("div_attach: inp != NULL")); - if (td && (error = suser(td)) != 0) - return error; + if (td != NULL) { + error = priv_check(td, PRIV_NETINET_DIVERT); + if (error) + return (error); + } error = soreserve(so, div_sendspace, div_recvspace); if (error) return error; diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 9fa652e3e68f..a475ee2b76f6 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -3980,7 +3981,7 @@ ipfw_ctl(struct sockopt *sopt) struct ip_fw *buf, *rule; u_int32_t rulenum[2]; - error = suser(sopt->sopt_td); + error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW); if (error) return (error); diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index a248b72bb830..6b00d8951728 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -576,7 +577,7 @@ X_mrt_ioctl(int cmd, caddr_t data) * Typically, only root can create the raw socket in order to execute * this ioctl method, however the request might be coming from a prison */ - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_MROUTE); if (error) return (error); switch (cmd) { diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 6e3833e9e9da..4a738a5219a6 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -987,8 +988,20 @@ ip_ctloutput(so, sopt) break; if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */ break; - priv = (sopt->sopt_td != NULL && - suser(sopt->sopt_td) != 0) ? 0 : 1; + if (sopt->sopt_td != NULL) { + /* + * XXXRW: Would be more desirable to do this + * one layer down so that we only exercise + * privilege if it is needed. + */ + error = priv_check(sopt->sopt_td, + PRIV_NETINET_IPSEC); + if (error) + priv = 0; + else + priv = 1; + } else + priv = 1; req = mtod(m, caddr_t); len = m->m_len; optname = sopt->sopt_name; diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 837933b1f632..e4d65c23be61 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -387,7 +388,11 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) case IP_FW_GET: case IP_FW_TABLE_GETSIZE: case IP_FW_TABLE_LIST: - error = suser(curthread); + /* + * XXXRW: Isn't this checked one layer down? Yes, it + * is. + */ + error = priv_check(curthread, PRIV_NETINET_IPFW); if (error != 0) return (error); if (ip_fw_ctl_ptr != NULL) @@ -397,7 +402,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) break; case IP_DUMMYNET_GET: - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_DUMMYNET); if (error != 0) return (error); if (ip_dn_ctl_ptr != NULL) @@ -418,7 +423,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) case MRT_API_CONFIG: case MRT_ADD_BW_UPCALL: case MRT_DEL_BW_UPCALL: - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_MROUTE); if (error != 0) return (error); error = ip_mrouter_get ? ip_mrouter_get(so, sopt) : @@ -452,7 +457,10 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) case IP_FW_TABLE_ADD: case IP_FW_TABLE_DEL: case IP_FW_TABLE_FLUSH: - error = suser(curthread); + /* + * XXXRW: Isn't this checked one layer down? + */ + error = priv_check(curthread, PRIV_NETINET_IPFW); if (error != 0) return (error); if (ip_fw_ctl_ptr != NULL) @@ -464,7 +472,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) case IP_DUMMYNET_CONFIGURE: case IP_DUMMYNET_DEL: case IP_DUMMYNET_FLUSH: - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_DUMMYNET); if (error != 0) return (error); if (ip_dn_ctl_ptr != NULL) @@ -474,14 +482,14 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) break ; case IP_RSVP_ON: - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_MROUTE); if (error != 0) return (error); error = ip_rsvp_init(so); break; case IP_RSVP_OFF: - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_MROUTE); if (error != 0) return (error); error = ip_rsvp_done(); @@ -489,7 +497,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) case IP_RSVP_VIF_ON: case IP_RSVP_VIF_OFF: - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_MROUTE); if (error != 0) return (error); error = ip_rsvp_vif ? @@ -508,7 +516,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt) case MRT_API_CONFIG: case MRT_ADD_BW_UPCALL: case MRT_DEL_BW_UPCALL: - error = suser(curthread); + error = priv_check(curthread, PRIV_NETINET_MROUTE); if (error != 0) return (error); error = ip_mrouter_set ? ip_mrouter_set(so, sopt) : @@ -598,9 +606,14 @@ rip_attach(struct socket *so, int proto, struct thread *td) inp = sotoinpcb(so); KASSERT(inp == NULL, ("rip_attach: inp != NULL")); + /* + * XXXRW: Centralize privilege decision in kern_jail.c. + */ if (jailed(td->td_ucred) && !jail_allow_raw_sockets) return (EPERM); - if ((error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL)) != 0) + error = priv_check_cred(td->td_ucred, PRIV_NETINET_RAW, + SUSER_ALLOWJAIL); + if (error) return error; if (proto >= IPPROTO_MAX || proto < 0) return EPROTONOSUPPORT; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 2b4f9bc78d7b..f211eb45674a 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -48,6 +48,7 @@ #ifdef INET6 #include #endif +#include #include #include #include @@ -1081,7 +1082,8 @@ tcp_getcred(SYSCTL_HANDLER_ARGS) struct inpcb *inp; int error; - error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED, + SUSER_ALLOWJAIL); if (error) return (error); error = SYSCTL_IN(req, addrs, sizeof(addrs)); @@ -1125,7 +1127,8 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS) struct inpcb *inp; int error, mapped = 0; - error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED, + SUSER_ALLOWJAIL); if (error) return (error); error = SYSCTL_IN(req, addrs, sizeof(addrs)); diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 2b4f9bc78d7b..f211eb45674a 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -48,6 +48,7 @@ #ifdef INET6 #include #endif +#include #include #include #include @@ -1081,7 +1082,8 @@ tcp_getcred(SYSCTL_HANDLER_ARGS) struct inpcb *inp; int error; - error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED, + SUSER_ALLOWJAIL); if (error) return (error); error = SYSCTL_IN(req, addrs, sizeof(addrs)); @@ -1125,7 +1127,8 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS) struct inpcb *inp; int error, mapped = 0; - error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED, + SUSER_ALLOWJAIL); if (error) return (error); error = SYSCTL_IN(req, addrs, sizeof(addrs)); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 28245875afcc..b0ba5377c975 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -687,7 +688,8 @@ udp_getcred(SYSCTL_HANDLER_ARGS) struct inpcb *inp; int error; - error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED, + SUSER_ALLOWJAIL); if (error) return (error); error = SYSCTL_IN(req, addrs, sizeof(addrs)); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 8177313287e9..52b57aaca4c1 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -325,12 +326,8 @@ in6_control(so, cmd, data, ifp, td) struct in6_ifreq *ifr = (struct in6_ifreq *)data; struct in6_ifaddr *ia = NULL; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; - int error, privileged; struct sockaddr_in6 *sa6; - - privileged = 0; - if (td == NULL || !suser(td)) - privileged++; + int error; switch (cmd) { case SIOCGETSGCNT_IN6: @@ -341,8 +338,11 @@ in6_control(so, cmd, data, ifp, td) switch(cmd) { case SIOCAADDRCTL_POLICY: case SIOCDADDRCTL_POLICY: - if (!privileged) - return (EPERM); + if (td != NULL) { + error = priv_check(td, PRIV_NETINET_ADDRCTRL6); + if (error) + return (error); + } return (in6_src_ioctl(cmd, data)); } @@ -355,8 +355,11 @@ in6_control(so, cmd, data, ifp, td) case SIOCSRTRFLUSH_IN6: case SIOCSDEFIFACE_IN6: case SIOCSIFINFO_FLAGS: - if (!privileged) - return (EPERM); + if (td != NULL) { + error = priv_check(td, PRIV_NETINET_ND6); + if (error) + return (error); + } /* FALLTHROUGH */ case OSIOCGIFINFO_IN6: case SIOCGIFINFO_IN6: @@ -383,8 +386,11 @@ in6_control(so, cmd, data, ifp, td) switch (cmd) { case SIOCSSCOPE6: - if (!privileged) - return (EPERM); + if (td != NULL) { + error = priv_check(td, PRIV_NETINET_SCOPE6); + if (error) + return (error); + } return (scope6_set(ifp, (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id)); case SIOCGSCOPE6: @@ -398,8 +404,15 @@ in6_control(so, cmd, data, ifp, td) switch (cmd) { case SIOCALIFADDR: case SIOCDLIFADDR: - if (!privileged) - return (EPERM); + /* + * XXXRW: Is this checked at another layer? What priv to use + * here? + */ + if (td != NULL) { + error = suser(td); + if (error) + return (error); + } /* FALLTHROUGH */ case SIOCGLIFADDR: return in6_lifaddr_ioctl(so, cmd, data, ifp, td); @@ -488,8 +501,16 @@ in6_control(so, cmd, data, ifp, td) if (ifra->ifra_addr.sin6_family != AF_INET6 || ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) return (EAFNOSUPPORT); - if (!privileged) - return (EPERM); + + /* + * XXXRW: Is this checked at another layer? What priv to use + * here? + */ + if (td != NULL) { + error = suser(td); + if (error) + return (error); + } break; @@ -508,8 +529,11 @@ in6_control(so, cmd, data, ifp, td) { struct in6_addrlifetime *lt; - if (!privileged) - return (EPERM); + if (td != NULL) { + error = priv_check(td, PRIV_NETINET_ALIFETIME6); + if (error) + return (error); + } if (ia == NULL) return (EADDRNOTAVAIL); /* sanity for overflow - beware unsigned */ diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 9305ed97cdd2..5e7da80d1b65 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -77,6 +77,7 @@ #include #include #include +#include #include #include @@ -190,8 +191,12 @@ in6_pcbbind(inp, nam, cred) /* GROSS */ if (ntohs(lport) <= ipport_reservedhigh && ntohs(lport) >= ipport_reservedlow && - suser_cred(cred, SUSER_ALLOWJAIL)) + priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, + SUSER_ALLOWJAIL)) return (EACCES); + /* + * XXXRW: What priv to use here? + */ if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) && suser_cred(so->so_cred, SUSER_ALLOWJAIL) != 0) { t = in6_pcblookup_local(pcbinfo, diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index 233d79b4a6f2..b9457dca57dc 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -772,7 +773,9 @@ in6_pcbsetport(laddr, inp, cred) last = ipport_hilastauto; lastport = &pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { - if ((error = suser_cred(cred, 0))) + error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, + SUSER_ALLOWJAIL); + if (error) return error; first = ipport_lowfirstauto; /* 1023 */ last = ipport_lowlastauto; /* 600 */ diff --git a/sys/netinet6/ipsec.c b/sys/netinet6/ipsec.c index 5ce3989ac8bd..a0b356b66cfb 100644 --- a/sys/netinet6/ipsec.c +++ b/sys/netinet6/ipsec.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -1221,8 +1222,14 @@ ipsec_init_pcbpolicy(so, pcb_sp) } bzero(new, sizeof(*new)); - if (so->so_cred != NULL && - suser_cred(so->so_cred, SUSER_ALLOWJAIL) == 0) + /* + * XXXRW: Can we avoid caching the privilege decision here, and + * instead cache the credential? + * + * XXXRW: Why is suser_allowjail set here? + */ + if (so->so_cred != NULL && priv_check_cred(so->so_cred, + PRIV_NETINET_IPSEC, 0) == 0) new->priv = 1; else new->priv = 0; diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index cec632c7cf9b..b91f9b698524 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -434,7 +435,8 @@ udp6_getcred(SYSCTL_HANDLER_ARGS) struct inpcb *inp; int error; - error = suser(req->td); + error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_GETCRED, + SUSER_ALLOWJAIL); if (error) return (error); diff --git a/sys/netipsec/ipsec_osdep.h b/sys/netipsec/ipsec_osdep.h index 34df84df09ca..e1a3926b067d 100644 --- a/sys/netipsec/ipsec_osdep.h +++ b/sys/netipsec/ipsec_osdep.h @@ -215,11 +215,13 @@ if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust) * NetBSD (1.6N) tests (so)->so_uid == 0). * This difference is wrapped inside the IPSEC_PRIVILEGED_SO() macro. * + * XXXRW: Why was this suser_allowjail? */ #ifdef __FreeBSD__ #define IPSEC_IS_PRIVILEGED_SO(_so) \ ((_so)->so_cred != NULL && \ - suser_cred((_so)->so_cred, SUSER_ALLOWJAIL) == 0) + priv_check_cred((_so)->so_cred, PRIV_NETINET_IPSEC, 0) \ + == 0) #endif /* __FreeBSD__ */ #ifdef __NetBSD__ diff --git a/sys/netipx/ipx_pcb.c b/sys/netipx/ipx_pcb.c index e2d9f5c9fb28..1ed22653485f 100644 --- a/sys/netipx/ipx_pcb.c +++ b/sys/netipx/ipx_pcb.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -107,11 +108,10 @@ ipx_pcbbind(ipxp, nam, td) lport = sipx->sipx_port; if (lport) { u_short aport = ntohs(lport); - int error; - if (aport < IPXPORT_RESERVED && - td != NULL && (error = suser(td)) != 0) - return (error); + if (aport < IPXPORT_RESERVED && td != NULL && + priv_check(td, PRIV_NETIPX_RESERVEDPORT)) + return (EACCES); if (ipx_pcblookup(&zeroipx_addr, lport, 0)) return (EADDRINUSE); } diff --git a/sys/netipx/ipx_usrreq.c b/sys/netipx/ipx_usrreq.c index 84de6294594d..058b0ad1ef50 100644 --- a/sys/netipx/ipx_usrreq.c +++ b/sys/netipx/ipx_usrreq.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -658,8 +659,13 @@ ripx_attach(so, proto, td) struct ipxpcb *ipxp = sotoipxpcb(so); KASSERT(ipxp == NULL, ("ripx_attach: ipxp != NULL")); - if (td != NULL && (error = suser(td)) != 0) - return (error); + + if (td != NULL) { + error = priv_check(td, PRIV_NETIPX_RAW); + if (error) + return (error); + } + /* * We hold the IPX list lock for the duration as address parameters * of the IPX pcb are changed. Since no one else holds a reference diff --git a/sys/netncp/ncp_conn.c b/sys/netncp/ncp_conn.c index 1455d6f092dd..370b004e8c2d 100644 --- a/sys/netncp/ncp_conn.c +++ b/sys/netncp/ncp_conn.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/netncp/ncp_mod.c b/sys/netncp/ncp_mod.c index b4f919df7684..955fa31e7303 100644 --- a/sys/netncp/ncp_mod.c +++ b/sys/netncp/ncp_mod.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/netncp/ncp_subr.h b/sys/netncp/ncp_subr.h index 83f1da2761a5..5c5775565d28 100644 --- a/sys/netncp/ncp_subr.h +++ b/sys/netncp/ncp_subr.h @@ -84,7 +84,7 @@ #define checkbad(fn) {error=(fn);if(error) goto bad;} -#define ncp_suser(cred) suser_cred(cred, 0) +#define ncp_suser(cred) priv_check_cred(cred, PRIV_NETNCP, 0) #define ncp_isowner(conn,cred) ((cred)->cr_uid == (conn)->nc_owner->cr_uid) diff --git a/sys/netsmb/smb_conn.c b/sys/netsmb/smb_conn.c index 038402adeac4..eee6b09e1db9 100644 --- a/sys/netsmb/smb_conn.c +++ b/sys/netsmb/smb_conn.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/netsmb/smb_subr.h b/sys/netsmb/smb_subr.h index 9b38bfa772aa..15e4a7a11474 100644 --- a/sys/netsmb/smb_subr.h +++ b/sys/netsmb/smb_subr.h @@ -68,7 +68,7 @@ void m_dumpm(struct mbuf *m); SIGISMEMBER(set, SIGHUP) || SIGISMEMBER(set, SIGKILL) || \ SIGISMEMBER(set, SIGQUIT)) -#define smb_suser(cred) suser_cred(cred, 0) +#define smb_suser(cred) priv_check_cred(cred, PRIV_NETSMB, 0) /* * Compatibility wrappers for simple locks diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c index b74325f792ef..4d6391ec9333 100644 --- a/sys/nfsserver/nfs_syscalls.c +++ b/sys/nfsserver/nfs_syscalls.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -142,7 +143,7 @@ nfssvc(struct thread *td, struct nfssvc_args *uap) if (error) return (error); #endif - error = suser(td); + error = priv_check(td, PRIV_NFSD); if (error) return (error); NET_LOCK_GIANT(); diff --git a/sys/pc98/cbus/fdc.c b/sys/pc98/cbus/fdc.c index b8c2827dae06..b653a5219e25 100644 --- a/sys/pc98/cbus/fdc.c +++ b/sys/pc98/cbus/fdc.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -2512,7 +2513,7 @@ fdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) #endif case FD_CLRERR: - if (suser(td) != 0) + if (priv_check(td, PRIV_DRIVER) != 0) return (EPERM); fd->fdc->fdc_errs = 0; return (0); @@ -2556,7 +2557,7 @@ fdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) case FD_STYPE: /* set drive type */ /* this is considered harmful; only allow for superuser */ - if (suser(td) != 0) + if (priv_check(td, PRIV_DRIVER) != 0) return (EPERM); *fd->ft = *(struct fd_type *)addr; break; @@ -2580,7 +2581,7 @@ fdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) #endif case FD_CLRERR: - if (suser(td) != 0) + if (priv_check(td, PRIV_DRIVER) != 0) return (EPERM); fd->fdc->fdc_errs = 0; break; diff --git a/sys/posix4/p1003_1b.c b/sys/posix4/p1003_1b.c index 189f5934421a..8ed0de53af10 100644 --- a/sys/posix4/p1003_1b.c +++ b/sys/posix4/p1003_1b.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -186,9 +187,10 @@ sched_setscheduler(struct thread *td, struct sched_setscheduler_args *uap) struct thread *targettd; struct proc *targetp; - /* Don't allow non root user to set a scheduler policy */ - if (suser(td) != 0) - return (EPERM); + /* Don't allow non root user to set a scheduler policy. */ + e = priv_check(td, PRIV_SCHED_SET); + if (e) + return (e); e = copyin(uap->param, &sched_param, sizeof(sched_param)); if (e) diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c index bb6f929889fe..c8121a0783c5 100644 --- a/sys/security/audit/audit.c +++ b/sys/security/audit/audit.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -509,7 +510,8 @@ audit_syscall_enter(unsigned short code, struct thread *td) * audit record is still required for this event by * re-calling au_preselect(). */ - if (audit_in_failure && suser(td) != 0) { + if (audit_in_failure && + priv_check(td, PRIV_AUDIT_FAILSTOP) != 0) { cv_wait(&audit_fail_cv, &audit_mtx); panic("audit_failing_stop: thread continued"); } diff --git a/sys/security/audit/audit_pipe.c b/sys/security/audit/audit_pipe.c index 6bea514d986b..3cc41efd1d96 100644 --- a/sys/security/audit/audit_pipe.c +++ b/sys/security/audit/audit_pipe.c @@ -626,9 +626,9 @@ audit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen, } /* - * Audit pipe open method. Explicit suser check isn't used as this allows - * file permissions on the special device to be used to grant audit review - * access. + * Audit pipe open method. Explicit privilege check isn't used as this + * allows file permissions on the special device to be used to grant audit + * review access. Those file permissions should be managed carefully. */ static int audit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td) diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c index fb5551156547..65772a824c33 100644 --- a/sys/security/audit/audit_syscalls.c +++ b/sys/security/audit/audit_syscalls.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ audit(struct thread *td, struct audit_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_SUBMIT); if (error) return (error); @@ -156,7 +157,7 @@ auditon(struct thread *td, struct auditon_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); AUDIT_ARG(cmd, uap->cmd); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_CONTROL); if (error) return (error); @@ -404,7 +405,7 @@ getauid(struct thread *td, struct getauid_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); @@ -428,7 +429,7 @@ setauid(struct thread *td, struct setauid_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_SETAUDIT); if (error) return (error); @@ -468,7 +469,7 @@ getaudit(struct thread *td, struct getaudit_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); @@ -489,7 +490,7 @@ setaudit(struct thread *td, struct setaudit_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_SETAUDIT); if (error) return (error); @@ -518,7 +519,7 @@ getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); return (ENOSYS); @@ -533,7 +534,7 @@ setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_SETAUDIT); if (error) return (error); return (ENOSYS); @@ -557,7 +558,7 @@ auditctl(struct thread *td, struct auditctl_args *uap) if (jailed(td->td_ucred)) return (ENOSYS); - error = suser(td); + error = priv_check(td, PRIV_AUDIT_CONTROL); if (error) return (error); diff --git a/sys/security/mac/mac_net.c b/sys/security/mac/mac_net.c index eb602da5c3e3..7279dc8ec857 100644 --- a/sys/security/mac/mac_net.c +++ b/sys/security/mac/mac_net.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -470,11 +471,11 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, } /* - * XXX: Note that this is a redundant privilege check, since - * policies impose this check themselves if required by the - * policy. Eventually, this should go away. + * XXX: Note that this is a redundant privilege check, since policies + * impose this check themselves if required by the policy. + * Eventually, this should go away. */ - error = suser_cred(cred, 0); + error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0); if (error) { mac_ifnet_label_free(intlabel); return (error); diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h index 7db278c31bba..f7c5670593b1 100644 --- a/sys/security/mac/mac_policy.h +++ b/sys/security/mac/mac_policy.h @@ -596,6 +596,8 @@ typedef int (*mpo_check_vnode_write_t)(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label); typedef void (*mpo_associate_nfsd_label_t)(struct ucred *cred); +typedef int (*mpo_priv_check_t)(struct ucred *cred, int priv); +typedef int (*mpo_priv_grant_t)(struct ucred *cred, int priv); struct mac_policy_ops { /* @@ -886,6 +888,8 @@ struct mac_policy_ops { mpo_check_vnode_write_t mpo_check_vnode_write; mpo_associate_nfsd_label_t mpo_associate_nfsd_label; mpo_create_mbuf_from_firewall_t mpo_create_mbuf_from_firewall; + mpo_priv_check_t mpo_priv_check; + mpo_priv_grant_t mpo_priv_grant; }; /* diff --git a/sys/security/mac/mac_system.c b/sys/security/mac/mac_system.c index eef66e6ce4a8..79108a3d1055 100644 --- a/sys/security/mac/mac_system.c +++ b/sys/security/mac/mac_system.c @@ -60,6 +60,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW, &mac_enforce_system, 0, "Enforce MAC policy on system operations"); TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system); +/* + * XXXRW: Some of these checks now duplicate privilege checks. However, + * others provide additional security context that may be useful to policies. + * We need to review these and remove ones that are pure duplicates. + */ + int mac_check_kenv_dump(struct ucred *cred) { diff --git a/sys/security/mac_bsdextended/mac_bsdextended.c b/sys/security/mac_bsdextended/mac_bsdextended.c index 7dec0d16d3c9..c32c5146c342 100644 --- a/sys/security/mac_bsdextended/mac_bsdextended.c +++ b/sys/security/mac_bsdextended/mac_bsdextended.c @@ -456,6 +456,9 @@ mac_bsdextended_check(struct ucred *cred, struct vnode *vp, struct vattr *vap, { int error, i; + /* + * XXXRW: More specific privilege selection needed? + */ if (suser_cred(cred, 0) == 0) return (0); diff --git a/sys/security/mac_lomac/mac_lomac.c b/sys/security/mac_lomac/mac_lomac.c index 07484d15ec84..7ca6e777b41a 100644 --- a/sys/security/mac_lomac/mac_lomac.c +++ b/sys/security/mac_lomac/mac_lomac.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -1697,8 +1698,10 @@ mac_lomac_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, * Rely on the traditional superuser status for the LOMAC * interface relabel requirements. XXXMAC: This will go * away. + * + * XXXRW: This is also redundant to a higher layer check. */ - error = suser_cred(cred, 0); + error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0); if (error) return (EPERM); diff --git a/sys/security/mac_partition/mac_partition.c b/sys/security/mac_partition/mac_partition.c index fe3d8e81677d..5ce8d20d1821 100644 --- a/sys/security/mac_partition/mac_partition.c +++ b/sys/security/mac_partition/mac_partition.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -191,7 +192,7 @@ mac_partition_check_cred_relabel(struct ucred *cred, struct label *newlabel) * in a partition in the first place, but this didn't * interact well with sendmail. */ - error = suser_cred(cred, 0); + error = priv_check_cred(cred, PRIV_MAC_PARTITION, 0); } return (error); diff --git a/sys/security/mac_portacl/mac_portacl.c b/sys/security/mac_portacl/mac_portacl.c index 80cd0539c90d..5218531cbed0 100644 --- a/sys/security/mac_portacl/mac_portacl.c +++ b/sys/security/mac_portacl/mac_portacl.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -427,7 +428,8 @@ rules_check(struct ucred *cred, int family, int type, u_int16_t port) mtx_unlock(&rule_mtx); if (error != 0 && mac_portacl_suser_exempt != 0) - error = suser_cred(cred, SUSER_ALLOWJAIL); + error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, + SUSER_ALLOWJAIL); return (error); } diff --git a/sys/security/mac_seeotheruids/mac_seeotheruids.c b/sys/security/mac_seeotheruids/mac_seeotheruids.c index b15dc00b64da..f8c02d2611f0 100644 --- a/sys/security/mac_seeotheruids/mac_seeotheruids.c +++ b/sys/security/mac_seeotheruids/mac_seeotheruids.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -126,7 +127,7 @@ mac_seeotheruids_check(struct ucred *u1, struct ucred *u2) return (0); if (suser_privileged) { - if (suser_cred(u1, 0) == 0) + if (priv_check_cred(u1, PRIV_SEEOTHERUIDS, 0) == 0) return (0); } diff --git a/sys/sun4v/sun4v/hvcons.c b/sys/sun4v/sun4v/hvcons.c index 2740b84b324e..e0e84686abcb 100644 --- a/sys/sun4v/sun4v/hvcons.c +++ b/sys/sun4v/sun4v/hvcons.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -134,7 +135,8 @@ hvcn_open(struct cdev *dev, int flag, int mode, struct thread *td) ttyconsolemode(tp, 0); setuptimeout = 1; - } else if ((tp->t_state & TS_XCLUDE) && suser(td)) { + } else if ((tp->t_state & TS_XCLUDE) && priv_check(td, + PRIV_TTY_EXCLUSIVE)) { return (EBUSY); } diff --git a/sys/sys/mac_policy.h b/sys/sys/mac_policy.h index 7db278c31bba..f7c5670593b1 100644 --- a/sys/sys/mac_policy.h +++ b/sys/sys/mac_policy.h @@ -596,6 +596,8 @@ typedef int (*mpo_check_vnode_write_t)(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label); typedef void (*mpo_associate_nfsd_label_t)(struct ucred *cred); +typedef int (*mpo_priv_check_t)(struct ucred *cred, int priv); +typedef int (*mpo_priv_grant_t)(struct ucred *cred, int priv); struct mac_policy_ops { /* @@ -886,6 +888,8 @@ struct mac_policy_ops { mpo_check_vnode_write_t mpo_check_vnode_write; mpo_associate_nfsd_label_t mpo_associate_nfsd_label; mpo_create_mbuf_from_firewall_t mpo_create_mbuf_from_firewall; + mpo_priv_check_t mpo_priv_check; + mpo_priv_grant_t mpo_priv_grant; }; /* diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index bc92afe4dcb2..b7e7fdaa9fd3 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -171,7 +172,7 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) #endif if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) goto nospace; - if (suser_cred(cred, SUSER_ALLOWJAIL) && + if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, SUSER_ALLOWJAIL) && freespace(fs, fs->fs_minfree) - numfrags(fs, size) < 0) goto nospace; if (bpref >= fs->fs_size) @@ -259,7 +260,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, cred, bpp) #endif /* DIAGNOSTIC */ reclaimed = 0; retry: - if (suser_cred(cred, SUSER_ALLOWJAIL) && + if (priv_check_cred(cred, PRIV_VFS_BLOCKRESERVE, SUSER_ALLOWJAIL) && freespace(fs, fs->fs_minfree) - numfrags(fs, nsize - osize) < 0) { goto nospace; } diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index b9ccf3a205a7..a2591bc88d41 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -257,15 +258,16 @@ ffs_mount(struct mount *mp, struct thread *td) * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ - if (suser(td)) { - vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); - if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, - td->td_ucred, td)) != 0) { - VOP_UNLOCK(devvp, 0, td); - return (error); - } + vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); + error = VOP_ACCESS(devvp, VREAD | VWRITE, + td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { VOP_UNLOCK(devvp, 0, td); + return (error); } + VOP_UNLOCK(devvp, 0, td); fs->fs_flags &= ~FS_UNCLEAN; if (fs->fs_clean == 0) { fs->fs_flags |= FS_UNCLEAN; @@ -364,14 +366,15 @@ ffs_mount(struct mount *mp, struct thread *td) * If mount by non-root, then verify that user has necessary * permissions on the device. */ - if (suser(td)) { - accessmode = VREAD; - if ((mp->mnt_flag & MNT_RDONLY) == 0) - accessmode |= VWRITE; - if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td))!= 0){ - vput(devvp); - return (error); - } + accessmode = VREAD; + if ((mp->mnt_flag & MNT_RDONLY) == 0) + accessmode |= VWRITE; + error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); + if (error) + error = priv_check(td, PRIV_VFS_MOUNT_PERM); + if (error) { + vput(devvp); + return (error); } if (mp->mnt_flag & MNT_UPDATE) { diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 4d8d9ef009ce..5ffedd75c7ee 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -781,7 +782,8 @@ ffs_write(ap) * tampering. */ if (resid > uio->uio_resid && ap->a_cred && - suser_cred(ap->a_cred, SUSER_ALLOWJAIL)) { + priv_check_cred(ap->a_cred, PRIV_VFS_CLEARSUGID, + SUSER_ALLOWJAIL)) { ip->i_mode &= ~(ISUID | ISGID); DIP_SET(ip, i_mode, ip->i_mode); } @@ -1107,7 +1109,7 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred) * tampering. */ if (resid > uio->uio_resid && ucred && - suser_cred(ucred, SUSER_ALLOWJAIL)) { + priv_check_cred(ucred, PRIV_VFS_CLEARSUGID, SUSER_ALLOWJAIL)) { ip->i_mode &= ~(ISUID | ISGID); dp->di_mode = ip->i_mode; } diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c index e6153f3efda9..f49f9883707a 100644 --- a/sys/ufs/ufs/ufs_extattr.c +++ b/sys/ufs/ufs/ufs_extattr.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -699,7 +700,8 @@ ufs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp, * Processes with privilege, but in jail, are not allowed to * configure extended attributes. */ - if ((error = suser(td))) { + error = priv_check(td, PRIV_UFS_EXTATTRCTL); + if (error) { if (filename_vp != NULL) VOP_UNLOCK(filename_vp, 0, td); return (error); diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 81a1d0d822e4..c4a93cdbfb7f 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -165,7 +166,8 @@ chkdq(ip, change, cred, flags) } return (0); } - if ((flags & FORCE) == 0 && suser_cred(cred, 0)) { + if ((flags & FORCE) == 0 && priv_check_cred(cred, + PRIV_UFS_EXCEEDQUOTA, 0)) { for (i = 0; i < MAXQUOTAS; i++) { if ((dq = ip->i_dquot[i]) == NODQUOT) continue; @@ -288,7 +290,8 @@ chkiq(ip, change, cred, flags) } return (0); } - if ((flags & FORCE) == 0 && suser_cred(cred, 0)) { + if ((flags & FORCE) == 0 && priv_check_cred(cred, + PRIV_UFS_EXCEEDQUOTA, 0)) { for (i = 0; i < MAXQUOTAS; i++) { if ((dq = ip->i_dquot[i]) == NODQUOT) continue; @@ -423,7 +426,11 @@ quotaon(td, mp, type, fname) int error, flags; struct nameidata nd; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + /* + * XXXRW: Can this be right? Jail is allowed to do this? + */ + error = priv_check_cred(td->td_ucred, PRIV_UFS_QUOTAON, + SUSER_ALLOWJAIL); if (error) return (error); @@ -517,7 +524,11 @@ quotaoff(td, mp, type) struct inode *ip; int error; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + /* + * XXXRW: This also seems wrong to allow in a jail? + */ + error = priv_check_cred(td->td_ucred, PRIV_UFS_QUOTAOFF, + SUSER_ALLOWJAIL); if (error) return (error); @@ -589,15 +600,18 @@ getquota(td, mp, id, type, addr) switch (type) { case USRQUOTA: if ((td->td_ucred->cr_uid != id) && !unprivileged_get_quota) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, + PRIV_UFS_GETQUOTA, SUSER_ALLOWJAIL); if (error) return (error); } break; case GRPQUOTA: - if (!groupmember(id, td->td_ucred) && !unprivileged_get_quota) { - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + if (!groupmember(id, td->td_ucred) && + !unprivileged_get_quota) { + error = priv_check_cred(td->td_ucred, + PRIV_UFS_GETQUOTA, SUSER_ALLOWJAIL); if (error) return (error); } @@ -632,7 +646,8 @@ setquota(td, mp, id, type, addr) struct dqblk newlim; int error; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_UFS_SETQUOTA, + SUSER_ALLOWJAIL); if (error) return (error); @@ -698,7 +713,8 @@ setuse(td, mp, id, type, addr) struct dqblk usage; int error; - error = suser_cred(td->td_ucred, SUSER_ALLOWJAIL); + error = priv_check_cred(td->td_ucred, PRIV_UFS_SETUSE, + SUSER_ALLOWJAIL); if (error) return (error); diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 4f964491cdf5..4fcadd0201fb 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -493,8 +494,11 @@ ufs_setattr(ap) * processes if the security.jail.chflags_allowed sysctl is * is non-zero; otherwise, they behave like unprivileged * processes. + * + * XXXRW: Move implementation of jail_chflags_allowed to + * kern_jail.c. */ - if (!suser_cred(cred, + if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, jail_chflags_allowed ? SUSER_ALLOWJAIL : 0)) { if (ip->i_flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { @@ -585,10 +589,19 @@ ufs_setattr(ap) * super-user. * If times is non-NULL, ... The caller must be the owner of * the file or be the super-user. + * + * Possibly for historical reasons, try to use VADMIN in + * preference to VADMIN for a NULL timestamp. This means we + * will return EACCES in preference to EPERM if neither + * check succeeds. */ - if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(vp, VWRITE, cred, td)))) + if (vap->va_vaflags & VA_UTIMES_NULL) { + error = VOP_ACCESS(vp, VADMIN, cred, td); + if (error) + error = VOP_ACCESS(vp, VWRITE, cred, td); + } else + error = VOP_ACCESS(vp, VADMIN, cred, td); + if (error) return (error); if (vap->va_atime.tv_sec != VNOVAL) ip->i_flag |= IN_ACCESS; @@ -654,11 +667,13 @@ ufs_chmod(vp, mode, cred, td) * jail(8). */ if (vp->v_type != VDIR && (mode & S_ISTXT)) { - if (suser_cred(cred, SUSER_ALLOWJAIL)) + if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, + SUSER_ALLOWJAIL)) return (EFTYPE); } if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) { - error = suser_cred(cred, SUSER_ALLOWJAIL); + error = priv_check_cred(cred, PRIV_VFS_SETGID, + SUSER_ALLOWJAIL); if (error) return (error); } @@ -695,19 +710,19 @@ ufs_chown(vp, uid, gid, cred, td) if (gid == (gid_t)VNOVAL) gid = ip->i_gid; /* - * To modify the ownership of a file, must possess VADMIN - * for that file. + * To modify the ownership of a file, must possess VADMIN for that + * file. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) return (error); /* - * To change the owner of a file, or change the group of a file - * to a group of which we are not a member, the caller must - * have privilege. + * To change the owner of a file, or change the group of a file to a + * group of which we are not a member, the caller must have + * privilege. */ if ((uid != ip->i_uid || (gid != ip->i_gid && !groupmember(gid, cred))) && - (error = suser_cred(cred, SUSER_ALLOWJAIL))) + (error = priv_check_cred(cred, PRIV_VFS_CHOWN, SUSER_ALLOWJAIL))) return (error); ogid = ip->i_gid; ouid = ip->i_uid; @@ -778,7 +793,8 @@ ufs_chown(vp, uid, gid, cred, td) panic("ufs_chown: lost quota"); #endif /* QUOTA */ ip->i_flag |= IN_CHANGE; - if (suser_cred(cred, SUSER_ALLOWJAIL) && (ouid != uid || ogid != gid)) { + if (priv_check_cred(cred, PRIV_VFS_CLEARSUGID, SUSER_ALLOWJAIL) && + (ouid != uid || ogid != gid)) { ip->i_mode &= ~(ISUID | ISGID); DIP_SET(ip, i_mode, ip->i_mode); } @@ -2357,7 +2373,8 @@ ufs_makeinode(mode, dvp, vpp, cnp) if (DOINGSOFTDEP(tvp)) softdep_change_linkcnt(ip); if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && - suser_cred(cnp->cn_cred, SUSER_ALLOWJAIL)) { + priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID, + SUSER_ALLOWJAIL)) { ip->i_mode &= ~ISGID; DIP_SET(ip, i_mode, ip->i_mode); } diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 85ea18e59ebc..7b7e5d18e16d 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1966,11 +1967,11 @@ swapon(struct thread *td, struct swapon_args *uap) struct nameidata nd; int error; - mtx_lock(&Giant); - error = suser(td); + error = priv_check(td, PRIV_SWAPON); if (error) - goto done2; + return (error); + mtx_lock(&Giant); while (swdev_syscall_active) tsleep(&swdev_syscall_active, PUSER - 1, "swpon", 0); swdev_syscall_active = 1; @@ -2009,7 +2010,6 @@ swapon(struct thread *td, struct swapon_args *uap) done: swdev_syscall_active = 0; wakeup_one(&swdev_syscall_active); -done2: mtx_unlock(&Giant); return (error); } @@ -2105,7 +2105,7 @@ swapoff(struct thread *td, struct swapoff_args *uap) struct swdevt *sp; int error; - error = suser(td); + error = priv_check(td, PRIV_SWAPOFF); if (error) return (error); diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 933080e59ae4..ff1ba18bea8f 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -684,7 +685,7 @@ madvise(td, uap) * "immortal." */ if (uap->behav == MADV_PROTECT) { - error = suser(td); + error = priv_check(td, PRIV_VM_MADV_PROTECT); if (error == 0) { p = td->td_proc; PROC_LOCK(p); @@ -951,7 +952,7 @@ mlock(td, uap) vm_size_t npages, size; int error; - error = suser(td); + error = priv_check(td, PRIV_VM_MLOCK); if (error) return (error); addr = (vm_offset_t)uap->addr; @@ -1016,7 +1017,7 @@ mlockall(td, uap) } PROC_UNLOCK(td->td_proc); #else - error = suser(td); + error = priv_check(td, PRIV_VM_MLOCK); if (error) return (error); #endif @@ -1061,7 +1062,7 @@ munlockall(td, uap) int error; map = &td->td_proc->p_vmspace->vm_map; - error = suser(td); + error = priv_check(td, PRIV_VM_MUNLOCK); if (error) return (error); @@ -1095,7 +1096,7 @@ munlock(td, uap) vm_size_t size; int error; - error = suser(td); + error = priv_check(td, PRIV_VM_MUNLOCK); if (error) return (error); addr = (vm_offset_t)uap->addr;