--- nfs_serv.c.orig Fri Sep 22 13:50:56 2006 +++ nfs_serv.c Mon Mar 17 21:13:38 2008 @@ -127,10 +127,39 @@ SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server"); static int nfs_suiddir_override_minuid = 0; static int nfs_suiddir_override_maxuid = 0; +static uint32_t nfs_suiddir_force_mode_file = 0; +static uint32_t nfs_suiddir_force_mode_dir = 0; +static uint32_t nfs_suiddir_force_umask = 0; +static int nfs_suiddir_force_minuid = 1; +static int nfs_suiddir_force_maxuid = 0; SYSCTL_UINT(_vfs_nfsrv, OID_AUTO, nfs_suiddir_override_minuid, CTLFLAG_RW, &nfs_suiddir_override_minuid, 0, ""); SYSCTL_UINT(_vfs_nfsrv, OID_AUTO, nfs_suiddir_override_maxuid, CTLFLAG_RW, &nfs_suiddir_override_maxuid, 0, ""); +SYSCTL_UINT(_vfs_nfsrv, OID_AUTO, nfs_suiddir_force_mode_file, CTLFLAG_RW, + &nfs_suiddir_force_mode_file, 0, ""); +SYSCTL_UINT(_vfs_nfsrv, OID_AUTO, nfs_suiddir_force_mode_dir, CTLFLAG_RW, + &nfs_suiddir_force_mode_dir, 0, ""); +SYSCTL_UINT(_vfs_nfsrv, OID_AUTO, nfs_suiddir_force_umask, CTLFLAG_RW, + &nfs_suiddir_force_umask, 0, ""); +SYSCTL_UINT(_vfs_nfsrv, OID_AUTO, nfs_suiddir_force_minuid, CTLFLAG_RW, + &nfs_suiddir_force_minuid, 0, ""); +SYSCTL_UINT(_vfs_nfsrv, OID_AUTO, nfs_suiddir_force_maxuid, CTLFLAG_RW, + &nfs_suiddir_force_maxuid, 0, ""); + +#define HANDLE_SUID_FORCE_FLAGS(flg,tpe) \ + if (flg & MNT_SUIDDIR && cred->cr_uid >= nfs_suiddir_force_minuid && \ + cred->cr_uid <= nfs_suiddir_force_maxuid && \ + (tpe == VREG || tpe == VDIR)) { \ + if (vap->va_mode == (mode_t)VNOVAL) \ + vap->va_mode = 0; \ + vap->va_mode &= ~nfs_suiddir_force_umask; \ + if (tpe == VREG) \ + vap->va_mode |= nfs_suiddir_force_mode_file; \ + else if (tpe == VDIR) \ + vap->va_mode |= nfs_suiddir_force_mode_dir; \ + } \ + static int nfs_async; static int nfs_commit_blks; @@ -444,6 +473,7 @@ } NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ + HANDLE_SUID_FORCE_FLAGS(vp->v_mount->mnt_flag,vp->v_type); error = VOP_SETATTR(vp, vap, cred, td); postat_ret = VOP_GETATTR(vp, vap, cred, td); mtx_unlock(&Giant); /* VFS */ @@ -1746,6 +1776,7 @@ u_quad_t tempsize; u_char cverf[NFSX_V3CREATEVERF]; struct mount *mp = NULL; + int mnt_flag; NFSD_LOCK_ASSERT(); @@ -1763,6 +1794,7 @@ } NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ + mnt_flag = mp->mnt_flag; (void) vn_start_write(NULL, &mp, V_WAIT); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -1854,6 +1886,7 @@ break; }; } + HANDLE_SUID_FORCE_FLAGS(mnt_flag, vap->va_type); /* * Iff doesn't exist, create it @@ -1878,6 +1911,7 @@ VATTR_NULL(vap); bcopy(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF); + HANDLE_SUID_FORCE_FLAGS(mnt_flag, vap->va_type); error = VOP_SETATTR(nd.ni_vp, vap, cred, td); } @@ -2055,6 +2089,7 @@ fhandle_t *fhp; struct mount *mp = NULL; int v3 = (nfsd->nd_flag & ND_NFSV3); + int mnt_flag; NFSD_LOCK_ASSERT(); @@ -2071,6 +2106,7 @@ } NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ + mnt_flag = mp->mnt_flag; (void) vn_start_write(NULL, &mp, V_WAIT); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -2125,6 +2161,7 @@ vap->va_mode = 0; NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ + HANDLE_SUID_FORCE_FLAGS(mnt_flag, vtyp); if (vtyp == VSOCK) { vrele(nd.ni_startdir); nd.ni_startdir = NULL; @@ -2263,6 +2300,7 @@ nfsfh_t nfh; fhandle_t *fhp; struct mount *mp = NULL; + int mnt_flag; NFSD_LOCK_ASSERT(); @@ -2277,6 +2315,7 @@ } NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ + mnt_flag = mp->mnt_flag; (void) vn_start_write(NULL, &mp, V_WAIT); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -2802,6 +2841,7 @@ nfsfh_t nfh; fhandle_t *fhp; struct mount *mp = NULL; + int mnt_flag; NFSD_LOCK_ASSERT(); @@ -2818,6 +2858,7 @@ } NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ + mnt_flag = mp->mnt_flag; (void) vn_start_write(NULL, &mp, V_WAIT); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -2867,6 +2908,7 @@ */ if (vap->va_mode == (mode_t)VNOVAL) vap->va_mode = 0; + HANDLE_SUID_FORCE_FLAGS(mnt_flag, vap->va_type); error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp); if (error) NDFREE(&nd, NDF_ONLY_PNBUF); @@ -2996,6 +3038,7 @@ nfsfh_t nfh; fhandle_t *fhp; struct mount *mp = NULL; + int mnt_flag; NFSD_LOCK_ASSERT(); @@ -3012,6 +3055,7 @@ } NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ + mnt_flag = mp->mnt_flag; (void) vn_start_write(NULL, &mp, V_WAIT); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -3066,6 +3110,7 @@ */ if (vap->va_mode == (mode_t)VNOVAL) vap->va_mode = 0; + HANDLE_SUID_FORCE_FLAGS(mnt_flag, vap->va_type); error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap); NDFREE(&nd, NDF_ONLY_PNBUF); vpexcl = 1;