11package unpacker // import "code.cloudfoundry.org/grootfs/base_image_puller/unpacker"
22
33import (
4+ "bytes"
5+ "encoding/json"
6+ "os"
7+ "syscall"
8+
49 "code.cloudfoundry.org/commandrunner"
10+ "github.com/containers/storage/pkg/reexec"
11+ "github.com/tscolari/lagregator"
12+ "github.com/urfave/cli"
513
14+ "code.cloudfoundry.org/grootfs/base_image_puller"
615 "code.cloudfoundry.org/grootfs/groot"
716 "code.cloudfoundry.org/lager"
17+ errorspkg "github.com/pkg/errors"
818)
919
1020//go:generate counterfeiter . IDMapper
21+
1122type IDMapper interface {
1223 MapUIDs (logger lager.Logger , pid int , mappings []groot.IDMappingSpec ) error
1324 MapGIDs (logger lager.Logger , pid int , mappings []groot.IDMappingSpec ) error
@@ -18,3 +29,128 @@ type NSIdMapperUnpacker struct {
1829 idMapper IDMapper
1930 unpackStrategy UnpackStrategy
2031}
32+
33+ func init () {
34+ reexec .Register ("unpack-wrapper" , func () {
35+ cli .ErrWriter = os .Stdout
36+ logger := lager .NewLogger ("unpack-wrapper" )
37+ logger .RegisterSink (lager .NewWriterSink (os .Stderr , lager .DEBUG ))
38+
39+ if len (os .Args ) != 3 {
40+ logger .Error ("parsing-command" , errorspkg .New ("destination directory or filesystem were not specified" ))
41+ os .Exit (1 )
42+ }
43+
44+ ctrlPipeR := os .NewFile (3 , "/ctrl/pipe" )
45+ buffer := make ([]byte , 1 )
46+ logger .Debug ("waiting-for-control-pipe" )
47+ _ , err := ctrlPipeR .Read (buffer )
48+ if err != nil {
49+ logger .Error ("reading-control-pipe" , err )
50+ os .Exit (1 )
51+ }
52+ logger .Debug ("got-back-from-control-pipe" )
53+
54+ // Once all id mappings are set, we need to spawn the untar function
55+ // in a child proccess, so it can make use of it
56+ targetDir := os .Args [1 ]
57+ unpackStrategyJson := os .Args [2 ]
58+ cmd := reexec .Command ("unpack" , targetDir , unpackStrategyJson )
59+ cmd .Stdout = os .Stdout
60+ cmd .Stderr = os .Stderr
61+ cmd .Stdin = os .Stdin
62+
63+ logger .Debug ("starting-unpack" , lager.Data {
64+ "path" : cmd .Path ,
65+ "args" : cmd .Args ,
66+ })
67+ if err := cmd .Run (); err != nil {
68+ logger .Error ("unpack-command-failed" , err )
69+ os .Exit (1 )
70+ }
71+ logger .Debug ("unpack-command-done" )
72+ })
73+ }
74+
75+ func NewNSIdMapperUnpacker (commandRunner commandrunner.CommandRunner , idMapper IDMapper , strategy UnpackStrategy ) * NSIdMapperUnpacker {
76+ return & NSIdMapperUnpacker {
77+ commandRunner : commandRunner ,
78+ idMapper : idMapper ,
79+ unpackStrategy : strategy ,
80+ }
81+ }
82+
83+ func (u * NSIdMapperUnpacker ) Unpack (logger lager.Logger , spec base_image_puller.UnpackSpec ) error {
84+ logger = logger .Session ("ns-id-mapper-unpacking" , lager.Data {"spec" : spec })
85+ logger .Debug ("starting" )
86+ defer logger .Debug ("ending" )
87+
88+ ctrlPipeR , ctrlPipeW , err := os .Pipe ()
89+ if err != nil {
90+ return errorspkg .Wrap (err , "creating tar control pipe" )
91+ }
92+
93+ unpackStrategyJson , err := json .Marshal (& u .unpackStrategy )
94+ if err != nil {
95+ logger .Error ("unmarshal-unpack-strategy-failed" , err )
96+ return errorspkg .Wrap (err , "unmarshal unpack strategy" )
97+ }
98+
99+ unpackCmd := reexec .Command ("unpack-wrapper" , spec .TargetPath , string (unpackStrategyJson ))
100+ unpackCmd .Stdin = spec .Stream
101+ if len (spec .UIDMappings ) > 0 || len (spec .GIDMappings ) > 0 {
102+ unpackCmd .SysProcAttr = & syscall.SysProcAttr {
103+ Cloneflags : syscall .CLONE_NEWUSER ,
104+ }
105+ }
106+
107+ outBuffer := bytes .NewBuffer ([]byte {})
108+ unpackCmd .Stdout = outBuffer
109+ unpackCmd .Stderr = lagregator .NewRelogger (logger )
110+ unpackCmd .ExtraFiles = []* os.File {ctrlPipeR }
111+
112+ logger .Debug ("starting-unpack-wrapper-command" , lager.Data {
113+ "path" : unpackCmd .Path ,
114+ "args" : unpackCmd .Args ,
115+ })
116+ if err := u .commandRunner .Start (unpackCmd ); err != nil {
117+ return errorspkg .Wrap (err , "starting unpack command" )
118+ }
119+ logger .Debug ("unpack-wrapper-command-is-started" )
120+
121+ if err := u .setIDMappings (logger , spec , unpackCmd .Process .Pid ); err != nil {
122+ _ = ctrlPipeW .Close ()
123+ return err
124+ }
125+
126+ if _ , err := ctrlPipeW .Write ([]byte {0 }); err != nil {
127+ return errorspkg .Wrap (err , "writing to tar control pipe" )
128+ }
129+ logger .Debug ("unpack-wrapper-command-is-signaled-to-continue" )
130+
131+ logger .Debug ("waiting-for-unpack-wrapper-command" )
132+ if err := u .commandRunner .Wait (unpackCmd ); err != nil {
133+ return errorspkg .Errorf (outBuffer .String ())
134+ }
135+ logger .Debug ("unpack-wrapper-command-done" )
136+
137+ return nil
138+ }
139+
140+ func (u * NSIdMapperUnpacker ) setIDMappings (logger lager.Logger , spec base_image_puller.UnpackSpec , untarPid int ) error {
141+ if len (spec .UIDMappings ) > 0 {
142+ if err := u .idMapper .MapUIDs (logger , untarPid , spec .UIDMappings ); err != nil {
143+ return errorspkg .Wrap (err , "setting uid mapping" )
144+ }
145+ logger .Debug ("uid-mappings-are-set" )
146+ }
147+
148+ if len (spec .GIDMappings ) > 0 {
149+ if err := u .idMapper .MapGIDs (logger , untarPid , spec .GIDMappings ); err != nil {
150+ return errorspkg .Wrap (err , "setting gid mapping" )
151+ }
152+ logger .Debug ("gid-mappings-are-set" )
153+ }
154+
155+ return nil
156+ }
0 commit comments