Skip to content

Commit

Permalink
Host.WriteFile move from os to syscall style
Browse files Browse the repository at this point in the history
Change Host.WriteFile to receive mode bits like os.Chmod, to fix issues with os abstraction preventing some bits from being set (eg: SUID).

commit-id:80a7ec02
  • Loading branch information
fornellas committed Oct 7, 2024
1 parent 2ff4402 commit f17af69
Show file tree
Hide file tree
Showing 11 changed files with 44 additions and 48 deletions.
5 changes: 2 additions & 3 deletions host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"context"
"fmt"
"os"
"os/user"
)

Expand Down Expand Up @@ -54,8 +53,8 @@ type Host interface {
// // Symlink works similar to os.Symlink.
// Symlink(ctx context.Context, oldname, newname string) error

// WriteFile works similar to os.WriteFile.
WriteFile(ctx context.Context, name string, data []byte, perm os.FileMode) error
// WriteFile works similar to os.WriteFile, but receives mode as is syscall.Chmod argument.
WriteFile(ctx context.Context, name string, data []byte, mode uint32) error

// A string representation of the host which uniquely identifies it, eg, its FQDN.
String() string
Expand Down
2 changes: 1 addition & 1 deletion internal/host/agent_grpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ func (a AgentGrpcClient) Run(ctx context.Context, cmd host.Cmd) (host.WaitStatus
// return cs.WaitStatus, nil
}

func (a AgentGrpcClient) WriteFile(ctx context.Context, name string, data []byte, perm os.FileMode) error {
func (a AgentGrpcClient) WriteFile(ctx context.Context, name string, data []byte, mode uint32) error {
panic("todo write file")
// logger := log.MustLogger(ctx)

Expand Down
6 changes: 3 additions & 3 deletions internal/host/agent_http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,16 +476,16 @@ func (a AgentHttpClient) Run(ctx context.Context, cmd host.Cmd) (host.WaitStatus
return cs.WaitStatus, nil
}

func (a AgentHttpClient) WriteFile(ctx context.Context, name string, data []byte, perm os.FileMode) error {
func (a AgentHttpClient) WriteFile(ctx context.Context, name string, data []byte, mode uint32) error {
logger := log.MustLogger(ctx)

logger.Debug("WriteFile", "name", name, "data", data, "perm", perm)
logger.Debug("WriteFile", "name", name, "data", data, "mode", mode)

if !filepath.IsAbs(name) {
return fmt.Errorf("path must be absolute: %s", name)
}

_, err := a.put(fmt.Sprintf("/file%s?perm=%d", name, perm), bytes.NewReader(data))
_, err := a.put(fmt.Sprintf("/file%s?mode=%d", name, mode), bytes.NewReader(data))
if err != nil {
return err
}
Expand Down
20 changes: 12 additions & 8 deletions internal/host/agent_server_http/main_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,33 @@ func PutFileFn(ctx context.Context) func(http.ResponseWriter, *http.Request) {
}
name = fmt.Sprintf("%c%s", os.PathSeparator, name)

perms, ok := r.URL.Query()["perm"]
modes, ok := r.URL.Query()["mode"]
if !ok {
internalServerError(w, errors.New("missing perm from query"))
internalServerError(w, errors.New("missing mode from query"))
return
}
if len(perms) != 1 {
internalServerError(w, fmt.Errorf("received multiple perm: %#v", perms))
if len(modes) != 1 {
internalServerError(w, fmt.Errorf("received multiple mode: %#v", modes))
return
}
permInt, err := strconv.ParseInt(perms[0], 10, 32)
modeInt, err := strconv.ParseUint(modes[0], 10, 32)
if err != nil {
internalServerError(w, fmt.Errorf("failed to parse perm: %#v: %s", perms[0], err))
internalServerError(w, fmt.Errorf("failed to parse mode: %#v: %s", modes[0], err))
return
}
perm := os.FileMode(permInt)
mode := uint32(modeInt)

body, err := io.ReadAll(r.Body)
if err != nil {
internalServerError(w, err)
return
}

if err := os.WriteFile(name, body, perm); err != nil {
if err := os.WriteFile(name, body, fs.FileMode(mode)); err != nil {
internalServerError(w, err)
return
}
if err := syscall.Chmod(name, mode); err != nil {
internalServerError(w, err)
return
}
Expand Down
14 changes: 4 additions & 10 deletions internal/host/cmd_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,10 +540,10 @@ func (br cmdHost) Remove(ctx context.Context, name string) error {
return nil
}

func (br cmdHost) WriteFile(ctx context.Context, name string, data []byte, perm os.FileMode) error {
func (br cmdHost) WriteFile(ctx context.Context, name string, data []byte, mode uint32) error {
logger := log.MustLogger(ctx)

logger.Debug("WriteFile", "name", name, "data", data, "perm", perm)
logger.Debug("WriteFile", "name", name, "data", data, "mode", mode)

if !filepath.IsAbs(name) {
return &fs.PathError{
Expand All @@ -553,10 +553,6 @@ func (br cmdHost) WriteFile(ctx context.Context, name string, data []byte, perm
}
}

var chmod bool
if _, err := br.Lstat(ctx, name); errors.Is(err, os.ErrNotExist) {
chmod = true
}
cmd := host.Cmd{
Path: "sh",
Args: []string{"-c", fmt.Sprintf("cat > %s", shellescape.Quote(name))},
Expand All @@ -581,8 +577,6 @@ func (br cmdHost) WriteFile(ctx context.Context, name string, data []byte, perm
cmd, waitStatus.String(), stdout, stderr,
)
}
if chmod {
return br.Chmod(ctx, name, uint32(perm))
}
return nil

return br.Chmod(ctx, name, mode)
}
3 changes: 1 addition & 2 deletions internal/host/cmd_run_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package host
import (
"context"
"errors"
"os"
"os/user"
"testing"

Expand Down Expand Up @@ -65,7 +64,7 @@ func (h cmdHostOnly) Remove(ctx context.Context, name string) error {
return err
}

func (h cmdHostOnly) WriteFile(ctx context.Context, name string, data []byte, perm os.FileMode) error {
func (h cmdHostOnly) WriteFile(ctx context.Context, name string, data []byte, mode uint32) error {
err := errors.New("unexpected call received: WriteFile")
h.T.Fatal(err)
return err
Expand Down
9 changes: 6 additions & 3 deletions internal/host/local_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ func (l Local) Run(ctx context.Context, cmd host.Cmd) (host.WaitStatus, error) {
return local_run.Run(ctx, cmd)
}

func (l Local) WriteFile(ctx context.Context, name string, data []byte, perm os.FileMode) error {
func (l Local) WriteFile(ctx context.Context, name string, data []byte, mode uint32) error {
logger := log.MustLogger(ctx)
logger.Debug("WriteFile", "name", name, "data", data, "perm", perm)
logger.Debug("WriteFile", "name", name, "data", data, "mode", mode)

if !filepath.IsAbs(name) {
return &fs.PathError{
Expand All @@ -169,7 +169,10 @@ func (l Local) WriteFile(ctx context.Context, name string, data []byte, perm os.
}
}

return os.WriteFile(name, data, perm)
if err := os.WriteFile(name, data, fs.FileMode(mode)); err != nil {
return err
}
return syscall.Chmod(name, mode)
}

func (l Local) String() string {
Expand Down
23 changes: 10 additions & 13 deletions internal/host/test_helpers_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"context"
"fmt"
"io/fs"
"net"
"os"
"os/user"
Expand Down Expand Up @@ -559,16 +558,15 @@ func testHost(t *testing.T, hst host.Host) {
outputBuffer.Reset()
name := filepath.Join(t.TempDir(), "foo")
data := []byte("foo")
fileMode := os.FileMode(0600)
var fileMode uint32 = 01607
err := hst.WriteFile(ctx, name, data, fileMode)
require.NoError(t, err)
readData, err := os.ReadFile(name)
require.NoError(t, err)
require.Equal(t, data, readData)
fileInfo, err := os.Lstat(name)
require.NoError(t, err)
require.False(t, fileInfo.IsDir())
require.Equal(t, fileMode, fileInfo.Mode()&fs.ModePerm)
var stat_t syscall.Stat_t
require.NoError(t, syscall.Lstat(name, &stat_t))
require.Equal(t, fileMode, stat_t.Mode&07777)
})
t.Run("path must be absolute", func(t *testing.T) {
outputBuffer.Reset()
Expand All @@ -584,27 +582,26 @@ func testHost(t *testing.T, hst host.Host) {
t.Run("ovewrite file", func(t *testing.T) {
outputBuffer.Reset()
name := filepath.Join(t.TempDir(), "foo")
fileMode := os.FileMode(0600)
var fileMode uint32 = 01607
err := hst.WriteFile(ctx, name, []byte{}, fileMode)
require.NoError(t, err)
data := []byte("foo")
newFileMode := os.FileMode(0640)
var newFileMode uint32 = 02675
err = hst.WriteFile(ctx, name, data, newFileMode)
require.NoError(t, err)
readData, err := os.ReadFile(name)
require.NoError(t, err)
require.Equal(t, data, readData)
fileInfo, err := os.Lstat(name)
require.NoError(t, err)
require.False(t, fileInfo.IsDir())
require.Equal(t, fileMode, fileInfo.Mode()&fs.ModePerm)
var stat_t syscall.Stat_t
require.NoError(t, syscall.Lstat(name, &stat_t))
require.Equal(t, newFileMode, stat_t.Mode&07777)
})
t.Run("is directory", func(t *testing.T) {
outputBuffer.Reset()
name := filepath.Join(t.TempDir(), "foo")
err := os.Mkdir(name, os.FileMode(0700))
require.NoError(t, err)
err = hst.WriteFile(ctx, name, []byte{}, os.FileMode(0640))
err = hst.WriteFile(ctx, name, []byte{}, 0640)
require.Error(t, err)
})
t.Run("ErrNotExist", func(t *testing.T) {
Expand Down
6 changes: 3 additions & 3 deletions internal/plan/prep_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestSaveOriginalResourcesState(t *testing.T) {
filePath := filepath.Join(t.TempDir(), "foo")
fileContent := "foo"
var fileMode uint32 = 0644
err := host.WriteFile(ctx, filePath, []byte("foo"), os.FileMode(fileMode))
err := host.WriteFile(ctx, filePath, []byte("foo"), fileMode)
require.NoError(t, err)
fileResource := &resouresPkg.File{
Path: filePath,
Expand Down Expand Up @@ -107,8 +107,8 @@ func TestLoadOrCreateAndSaveLastBlueprintWithValidation(t *testing.T) {

filePath := filepath.Join(t.TempDir(), "foo")
fileContent := "foo"
filePerm := os.FileMode(0644)
err := host.WriteFile(ctx, filePath, []byte("foo"), filePerm)
var fileMode uint32 = 0644
err := host.WriteFile(ctx, filePath, []byte("foo"), fileMode)
require.NoError(t, err)
fileResource := &resouresPkg.File{
Path: filePath,
Expand Down
2 changes: 1 addition & 1 deletion internal/store/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func (s *HostStore) saveYaml(ctx context.Context, obj any, path string) error {
return err
}

return s.Host.WriteFile(ctx, path, blueprintBytes, os.FileMode(0600))
return s.Host.WriteFile(ctx, path, blueprintBytes, 0600)
}

func (s *HostStore) SaveLastBlueprint(ctx context.Context, blueprint *blueprintPkg.Blueprint) error {
Expand Down
2 changes: 1 addition & 1 deletion resources/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (f *File) Apply(ctx context.Context, hst host.Host) error {
}

// Content
if err := hst.WriteFile(ctx, string(f.Path), []byte(f.Content), os.FileMode(f.Mode)); err != nil {
if err := hst.WriteFile(ctx, string(f.Path), []byte(f.Content), f.Mode); err != nil {
return err
}

Expand Down

0 comments on commit f17af69

Please sign in to comment.