예제 #1
0
파일: mem.c 프로젝트: UnitedMarsupials/kame
static int
mmopen(dev_t dev, int flags, int fmt, struct thread *td)
{
	int error;

	switch (minor(dev)) {
	case 0:
	case 1:
		if (flags & FWRITE) {
			error = securelevel_gt(td->td_ucred, 0);
			if (error != 0)
				return (error);
		}
		break;
	case 14:
		error = suser(td);
		if (error != 0)
			return (error);
		error = securelevel_gt(td->td_ucred, 0);
		if (error != 0)
			return (error);
		td->td_frame->tf_rflags |= PSL_IOPL;
		break;
	}
	return (0);
}
예제 #2
0
/*
 * Lookup and potentially load the specified firmware image.
 * If the firmware is not found in the registry, try to load a kernel
 * module named as the image name.
 * If the firmware is located, a reference is returned. The caller must
 * release this reference for the image to be eligible for removal/unload.
 */
const struct firmware *
firmware_get(const char *imagename)
{
	struct task fwload_task;
	struct thread *td;
	struct priv_fw *fp;

	mtx_lock(&firmware_mtx);
	fp = lookup(imagename, NULL);
	if (fp != NULL)
		goto found;
	/*
	 * Image not present, try to load the module holding it.
	 */
	td = curthread;
	if (priv_check(td, PRIV_FIRMWARE_LOAD) != 0 ||
	    securelevel_gt(td->td_ucred, 0) != 0) {
		mtx_unlock(&firmware_mtx);
		printf("%s: insufficient privileges to "
		    "load firmware image %s\n", __func__, imagename);
		return NULL;
	}
	/* 
	 * Defer load to a thread with known context.  linker_reference_module
	 * may do filesystem i/o which requires root & current dirs, etc.
	 * Also we must not hold any mtx's over this call which is problematic.
	 */
	if (!cold) {
		TASK_INIT(&fwload_task, 0, loadimage, __DECONST(void *,
		    imagename));
		taskqueue_enqueue(firmware_tq, &fwload_task);
		msleep(__DECONST(void *, imagename), &firmware_mtx, 0,
		    "fwload", 0);
	}
예제 #3
0
파일: randomdev.c 프로젝트: MarginC/kame
/* ARGSUSED */
static int
random_close(dev_t dev __unused, int flags, int fmt __unused, struct thread *td)
{
	if (flags & FWRITE) {
		if (!(suser(td) ||
		    securelevel_gt(td->td_ucred, 0)))
			random_reseed();
	}
	return 0;
}
예제 #4
0
static int
pci_open(struct dev_open_args *ap)
{
#if 0
	int error;
	if (oflags & FWRITE) {
		error = securelevel_gt(td->td_ucred, 0);
		if (error)
			return (error);
	}
#endif
	return (0);
}
예제 #5
0
static int
pci_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
	int error;

	if (oflags & FWRITE) {
		error = securelevel_gt(td->td_ucred, 0);
		if (error)
			return (error);
	}

	return (0);
}
예제 #6
0
파일: randomdev.c 프로젝트: MarginC/kame
/* ARGSUSED */
static int
random_open(dev_t dev __unused, int flags, int fmt __unused, struct thread *td)
{
	int error;

	if (flags & FWRITE) {
		error = suser(td);
		if (error)
			return (error);
		error = securelevel_gt(td->td_ucred, 0);
		if (error)
			return (error);
	}
	return 0;
}
예제 #7
0
int
linux_iopl(struct thread *td, struct linux_iopl_args *args)
{
    int error;

    LINUX_CTR(iopl);

    if (args->level > 3)
        return (EINVAL);
    if ((error = priv_check(td, PRIV_IO)) != 0)
        return (error);
    if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
        return (error);
    td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
                              (args->level * (PSL_IOPL / 3));

    return (0);
}
예제 #8
0
/*
 * Set attribute vnode op. called from several syscalls
 */
