usr/src/uts/common/os/devpolicy.c
author jpk
Fri, 24 Mar 2006 12:29:20 -0800
changeset 1676 37f4a3e2bd99
parent 0 68f95e015346
child 5753 d64b1f799526
permissions -rw-r--r--
PSARC/2002/762 Layered Trusted Solaris PSARC/2005/060 TSNET: Trusted Networking with Security Labels PSARC/2005/259 Layered Trusted Solaris Label Interfaces PSARC/2005/573 Solaris Trusted Extensions for Printing PSARC/2005/691 Trusted Extensions for Device Allocation PSARC/2005/723 Solaris Trusted Extensions Filesystem Labeling PSARC/2006/009 Labeled Auditing PSARC/2006/155 Trusted Extensions RBAC Changes PSARC/2006/191 is_system_labeled 6293271 Zone processes should use zone_kcred instead of kcred 6394554 integrate Solaris Trusted Extensions
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
 * Device policy implementation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
 * Maintains the device policy table and defines the lookup functions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 * The table contains one entry for each major device number; each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 * major bucket has a list of minor number specific entries.  First
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 * match gets it.  Not even simple minor names are expanded as that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 * would cause the device to be loaded.  Non-wildcard entries are expanded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 * on first match. Wildcard entries are matched each open but the actual
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 * policy is cached with the common snode, so the matching code will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 * probably be called infrequently.  The trivial wildcard ``*'' does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 * not cause expensive string expansions and matches.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 * When the policy is updated, the the generation count is increased;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 * whenever a cached policy is used, the generation count is compared;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 * if there's no match, the device policy is refreshed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 * The special policy "nullpolicy" is used to mean "no checking beyond DAC
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 * needed".  It too will change when the policy is rev'ed to make sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 * that devices with nullpolicy are also refreshed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
 * The special policy "dfltpolicy" is used for those devices with no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
 * matching policy.  On boot, it is "all privileges required".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
 * This restriction on boot functions as a fail-safe; if no device policy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
 * is loaded a "no restriction policy" would lead to security problems that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
 * are not immediately noticable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <sys/priv_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <sys/policy.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <sys/atomic.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <sys/autoconf.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <sys/systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <sys/vnode.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <sys/devpolicy.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#include <sys/priv.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <sys/ksynch.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <sys/sunddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
#include <c2/audit.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <sys/fs/dv_node.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
 * Internal data structures definitions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
