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