@@ -430,6 +430,92 @@ get_bind_mount (const char *src, libcrun_error_t *err)
430430 return get_and_reset (& open_tree_fd );
431431}
432432
433+ int
434+ parse_idmapped_mount_option (runtime_spec_schema_config_schema * def , bool is_uids , char * option , char * * out , size_t * len , libcrun_error_t * err )
435+ {
436+ size_t written = 0 , allocated = 256 ;
437+ cleanup_free char * mappings = NULL ;
438+ const char * it ;
439+
440+ mappings = xmalloc (allocated );
441+
442+ for (it = option ; * it ;)
443+ {
444+ bool relative = false;
445+ long value [3 ];
446+ size_t i ;
447+
448+ if (* it == '\0' )
449+ break ;
450+
451+ if (* it == '#' )
452+ it ++ ;
453+
454+ if (* it == '@' )
455+ {
456+ relative = true;
457+ it ++ ;
458+ }
459+
460+ /* read a triplet: file system id - host id - size. */
461+ for (i = 0 ; i < 3 ; i ++ )
462+ {
463+ char * endptr = NULL ;
464+
465+ if (i > 0 && * it == '-' )
466+ it ++ ;
467+
468+ if (* it == '\0' )
469+ return crun_make_error (err , errno , "invalid mapping specified `%s`" , option );
470+
471+ errno = 0 ;
472+ value [i ] = strtol (it , & endptr , 10 );
473+ if (errno || endptr == it )
474+ return crun_make_error (err , errno , "invalid mapping specified `%s`" , option );
475+
476+ it = endptr ;
477+ }
478+
479+ if (relative )
480+ {
481+ runtime_spec_schema_defs_id_mapping * * mappings ;
482+ size_t mappings_len ;
483+
484+ if (def == NULL
485+ || def -> linux == NULL
486+ || (is_uids && def -> linux -> uid_mappings_len == 0 )
487+ || (! is_uids && def -> linux -> gid_mappings_len == 0 ))
488+ return crun_make_error (err , 0 , "specified a relative mapping without user namespace mappings" );
489+
490+ mappings_len = (is_uids ? def -> linux -> uid_mappings_len : def -> linux -> gid_mappings_len );
491+ mappings = is_uids ? def -> linux -> uid_mappings : def -> linux -> gid_mappings ;
492+
493+ for (i = 0 ; i < mappings_len ; i ++ )
494+ if (value [0 ] >= mappings [i ]-> container_id && value [0 ] < mappings [i ]-> container_id + mappings [i ]-> size )
495+ break ;
496+
497+ if (i == mappings_len )
498+ return crun_make_error (err , 0 , "could not find a user namespace mapping for the relative mapping `%s`" , option );
499+
500+ value [1 ] += mappings [i ]-> host_id - mappings [i ]-> container_id ;
501+ }
502+ if (written > allocated - 64 )
503+ {
504+ allocated += 256 ;
505+ mappings = xrealloc (mappings , allocated );
506+ }
507+ written += sprintf (mappings + written , "%ld %ld %ld\n" , value [0 ], value [1 ], value [2 ]);
508+ }
509+ * (mappings + written ) = '\0' ;
510+
511+ * len = written ;
512+
513+ * out = mappings ;
514+ mappings = NULL ;
515+
516+ return 0 ;
517+ }
518+
433519static pid_t
434520create_userns_for_idmapped_mount (runtime_spec_schema_config_schema * def , const char * options , libcrun_error_t * err )
435521{
@@ -453,7 +539,6 @@ create_userns_for_idmapped_mount (runtime_spec_schema_config_schema *def, const
453539 for (option = strtok_r (dup_options , ";" , & saveptr ); option ; option = strtok_r (NULL , ";" , & saveptr ))
454540 {
455541 cleanup_free char * mappings = NULL ;
456- char * ids , * it , * it_mappings ;
457542 bool is_uids = false;
458543 char proc_file [64 ];
459544 size_t len = 0 ;
@@ -469,85 +554,11 @@ create_userns_for_idmapped_mount (runtime_spec_schema_config_schema *def, const
469554 else
470555 return crun_make_error (err , 0 , "invalid option `%s` specified" , option );
471556
472- ids = option + 5 /* strlen ("uids=") and strlen ("gids=") */ ;
473-
474- for (it = ids ; * it ; it ++ )
475- {
476- /* Account for the maximum length. */
477- if (* it == '-' )
478- len += 10 /* strlen ("4294967295") */ + 1 ;
479- len ++ ;
480- }
481-
482- it_mappings = mappings = xmalloc (len + 1 );
483-
484- for (it = ids ; * it ;)
485- {
486- bool relative = false;
487- long value [3 ];
488- size_t i ;
489-
490- * it_mappings = * it ;
491-
492- if (* it == '\0' )
493- break ;
494-
495- if (* it == '#' )
496- it ++ ;
497-
498- if (* it == '@' )
499- {
500- relative = true;
501- it ++ ;
502- }
503-
504- /* read a triplet: file system id - host id - size. */
505- for (i = 0 ; i < 3 ; i ++ )
506- {
507- char * endptr = NULL ;
508-
509- if (i > 0 && * it == '-' )
510- it ++ ;
511-
512- if (* it == '\0' )
513- return crun_make_error (err , errno , "invalid mapping specified `%s`" , option );
514-
515- errno = 0 ;
516- value [i ] = strtol (it , & endptr , 10 );
517- if (errno || endptr == it )
518- return crun_make_error (err , errno , "invalid mapping specified `%s`" , option );
519-
520- it = endptr ;
521- }
522-
523- if (relative )
524- {
525- runtime_spec_schema_defs_id_mapping * * mappings ;
526- size_t mappings_len ;
527-
528- if (def -> linux == NULL
529- || (is_uids && def -> linux -> uid_mappings_len == 0 )
530- || (! is_uids && def -> linux -> gid_mappings_len == 0 ))
531- return crun_make_error (err , 0 , "specified a relative mapping without user namespace mappings" );
532-
533- mappings_len = (is_uids ? def -> linux -> uid_mappings_len : def -> linux -> gid_mappings_len );
534- mappings = is_uids ? def -> linux -> uid_mappings : def -> linux -> gid_mappings ;
535-
536- for (i = 0 ; i < mappings_len ; i ++ )
537- if (value [0 ] >= mappings [i ]-> container_id && value [0 ] < mappings [i ]-> container_id + mappings [i ]-> size )
538- break ;
539-
540- if (i == mappings_len )
541- return crun_make_error (err , 0 , "could not find a user namespace mapping for the relative mapping `%s`" , option );
542-
543- value [1 ] += mappings [i ]-> host_id - mappings [i ]-> container_id ;
544- }
545-
546- it_mappings += sprintf (it_mappings , "%ld %ld %ld\n" , value [0 ], value [1 ], value [2 ]);
547- }
548- * it_mappings = '\0' ;
557+ ret = parse_idmapped_mount_option (def , is_uids , option + 5 /* strlen ("uids="), strlen ("gids=")*/ , & mappings , & len , err );
558+ if (UNLIKELY (ret < 0 ))
559+ return ret ;
549560
550- ret = write_file (proc_file , mappings , it_mappings - mappings , err );
561+ ret = write_file (proc_file , mappings , len , err );
551562 if (UNLIKELY (ret < 0 ))
552563 return ret ;
553564 }
0 commit comments