1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Blacklist special file 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <sys/conf.h> 35*0Sstevel@tonic-gate #include <sys/stat.h> 36*0Sstevel@tonic-gate #include <sys/modctl.h> 37*0Sstevel@tonic-gate #include <sys/kmem.h> 38*0Sstevel@tonic-gate #include <sys/ddi.h> 39*0Sstevel@tonic-gate #include <sys/sunddi.h> 40*0Sstevel@tonic-gate #include <sys/open.h> 41*0Sstevel@tonic-gate #include <sys/policy.h> 42*0Sstevel@tonic-gate #include <sys/fm/protocol.h> 43*0Sstevel@tonic-gate #include <sys/bl.h> 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate static dev_info_t *bl_dip; /* private copy of devinfo pointer */ 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate static int 48*0Sstevel@tonic-gate bl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 49*0Sstevel@tonic-gate { 50*0Sstevel@tonic-gate switch (cmd) { 51*0Sstevel@tonic-gate case DDI_ATTACH: 52*0Sstevel@tonic-gate break; 53*0Sstevel@tonic-gate case DDI_RESUME: 54*0Sstevel@tonic-gate return (DDI_SUCCESS); 55*0Sstevel@tonic-gate default: 56*0Sstevel@tonic-gate return (DDI_FAILURE); 57*0Sstevel@tonic-gate } 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate if (ddi_create_minor_node(dip, ddi_get_name(dip), S_IFCHR, 60*0Sstevel@tonic-gate ddi_get_instance(dip), DDI_PSEUDO, 0) != DDI_SUCCESS) 61*0Sstevel@tonic-gate return (DDI_FAILURE); 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate bl_dip = dip; 64*0Sstevel@tonic-gate return (DDI_SUCCESS); 65*0Sstevel@tonic-gate } 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate /*ARGSUSED*/ 68*0Sstevel@tonic-gate static int 69*0Sstevel@tonic-gate bl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 70*0Sstevel@tonic-gate { 71*0Sstevel@tonic-gate switch (cmd) { 72*0Sstevel@tonic-gate case DDI_DETACH: 73*0Sstevel@tonic-gate break; 74*0Sstevel@tonic-gate case DDI_SUSPEND: 75*0Sstevel@tonic-gate return (DDI_SUCCESS); 76*0Sstevel@tonic-gate default: 77*0Sstevel@tonic-gate return (DDI_FAILURE); 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate ddi_remove_minor_node(bl_dip, NULL); 81*0Sstevel@tonic-gate return (DDI_SUCCESS); 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate /*ARGSUSED*/ 85*0Sstevel@tonic-gate static int 86*0Sstevel@tonic-gate bl_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 87*0Sstevel@tonic-gate { 88*0Sstevel@tonic-gate int rc = DDI_SUCCESS; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate switch (infocmd) { 91*0Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 92*0Sstevel@tonic-gate *result = bl_dip; 93*0Sstevel@tonic-gate break; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 96*0Sstevel@tonic-gate *result = (void *)(uintptr_t)getminor((dev_t)arg); 97*0Sstevel@tonic-gate break; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate default: 100*0Sstevel@tonic-gate *result = NULL; 101*0Sstevel@tonic-gate rc = DDI_FAILURE; 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate return (rc); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate /*ARGSUSED*/ 108*0Sstevel@tonic-gate static int 109*0Sstevel@tonic-gate bl_open(dev_t *devp, int flag, int otyp, struct cred *credp) 110*0Sstevel@tonic-gate { 111*0Sstevel@tonic-gate if (otyp != OTYP_CHR) 112*0Sstevel@tonic-gate return (EINVAL); 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate if (secpolicy_blacklist(credp) != 0) 115*0Sstevel@tonic-gate return (EPERM); 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate return (0); 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /*ARGSUSED*/ 121*0Sstevel@tonic-gate static int 122*0Sstevel@tonic-gate bl_ioctl(dev_t dev, int cmd, intptr_t data, int flag, cred_t *cred, int *rvalp) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate bl_req_t blr; 125*0Sstevel@tonic-gate nvlist_t *fmri; 126*0Sstevel@tonic-gate const char *scheme; 127*0Sstevel@tonic-gate char class[128]; 128*0Sstevel@tonic-gate char *buf; 129*0Sstevel@tonic-gate int err; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate #ifdef _SYSCALL32 132*0Sstevel@tonic-gate if (get_udatamodel() != DATAMODEL_NATIVE) { 133*0Sstevel@tonic-gate bl_req32_t blr32; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate if (copyin((void *)data, &blr32, sizeof (bl_req32_t)) != 0) 136*0Sstevel@tonic-gate return (EFAULT); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate blr.bl_fmri = (caddr_t)(uintptr_t)blr32.bl_fmri; 139*0Sstevel@tonic-gate blr.bl_fmrisz = blr32.bl_fmrisz; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate blr.bl_class = (caddr_t)(uintptr_t)blr32.bl_class; 142*0Sstevel@tonic-gate } else 143*0Sstevel@tonic-gate #endif 144*0Sstevel@tonic-gate { 145*0Sstevel@tonic-gate if (copyin((void *)data, &blr, sizeof (bl_req_t)) != 0) 146*0Sstevel@tonic-gate return (EFAULT); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate if (blr.bl_fmri == NULL || blr.bl_fmrisz > BL_FMRI_MAX_BUFSIZE || 150*0Sstevel@tonic-gate blr.bl_class == NULL) 151*0Sstevel@tonic-gate return (EINVAL); 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate if (copyinstr(blr.bl_class, class, sizeof (class), NULL) != 0) 154*0Sstevel@tonic-gate return (EFAULT); 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate buf = kmem_zalloc(blr.bl_fmrisz, KM_SLEEP); 157*0Sstevel@tonic-gate if (copyin(blr.bl_fmri, buf, blr.bl_fmrisz) != 0) { 158*0Sstevel@tonic-gate kmem_free(buf, blr.bl_fmrisz); 159*0Sstevel@tonic-gate return (EFAULT); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate err = nvlist_unpack(buf, blr.bl_fmrisz, &fmri, KM_SLEEP); 163*0Sstevel@tonic-gate kmem_free(buf, blr.bl_fmrisz); 164*0Sstevel@tonic-gate if (err != 0) 165*0Sstevel@tonic-gate return (err); 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate if (nvlist_lookup_string(fmri, FM_FMRI_SCHEME, (char **)&scheme) != 0) { 168*0Sstevel@tonic-gate nvlist_free(fmri); 169*0Sstevel@tonic-gate return (EINVAL); 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate switch (cmd) { 173*0Sstevel@tonic-gate case BLIOC_INSERT: 174*0Sstevel@tonic-gate case BLIOC_DELETE: 175*0Sstevel@tonic-gate err = blacklist(cmd, scheme, fmri, class); 176*0Sstevel@tonic-gate break; 177*0Sstevel@tonic-gate default: 178*0Sstevel@tonic-gate err = ENOTSUP; 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate nvlist_free(fmri); 182*0Sstevel@tonic-gate return (err); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate static struct cb_ops bl_cb_ops = { 187*0Sstevel@tonic-gate bl_open, /* open */ 188*0Sstevel@tonic-gate nulldev, /* close */ 189*0Sstevel@tonic-gate nodev, /* strategy */ 190*0Sstevel@tonic-gate nodev, /* print */ 191*0Sstevel@tonic-gate nodev, /* dump */ 192*0Sstevel@tonic-gate nodev, /* read */ 193*0Sstevel@tonic-gate nodev, /* write */ 194*0Sstevel@tonic-gate bl_ioctl, /* ioctl */ 195*0Sstevel@tonic-gate nodev, /* devmap */ 196*0Sstevel@tonic-gate nodev, /* mmap */ 197*0Sstevel@tonic-gate nodev, /* segmap */ 198*0Sstevel@tonic-gate nochpoll, /* poll */ 199*0Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 200*0Sstevel@tonic-gate 0, /* streamtab */ 201*0Sstevel@tonic-gate D_NEW | D_MP | D_64BIT /* Driver compatibility flag */ 202*0Sstevel@tonic-gate }; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate static struct dev_ops bl_ops = { 205*0Sstevel@tonic-gate DEVO_REV, /* devo_rev */ 206*0Sstevel@tonic-gate 0, /* devo_refcnt */ 207*0Sstevel@tonic-gate bl_getinfo, /* devo_getinfo */ 208*0Sstevel@tonic-gate nulldev, /* devo_identify */ 209*0Sstevel@tonic-gate nulldev, /* devo_probe */ 210*0Sstevel@tonic-gate bl_attach, /* devo_attach */ 211*0Sstevel@tonic-gate bl_detach, /* devo_detach */ 212*0Sstevel@tonic-gate nodev, /* devo_reset */ 213*0Sstevel@tonic-gate &bl_cb_ops, /* devo_cb_ops */ 214*0Sstevel@tonic-gate (struct bus_ops *)0, /* devo_bus_ops */ 215*0Sstevel@tonic-gate NULL /* devo_power */ 216*0Sstevel@tonic-gate }; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate static struct modldrv modldrv = { 219*0Sstevel@tonic-gate &mod_driverops, "blacklist driver %I%", &bl_ops, 220*0Sstevel@tonic-gate }; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 223*0Sstevel@tonic-gate MODREV_1, &modldrv, NULL 224*0Sstevel@tonic-gate }; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate int 227*0Sstevel@tonic-gate _init(void) 228*0Sstevel@tonic-gate { 229*0Sstevel@tonic-gate return (mod_install(&modlinkage)); 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate int 233*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 234*0Sstevel@tonic-gate { 235*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate int 239*0Sstevel@tonic-gate _fini(void) 240*0Sstevel@tonic-gate { 241*0Sstevel@tonic-gate return (mod_remove(&modlinkage)); 242*0Sstevel@tonic-gate } 243