static int
ext2_setattr(struct vop_setattr_args *ap)
{
	struct vattr *vap = ap->a_vap;
	struct vnode *vp = ap->a_vp;
	struct inode *ip = VTOI(vp);
	struct ucred *cred = ap->a_cred;
	struct thread *td = curthread;
	int error;

	/*
	 * Check for unsettable attributes.
	 */
	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
		return (EINVAL);
	}
	if (vap->va_flags != VNOVAL) {
		/* Disallow flags not supported by ext2fs. */
		if(vap->va_flags & ~(SF_APPEND | SF_IMMUTABLE | UF_NODUMP))
			return (EOPNOTSUPP);

		if (vp->v_mount->mnt_flag & MNT_RDONLY)
			return (EROFS);
		/*
		 * Callers may only modify the file flags on objects they
		 * have VADMIN rights for.
		 */
		if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
			return (error);
		/*
		 * Unprivileged processes and privileged processes in
		 * jail() are not permitted to unset system flags, or
		 * modify flags if any system flags are set.
		 * Privileged non-jail processes may not modify system flags
		 * if securelevel > 0 and any existing system flags are set.
		 */
		if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
			if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) {
				error = securelevel_gt(cred, 0);
				if (error)
					return (error);
			}
		} else {
			if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND) ||
			    ((vap->va_flags ^ ip->i_flags) & SF_SETTABLE))
				return (EPERM);
		}
		ip->i_flags = vap->va_flags;
		ip->i_flag |= IN_CHANGE;
		if (ip->i_flags & (IMMUTABLE | APPEND))
			return (0);
	}
	if (ip->i_flags & (IMMUTABLE | APPEND))
		return (EPERM);
	/*
	 * Go through the fields and update iff not VNOVAL.
	 */
	if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY)
			return (EROFS);
		if ((error = ext2_chown(vp, vap->va_uid, vap->va_gid, cred,
		    td)) != 0)
			return (error);
	}
	if (vap->va_size != VNOVAL) {
		/*
		 * Disallow write attempts on read-only file systems;
		 * unless the file is a socket, fifo, or a block or
		 * character device resident on the file system.
		 */
		switch (vp->v_type) {
		case VDIR:
			return (EISDIR);
		case VLNK:
		case VREG:
			if (vp->v_mount->mnt_flag & MNT_RDONLY)
				return (EROFS);
			break;
		default:
			break;
		}
		if ((error = ext2_truncate(vp, vap->va_size, 0, cred, td)) != 0)
			return (error);
	}
	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY)
			return (EROFS);
		/*
		 * From utimes(2):
		 * If times is NULL, ... The caller must be the owner of
		 * the file, have permission to write the file, or be the
		 * super-user.
		 * If times is non-NULL, ... The caller must be the owner of
		 * the file or be the super-user.
		 */
		if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) &&
		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
		    (error = VOP_ACCESS(vp, VWRITE, cred, td))))
			return (error);
		if (vap->va_atime.tv_sec != VNOVAL)
			ip->i_flag |= IN_ACCESS;
		if (vap->va_mtime.tv_sec != VNOVAL)
			ip->i_flag |= IN_CHANGE | IN_UPDATE;
		ext2_itimes(vp);
		if (vap->va_atime.tv_sec != VNOVAL) {
			ip->i_atime = vap->va_atime.tv_sec;
			ip->i_atimensec = vap->va_atime.tv_nsec;
		}
		if (vap->va_mtime.tv_sec != VNOVAL) {
			ip->i_mtime = vap->va_mtime.tv_sec;
			ip->i_mtimensec = vap->va_mtime.tv_nsec;
		}
		ip->i_birthtime = vap->va_birthtime.tv_sec;
		ip->i_birthnsec = vap->va_birthtime.tv_nsec;
		error = ext2_update(vp, 0);
		if (error)
			return (error);
	}
	error = 0;
	if (vap->va_mode != (mode_t)VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY)
			return (EROFS);
		error = ext2_chmod(vp, (int)vap->va_mode, cred, td);
	}
	return (error);
}
예제 #9
0
static int
sysctl_control(SYSCTL_HANDLER_ARGS)
{
	secadm_command_t cmd;
	secadm_reply_t reply;
	int err;

	if (!(req->newptr) || (req->newlen != sizeof(secadm_command_t)))
		return (EINVAL);

	if (!(req->oldptr) || (req->oldlen) != sizeof(secadm_reply_t))
		return (EINVAL);

	err = SYSCTL_IN(req, &cmd, sizeof(secadm_command_t));
	if (err)
		return (err);

	/* Access control comes first */
	switch (cmd.sc_type) {
	case secadm_flush_rules:
	case secadm_set_rules:
		/* XXX Should we cache the ucred for local use in the
		 * sysctl lifecycle? */
		// XXXOP LOCKING
		if (req->td->td_ucred->cr_uid != 0) {
			printf("[SECADM] Disallowed command: 0x%x by uid: %d\n",
			    cmd.sc_type, req->td->td_ucred->cr_uid);
			return (EPERM);
		}

		// XXXOP LOCKING
		if (securelevel_gt(req->td->td_ucred, 0)) {
			printf("[SECADM] Disallowed command: 0x%x by uid: %d\n",
			    cmd.sc_type, req->td->td_ucred->cr_uid);
			return (EPERM);
		}
		break;
	default:
		break;
	}

	/* XXX We should relax this check once we get stable releases. */
	if (cmd.sc_version < SECADM_VERSION)
		return (EINVAL);

	memset(&reply, 0x00, sizeof(reply));
	if ((err = copyin(req->oldptr, &reply, sizeof(reply))))
		return (err);

	reply.sr_version = SECADM_VERSION;
	reply.sr_id = cmd.sc_id;

	switch (cmd.sc_type) {
	case  secadm_get_version:
		if (cmd.sc_bufsize < sizeof(unsigned long))
			return (EINVAL);

		handle_version_command(&cmd, &reply);
		break;
	case secadm_set_rules:
		if (cmd.sc_size != sizeof(secadm_rule_t))
			return (EINVAL);

		handle_add_rule(req->td, &cmd, &reply);
		break;
	case secadm_flush_rules:
		flush_rules(req->td);
		break;
	case secadm_get_rule_size:
		handle_get_rule_size(req->td, &cmd, &reply);
		break;
	case secadm_get_num_rules:
		get_num_rules(req->td, &cmd, &reply);
		break;
	case secadm_get_rule:
		handle_get_rule(req->td, &cmd, &reply);
		break;
	case secadm_get_rules:
	case secadm_get_admins:
	case secadm_set_admins:
	case secadm_get_views:
	case secadm_set_views:
		return (ENOTSUP);
	default:
		// XXXOP LOCKING
		printf("[SECADM] Unknown command: 0x%x by uid: %d\n",
		    cmd.sc_type, req->td->td_ucred->cr_uid);
		return (EINVAL);
	}

	err = SYSCTL_OUT(req, &reply, sizeof(secadm_reply_t));
	return (err);
}