typedef struct devplcyent devplcyent_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 * The device policy entry; if there is an expression string, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 * minor numbers are not relevant.  This is indicated by dpe_len > 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
struct devplcyent {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
	devplcyent_t	*dpe_next;	/* next entry in this list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
	devplcy_t	*dpe_plcy;	/* policy for this entry */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
	char		*dpe_expr;	/* expression matching minor mode */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
	int		dpe_len;	/* size of allocated mem for expr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
	uint32_t	dpe_flags;	/* flags */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
	minor_t		dpe_lomin;	/* expanded: low minor number */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
	minor_t		dpe_himin;	/* expanded: high minor number */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
	vtype_t		dpe_spec;	/* expanded: VBLK or VCHR */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
#define	DPE_WILDC	0x01		/* Expression has wildcard */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
#define	DPE_ALLMINOR	0x02		/* Matches all minor numbers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
#define	DPE_EXPANDED	0x04		/* Minor numbers expanded */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
typedef struct tableent {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
	devplcyent_t	*t_ent;		/* list of policies by minor */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
	major_t		t_major;	/* device major number */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
} tableent_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
 * The data store.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
static int ntabent;		/* # of major numbers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
static int totitems;		/* Number of entries in all buckets + dflt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
static tableent_t *devpolicy;	/* The device policy itself */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
static krwlock_t policyrw;	/* protects the table */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
static kmutex_t policymutex;	/* allows only one concurrent devpolicy_load */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
devplcy_t *nullpolicy;		/* public because it's used for shortcuts */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
static devplcy_t *dfltpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
static devplcy_t *netpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 * Device policy generation count; only device policies matching the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 * generation count are still valid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
volatile uint32_t devplcy_gen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
 * Tunable: maximum number of device policy entries to load in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
 * a system call.  (Protects KM_SLEEP call)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
int maxdevpolicy = MAXDEVPOLICY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 * Initialize the device policy code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
devpolicy_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	rw_init(&policyrw, NULL, RW_DRIVER, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	mutex_init(&policymutex, NULL, MUTEX_DRIVER, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	/* The mutex is held here in order to satisfy the ASSERT in dpget() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	mutex_enter(&policymutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	nullpolicy = dpget();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
	dfltpolicy = dpget();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	netpolicy = dpget();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	 * Initially, we refuse access to all devices except
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
	 * to processes with all privileges.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
	priv_fillset(&dfltpolicy->dp_rdp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
	priv_fillset(&dfltpolicy->dp_wrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
	totitems = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
	devplcy_gen++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	mutex_exit(&policymutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	/* initialize default network privilege */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	priv_emptyset(&netpolicy->dp_rdp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
	priv_emptyset(&netpolicy->dp_wrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
	priv_addset(&netpolicy->dp_rdp, PRIV_NET_RAWACCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	priv_addset(&netpolicy->dp_wrp, PRIV_NET_RAWACCESS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
 * Devpolicy reference counting/allocation routines.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
 * cf. crget()/crhold()/crfree().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
devplcy_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
dpget(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	devplcy_t *dp = kmem_zalloc(sizeof (*dp), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	ASSERT(MUTEX_HELD(&policymutex));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	dp->dp_ref = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
	/* New ones belong to the next generation */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	dp->dp_gen = devplcy_gen + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	return (dp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
dphold(devplcy_t *dp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
	ASSERT(dp->dp_ref != 0xdeadbeef && dp->dp_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
	atomic_add_32(&dp->dp_ref, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
dpfree(devplcy_t *dp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	ASSERT(dp->dp_ref != 0xdeadbeef && dp->dp_ref != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
	if (atomic_add_32_nv(&dp->dp_ref, -1) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
		kmem_free(dp, sizeof (*dp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
 * Find the policy that matches this device.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
static devplcy_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
match_policy(devplcyent_t *de, dev_t dev, vtype_t spec)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	char *mname = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	minor_t min = getminor(dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
	for (; de != NULL; de = de->dpe_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
		if (de->dpe_flags & DPE_ALLMINOR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
		if (de->dpe_flags & DPE_EXPANDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
			if (min >= de->dpe_lomin && min <= de->dpe_himin &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
			    spec == de->dpe_spec) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
		 * We now need the minor name to match string or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
		 * simle regexp.  Could we use csp->s_dip and not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
		 * allocate a string here?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
		if (mname == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
		    ddi_lyr_get_minor_name(dev, spec, &mname) != DDI_SUCCESS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
			/* mname can be set after the function fails */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
			return (dfltpolicy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
		/* Simple wildcard, with only one ``*'' */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
		if (de->dpe_flags & DPE_WILDC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
			int plen = de->dpe_len - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
			int slen = strlen(mname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
			char *pp = de->dpe_expr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
			char *sp = mname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
			/* string must be at least as long as pattern w/o '*' */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
			if (slen < plen - 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
			/* skip prefix */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
			while (*pp == *sp && *pp != '\0') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
				pp++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
				sp++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
			/* matched single '*' */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
			if (*pp == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
				if (*sp == '\0')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
			if (*pp != '*')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
			pp++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
			 * skip characters matched by '*': difference of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
			 * length of s and length of pattern sans '*'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
			sp += slen - (plen - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
			if (strcmp(pp, sp) == 0) 	/* match! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
		} else if (strcmp(de->dpe_expr, mname) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
			/* Store minor number, if no contention */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
			if (rw_tryupgrade(&policyrw)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
				de->dpe_lomin = de->dpe_himin = min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
				de->dpe_spec = spec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
				de->dpe_flags |= DPE_EXPANDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
	if (mname != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
		kmem_free(mname, strlen(mname) + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
	return (de != NULL ? de->dpe_plcy : dfltpolicy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
devpolicyent_bymajor(major_t maj)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
	int lo, hi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
	ASSERT(RW_LOCK_HELD(&policyrw));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
	lo = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
	hi = ntabent - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
	/* Binary search for major number */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
	while (lo <= hi) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
		int mid = (lo + hi) / 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
		if (devpolicy[mid].t_major == maj)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
			return (mid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
		else if (maj < devpolicy[mid].t_major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
			hi = mid - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
			lo = mid + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
 * Returns held device policy for the specific device node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
 * Note devfs_devpolicy returns with a hold on the policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
devplcy_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
devpolicy_find(vnode_t *vp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
	dev_t dev = vp->v_rdev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
	vtype_t spec = vp->v_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
	major_t maj = getmajor(dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	devplcy_t *res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	if (maj == clone_major)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
		maj = getminor(dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
	rw_enter(&policyrw, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	i = devpolicyent_bymajor(maj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
	if (i != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
		res = match_policy(devpolicy[i].t_ent, dev, spec);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
		dphold(res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
	} else if (devfs_devpolicy(vp, &res) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
		res = NETWORK_DRV(maj) ? netpolicy : dfltpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
		dphold(res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
	rw_exit(&policyrw);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
	return (res);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
static devplcyent_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
parse_policy(devplcysys_t *ds, devplcy_t *nullp, devplcy_t *defp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
	devplcyent_t *de = kmem_zalloc(sizeof (*de), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
	devplcy_t *np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
	if (priv_isemptyset(&ds->dps_rdp) && priv_isemptyset(&ds->dps_wrp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
		dphold(np = nullp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
	else if (defp != nullp &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
		    priv_isequalset(&ds->dps_rdp, &defp->dp_rdp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
		    priv_isequalset(&ds->dps_wrp, &defp->dp_wrp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
		dphold(np = defp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
		np = dpget();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
		np->dp_rdp = ds->dps_rdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
		np->dp_wrp = ds->dps_wrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	if (ds->dps_minornm[0] != '\0') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
		de->dpe_len = strlen(ds->dps_minornm) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
		if (strchr(ds->dps_minornm, '*') != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
			if (de->dpe_len == 2) {		/* "*\0" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
				de->dpe_flags = DPE_ALLMINOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
				de->dpe_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
			} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
				de->dpe_flags = DPE_WILDC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
		if (de->dpe_len != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
			de->dpe_expr = kmem_alloc(de->dpe_len, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
			(void) strcpy(de->dpe_expr, ds->dps_minornm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
		de->dpe_lomin = ds->dps_lomin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
		de->dpe_himin = ds->dps_himin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
		de->dpe_flags = DPE_EXPANDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
		de->dpe_spec = ds->dps_isblock ? VBLK : VCHR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
	de->dpe_plcy = np;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	ASSERT((de->dpe_flags & (DPE_ALLMINOR|DPE_EXPANDED)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
		de->dpe_expr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	return (de);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
freechain(devplcyent_t *de)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	devplcyent_t *dn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
		dn = de->dpe_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
		dpfree(de->dpe_plcy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
		if (de->dpe_len != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
			kmem_free(de->dpe_expr, de->dpe_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
		kmem_free(de, sizeof (*de));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
		de = dn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	} while (de != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
 * Load the device policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
 * The device policy currently makes nu distinction between the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
 * block and characters devices; that is generally not a problem
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
 * as the names of those devices cannot clash.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
devpolicy_load(int nitems, size_t sz, devplcysys_t *uitmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
	int i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
	int nmaj = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
	major_t lastmajor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
	devplcysys_t *items;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
	size_t mem;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
	major_t curmaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
	devplcyent_t **last, *de;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
	tableent_t *newpolicy, *oldpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
	devplcy_t *newnull, *newdflt, *oldnull, *olddflt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
	int oldcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
	int lastlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
	int lastwild;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
#ifdef lint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
	/* Lint can't figure out that the "i == 1" test protects all */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
	lastlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	lastwild = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
	lastmajor = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
	 * The application must agree with the kernel on the size of each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
	 * item; it must not exceed the maximum number and must be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
	 * at least 1 item in size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
	if (sz != sizeof (devplcysys_t) || nitems > maxdevpolicy || nitems < 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
	mem = nitems * sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
	items = kmem_alloc(mem, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
	if (copyin(uitmp, items, mem)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
		kmem_free(items, mem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
		return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
	/* Check for default policy, it must exist and be sorted first */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
	if (items[0].dps_maj != DEVPOLICY_DFLT_MAJ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
		kmem_free(items, mem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
	 * Application must deliver entries sorted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
	 * Sorted meaning here:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
	 *	In major number order
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
	 *	For each major number, we first need to have the explicit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
	 *	entries, then the wild card entries, longest first.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
	for (i = 1; i < nitems; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
		int len, wild;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
		char *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
		curmaj = items[i].dps_maj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
		len = strlen(items[i].dps_minornm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
		wild = len > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
			(tmp = strchr(items[i].dps_minornm, '*')) != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
		/* Another default major, string too long or too many ``*'' */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
		if (curmaj == DEVPOLICY_DFLT_MAJ ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
		    len >= sizeof (items[i].dps_minornm) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
		    wild && strchr(tmp + 1, '*') != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
			kmem_free(items, mem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
		if (i == 1 || lastmajor < curmaj) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
			lastmajor = curmaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
			nmaj++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
		} else if (lastmajor > curmaj || lastwild > wild ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
				lastwild && lastlen < len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
			kmem_free(items, mem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
		lastlen = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
		lastwild = wild;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
#ifdef C2_AUDIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
	if (audit_active)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
		audit_devpolicy(nitems, items);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
	 * Parse the policy.  We create an array for all major numbers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
	 * and in each major number bucket we'll have a linked list of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
	 * entries.  Each item may contain either a lo,hi minor pair
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
	 * or a string/wild card matching a minor node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
	if (nmaj > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
		newpolicy = kmem_zalloc(nmaj * sizeof (tableent_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
	 * We want to lock out concurrent updates but we don't want to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
	 * lock out device opens while we still need to allocate memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
	 * As soon as we allocate new devplcy_t's we commit to the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
	 * generation number, so we must lock out other updates from here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
	mutex_enter(&policymutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
	/* New default and NULL policy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
	newnull = dpget();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
	if (priv_isemptyset(&items[0].dps_rdp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
	    priv_isemptyset(&items[0].dps_wrp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
		newdflt = newnull;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
		dphold(newdflt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
		newdflt = dpget();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
		newdflt->dp_rdp = items[0].dps_rdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
		newdflt->dp_wrp = items[0].dps_wrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
	j = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
	/* Userland made sure sorting was ok */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
	for (i = 1; i < nitems; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
		de = parse_policy(&items[i], newnull, newdflt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		if (j == -1 || curmaj != items[i].dps_maj) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
			j++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
			newpolicy[j].t_major = curmaj = items[i].dps_maj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
			last = &newpolicy[j].t_ent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
		*last = de;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
		last = &de->dpe_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
	/* Done parsing, throw away input */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
	kmem_free(items, mem);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
	/* Lock out all devpolicy_find()s */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
	rw_enter(&policyrw, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
	/* Install the new global data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
	oldnull = nullpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
	nullpolicy = newnull;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
	olddflt = dfltpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
	dfltpolicy = newdflt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
	oldcnt = ntabent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
	ntabent = nmaj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
	totitems = nitems;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
	oldpolicy = devpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
	devpolicy = newpolicy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
	/* Force all calls by devpolicy_find() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
	devplcy_gen++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
	/* Reenable policy finds */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
	rw_exit(&policyrw);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
	mutex_exit(&policymutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
	/* Free old stuff */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
	if (oldcnt != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
		for (i = 0; i < oldcnt; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
			freechain(oldpolicy[i].t_ent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
		kmem_free(oldpolicy, oldcnt * sizeof (*oldpolicy));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	dpfree(oldnull);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	dpfree(olddflt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
 * Get device policy: argument one is a pointer to an integer holding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
 * the number of items allocated for the 3rd argument; the size argument
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
 * is a revision check between kernel and userland.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
devpolicy_get(int *nitemp, size_t sz, devplcysys_t *uitmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
	devplcyent_t *de;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
	devplcysys_t *itmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
	int ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
	int nitems;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
	int err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
	size_t alloced;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	if (sz != sizeof (devplcysys_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	if (copyin(nitemp, &nitems, sizeof (nitems)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
		return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
	rw_enter(&policyrw, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
	if (copyout(&totitems, nitemp, sizeof (totitems)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
		err = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
	else if (nitems < totitems)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
		err = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
	if (err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
		rw_exit(&policyrw);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
	alloced = totitems * sizeof (devplcysys_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
	itmp = kmem_zalloc(alloced, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
	itmp[0].dps_rdp = dfltpolicy->dp_rdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
	itmp[0].dps_wrp = dfltpolicy->dp_wrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
	itmp[0].dps_maj = DEVPOLICY_DFLT_MAJ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
	ind = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
	for (i = 0; i < ntabent; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
		for (de = devpolicy[i].t_ent; de != NULL; de = de->dpe_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
			itmp[ind].dps_maj = devpolicy[i].t_major;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
			itmp[ind].dps_rdp = de->dpe_plcy->dp_rdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
			itmp[ind].dps_wrp = de->dpe_plcy->dp_wrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
			if (de->dpe_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
				(void) strcpy(itmp[ind].dps_minornm,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
						de->dpe_expr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
			else if (de->dpe_flags & DPE_ALLMINOR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
				(void) strcpy(itmp[ind].dps_minornm, "*");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
			else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
				itmp[ind].dps_lomin = de->dpe_lomin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
				itmp[ind].dps_himin = de->dpe_himin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
				itmp[ind].dps_isblock = de->dpe_spec == VBLK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
			ind++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
	rw_exit(&policyrw);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
	if (copyout(itmp, uitmp, alloced))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
		err = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
	kmem_free(itmp, alloced);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
 * Get device policy by device name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
 * This is the implementation of MODGETDEVPOLICYBYNAME
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
devpolicy_getbyname(size_t sz, devplcysys_t *uitmp, char *devname)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	devplcysys_t itm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
	devplcy_t *plcy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
	vtype_t spec;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
	vnode_t *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
	if (sz != sizeof (devplcysys_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	if (lookupname(devname, UIO_USERSPACE, FOLLOW,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
	    NULLVPP, &vp) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
	spec = vp->v_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	if (spec != VBLK && spec != VCHR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
		VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
	plcy = devpolicy_find(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
	VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	bzero(&itm, sizeof (itm));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	/* These are the only values of interest */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	itm.dps_rdp = plcy->dp_rdp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
	itm.dps_wrp = plcy->dp_wrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
	dpfree(plcy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
	if (copyout(&itm, uitmp, sz))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
		return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
priv_str_to_set(const char *priv_name, priv_set_t *priv_set)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
	if (priv_name == NULL || strcmp(priv_name, "none") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
		priv_emptyset(priv_set);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
	} else if (strcmp(priv_name, "all") == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
		priv_fillset(priv_set);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
		int priv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
		priv = priv_getbyname(priv_name, PRIV_ALLOC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
		if (priv < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
			cmn_err(CE_WARN, "fail to allocate privilege: %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
			    priv_name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
		priv_emptyset(priv_set);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
		priv_addset(priv_set, priv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
 * Return device privileges by privilege name
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
 * Called by ddi_create_priv_minor_node()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
devplcy_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
devpolicy_priv_by_name(const char *read_priv, const char *write_priv)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
	devplcy_t *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
	mutex_enter(&policymutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
	dp = dpget();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
	mutex_exit(&policymutex);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
	priv_str_to_set(read_priv, &dp->dp_rdp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
	priv_str_to_set(write_priv, &dp->dp_wrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
	return (dp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
}