Print this page
2882 implement libzfs_core
2883 changing "canmount" property to "on" should not always remount dataset
2900 "zfs snapshot" should be able to create multiple, arbitrary snapshots at once
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Chris Siden <christopher.siden@delphix.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Bill Pijewski <wdp@joyent.com>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/zfs/dsl_deleg.c
+++ new/usr/src/uts/common/fs/zfs/dsl_deleg.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 2012 by Delphix. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * DSL permissions are stored in a two level zap attribute
28 28 * mechanism. The first level identifies the "class" of
29 29 * entry. The class is identified by the first 2 letters of
30 30 * the attribute. The second letter "l" or "d" identifies whether
31 31 * it is a local or descendent permission. The first letter
32 32 * identifies the type of entry.
33 33 *
34 34 * ul$<id> identifies permissions granted locally for this userid.
35 35 * ud$<id> identifies permissions granted on descendent datasets for
36 36 * this userid.
37 37 * Ul$<id> identifies permission sets granted locally for this userid.
38 38 * Ud$<id> identifies permission sets granted on descendent datasets for
39 39 * this userid.
40 40 * gl$<id> identifies permissions granted locally for this groupid.
41 41 * gd$<id> identifies permissions granted on descendent datasets for
42 42 * this groupid.
43 43 * Gl$<id> identifies permission sets granted locally for this groupid.
44 44 * Gd$<id> identifies permission sets granted on descendent datasets for
45 45 * this groupid.
46 46 * el$ identifies permissions granted locally for everyone.
47 47 * ed$ identifies permissions granted on descendent datasets
48 48 * for everyone.
49 49 * El$ identifies permission sets granted locally for everyone.
50 50 * Ed$ identifies permission sets granted to descendent datasets for
51 51 * everyone.
52 52 * c-$ identifies permission to create at dataset creation time.
53 53 * C-$ identifies permission sets to grant locally at dataset creation
54 54 * time.
55 55 * s-$@<name> permissions defined in specified set @<name>
56 56 * S-$@<name> Sets defined in named set @<name>
57 57 *
58 58 * Each of the above entities points to another zap attribute that contains one
59 59 * attribute for each allowed permission, such as create, destroy,...
60 60 * All of the "upper" case class types will specify permission set names
61 61 * rather than permissions.
62 62 *
63 63 * Basically it looks something like this:
64 64 * ul$12 -> ZAP OBJ -> permissions...
65 65 *
66 66 * The ZAP OBJ is referred to as the jump object.
67 67 */
68 68
69 69 #include <sys/dmu.h>
70 70 #include <sys/dmu_objset.h>
71 71 #include <sys/dmu_tx.h>
72 72 #include <sys/dsl_dataset.h>
73 73 #include <sys/dsl_dir.h>
74 74 #include <sys/dsl_prop.h>
75 75 #include <sys/dsl_synctask.h>
76 76 #include <sys/dsl_deleg.h>
77 77 #include <sys/spa.h>
78 78 #include <sys/zap.h>
79 79 #include <sys/fs/zfs.h>
80 80 #include <sys/cred.h>
81 81 #include <sys/sunddi.h>
82 82
83 83 #include "zfs_deleg.h"
84 84
85 85 /*
86 86 * Validate that user is allowed to delegate specified permissions.
87 87 *
88 88 * In order to delegate "create" you must have "create"
89 89 * and "allow".
90 90 */
91 91 int
92 92 dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr)
93 93 {
94 94 nvpair_t *whopair = NULL;
95 95 int error;
96 96
97 97 if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
98 98 return (error);
99 99
100 100 while (whopair = nvlist_next_nvpair(nvp, whopair)) {
101 101 nvlist_t *perms;
102 102 nvpair_t *permpair = NULL;
103 103
104 104 VERIFY(nvpair_value_nvlist(whopair, &perms) == 0);
105 105
106 106 while (permpair = nvlist_next_nvpair(perms, permpair)) {
107 107 const char *perm = nvpair_name(permpair);
108 108
109 109 if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0)
110 110 return (EPERM);
111 111
112 112 if ((error = dsl_deleg_access(ddname, perm, cr)) != 0)
113 113 return (error);
114 114 }
115 115 }
116 116 return (0);
117 117 }
118 118
119 119 /*
120 120 * Validate that user is allowed to unallow specified permissions. They
121 121 * must have the 'allow' permission, and even then can only unallow
122 122 * perms for their uid.
123 123 */
124 124 int
125 125 dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr)
126 126 {
127 127 nvpair_t *whopair = NULL;
128 128 int error;
129 129 char idstr[32];
130 130
131 131 if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
132 132 return (error);
133 133
134 134 (void) snprintf(idstr, sizeof (idstr), "%lld",
135 135 (longlong_t)crgetuid(cr));
136 136
137 137 while (whopair = nvlist_next_nvpair(nvp, whopair)) {
138 138 zfs_deleg_who_type_t type = nvpair_name(whopair)[0];
139 139
140 140 if (type != ZFS_DELEG_USER &&
141 141 type != ZFS_DELEG_USER_SETS)
142 142 return (EPERM);
143 143
144 144 if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0)
145 145 return (EPERM);
146 146 }
147 147 return (0);
148 148 }
149 149
150 150 static void
151 151 dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
152 152 {
153 153 dsl_dir_t *dd = arg1;
154 154 nvlist_t *nvp = arg2;
155 155 objset_t *mos = dd->dd_pool->dp_meta_objset;
156 156 nvpair_t *whopair = NULL;
157 157 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
158 158
159 159 if (zapobj == 0) {
160 160 dmu_buf_will_dirty(dd->dd_dbuf, tx);
161 161 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
162 162 DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
163 163 }
164 164
165 165 while (whopair = nvlist_next_nvpair(nvp, whopair)) {
166 166 const char *whokey = nvpair_name(whopair);
167 167 nvlist_t *perms;
168 168 nvpair_t *permpair = NULL;
169 169 uint64_t jumpobj;
170 170
171 171 VERIFY(nvpair_value_nvlist(whopair, &perms) == 0);
172 172
173 173 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
↓ open down ↓ |
173 lines elided |
↑ open up ↑ |
174 174 jumpobj = zap_create_link(mos, DMU_OT_DSL_PERMS,
175 175 zapobj, whokey, tx);
176 176 }
177 177
178 178 while (permpair = nvlist_next_nvpair(perms, permpair)) {
179 179 const char *perm = nvpair_name(permpair);
180 180 uint64_t n = 0;
181 181
182 182 VERIFY(zap_update(mos, jumpobj,
183 183 perm, 8, 1, &n, tx) == 0);
184 - spa_history_log_internal(LOG_DS_PERM_UPDATE,
185 - dd->dd_pool->dp_spa, tx,
186 - "%s %s dataset = %llu", whokey, perm,
187 - dd->dd_phys->dd_head_dataset_obj);
184 + spa_history_log_internal_dd(dd, "permission update", tx,
185 + "%s %s", whokey, perm);
188 186 }
189 187 }
190 188 }
191 189
192 190 static void
193 191 dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx)
194 192 {
195 193 dsl_dir_t *dd = arg1;
196 194 nvlist_t *nvp = arg2;
197 195 objset_t *mos = dd->dd_pool->dp_meta_objset;
198 196 nvpair_t *whopair = NULL;
199 197 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
200 198
201 199 if (zapobj == 0)
202 200 return;
203 201
204 202 while (whopair = nvlist_next_nvpair(nvp, whopair)) {
205 203 const char *whokey = nvpair_name(whopair);
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
206 204 nvlist_t *perms;
207 205 nvpair_t *permpair = NULL;
208 206 uint64_t jumpobj;
209 207
210 208 if (nvpair_value_nvlist(whopair, &perms) != 0) {
211 209 if (zap_lookup(mos, zapobj, whokey, 8,
212 210 1, &jumpobj) == 0) {
213 211 (void) zap_remove(mos, zapobj, whokey, tx);
214 212 VERIFY(0 == zap_destroy(mos, jumpobj, tx));
215 213 }
216 - spa_history_log_internal(LOG_DS_PERM_WHO_REMOVE,
217 - dd->dd_pool->dp_spa, tx,
218 - "%s dataset = %llu", whokey,
219 - dd->dd_phys->dd_head_dataset_obj);
214 + spa_history_log_internal_dd(dd, "permission who remove",
215 + tx, "%s", whokey);
220 216 continue;
221 217 }
222 218
223 219 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0)
224 220 continue;
225 221
226 222 while (permpair = nvlist_next_nvpair(perms, permpair)) {
227 223 const char *perm = nvpair_name(permpair);
228 224 uint64_t n = 0;
229 225
230 226 (void) zap_remove(mos, jumpobj, perm, tx);
231 227 if (zap_count(mos, jumpobj, &n) == 0 && n == 0) {
232 228 (void) zap_remove(mos, zapobj,
233 229 whokey, tx);
234 230 VERIFY(0 == zap_destroy(mos,
235 231 jumpobj, tx));
236 232 }
237 - spa_history_log_internal(LOG_DS_PERM_REMOVE,
238 - dd->dd_pool->dp_spa, tx,
239 - "%s %s dataset = %llu", whokey, perm,
240 - dd->dd_phys->dd_head_dataset_obj);
233 + spa_history_log_internal_dd(dd, "permission remove", tx,
234 + "%s %s", whokey, perm);
241 235 }
242 236 }
243 237 }
244 238
245 239 int
246 240 dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset)
247 241 {
248 242 dsl_dir_t *dd;
249 243 int error;
250 244 nvpair_t *whopair = NULL;
251 245 int blocks_modified = 0;
252 246
253 247 error = dsl_dir_open(ddname, FTAG, &dd, NULL);
254 248 if (error)
255 249 return (error);
256 250
257 251 if (spa_version(dmu_objset_spa(dd->dd_pool->dp_meta_objset)) <
258 252 SPA_VERSION_DELEGATED_PERMS) {
259 253 dsl_dir_close(dd, FTAG);
260 254 return (ENOTSUP);
261 255 }
262 256
263 257 while (whopair = nvlist_next_nvpair(nvp, whopair))
264 258 blocks_modified++;
265 259
266 260 error = dsl_sync_task_do(dd->dd_pool, NULL,
267 261 unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync,
268 262 dd, nvp, blocks_modified);
269 263 dsl_dir_close(dd, FTAG);
270 264
271 265 return (error);
272 266 }
273 267
274 268 /*
275 269 * Find all 'allow' permissions from a given point and then continue
276 270 * traversing up to the root.
277 271 *
278 272 * This function constructs an nvlist of nvlists.
279 273 * each setpoint is an nvlist composed of an nvlist of an nvlist
280 274 * of the individual * users/groups/everyone/create
281 275 * permissions.
282 276 *
283 277 * The nvlist will look like this.
284 278 *
285 279 * { source fsname -> { whokeys { permissions,...}, ...}}
286 280 *
287 281 * The fsname nvpairs will be arranged in a bottom up order. For example,
288 282 * if we have the following structure a/b/c then the nvpairs for the fsnames
289 283 * will be ordered a/b/c, a/b, a.
290 284 */
291 285 int
292 286 dsl_deleg_get(const char *ddname, nvlist_t **nvp)
293 287 {
294 288 dsl_dir_t *dd, *startdd;
295 289 dsl_pool_t *dp;
296 290 int error;
297 291 objset_t *mos;
298 292
299 293 error = dsl_dir_open(ddname, FTAG, &startdd, NULL);
300 294 if (error)
301 295 return (error);
302 296
303 297 dp = startdd->dd_pool;
304 298 mos = dp->dp_meta_objset;
305 299
306 300 VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
307 301
308 302 rw_enter(&dp->dp_config_rwlock, RW_READER);
309 303 for (dd = startdd; dd != NULL; dd = dd->dd_parent) {
310 304 zap_cursor_t basezc;
311 305 zap_attribute_t baseza;
312 306 nvlist_t *sp_nvp;
313 307 uint64_t n;
314 308 char source[MAXNAMELEN];
315 309
316 310 if (dd->dd_phys->dd_deleg_zapobj &&
317 311 (zap_count(mos, dd->dd_phys->dd_deleg_zapobj,
318 312 &n) == 0) && n) {
319 313 VERIFY(nvlist_alloc(&sp_nvp,
320 314 NV_UNIQUE_NAME, KM_SLEEP) == 0);
321 315 } else {
322 316 continue;
323 317 }
324 318
325 319 for (zap_cursor_init(&basezc, mos,
326 320 dd->dd_phys->dd_deleg_zapobj);
327 321 zap_cursor_retrieve(&basezc, &baseza) == 0;
328 322 zap_cursor_advance(&basezc)) {
329 323 zap_cursor_t zc;
330 324 zap_attribute_t za;
331 325 nvlist_t *perms_nvp;
332 326
333 327 ASSERT(baseza.za_integer_length == 8);
334 328 ASSERT(baseza.za_num_integers == 1);
335 329
336 330 VERIFY(nvlist_alloc(&perms_nvp,
337 331 NV_UNIQUE_NAME, KM_SLEEP) == 0);
338 332 for (zap_cursor_init(&zc, mos, baseza.za_first_integer);
339 333 zap_cursor_retrieve(&zc, &za) == 0;
340 334 zap_cursor_advance(&zc)) {
341 335 VERIFY(nvlist_add_boolean(perms_nvp,
342 336 za.za_name) == 0);
343 337 }
344 338 zap_cursor_fini(&zc);
345 339 VERIFY(nvlist_add_nvlist(sp_nvp, baseza.za_name,
346 340 perms_nvp) == 0);
347 341 nvlist_free(perms_nvp);
348 342 }
349 343
350 344 zap_cursor_fini(&basezc);
351 345
352 346 dsl_dir_name(dd, source);
353 347 VERIFY(nvlist_add_nvlist(*nvp, source, sp_nvp) == 0);
354 348 nvlist_free(sp_nvp);
355 349 }
356 350 rw_exit(&dp->dp_config_rwlock);
357 351
358 352 dsl_dir_close(startdd, FTAG);
359 353 return (0);
360 354 }
361 355
362 356 /*
363 357 * Routines for dsl_deleg_access() -- access checking.
364 358 */
365 359 typedef struct perm_set {
366 360 avl_node_t p_node;
367 361 boolean_t p_matched;
368 362 char p_setname[ZFS_MAX_DELEG_NAME];
369 363 } perm_set_t;
370 364
371 365 static int
372 366 perm_set_compare(const void *arg1, const void *arg2)
373 367 {
374 368 const perm_set_t *node1 = arg1;
375 369 const perm_set_t *node2 = arg2;
376 370 int val;
377 371
378 372 val = strcmp(node1->p_setname, node2->p_setname);
379 373 if (val == 0)
380 374 return (0);
381 375 return (val > 0 ? 1 : -1);
382 376 }
383 377
384 378 /*
385 379 * Determine whether a specified permission exists.
386 380 *
387 381 * First the base attribute has to be retrieved. i.e. ul$12
388 382 * Once the base object has been retrieved the actual permission
389 383 * is lookup up in the zap object the base object points to.
390 384 *
391 385 * Return 0 if permission exists, ENOENT if there is no whokey, EPERM if
392 386 * there is no perm in that jumpobj.
393 387 */
394 388 static int
395 389 dsl_check_access(objset_t *mos, uint64_t zapobj,
396 390 char type, char checkflag, void *valp, const char *perm)
397 391 {
398 392 int error;
399 393 uint64_t jumpobj, zero;
400 394 char whokey[ZFS_MAX_DELEG_NAME];
401 395
402 396 zfs_deleg_whokey(whokey, type, checkflag, valp);
403 397 error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj);
404 398 if (error == 0) {
405 399 error = zap_lookup(mos, jumpobj, perm, 8, 1, &zero);
406 400 if (error == ENOENT)
407 401 error = EPERM;
408 402 }
409 403 return (error);
410 404 }
411 405
412 406 /*
413 407 * check a specified user/group for a requested permission
414 408 */
415 409 static int
416 410 dsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm,
417 411 int checkflag, cred_t *cr)
418 412 {
419 413 const gid_t *gids;
420 414 int ngids;
421 415 int i;
422 416 uint64_t id;
423 417
424 418 /* check for user */
425 419 id = crgetuid(cr);
426 420 if (dsl_check_access(mos, zapobj,
427 421 ZFS_DELEG_USER, checkflag, &id, perm) == 0)
428 422 return (0);
429 423
430 424 /* check for users primary group */
431 425 id = crgetgid(cr);
432 426 if (dsl_check_access(mos, zapobj,
433 427 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
434 428 return (0);
435 429
436 430 /* check for everyone entry */
437 431 id = -1;
438 432 if (dsl_check_access(mos, zapobj,
439 433 ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0)
440 434 return (0);
441 435
442 436 /* check each supplemental group user is a member of */
443 437 ngids = crgetngroups(cr);
444 438 gids = crgetgroups(cr);
445 439 for (i = 0; i != ngids; i++) {
446 440 id = gids[i];
447 441 if (dsl_check_access(mos, zapobj,
448 442 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
449 443 return (0);
450 444 }
451 445
452 446 return (EPERM);
453 447 }
454 448
455 449 /*
456 450 * Iterate over the sets specified in the specified zapobj
457 451 * and load them into the permsets avl tree.
458 452 */
459 453 static int
460 454 dsl_load_sets(objset_t *mos, uint64_t zapobj,
461 455 char type, char checkflag, void *valp, avl_tree_t *avl)
462 456 {
463 457 zap_cursor_t zc;
464 458 zap_attribute_t za;
465 459 perm_set_t *permnode;
466 460 avl_index_t idx;
467 461 uint64_t jumpobj;
468 462 int error;
469 463 char whokey[ZFS_MAX_DELEG_NAME];
470 464
471 465 zfs_deleg_whokey(whokey, type, checkflag, valp);
472 466
473 467 error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj);
474 468 if (error != 0)
475 469 return (error);
476 470
477 471 for (zap_cursor_init(&zc, mos, jumpobj);
478 472 zap_cursor_retrieve(&zc, &za) == 0;
479 473 zap_cursor_advance(&zc)) {
480 474 permnode = kmem_alloc(sizeof (perm_set_t), KM_SLEEP);
481 475 (void) strlcpy(permnode->p_setname, za.za_name,
482 476 sizeof (permnode->p_setname));
483 477 permnode->p_matched = B_FALSE;
484 478
485 479 if (avl_find(avl, permnode, &idx) == NULL) {
486 480 avl_insert(avl, permnode, idx);
487 481 } else {
488 482 kmem_free(permnode, sizeof (perm_set_t));
489 483 }
490 484 }
491 485 zap_cursor_fini(&zc);
492 486 return (0);
493 487 }
494 488
495 489 /*
496 490 * Load all permissions user based on cred belongs to.
497 491 */
498 492 static void
499 493 dsl_load_user_sets(objset_t *mos, uint64_t zapobj, avl_tree_t *avl,
500 494 char checkflag, cred_t *cr)
501 495 {
502 496 const gid_t *gids;
503 497 int ngids, i;
504 498 uint64_t id;
505 499
506 500 id = crgetuid(cr);
507 501 (void) dsl_load_sets(mos, zapobj,
508 502 ZFS_DELEG_USER_SETS, checkflag, &id, avl);
509 503
510 504 id = crgetgid(cr);
511 505 (void) dsl_load_sets(mos, zapobj,
512 506 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
513 507
514 508 (void) dsl_load_sets(mos, zapobj,
515 509 ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);
516 510
↓ open down ↓ |
266 lines elided |
↑ open up ↑ |
517 511 ngids = crgetngroups(cr);
518 512 gids = crgetgroups(cr);
519 513 for (i = 0; i != ngids; i++) {
520 514 id = gids[i];
521 515 (void) dsl_load_sets(mos, zapobj,
522 516 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
523 517 }
524 518 }
525 519
526 520 /*
527 - * Check if user has requested permission. If descendent is set, must have
528 - * descendent perms.
521 + * Check if user has requested permission.
529 522 */
530 523 int
531 -dsl_deleg_access_impl(dsl_dataset_t *ds, boolean_t descendent, const char *perm,
532 - cred_t *cr)
524 +dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr)
533 525 {
534 526 dsl_dir_t *dd;
535 527 dsl_pool_t *dp;
536 528 void *cookie;
537 529 int error;
538 530 char checkflag;
539 531 objset_t *mos;
540 532 avl_tree_t permsets;
541 533 perm_set_t *setnode;
542 534
543 535 dp = ds->ds_dir->dd_pool;
544 536 mos = dp->dp_meta_objset;
545 537
546 538 if (dsl_delegation_on(mos) == B_FALSE)
547 539 return (ECANCELED);
548 540
549 541 if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
550 542 SPA_VERSION_DELEGATED_PERMS)
551 543 return (EPERM);
552 544
553 - if (dsl_dataset_is_snapshot(ds) || descendent) {
545 + if (dsl_dataset_is_snapshot(ds)) {
554 546 /*
555 547 * Snapshots are treated as descendents only,
556 548 * local permissions do not apply.
557 549 */
558 550 checkflag = ZFS_DELEG_DESCENDENT;
559 551 } else {
560 552 checkflag = ZFS_DELEG_LOCAL;
561 553 }
562 554
563 555 avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
564 556 offsetof(perm_set_t, p_node));
565 557
566 558 rw_enter(&dp->dp_config_rwlock, RW_READER);
567 559 for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
568 560 checkflag = ZFS_DELEG_DESCENDENT) {
569 561 uint64_t zapobj;
570 562 boolean_t expanded;
571 563
572 564 /*
573 565 * If not in global zone then make sure
574 566 * the zoned property is set
575 567 */
576 568 if (!INGLOBALZONE(curproc)) {
577 569 uint64_t zoned;
578 570
579 571 if (dsl_prop_get_dd(dd,
580 572 zfs_prop_to_name(ZFS_PROP_ZONED),
581 573 8, 1, &zoned, NULL, B_FALSE) != 0)
582 574 break;
583 575 if (!zoned)
584 576 break;
585 577 }
586 578 zapobj = dd->dd_phys->dd_deleg_zapobj;
587 579
588 580 if (zapobj == 0)
589 581 continue;
590 582
591 583 dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr);
592 584 again:
593 585 expanded = B_FALSE;
594 586 for (setnode = avl_first(&permsets); setnode;
595 587 setnode = AVL_NEXT(&permsets, setnode)) {
596 588 if (setnode->p_matched == B_TRUE)
597 589 continue;
598 590
599 591 /* See if this set directly grants this permission */
600 592 error = dsl_check_access(mos, zapobj,
601 593 ZFS_DELEG_NAMED_SET, 0, setnode->p_setname, perm);
602 594 if (error == 0)
603 595 goto success;
604 596 if (error == EPERM)
605 597 setnode->p_matched = B_TRUE;
606 598
607 599 /* See if this set includes other sets */
608 600 error = dsl_load_sets(mos, zapobj,
609 601 ZFS_DELEG_NAMED_SET_SETS, 0,
610 602 setnode->p_setname, &permsets);
611 603 if (error == 0)
612 604 setnode->p_matched = expanded = B_TRUE;
613 605 }
614 606 /*
615 607 * If we expanded any sets, that will define more sets,
616 608 * which we need to check.
617 609 */
618 610 if (expanded)
619 611 goto again;
620 612
621 613 error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr);
622 614 if (error == 0)
623 615 goto success;
624 616 }
625 617 error = EPERM;
626 618 success:
627 619 rw_exit(&dp->dp_config_rwlock);
628 620
629 621 cookie = NULL;
630 622 while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
631 623 kmem_free(setnode, sizeof (perm_set_t));
632 624
633 625 return (error);
634 626 }
635 627
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
636 628 int
637 629 dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
638 630 {
639 631 dsl_dataset_t *ds;
640 632 int error;
641 633
642 634 error = dsl_dataset_hold(dsname, FTAG, &ds);
643 635 if (error)
644 636 return (error);
645 637
646 - error = dsl_deleg_access_impl(ds, B_FALSE, perm, cr);
638 + error = dsl_deleg_access_impl(ds, perm, cr);
647 639 dsl_dataset_rele(ds, FTAG);
648 640
649 641 return (error);
650 642 }
651 643
652 644 /*
653 645 * Other routines.
654 646 */
655 647
656 648 static void
657 649 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj,
658 650 boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
659 651 {
660 652 objset_t *mos = dd->dd_pool->dp_meta_objset;
661 653 uint64_t jumpobj, pjumpobj;
662 654 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
663 655 zap_cursor_t zc;
664 656 zap_attribute_t za;
665 657 char whokey[ZFS_MAX_DELEG_NAME];
666 658
667 659 zfs_deleg_whokey(whokey,
668 660 dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE,
669 661 ZFS_DELEG_LOCAL, NULL);
670 662 if (zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj) != 0)
671 663 return;
672 664
673 665 if (zapobj == 0) {
674 666 dmu_buf_will_dirty(dd->dd_dbuf, tx);
675 667 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
676 668 DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
677 669 }
678 670
679 671 zfs_deleg_whokey(whokey,
680 672 dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER,
681 673 ZFS_DELEG_LOCAL, &uid);
682 674 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) {
683 675 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
684 676 VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0);
685 677 }
686 678
687 679 for (zap_cursor_init(&zc, mos, pjumpobj);
688 680 zap_cursor_retrieve(&zc, &za) == 0;
689 681 zap_cursor_advance(&zc)) {
690 682 uint64_t zero = 0;
691 683 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
692 684
693 685 VERIFY(zap_update(mos, jumpobj, za.za_name,
694 686 8, 1, &zero, tx) == 0);
695 687 }
696 688 zap_cursor_fini(&zc);
697 689 }
698 690
699 691 /*
700 692 * set all create time permission on new dataset.
701 693 */
702 694 void
703 695 dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr)
704 696 {
705 697 dsl_dir_t *dd;
706 698 uint64_t uid = crgetuid(cr);
707 699
708 700 if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) <
709 701 SPA_VERSION_DELEGATED_PERMS)
710 702 return;
711 703
712 704 for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) {
713 705 uint64_t pzapobj = dd->dd_phys->dd_deleg_zapobj;
714 706
715 707 if (pzapobj == 0)
716 708 continue;
717 709
718 710 copy_create_perms(sdd, pzapobj, B_FALSE, uid, tx);
719 711 copy_create_perms(sdd, pzapobj, B_TRUE, uid, tx);
720 712 }
721 713 }
722 714
723 715 int
724 716 dsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx)
725 717 {
726 718 zap_cursor_t zc;
727 719 zap_attribute_t za;
728 720
729 721 if (zapobj == 0)
730 722 return (0);
731 723
732 724 for (zap_cursor_init(&zc, mos, zapobj);
733 725 zap_cursor_retrieve(&zc, &za) == 0;
734 726 zap_cursor_advance(&zc)) {
735 727 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
736 728 VERIFY(0 == zap_destroy(mos, za.za_first_integer, tx));
737 729 }
738 730 zap_cursor_fini(&zc);
739 731 VERIFY(0 == zap_destroy(mos, zapobj, tx));
740 732 return (0);
741 733 }
742 734
743 735 boolean_t
744 736 dsl_delegation_on(objset_t *os)
745 737 {
746 738 return (!!spa_delegation(os->os_spa));
747 739 }
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX