-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: lifubang <[email protected]>
- Loading branch information
Showing
11 changed files
with
411 additions
and
824 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
package libcontainer | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/opencontainers/runc/libcontainer/configs" | ||
"github.com/opencontainers/runc/libcontainer/system" | ||
"github.com/sirupsen/logrus" | ||
"github.com/vishvananda/netlink/nl" | ||
"golang.org/x/sys/execabs" | ||
"golang.org/x/sys/unix" | ||
) | ||
|
||
// NsExecSyncMsg is used for communication between the parent and child during | ||
// container setup. | ||
type NsExecSyncMsg uint32 | ||
|
||
const ( | ||
syncUsermapPls NsExecSyncMsg = iota + 0x40 | ||
syncUsermapAck | ||
syncRecvPidPls | ||
syncRecvPidAck | ||
syncTimeOffsetsPls | ||
syncTimeOffsetsAck | ||
) | ||
|
||
type NsExecSetup struct { | ||
process *containerProcess | ||
} | ||
|
||
const bufSize int = 4 | ||
|
||
// parseNsExecSync runs the given callback function on each message received | ||
// from the child. It will return once the child sends SYNC_RECVPID_PLS. | ||
func parseNsExecSync(r io.Reader, fn func(NsExecSyncMsg) error) error { | ||
logrus.Debugf("start to communicate with the nsexec\n") | ||
var msg NsExecSyncMsg | ||
var buf [bufSize]byte | ||
native := nl.NativeEndian() | ||
|
||
for { | ||
if _, err := io.ReadAtLeast(r, buf[:], bufSize); err != nil { | ||
return err | ||
} | ||
msg = NsExecSyncMsg(native.Uint32(buf[:])) | ||
if err := fn(msg); err != nil { | ||
return err | ||
} | ||
if msg == syncRecvPidPls { | ||
break | ||
} | ||
} | ||
logrus.Debugf("finished communicating with the nsexec\n") | ||
return nil | ||
} | ||
|
||
// ackSyncMsg is used to send a message to the child. | ||
func ackSyncMsg(f *os.File, msg NsExecSyncMsg) error { | ||
var buf [bufSize]byte | ||
native := nl.NativeEndian() | ||
native.PutUint32(buf[:], uint32(msg)) | ||
if _, err := unix.Write(int(f.Fd()), buf[:]); err != nil { | ||
logrus.Debugf("failed to write message to nsexec: %v", err) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
// helpDoingNsExec is used to help the process to communicate with the nsexec. | ||
func (s *NsExecSetup) helpDoingNsExec() error { | ||
return parseNsExecSync(s.process.comm.stage1SockParent, func(msg NsExecSyncMsg) error { | ||
switch msg { | ||
case syncUsermapPls: | ||
logrus.Debugf("stage-1 requested userns mappings") | ||
if err := s.setupUsermap(); err != nil { | ||
return err | ||
} | ||
return ackSyncMsg(s.process.comm.stage1SockParent, syncUsermapAck) | ||
case syncRecvPidPls: | ||
logrus.Debugf("stage-1 reports pid") | ||
if err := json.NewDecoder(s.process.comm.stage1SockParent).Decode(&s.process.childPid); err != nil { | ||
return err | ||
} | ||
return ackSyncMsg(s.process.comm.stage1SockParent, syncRecvPidAck) | ||
case syncTimeOffsetsPls: | ||
logrus.Debugf("stage-1 requested timens offsets to be configured") | ||
if err := system.UpdateTimeNsOffsets(s.process.cmd.Process.Pid, s.process.container.config.TimeOffsets); err != nil { | ||
return err | ||
} | ||
return ackSyncMsg(s.process.comm.stage1SockParent, syncTimeOffsetsAck) | ||
default: | ||
} | ||
return fmt.Errorf("unexpected message %d", msg) | ||
}) | ||
} | ||
|
||
// setupUsermap is used to set up the user mappings. | ||
func (s *NsExecSetup) setupUsermap() error { | ||
var uidMapPath, gidMapPath string | ||
/* | ||
* Enable setgroups(2) if we've been asked to. But we also | ||
* have to explicitly disable setgroups(2) if we're | ||
* creating a rootless container for single-entry mapping. | ||
* i.e. config.is_setgroup == false. | ||
* (this is required since Linux 3.19). | ||
* | ||
* For rootless multi-entry mapping, config.is_setgroup shall be true and | ||
* newuidmap/newgidmap shall be used. | ||
*/ | ||
if s.process.config.RootlessEUID && !requiresRootOrMappingTool(s.process.config.Config.GIDMappings) { | ||
_ = system.UpdateSetgroups(s.process.cmd.Process.Pid, system.SetgroupsDeny) | ||
} | ||
|
||
nsMaps := make(map[configs.NamespaceType]string) | ||
for _, ns := range s.process.container.config.Namespaces { | ||
if ns.Path != "" { | ||
nsMaps[ns.Type] = ns.Path | ||
} | ||
} | ||
_, joinExistingUser := nsMaps[configs.NEWUSER] | ||
if !joinExistingUser { | ||
// write uid mappings | ||
if len(s.process.container.config.UIDMappings) > 0 { | ||
if s.process.container.config.RootlessEUID { | ||
if path, err := execabs.LookPath("newuidmap"); err == nil { | ||
uidMapPath = path | ||
} | ||
} | ||
} | ||
|
||
// write gid mappings | ||
if len(s.process.container.config.GIDMappings) > 0 { | ||
if s.process.container.config.RootlessEUID { | ||
if path, err := execabs.LookPath("newgidmap"); err == nil { | ||
gidMapPath = path | ||
} | ||
} | ||
} | ||
} | ||
|
||
/* Set up mappings. */ | ||
if err := system.UpdateUidmap(uidMapPath, s.process.cmd.Process.Pid, s.process.container.config.UIDMappings); err != nil { | ||
return err | ||
} | ||
return system.UpdateGidmap(gidMapPath, s.process.cmd.Process.Pid, s.process.container.config.GIDMappings) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.