4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
38 #include <sys/devpolicy.h>
39 #include <sys/modctl.h>
43 /* Cannot include devfsadm_impl.h because of static definitions */
44 #define err_print devfsadm_errprint
45 extern void err_print(char *, ...);
47 #define PLCY_CHUNK 128
50 * devpolicy sort order sorts on three items to help the kernel;
51 * the kernel will verify but not sort.
53 * 1) major number - but default major will be first in sorted output
54 * 2) wildcard or not - non wildcard entries are sorted first.
55 * 2a) Expanded minor numbers first (empty name sorts first).
57 * 3) length of wildcard entry - longest pattern first
59 * The last rule allows patterns such as *ctl and * to be used both
60 * unambiguously instead of current bogosities as found in /etc/minor_perm:
61 * rtvc:ctl 0644 root sys
62 * rtvc:rtvcctl* 0644 root sys
63 * rtvc:rtvc[!ctl]* 0666 root sys
65 * The last pattern only works by accident.
67 * This would simply become (in sorted order):
74 qcmp(const void *a
, const void *b
)
76 const devplcysys_t
*pa
= a
;
77 const devplcysys_t
*pb
= b
;
80 /* sort on major number, default major first in sort output */
81 if (pa
->dps_maj
== DEVPOLICY_DFLT_MAJ
)
83 if (pb
->dps_maj
== DEVPOLICY_DFLT_MAJ
)
86 if (pa
->dps_maj
> pb
->dps_maj
)
88 else if (pa
->dps_maj
< pb
->dps_maj
)
91 wilda
= strchr(pa
->dps_minornm
, '*') != NULL
;
92 wildb
= strchr(pb
->dps_minornm
, '*') != NULL
;
94 /* sort the entry with the wildcard last */
96 return (wilda
- wildb
);
98 /* entries without wildcards compare with strcmp() */
100 return (strcmp(pa
->dps_minornm
, pb
->dps_minornm
));
102 /* shortest wildcard last */
103 return ((int)(strlen(pb
->dps_minornm
) - strlen(pa
->dps_minornm
)));
107 loadprivs(const char *infile
)
111 struct fileentry
*fep
;
114 in
= fopen(infile
, "r");
119 while ((fep
= fgetline(in
)) != NULL
&& fep
->entry
!= NULL
) {
125 line
[strlen(line
)-1] = '\0';
127 col
= strchr(line
, ':');
133 if (modctl(MODGETMAJBIND
, line
, col
- line
+ 1, &maj
)
140 if (modctl(MODALLOCPRIV
, line
) != 0) {
141 (void) err_print("modctl(MODALLOCPRIV, %s): %s\n",
142 line
, strerror(errno
));
150 loadpolicy(const char *infile
)
153 int nalloc
= 0, cnt
= 0;
155 devplcysys_t
*dp
, *dflt
= NULL
;
157 struct fileentry
*fep
;
164 in
= fopen(infile
, "r");
167 err_print(OPEN_FAILED
, infile
, strerror(errno
));
171 while ((fep
= fgetline(in
)) != NULL
&& fep
->entry
!= NULL
) {
174 nalloc
+= PLCY_CHUNK
;
175 mem
= realloc(mem
, nalloc
* devplcysys_sz
);
177 err_print(MALLOC_FAILED
,
178 nalloc
* devplcysys_sz
);
182 /* Readjust pointer to dflt after realloc */
184 /* LINTED: alignment */
185 dflt
= (devplcysys_t
*)mem
;
187 maj
= strtok(line
, "\n\t ");
192 /* LINTED: alignment */
193 dp
= (devplcysys_t
*)(mem
+ devplcysys_sz
* cnt
);
195 if (strcmp(maj
, "*") == 0) {
197 err_print(DPLCY_ONE_DFLT
, infile
);
200 (void) memset(dp
, 0, devplcysys_sz
);
201 dp
->dps_maj
= DEVPOLICY_DFLT_MAJ
;
205 err_print(DPLCY_FIRST
, infile
);
209 (void) memcpy(dp
, dflt
, devplcysys_sz
);
211 min
= strchr(maj
, ':');
215 if (strchr(min
, ':') != NULL
) {
216 (void) fprintf(stderr
,
217 "Too many ``:'' in entry\n");
223 /* Silently ignore unknown devices. */
224 if (modctl(MODGETMAJBIND
, maj
, strlen(maj
) + 1,
229 /* Numeric minor range */
232 if (parse_minor_range(min
, &dp
->dps_lomin
,
233 &dp
->dps_himin
, &type
) == -1) {
234 err_print(INVALID_MINOR
, min
);
237 dp
->dps_isblock
= type
== 'b';
239 if (strlen(min
) >= sizeof (dp
->dps_minornm
)) {
240 err_print(MINOR_TOO_LONG
, maj
, min
);
243 (void) strcpy(dp
->dps_minornm
, min
);
247 while (tok
= strtok(NULL
, "\n\t ")) {
248 if (parse_plcy_token(tok
, dp
)) {
249 err_print(BAD_ENTRY
, fep
->startline
,
258 err_print(UNEXPECTED_EOF
, infile
);
260 err_print(NO_MEMORY
);
263 qsort(mem
, cnt
, devplcysys_sz
, qcmp
);
265 if ((res
= modctl(MODSETDEVPOLICY
, cnt
, devplcysys_sz
, mem
)) != 0)
266 err_print("modctl(MODSETDEVPOLICY): %s\n", strerror(errno
));
278 res
= loadprivs(EXTRA_PRIVS
);
279 res
+= loadpolicy(DEV_POLICY
);