1- from os import CLONE_NEWNS , CLONE_NEWUSER , getlogin , unshare
1+ from os import CLONE_NEWNS , CLONE_NEWUSER , getlogin , unshare , getuid
22from subprocess import CalledProcessError , run
33
44
@@ -19,11 +19,32 @@ def get_id_map(username=None, id_type="uid"):
1919 raise ValueError (f"User { username } not found in /etc/sub{ id_type } " )
2020
2121
22+ def write_id_map (id_type , pid , * args , failures = 0 ):
23+ if id_type not in ("uid" , "gid" ):
24+ raise ValueError ("id_type must be 'uid' or 'gid" )
25+
26+ map_file = f"/proc/{ pid } /uid_map" if id_type == "uid" else f"/proc/{ pid } /gid_map"
27+
28+ # Get id, nsid, count tuples from args
29+ map_contents = [f"{ id } { nsid } { count } " for id , nsid , count in zip (* [iter (args )] * 3 )]
30+
31+ try :
32+ with open (map_file , "w" ) as f :
33+ f .write ("\n " .join (map_contents ))
34+ except PermissionError as e :
35+ if failures > 5 :
36+ raise e
37+ new_id_map (id_type , pid , * args , failures = failures + 1 )
38+
2239def new_id_map (id_type , pid , id , nsid , count = 1 , * args , failures = 0 ):
2340 if id_type not in ("uid" , "gid" ):
2441 raise ValueError ("id_type must be 'uid' or 'gid" )
25- cmd_args = [f"new{ id_type } map" , str (pid ), str (id ), str (nsid ), str (count ), * map (str , args )]
42+
43+ if getuid () == 0 :
44+ return write_id_map (id_type , pid , id , nsid , count , * args )
45+
2646 try :
47+ cmd_args = [f"new{ id_type } map" , str (pid ), str (id ), str (nsid ), str (count ), * map (str , args )]
2748 return run (cmd_args , check = True , capture_output = True )
2849 except CalledProcessError as e :
2950 if failures > 5 :
0 commit comments