Skip to content

Commit

Permalink
Fixes #24
Browse files Browse the repository at this point in the history
  • Loading branch information
targodan committed Jun 1, 2022
1 parent a9d97f4 commit 0f9bc8f
Show file tree
Hide file tree
Showing 9 changed files with 755 additions and 2 deletions.
23 changes: 22 additions & 1 deletion procio/memory_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bufio"
"fmt"
"io"
"os"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -106,7 +107,7 @@ func stateSegmentHead(in *bufio.Reader, out chan<- *MemorySegmentInfo, lastSeg *
}

func parseSegmentHead(line string) (*MemorySegmentInfo, error) {
line = strings.TrimSpace(line)
line = strings.TrimRight(line, "\n")
matches := segmentHeadRegex.FindStringSubmatch(line)
if len(matches) != expectedFieldCount {
return nil, fmt.Errorf("invalid format \"%s\"", line)
Expand Down Expand Up @@ -228,6 +229,26 @@ func parseBytes(value string) (uintptr, error) {
return uintptr(amountUint) * detailUnitMultiplier, nil
}

func sanitizeMappedFile(proc Process, seg *MemorySegmentInfo) {
if seg.MappedFile == nil {
return
}
originalPath := seg.MappedFile.Path()
if strings.Contains(originalPath, "\\012") {
// newline characters are encoded as '\012', but we cannot distinguish between an actual
// literal '\012' or it representing the newline character => lookup the link
linkPath := fmt.Sprintf("%s/%d/map_files/%x-%x", procPath, proc.PID(), seg.BaseAddress, seg.BaseAddress+seg.Size)
actualPath, err := os.Readlink(linkPath)
if err != nil {
// Could not read the link => leave it as-is
return
}
if originalPath != actualPath {
seg.MappedFile = fileio.NewFile(actualPath)
}
}
}

// PermissionsToNative converts the given Permissions to the
// native linux representation.
func PermissionsToNative(perms Permissions) int {
Expand Down
142 changes: 142 additions & 0 deletions procio/memory_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"fmt"
"io"
"os"
"testing"

"github.com/fkie-cad/yapscan/fileio"
Expand Down Expand Up @@ -160,6 +161,52 @@ func TestParseSegmentHead(t *testing.T) {
})
})

Convey("A private file-backed segment with whitespaces should work", t, func() {
info, err := parseSegmentHead("00400000-0048a000 r-xp 00000000 fd:03 960637 /bin/some path/with whitespaces.txt")
So(err, ShouldBeNil)
So(info, ShouldResemble, &MemorySegmentInfo{
ParentBaseAddress: 0x400000,
BaseAddress: 0x400000,
AllocatedPermissions: Permissions{
Read: true, Execute: true,
},
CurrentPermissions: Permissions{
Read: true, Execute: true,
},
Size: 0x8a000,
RSS: 0,
State: StateCommit,
Type: SegmentTypePrivateMapped,
MappedFile: &fileio.OSFile{
FilePath: "/bin/some path/with whitespaces.txt",
},
SubSegments: []*MemorySegmentInfo{},
})
})

Convey("A private file-backed segment with trailing whitespace should work", t, func() {
info, err := parseSegmentHead("00400000-0048a000 r-xp 00000000 fd:03 960637 /bin/bash ")
So(err, ShouldBeNil)
So(info, ShouldResemble, &MemorySegmentInfo{
ParentBaseAddress: 0x400000,
BaseAddress: 0x400000,
AllocatedPermissions: Permissions{
Read: true, Execute: true,
},
CurrentPermissions: Permissions{
Read: true, Execute: true,
},
Size: 0x8a000,
RSS: 0,
State: StateCommit,
Type: SegmentTypePrivateMapped,
MappedFile: &fileio.OSFile{
FilePath: "/bin/bash ",
},
SubSegments: []*MemorySegmentInfo{},
})
})

Convey("A shared file-backed segment should work", t, func() {
info, err := parseSegmentHead("00400000-0048a000 rwxs 00000000 fd:03 960637 /bin/bash")
So(err, ShouldBeNil)
Expand Down Expand Up @@ -351,3 +398,98 @@ func TestPermissionsToNative(t *testing.T) {
})
}
}

func TestSanitizeMappedFile(t *testing.T) {
Convey("Sanitizing a segment without a mapped file should do nothing", t, func() {
proc := NewMockProcess(t)

seg := &MemorySegmentInfo{}
sanitizeMappedFile(proc, seg)
So(seg, ShouldResemble, &MemorySegmentInfo{})
})

Convey("Sanitizing a segment with a mapped file", t, func() {
Convey("without any special escapes should do nothing", func() {
proc := NewMockProcess(t)

seg := &MemorySegmentInfo{
MappedFile: fileio.NewFile("/some/normal/path"),
}

sanitizeMappedFile(proc, seg)

So(seg, ShouldResemble, &MemorySegmentInfo{
MappedFile: fileio.NewFile("/some/normal/path"),
})
})

Convey("with a newline escape sequence", func() {
pid := 42
proc := NewMockProcess(t)
proc.On("PID").Return(pid)

Convey("where the link is non-existent should do nothing", func() {
seg := &MemorySegmentInfo{
MappedFile: fileio.NewFile("/path/withEscapeSequence\\012"),
}

sanitizeMappedFile(proc, seg)

So(seg, ShouldResemble, &MemorySegmentInfo{
MappedFile: fileio.NewFile("/path/withEscapeSequence\\012"),
})
})

Convey("but the link shows its a literal '\\012' should do nothing", func() {
origProcPath := procPath
defer func() {
procPath = origProcPath
}()

tempdir := t.TempDir()
procPath = tempdir

mappedName := "/path/withEscapeSequence\\012/but/notANewline"
seg := &MemorySegmentInfo{
MappedFile: fileio.NewFile(mappedName),
}

mapFilesPath := fmt.Sprintf("%s/%d/map_files", tempdir, pid)
os.MkdirAll(mapFilesPath, 0700)
os.Symlink(mappedName, fmt.Sprintf("%s/%x-%x", mapFilesPath, seg.BaseAddress, seg.BaseAddress+seg.Size))

sanitizeMappedFile(proc, seg)

So(seg, ShouldResemble, &MemorySegmentInfo{
MappedFile: fileio.NewFile(mappedName),
})
})

Convey("and its a newline character should replace the path", func() {
origProcPath := procPath
defer func() {
procPath = origProcPath
}()

tempdir := t.TempDir()
procPath = tempdir

mappedName := "/path/withEscapeSequence\\012/asNewline"
readName := "/path/withEscapeSequence\n/asNewline"
seg := &MemorySegmentInfo{
MappedFile: fileio.NewFile(mappedName),
}

mapFilesPath := fmt.Sprintf("%s/%d/map_files", tempdir, pid)
os.MkdirAll(mapFilesPath, 0700)
os.Symlink(readName, fmt.Sprintf("%s/%x-%x", mapFilesPath, seg.BaseAddress, seg.BaseAddress+seg.Size))

sanitizeMappedFile(proc, seg)

So(seg, ShouldResemble, &MemorySegmentInfo{
MappedFile: fileio.NewFile(readName),
})
})
})
})
}
175 changes: 175 additions & 0 deletions procio/mock_CachingProcess_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 0f9bc8f

Please sign in to comment.