/*ARGSUSED*/ int consioctl(__unused dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { dev_t device; boolean_t funnel_state; int error; funnel_state = thread_funnel_set(kernel_flock, TRUE); if (constty) device = constty->t_dev; else device = cons.t_dev; /* * Superuser can always use this to wrest control of console * output from the "virtual" console. */ if ((unsigned int)cmd == TIOCCONS && constty) { error = proc_suser(p); if (error) { goto out; } constty = NULL; error = 0; goto out; } error = (*cdevsw[major(device)].d_ioctl)(device, cmd, addr, flag, p); out: thread_funnel_set(kernel_flock, funnel_state); return(error); }
/* * cdevsw interface to km driver. */ int kmopen(dev_t dev, int flag, __unused int devtype, struct proc *pp) { int unit; struct tty *tp; struct winsize *wp; int ret; unit = minor(dev); if(unit >= 1) return (ENXIO); tp = (struct tty *)&cons; tp->t_oproc = kmstart; tp->t_param = NULL; tp->t_dev = dev; if ( !(tp->t_state & TS_ISOPEN) ) { tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = (CREAD | CS8 | CLOCAL); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; termioschars(&tp->t_termios); ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) && proc_suser(pp)) return EBUSY; tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is on. */ ret = ((*linesw[tp->t_line].l_open)(dev, tp)); { PE_Video video; wp = &tp->t_winsize; /* Magic numbers. These are CHARWIDTH and CHARHEIGHT * from osfmk/ppc/POWERMAC/video_console.c */ wp->ws_xpixel = 8; wp->ws_ypixel = 16; if (flag & O_POPUP) PE_initialize_console(0, kPETextScreen); bzero(&video, sizeof(video)); PE_current_console(&video); if( video.v_width != 0 && video.v_height != 0 ) { wp->ws_col = video.v_width / wp->ws_xpixel; wp->ws_row = video.v_height / wp->ws_ypixel; } else { wp->ws_col = 100; wp->ws_row = 36; } } return ret; }
/* * afs_suser() returns true if the caller is superuser, false otherwise. * * Note that it must NOT set errno. */ int afs_suser(void *credp) { int error; struct proc *p = current_proc(); #ifdef AFS_DARWIN80_ENV if ((error = proc_suser(p)) == 0) { return (1); } return (0); #else if ((error = suser(p->p_ucred, &p->p_acflag)) == 0) { return (1); } return (0); #endif }
int cnioctl(__unused dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { dev = cndev(); /* * XXX This check prevents the cons.c code from being shared between * XXX all architectures; it is probably not needed on ARM, either, * XXX but I have no test platforms or ability to run a kernel. * * Superuser can always use this to wrest control of console * output from the "virtual" console. */ if ((unsigned) cmd == TIOCCONS && constty) { int error = proc_suser(p); if (error) return (error); constty = NULL; return (0); } return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, addr, flag, p)); }
/* ARGSUSED */ static int vnioctl(dev_t dev, u_long cmd, caddr_t data, __unused int flag, proc_t p, int is_char) { struct vn_softc *vn; struct vn_ioctl_64 *viop; int error; u_int32_t *f; u_int64_t * o; int unit; struct vfsioattr ioattr; struct vn_ioctl_64 user_vnio; struct vfs_context context; unit = vnunit(dev); if (vnunit(dev) >= NVNDEVICE) { return (ENXIO); } vn = vn_table + unit; error = proc_suser(p); if (error) { goto done; } context.vc_thread = current_thread(); context.vc_ucred = vn->sc_cred; viop = (struct vn_ioctl_64 *)data; f = (u_int32_t *)data; o = (u_int64_t *)data; switch (cmd) { #ifdef __LP64__ case VNIOCDETACH32: case VNIOCDETACH: #else case VNIOCDETACH: case VNIOCDETACH64: #endif case DKIOCGETBLOCKSIZE: case DKIOCSETBLOCKSIZE: case DKIOCGETMAXBLOCKCOUNTREAD: case DKIOCGETMAXBLOCKCOUNTWRITE: case DKIOCGETMAXSEGMENTCOUNTREAD: case DKIOCGETMAXSEGMENTCOUNTWRITE: case DKIOCGETMAXSEGMENTBYTECOUNTREAD: case DKIOCGETMAXSEGMENTBYTECOUNTWRITE: case DKIOCGETBLOCKCOUNT: case DKIOCGETBLOCKCOUNT32: if ((vn->sc_flags & VNF_INITED) == 0) { error = ENXIO; goto done; } break; default: break; } if (vn->sc_vp != NULL) vfs_ioattr(vnode_mount(vn->sc_vp), &ioattr); else bzero(&ioattr, sizeof(ioattr)); switch (cmd) { case DKIOCISVIRTUAL: *f = 1; break; case DKIOCGETMAXBLOCKCOUNTREAD: *o = ioattr.io_maxreadcnt / vn->sc_secsize; break; case DKIOCGETMAXBLOCKCOUNTWRITE: *o = ioattr.io_maxwritecnt / vn->sc_secsize; break; case DKIOCGETMAXBYTECOUNTREAD: *o = ioattr.io_maxreadcnt; break; case DKIOCGETMAXBYTECOUNTWRITE: *o = ioattr.io_maxwritecnt; break; case DKIOCGETMAXSEGMENTCOUNTREAD: *o = ioattr.io_segreadcnt; break; case DKIOCGETMAXSEGMENTCOUNTWRITE: *o = ioattr.io_segwritecnt; break; case DKIOCGETMAXSEGMENTBYTECOUNTREAD: *o = ioattr.io_maxsegreadsize; break; case DKIOCGETMAXSEGMENTBYTECOUNTWRITE: *o = ioattr.io_maxsegwritesize; break; case DKIOCGETBLOCKSIZE: *f = vn->sc_secsize; break; case DKIOCSETBLOCKSIZE: if (is_char) { /* can only set block size on block device */ error = ENODEV; break; } if (*f < DEV_BSIZE) { error = EINVAL; break; } if (vn->sc_shadow_vp != NULL) { if (*f == (unsigned)vn->sc_secsize) { break; } /* can't change the block size if already shadowing */ error = EBUSY; break; } vn->sc_secsize = *f; /* recompute the size in terms of the new blocksize */ vn->sc_size = vn->sc_fsize / vn->sc_secsize; break; case DKIOCISWRITABLE: *f = 1; break; case DKIOCGETBLOCKCOUNT32: *f = vn->sc_size; break; case DKIOCGETBLOCKCOUNT: *o = vn->sc_size; break; #ifdef __LP64__ case VNIOCSHADOW32: case VNIOCSHADOW: #else case VNIOCSHADOW: case VNIOCSHADOW64: #endif if (vn->sc_shadow_vp != NULL) { error = EBUSY; break; } if (vn->sc_vp == NULL) { /* much be attached before we can shadow */ error = EINVAL; break; } if (!proc_is64bit(p)) { /* downstream code expects LP64 version of vn_ioctl structure */ vn_ioctl_to_64((struct vn_ioctl_32 *)viop, &user_vnio); viop = &user_vnio; } if (viop->vn_file == USER_ADDR_NULL) { error = EINVAL; break; } error = vniocattach_shadow(vn, viop, dev, 0, p); break; #ifdef __LP64__ case VNIOCATTACH32: case VNIOCATTACH: #else case VNIOCATTACH: case VNIOCATTACH64: #endif if (is_char) { /* attach only on block device */ error = ENODEV; break; } if (vn->sc_flags & VNF_INITED) { error = EBUSY; break; } if (!proc_is64bit(p)) { /* downstream code expects LP64 version of vn_ioctl structure */ vn_ioctl_to_64((struct vn_ioctl_32 *)viop, &user_vnio); viop = &user_vnio; } if (viop->vn_file == USER_ADDR_NULL) { error = EINVAL; break; } error = vniocattach_file(vn, viop, dev, 0, p); break; #ifdef __LP64__ case VNIOCDETACH32: case VNIOCDETACH: #else case VNIOCDETACH: case VNIOCDETACH64: #endif if (is_char) { /* detach only on block device */ error = ENODEV; break; } /* Note: spec_open won't open a mounted block device */ /* * XXX handle i/o in progress. Return EBUSY, or wait, or * flush the i/o. * XXX handle multiple opens of the device. Return EBUSY, * or revoke the fd's. * How are these problems handled for removable and failing * hardware devices? (Hint: They are not) */ vnclear(vn, &context); break; case VNIOCGSET: vn_options |= *f; *f = vn_options; break; case VNIOCGCLEAR: vn_options &= ~(*f); *f = vn_options; break; case VNIOCUSET: vn->sc_options |= *f; *f = vn->sc_options; break; case VNIOCUCLEAR: vn->sc_options &= ~(*f); *f = vn->sc_options; break; default: error = ENOTTY; break; } done: return(error); }
/* * cdevsw interface to km driver. */ int kmopen(dev_t dev, int flag, __unused int devtype, proc_t pp) { int unit; struct tty *tp; struct winsize *wp; int ret; unit = minor(dev); if (unit >= 1) return (ENXIO); tp = km_tty[unit]; tty_lock(tp); tp->t_oproc = kmstart; tp->t_param = NULL; tp->t_dev = dev; if (!(tp->t_state & TS_ISOPEN)) { tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_cflag = (CREAD | CS8 | CLOCAL); tp->t_lflag = TTYDEF_LFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; termioschars(&tp->t_termios); ttsetwater(tp); } else if ((tp->t_state & TS_XCLUDE) && proc_suser(pp)) { ret = EBUSY; goto out; } tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is * on. */ ret = ((*linesw[tp->t_line].l_open) (dev, tp)); { PE_Video video; wp = &tp->t_winsize; /* * Magic numbers. These are CHARWIDTH and CHARHEIGHT from * pexpert/i386/video_console.c */ wp->ws_xpixel = 8; wp->ws_ypixel = 16; tty_unlock(tp); /* XXX race window */ if (flag & O_POPUP) PE_initialize_console(0, kPETextScreen); bzero(&video, sizeof(video)); PE_current_console(&video); tty_lock(tp); if (serialmode & SERIALMODE_OUTPUT) { wp->ws_col = 80; wp->ws_row = 24; } else if (video.v_width != 0 && video.v_height != 0) { wp->ws_col = video.v_width / wp->ws_xpixel; wp->ws_row = video.v_height / wp->ws_ypixel; } else { wp->ws_col = 100; wp->ws_row = 36; } } out: tty_unlock(tp); return ret; }