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 2003 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 #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <unistd.h> 32*7c478bd9Sstevel@tonic-gate #include <ctype.h> 33*7c478bd9Sstevel@tonic-gate #include <priv.h> 34*7c478bd9Sstevel@tonic-gate #include <string.h> 35*7c478bd9Sstevel@tonic-gate #include <libgen.h> 36*7c478bd9Sstevel@tonic-gate #include <errno.h> 37*7c478bd9Sstevel@tonic-gate #include <libintl.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/devpolicy.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 40*7c478bd9Sstevel@tonic-gate #include "message.h" 41*7c478bd9Sstevel@tonic-gate #include "plcysubr.h" 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* Cannot include devfsadm_impl.h because of static definitions */ 44*7c478bd9Sstevel@tonic-gate #define err_print devfsadm_errprint 45*7c478bd9Sstevel@tonic-gate extern void err_print(char *, ...); 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #define PLCY_CHUNK 128 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* 50*7c478bd9Sstevel@tonic-gate * devpolicy sort order sorts on three items to help the kernel; 51*7c478bd9Sstevel@tonic-gate * the kernel will verify but not sort. 52*7c478bd9Sstevel@tonic-gate * 53*7c478bd9Sstevel@tonic-gate * 1) major number - but default major will be first in sorted output 54*7c478bd9Sstevel@tonic-gate * 2) wildcard or not - non wildcard entries are sorted first. 55*7c478bd9Sstevel@tonic-gate * 2a) Expanded minor numbers first (empty name sorts first). 56*7c478bd9Sstevel@tonic-gate * 2b) Named minors. 57*7c478bd9Sstevel@tonic-gate * 3) length of wildcard entry - longest pattern first 58*7c478bd9Sstevel@tonic-gate * 59*7c478bd9Sstevel@tonic-gate * The last rule allows patterns such as *ctl and * to be used both 60*7c478bd9Sstevel@tonic-gate * unambiguously instead of current bogosities as found in /etc/minor_perm: 61*7c478bd9Sstevel@tonic-gate * rtvc:ctl 0644 root sys 62*7c478bd9Sstevel@tonic-gate * rtvc:rtvcctl* 0644 root sys 63*7c478bd9Sstevel@tonic-gate * rtvc:rtvc[!ctl]* 0666 root sys 64*7c478bd9Sstevel@tonic-gate * 65*7c478bd9Sstevel@tonic-gate * The last pattern only works by accident. 66*7c478bd9Sstevel@tonic-gate * 67*7c478bd9Sstevel@tonic-gate * This would simply become (in sorted order): 68*7c478bd9Sstevel@tonic-gate * rtvc:ctl 69*7c478bd9Sstevel@tonic-gate * rtvc:rtvcctl* 70*7c478bd9Sstevel@tonic-gate * rtvc:* 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate static int 74*7c478bd9Sstevel@tonic-gate qcmp(const void *a, const void *b) 75*7c478bd9Sstevel@tonic-gate { 76*7c478bd9Sstevel@tonic-gate const devplcysys_t *pa = a; 77*7c478bd9Sstevel@tonic-gate const devplcysys_t *pb = b; 78*7c478bd9Sstevel@tonic-gate int wilda, wildb; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* sort on major number, default major first in sort output */ 81*7c478bd9Sstevel@tonic-gate if (pa->dps_maj == DEVPOLICY_DFLT_MAJ) 82*7c478bd9Sstevel@tonic-gate return (-1); 83*7c478bd9Sstevel@tonic-gate if (pb->dps_maj == DEVPOLICY_DFLT_MAJ) 84*7c478bd9Sstevel@tonic-gate return (1); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate if (pa->dps_maj > pb->dps_maj) 87*7c478bd9Sstevel@tonic-gate return (1); 88*7c478bd9Sstevel@tonic-gate else if (pa->dps_maj < pb->dps_maj) 89*7c478bd9Sstevel@tonic-gate return (-1); 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate wilda = strchr(pa->dps_minornm, '*') != NULL; 92*7c478bd9Sstevel@tonic-gate wildb = strchr(pb->dps_minornm, '*') != NULL; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* sort the entry with the wildcard last */ 95*7c478bd9Sstevel@tonic-gate if (wilda != wildb) 96*7c478bd9Sstevel@tonic-gate return (wilda - wildb); 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* entries without wildcards compare with strcmp() */ 99*7c478bd9Sstevel@tonic-gate if (wilda == 0) 100*7c478bd9Sstevel@tonic-gate return (strcmp(pa->dps_minornm, pb->dps_minornm)); 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /* shortest wildcard last */ 103*7c478bd9Sstevel@tonic-gate return ((int)(strlen(pb->dps_minornm) - strlen(pa->dps_minornm))); 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate static int 107*7c478bd9Sstevel@tonic-gate loadprivs(const char *infile) 108*7c478bd9Sstevel@tonic-gate { 109*7c478bd9Sstevel@tonic-gate char *line, *col; 110*7c478bd9Sstevel@tonic-gate FILE *in; 111*7c478bd9Sstevel@tonic-gate struct fileentry *fep; 112*7c478bd9Sstevel@tonic-gate int res = 0; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate in = fopen(infile, "r"); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if (in == NULL) 117*7c478bd9Sstevel@tonic-gate return (0); 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate while ((fep = fgetline(in)) != NULL && fep->entry != NULL) { 120*7c478bd9Sstevel@tonic-gate line = fep->entry; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate if (*line == '\0') 123*7c478bd9Sstevel@tonic-gate continue; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate line[strlen(line)-1] = '\0'; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate col = strchr(line, ':'); 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate if (col != NULL) { 130*7c478bd9Sstevel@tonic-gate major_t maj; 131*7c478bd9Sstevel@tonic-gate *col = '\0'; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate if (modctl(MODGETMAJBIND, line, col - line + 1, &maj) 134*7c478bd9Sstevel@tonic-gate != 0) 135*7c478bd9Sstevel@tonic-gate continue; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate line = col + 1; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate if (modctl(MODALLOCPRIV, line) != 0) { 141*7c478bd9Sstevel@tonic-gate (void) err_print("modctl(MODALLOCPRIV, %s): %s\n", 142*7c478bd9Sstevel@tonic-gate line, strerror(errno)); 143*7c478bd9Sstevel@tonic-gate res = -1; 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate return (res); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate static int 150*7c478bd9Sstevel@tonic-gate loadpolicy(const char *infile) 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate char *line; 153*7c478bd9Sstevel@tonic-gate int nalloc = 0, cnt = 0; 154*7c478bd9Sstevel@tonic-gate char *mem = NULL; 155*7c478bd9Sstevel@tonic-gate devplcysys_t *dp, *dflt = NULL; 156*7c478bd9Sstevel@tonic-gate FILE *in; 157*7c478bd9Sstevel@tonic-gate struct fileentry *fep; 158*7c478bd9Sstevel@tonic-gate int res; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate char *maj; 161*7c478bd9Sstevel@tonic-gate char *tok; 162*7c478bd9Sstevel@tonic-gate char *min; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate in = fopen(infile, "r"); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate if (in == NULL) { 167*7c478bd9Sstevel@tonic-gate err_print(OPEN_FAILED, infile, strerror(errno)); 168*7c478bd9Sstevel@tonic-gate return (-1); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate while ((fep = fgetline(in)) != NULL && fep->entry != NULL) { 172*7c478bd9Sstevel@tonic-gate line = fep->entry; 173*7c478bd9Sstevel@tonic-gate if (cnt >= nalloc) { 174*7c478bd9Sstevel@tonic-gate nalloc += PLCY_CHUNK; 175*7c478bd9Sstevel@tonic-gate mem = realloc(mem, nalloc * devplcysys_sz); 176*7c478bd9Sstevel@tonic-gate if (mem == NULL) { 177*7c478bd9Sstevel@tonic-gate err_print(MALLOC_FAILED, 178*7c478bd9Sstevel@tonic-gate nalloc * devplcysys_sz); 179*7c478bd9Sstevel@tonic-gate return (-1); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* Readjust pointer to dflt after realloc */ 183*7c478bd9Sstevel@tonic-gate if (dflt != NULL) 184*7c478bd9Sstevel@tonic-gate /* LINTED: alignment */ 185*7c478bd9Sstevel@tonic-gate dflt = (devplcysys_t *)mem; 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate maj = strtok(line, "\n\t "); 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if (maj == NULL) 190*7c478bd9Sstevel@tonic-gate continue; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate /* LINTED: alignment */ 193*7c478bd9Sstevel@tonic-gate dp = (devplcysys_t *)(mem + devplcysys_sz * cnt); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (strcmp(maj, "*") == 0) { 196*7c478bd9Sstevel@tonic-gate if (dflt != NULL) { 197*7c478bd9Sstevel@tonic-gate err_print(DPLCY_ONE_DFLT, infile); 198*7c478bd9Sstevel@tonic-gate return (-1); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate (void) memset(dp, 0, devplcysys_sz); 201*7c478bd9Sstevel@tonic-gate dp->dps_maj = DEVPOLICY_DFLT_MAJ; 202*7c478bd9Sstevel@tonic-gate dflt = dp; 203*7c478bd9Sstevel@tonic-gate } else { 204*7c478bd9Sstevel@tonic-gate if (dflt == NULL) { 205*7c478bd9Sstevel@tonic-gate err_print(DPLCY_FIRST, infile); 206*7c478bd9Sstevel@tonic-gate return (-1); 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate (void) memcpy(dp, dflt, devplcysys_sz); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate min = strchr(maj, ':'); 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (min != NULL) { 214*7c478bd9Sstevel@tonic-gate *min++ = '\0'; 215*7c478bd9Sstevel@tonic-gate if (strchr(min, ':') != NULL) { 216*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 217*7c478bd9Sstevel@tonic-gate "Too many ``:'' in entry\n"); 218*7c478bd9Sstevel@tonic-gate return (-1); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate } else 221*7c478bd9Sstevel@tonic-gate min = "*"; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* Silently ignore unknown devices. */ 224*7c478bd9Sstevel@tonic-gate if (modctl(MODGETMAJBIND, maj, strlen(maj) + 1, 225*7c478bd9Sstevel@tonic-gate &dp->dps_maj) != 0) 226*7c478bd9Sstevel@tonic-gate continue; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate if (*min == '(') { 229*7c478bd9Sstevel@tonic-gate /* Numeric minor range */ 230*7c478bd9Sstevel@tonic-gate char type; 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate if (parse_minor_range(min, &dp->dps_lomin, 233*7c478bd9Sstevel@tonic-gate &dp->dps_himin, &type) == -1) { 234*7c478bd9Sstevel@tonic-gate err_print(INVALID_MINOR, min); 235*7c478bd9Sstevel@tonic-gate return (-1); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate dp->dps_isblock = type == 'b'; 238*7c478bd9Sstevel@tonic-gate } else { 239*7c478bd9Sstevel@tonic-gate if (strlen(min) >= sizeof (dp->dps_minornm)) { 240*7c478bd9Sstevel@tonic-gate err_print(MINOR_TOO_LONG, maj, min); 241*7c478bd9Sstevel@tonic-gate return (-1); 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate (void) strcpy(dp->dps_minornm, min); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate while (tok = strtok(NULL, "\n\t ")) { 248*7c478bd9Sstevel@tonic-gate if (parse_plcy_token(tok, dp)) { 249*7c478bd9Sstevel@tonic-gate err_print(BAD_ENTRY, fep->startline, 250*7c478bd9Sstevel@tonic-gate fep->orgentry); 251*7c478bd9Sstevel@tonic-gate return (-1); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate cnt++; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate if (fep == NULL) { 257*7c478bd9Sstevel@tonic-gate if (feof(in)) 258*7c478bd9Sstevel@tonic-gate err_print(UNEXPECTED_EOF, infile); 259*7c478bd9Sstevel@tonic-gate else 260*7c478bd9Sstevel@tonic-gate err_print(NO_MEMORY); 261*7c478bd9Sstevel@tonic-gate return (-1); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate qsort(mem, cnt, devplcysys_sz, qcmp); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate if ((res = modctl(MODSETDEVPOLICY, cnt, devplcysys_sz, mem)) != 0) 266*7c478bd9Sstevel@tonic-gate err_print("modctl(MODSETDEVPOLICY): %s\n", strerror(errno)); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate return (res); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate int 272*7c478bd9Sstevel@tonic-gate load_devpolicy(void) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate int res; 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate devplcy_init(); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate res = loadprivs(EXTRA_PRIVS); 279*7c478bd9Sstevel@tonic-gate res += loadpolicy(DEV_POLICY); 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate return (res); 282*7c478bd9Sstevel@tonic-gate } 283