@@ -290,6 +290,10 @@ struct mount_attr_s
290
290
# define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only */
291
291
#endif
292
292
293
+ #ifndef MOUNT_ATTR_IDMAP
294
+ # define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */
295
+ #endif
296
+
293
297
static int
294
298
syscall_mount_setattr (int dfd , const char * path , unsigned int flags ,
295
299
struct mount_attr_s * attr )
@@ -358,6 +362,42 @@ make_mount_rro (const char *target, int targetfd, libcrun_error_t *err)
358
362
return 0 ;
359
363
}
360
364
365
+ static int
366
+ get_idmapped_mount (const char * src , pid_t pid , libcrun_error_t * err )
367
+ {
368
+ cleanup_close int open_tree_fd = -1 ;
369
+ cleanup_close int fd = -1 ;
370
+ int ret ;
371
+ char proc_path [64 ];
372
+ struct mount_attr_s attr = {
373
+ 0 ,
374
+ };
375
+
376
+ sprintf (proc_path , "/proc/%d/ns/user" , pid );
377
+ fd = open (proc_path , O_RDONLY );
378
+ if (UNLIKELY (fd < 0 ))
379
+ return crun_make_error (err , errno , "open `%s`" , proc_path );
380
+
381
+ open_tree_fd = syscall_open_tree (-1 , src ,
382
+ AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE );
383
+ if (UNLIKELY (open_tree_fd < 0 ))
384
+ return crun_make_error (err , errno , "open `/%s`" , src );
385
+
386
+ attr .attr_set = MOUNT_ATTR_IDMAP ;
387
+ attr .userns_fd = fd ;
388
+
389
+ ret = syscall_mount_setattr (open_tree_fd , "" , AT_EMPTY_PATH , & attr );
390
+ if (UNLIKELY (ret < 0 ))
391
+ return crun_make_error (err , errno , "mount_setattr `%s`" , src );
392
+
393
+ /*
394
+ ret = syscall_fsmount (open_tree_fd, FSMOUNT_CLOEXEC, 0);
395
+ if (UNLIKELY (ret < 0))
396
+ return crun_make_error (err, errno, "fsmount `%s`", src);
397
+ */
398
+ return get_and_reset (& open_tree_fd );
399
+ }
400
+
361
401
int
362
402
libcrun_create_keyring (const char * name , const char * label , libcrun_error_t * err )
363
403
{
@@ -431,8 +471,11 @@ enum
431
471
{
432
472
OPTION_TMPCOPYUP = (1 << 0 ),
433
473
OPTION_RRO = (1 << 1 ),
474
+ OPTION_IDMAP = (1 << 2 ),
434
475
};
435
476
477
+ #define IDMAP "idmap"
478
+
436
479
static struct propagation_flags_s propagation_flags [] = { { "defaults" , 0 , 0 , 0 },
437
480
{ "bind" , 0 , MS_BIND , 0 },
438
481
{ "rbind" , 0 , MS_REC | MS_BIND , 0 },
@@ -469,6 +512,7 @@ static struct propagation_flags_s propagation_flags[] = { { "defaults", 0, 0, 0
469
512
470
513
{ "tmpcopyup" , 0 , 0 , OPTION_TMPCOPYUP },
471
514
{ "rro" , 0 , 0 , OPTION_RRO },
515
+ { IDMAP , 0 , 0 , OPTION_IDMAP },
472
516
473
517
{ NULL , 0 , 0 , 0 } };
474
518
@@ -1657,7 +1701,8 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
1657
1701
ret = fs_move_mount_to (mfd , targetfd , NULL );
1658
1702
if (LIKELY (ret == 0 ))
1659
1703
{
1660
- ret = do_mount (container , NULL , mfd , target , NULL , flags , data , LABEL_NONE , err );
1704
+ /* Force no MS_BIND flag to not attempt again the bind mount. */
1705
+ ret = do_mount (container , NULL , mfd , target , NULL , flags & ~MS_BIND , data , LABEL_NONE , err );
1661
1706
if (UNLIKELY (ret < 0 ))
1662
1707
return ret ;
1663
1708
mounted = true;
@@ -1710,17 +1755,20 @@ do_mounts (libcrun_container_t *container, int rootfsfd, const char *rootfs, con
1710
1755
return ret ;
1711
1756
}
1712
1757
1713
- if (extra_flags & OPTION_RRO )
1758
+ if (extra_flags & ( OPTION_RRO | OPTION_IDMAP ) )
1714
1759
{
1715
1760
cleanup_close int dfd = -1 ;
1716
1761
1717
1762
dfd = safe_openat (rootfsfd , rootfs , rootfs_len , target , O_DIRECTORY , 0 , err );
1718
1763
if (UNLIKELY (dfd < 0 ))
1719
1764
return crun_make_error (err , errno , "open mount target `/%s`" , target );
1720
1765
1721
- ret = make_mount_rro (target , dfd , err );
1722
- if (UNLIKELY (ret < 0 ))
1723
- return ret ;
1766
+ if (extra_flags & OPTION_RRO )
1767
+ {
1768
+ ret = make_mount_rro (target , dfd , err );
1769
+ if (UNLIKELY (ret < 0 ))
1770
+ return ret ;
1771
+ }
1724
1772
}
1725
1773
}
1726
1774
return 0 ;
@@ -3256,6 +3304,17 @@ get_fd_map (libcrun_container_t *container)
3256
3304
return mount_fds ;
3257
3305
}
3258
3306
3307
+ static bool
3308
+ is_idmapped (runtime_spec_schema_defs_mount * mnt )
3309
+ {
3310
+ size_t i ;
3311
+
3312
+ for (i = 0 ; i < mnt -> options_len ; i ++ )
3313
+ if (strcmp (mnt -> options [i ], IDMAP ) == 0 )
3314
+ return true;
3315
+ return false;
3316
+ }
3317
+
3259
3318
static int
3260
3319
prepare_and_send_mounts (libcrun_container_t * container , pid_t pid , int sync_socket_host , libcrun_error_t * err )
3261
3320
{
@@ -3272,6 +3331,17 @@ prepare_and_send_mounts (libcrun_container_t *container, pid_t pid, int sync_soc
3272
3331
3273
3332
for (i = 0 ; i < def -> mounts_len ; i ++ )
3274
3333
{
3334
+ if (is_idmapped (def -> mounts [i ]))
3335
+ {
3336
+ int fd ;
3337
+
3338
+ fd = get_idmapped_mount (def -> mounts [i ]-> source , pid , err );
3339
+ if (UNLIKELY (fd < 0 ))
3340
+ return fd ;
3341
+
3342
+ mount_fds -> fds [i ] = fd ;
3343
+ }
3344
+
3275
3345
if (mount_fds -> fds [i ] >= 0 )
3276
3346
how_many ++ ;
3277
3347
}
0 commit comments