int secpolicy_setid_setsticky_clear(struct vnode *vp, struct vattr *vap, const struct vattr *ovap, kauth_cred_t cred) { /* * Privileged processes may set the sticky bit on non-directories, * as well as set the setgid bit on a file with a group that the process * is not a member of. Both of these are allowed in jail(8). */ if (vp->v_type != VDIR && (vap->va_mode & S_ISTXT)) { if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL)) return (EFTYPE); } /* * Check for privilege if attempting to set the * group-id bit. */ if ((vap->va_mode & S_ISGID) != 0) return (secpolicy_vnode_setids_setgids(cred, ovap->va_gid)); return (0); }
static int xdirmakexnode( struct xmemnode *dir, struct xmount *xm, struct vattr *va, enum de_op op, struct xmemnode **newnode, struct cred *cred) { struct xmemnode *xp; enum vtype type; ASSERT(va != NULL); ASSERT(op == DE_CREATE || op == DE_MKDIR); if (((va->va_mask & AT_ATIME) && TIMESPEC_OVERFLOW(&va->va_atime)) || ((va->va_mask & AT_MTIME) && TIMESPEC_OVERFLOW(&va->va_mtime))) return (EOVERFLOW); type = va->va_type; xp = xmem_memalloc(sizeof (struct xmemnode), 1); xp->xn_vnode = vn_alloc(KM_SLEEP); xmemnode_init(xm, xp, va, cred); if (type == VBLK || type == VCHR) { xp->xn_vnode->v_rdev = xp->xn_rdev = va->va_rdev; } else { xp->xn_vnode->v_rdev = xp->xn_rdev = NODEV; } xp->xn_vnode->v_type = type; xp->xn_uid = crgetuid(cred); /* * To determine the group-id of the created file: * 1) If the gid is set in the attribute list (non-Sun & pre-4.0 * clients are not likely to set the gid), then use it if * the process is privileged, belongs to the target group, * or the group is the same as the parent directory. * 2) If the filesystem was not mounted with the Old-BSD-compatible * GRPID option, and the directory's set-gid bit is clear, * then use the process's gid. * 3) Otherwise, set the group-id to the gid of the parent directory. */ if ((va->va_mask & AT_GID) && ((va->va_gid == dir->xn_gid) || groupmember(va->va_gid, cred) || secpolicy_vnode_create_gid(cred) == 0)) { xp->xn_gid = va->va_gid; } else { if (dir->xn_mode & VSGID) xp->xn_gid = dir->xn_gid; else xp->xn_gid = crgetgid(cred); } /* * If we're creating a directory, and the parent directory has the * set-GID bit set, set it on the new directory. * Otherwise, if the user is neither privileged nor a member of the * file's new group, clear the file's set-GID bit. */ if (dir->xn_mode & VSGID && type == VDIR) xp->xn_mode |= VSGID; else if ((xp->xn_mode & VSGID) && secpolicy_vnode_setids_setgids(cred, xp->xn_gid) != 0) xp->xn_mode &= ~VSGID; if (va->va_mask & AT_ATIME) xp->xn_atime = va->va_atime; if (va->va_mask & AT_MTIME) xp->xn_mtime = va->va_mtime; if (op == DE_MKDIR) xdirinit(dir, xp); *newnode = xp; return (0); }