Index: contrib/amd/include/am_defs.h =================================================================== RCS file: /home/ncvs/src/contrib/amd/include/am_defs.h,v retrieving revision 1.8 diff -u -r1.8 am_defs.h --- contrib/amd/include/am_defs.h 1999/11/05 11:58:03 1.8 +++ contrib/amd/include/am_defs.h 2000/04/12 17:04:20 @@ -445,6 +445,7 @@ * Actions to take if exists. */ #ifdef HAVE_SYS_UCRED_H +#include # include #endif /* HAVE_SYS_UCRED_H */ Index: etc/rc =================================================================== RCS file: /home/ncvs/src/etc/rc,v retrieving revision 1.244 diff -u -r1.244 rc --- etc/rc 2000/12/17 08:24:49 1.244 +++ etc/rc 2001/01/05 16:50:06 @@ -204,6 +204,19 @@ sh ${diskless_mount} fi +case ${extattr_root} in +[Nn][Oo] | '') + ;; +*) + echo Starting extended attributes on root file system. + /usr/sbin/extattrctl start / + cd /.attribute && for file in * + do + /usr/sbin/extattrctl enable / $file /.attribute/$file + done + ;; +esac + # Second attempt at reseeding, if needed. # case ${entropy_reseeded} in Index: etc/defaults/rc.conf =================================================================== RCS file: /home/ncvs/src/etc/defaults/rc.conf,v retrieving revision 1.83 diff -u -r1.83 rc.conf --- etc/defaults/rc.conf 2000/10/29 19:59:04 1.83 +++ etc/defaults/rc.conf 2000/11/07 02:25:17 @@ -322,6 +322,7 @@ update_motd="YES" # update version info in /etc/motd (or NO) start_vinum="" # set to YES to start vinum unaligned_print="YES" # print unaligned access warnings on the alpha (or NO). +extattr_root="NO" # Auto-start extended attributes on / at boot entropy_file="/entropy" # Set to NO to disable caching entropy through reboots. # /var/db/entropy is preferred if / is not available. Index: lib/libc/gen/getmntinfo.c =================================================================== RCS file: /home/ncvs/src/lib/libc/gen/getmntinfo.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 getmntinfo.c --- lib/libc/gen/getmntinfo.c 1994/05/27 04:56:40 1.1.1.1 +++ lib/libc/gen/getmntinfo.c 2000/01/09 07:19:44 @@ -36,6 +36,7 @@ #endif /* LIBC_SCCS and not lint */ #include +#include #include #include #include Index: lib/libposix1e/Makefile =================================================================== RCS file: /home/ncvs/src/lib/libposix1e/Makefile,v retrieving revision 1.9 diff -u -r1.9 Makefile --- lib/libposix1e/Makefile 2000/10/13 18:24:58 1.9 +++ lib/libposix1e/Makefile 2000/10/23 06:45:16 @@ -1,5 +1,6 @@ # $FreeBSD: src/lib/libposix1e/Makefile,v 1.9 2000/10/13 18:24:58 rwatson Exp $ +CFLAGS+=-g -Wall MAINTAINER= rwatson@FreeBSD.org LIB= posix1e SHLIB_MAJOR= 2 Index: lib/libposix1e/cap.3 =================================================================== RCS file: /home/ncvs/src/lib/libposix1e/cap.3,v retrieving revision 1.6 diff -u -r1.6 cap.3 --- lib/libposix1e/cap.3 2000/12/14 11:45:20 1.6 +++ lib/libposix1e/cap.3 2001/01/05 16:53:01 @@ -93,7 +93,7 @@ (more) readable by humans. .El .Pp -A number of capabilities exist, each mapping to the ability to violate +A number of capabilities exist, each mapping to the ability to override a particular aspect of the system policy. Each capability in a capability set has three flags, indicating the status of the capability with respect to the file or process it is Index: lib/libposix1e/cap_get_proc.3 =================================================================== RCS file: /home/ncvs/src/lib/libposix1e/cap_get_proc.3,v retrieving revision 1.4 diff -u -r1.4 cap_get_proc.3 --- lib/libposix1e/cap_get_proc.3 2000/12/14 11:45:20 1.4 +++ lib/libposix1e/cap_get_proc.3 2001/01/05 16:53:02 @@ -95,7 +95,3 @@ and development continues. .Sh AUTHORS .An Robert N M Watson -.Sh BUGS -While libposix1e is fully implemented, supporting kernel code is not -yet available in the base distribution. -It is slated for inclusion prior to 5.0-RELEASE. Index: lib/libposix1e/cap_set_proc.3 =================================================================== RCS file: /home/ncvs/src/lib/libposix1e/cap_set_proc.3,v retrieving revision 1.4 diff -u -r1.4 cap_set_proc.3 --- lib/libposix1e/cap_set_proc.3 2000/12/14 11:45:20 1.4 +++ lib/libposix1e/cap_set_proc.3 2001/01/05 16:53:02 @@ -102,7 +102,3 @@ and development continues. .Sh AUTHORS .An Robert N M Watson -.Sh BUGS -While libposix1e is fully implemented, supporting kernel code is not -yet available in the base distribution. -It is slated for inclusion prior to 5.0-RELEASE. Index: sys/coda/coda_namecache.c =================================================================== RCS file: /home/ncvs/src/sys/coda/coda_namecache.c,v retrieving revision 1.10 diff -u -r1.10 coda_namecache.c --- sys/coda/coda_namecache.c 1999/08/28 00:40:53 1.10 +++ sys/coda/coda_namecache.c 2000/04/12 04:43:28 @@ -79,6 +79,7 @@ #include #include #include +#include #include #include Index: sys/fs/hpfs/hpfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/hpfs/hpfs_vnops.c,v retrieving revision 1.8 diff -u -r1.8 hpfs_vnops.c --- sys/fs/hpfs/hpfs_vnops.c 2000/11/01 17:57:22 1.8 +++ sys/fs/hpfs/hpfs_vnops.c 2000/11/07 02:41:02 @@ -579,7 +579,7 @@ if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != hp->h_uid && - (error = suser_xxx(cred, p, PRISON_ROOT)) && + (error = cap_check(cred, p, CAP_FOWNER, PRISON_ROOT)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(vp, VWRITE, cred, p)))) return (error); Index: sys/isa/fd.c =================================================================== RCS file: /home/ncvs/src/sys/isa/fd.c,v retrieving revision 1.192 diff -u -r1.192 fd.c --- sys/isa/fd.c 2000/12/08 21:50:26 1.192 +++ sys/isa/fd.c 2000/12/13 05:37:16 @@ -2411,8 +2411,9 @@ case FD_STYPE: /* set drive type */ /* this is considered harmful; only allow for superuser */ - if (suser(p) != 0) - return EPERM; + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + return (error); + suser_used(p); *fd->ft = *(struct fd_type *)addr; break; Index: sys/isofs/cd9660/cd9660_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v retrieving revision 1.81 diff -u -r1.81 cd9660_vfsops.c --- sys/isofs/cd9660/cd9660_vfsops.c 2000/12/08 21:50:31 1.81 +++ sys/isofs/cd9660/cd9660_vfsops.c 2000/12/13 05:37:18 @@ -223,13 +223,21 @@ /* * Verify that user has necessary permissions on the device, - * or has superuser abilities + * or has superuser abilities. + * + * XXX: Capability check is to see if caller can override + * permissions protecting the device. Perhaps also should + * be checks for the right to open devices? Also, what about + * securelevel? */ accessmode = VREAD; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p); - if (error) - error = suser(p); + if (error) { + error = cap_check(NULL, p, CAP_DAC_READ_SEARCH, 0); + if (error == 0) + suser_used(p); + } if (error) { vput(devvp); return (error); Index: sys/kern/init_main.c =================================================================== RCS file: /home/ncvs/src/sys/kern/init_main.c,v retrieving revision 1.151 diff -u -r1.151 init_main.c --- sys/kern/init_main.c 2000/12/13 00:17:00 1.151 +++ sys/kern/init_main.c 2000/12/13 05:37:19 @@ -75,6 +75,7 @@ #include #include #include +#include extern struct linker_set sysinit_set; /* XXX */ @@ -322,6 +323,10 @@ p->p_cred = &cred0; p->p_ucred = crget(); p->p_ucred->cr_ngroups = 1; /* group 0 */ + + /* Give all kernel processes many capabilities */ + cap_init_proc0(&p->p_ucred->cr_cap); + p->p_ucred->cr_uidinfo = uifind(0); /* Don't jail it */ @@ -598,6 +603,12 @@ panic("cannot fork init: %d\n", error); initproc->p_flag |= P_INMEM | P_SYSTEM; cpu_set_fork_handler(initproc, start_init, NULL); + + /* + * Give init necessary capabilities to shut the system down and + * avoid a panic when done. + */ + cap_init_proc1(&initproc->p_ucred->cr_cap); } SYSINIT(init,SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL) Index: sys/kern/kern_acct.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_acct.c,v retrieving revision 1.27 diff -u -r1.27 kern_acct.c --- sys/kern/kern_acct.c 2000/11/27 22:52:29 1.27 +++ sys/kern/kern_acct.c 2000/12/13 05:37:19 @@ -118,9 +118,9 @@ int error, flags; /* Make sure that the caller is root. */ - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_PACCT, 0)) != 0) return (error); + suser_used(p); /* * If accounting is to be started to a file, open that file for Index: sys/kern/kern_cap.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_cap.c,v retrieving revision 1.5 diff -u -r1.5 kern_cap.c --- sys/kern/kern_cap.c 2000/10/29 13:56:50 1.5 +++ sys/kern/kern_cap.c 2000/11/07 02:42:40 @@ -31,8 +31,6 @@ /* * Developed by the TrustedBSD Project. * Support for POSIX.1e process capabilities. - * - * XXX: Currently just syscall stubs. */ #include @@ -50,14 +48,340 @@ #include "opt_cap.h" +static void cap_zero(struct cap *cap_p); +static int cap_valid(struct cap *cap_p); +static int cap_subset(struct cap *cap1, struct cap *cap2); +static int cap_get_vp(struct vnode *vp, int ioflg, struct cap *cap_p, + struct proc *p); +static int cap_set_vp(struct vnode *vp, int ioflg, struct cap *cap_p, + struct proc *p); + + +static int kern_security_suser_enabled = 1; +#ifdef CAPABILITIES +static int kern_security_capabilities_enabled = 1; +#endif + +SYSCTL_NODE(_kern, OID_AUTO, security, CTLFLAG_RD, 0, "Kernel Security MIB"); +SYSCTL_INT(_kern_security, OID_AUTO, suser_permitted, CTLFLAG_RW, + &kern_security_suser_enabled, 0, "Super-user Enabled"); +#ifdef CAPABILITIES +SYSCTL_INT(_kern_security, OID_AUTO, capabilities_enabled, CTLFLAG_RW, + &kern_security_capabilities_enabled, 0, "POSIX.1e Capabilities Enabled"); +#endif + +/* + * Return a capability set to a state where it has no flags enabled. + */ +static void +cap_zero(struct cap *cap_p) +{ + + bzero(cap_p, sizeof(*cap_p)); +} + +/* + * Check the validity of a capability set -- 0 on success, EINVAL otherwise + */ +static int +cap_valid(struct cap *cap_p) +{ + + /* + * Effective cannot contain anything not in permitted. + */ + if ((cap_p->c_permitted | cap_p->c_effective) != cap_p->c_permitted) + return (EINVAL); + return (0); +} + +/* + * Check whether cap2 is a strict subset of cap1, from the perspective + * of setting a new capability set for a process without appropriate + * privilege. + */ +static int +cap_subset(struct cap *cap1, struct cap *cap2) +{ + + /* + * New permitted set must be a subset of the old permitted set. + */ + if ((cap2->c_permitted | cap1->c_permitted) != + cap1->c_permitted) + return (EPERM); + + /* + * New effective set must be a subset of the new permitted set. + */ + if ((cap2->c_effective | cap2->c_permitted) != + cap2->c_permitted) + return (EPERM); + + /* + * New inheritable set must be a subset of the old permitted set. + */ + if ((cap2->c_inheritable | cap1->c_permitted) != + cap1->c_permitted) + return (EPERM); + return (0); +} + +/* + * cap_proc0: initialize capabilities for kernel processes + * + * XXX for now, give them all capabilities, as kernel processes may + * need to do all kinds of things. + */ +void +cap_init_proc0(struct cap *cap_p) +{ + + /* All available rights. */ + cap_p->c_effective = ~0; + cap_p->c_permitted = ~0; + cap_p->c_inheritable = ~0; +} + +/* + * cap_init: initialize capabilities for init + * + * XXX init requires CAP_KILL in order to shut the system + * down successfully, as well as CAP_SYS_BOOT. + */ +void +cap_init_proc1(struct cap *cap_p) +{ + + bzero(cap_p, sizeof(struct cap)); + + /* + * Give init(8) all rights, as it will need to pass them on + * to startup processes during the system boot. For safety, + * default to non-inheritable for all of the capabilities, + * allowing a legacy init(8) to operate safely on a + * capabilities environment. + * + * XXX we may need to setsugid() init, so would require + * a proc pointer, not just the cap pointer here. + */ + cap_p->c_effective = ~0; + cap_p->c_permitted = ~0; + cap_p->c_inheritable = 0; + + /* + * For reference, the following rights are the ones required for + * normal system operation of init(8), leaving aside the + * requirement that programs executed by init(8) might require + * privilege. + * + * cap_p->c_effective = cap_p->c_permitted = cap_p->c_inheritable = 0; + * SET_CAPABILITY(cap_p->c_permitted, CAP_KILL); + * SET_CAPABILITY(cap_p->c_effective, CAP_KILL); + * SET_CAPABILITY(cap_p->c_permitted, CAP_SYS_BOOT); + * SET_CAPABILITY(cap_p->c_effective, CAP_SYS_BOOT); + */ +} + /* + * Perform capability inheritence on p, with optional vnode for a file + * from which to gain/mask new capabilities. To not use a vnode, set + * vp to NULL. + * + * POSIX.1e defines the following inheritence: + * pI` = pI + * pP` = (fP & X) | (fI & pI) + * pE` = (fE & pP`) + * + * We currently don't implement X, but will soon implement a per-process + * inherited bounding set to support jail(). + * Linux currently uses: X = fB & (~pB) where fB is a per-fs bound, and + * pB is the inherited process bound. + * + * If capabilities have been disabled using the sysctl, new programs + * running are not permitted to acquire and capabilities regardless of + * their on-disk state, or inherited capabilities. + * + * If any capabilities are set on the process, i.e, requiring protection, + * then return (1), otherwise (0). This allows the caller to determine + * what protection is appropriate. + */ +int +cap_inherit(struct vnode *vp, struct proc *p) +{ + struct cap cap_file; + struct cap cap_new; + struct cap *cap_p_proc; +#ifdef CAPABILITIES + int len; +#endif + int error; + + /* + * XXX have to do this, since we don't know if capabilities will + * change. This should be fixed to not crcopy if the capabilities + * have not changed. + */ + p->p_ucred = crcopy(p->p_ucred); + cap_p_proc = &p->p_ucred->cr_cap; + +#ifdef CAPABILITIES + if (kern_security_capabilities_enabled == 1) { + len = sizeof(cap_file); + error = cap_get_vp(vp, 0, &cap_file, p); + if (error) { + printf("cap_inherit: error retrieving capability\n"); + printf("error: %d\n", error); + } + } else +#endif + error = 1; /* force zero'ing of capabilities */ + + if (error == 0) { + cap_new.c_inheritable = cap_p_proc->c_inheritable; + cap_new.c_permitted = cap_file.c_permitted | + (cap_file.c_inheritable & cap_p_proc->c_inheritable); + cap_new.c_effective = cap_file.c_effective & + cap_new.c_permitted; + } else { + cap_new.c_inheritable = 0; + cap_new.c_permitted = 0; + cap_new.c_effective = 0; + } + *cap_p_proc = cap_new; + + /* + * Currently, we protect a process only if some of its capability + * bits end up being turned on. Is this correct? + */ + if (cap_p_proc->c_permitted || cap_p_proc->c_effective) + return (1); + return (0); +} + +/* + * cap_check: perform an authorization check to see if the given process + * appropriate privilege. Flags model those of suser_xxx. + */ +int +cap_check(const struct ucred *cred, const struct proc *proc, + cap_value_t cap, int flags) +{ + + if (!cred && !proc) { + printf("cap_check(): THINK!\n"); + return (EPERM); + } + if (!cred) + cred = proc->p_ucred; + /* + * Disqualify processes in jail(), if flags indicate that jail()'d + * processes cannot user privilege with this call. + * + * XXX: Right now, this only works if the process structure is + * passed as an argument. + * XXX: Eventually, jail(8) support will be implemented using + * inherited capability bounds, meaning the flags can go away. + */ + if (proc && proc->p_prison && !(flags & PRISON_ROOT)) + return (EPERM); +#ifdef CAPABILITIES + /* + * If capabilities are enabled, try to gain privilege through the + * appropriate capability flag in the credential. + */ + if (kern_security_capabilities_enabled && + (cred->cr_cap.c_effective & cap)) + return (0); +#endif + /* + * If the super-user is enabled, try to gain privilege through an + * effective uid of 0. + */ + if (kern_security_suser_enabled && + (cred->cr_uid == 0)) + return (0); + /* + * Return failure, as no form of privilege was available to + * authorize the request. + */ + return (EPERM); +} + +/* + * Internal function to retrieve the capability block from a + * vnode. Will always fill in the cap set, possibly by zero'ing it + * if the file doesn't have a capability, or if it is invalid. + */ +static int +cap_get_vp(struct vnode *vp, int ioflg, struct cap *cap_p, struct proc *p) +{ + int len, error; + + /* + * XXX: Check to see if this file system has capability support + * enabled. + */ + + len = sizeof(*cap_p); + error = vn_extattr_get(vp, ioflg, POSIX1E_CAPABILITY_EXTATTR_NAME, + &len, (char *) cap_p, p); + /* + * XXX should check for ENOATTR and convert to null capability it + * received, not ENOENT + */ + if (error == ENOENT || error == EOPNOTSUPP) { + /* + * Coerce no capability attribute to a null capability set + */ + error = 0; + cap_zero(cap_p); + } else if (error == 0 && len != sizeof(*cap_p)) { + printf("__cap_get_file: invalid capability on file\n"); + cap_zero(cap_p); + } + return (error); +} + +/* + * Internal function to set the capability set for a vnode. + * Partial writes of extended attributes may be a problem if the + * underlying implementation doesn't properly return failure + * information. A partial write *should* result in an invalid + * capability, which cap_get_vp will convert into a NULL capability + * set. Let vn_extattr_set() handle locking. + */ +static int +cap_set_vp(struct vnode *vp, int ioflg, struct cap *cap_p, + struct proc *p) +{ + int len, error; + + /* + * XXX: Check to see if this file system has capability support + * enabled. + */ + + if ((error = cap_check(NULL, p, CAP_SETFCAP, PRISON_ROOT))) + return (error); + + /* XXX Audit privilege here. */ + + len = sizeof(*cap_p); + error = vn_extattr_set(vp, ioflg, POSIX1E_CAPABILITY_EXTATTR_NAME, + len, (char *) cap_p, p); + return (error); +} + +/* * Syscall to allow a process to get it's currently capability set */ int __cap_get_proc(struct proc *p, struct __cap_get_proc_args *uap) { - return (ENOSYS); + return (copyout(&p->p_ucred->cr_cap, (caddr_t)uap->cap_p, + sizeof (struct cap))); } /* @@ -67,10 +391,38 @@ int __cap_set_proc(struct proc *p, struct __cap_set_proc_args *uap) { + struct cap capability; + int error, requires_privilege; - return (ENOSYS); + error = copyin(SCARG(uap, cap_p), &capability, sizeof(struct cap)); + if (error) + return (error); + + if ((error = cap_valid(&capability))) + return (error); + + if (cap_subset(&p->p_ucred->cr_cap, &capability) == 0) + requires_privilege = 0; + else + requires_privilege = 1; + + if (requires_privilege) { + if ((error = cap_check(NULL, p, CAP_SETPCAP, PRISON_ROOT)) != + 0) + return (error); + suser_used(p); + } + + /* + * XXX: Ideally, this wouldn't be necessary. + */ + p->p_ucred = crcopy(p->p_ucred); + p->p_ucred->cr_cap = capability; + + return (0); } + /* * Syscalls to allow a process to retrieve capabilities associated with * files, if permitted. @@ -78,15 +430,41 @@ int __cap_get_fd(struct proc *p, struct __cap_get_fd_args *uap) { + struct filedesc *fdp = p->p_fd; + struct file *fp; + struct vnode *vp; + struct cap cap; + int error; + + if ((unsigned)uap->fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[uap->fd]) == NULL) + return (EBADF); + vp = (struct vnode *)fp->f_data; + error = cap_get_vp(vp, 0, &cap, p); + if (error == 0) + error = copyout(&cap, SCARG(uap, cap_p), sizeof(cap)); - return (ENOSYS); + return (error); } int __cap_get_file(struct proc *p, struct __cap_get_file_args *uap) { + struct nameidata nd; + struct cap cap; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, + SCARG(uap, path_p), p); + if ((error = namei(&nd)) != 0) + return (error); + + error = cap_get_vp(nd.ni_vp, 0, &cap, p); + if (error == 0) + error = copyout(&cap, SCARG(uap, cap_p), sizeof(cap)); - return (ENOSYS); + NDFREE(&nd, 0); + return (error); } /* @@ -96,13 +474,39 @@ int __cap_set_fd(struct proc *p, struct __cap_set_fd_args *uap) { - - return (ENOSYS); + struct filedesc *fdp = p->p_fd; + struct file *fp; + struct vnode *vp; + struct cap cap; + int error; + + error = copyin(SCARG(uap, cap_p), &cap, sizeof(cap)); + if (error) + return (error); + + if ((unsigned)uap->fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[uap->fd]) == NULL) + return (EBADF); + vp = (struct vnode *)fp->f_data; + error = cap_set_vp(vp, 0, &cap, p); + return (error); } int __cap_set_file(struct proc *p, struct __cap_set_file_args *uap) { - - return (ENOSYS); + struct nameidata nd; + struct cap cap; + int error; + + error = copyin(SCARG(uap, cap_p), &cap, sizeof(cap)); + if (error) + return (error); + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path_p), p); + if ((error = namei(&nd)) != 0) + return (error); + error = cap_set_vp(nd.ni_vp, 0, &cap, p); + NDFREE(&nd, 0); + return (error); } Index: sys/kern/kern_exec.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_exec.c,v retrieving revision 1.121 diff -u -r1.121 kern_exec.c --- sys/kern/kern_exec.c 2000/12/23 19:43:09 1.121 +++ sys/kern/kern_exec.c 2001/01/05 17:01:03 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,7 @@ /* * Check file permissions (also 'opens' file) + * XXX Capability interaction here? */ error = exec_check_permissions(imgp); if (error) { @@ -279,6 +281,8 @@ * * Don't honor setuid/setgid if the filesystem prohibits it or if * the process is being traced. + * + * Do CAP execution stuff here, in style of setuid/setgid */ if ((((attr.va_mode & VSUID) && p->p_ucred->cr_uid != attr.va_uid) || ((attr.va_mode & VSGID) && p->p_ucred->cr_gid != attr.va_gid)) && @@ -288,11 +292,13 @@ * Turn off syscall tracing for set-id programs, except for * root. */ - if (p->p_tracep && suser(p)) { + if (p->p_tracep && cap_check(NULL, p, CAP_SYS_PTRACE, 0)) { p->p_traceflag = 0; vrele(p->p_tracep); p->p_tracep = NULL; } + if (p->p_tracep) + suser_used(p); /* * Set the new credentials. */ @@ -314,6 +320,30 @@ */ p->p_cred->p_svuid = p->p_ucred->cr_uid; p->p_cred->p_svgid = p->p_ucred->cr_gid; + + /* + * CAP inheritence, et al. + * XXX should this be above the file CAP stuff? + * XXX is this the right vp? could be the vp from the interpreter. + * XXX vp is now unlocked? + * XXX What about ptrace() handling? + * XXX is ordering here a problem? (above does tracep first, + * then rights, then sugid safety, but this is different) + */ + if (cap_inherit(ndp->ni_vp, p)) { + /* + * Resulted in a process with capabilities. + */ + if (p->p_tracep && cap_check(NULL, p, CAP_SYS_PTRACE, 0)) { + p->p_traceflag = 0; + vrele(p->p_tracep); + p->p_tracep = NULL; + } + if (p->p_tracep) + suser_used(p); + setsugid(p); + setugidsafety(p); + } /* * Store the vp for use in procfs Index: sys/kern/kern_jail.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_jail.c,v retrieving revision 1.9 diff -u -r1.9 kern_jail.c --- sys/kern/kern_jail.c 2000/12/08 21:50:32 1.9 +++ sys/kern/kern_jail.c 2000/12/13 05:37:20 @@ -56,9 +56,10 @@ struct jail j; struct chroot_args ca; - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_CHROOT, 0)) != 0) return (error); + suser_used(p); + error = copyin(uap->jail, &j, sizeof j); if (error) return (error); Index: sys/kern/kern_linker.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_linker.c,v retrieving revision 1.54 diff -u -r1.54 kern_linker.c --- sys/kern/kern_linker.c 2000/12/28 08:14:58 1.54 +++ sys/kern/kern_linker.c 2001/01/05 17:01:03 @@ -693,8 +693,9 @@ if (securelevel > 0) /* redundant, but that's OK */ return EPERM; - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_SYS_MODULE, 0)) != 0) return error; + suser_used(p); realpath = NULL; pathname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); @@ -736,8 +737,9 @@ if (securelevel > 0) /* redundant, but that's OK */ return EPERM; - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_SYS_MODULE, 0)) != 0) return error; + suser_used(p); lf = linker_find_file_by_id(SCARG(uap, fileid)); if (lf) { Index: sys/kern/kern_ntptime.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_ntptime.c,v retrieving revision 1.37 diff -u -r1.37 kern_ntptime.c --- sys/kern/kern_ntptime.c 2000/09/10 09:13:34 1.37 +++ sys/kern/kern_ntptime.c 2000/09/17 14:51:36 @@ -291,10 +291,11 @@ * from the ntv.constant member, depending on the mode bits. */ modes = ntv.modes; - if (modes) - error = suser(p); - if (error) - return (error); + if (modes) { + if ((error = cap_check(NULL, p, CAP_SYS_TIME, 0)) != 0); + return (error); + suser_used(p); + } s = splclock(); if (modes & MOD_FREQUENCY) { freq = (ntv.freq * 1000LL) >> 16; Index: sys/kern/kern_prot.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_prot.c,v retrieving revision 1.70 diff -u -r1.70 kern_prot.c --- sys/kern/kern_prot.c 2000/12/23 19:43:09 1.70 +++ sys/kern/kern_prot.c 2001/01/05 17:01:04 @@ -422,7 +422,7 @@ #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ #endif - (error = suser_xxx(0, p, PRISON_ROOT))) + (error = cap_check(0, p, CAP_SETUID, PRISON_ROOT)) != 0) return (error); #ifdef _POSIX_SAVED_IDS @@ -434,7 +434,7 @@ #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ uid == pc->pc_ucred->cr_uid || #endif - suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ + cap_check(0, p, CAP_SETUID, PRISON_ROOT) == 0) #endif { /* @@ -486,7 +486,7 @@ euid = uap->euid; if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ euid != pc->p_svuid && /* allow seteuid(saved uid) */ - (error = suser_xxx(0, p, PRISON_ROOT))) + (error = cap_check(0, p, CAP_SETUID, PRISON_ROOT))) return (error); /* * Everything's okay, do it. Copy credentials so other references do @@ -533,7 +533,7 @@ #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ #endif - (error = suser_xxx(0, p, PRISON_ROOT))) + (error = cap_check(0, p, CAP_SETGID, PRISON_ROOT))) return (error); #ifdef _POSIX_SAVED_IDS @@ -545,7 +545,7 @@ #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ gid == pc->pc_ucred->cr_groups[0] || #endif - suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ + cap_check(0, p, CAP_SETGID, PRISON_ROOT) == 0) #endif { /* @@ -597,7 +597,7 @@ egid = uap->egid; if (egid != pc->p_rgid && /* allow setegid(getgid()) */ egid != pc->p_svgid && /* allow setegid(saved gid) */ - (error = suser_xxx(0, p, PRISON_ROOT))) + (error = cap_check(0, p, CAP_SETGID, PRISON_ROOT))) return (error); if (pc->pc_ucred->cr_groups[0] != egid) { pc->pc_ucred = crcopy(pc->pc_ucred); @@ -623,7 +623,7 @@ register u_int ngrp; int error; - if ((error = suser_xxx(0, p, PRISON_ROOT))) + if ((error = cap_check(0, p, CAP_SETGID, PRISON_ROOT))) return (error); ngrp = uap->gidsetsize; if (ngrp > NGROUPS) @@ -672,7 +672,7 @@ if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid && euid != pc->p_svuid)) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + (error = cap_check(0, p, CAP_SETUID, PRISON_ROOT)) != 0) return (error); if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { @@ -712,7 +712,7 @@ if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid && egid != pc->p_svgid)) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + (error = cap_check(0, p, CAP_SETGID, PRISON_ROOT)) != 0) return (error); if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { @@ -763,7 +763,7 @@ euid != pc->pc_ucred->cr_uid) || (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid && suid != pc->pc_ucred->cr_uid)) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + (error = cap_check(0, p, CAP_SETUID, PRISON_ROOT)) != 0) return (error); if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { change_euid(p, euid); @@ -811,7 +811,7 @@ egid != pc->pc_ucred->cr_groups[0]) || (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && sgid != pc->pc_ucred->cr_groups[0])) && - (error = suser_xxx(0, p, PRISON_ROOT)) != 0) + (error = cap_check(0, p, CAP_SETGID, PRISON_ROOT)) != 0) return (error); if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { @@ -928,6 +928,23 @@ return (0); } +/* + * For accounting purposes, flag a process as having used super-user + * privileges. Right now this is not called much, as most code still + * assumes that suser() will do the dirty work. But this is incorrect + * behavior. Use of suser_used() is difficult in current code due to + * abuse of short-circuit boolean evaluation to call or not call + * suser(), rather than isolating use of privilege. + */ +void +suser_used(proc) + struct proc *proc; +{ + + if (proc) + proc->p_acflag |= ASU; +} + static int suser_permitted = 1; SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0, @@ -935,8 +952,9 @@ /* * Test whether the specified credentials imply "super-user" - * privilege; if so, and we have accounting info, set the flag - * indicating use of super-powers. + * privilege. This used to also set the appropriate accounting flag, + * but now ``suser_used(p)'' must be called explicitely, as not all + * invocations of suser() result in the privilege being excercised. * Returns 0 or error. */ int @@ -978,14 +996,13 @@ return (ESRCH); if (!ps_showallprocs && p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) { - if (suser_xxx(NULL, p1, PRISON_ROOT) == 0) { + if (cap_check(NULL, p1, CAP_SYS_ADMIN, PRISON_ROOT) == 0) { if (privused != NULL) *privused = 1; return (0); } return (ESRCH); } - return (0); } @@ -1014,21 +1031,12 @@ return (0); if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) return (0); - - if (!suser_xxx(0, p1, PRISON_ROOT)) { + if (!cap_check(NULL, p1, CAP_KILL, PRISON_ROOT)) { if (privused != NULL) *privused = 1; return (0); } -#ifdef CAPABILITIES - if (!cap_check_xxx(0, p1, CAP_KILL, PRISON_ROOT)) { - if (privused != NULL) - *privused = 1; - return (0); - } -#endif - return (EPERM); } @@ -1057,21 +1065,12 @@ return (0); if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) return (0); - - if (!suser_xxx(0, p1, PRISON_ROOT)) { + if (!cap_check(0, p1, CAP_SYS_NICE, PRISON_ROOT)) { if (privused != NULL) *privused = 1; return (0); } -#ifdef CAPABILITIES - if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) { - if (privused != NULL) - *privused = 1; - return (0); - } -#endif - return (EPERM); } @@ -1096,7 +1095,8 @@ p1->p_cred->p_ruid != p2->p_cred->p_ruid || p1->p_cred->p_svuid != p2->p_cred->p_ruid || p2->p_flag & P_SUGID) { - if ((error = suser_xxx(0, p1, PRISON_ROOT))) + if ((error = + cap_check(NULL, p1, CAP_SYS_PTRACE, PRISON_ROOT)) != 0) return (error); if (privused != NULL) *privused = 1; @@ -1132,7 +1132,6 @@ } } - /* * Allocate a zeroed cred structure. */ @@ -1262,7 +1261,7 @@ int error; char logintmp[MAXLOGNAME]; - if ((error = suser_xxx(0, p, PRISON_ROOT))) + if ((error = cap_check(0, p, CAP_SETUID, PRISON_ROOT)) != 0) return (error); error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, sizeof(logintmp), (size_t *)0); Index: sys/kern/kern_resource.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_resource.c,v retrieving revision 1.69 diff -u -r1.69 kern_resource.c --- sys/kern/kern_resource.c 2000/12/13 00:17:01 1.69 +++ sys/kern/kern_resource.c 2000/12/13 05:40:23 @@ -89,6 +89,7 @@ { register struct proc *p; register int low = PRIO_MAX + 1; + int privused = 0, cumulative_privused = 0; switch (uap->which) { @@ -112,8 +113,11 @@ else if ((pg = pgfind(uap->who)) == NULL) break; LIST_FOREACH(p, &pg->pg_members, p_pglist) { - if (!p_can(curp, p, P_CAN_SEE, NULL) && p->p_nice < low) + if (!p_can(curp, p, P_CAN_SEE, &privused) && + p->p_nice < low) low = p->p_nice; + if (privused) + cumulative_privused = 1; } break; } @@ -123,10 +127,13 @@ uap->who = curp->p_ucred->cr_uid; ALLPROC_LOCK(AP_SHARED); LIST_FOREACH(p, &allproc, p_list) - if (!p_can(curp, p, P_CAN_SEE, NULL) && + if (!p_can(curp, p, P_CAN_SEE, NULL) && p->p_ucred->cr_uid == uap->who && - p->p_nice < low) + p->p_nice < low) { low = p->p_nice; + if (privused) + cumulative_privused = 1; + } ALLPROC_LOCK(AP_RELEASE); break; @@ -135,6 +142,10 @@ } if (low == PRIO_MAX + 1) return (ESRCH); + + if (cumulative_privused) + suser_used(curp); + curp->p_retval[0] = low; return (0); } @@ -220,8 +231,11 @@ n = PRIO_MAX; if (n < PRIO_MIN) n = PRIO_MIN; - if (n < chgp->p_nice && suser(curp)) - return (EACCES); + if (n < chgp->p_nice) { + if ((error = cap_check(NULL, curp, CAP_SYS_NICE, 0)) != 0) + return (error); + suser_used(curp); + } chgp->p_nice = n; (void)resetpriority(chgp); return (0); @@ -269,7 +283,7 @@ if ((error = p_can(curp, p, P_CAN_SCHED, NULL))) return (error); /* disallow setting rtprio in most cases if not superuser */ - if (suser(curp) != 0) { + if (cap_check(NULL, curp, CAP_SYS_NICE, 0)) { /* can't set someone else's */ if (uap->pid) return (EPERM); @@ -287,6 +301,7 @@ if (rtp.type != RTP_PRIO_NORMAL) return (EPERM); } + suser_used(curp); switch (rtp.type) { #ifdef RTP_PRIO_FIFO case RTP_PRIO_FIFO: @@ -401,9 +416,12 @@ limp->rlim_max = RLIM_INFINITY; if (limp->rlim_cur > alimp->rlim_max || - limp->rlim_max > alimp->rlim_max) - if ((error = suser_xxx(0, p, PRISON_ROOT))) + limp->rlim_max > alimp->rlim_max) { + if ((error = cap_check(0, p, CAP_SYS_NICE, PRISON_ROOT)) + != 0) return (error); + suser_used(p); + } if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; if (p->p_limit->p_refcnt > 1 && Index: sys/kern/kern_shutdown.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_shutdown.c,v retrieving revision 1.90 diff -u -r1.90 kern_shutdown.c --- sys/kern/kern_shutdown.c 2000/12/15 20:08:19 1.90 +++ sys/kern/kern_shutdown.c 2001/01/05 17:01:04 @@ -139,8 +139,9 @@ { int error; - if ((error = suser(p))) + if ((error = cap_check(NULL, p, CAP_SYS_BOOT, 0)) != 0) return (error); + suser_used(p); boot(uap->opt); return (0); Index: sys/kern/kern_sig.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_sig.c,v retrieving revision 1.101 diff -u -r1.101 kern_sig.c --- sys/kern/kern_sig.c 2001/01/02 18:54:09 1.101 +++ sys/kern/kern_sig.c 2001/01/05 17:01:05 @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,11 @@ /* * Can process p, with pcred pc, send the signal sig to process q? + * XXX should p be able to signal q outside the same prison if CAP_KILL + * is present? + * + * XXX This should propagate the privused flag up the stack but + * doesn't. */ #define CANSIGNAL(p, q, sig) \ (!p_can(p, q, P_CAN_KILL, NULL) || \ Index: sys/kern/kern_sysctl.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_sysctl.c,v retrieving revision 1.102 diff -u -r1.102 kern_sysctl.c --- sys/kern/kern_sysctl.c 2001/01/05 07:00:44 1.102 +++ sys/kern/kern_sysctl.c 2001/01/05 17:01:05 @@ -1015,11 +1015,22 @@ return (EPERM); /* Most likely only root can write */ + /* + * XXX What about capabilities? + * Ought to have another argument to SYSCTL_* allowing a specific + * capability to be identified as providing the privilege to write, + * rather than just suser(). For now, use CAP_SYSADMIN, but this + * should change. + */ if (!(oid->oid_kind & CTLFLAG_ANYBODY) && - req->newptr && req->p && - (error = suser_xxx(0, req->p, - (oid->oid_kind & CTLFLAG_PRISON) ? PRISON_ROOT : 0))) - return (error); + req->newptr && req->p) { + int flag_prison = ((oid->oid_kind & CTLFLAG_PRISON) ? + PRISON_ROOT : 0); + if ((error = cap_check(0, req->p, CAP_SYS_ADMIN, + flag_prison)) != 0) + return (error); + suser_used(req->p); + } if (!oid->oid_handler) return EINVAL; Index: sys/kern/kern_time.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_time.c,v retrieving revision 1.71 diff -u -r1.71 kern_time.c --- sys/kern/kern_time.c 2000/11/27 22:52:29 1.71 +++ sys/kern/kern_time.c 2000/12/13 05:37:22 @@ -174,8 +174,9 @@ struct timespec ats; int error; - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_SYS_TIME, 0)) != 0) return (error); + suser_used(p); if (SCARG(uap, clock_id) != CLOCK_REALTIME) return (EINVAL); if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0) @@ -331,8 +332,9 @@ struct timezone atz; int error; - if ((error = suser(p))) + if ((error = cap_check(NULL, p, CAP_SYS_TIME, 0)) != 0) return (error); + suser_used(p); /* Verify all parameters before changing time. */ if (uap->tv) { if ((error = copyin((caddr_t)uap->tv, (caddr_t)&atv, @@ -371,8 +373,10 @@ register long ndelta, ntickdelta, odelta; int s, error; - if ((error = suser(p))) + if ((error = cap_check(NULL, p, CAP_SYS_TIME, 0)) != 0) return (error); + suser_used(p); + if ((error = copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval)))) return (error); Index: sys/kern/kern_xxx.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_xxx.c,v retrieving revision 1.31 diff -u -r1.31 kern_xxx.c --- sys/kern/kern_xxx.c 1999/08/28 00:46:15 1.31 +++ sys/kern/kern_xxx.c 2000/09/17 14:56:07 @@ -85,8 +85,10 @@ name[0] = CTL_KERN; name[1] = KERN_HOSTNAME; - if ((error = suser_xxx(0, p, PRISON_ROOT))) + if ((error = cap_check(0, p, CAP_SYS_ADMIN, PRISON_ROOT)) != 0) return (error); + suser_used(p); + return (userland_sysctl(p, name, 2, 0, 0, 0, uap->hostname, uap->len, 0)); } @@ -122,8 +124,10 @@ { int error; - if ((error = suser(p))) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); + suser_used(p); + hostid = uap->hostid; return (0); } @@ -244,8 +248,10 @@ { int error, domainnamelen; - if ((error = suser(p))) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); + suser_used(p); + if ((u_int)uap->len > sizeof (domainname) - 1) return EINVAL; domainnamelen = uap->len; Index: sys/kern/makesyscalls.sh =================================================================== RCS file: /home/ncvs/src/sys/kern/makesyscalls.sh,v retrieving revision 1.44 diff -u -r1.44 makesyscalls.sh --- sys/kern/makesyscalls.sh 2000/12/01 08:47:54 1.44 +++ sys/kern/makesyscalls.sh 2000/12/13 05:37:22 @@ -111,8 +111,9 @@ printf " * created from%s\n */\n\n", $0 > sysarg printf "#ifndef %s\n", sysproto_h > sysarg printf "#define\t%s\n\n", sysproto_h > sysarg - printf "#include \n\n" > sysarg - printf "#include \n\n" > sysarg + printf "#include \n" > sysarg + printf "#include \n" > sysarg + printf "#include \n\n" > sysarg printf "struct proc;\n\n" > sysarg printf "#define\tPAD_(t)\t(sizeof(register_t) <= sizeof(t) ? \\\n" > sysarg printf "\t\t0 : sizeof(register_t) - sizeof(t))\n\n" > sysarg Index: sys/kern/sys_process.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_process.c,v retrieving revision 1.59 diff -u -r1.59 sys_process.c --- sys/kern/sys_process.c 2000/12/31 01:30:27 1.59 +++ sys/kern/sys_process.c 2001/01/05 17:01:06 @@ -206,6 +206,7 @@ struct proc *p; struct iovec iov; struct uio uio; + int privused = 0; int error = 0; int write; int s; @@ -237,8 +238,10 @@ if (p->p_flag & P_TRACED) return EBUSY; - if ((error = p_can(curp, p, P_CAN_DEBUG, NULL))) + if ((error = p_can(curp, p, P_CAN_DEBUG, &privused))) return error; + if (privused) + suser_used(curp); /* OK */ break; Index: sys/kern/sys_socket.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_socket.c,v retrieving revision 1.32 diff -u -r1.32 sys_socket.c --- sys/kern/sys_socket.c 2000/07/03 00:05:40 1.32 +++ sys/kern/sys_socket.c 2000/08/07 18:44:28 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include Index: sys/kern/sysv_ipc.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sysv_ipc.c,v retrieving revision 1.17 diff -u -r1.17 sysv_ipc.c --- sys/kern/sysv_ipc.c 2000/12/01 08:57:45 1.17 +++ sys/kern/sysv_ipc.c 2000/12/14 00:42:39 @@ -92,8 +92,13 @@ /* Check for user match. */ if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) { - if (mode & IPC_M) - return (suser(p) == 0 ? 0 : EPERM); + if (mode & IPC_M) { + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + return (error); + else { + suser_used(p); + return (0); + } /* Check for group match. */ mode >>= 3; if (!groupmember(perm->gid, cred) && @@ -104,5 +109,13 @@ if (mode & IPC_M) return (0); - return ((mode & perm->mode) == mode || suser(p) == 0 ? 0 : EACCES); + + if ((mode & perm->mode) == mode) + return (0); + + if (cap_check(NULL, p, CAP_IPC_OWNER, 0) == 0) { + suser_user(p); + return (0); + } + return (EACCES); } Index: sys/kern/sysv_msg.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sysv_msg.c,v retrieving revision 1.28 diff -u -r1.28 sysv_msg.c --- sys/kern/sysv_msg.c 2000/12/05 23:05:45 1.28 +++ sys/kern/sysv_msg.c 2000/12/13 05:37:24 @@ -402,9 +402,10 @@ if ((eval = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0) return(eval); if (msqbuf.msg_qbytes > msqptr->msg_qbytes) { - eval = suser(p); - if (eval) + eval = cap_check(NULL, p, CAP_SYS_RESOURCE, 0); + if (eval != 0) return(eval); + suser_used(p); } if (msqbuf.msg_qbytes > msginfo.msgmnb) { #ifdef MSG_DEBUG_OK Index: sys/kern/tty.c =================================================================== RCS file: /home/ncvs/src/sys/kern/tty.c,v retrieving revision 1.142 diff -u -r1.142 tty.c --- sys/kern/tty.c 2000/12/08 21:50:36 1.142 +++ sys/kern/tty.c 2000/12/13 05:37:24 @@ -816,8 +816,10 @@ ISSET(constty->t_state, TS_CONNECTED)) return (EBUSY); #ifndef UCONSOLE - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_SYS_TTY_CONFIG, + 0)) != 0) return (error); + suser_used(p); #endif constty = tp; } else if (tp == constty) @@ -988,10 +990,19 @@ splx(s); break; case TIOCSTI: /* simulate terminal input */ - if ((flag & FREAD) == 0 && suser(p)) - return (EPERM); - if (!isctty(p, tp) && suser(p)) - return (EACCES); + if ((flag & FREAD) == 0) { + if ((error = cap_check(NULL, p, CAP_SYS_TTY_CONFIG, + 0)) != 0) + return (error); + else + suser_used(p); + } + if (!isctty(p, tp)) { + if (cap_check(NULL, p, CAP_SYS_TTY_CONFIG, 0) != 0) + return (EACCES); + else + suser_used(p); + } s = spltty(); (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp); splx(s); @@ -1038,9 +1049,10 @@ } break; case TIOCSDRAINWAIT: - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_TTY_CONFIG, 0)) != 0) return (error); + suser_used(p); + tp->t_timeout = *(int *)data * hz; wakeup(TSA_OCOMPLETE(tp)); wakeup(TSA_OLOWAT(tp)); Index: sys/kern/tty_cons.c =================================================================== RCS file: /home/ncvs/src/sys/kern/tty_cons.c,v retrieving revision 1.88 diff -u -r1.88 tty_cons.c --- sys/kern/tty_cons.c 2000/12/20 21:50:37 1.88 +++ sys/kern/tty_cons.c 2001/01/05 17:01:06 @@ -374,9 +374,10 @@ * output from the "virtual" console. */ if (cmd == TIOCCONS && constty) { - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_TTY_CONFIG, 0)) != 0) return (error); + suser_used(p); + constty = NULL; return (0); } Index: sys/kern/tty_pty.c =================================================================== RCS file: /home/ncvs/src/sys/kern/tty_pty.c,v retrieving revision 1.82 diff -u -r1.82 tty_pty.c --- sys/kern/tty_pty.c 2000/12/08 21:50:37 1.82 +++ sys/kern/tty_pty.c 2000/12/13 05:37:25 @@ -183,7 +183,11 @@ tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; - } else if (tp->t_state & TS_XCLUDE && suser(p)) { + } else if (tp->t_state & TS_XCLUDE) { + /* + * XXX used to be && suser(p) with, why could suser override + * TS_XCLUDE? + */ return (EBUSY); } else if (pti->pt_prison != p->p_prison) { return (EBUSY); Index: sys/kern/tty_snoop.c =================================================================== RCS file: /home/ncvs/src/sys/kern/tty_snoop.c,v retrieving revision 1.50 diff -u -r1.50 tty_snoop.c --- sys/kern/tty_snoop.c 2000/12/08 21:50:37 1.50 +++ sys/kern/tty_snoop.c 2000/12/13 05:37:25 @@ -285,7 +285,7 @@ struct snoop *snp; int error; - if ((error = suser(p)) != 0) + if (((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); if (dev->si_drv1 == NULL) { Index: sys/kern/vfs_subr.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v retrieving revision 1.298 diff -u -r1.298 vfs_subr.c --- sys/kern/vfs_subr.c 2000/12/15 20:08:19 1.298 +++ sys/kern/vfs_subr.c 2001/01/05 17:01:07 @@ -3032,15 +3032,12 @@ int *privused; { mode_t dac_granted; -#ifdef CAPABILITIES mode_t cap_granted; -#endif /* * Look for a normal, non-privileged way to access the file/directory * as requested. If it exists, go with that. */ - if (privused != NULL) *privused = 0; @@ -3088,14 +3085,6 @@ return (0); privcheck: - if (!suser_xxx(cred, NULL, PRISON_ROOT)) { - /* XXX audit: privilege used */ - if (privused != NULL) - *privused = 1; - return (0); - } - -#ifdef CAPABILITIES /* * Build a capability mask to determine if the set of capabilities * satisfies the requirements when combined with the granted mask @@ -3104,16 +3093,27 @@ * or the request type onto the cap_granted mask. */ cap_granted = 0; - if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) && - !cap_check_xxx(cred, NULL, CAP_DAC_EXECUTE, PRISON_ROOT)) - cap_granted |= VEXEC; + + if (type == VDIR) { + /* + * For directories, use CAP_DAC_READ_SEARCH to satisfy + * VEXEC requests, instead of CAP_DAC_EXECUTE. + */ + if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) && + !cap_check(cred, NULL, CAP_DAC_READ_SEARCH, PRISON_ROOT)) + cap_granted |= VEXEC; + } else { + if ((acc_mode & VEXEC) && ((dac_granted & VEXEC) == 0) && + !cap_check(cred, NULL, CAP_DAC_EXECUTE, PRISON_ROOT)) + cap_granted |= VEXEC; + } if ((acc_mode & VREAD) && ((dac_granted & VREAD) == 0) && - !cap_check_xxx(cred, NULL, CAP_DAC_READ_SEARCH, PRISON_ROOT)) + !cap_check(cred, NULL, CAP_DAC_READ_SEARCH, PRISON_ROOT)) cap_granted |= VREAD; if ((acc_mode & VWRITE) && ((dac_granted & VWRITE) == 0) && - !cap_check_xxx(cred, NULL, CAP_DAC_WRITE, PRISON_ROOT)) + !cap_check(cred, NULL, CAP_DAC_WRITE, PRISON_ROOT)) cap_granted |= VWRITE; if ((acc_mode & VADMIN) && ((dac_granted & VADMIN) == 0) && @@ -3126,7 +3126,6 @@ *privused = 1; return (0); } -#endif return (EACCES); } Index: sys/kern/vfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.175 diff -u -r1.175 vfs_syscalls.c --- sys/kern/vfs_syscalls.c 2000/12/13 00:17:01 1.175 +++ sys/kern/vfs_syscalls.c 2000/12/13 05:37:27 @@ -122,21 +122,28 @@ struct nameidata nd; char fstypename[MFSNAMELEN]; - if (usermount == 0 && (error = suser(p))) - return (error); + if (usermount == 0) { + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + return (error); + suser_used(p); + } /* * Do not allow NFS export by non-root users. */ if (SCARG(uap, flags) & MNT_EXPORTED) { - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); + suser_used(p); } /* * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users */ - if (suser_xxx(p->p_ucred, 0, 0)) + if (cap_check(p->p_ucred, NULL, CAP_SYS_ADMIN, 0) != 0) SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; + else if ((SCARG(uap, flags) & (MNT_NOSUID | MNT_NODEV)) != + (MNT_NOSUID | MNT_NODEV)) + suser_used(p); + /* * Get vnode to be covered */ @@ -168,10 +175,11 @@ * permitted to update it. */ if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && - (error = suser(p))) { + ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0)) { vput(vp); return (error); - } + } else + suser_used(p); if (vfs_busy(mp, LK_NOWAIT, 0, p)) { vput(vp); return (EBUSY); @@ -196,10 +204,13 @@ * onto which we are attempting to mount. */ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || - (va.va_uid != p->p_ucred->cr_uid && - (error = suser(p)))) { - vput(vp); - return (error); + (va.va_uid != p->p_ucred->cr_uid)) { + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + suser_used(p); + else { + vput(vp); + return (error); + } } if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) { vput(vp); @@ -220,10 +231,11 @@ linker_file_t lf; /* Only load modules for root (very important!) */ - if ((error = suser(p)) != 0) { + if ((error = cap_check(NULL, p, CAP_SYS_MODULE, 0)) != 0) { vput(vp); return error; } + suser_used(p); error = linker_load_file(fstypename, &lf); if (error || lf == NULL) { vput(vp); @@ -426,10 +438,12 @@ * Only root, or the user that did the original mount is * permitted to unmount this filesystem. */ - if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && - (error = suser(p))) { - vput(vp); - return (error); + if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid)) { + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) { + vput(vp); + return (error); + } + suser_used(p); } /* @@ -652,11 +666,12 @@ if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, 0, 0)) { + if (cap_check(p->p_ucred, NULL, CAP_SYS_ADMIN, 0) != 0) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; sp = &sb; - } + } else + suser_used(p); return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); } @@ -692,11 +707,12 @@ if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, 0, 0)) { + if (cap_check(p->p_ucred, NULL, CAP_SYS_ADMIN, 0) != 0) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; sp = &sb; - } + } else + suser_used(p); return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); } @@ -908,9 +924,10 @@ int error; struct nameidata nd; - error = suser_xxx(0, p, PRISON_ROOT); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_CHROOT, PRISON_ROOT)) != 0) return (error); + suser_used(p); + if (chroot_allow_open_directories == 0 || (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) error = chroot_refuse_vdir_fds(fdp); @@ -1170,10 +1187,10 @@ switch (SCARG(uap, mode) & S_IFMT) { case S_IFCHR: case S_IFBLK: - error = suser(p); + error = cap_check(NULL, p, CAP_MKNOD, 0); break; default: - error = suser_xxx(0, p, PRISON_ROOT); + error = cap_check(NULL, p, CAP_MKNOD, PRISON_ROOT); break; } if (error) @@ -2052,9 +2069,12 @@ * if they are allowed to set flags and programs assume that * chown can't fail when done as root. */ - if ((vp->v_type == VCHR || vp->v_type == VBLK) && - ((error = suser_xxx(p->p_ucred, p, PRISON_ROOT)) != 0)) - return (error); + if (vp->v_type == VCHR || vp->v_type == VBLK) { + if ((error = cap_check(p->p_ucred, p, CAP_SYS_SETFFLAG, + PRISON_ROOT)) != 0) + return (error); + suser_used(p); + } if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) return (error); @@ -3244,8 +3264,12 @@ } if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) goto out; - if (p->p_ucred->cr_uid != vattr.va_uid && - (error = suser_xxx(0, p, PRISON_ROOT))) + if (p->p_ucred->cr_uid != vattr.va_uid) { + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, + PRISON_ROOT)) != 0) + goto out; + suser_used(p); + } goto out; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) goto out; @@ -3298,9 +3322,10 @@ /* * Must be super user */ - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); + suser_used(p); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); error = namei(&nd); if (error) @@ -3353,9 +3378,9 @@ /* * Must be super user */ - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); + suser_used(p); fmode = FFLAGS(SCARG(uap, flags)); /* why not allow a non-read/write open for our lockd? */ @@ -3523,9 +3548,9 @@ /* * Must be super user */ - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); + suser_used(p); error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); if (error) @@ -3570,8 +3595,9 @@ /* * Must be super user */ - if ((error = suser(p))) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); + suser_used(p); if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) return (error); @@ -3586,11 +3612,13 @@ if ((error = VFS_STATFS(mp, sp, p)) != 0) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, 0, 0)) { + if (cap_check(p->p_ucred, NULL, CAP_SYS_ADMIN, 0) != 0) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; sp = &sb; - } + } else + suser_used(p); + return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); } Index: sys/kern/vfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_vnops.c,v retrieving revision 1.106 diff -u -r1.106 vfs_vnops.c --- sys/kern/vfs_vnops.c 2000/11/18 23:06:23 1.106 +++ sys/kern/vfs_vnops.c 2000/12/13 05:37:27 @@ -531,7 +531,7 @@ } sb->st_flags = vap->va_flags; - if (suser_xxx(p->p_ucred, 0, 0)) + if (cap_check(p->p_ucred, NULL, CAP_SYS_ADMIN, 0) != 0) sb->st_gen = 0; else sb->st_gen = vap->va_gen; Index: sys/miscfs/procfs/procfs_mem.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_mem.c,v retrieving revision 1.47 diff -u -r1.47 procfs_mem.c --- sys/miscfs/procfs/procfs_mem.c 2000/08/30 04:49:08 1.47 +++ sys/miscfs/procfs/procfs_mem.c 2000/09/17 15:32:38 @@ -304,7 +304,10 @@ struct ucred *cred; cred = curp->p_ucred; - if (suser(curp)) + /* + * XXX is CAP_SYS_ADMIN appropriate here? If not, what? + */ + if (cap_check(NULL, curp, CAP_SYS_ADMIN, 0)) return 1; /* XXX: Why isn't this done with file-perms ??? */ Index: sys/miscfs/procfs/procfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_vnops.c,v retrieving revision 1.87 diff -u -r1.87 procfs_vnops.c --- sys/miscfs/procfs/procfs_vnops.c 2000/12/31 10:24:19 1.87 +++ sys/miscfs/procfs/procfs_vnops.c 2001/01/05 17:41:26 @@ -248,7 +248,8 @@ */ #define NFLAGS (PF_ISUGID) flags = (unsigned char)*(unsigned int*)ap->a_data; - if (flags & NFLAGS && (error = suser(p))) + if (flags & NFLAGS && (error = cap_check(NULL, p, CAP_SYS_PTRACE, + 0))) return error; procp->p_pfsflags = flags; break; Index: sys/miscfs/umapfs/umap_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/umapfs/umap_vfsops.c,v retrieving revision 1.33 diff -u -r1.33 umap_vfsops.c --- sys/miscfs/umapfs/umap_vfsops.c 2000/10/29 16:06:36 1.33 +++ sys/miscfs/umapfs/umap_vfsops.c 2000/11/07 02:43:13 @@ -100,8 +100,9 @@ /* * Only for root + * XXX: Is CAP_SYS_ADMIN appropriate? */ - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) return (error); #ifdef DEBUG Index: sys/msdosfs/msdosfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/msdosfs/msdosfs_vnops.c,v retrieving revision 1.106 diff -u -r1.106 msdosfs_vnops.c --- sys/msdosfs/msdosfs_vnops.c 2000/10/22 14:24:30 1.106 +++ sys/msdosfs/msdosfs_vnops.c 2000/10/23 06:52:29 @@ -391,7 +391,8 @@ if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) + (error = + cap_check(cred, ap->a_p, CAP_FOWNER, PRISON_ROOT))) return (error); /* * We are very inconsistent about handling unsupported Index: sys/net/if.c =================================================================== RCS file: /home/ncvs/src/sys/net/if.c,v retrieving revision 1.96 diff -u -r1.96 if.c --- sys/net/if.c 2000/12/08 21:50:43 1.96 +++ sys/net/if.c 2000/12/13 05:38:16 @@ -769,7 +769,7 @@ register struct ifnet *ifp; register struct ifreq *ifr; struct ifstat *ifs; - int error; + int error, privilege_used = 0; short oif_flags; switch (cmd) { @@ -801,9 +801,10 @@ break; case SIOCSIFFLAGS: - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + suser_used(p); + ifr->ifr_prevflags = ifp->if_flags; if (ifp->if_flags & IFF_SMART) { /* Smart drivers twiddle their own routes */ @@ -826,31 +827,37 @@ break; case SIOCSIFMETRIC: - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + suser_used(p); + ifp->if_metric = ifr->ifr_metric; getmicrotime(&ifp->if_lastchange); break; case SIOCSIFPHYS: - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return error; + privilege_used = 1; + if (!ifp->if_ioctl) return EOPNOTSUPP; error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == 0) getmicrotime(&ifp->if_lastchange); + + if (error == 0 && privilege_used) + suser_used(p); return(error); case SIOCSIFMTU: { u_long oldmtu = ifp->if_mtu; - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + privilege_used = 1; + if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) @@ -868,14 +875,16 @@ nd6_setmtu(ifp); #endif } + if (error == 0 && privilege_used) + suser_used(p); return (error); } case SIOCADDMULTI: case SIOCDELMULTI: - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + privilege_used = 1; /* Don't allow group membership on non-multicast interfaces. */ if ((ifp->if_flags & IFF_MULTICAST) == 0) @@ -893,6 +902,8 @@ } if (error == 0) getmicrotime(&ifp->if_lastchange); + if (error == 0 && privilege_used) + suser_used(p); return error; case SIOCSIFPHYADDR: @@ -902,14 +913,17 @@ #endif case SIOCSIFMEDIA: case SIOCSIFGENERIC: - error = suser(p); - if (error) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + privilege_used = 1; + if (ifp->if_ioctl == 0) return (EOPNOTSUPP); error = (*ifp->if_ioctl)(ifp, cmd, data); if (error == 0) getmicrotime(&ifp->if_lastchange); + if (error == 0 && privilege_used) + suser_used(p); return error; case SIOCGIFSTATUS: @@ -923,7 +937,7 @@ return ((*ifp->if_ioctl)(ifp, cmd, data)); case SIOCSIFLLADDR: - error = suser(p); + error = cap_check(NULL, p, CAP_NET_ADMIN, 0); if (error) return (error); return if_setlladdr(ifp, Index: sys/net/if_ppp.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_ppp.c,v retrieving revision 1.68 diff -u -r1.68 if_ppp.c --- sys/net/if_ppp.c 2000/11/25 07:35:31 1.68 +++ sys/net/if_ppp.c 2000/12/13 05:43:39 @@ -355,8 +355,10 @@ break; case PPPIOCSFLAGS: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + return (error); + suser_used(p); flags = *(int *)data & SC_MASK; s = splsoftnet(); #ifdef PPP_COMPRESS @@ -369,8 +371,9 @@ break; case PPPIOCSMRU: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + suser_used(p); mru = *(int *)data; if (mru >= PPP_MRU && mru <= PPP_MAXMRU) sc->sc_mru = mru; @@ -382,8 +385,9 @@ #ifdef VJC case PPPIOCSMAXCID: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + suser_used(p); if (sc->sc_comp) { s = splsoftnet(); sl_compress_init(sc->sc_comp, *(int *)data); @@ -393,15 +397,17 @@ #endif case PPPIOCXFERUNIT: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + suser_used(p); sc->sc_xfer = p->p_pid; break; #ifdef PPP_COMPRESS case PPPIOCSCOMPRESS: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + suser_used(p); odp = (struct ppp_option_data *) data; nb = odp->length; if (nb > sizeof(ccp_option)) @@ -475,8 +481,10 @@ if (cmd == PPPIOCGNPMODE) { npi->mode = sc->sc_npmode[npx]; } else { - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + return (error); + suser_used(p); if (npi->mode != sc->sc_npmode[npx]) { s = splsoftnet(); sc->sc_npmode[npx] = npi->mode; @@ -601,8 +609,9 @@ break; case SIOCSIFMTU: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + suser_used(p); if (ifr->ifr_mtu > PPP_MAXMTU) error = EINVAL; else { Index: sys/net/if_sl.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_sl.c,v retrieving revision 1.92 diff -u -r1.92 if_sl.c --- sys/net/if_sl.c 2000/12/21 21:43:45 1.92 +++ sys/net/if_sl.c 2001/01/05 17:42:12 @@ -328,9 +328,10 @@ register struct sl_softc *sc; int s, error; - error = suser(p); + error = cap_check(NULL, p, CAP_NET_ADMIN, 0); if (error) return (error); + suser_used(p); if (tp->t_line == SLIPDISC) return (0); Index: sys/net/if_tap.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_tap.c,v retrieving revision 1.5 diff -u -r1.5 if_tap.c --- sys/net/if_tap.c 2000/12/08 21:50:44 1.5 +++ sys/net/if_tap.c 2000/12/13 05:38:17 @@ -271,8 +271,9 @@ struct tap_softc *tp = NULL; int error; - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + suser_used(p); tp = dev->si_drv1; if (tp == NULL) { Index: sys/net/if_tun.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_tun.c,v retrieving revision 1.83 diff -u -r1.83 if_tun.c --- sys/net/if_tun.c 2000/12/08 21:50:44 1.83 +++ sys/net/if_tun.c 2000/12/13 05:38:18 @@ -180,9 +180,10 @@ struct tun_softc *tp; register int error; - error = suser(p); + error = cap_check(NULL, p, CAP_NET_ADMIN, 0); if (error) return (error); + suser_used(p); tp = dev->si_drv1; if (!tp) { Index: sys/net/ppp_tty.c =================================================================== RCS file: /home/ncvs/src/sys/net/ppp_tty.c,v retrieving revision 1.46 diff -u -r1.46 ppp_tty.c --- sys/net/ppp_tty.c 2000/12/21 21:43:45 1.46 +++ sys/net/ppp_tty.c 2001/01/05 17:42:12 @@ -175,8 +175,9 @@ register struct ppp_softc *sc; int error, s; - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + suser_used(p); s = spltty(); @@ -444,8 +445,9 @@ error = 0; switch (cmd) { case PPPIOCSASYNCMAP: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + suser_used(p); sc->sc_asyncmap[0] = *(u_int *)data; break; @@ -454,8 +456,9 @@ break; case PPPIOCSRASYNCMAP: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + suser_used(p); sc->sc_rasyncmap = *(u_int *)data; break; @@ -464,8 +467,9 @@ break; case PPPIOCSXASYNCMAP: - if ((error = suser(p)) != 0) + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) break; + suser_used(p); s = spltty(); bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap)); sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */ Index: sys/net/raw_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/net/raw_usrreq.c,v retrieving revision 1.19 diff -u -r1.19 raw_usrreq.c --- sys/net/raw_usrreq.c 2000/10/29 16:06:43 1.19 +++ sys/net/raw_usrreq.c 2000/11/07 02:45:17 @@ -157,8 +157,9 @@ if (rp == 0) return EINVAL; - if (p && (error = suser(p)) != 0) + if (p && (error = cap_check(NULL, p, CAP_NET_RAW, 0)) != 0) return error; + suser_used(p); return raw_attach(so, proto); } Index: sys/netatalk/at_control.c =================================================================== RCS file: /home/ncvs/src/sys/netatalk/at_control.c,v retrieving revision 1.29 diff -u -r1.29 at_control.c --- sys/netatalk/at_control.c 2000/12/08 21:50:45 1.29 +++ sys/netatalk/at_control.c 2000/12/13 05:38:19 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ struct at_ifaddr *aa0; struct at_ifaddr *aa = 0; struct ifaddr *ifa, *ifa0; + int error; /* * If we have an ifp, then find the matching at_ifaddr if it exists @@ -99,9 +101,10 @@ /* * If we are not superuser, then we don't get to do these ops. */ - if ( suser(p) ) { - return( EPERM ); + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) { + return( error ); } + suser_used(p); sat = satosat( &ifr->ifr_addr ); nr = (struct netrange *)sat->sat_zero; Index: sys/netatalk/ddp_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/netatalk/ddp_usrreq.c,v retrieving revision 1.20 diff -u -r1.20 ddp_usrreq.c --- sys/netatalk/ddp_usrreq.c 2000/12/08 21:50:45 1.20 +++ sys/netatalk/ddp_usrreq.c 2000/12/13 05:38:19 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -253,8 +254,9 @@ return( EINVAL ); } if ( sat->sat_port < ATPORT_RESERVED && - suser(p) ) { + cap_check(NULL, p, CAP_NET_BIND_SERVICE, 0) ) { return( EACCES ); + suser_used(p); } } } else { Index: sys/netatm/atm_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/netatm/atm_usrreq.c,v retrieving revision 1.11 diff -u -r1.11 atm_usrreq.c --- sys/netatm/atm_usrreq.c 2000/12/07 22:19:04 1.11 +++ sys/netatm/atm_usrreq.c 2000/12/13 05:38:20 @@ -192,8 +192,11 @@ struct atmcfgreq *acp = (struct atmcfgreq *)data; struct atm_pif *pip; - if (p && (suser(p) != 0)) - ATM_RETERR(EPERM); + if (p) { + if ((err = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + ATM_RETERR(err); + suser_used(p); + } switch (acp->acr_opcode) { @@ -225,8 +228,11 @@ struct atmaddreq *aap = (struct atmaddreq *)data; Atm_endpoint *epp; - if (p && (suser(p) != 0)) - ATM_RETERR(EPERM); + if (p) { + if ((err = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + ATM_RETERR(err); + suser_used(p); + } switch (aap->aar_opcode) { @@ -275,8 +281,11 @@ struct sigmgr *smp; Atm_endpoint *epp; - if (p && (suser(p) != 0)) - ATM_RETERR(EPERM); + if (p) { + if ((err = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + ATM_RETERR(err); + suser_used(p); + } switch (adp->adr_opcode) { @@ -328,8 +337,11 @@ struct sigmgr *smp; struct ifnet *ifp2; - if (p && (suser(p) != 0)) - ATM_RETERR(EPERM); + if (p) { + if ((err = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + ATM_RETERR(err); + suser_used(p); + } switch (asp->asr_opcode) { Index: sys/netgraph/ng_socket.c =================================================================== RCS file: /home/ncvs/src/sys/netgraph/ng_socket.c,v retrieving revision 1.20 diff -u -r1.20 ng_socket.c --- sys/netgraph/ng_socket.c 2000/12/18 20:03:32 1.20 +++ sys/netgraph/ng_socket.c 2001/01/05 17:42:19 @@ -157,9 +157,11 @@ ngc_attach(struct socket *so, int proto, struct proc *p) { struct ngpcb *const pcbp = sotongpcb(so); + int error; - if (suser(p)) - return (EPERM); + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + return (error); + suser_used(p); if (pcbp != NULL) return (EISCONN); return (ng_attach_cntl(so)); Index: sys/netgraph/ng_tty.c =================================================================== RCS file: /home/ncvs/src/sys/netgraph/ng_tty.c,v retrieving revision 1.16 diff -u -r1.16 ng_tty.c --- sys/netgraph/ng_tty.c 2000/12/18 20:03:32 1.16 +++ sys/netgraph/ng_tty.c 2001/01/05 17:42:19 @@ -195,8 +195,10 @@ int s, error; /* Super-user only */ - if ((error = suser(p))) + /* XXX perhaps this should be CAP_SYS_TTY_CONFIG? */ + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) return (error); + suser_used(p); s = splnet(); (void) spltty(); /* XXX is this necessary? */ Index: sys/netinet/in.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/in.c,v retrieving revision 1.48 diff -u -r1.48 in.c --- sys/netinet/in.c 2000/12/08 21:50:46 1.48 +++ sys/netinet/in.c 2000/12/13 05:38:27 @@ -207,9 +207,12 @@ switch (cmd) { case SIOCSIFPHYADDR: case SIOCDIFPHYADDR: - if (p && - (error = suser(p)) != 0) - return(error); + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, + 0)) != 0) + return(error); + suser_used(p); + } case SIOCGIFPSRCADDR: case SIOCGIFPDSTADDR: return gif_ioctl(ifp, cmd, data); @@ -220,8 +223,11 @@ switch (cmd) { case SIOCALIFADDR: case SIOCDLIFADDR: - if (p && (error = suser(p)) != 0) - return error; + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + return error; + suser_used(p); + } /*fall through*/ case SIOCGLIFADDR: if (!ifp) @@ -276,8 +282,11 @@ case SIOCSIFADDR: case SIOCSIFNETMASK: case SIOCSIFDSTADDR: - if (p && (error = suser(p)) != 0) - return error; + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + return error; + suser_used(p); + } if (ifp == 0) return (EADDRNOTAVAIL); @@ -312,8 +321,11 @@ break; case SIOCSIFBRDADDR: - if (p && (error = suser(p)) != 0) - return error; + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + return error; + suser_used(p); + } /* FALLTHROUGH */ case SIOCGIFADDR: Index: sys/netinet/in_pcb.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.71 diff -u -r1.71 in_pcb.c --- sys/netinet/in_pcb.c 2000/12/27 03:02:29 1.71 +++ sys/netinet/in_pcb.c 2001/01/05 17:42:20 @@ -49,6 +49,7 @@ #include #include #include +#include #include @@ -221,9 +222,12 @@ struct inpcb *t; /* GROSS */ - if (ntohs(lport) < IPPORT_RESERVED && p && - suser_xxx(0, p, PRISON_ROOT)) - return (EACCES); + if (ntohs(lport) < IPPORT_RESERVED && p) { + if (cap_check(NULL, p, CAP_NET_BIND_SERVICE, + PRISON_ROOT)) + return (EACCES); + suser_used(p); + } if (p && p->p_prison) prison = 1; if (so->so_cred->cr_uid != 0 && @@ -283,8 +287,12 @@ last = ipport_hilastauto; lastport = &pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { - if (p && (error = suser_xxx(0, p, PRISON_ROOT))) - return error; + if (p) { + if ((error = cap_check(NULL, p, + CAP_NET_BIND_SERVICE, PRISON_ROOT))) + return error; + suser_used(p); + } first = ipport_lowfirstauto; /* 1023 */ last = ipport_lowlastauto; /* 600 */ lastport = &pcbinfo->lastlow; Index: sys/netinet/ip_divert.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_divert.c,v retrieving revision 1.48 diff -u -r1.48 ip_divert.c --- sys/netinet/ip_divert.c 2000/10/29 16:06:47 1.48 +++ sys/netinet/ip_divert.c 2000/11/07 02:46:01 @@ -344,8 +344,11 @@ inp = sotoinpcb(so); if (inp) panic("div_attach"); - if (p && (error = suser(p)) != 0) - return error; + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_RAW, 0)) != 0) + return error; + suser_used(p); + } error = soreserve(so, div_sendspace, div_recvspace); if (error) Index: sys/netinet/ip_output.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v retrieving revision 1.117 diff -u -r1.117 ip_output.c --- sys/netinet/ip_output.c 2000/12/21 21:44:01 1.117 +++ sys/netinet/ip_output.c 2001/01/05 17:42:21 @@ -1231,8 +1231,14 @@ break; if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */ break; - priv = (sopt->sopt_p != NULL && - suser(sopt->sopt_p) != 0) ? 0 : 1; + if (sopt->sopt_p != NULL) { + if (cap_check(sopt->sopt_p, CAP_NET_ADMIN)) + priv = 0; + else { + priv = 1; + suser_used(sopt->sopt_p); + } + } req = mtod(m, caddr_t); len = m->m_len; optname = sopt->sopt_name; Index: sys/netinet/raw_ip.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.72 diff -u -r1.72 raw_ip.c --- sys/netinet/raw_ip.c 2000/12/21 21:44:02 1.72 +++ sys/netinet/raw_ip.c 2001/01/05 17:42:22 @@ -46,6 +46,7 @@ #include #include #include +#include #include @@ -444,8 +445,11 @@ inp = sotoinpcb(so); if (inp) panic("rip_attach"); - if (p && (error = suser(p)) != 0) - return error; + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_RAW, 0)) != 0) + return error; + suser_used(p); + } error = soreserve(so, rip_sendspace, rip_recvspace); if (error) Index: sys/netinet/tcp_subr.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/tcp_subr.c,v retrieving revision 1.86 diff -u -r1.86 tcp_subr.c --- sys/netinet/tcp_subr.c 2000/12/24 10:57:21 1.86 +++ sys/netinet/tcp_subr.c 2001/01/05 17:42:22 @@ -897,9 +897,11 @@ struct inpcb *inp; int error, s; - error = suser(req->p); + /* XXX Why bother check for privilege here? */ + error = cap_check(NULL, req->p, CAP_SYS_ADMIN, 0); if (error) return (error); + suser_used(req->p); error = SYSCTL_IN(req, addrs, sizeof(addrs)); if (error) return (error); @@ -927,9 +929,11 @@ struct inpcb *inp; int error, s, mapped = 0; - error = suser(req->p); + /* XXX Why bother check for privilege here? */ + error = cap_check(NULL, req->p, CAP_SYS_ADMIN, 0); if (error) return (error); + suser_used(req->p); error = SYSCTL_IN(req, addrs, sizeof(addrs)); if (error) return (error); Index: sys/netinet/udp_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.80 diff -u -r1.80 udp_usrreq.c --- sys/netinet/udp_usrreq.c 2000/12/24 10:57:21 1.80 +++ sys/netinet/udp_usrreq.c 2001/01/05 17:42:22 @@ -610,9 +610,10 @@ struct inpcb *inp; int error, s; - error = suser(req->p); + error = cap_check(NULL, req->p, CAP_SYS_ADMIN, 0); if (error) return (error); + suser_used(req->p); error = SYSCTL_IN(req, addrs, sizeof(addrs)); if (error) return (error); Index: sys/netinet6/in6.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/in6.c,v retrieving revision 1.10 diff -u -r1.10 in6.c --- sys/netinet6/in6.c 2000/07/12 05:20:41 1.10 +++ sys/netinet6/in6.c 2000/09/17 15:14:47 @@ -337,7 +337,7 @@ int privileged; privileged = 0; - if (p == NULL || !suser(p)) + if (p == NULL || !cap_check(NULL, p, CAP_NET_ADMIN, 0)) privileged++; /* @@ -349,6 +349,8 @@ case SIOCSIFPHYADDR_IN6: if (!privileged) return(EPERM); + if (p) + suser_used(p); /*fall through*/ case SIOCGIFPSRCADDR_IN6: case SIOCGIFPDSTADDR_IN6: @@ -373,6 +375,8 @@ case SIOCSIFINFO_FLAGS: if (!privileged) return(EPERM); + if (p) + suser_used(p); /*fall through*/ case SIOCGIFINFO_IN6: case SIOCGDRLST_IN6: @@ -390,6 +394,8 @@ case SIOCSGIFPREFIX_IN6: if (!privileged) return(EPERM); + if (p) + suser_used(p); /*fall through*/ case SIOCGIFPREFIX_IN6: if (ip6_forwarding == 0) @@ -401,6 +407,8 @@ case SIOCSSCOPE6: if (!privileged) return(EPERM); + if (p) + suser_used(p); return(scope6_set(ifp, ifr->ifr_ifru.ifru_scope_id)); break; case SIOCGSCOPE6: @@ -416,6 +424,8 @@ case SIOCDLIFADDR: if (!privileged) return(EPERM); + if (p) + suser_used(p); /*fall through*/ case SIOCGLIFADDR: return in6_lifaddr_ioctl(so, cmd, data, ifp, p); @@ -475,6 +485,8 @@ return(EAFNOSUPPORT); if (!privileged) return(EPERM); + if (p) + suser_used(p); if (ia == NULL) { ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR, M_WAITOK); @@ -553,6 +565,8 @@ if (!privileged) return(EPERM); + if (p) + suser_used(p); if (ia == NULL) return(EADDRNOTAVAIL); /* sanity for overflow - beware unsigned */ Index: sys/netinet6/in6_pcb.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/in6_pcb.c,v retrieving revision 1.13 diff -u -r1.13 in6_pcb.c --- sys/netinet6/in6_pcb.c 2000/07/04 16:35:09 1.13 +++ sys/netinet6/in6_pcb.c 2000/09/17 15:15:16 @@ -177,10 +177,15 @@ struct inpcb *t; /* GROSS */ - if (ntohs(lport) < IPV6PORT_RESERVED && p && - suser_xxx(0, p, PRISON_ROOT)) - return(EACCES); - if (so->so_cred->cr_uid != 0 && + if (ntohs(lport) < IPV6PORT_RESERVED && p) { + if (cap_check(NULL, p, CAP_NET_BIND_SERVICE, + PRISON_ROOT)) + return(EACCES); + suser_used(p); + } + /* XXX setting suser_used() in this check is hard */ + if (cap_check(so->so_cred, NULL, CAP_NET_ADMIN, + PRISON_ROOT) && !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr, lport, Index: sys/netinet6/in6_src.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/in6_src.c,v retrieving revision 1.2 diff -u -r1.2 in6_src.c --- sys/netinet6/in6_src.c 2000/10/29 16:06:48 1.2 +++ sys/netinet6/in6_src.c 2000/11/07 02:46:12 @@ -345,8 +345,12 @@ last = ipport_hilastauto; lastport = &pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { - if (p && (error = suser(p))) - return error; + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_BIND_SERVICE, + 0)) != 0) + return error; + suser_used(p); + } first = ipport_lowfirstauto; /* 1023 */ last = ipport_lowlastauto; /* 600 */ lastport = &pcbinfo->lastlow; Index: sys/netinet6/ip6_input.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.19 diff -u -r1.19 ip6_input.c --- sys/netinet6/ip6_input.c 2000/11/25 07:35:34 1.19 +++ sys/netinet6/ip6_input.c 2000/12/13 05:38:30 @@ -940,7 +940,7 @@ int privileged; privileged = 0; - if (p && !suser(p)) + if (p && !cap_check(NULL, p, CAP_NET_ADMIN, 0)) privileged++; if (in6p->in6p_socket->so_options & SO_TIMESTAMP) { @@ -1005,6 +1005,7 @@ struct ip6_hbh *hbh; int hbhlen; + suser_used(p); #ifndef PULLDOWN_TEST hbh = (struct ip6_hbh *)(ip6 + 1); hbhlen = (hbh->ip6h_len + 1) << 3; @@ -1089,6 +1090,7 @@ */ if (!privileged) break; + suser_used(p); *mp = sbcreatecontrol((caddr_t)ip6e, elen, IPV6_DSTOPTS, Index: sys/netinet6/ip6_output.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/ip6_output.c,v retrieving revision 1.22 diff -u -r1.22 ip6_output.c --- sys/netinet6/ip6_output.c 2000/12/21 21:44:10 1.22 +++ sys/netinet6/ip6_output.c 2001/01/05 17:42:24 @@ -1223,7 +1223,8 @@ } error = optval = 0; - privileged = (p == 0 || suser(p)) ? 0 : 1; + /* XXX Should this be CAP_NET_ADMIN or CAP_NET_RAW? */ + privileged = (p == 0 || cap_check(NULL, p, CAP_NET_ADMIN, 0)) ? 0 : 1; if (level == IPPROTO_IPV6) { switch (op) { @@ -1248,6 +1249,7 @@ error = EPERM; break; } + suser_used(p); /* fall through */ case IPV6_UNICAST_HOPS: case IPV6_PKTINFO: @@ -1388,6 +1390,7 @@ req = mtod(m, caddr_t); len = m->m_len; } + /* XXX can't set suser_used here */ error = ipsec6_set_policy(in6p, optname, req, len, privileged); m_freem(m); @@ -1439,6 +1442,7 @@ error = EPERM; break; } + suser_used(p); /* fall through */ case IPV6_UNICAST_HOPS: case IPV6_PKTINFO: @@ -1614,7 +1618,8 @@ } /* set options specified by user. */ - if (p && !suser(p)) + /* XXX Should this be CAP_NET_ADMIN or CAP_NET_RAW? */ + if (p && !cap_check(NULL, p, CAP_NET_ADMIN, 0)) priv = 1; if ((error = ip6_setpktoptions(m, opt, priv)) != 0) { (void)m_free(m); @@ -1732,11 +1737,12 @@ * all multicast addresses. Only super user is allowed * to do this. */ - if (suser(p)) + if (cap_check(NULL, p, CAP_NET_BIND_SERVICE, 0)) { error = EACCES; break; } + suser_used(p); } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) { error = EINVAL; break; @@ -1839,10 +1845,11 @@ } mreq = mtod(m, struct ipv6_mreq *); if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) { - if (suser(p)) { + if (cap_check(NULL, p, CAP_NET_BIND_SERVICE, 0)) { error = EACCES; break; } + suser_used(p); } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) { error = EINVAL; break; Index: sys/netinet6/raw_ip6.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.10 diff -u -r1.10 raw_ip6.c --- sys/netinet6/raw_ip6.c 2000/12/21 21:44:10 1.10 +++ sys/netinet6/raw_ip6.c 2001/01/05 17:42:24 @@ -525,8 +525,11 @@ inp = sotoinpcb(so); if (inp) panic("rip6_attach"); - if (p && (error = suser(p)) != 0) - return error; + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_RAW, 0)) != 0) + return error; + suser_used(p); + } error = soreserve(so, rip_sendspace, rip_recvspace); if (error) Index: sys/netinet6/udp6_output.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/udp6_output.c,v retrieving revision 1.2 diff -u -r1.2 udp6_output.c --- sys/netinet6/udp6_output.c 2000/10/29 16:06:49 1.2 +++ sys/netinet6/udp6_output.c 2000/11/07 02:46:17 @@ -140,7 +140,8 @@ struct sockaddr_in6 tmp; priv = 0; - if (p && !suser(p)) + /* XXX Should this be CAP_NET_ADMIN or CAP_NET_RAW? */ + if (p && !cap_check(NULL, p, CAP_NET_ADMIN, 0)) priv = 1; if (control) { if ((error = ip6_setpktoptions(control, &opt, priv)) != 0) Index: sys/netinet6/udp6_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/udp6_usrreq.c,v retrieving revision 1.13 diff -u -r1.13 udp6_usrreq.c --- sys/netinet6/udp6_usrreq.c 2000/10/23 07:11:01 1.13 +++ sys/netinet6/udp6_usrreq.c 2000/11/07 02:46:17 @@ -478,9 +478,11 @@ struct inpcb *inp; int error, s; - error = suser(req->p); + /* XXX Should this be CAP_NET_ADMIN or CAP_NET_RAW? */ + error = cap_check(NULL, req->p, CAP_NET_ADMIN, 0); if (error) return (error); + suser_used(req->p); if (req->newlen != sizeof(addrs)) return (EINVAL); Index: sys/netipx/ipx.c =================================================================== RCS file: /home/ncvs/src/sys/netipx/ipx.c,v retrieving revision 1.19 diff -u -r1.19 ipx.c --- sys/netipx/ipx.c 2000/12/08 21:50:49 1.19 +++ sys/netipx/ipx.c 2000/12/13 05:38:32 @@ -108,8 +108,11 @@ return (0); } - if (p && (error = suser(p)) != 0) - return (error); + if (p) { + if ((error = cap_check(NULL, p, CAP_NET_ADMIN, 0)) != 0) + return (error); + suser_used(p); + } switch (cmd) { case SIOCAIFADDR: Index: sys/netipx/ipx_pcb.c =================================================================== RCS file: /home/ncvs/src/sys/netipx/ipx_pcb.c,v retrieving revision 1.20 diff -u -r1.20 ipx_pcb.c --- sys/netipx/ipx_pcb.c 2000/12/08 21:50:49 1.20 +++ sys/netipx/ipx_pcb.c 2000/12/13 05:40:34 @@ -98,9 +98,12 @@ u_short aport = ntohs(lport); int error; - if (aport < IPXPORT_RESERVED && - p != NULL && (error = suser(p)) != 0) - return (error); + if (aport < IPXPORT_RESERVED && p != NULL) { + if ((error = cap_check(NULL, p, CAP_NET_BIND_SERVICE, + 0)) != 0) + return (error); + suser_used(p); + } if (ipx_pcblookup(&zeroipx_addr, lport, 0)) return (EADDRINUSE); } Index: sys/netipx/ipx_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/netipx/ipx_usrreq.c,v retrieving revision 1.27 diff -u -r1.27 ipx_usrreq.c --- sys/netipx/ipx_usrreq.c 2000/10/29 16:06:50 1.27 +++ sys/netipx/ipx_usrreq.c 2000/11/07 02:46:19 @@ -602,8 +602,11 @@ int s; struct ipxpcb *ipxp = sotoipxpcb(so); - if (p != NULL && (error = suser(p)) != 0) - return (error); + if (p != NULL) { + if ((error = cap_check(NULL, p, CAP_NET_RAW, 0)) != 0) + return (error); + suser_used(error); + } s = splnet(); error = ipx_pcballoc(so, &ipxrawpcb, p); splx(s); Index: sys/nfs/nfs_serv.c =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfs_serv.c,v retrieving revision 1.98 diff -u -r1.98 nfs_serv.c --- sys/nfs/nfs_serv.c 2000/12/21 21:44:24 1.98 +++ sys/nfs/nfs_serv.c 2001/01/05 17:42:28 @@ -1788,11 +1788,13 @@ /* * Handle SysV FIFO node special cases. All other * devices require super user to access. + * + * XXX CAP_MKNOD seems to be the closest match. */ if (vap->va_type == VCHR && rdev == 0xffffffff) vap->va_type = VFIFO; if (vap->va_type != VFIFO && - (error = suser_xxx(cred, 0, 0))) { + (error = cap_check(cred, NULL, CAP_MKNOD, 0))) { goto nfsmreply0; } vap->va_rdev = rdev; @@ -2004,7 +2006,10 @@ if (error) NDFREE(&nd, NDF_ONLY_PNBUF); } else { - if (vtyp != VFIFO && (error = suser_xxx(cred, 0, 0))) + /* + * XXX CAP_MKNOD seems to be the closest match? + */ + if (vtyp != VFIFO && (error = cap_check(cred, NULL, CAP_MKNOD, 0))) goto out; nqsrv_getl(nd.ni_dvp, ND_WRITE); Index: sys/nfs/nfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/nfs/nfs_syscalls.c,v retrieving revision 1.64 diff -u -r1.64 nfs_syscalls.c --- sys/nfs/nfs_syscalls.c 2000/12/21 21:44:24 1.64 +++ sys/nfs/nfs_syscalls.c 2001/01/05 17:42:29 @@ -154,10 +154,12 @@ /* * Must be super user + * XXX CAP_SYS_ADMIN seems to be a catch all, is it right? */ - error = suser(p); + error = cap_check(NULL, p, CAP_SYS_ADMIN, 0); if(error) return (error); + suser_used(p); while (nfssvc_sockhead_flag & SLP_INIT) { nfssvc_sockhead_flag |= SLP_WANTINIT; (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0); Index: sys/pccard/pccard.c =================================================================== RCS file: /home/ncvs/src/sys/pccard/pccard.c,v retrieving revision 1.115 diff -u -r1.115 pccard.c --- sys/pccard/pccard.c 2000/10/29 16:29:05 1.115 +++ sys/pccard/pccard.c 2000/11/07 02:46:52 @@ -507,8 +507,9 @@ * At the very least, we only allow root to set the context. */ case PIOCSMEM: - if (suser(p)) - return(EPERM); + if ((err = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + return(err); + suser_used(p); if (slt->state != filled) return(ENXIO); s = ((struct mem_desc *)data)->window; @@ -532,8 +533,9 @@ * Set I/O port context. */ case PIOCSIO: - if (suser(p)) - return(EPERM); + if ((err = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + return(err); + suser_used(p); if (slt->state != filled) return(ENXIO); s = ((struct io_desc *)data)->window; @@ -560,8 +562,9 @@ *(unsigned long *)data = pccard_mem; break; } - if (suser(p)) - return(EPERM); + if ((err = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + return(err); + suser_used(p); /* * Validate the memory by checking it against the I/O * memory range. It must also start on an aligned block size. @@ -589,8 +592,9 @@ * Allocate a driver to this slot. */ case PIOCSDRV: - if (suser(p)) - return(EPERM); + if ((err = cap_check(NULL, p, CAP_SYS_ADMIN, 0)) != 0) + return(err); + suser_used(p); err = allocate_driver(slt, (struct dev_desc *)data); if (!err) pccard_success_beep(); Index: sys/sys/mount.h =================================================================== RCS file: /home/ncvs/src/sys/sys/mount.h,v retrieving revision 1.99 diff -u -r1.99 mount.h --- sys/sys/mount.h 2000/12/04 09:21:05 1.99 +++ sys/sys/mount.h 2000/12/13 05:40:51 @@ -37,6 +37,7 @@ #ifndef _SYS_MOUNT_H_ #define _SYS_MOUNT_H_ +#include #include #include #ifdef _KERNEL Index: sys/sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.137 diff -u -r1.137 proc.h --- sys/sys/proc.h 2000/12/23 19:43:10 1.137 +++ sys/sys/proc.h 2001/01/05 17:42:40 @@ -52,6 +52,7 @@ #ifndef _KERNEL #include /* For structs itimerval, timeval. */ #endif +#include #include /* @@ -333,6 +334,7 @@ uid_t p_svuid; /* Saved effective user id. */ gid_t p_rgid; /* Real group id. */ gid_t p_svgid; /* Saved effective group id. */ + struct cap p_cap; /* Capabilities */ int p_refcnt; /* Number of references. */ struct uidinfo *p_uidinfo; /* Per uid resource consumption. */ }; Index: sys/sys/sysctl.h =================================================================== RCS file: /home/ncvs/src/sys/sys/sysctl.h,v retrieving revision 1.88 diff -u -r1.88 sysctl.h --- sys/sys/sysctl.h 2001/01/05 07:00:45 1.88 +++ sys/sys/sysctl.h 2001/01/05 17:42:41 @@ -328,7 +328,7 @@ #define KERN_PS_STRINGS 32 /* int: address of PS_STRINGS */ #define KERN_USRSTACK 33 /* int: address of USRSTACK */ #define KERN_LOGSIGEXIT 34 /* int: do we log sigexit procs? */ -#define KERN_MAXID 35 /* number of valid kern ids */ +#define KERN_MAXID 35 /* number of valid kern ids */ #define CTL_KERN_NAMES { \ { 0, 0 }, \ Index: sys/sys/systm.h =================================================================== RCS file: /home/ncvs/src/sys/sys/systm.h,v retrieving revision 1.131 diff -u -r1.131 systm.h --- sys/sys/systm.h 2000/12/20 21:50:34 1.131 +++ sys/sys/systm.h 2001/01/05 17:42:41 @@ -47,6 +47,7 @@ #include extern int securelevel; /* system security level (see init(8)) */ +extern int suser_permitted; /* suser_xxx() is permitted to return 0 */ extern int cold; /* nonzero if we are doing a cold boot */ extern const char *panicstr; /* panic message */ Index: sys/sys/ucred.h =================================================================== RCS file: /home/ncvs/src/sys/sys/ucred.h,v retrieving revision 1.19 diff -u -r1.19 ucred.h --- sys/sys/ucred.h 2000/11/30 19:09:47 1.19 +++ sys/sys/ucred.h 2000/12/13 05:40:53 @@ -50,6 +50,7 @@ uid_t cr_uid; /* effective user id */ short cr_ngroups; /* number of groups */ gid_t cr_groups[NGROUPS]; /* groups */ + struct cap cr_cap; /* capabilities */ struct uidinfo *cr_uidinfo; /* per uid resource consumption */ struct mtx cr_mtx; /* protect refcount */ }; Index: sys/sys/user.h =================================================================== RCS file: /home/ncvs/src/sys/sys/user.h,v retrieving revision 1.26 diff -u -r1.26 user.h --- sys/sys/user.h 2000/12/12 07:25:54 1.26 +++ sys/sys/user.h 2000/12/13 05:40:53 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include Index: sys/sys/vnode.h =================================================================== RCS file: /home/ncvs/src/sys/sys/vnode.h,v retrieving revision 1.134 diff -u -r1.134 vnode.h --- sys/sys/vnode.h 2000/12/26 19:41:37 1.134 +++ sys/sys/vnode.h 2001/01/05 17:42:42 @@ -532,6 +532,7 @@ struct proc; struct stat; struct nstat; +struct cap; struct ucred; struct uio; struct vattr; Index: sys/ufs/ufs/ufs_extattr.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_extattr.c,v retrieving revision 1.15 diff -u -r1.15 ufs_extattr.c --- sys/ufs/ufs/ufs_extattr.c 2000/10/09 20:04:39 1.15 +++ sys/ufs/ufs/ufs_extattr.c 2000/10/11 17:49:26 @@ -367,8 +367,9 @@ * Processes with privilege, but in jail, are not allowed to * configure extended attributes. */ - if ((error = suser_xxx(p->p_cred->pc_ucred, p, 0))) + if ((error = cap_check(p->p_cred->pc_ucred, p, CAP_SYS_ADMIN, 0))) return (error); + suser_used(p); switch(cmd) { case UFS_EXTATTR_CMD_START: @@ -424,13 +425,16 @@ ufs_extattr_credcheck(struct vnode *vp, struct ufs_extattr_list_entry *uele, struct ucred *cred, struct proc *p, int access) { - int system_namespace; + int system_namespace, error; system_namespace = (strlen(uele->uele_attrname) >= 1 && uele->uele_attrname[0] == '$'); /* - * Kernel-invoked always succeeds + * Kernel-invoked always succeeds. + * + * XXX: Is this correct? Might be appropriate to check also + * whether the inode is immutable, et al. */ if (cred == NULL) return (0); @@ -442,9 +446,12 @@ * XXX What capability should apply here? * Probably CAP_SYS_SETFFLAG. */ - if (system_namespace) - return (suser_xxx(cred, p, 0)); - else + if (system_namespace) { + if ((error = cap_check(cred, p, CAP_SYS_ADMIN, 0))) + return (error); + suser_used(p); + return (0); + } else return (VOP_ACCESS(vp, access, cred, p)); } Index: sys/ufs/ufs/ufs_readwrite.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_readwrite.c,v retrieving revision 1.73 diff -u -r1.73 ufs_readwrite.c --- sys/ufs/ufs/ufs_readwrite.c 2000/12/26 19:41:37 1.73 +++ sys/ufs/ufs/ufs_readwrite.c 2001/01/05 17:42:45 @@ -530,7 +530,7 @@ * tampering. */ if (resid > uio->uio_resid && ap->a_cred && - suser_xxx(ap->a_cred, NULL, PRISON_ROOT)) + cap_check(ap->a_cred, NULL, CAP_FSETID, PRISON_ROOT)) ip->i_mode &= ~(ISUID | ISGID); if (resid > uio->uio_resid) VN_KNOTE(vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0)); Index: sys/ufs/ufs/ufs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_vfsops.c,v retrieving revision 1.20 diff -u -r1.20 ufs_vfsops.c --- sys/ufs/ufs/ufs_vfsops.c 2000/10/30 20:37:19 1.20 +++ sys/ufs/ufs/ufs_vfsops.c 2000/11/07 02:47:26 @@ -103,7 +103,7 @@ #ifndef QUOTA return (EOPNOTSUPP); #else - int cmd, type, error; + int cmd, type, error, privilege_used = 0; if (uid == -1) uid = p->p_cred->p_ruid; @@ -117,8 +117,9 @@ break; /* fall through */ default: - if ((error = suser_xxx(0, p, PRISON_ROOT)) != 0) + if ((error = cap_check(NULL, p, CAP_SYS_ADMIN, PRISON_ROOT))) return (error); + privilege_used = 1; } type = cmds & SUBCMDMASK; @@ -158,6 +159,8 @@ break; } vfs_unbusy(mp, p); + if (error == 0 && privilege_used) + suser_used(p); return (error); #endif } Index: sys/ufs/ufs/ufs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/ufs/ufs_vnops.c,v retrieving revision 1.154 diff -u -r1.154 ufs_vnops.c --- sys/ufs/ufs/ufs_vnops.c 2000/11/04 08:10:56 1.154 +++ sys/ufs/ufs/ufs_vnops.c 2001/01/07 17:22:45 @@ -58,6 +58,7 @@ #include #include #include +#include #include @@ -303,9 +304,7 @@ struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); mode_t mode = ap->a_mode; -#ifdef QUOTA - int error; -#endif + int error, privused; /* * Disallow write attempts on read-only file systems; @@ -332,9 +331,16 @@ /* If immutable bit set, nobody gets to write it. */ if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) return (EPERM); + + privused = 0; + error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, + ap->a_mode, ap->a_cred, &privused); + if (error) + return (error); + if (privused) + suser_used(ap->a_p); - return (vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, - ap->a_mode, ap->a_cred, NULL)); + return (0); } /* ARGSUSED */ @@ -396,7 +402,7 @@ struct inode *ip = VTOI(vp); struct ucred *cred = ap->a_cred; struct proc *p = ap->a_p; - int error; + int error, privilege_used = 0; /* * Check for unsettable attributes. @@ -413,16 +419,21 @@ /* * Callers may only modify the file flags on objects they * have VADMIN rights for. + * + * XXX: This abstracts use of privilege, and may not + * account for it properly. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) return (error); + /* * Unprivileged processes and privileged processes in * jail() are not permitted to set system flags. * Privileged processes not in jail() may only set system * flags if the securelevel <= 0. */ - if (!suser_xxx(cred, NULL, 0)) { + if (!cap_check(cred, p, CAP_SYS_SETFFLAG, 0)) { + privilege_used = 1; if ((ip->i_flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) && securelevel > 0) @@ -443,8 +454,11 @@ ip->i_flags |= (vap->va_flags & UF_SETTABLE); } ip->i_flag |= IN_CHANGE; - if (vap->va_flags & (IMMUTABLE | APPEND)) + if (vap->va_flags & (IMMUTABLE | APPEND)) { + if (privilege_used) + suser_used(p); return (0); + } } if (ip->i_flags & (IMMUTABLE | APPEND)) return (EPERM); @@ -495,8 +509,12 @@ */ if ((error = VOP_ACCESS(vp, VADMIN, cred, p)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(vp, VWRITE, cred, p)))) - return (error); + (error = VOP_ACCESS(vp, VWRITE, cred, p)))) { + if ((error = cap_check(cred, p, CAP_FOWNER, + PRISON_ROOT)) != 0) + return (error); + privilege_used = 1; + } if (vap->va_atime.tv_sec != VNOVAL) ip->i_flag |= IN_ACCESS; if (vap->va_mtime.tv_sec != VNOVAL) @@ -524,6 +542,8 @@ error = ufs_chmod(vp, (int)vap->va_mode, cred, p); } VN_KNOTE(vp, NOTE_ATTRIB); + if (error == 0 && privilege_used) + suser_used(p); return (error); } @@ -539,28 +559,55 @@ struct proc *p; { register struct inode *ip = VTOI(vp); - int error; + int error, privilege_used = 0; /* - * To modify the permissions on a file, must possess VADMIN - * for that file. + * In general, to modify the permissions on a file, you must posess + * VADMIN for the file (by virtue of owning the file, or having + * privilege such as super-user or CAP_FOWNER). However, if the + * modification involves either of the setugid bits being in the + * new mode, additional checks are performed: for setuid, the + * effective uid of the process must match the inode uid or + * superuser/CAP_FSETID must be held, and for setgid, one of the + * groups of the process must match that of the file, or supuser/ + * CAP_FSETID must be held. + * + * XXX: This diverges slightly from POSIX.1e D17 by tightening the + * requirements: both CAP_FOWNER and CAP_FSETID must be held to + * update sugid bits, but this divergence is portable to at least + * Linux, and substantially simplifies (and makes sensical) the + * interactions. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, p))) return (error); /* - * 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. - */ - if (suser_xxx(cred, NULL, PRISON_ROOT)) { - if (vp->v_type != VDIR && (mode & S_ISTXT)) - return (EFTYPE); - if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) - return (EPERM); + * Traditionally, privilege has allowed a process to set the + * sticky bit on non-directories. However, this has no meaning, + * so is now disabled. + */ + if (vp->v_type != VDIR && (mode & S_ISTXT)) + return(EFTYPE); + /* + * Privilege is required to set the setuid or setgid bits if the + * process doesn't already have access to the respective uid + * or gid in its credentials. + * XXX: Check that uid/gid checks here fit abstractions. + */ + if ((ip->i_uid != cred->cr_uid) && (mode & ISUID)) { + if ((error = cap_check(cred, p, CAP_FSETID, PRISON_ROOT)) != 0) + return (error); + privilege_used = 1; + } + if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) { + if ((error = cap_check(cred, p, CAP_FSETID, PRISON_ROOT)) != 0) + return (error); + privilege_used = 1; } ip->i_mode &= ~ALLPERMS; ip->i_mode |= (mode & ALLPERMS); ip->i_flag |= IN_CHANGE; + if (privilege_used) + suser_used(p); return (0); } @@ -579,7 +626,7 @@ register struct inode *ip = VTOI(vp); uid_t ouid; gid_t ogid; - int error = 0; + int error = 0, privilege_used = 0; #ifdef QUOTA register int i; long change; @@ -600,10 +647,12 @@ * 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_xxx(cred, p, PRISON_ROOT))) - return (error); + if (uid != ip->i_uid || + (gid != ip->i_gid && !groupmember(gid, cred))) { + if (error = cap_check(cred, p, CAP_CHOWN, PRISON_ROOT))) + return (error); + privilege_used = 1; + } ogid = ip->i_gid; ouid = ip->i_uid; #ifdef QUOTA @@ -669,8 +718,14 @@ panic("ufs_chown: lost quota"); #endif /* QUOTA */ ip->i_flag |= IN_CHANGE; - if (suser_xxx(cred, NULL, PRISON_ROOT) && (ouid != uid || ogid != gid)) - ip->i_mode &= ~(ISUID | ISGID); + if (ouid != uid || ogid != gid) { + if (cap_check(cred, p, CAP_FSETID, PRISON_ROOT) != 0) + ip->i_mode &= ~(ISUID | ISGID); + else + privilege_used = 1; + } + if (privilege_used) + suser_used(p); return (0); } @@ -866,7 +921,7 @@ struct inode *ip, *xp, *dp; struct direct newdir; int doingdirectory = 0, oldparent = 0, newparent = 0; - int error = 0, ioflag; + int error = 0, ioflag, privilege_used = 0; #ifdef DIAGNOSTIC if ((tcnp->cn_flags & HASBUF) == 0 || @@ -1104,6 +1159,14 @@ * must possess VADMIN for the parent directory, or the * destination of the rename. This implements append-only * directories. + * + * XXX: In TRIX, CAP_DAC_WRITE appears also to override the + * sticky bit limitations -- should we do the same? Such a + * check would read: + * (cap_check(tcnp->cn_cred, NULL, CAP_DAC_WRITE, + * PRISON_ROOT)) + * XXX: Since the introduction of VADMIN, the ability to + * set privilege_used here has been lost. */ if ((dp->i_mode & S_ISTXT) && VOP_ACCESS(tdvp, VADMIN, tcnp->cn_cred, p) && @@ -1197,6 +1260,8 @@ if (doingdirectory) panic("ufs_rename: lost dir entry"); vrele(ap->a_fvp); + if (privilege_used) + suser_used(p); return (0); } /* @@ -1232,6 +1297,8 @@ if (xp) vput(fvp); vrele(ap->a_fvp); + if (error == 0 && privilege_used) + suser_used(p); return (error); bad: @@ -1251,6 +1318,8 @@ vput(fvp); } else vrele(fvp); + if (error == 0 && privilege_used) + suser_used(p); return (error); } @@ -2055,7 +2124,7 @@ register struct inode *ip, *pdir; struct direct newdir; struct vnode *tvp; - int error; + int error, privilege_used = 0; pdir = VTOI(dvp); #ifdef DIAGNOSTIC @@ -2133,9 +2202,12 @@ ip->i_nlink = 1; if (DOINGSOFTDEP(tvp)) softdep_change_linkcnt(ip); - if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && - suser_xxx(cnp->cn_cred, NULL, PRISON_ROOT)) - ip->i_mode &= ~ISGID; + if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred)) { + if (cap_check(cnp->cn_cred, NULL, CAP_FSETID, PRISON_ROOT)) + ip->i_mode &= ~ISGID; + else + privilege_used = 1; + } if (cnp->cn_flags & ISWHITEOUT) ip->i_flags |= UF_OPAQUE; @@ -2151,6 +2223,13 @@ if (error) goto bad; *vpp = tvp; +/* + XXX struct proc is not passed in, so we can't mark as having used + privilege + + if (privilege_used) + suser_used(p); +*/ return (0); bad: Index: sys/vm/vm_mmap.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_mmap.c,v retrieving revision 1.117 diff -u -r1.117 vm_mmap.c --- sys/vm/vm_mmap.c 2000/11/18 21:01:04 1.117 +++ sys/vm/vm_mmap.c 2000/12/13 05:40:58 @@ -335,8 +335,11 @@ */ if (securelevel >= 1) disablexworkaround = 1; - else - disablexworkaround = suser(p); + else { + /* XXX How to suser_used() here? */ + disablexworkaround = cap_check(NULL, p, + CAP_SYS_RAWIO, 0); + } if (vp->v_type == VCHR && disablexworkaround && (flags & (MAP_PRIVATE|MAP_COPY))) { error = EINVAL; Index: sys/vm/vm_swap.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_swap.c,v retrieving revision 1.106 diff -u -r1.106 vm_swap.c --- sys/vm/vm_swap.c 2000/12/13 10:01:00 1.106 +++ sys/vm/vm_swap.c 2001/01/05 17:42:49 @@ -191,9 +191,10 @@ struct nameidata nd; int error; - error = suser(p); + error = cap_check(NULL, p, CAP_SYS_ADMIN, 0); if (error) return (error); + suser_used(p); /* * Swap metadata may not fit in the KVM if we have physical Index: usr.bin/find/function.c =================================================================== RCS file: /home/ncvs/src/usr.bin/find/function.c,v retrieving revision 1.27 diff -u -r1.27 function.c --- usr.bin/find/function.c 2000/07/28 20:02:42 1.27 +++ usr.bin/find/function.c 2000/08/07 00:56:16 @@ -44,6 +44,7 @@ #endif /* not lint */ #include +#include #include #include #include Index: usr.bin/kdump/Makefile =================================================================== RCS file: /home/ncvs/src/usr.bin/kdump/Makefile,v retrieving revision 1.7 diff -u -r1.7 Makefile --- usr.bin/kdump/Makefile 2000/09/14 18:52:48 1.7 +++ usr.bin/kdump/Makefile 2000/09/16 03:39:24 @@ -2,7 +2,7 @@ # $FreeBSD: src/usr.bin/kdump/Makefile,v 1.7 2000/09/14 18:52:48 jkh Exp $ PROG= kdump -CFLAGS+=-I${.CURDIR}/../ktrace -I${.CURDIR}/../.. +CFLAGS+=-I${.CURDIR}/../ktrace -I${.CURDIR}/../.. -I${.CURDIR}/../../sys SRCS= kdump.c ioctl.c subr.c .PATH: ${.CURDIR}/../ktrace CLEANFILES+=ioctl.c Index: usr.sbin/inetd/builtins.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/inetd/builtins.c,v retrieving revision 1.29 diff -u -r1.29 builtins.c --- usr.sbin/inetd/builtins.c 2000/12/05 13:56:01 1.29 +++ usr.sbin/inetd/builtins.c 2000/12/13 05:43:44 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include Index: usr.sbin/pstat/pstat.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pstat/pstat.c,v retrieving revision 1.52 diff -u -r1.52 pstat.c --- usr.sbin/pstat/pstat.c 2000/12/30 15:41:40 1.52 +++ usr.sbin/pstat/pstat.c 2001/01/05 17:49:03 @@ -48,6 +48,7 @@ #include #include #include +#include #include #define _KERNEL #include Index: usr.sbin/rpc.umntall/rpc.umntall.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/rpc.umntall/rpc.umntall.c,v retrieving revision 1.3 diff -u -r1.3 rpc.umntall.c --- usr.sbin/rpc.umntall/rpc.umntall.c 2000/01/15 14:28:14 1.3 +++ usr.sbin/rpc.umntall/rpc.umntall.c 2000/04/12 20:10:46 @@ -31,6 +31,7 @@ #endif /* not lint */ #include +#include #include #include