Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate through calls more selectively to avoid false positives #292

Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ func (s Source) CopyPointer() (*Source, error) {
return &s, nil
}

func (s Source) Propagate(str string) string {
return str
}

type TaggedSource struct {
Data string `levee:"source"`
ID int
Expand All @@ -62,7 +58,3 @@ func (i Innocuous) GetID() int {
func (i Innocuous) GetData() string {
return i.Data
}

type SourceManipulator interface {
Propagate(string) string
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,56 +15,31 @@
package callorder

import (
"fmt"
"io"
PurelyApplied marked this conversation as resolved.
Show resolved Hide resolved
"levee_analysistest/example/core"
)

func TestTaintedColocatedArgumentDoesNotReachSinkThatPrecedesColocation() {
s := core.Source{}
i := newInnocuous()
if err := fail(i); err != nil {
core.Sink(err)
func TestTaintedColocatedArgumentDoesNotReachSinkThatPrecedesColocation(w io.Writer, src core.Source) {
if true {
core.Sink(w)
}
taintColocated(s, i)
fmt.Fprint(w, src)
}

func TestTaintedColocatedArgumentReachesSinkThatFollowsColocation() {
s := core.Source{}
i := newInnocuous()
taintColocated(s, i)
if err := fail(i); err != nil {
core.Sink(err) // want "a source has reached a sink"
func TestTaintedColocatedArgumentReachesSinkThatFollowsColocation(w io.Writer, src core.Source) {
if _, err := fmt.Fprint(w, src); err != nil {
core.Sink(w) // want "a source has reached a sink"
}
}

func TestAvoidingIncorrectPropagationFromColocationDoesNotPreventCorrectReport() {
source := newSource()

cp, err := copy(source)
func TestAvoidingIncorrectPropagationFromColocationDoesNotPreventCorrectReport(w io.Writer, src core.Source) {
_, err := fmt.Fprint(w, src)
if err != nil {
core.Sink(err) // want "a source has reached a sink"
core.Sink(w) // want "a source has reached a sink"
}

if true {
innoc := newInnocuous()
taintColocated(cp, innoc)
fmt.Fprint(w, src)
}
}

func fail(x interface{}) error {
return nil
}

func taintColocated(a, b interface{}) {
}

func newInnocuous() *core.Innocuous {
return &core.Innocuous{}
}

func newSource() *core.Source {
return &core.Source{}
}

func copy(a interface{}) (interface{}, error) {
return nil, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,120 +16,10 @@ package colocation

import (
"encoding/json"
"reflect"

"levee_analysistest/example/core"
)

func colocateString(core.Source, string) {}

func TestBasicTypeIsNotTainted(s core.Source, str string) {
colocateString(s, str)
core.Sink(str)
}

func colocateStringPointer(core.Source, *string) {}

func TestBasicPointerTypeIsTainted(s core.Source, strptr *string) {
colocateStringPointer(s, strptr)
core.Sink(strptr) // want "a source has reached a sink"
}

func TestPointerToBasicTypeIsTainted(s core.Source, str string) {
// This test is failing because &x introduces an Alloc,
// and we don't traverse through non-array Allocs
colocateStringPointer(s, &str)
core.Sink(str) // TODO(212) want "a source has reached a sink"
}

func colocateInnoc(core.Source, core.Innocuous) {}

func TestNamedStructTypeIsNotTainted(s core.Source, i core.Innocuous) {
colocateInnoc(s, i)
core.Sink(i)
}

func colocateInnocPtr(core.Source, *core.Innocuous) {}

func TestNamedStructPointerIsTainted(s core.Source, i *core.Innocuous) {
colocateInnocPtr(s, i)
core.Sink(i) // want "a source has reached a sink"
}

func TestPointerToNamedStructIsTainted(s core.Source, i core.Innocuous) {
// This test is failing because &x introduces an Alloc,
// and we don't traverse through non-array Allocs
colocateInnocPtr(s, &i)
core.Sink(i) // TODO(212) want "a source has reached a sink"
}

type PointerHolder struct{ ptr *core.Source }

func colocatePointerHolder(core.Source, PointerHolder) {}

func TestNamedStructPointerHolderIsTainted(s core.Source, ph PointerHolder) {
// This test is failing because ph is created by an Alloc,
// and we don't traverse through non-array Allocs
colocatePointerHolder(s, ph)
core.Sink(ph) // TODO(212) want "a source has reached a sink"
}

func colocateArrOfValues(core.Source, [1]string) {}

func TestArrOfValuesIsNotTainted(s core.Source, arr [1]string) {
colocateArrOfValues(s, arr)
core.Sink(arr)
}

func colocateArrOfPointers(core.Source, [1]*string) {}

func TestArrOfPointersIsTainted(s core.Source, arr [1]*string) {
colocateArrOfPointers(s, arr)
core.Sink(arr) // want "a source has reached a sink"
}

func colocateReferenceCollections(core.Source, map[string]string, chan string, []string) {}

func TestReferenceCollectionsAreTainted(s core.Source) {
m := make(map[string]string)
c := make(chan string)
sl := make([]string, 0)
colocateReferenceCollections(s, m, c, sl)
core.Sink(m) // want "a source has reached a sink"
core.Sink(c) // want "a source has reached a sink"
core.Sink(sl) // want "a source has reached a sink"
}

func colocateReflectValue(core.Source, reflect.Value) {}

func TestReflectValuesAreTainted(s core.Source, r reflect.Value) {
// This test is failing because r is created by an Alloc,
// and we don't traverse through non-array Allocs
colocateReflectValue(s, r)
core.Sink(r) // TODO(212) want "a source has reached a sink"
}

func colocateSingleInterface(s core.Source, e interface{}) {}
func colocateVariadicInterface(s core.Source, taintees ...interface{}) {}

func TestTaintedInterface(s core.Source, i interface{}) {
colocateSingleInterface(s, i)
core.Sink(i) // want "a source has reached a sink"

}

func TestTaintedThroughInterface(s core.Source, str string, i core.Innocuous) {
colocateVariadicInterface(s, str, i)
core.Sink(str)
core.Sink(i)
}

func TestPointerTaintedThroughInterface(s core.Source, str string, i core.Innocuous) {
colocateVariadicInterface(s, &str, &i)
core.Sink(str) // TODO(212) want "a source has reached a sink"
core.Sink(i) // TODO(212) want "a source has reached a sink"
}

// CVE-2020-8564
func TestTaintIsPropagatedToDataBeingUnmarshalled(contents []byte) (src core.Source, err error) {
if err = json.Unmarshal(contents, &src); err != nil {
Expand All @@ -141,18 +31,3 @@ func TestTaintIsPropagatedToDataBeingUnmarshalled(contents []byte) (src core.Sou
core.Sink(contents) // want "a source has reached a sink"
return
}

func colocateFunc(core.Source, func()) {}

func TestTaintIsNotPropagatedToFunction(s core.Source) {
f := func() {}
// f is an *ssa.Function with type *types.Signature
colocateFunc(s, f)
core.Sink(f)
}

func TestTaintIsNotPropagatedToFunctionParameter(s core.Source, f func()) {
// f is an *ssa.Parameter with type *types.Signature
colocateFunc(s, f)
core.Sink(f)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ func CreateSourceFlipped() (error, core.Source) {
return nil, core.Source{}
}

func TakeSource(s core.Source) (string, int, interface{}) {
return "", 0, nil
}

func TestOnlySourceExtractIsTaintedFromCall() {
s, ok := TryUpdateSource(core.Source{})
core.Sink(s) // want "a source has reached a sink"
Expand Down Expand Up @@ -77,13 +73,6 @@ func TestOnlySourceExtractIsTaintedInstructionOrderFlipped() {
core.Sink(s) // want "a source has reached a sink"
}

func TestExtractsFromCallWithSourceArgAreTainted(s core.Source) {
str, i, e := TakeSource(s)
core.Sink(str) // want "a source has reached a sink"
core.Sink(i)
core.Sink(e) // want "a source has reached a sink"
}

func NewSource() (*core.Source, error) {
return &core.Source{}, nil
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,13 @@
package propagation

import (
"fmt"

"errors"
"levee_analysistest/example/core"
"os"
PurelyApplied marked this conversation as resolved.
Show resolved Hide resolved
)

func Identity(arg interface{}) interface{} {
return arg
}

func TestIdentityPropagator(s core.Source) {
i := Identity(s)
core.Sink(i) // want "a source has reached a sink"
core.Sink(Identity(s)) // want "a source has reached a sink"
}

func ToString(arg interface{}) string {
return fmt.Sprintf("%v", arg)
}

func TestToStringPropagator(s core.Source) {
v := ToString(s)
core.Sink(v) // want "a source has reached a sink"
}

func TestPropagationViaSourceMethod(s core.Source) {
tainted := s.Propagate(s.Data)
core.Sink(tainted) // want "a source has reached a sink"
}

func TestPropagationViaFunctionReturningBool(s *core.Source, i *core.Innocuous) {
if ok := TryCopy(i, s); !ok {
core.Sinkf("couldn't copy to: %v", i) // want "a source has reached a sink"
func TestPropagationViaFunctionReturningBool(s core.Source, err *os.PathError) {
if ok := errors.As(errors.New(s.Data), err); !ok {
core.Sinkf("not a PathError: %v", err) // want "a source has reached a sink"
}
}

func TryCopy(dst interface{}, src interface{}) bool {
return true
}
Loading