diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/spec/spec.go | 34 | ||||
-rw-r--r-- | pkg/varlinkapi/containers.go | 17 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 8 | ||||
-rw-r--r-- | pkg/varlinkapi/transfers.go | 75 |
4 files changed, 123 insertions, 11 deletions
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 46105af4a..76b8963ff 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -9,6 +9,7 @@ import ( "github.com/containers/storage/pkg/mount" "github.com/docker/docker/daemon/caps" "github.com/docker/go-units" + "github.com/opencontainers/runc/libcontainer/user" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/pkg/errors" @@ -45,6 +46,18 @@ func supercedeUserMounts(mounts []spec.Mount, configMount []spec.Mount) []spec.M return configMount } +func getAvailableGids() (int64, error) { + idMap, err := user.ParseIDMapFile("/proc/self/gid_map") + if err != nil { + return 0, err + } + count := int64(0) + for _, r := range idMap { + count += r.Count + } + return count, nil +} + // CreateConfigToOCISpec parses information needed to create a container into an OCI runtime spec func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint cgroupPerm := "ro" @@ -91,14 +104,21 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint g.AddMount(sysMnt) } if isRootless { - g.RemoveMount("/dev/pts") - devPts := spec.Mount{ - Destination: "/dev/pts", - Type: "devpts", - Source: "devpts", - Options: []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"}, + nGids, err := getAvailableGids() + if err != nil { + return nil, err + } + if nGids < 5 { + // If we have no GID mappings, the gid=5 default option would fail, so drop it. + g.RemoveMount("/dev/pts") + devPts := spec.Mount{ + Destination: "/dev/pts", + Type: "devpts", + Source: "devpts", + Options: []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"}, + } + g.AddMount(devPts) } - g.AddMount(devPts) } if inUserNS && config.IpcMode.IsHost() { g.RemoveMount("/dev/mqueue") diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index a01e3cc2b..737e2dd96 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "os" "syscall" "time" @@ -194,15 +195,25 @@ func (i *LibpodAPI) ListContainerChanges(call iopodman.VarlinkCall, name string) } // ExportContainer ... -func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, path string) error { +func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath string) error { ctr, err := i.Runtime.LookupContainer(name) if err != nil { return call.ReplyContainerNotFound(name) } - if err := ctr.Export(path); err != nil { + outputFile, err := ioutil.TempFile("", "varlink_recv") + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + defer outputFile.Close() + if outPath == "" { + outPath = outputFile.Name() + } + if err := ctr.Export(outPath); err != nil { return call.ReplyErrorOccurred(err.Error()) } - return call.ReplyExportContainer(path) + return call.ReplyExportContainer(outPath) + } // GetContainerStats ... diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index 0ab645802..5e0889645 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -500,7 +500,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch } // ImportImage imports an image from a tarball to the image store -func (i *LibpodAPI) ImportImage(call iopodman.VarlinkCall, source, reference, message string, changes []string) error { +func (i *LibpodAPI) ImportImage(call iopodman.VarlinkCall, source, reference, message string, changes []string, delete bool) error { configChanges, err := util.GetImageConfig(changes) if err != nil { return call.ReplyErrorOccurred(err.Error()) @@ -516,6 +516,12 @@ func (i *LibpodAPI) ImportImage(call iopodman.VarlinkCall, source, reference, me if err != nil { return call.ReplyErrorOccurred(err.Error()) } + if delete { + if err := os.Remove(source); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + } + return call.ReplyImportImage(newImage.ID()) } diff --git a/pkg/varlinkapi/transfers.go b/pkg/varlinkapi/transfers.go new file mode 100644 index 000000000..0cb7e5e2e --- /dev/null +++ b/pkg/varlinkapi/transfers.go @@ -0,0 +1,75 @@ +package varlinkapi + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os" + + "github.com/containers/libpod/cmd/podman/varlink" +) + +// SendFile allows a client to send a file to the varlink server +func (i *LibpodAPI) SendFile(call iopodman.VarlinkCall, ftype string, length int64) error { + if !call.WantsUpgrade() { + return call.ReplyErrorOccurred("client must use upgraded connection to send files") + } + + outputFile, err := ioutil.TempFile("", "varlink_send") + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + defer outputFile.Close() + + if err = call.ReplySendFile(outputFile.Name()); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + writer := bufio.NewWriter(outputFile) + defer writer.Flush() + + reader := call.Call.Reader + if _, err := io.CopyN(writer, reader, length); err != nil { + return err + } + + // Send an ACK to the client + call.Call.Writer.WriteString(fmt.Sprintf("%s:", outputFile.Name())) + call.Call.Writer.Flush() + return nil + +} + +// ReceiveFile allows the varlink server to send a file to a client +func (i *LibpodAPI) ReceiveFile(call iopodman.VarlinkCall, filepath string, delete bool) error { + if !call.WantsUpgrade() { + return call.ReplyErrorOccurred("client must use upgraded connection to send files") + } + fs, err := os.Open(filepath) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + fileInfo, err := fs.Stat() + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + // Send the file length down to client + // Varlink connection upraded + if err = call.ReplyReceiveFile(fileInfo.Size()); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + reader := bufio.NewReader(fs) + _, err = reader.WriteTo(call.Writer) + if err != nil { + return err + } + if delete { + if err := os.Remove(filepath); err != nil { + return err + } + } + return call.Writer.Flush() +} |