64
64
#include <sys/dsl_dir.h>
65
65
#include <sys/spa_boot.h>
66
66
#include <sys/jail.h>
67
+ #include <sys/osd.h>
67
68
#include <ufs/ufs/quota.h>
68
69
#include <sys/zfs_quota.h>
69
70
@@ -89,12 +90,19 @@ int zfs_debug_level;
89
90
SYSCTL_INT (_vfs_zfs , OID_AUTO , debug , CTLFLAG_RWTUN , & zfs_debug_level , 0 ,
90
91
"Debug level" );
91
92
92
- /* BEGIN CSTYLED */
93
- int zfs_jail_mount_snapshot ;
94
- SYSCTL_INT (_vfs_zfs , OID_AUTO , jail_mount_snapshot , CTLFLAG_RW ,
95
- & zfs_jail_mount_snapshot , 0 ,
96
- "Allow mounting snapshots in the .zfs directory within jails" );
97
- /* END CSTYLED */
93
+ struct zfs_jailparam {
94
+ int mount_snapshot ;
95
+ };
96
+
97
+ static struct zfs_jailparam zfs_jailparam0 = {
98
+ .mount_snapshot = 0 ,
99
+ };
100
+
101
+ static int zfs_jailparam_slot ;
102
+
103
+ SYSCTL_JAIL_PARAM_SYS_NODE (zfs , CTLFLAG_RW , "Jail ZFS parameters" );
104
+ SYSCTL_JAIL_PARAM (_zfs , mount_snapshot , CTLTYPE_INT | CTLFLAG_RW , "I" ,
105
+ "Allow mounting snapshots in the .zfs directory for unjailed datasets" );
98
106
99
107
SYSCTL_NODE (_vfs_zfs , OID_AUTO , version , CTLFLAG_RD , 0 , "ZFS versions" );
100
108
static int zfs_version_acl = ZFS_ACL_VERSION ;
@@ -1393,10 +1401,28 @@ zfs_mount(vfs_t *vfsp)
1393
1401
* dataset is not visible.
1394
1402
*/
1395
1403
if (!INGLOBALZONE (curproc ) &&
1396
- !(isctlsnap && zfs_jail_mount_snapshot ) &&
1397
1404
(!zone_dataset_visible (osname , & canwrite ) || !canwrite )) {
1398
- error = SET_ERROR (EPERM );
1399
- goto out ;
1405
+ boolean_t mount_snapshot = B_FALSE ;
1406
+
1407
+ /*
1408
+ * Snapshots may be mounted in .zfs for unjailed datasets
1409
+ * if allowed by the jail param zfs.mount_snapshot.
1410
+ */
1411
+ if (isctlsnap ) {
1412
+ struct prison * pr ;
1413
+ struct zfs_jailparam * zjp ;
1414
+
1415
+ pr = curthread -> td_ucred -> cr_prison ;
1416
+ mtx_lock (& pr -> pr_mtx );
1417
+ zjp = osd_jail_get (pr , zfs_jailparam_slot );
1418
+ mtx_unlock (& pr -> pr_mtx );
1419
+ if (zjp && zjp -> mount_snapshot )
1420
+ mount_snapshot = B_TRUE ;
1421
+ }
1422
+ if (!mount_snapshot ) {
1423
+ error = SET_ERROR (EPERM );
1424
+ goto out ;
1425
+ }
1400
1426
}
1401
1427
1402
1428
vfsp -> vfs_flag |= MNT_NFS4ACLS ;
@@ -2315,7 +2341,6 @@ zfs_get_vfs_flag_unmounted(objset_t *os)
2315
2341
return (unmounted );
2316
2342
}
2317
2343
2318
- #ifdef _KERNEL
2319
2344
void
2320
2345
zfsvfs_update_fromname (const char * oldname , const char * newname )
2321
2346
{
@@ -2345,4 +2370,225 @@ zfsvfs_update_fromname(const char *oldname, const char *newname)
2345
2370
}
2346
2371
mtx_unlock (& mountlist_mtx );
2347
2372
}
2348
- #endif
2373
+
2374
+ /*
2375
+ * Find a prison with ZFS info.
2376
+ * Return the ZFS info and the (locked) prison.
2377
+ */
2378
+ static struct zfs_jailparam *
2379
+ zfs_jailparam_find (struct prison * spr , struct prison * * prp )
2380
+ {
2381
+ struct prison * pr ;
2382
+ struct zfs_jailparam * zjp ;
2383
+
2384
+ for (pr = spr ; ; pr = pr -> pr_parent ) {
2385
+ mtx_lock (& pr -> pr_mtx );
2386
+ if (pr == & prison0 ) {
2387
+ zjp = & zfs_jailparam0 ;
2388
+ break ;
2389
+ }
2390
+ zjp = osd_jail_get (pr , zfs_jailparam_slot );
2391
+ if (zjp != NULL )
2392
+ break ;
2393
+ mtx_unlock (& pr -> pr_mtx );
2394
+ }
2395
+ * prp = pr ;
2396
+
2397
+ return (zjp );
2398
+ }
2399
+
2400
+ /*
2401
+ * Ensure a prison has its own ZFS info. If zjpp is non-null, point it to the
2402
+ * ZFS info and lock the prison.
2403
+ */
2404
+ static void
2405
+ zfs_jailparam_alloc (struct prison * pr , struct zfs_jailparam * * zjpp )
2406
+ {
2407
+ struct prison * ppr ;
2408
+ struct zfs_jailparam * zjp , * nzjp ;
2409
+ void * * rsv ;
2410
+
2411
+ /* If this prison already has ZFS info, return that. */
2412
+ zjp = zfs_jailparam_find (pr , & ppr );
2413
+ if (ppr == pr )
2414
+ goto done ;
2415
+
2416
+ /*
2417
+ * Allocate a new info record. Then check again, in case something
2418
+ * changed during the allocation.
2419
+ */
2420
+ mtx_unlock (& ppr -> pr_mtx );
2421
+ nzjp = malloc (sizeof (struct zfs_jailparam ), M_PRISON , M_WAITOK );
2422
+ rsv = osd_reserve (zfs_jailparam_slot );
2423
+ zjp = zfs_jailparam_find (pr , & ppr );
2424
+ if (ppr == pr ) {
2425
+ free (nzjp , M_PRISON );
2426
+ osd_free_reserved (rsv );
2427
+ goto done ;
2428
+ }
2429
+ /* Inherit the initial values from the ancestor. */
2430
+ mtx_lock (& pr -> pr_mtx );
2431
+ (void ) osd_jail_set_reserved (pr , zfs_jailparam_slot , rsv , nzjp );
2432
+ (void ) memcpy (nzjp , zjp , sizeof (* zjp ));
2433
+ zjp = nzjp ;
2434
+ mtx_unlock (& ppr -> pr_mtx );
2435
+ done :
2436
+ if (zjpp != NULL )
2437
+ * zjpp = zjp ;
2438
+ else
2439
+ mtx_unlock (& pr -> pr_mtx );
2440
+ }
2441
+
2442
+ /*
2443
+ * Jail OSD methods for ZFS VFS info.
2444
+ */
2445
+ static int
2446
+ zfs_jailparam_create (void * obj , void * data )
2447
+ {
2448
+ struct prison * pr = obj ;
2449
+ struct vfsoptlist * opts = data ;
2450
+ int jsys ;
2451
+
2452
+ if (vfs_copyopt (opts , "zfs" , & jsys , sizeof (jsys )) == 0 &&
2453
+ jsys == JAIL_SYS_INHERIT )
2454
+ return (0 );
2455
+ /*
2456
+ * Inherit a prison's initial values from its parent
2457
+ * (different from JAIL_SYS_INHERIT which also inherits changes).
2458
+ */
2459
+ zfs_jailparam_alloc (pr , NULL );
2460
+ return (0 );
2461
+ }
2462
+
2463
+ static int
2464
+ zfs_jailparam_get (void * obj , void * data )
2465
+ {
2466
+ struct prison * ppr , * pr = obj ;
2467
+ struct vfsoptlist * opts = data ;
2468
+ struct zfs_jailparam * zjp ;
2469
+ int jsys , error ;
2470
+
2471
+ zjp = zfs_jailparam_find (pr , & ppr );
2472
+ jsys = (ppr == pr ) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT ;
2473
+ error = vfs_setopt (opts , "zfs" , & jsys , sizeof (jsys ));
2474
+ if (error != 0 && error != ENOENT )
2475
+ goto done ;
2476
+ if (jsys == JAIL_SYS_NEW ) {
2477
+ error = vfs_setopt (opts , "zfs.mount_snapshot" ,
2478
+ & zjp -> mount_snapshot , sizeof (zjp -> mount_snapshot ));
2479
+ if (error != 0 && error != ENOENT )
2480
+ goto done ;
2481
+ } else {
2482
+ /*
2483
+ * If this prison is inheriting its ZFS info, report
2484
+ * empty/zero parameters.
2485
+ */
2486
+ static int mount_snapshot = 0 ;
2487
+
2488
+ error = vfs_setopt (opts , "zfs.mount_snapshot" ,
2489
+ & mount_snapshot , sizeof (mount_snapshot ));
2490
+ if (error != 0 && error != ENOENT )
2491
+ goto done ;
2492
+ }
2493
+ error = 0 ;
2494
+ done :
2495
+ mtx_unlock (& ppr -> pr_mtx );
2496
+ return (error );
2497
+ }
2498
+
2499
+ static int
2500
+ zfs_jailparam_set (void * obj , void * data )
2501
+ {
2502
+ struct prison * pr = obj ;
2503
+ struct vfsoptlist * opts = data ;
2504
+ int error , jsys , mount_snapshot ;
2505
+
2506
+ /* Set the parameters, which should be correct. */
2507
+ error = vfs_copyopt (opts , "zfs" , & jsys , sizeof (jsys ));
2508
+ if (error == ENOENT )
2509
+ jsys = -1 ;
2510
+ error = vfs_copyopt (opts , "zfs.mount_snapshot" , & mount_snapshot ,
2511
+ sizeof (mount_snapshot ));
2512
+ if (error == ENOENT )
2513
+ mount_snapshot = -1 ;
2514
+ else
2515
+ jsys = JAIL_SYS_NEW ;
2516
+ if (jsys == JAIL_SYS_NEW ) {
2517
+ /* "zfs=new" or "zfs.*": the prison gets its own ZFS info. */
2518
+ struct zfs_jailparam * zjp ;
2519
+
2520
+ zfs_jailparam_alloc (pr , & zjp );
2521
+ if (mount_snapshot != -1 )
2522
+ zjp -> mount_snapshot = mount_snapshot ;
2523
+ mtx_unlock (& pr -> pr_mtx );
2524
+ } else {
2525
+ /* "zfs=inherit": inherit the parent's ZFS info. */
2526
+ mtx_lock (& pr -> pr_mtx );
2527
+ osd_jail_del (pr , zfs_jailparam_slot );
2528
+ mtx_unlock (& pr -> pr_mtx );
2529
+ }
2530
+ return (0 );
2531
+ }
2532
+
2533
+ static int
2534
+ zfs_jailparam_check (void * obj __unused , void * data )
2535
+ {
2536
+ struct vfsoptlist * opts = data ;
2537
+ int error , jsys , mount_snapshot ;
2538
+
2539
+ /* Check that the parameters are correct. */
2540
+ error = vfs_copyopt (opts , "zfs" , & jsys , sizeof (jsys ));
2541
+ if (error != ENOENT ) {
2542
+ if (error != 0 )
2543
+ return (error );
2544
+ if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT )
2545
+ return (EINVAL );
2546
+ }
2547
+ error = vfs_copyopt (opts , "zfs.mount_snapshot" , & mount_snapshot ,
2548
+ sizeof (mount_snapshot ));
2549
+ if (error != ENOENT ) {
2550
+ if (error != 0 )
2551
+ return (error );
2552
+ if (mount_snapshot != 0 && mount_snapshot != 1 )
2553
+ return (EINVAL );
2554
+ }
2555
+ return (0 );
2556
+ }
2557
+
2558
+ static void
2559
+ zfs_jailparam_destroy (void * data )
2560
+ {
2561
+
2562
+ free (data , M_PRISON );
2563
+ }
2564
+
2565
+ static void
2566
+ zfs_jailparam_sysinit (void * arg __unused )
2567
+ {
2568
+ struct prison * pr ;
2569
+ osd_method_t methods [PR_MAXMETHOD ] = {
2570
+ [PR_METHOD_CREATE ] = zfs_jailparam_create ,
2571
+ [PR_METHOD_GET ] = zfs_jailparam_get ,
2572
+ [PR_METHOD_SET ] = zfs_jailparam_set ,
2573
+ [PR_METHOD_CHECK ] = zfs_jailparam_check ,
2574
+ };
2575
+
2576
+ zfs_jailparam_slot = osd_jail_register (zfs_jailparam_destroy , methods );
2577
+ /* Copy the defaults to any existing prisons. */
2578
+ sx_slock (& allprison_lock );
2579
+ TAILQ_FOREACH (pr , & allprison , pr_list )
2580
+ zfs_jailparam_alloc (pr , NULL );
2581
+ sx_sunlock (& allprison_lock );
2582
+ }
2583
+
2584
+ static void
2585
+ zfs_jailparam_sysuninit (void * arg __unused )
2586
+ {
2587
+
2588
+ osd_jail_deregister (zfs_jailparam_slot );
2589
+ }
2590
+
2591
+ SYSINIT (zfs_jailparam_sysinit , SI_SUB_DRIVERS , SI_ORDER_ANY ,
2592
+ zfs_jailparam_sysinit , NULL );
2593
+ SYSUNINIT (zfs_jailparam_sysuninit , SI_SUB_DRIVERS , SI_ORDER_ANY ,
2594
+ zfs_jailparam_sysuninit , NULL );
0 commit comments