Skip to content

Commit

Permalink
update im
Browse files Browse the repository at this point in the history
Signed-off-by: David Ko <dko@suse.com>
  • Loading branch information
innobead committed Dec 9, 2021
1 parent 1ee56be commit 884c12d
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 5 deletions.
53 changes: 51 additions & 2 deletions pkg/process/process_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package process

import (
"fmt"
"path/filepath"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -111,6 +112,44 @@ func (pm *Manager) Shutdown() {
close(pm.shutdownCh)
}

func decodeProcessPath(path string) (dir, image, binary string) {
path, binary = filepath.Split(filepath.Clean(path))
dir, image = filepath.Split(filepath.Clean(path))
return dir, image, binary
}

func isValidBinary(binary string) bool {
switch binary {
case "longhorn":
return true
default:
return false
}
}

func isValidDirectory(dir string) bool {
switch dir {
case "/engine-binaries/", "/host/var/lib/longhorn/engine-binaries/":
return true
default:
return false
}
}

func ensureValidProcessPath(path string) (string, error) {
dir, image, binary := decodeProcessPath(path)
logrus.Debugf("Process Manager: validate process path: %v dir: %v image: %v binary: %v", path, dir, image, binary)
if !isValidBinary(binary) {
return "", fmt.Errorf("unsupported binary %v", binary)
}

if !isValidDirectory(dir) {
return "", fmt.Errorf("unsupported process path %v", path)
}

return filepath.Join(dir, image, binary), nil
}

// ProcessCreate will create a process according to the request.
// If the specified process name exists already, the creation will fail.
func (pm *Manager) ProcessCreate(ctx context.Context, req *rpc.ProcessCreateRequest) (ret *rpc.ProcessResponse, err error) {
Expand All @@ -124,9 +163,14 @@ func (pm *Manager) ProcessCreate(ctx context.Context, req *rpc.ProcessCreateRequ
return nil, err
}

processPath, err := ensureValidProcessPath(req.Spec.Binary)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

p := &Process{
Name: req.Spec.Name,
Binary: req.Spec.Binary,
Binary: processPath,
Args: req.Spec.Args,
PortCount: req.Spec.PortCount,
PortArgs: req.Spec.PortArgs,
Expand Down Expand Up @@ -381,6 +425,11 @@ func (pm *Manager) ProcessReplace(ctx context.Context, req *rpc.ProcessReplaceRe
}
terminateSignal := syscall.SIGHUP

processPath, err := ensureValidProcessPath(req.Spec.Binary)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

logrus.Infof("Process Manager: prepare to replace process %v", req.Spec.Name)
logger, err := util.NewLonghornWriter(req.Spec.Name, pm.logsDir)
if err != nil {
Expand All @@ -389,7 +438,7 @@ func (pm *Manager) ProcessReplace(ctx context.Context, req *rpc.ProcessReplaceRe

p := &Process{
Name: req.Spec.Name,
Binary: req.Spec.Binary,
Binary: processPath,
Args: req.Spec.Args,
PortCount: req.Spec.PortCount,
PortArgs: req.Spec.PortArgs,
Expand Down
62 changes: 59 additions & 3 deletions pkg/process/process_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (
const (
RetryCount = 50
RetryInterval = 100 * time.Millisecond
TestBinary = "any"
TestBinaryMissing = "fail-missing-binary"
TestBinaryReplace = "replacement"
TestBinary = "/engine-binaries/test/longhorn"
TestBinaryMissing = "/engine-binaries/test-missing/longhorn"
TestBinaryReplace = "/engine-binaries/test-replacement/longhorn"
)

func Test(t *testing.T) { TestingT(t) }
Expand Down Expand Up @@ -285,6 +285,62 @@ func (s *TestSuite) TestProcessReplaceDuringDeletion(c *C) {
wg.Wait()
}

func (s *TestSuite) TestProcessInvalidProcessBinary(c *C) {

invalidBinaries := []string{
"/usr/bin/echo",
"/engine-binaries/invalid-binary",
"/host/var/lib/longhorn/engine-binaries/invalid-binary",
"/host/var/lib/longhorn/../longhorn/engine-binaries//../engine-binaries/valid-image/invalid-binary",
}
invalidPaths := []string{
"longhorn",
"/longhorn",
"/engine-binaries/invalid/image/longhorn",
"/engine-binaries/longhorn", // missing required image folder
"/invalid/path/longhorn",
}
invalidProcess := append(invalidBinaries, invalidPaths...)

// invalid process creation
for i, binary := range invalidProcess {
name := "test_invalid_process-" + strconv.Itoa(i)
createReq := &rpc.ProcessCreateRequest{
Spec: createProcessSpec(name, binary),
}
createResp, err := s.pm.ProcessCreate(nil, createReq)
c.Assert(createResp, IsNil)
c.Assert(err, NotNil)
c.Assert(status.Code(err), Equals, codes.InvalidArgument)
}

// valid process creation
name := "test_valid_process"
assertProcessCreation(c, s.pm, name, TestBinary)
defer func() {
// verify that the original process is not impacted by an invalid process replace call
assertProcessDeletion(c, s.pm, name)
deleted, err := waitForProcessListState(s.pm, func(processes map[string]*rpc.ProcessResponse) bool {
_, exists := processes[name]
return !exists
})
c.Assert(err, IsNil)
c.Assert(deleted, Equals, true)
}()

// invalid process replacement
for _, binary := range invalidProcess {
replaceReq := &rpc.ProcessReplaceRequest{
Spec: createProcessSpec(name, binary),
TerminateSignal: "SIGHUP",
}
rsp, err := s.pm.ProcessReplace(nil, replaceReq)
c.Assert(rsp, IsNil)
c.Assert(err, NotNil)
c.Assert(status.Code(err), Equals, codes.InvalidArgument)
}
}

func assertProcessReplace(c *C, pm *Manager, name, binary string) {
replaceReq := &rpc.ProcessReplaceRequest{
Spec: createProcessSpec(name, binary),
Expand Down

0 comments on commit 884c12d

Please sign in to comment.