1a237e38eSth /*
2a237e38eSth * CDDL HEADER START
3a237e38eSth *
4a237e38eSth * The contents of this file are subject to the terms of the
5a237e38eSth * Common Development and Distribution License (the "License").
6a237e38eSth * You may not use this file except in compliance with the License.
7a237e38eSth *
8a237e38eSth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a237e38eSth * or http://www.opensolaris.org/os/licensing.
10a237e38eSth * See the License for the specific language governing permissions
11a237e38eSth * and limitations under the License.
12a237e38eSth *
13a237e38eSth * When distributing Covered Code, include this CDDL HEADER in each
14a237e38eSth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a237e38eSth * If applicable, add the following below this CDDL HEADER, with the
16a237e38eSth * fields enclosed by brackets "[]" replaced with your own identifying
17a237e38eSth * information: Portions Copyright [yyyy] [name of copyright owner]
18a237e38eSth *
19a237e38eSth * CDDL HEADER END
20a237e38eSth */
21a237e38eSth
22a237e38eSth /*
230616fd7fSPavel Filipensky * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24a237e38eSth */
25a237e38eSth
26*0dfe541eSEvan Layton /*
27*0dfe541eSEvan Layton * Copyright 2018 Nexenta Systems, Inc.
28*0dfe541eSEvan Layton * Copyright 2020 Joyent, Inc.
29*0dfe541eSEvan Layton */
30*0dfe541eSEvan Layton
31a237e38eSth #include <sys/types.h>
32a237e38eSth #include <sys/types32.h>
33a237e38eSth #include <sys/param.h>
34a237e38eSth #include <sys/systm.h>
35a237e38eSth #include <rpc/types.h>
36a237e38eSth #include <sys/vfs.h>
37a237e38eSth #include <sys/siginfo.h>
38a237e38eSth #include <sys/proc.h> /* for exit() declaration */
39a237e38eSth #include <sys/kmem.h>
40a237e38eSth #include <sys/pathname.h>
41a237e38eSth #include <sys/debug.h>
42a237e38eSth #include <sys/vtrace.h>
43a237e38eSth #include <sys/cmn_err.h>
44a237e38eSth #include <sys/atomic.h>
45ecd6cf80Smarks #include <sys/policy.h>
46a237e38eSth
47a237e38eSth #include <sharefs/sharefs.h>
48a237e38eSth
49a237e38eSth /*
50a237e38eSth * A macro to avoid cut-and-paste errors on getting a string field
51a237e38eSth * from user-land.
52a237e38eSth */
53a237e38eSth #define SHARETAB_COPYIN(field) \
54a237e38eSth if (copyinstr(STRUCT_FGETP(u_sh, sh_##field), \
55*0dfe541eSEvan Layton buf, \
56*0dfe541eSEvan Layton bufsz + 1, /* Add one for extra NUL */ \
57*0dfe541eSEvan Layton &len)) { \
58a237e38eSth error = EFAULT; \
59a237e38eSth goto cleanup; \
60a237e38eSth } \
61*0dfe541eSEvan Layton /* Need to remove 1 because copyinstr() counts the NUL */ \
62a237e38eSth len--; \
63a237e38eSth sh->sh_##field = kmem_alloc(len + 1, KM_SLEEP); \
64a237e38eSth bcopy(buf, sh->sh_##field, len); \
65a237e38eSth sh->sh_##field[len] = '\0'; \
66a237e38eSth shl.shl_##field = (int)len; \
67a237e38eSth sh->sh_size += shl.shl_##field; /* Debug counting */
68a237e38eSth
69a237e38eSth #define SHARETAB_DELETE_FIELD(field) \
70*0dfe541eSEvan Layton if (sh->sh_##field != NULL) { \
71a237e38eSth kmem_free(sh->sh_##field, \
72*0dfe541eSEvan Layton shl ? shl->shl_##field + 1 : \
73*0dfe541eSEvan Layton strlen(sh->sh_##field) + 1); \
74a237e38eSth }
75a237e38eSth
76*0dfe541eSEvan Layton static zone_key_t sharetab_zone_key;
77a237e38eSth
78a237e38eSth /*
79a237e38eSth * Take care of cleaning up a share.
80a237e38eSth * If passed in a length array, use it to determine how much
81a237e38eSth * space to clean up. Else, figure that out.
82a237e38eSth */
83a237e38eSth static void
sharefree(share_t * sh,sharefs_lens_t * shl)84a237e38eSth sharefree(share_t *sh, sharefs_lens_t *shl)
85a237e38eSth {
86*0dfe541eSEvan Layton if (sh == NULL)
87a237e38eSth return;
88a237e38eSth
89a237e38eSth SHARETAB_DELETE_FIELD(path);
90a237e38eSth SHARETAB_DELETE_FIELD(res);
91a237e38eSth SHARETAB_DELETE_FIELD(fstype);
92a237e38eSth SHARETAB_DELETE_FIELD(opts);
93a237e38eSth SHARETAB_DELETE_FIELD(descr);
94a237e38eSth
95*0dfe541eSEvan Layton kmem_free(sh, sizeof (*sh));
96a237e38eSth }
97a237e38eSth
98a237e38eSth /*
99a237e38eSth * If there is no error, then this function is responsible for
100a237e38eSth * cleaning up the memory associated with the share argument.
101a237e38eSth */
102a237e38eSth static int
sharefs_remove(sharetab_globals_t * sg,share_t * sh,sharefs_lens_t * shl)103*0dfe541eSEvan Layton sharefs_remove(sharetab_globals_t *sg, share_t *sh, sharefs_lens_t *shl)
104a237e38eSth {
105a237e38eSth int iHash;
106a237e38eSth sharetab_t *sht;
107a237e38eSth share_t *s, *p;
108a237e38eSth int iPath;
109a237e38eSth
110a237e38eSth if (!sh)
111a237e38eSth return (ENOENT);
112a237e38eSth
113*0dfe541eSEvan Layton rw_enter(&sg->sharetab_lock, RW_WRITER);
114*0dfe541eSEvan Layton for (sht = sg->sharefs_sharetab; sht != NULL; sht = sht->s_next) {
115*0dfe541eSEvan Layton if (strcmp(sh->sh_fstype, sht->s_fstype) == 0)
116a237e38eSth break;
117a237e38eSth }
118a237e38eSth
119a237e38eSth /*
120a237e38eSth * There does not exist a fstype in memory which
121a237e38eSth * matches the share passed in.
122a237e38eSth */
123*0dfe541eSEvan Layton if (sht == NULL) {
124*0dfe541eSEvan Layton rw_exit(&sg->sharetab_lock);
125a237e38eSth return (ENOENT);
126a237e38eSth }
127a237e38eSth
128*0dfe541eSEvan Layton iPath = shl != NULL ? shl->shl_path : strlen(sh->sh_path);
1290616fd7fSPavel Filipensky iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
130a237e38eSth
131a237e38eSth /*
132a237e38eSth * Now walk down the hash table and find the entry to free!
133a237e38eSth */
134a237e38eSth for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
135ecd6cf80Smarks s != NULL; s = s->sh_next) {
136a237e38eSth /*
137a237e38eSth * We need exact matches.
138a237e38eSth */
139a237e38eSth if (strcmp(sh->sh_path, s->sh_path) == 0 &&
140ecd6cf80Smarks strlen(s->sh_path) == iPath) {
141*0dfe541eSEvan Layton if (p != NULL)
142a237e38eSth p->sh_next = s->sh_next;
143*0dfe541eSEvan Layton else
144a237e38eSth sht->s_buckets[iHash].ssh_sh = s->sh_next;
145a237e38eSth
146a237e38eSth ASSERT(sht->s_buckets[iHash].ssh_count != 0);
1471a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&sht->s_buckets[iHash].ssh_count);
1481a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&sht->s_count);
149*0dfe541eSEvan Layton atomic_dec_32(&sg->sharetab_count);
150a237e38eSth
151*0dfe541eSEvan Layton ASSERT(sg->sharetab_size >= s->sh_size);
152*0dfe541eSEvan Layton sg->sharetab_size -= s->sh_size;
153a237e38eSth
154*0dfe541eSEvan Layton gethrestime(&sg->sharetab_mtime);
155*0dfe541eSEvan Layton atomic_inc_32(&sg->sharetab_generation);
156a237e38eSth
157a237e38eSth break;
158a237e38eSth }
159a237e38eSth
160a237e38eSth p = s;
161a237e38eSth }
162a237e38eSth
163*0dfe541eSEvan Layton rw_exit(&sg->sharetab_lock);
164a237e38eSth
165*0dfe541eSEvan Layton if (s == NULL)
166a237e38eSth return (ENOENT);
167a237e38eSth
168a237e38eSth s->sh_next = NULL;
169a237e38eSth sharefree(s, NULL);
170a237e38eSth
171*0dfe541eSEvan Layton /* We need to free the share for the caller */
172a237e38eSth sharefree(sh, shl);
173a237e38eSth
174a237e38eSth return (0);
175a237e38eSth }
176a237e38eSth
177a237e38eSth /*
178a237e38eSth * The caller must have allocated memory for us to use.
179a237e38eSth */
180a237e38eSth static int
sharefs_add(sharetab_globals_t * sg,share_t * sh,sharefs_lens_t * shl)181*0dfe541eSEvan Layton sharefs_add(sharetab_globals_t *sg, share_t *sh, sharefs_lens_t *shl)
182a237e38eSth {
183a237e38eSth int iHash;
184a237e38eSth sharetab_t *sht;
185a237e38eSth share_t *s, *p;
186a237e38eSth int iPath;
187a237e38eSth int n;
188a237e38eSth
189*0dfe541eSEvan Layton if (sh == NULL)
190a237e38eSth return (ENOENT);
191a237e38eSth
192*0dfe541eSEvan Layton /* We need to find the hash buckets for the fstype */
193*0dfe541eSEvan Layton rw_enter(&sg->sharetab_lock, RW_WRITER);
194*0dfe541eSEvan Layton for (sht = sg->sharefs_sharetab; sht != NULL; sht = sht->s_next) {
195*0dfe541eSEvan Layton if (strcmp(sh->sh_fstype, sht->s_fstype) == 0)
196a237e38eSth break;
197a237e38eSth }
198a237e38eSth
199*0dfe541eSEvan Layton /* Did not exist, so allocate one and add it to the sharetab */
200*0dfe541eSEvan Layton if (sht == NULL) {
201a237e38eSth sht = kmem_zalloc(sizeof (*sht), KM_SLEEP);
202a237e38eSth n = strlen(sh->sh_fstype);
203a237e38eSth sht->s_fstype = kmem_zalloc(n + 1, KM_SLEEP);
204a237e38eSth (void) strncpy(sht->s_fstype, sh->sh_fstype, n);
205a237e38eSth
206*0dfe541eSEvan Layton sht->s_next = sg->sharefs_sharetab;
207*0dfe541eSEvan Layton sg->sharefs_sharetab = sht;
208a237e38eSth }
209a237e38eSth
210*0dfe541eSEvan Layton /* Now we need to find where we have to add the entry */
211*0dfe541eSEvan Layton iPath = shl != NULL ? shl->shl_path : strlen(sh->sh_path);
2120616fd7fSPavel Filipensky iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
213a237e38eSth
214a237e38eSth if (shl) {
215a237e38eSth sh->sh_size = shl->shl_path + shl->shl_res +
216ecd6cf80Smarks shl->shl_fstype + shl->shl_opts + shl->shl_descr;
217a237e38eSth } else {
218a237e38eSth sh->sh_size = strlen(sh->sh_path) +
219ecd6cf80Smarks strlen(sh->sh_res) + strlen(sh->sh_fstype) +
220ecd6cf80Smarks strlen(sh->sh_opts) + strlen(sh->sh_descr);
221a237e38eSth }
222a237e38eSth
223*0dfe541eSEvan Layton /* We need to account for field separators and the EOL */
224a237e38eSth sh->sh_size += 5;
225a237e38eSth
226*0dfe541eSEvan Layton /* Now walk down the hash table and add the new entry */
227a237e38eSth for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
228ecd6cf80Smarks s != NULL; s = s->sh_next) {
229a237e38eSth /*
230a237e38eSth * We need exact matches.
231a237e38eSth *
232a237e38eSth * We found a matching path. Either we have a
233a237e38eSth * duplicate path in a share command or we are
234a237e38eSth * being asked to replace an existing entry.
235a237e38eSth */
236a237e38eSth if (strcmp(sh->sh_path, s->sh_path) == 0 &&
237ecd6cf80Smarks strlen(s->sh_path) == iPath) {
238*0dfe541eSEvan Layton if (p != NULL)
239a237e38eSth p->sh_next = sh;
240*0dfe541eSEvan Layton else
241a237e38eSth sht->s_buckets[iHash].ssh_sh = sh;
242a237e38eSth
243a237e38eSth sh->sh_next = s->sh_next;
244a237e38eSth
245*0dfe541eSEvan Layton ASSERT(sg->sharetab_size >= s->sh_size);
246*0dfe541eSEvan Layton sg->sharetab_size -= s->sh_size;
247*0dfe541eSEvan Layton sg->sharetab_size += sh->sh_size;
248a237e38eSth
249*0dfe541eSEvan Layton /* Get rid of the old node */
250a237e38eSth sharefree(s, NULL);
251a237e38eSth
252*0dfe541eSEvan Layton gethrestime(&sg->sharetab_mtime);
253*0dfe541eSEvan Layton atomic_inc_32(&sg->sharetab_generation);
254a237e38eSth
255a237e38eSth ASSERT(sht->s_buckets[iHash].ssh_count != 0);
256*0dfe541eSEvan Layton rw_exit(&sg->sharetab_lock);
257a237e38eSth
258a237e38eSth return (0);
259a237e38eSth }
260a237e38eSth
261a237e38eSth p = s;
262a237e38eSth }
263a237e38eSth
264a237e38eSth /*
265a237e38eSth * Okay, we have gone through the entire hash chain and not
266a237e38eSth * found a match. We just need to add this node.
267a237e38eSth */
268a237e38eSth sh->sh_next = sht->s_buckets[iHash].ssh_sh;
269a237e38eSth sht->s_buckets[iHash].ssh_sh = sh;
2701a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&sht->s_buckets[iHash].ssh_count);
2711a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&sht->s_count);
272*0dfe541eSEvan Layton atomic_inc_32(&sg->sharetab_count);
273*0dfe541eSEvan Layton sg->sharetab_size += sh->sh_size;
274a237e38eSth
275*0dfe541eSEvan Layton gethrestime(&sg->sharetab_mtime);
276*0dfe541eSEvan Layton atomic_inc_32(&sg->sharetab_generation);
277a237e38eSth
278*0dfe541eSEvan Layton rw_exit(&sg->sharetab_lock);
279a237e38eSth
280a237e38eSth return (0);
281a237e38eSth }
282a237e38eSth
283*0dfe541eSEvan Layton /* ARGSUSED */
284*0dfe541eSEvan Layton static void *
sharetab_zone_init(zoneid_t zoneid)285*0dfe541eSEvan Layton sharetab_zone_init(zoneid_t zoneid)
286*0dfe541eSEvan Layton {
287*0dfe541eSEvan Layton sharetab_globals_t *sg;
288*0dfe541eSEvan Layton
289*0dfe541eSEvan Layton sg = kmem_zalloc(sizeof (*sg), KM_SLEEP);
290*0dfe541eSEvan Layton
291*0dfe541eSEvan Layton rw_init(&sg->sharetab_lock, NULL, RW_DEFAULT, NULL);
292*0dfe541eSEvan Layton rw_init(&sg->sharefs_lock, NULL, RW_DEFAULT, NULL);
293*0dfe541eSEvan Layton
294*0dfe541eSEvan Layton sg->sharetab_size = 0;
295*0dfe541eSEvan Layton sg->sharetab_count = 0;
296*0dfe541eSEvan Layton sg->sharetab_generation = 1;
297*0dfe541eSEvan Layton
298*0dfe541eSEvan Layton gethrestime(&sg->sharetab_mtime);
299*0dfe541eSEvan Layton gethrestime(&sg->sharetab_snap_time);
300*0dfe541eSEvan Layton
301*0dfe541eSEvan Layton return (sg);
302*0dfe541eSEvan Layton }
303*0dfe541eSEvan Layton
304*0dfe541eSEvan Layton /* ARGSUSED */
305*0dfe541eSEvan Layton static void
sharetab_zone_fini(zoneid_t zoneid,void * data)306*0dfe541eSEvan Layton sharetab_zone_fini(zoneid_t zoneid, void *data)
307*0dfe541eSEvan Layton {
308*0dfe541eSEvan Layton sharetab_globals_t *sg = data;
309*0dfe541eSEvan Layton
310*0dfe541eSEvan Layton rw_destroy(&sg->sharefs_lock);
311*0dfe541eSEvan Layton rw_destroy(&sg->sharetab_lock);
312*0dfe541eSEvan Layton
313*0dfe541eSEvan Layton /* ALL of the allocated things must be cleaned before we free sg. */
314*0dfe541eSEvan Layton while (sg->sharefs_sharetab != NULL) {
315*0dfe541eSEvan Layton int i;
316*0dfe541eSEvan Layton sharetab_t *freeing = sg->sharefs_sharetab;
317*0dfe541eSEvan Layton
318*0dfe541eSEvan Layton sg->sharefs_sharetab = freeing->s_next;
319*0dfe541eSEvan Layton kmem_free(freeing->s_fstype, strlen(freeing->s_fstype) + 1);
320*0dfe541eSEvan Layton for (i = 0; i < PKP_HASH_SIZE; i++) {
321*0dfe541eSEvan Layton sharefs_hash_head_t *bucket;
322*0dfe541eSEvan Layton
323*0dfe541eSEvan Layton bucket = &(freeing->s_buckets[i]);
324*0dfe541eSEvan Layton while (bucket->ssh_sh != NULL) {
325*0dfe541eSEvan Layton share_t *share = bucket->ssh_sh;
326*0dfe541eSEvan Layton
327*0dfe541eSEvan Layton bucket->ssh_sh = share->sh_next;
328*0dfe541eSEvan Layton sharefree(share, NULL);
329*0dfe541eSEvan Layton }
330*0dfe541eSEvan Layton }
331*0dfe541eSEvan Layton kmem_free(freeing, sizeof (*freeing));
332*0dfe541eSEvan Layton }
333*0dfe541eSEvan Layton
334*0dfe541eSEvan Layton kmem_free(sg, sizeof (*sg));
335*0dfe541eSEvan Layton }
336*0dfe541eSEvan Layton
337a237e38eSth void
sharefs_sharetab_init(void)338a237e38eSth sharefs_sharetab_init(void)
339a237e38eSth {
340*0dfe541eSEvan Layton zone_key_create(&sharetab_zone_key, sharetab_zone_init,
341*0dfe541eSEvan Layton NULL, sharetab_zone_fini);
342*0dfe541eSEvan Layton }
343a237e38eSth
344*0dfe541eSEvan Layton sharetab_globals_t *
sharetab_get_globals(zone_t * zone)345*0dfe541eSEvan Layton sharetab_get_globals(zone_t *zone)
346*0dfe541eSEvan Layton {
347*0dfe541eSEvan Layton return (zone_getspecific(sharetab_zone_key, zone));
348a237e38eSth }
349a237e38eSth
350a237e38eSth int
sharefs_impl(enum sharefs_sys_op opcode,share_t * sh_in,uint32_t iMaxLen)351ecd6cf80Smarks sharefs_impl(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
352a237e38eSth {
353a237e38eSth int error = 0;
354a237e38eSth size_t len;
355a237e38eSth size_t bufsz;
356a237e38eSth share_t *sh;
357a237e38eSth sharefs_lens_t shl;
358a237e38eSth model_t model;
359a237e38eSth char *buf = NULL;
360*0dfe541eSEvan Layton sharetab_globals_t *sg = sharetab_get_globals(curzone);
361a237e38eSth
362a237e38eSth STRUCT_DECL(share, u_sh);
363a237e38eSth
364a237e38eSth bufsz = iMaxLen;
365a237e38eSth
366a237e38eSth /*
367a237e38eSth * Before we do anything, lets make sure we have
368a237e38eSth * a sharetab in memory if we need one.
369a237e38eSth */
370*0dfe541eSEvan Layton rw_enter(&sg->sharetab_lock, RW_READER);
371a237e38eSth switch (opcode) {
372*0dfe541eSEvan Layton case SHAREFS_REMOVE:
373*0dfe541eSEvan Layton case SHAREFS_REPLACE:
374*0dfe541eSEvan Layton if (!sg->sharefs_sharetab) {
375*0dfe541eSEvan Layton rw_exit(&sg->sharetab_lock);
376a237e38eSth return (set_errno(ENOENT));
377a237e38eSth }
378a237e38eSth break;
379*0dfe541eSEvan Layton case SHAREFS_ADD:
380*0dfe541eSEvan Layton default:
381a237e38eSth break;
382a237e38eSth }
383*0dfe541eSEvan Layton rw_exit(&sg->sharetab_lock);
384a237e38eSth
385a237e38eSth model = get_udatamodel();
386a237e38eSth
387a237e38eSth /*
388a237e38eSth * Initialize the data pointers.
389a237e38eSth */
390a237e38eSth STRUCT_INIT(u_sh, model);
391*0dfe541eSEvan Layton if (copyin(sh_in, STRUCT_BUF(u_sh), STRUCT_SIZE(u_sh)))
392a237e38eSth return (set_errno(EFAULT));
393a237e38eSth
394*0dfe541eSEvan Layton /* Get the share */
395a237e38eSth sh = kmem_zalloc(sizeof (share_t), KM_SLEEP);
396a237e38eSth
397*0dfe541eSEvan Layton /* Get some storage for copying in the strings */
398a237e38eSth buf = kmem_zalloc(bufsz + 1, KM_SLEEP);
399a237e38eSth bzero(&shl, sizeof (sharefs_lens_t));
400a237e38eSth
401*0dfe541eSEvan Layton /* Only grab these two until we know what we want */
402a237e38eSth SHARETAB_COPYIN(path);
403a237e38eSth SHARETAB_COPYIN(fstype);
404a237e38eSth
405a237e38eSth switch (opcode) {
406*0dfe541eSEvan Layton case SHAREFS_ADD:
407*0dfe541eSEvan Layton case SHAREFS_REPLACE:
408a237e38eSth SHARETAB_COPYIN(res);
409a237e38eSth SHARETAB_COPYIN(opts);
410a237e38eSth SHARETAB_COPYIN(descr);
411*0dfe541eSEvan Layton error = sharefs_add(sg, sh, &shl);
412a237e38eSth break;
413*0dfe541eSEvan Layton case SHAREFS_REMOVE:
414*0dfe541eSEvan Layton error = sharefs_remove(sg, sh, &shl);
415a237e38eSth break;
416a237e38eSth default:
417a237e38eSth error = EINVAL;
418a237e38eSth break;
419a237e38eSth }
420a237e38eSth
421a237e38eSth cleanup:
422a237e38eSth /*
423a237e38eSth * If there is no error, then we have stashed the structure
424a237e38eSth * away in the sharetab hash table or have deleted it.
425a237e38eSth *
426a237e38eSth * Either way, the only reason to blow away the data is if
427a237e38eSth * there was an error.
428a237e38eSth */
429*0dfe541eSEvan Layton if (error != 0)
430a237e38eSth sharefree(sh, &shl);
431a237e38eSth
432*0dfe541eSEvan Layton if (buf != NULL)
433a237e38eSth kmem_free(buf, bufsz + 1);
434a237e38eSth
435*0dfe541eSEvan Layton return (error != 0 ? set_errno(error) : 0);
436a237e38eSth }
437ecd6cf80Smarks
438ecd6cf80Smarks int
sharefs(enum sharefs_sys_op opcode,share_t * sh_in,uint32_t iMaxLen)439ecd6cf80Smarks sharefs(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
440ecd6cf80Smarks {
441*0dfe541eSEvan Layton /*
442*0dfe541eSEvan Layton * If we're in the global zone PRIV_SYS_CONFIG gives us the
443*0dfe541eSEvan Layton * privileges needed to act on sharetab. However if we're in
444*0dfe541eSEvan Layton * a non-global zone PRIV_SYS_CONFIG is not allowed. To work
445*0dfe541eSEvan Layton * around this issue PRIV_SYS_NFS is used in this case.
446*0dfe541eSEvan Layton *
447*0dfe541eSEvan Layton * TODO: This basically overloads the definition/use of
448*0dfe541eSEvan Layton * PRIV_SYS_NFS to work around the limitation of PRIV_SYS_CONFIG
449*0dfe541eSEvan Layton * in a zone. Solaris 11 solved this by implementing a PRIV_SYS_SHARE
450*0dfe541eSEvan Layton * we should do the same and replace the use of PRIV_SYS_NFS here and
451*0dfe541eSEvan Layton * in zfs_secpolicy_share.
452*0dfe541eSEvan Layton */
453*0dfe541eSEvan Layton if (INGLOBALZONE(curproc)) {
454*0dfe541eSEvan Layton if (secpolicy_sys_config(CRED(), B_FALSE) != 0)
455*0dfe541eSEvan Layton return (set_errno(EPERM));
456*0dfe541eSEvan Layton } else {
457*0dfe541eSEvan Layton /* behave like zfs_secpolicy_share() */
458*0dfe541eSEvan Layton if (secpolicy_nfs(CRED()) != 0)
459*0dfe541eSEvan Layton return (set_errno(EPERM));
460ecd6cf80Smarks
461*0dfe541eSEvan Layton }
462ecd6cf80Smarks return (sharefs_impl(opcode, sh_in, iMaxLen));
463ecd6cf80Smarks }
464