aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-04-29 07:55:42 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-04-29 14:53:56 +0000
commitee541933d6cdece196c947c5aeecf496cab5e983 (patch)
treea71a35dce425a0b48243884cc21ebbe6c9995f76 /prog
parentff7c0a076c7baabdc6797179f649803250f21bd9 (diff)
prog: add raw deserialization mode
Raw deserialization mode does not do any program sanitization and allows to use global file names, prohibited ioctl's, etc. This will be useful for moving syscall/feature checking code to the host, we will need to probe opening global files, etc.
Diffstat (limited to 'prog')
-rw-r--r--prog/encoding.go23
-rw-r--r--prog/validation.go5
2 files changed, 21 insertions, 7 deletions
diff --git a/prog/encoding.go b/prog/encoding.go
index db32484a8..06099993f 100644
--- a/prog/encoding.go
+++ b/prog/encoding.go
@@ -235,8 +235,17 @@ func (a *ResultArg) serialize(ctx *serializer) {
type DeserializeMode int
const (
- Strict DeserializeMode = iota
- NonStrict DeserializeMode = iota
+ // In strict mode deserialization fails if the program is malformed in any way.
+ // This mode is used for manually written programs to ensure that they are correct.
+ Strict DeserializeMode = iota
+ // In non-strict mode malformed programs silently fixed in a best-effort way,
+ // e.g. missing/wrong arguments are replaced with default values.
+ // This mode is used for the corpus programs to "repair" them after descriptions changes.
+ NonStrict
+ // Unsafe mode is used for VM checking programs. In this mode programs are not fixed
+ // for safety, e.g. can access global files, issue prohibited ioctl's, disabled syscalls, etc.
+ StrictUnsafe
+ NonStrictUnsafe
)
func (target *Target) Deserialize(data []byte, mode DeserializeMode) (*Prog, error) {
@@ -246,7 +255,8 @@ func (target *Target) Deserialize(data []byte, mode DeserializeMode) (*Prog, err
err, target.OS, target.Arch, GitRevision, mode, data))
}
}()
- p := newParser(target, data, mode == Strict)
+ strict := mode == Strict || mode == StrictUnsafe
+ p := newParser(target, data, strict)
prog, err := p.parseProg()
if err := p.Err(); err != nil {
return nil, err
@@ -260,6 +270,7 @@ func (target *Target) Deserialize(data []byte, mode DeserializeMode) (*Prog, err
if err := prog.validateWithOpts(validationOptions{
// Don't validate auto-set conditional fields. We'll patch them later.
ignoreTransient: true,
+ allowUnsafe: mode == StrictUnsafe || mode == NonStrictUnsafe,
}); err != nil {
return nil, err
}
@@ -267,8 +278,10 @@ func (target *Target) Deserialize(data []byte, mode DeserializeMode) (*Prog, err
if p.autos != nil {
p.fixupAutos(prog)
}
- if err := prog.sanitize(mode == NonStrict); err != nil {
- return nil, err
+ if mode != StrictUnsafe {
+ if err := prog.sanitize(!strict); err != nil {
+ return nil, err
+ }
}
return prog, nil
}
diff --git a/prog/validation.go b/prog/validation.go
index f38dcd1e8..b2a358706 100644
--- a/prog/validation.go
+++ b/prog/validation.go
@@ -34,6 +34,7 @@ type validCtx struct {
type validationOptions struct {
ignoreTransient bool
+ allowUnsafe bool // allow global file names, etc
}
func (p *Prog) validateWithOpts(opts validationOptions) error {
@@ -60,7 +61,7 @@ func (p *Prog) validateWithOpts(opts validationOptions) error {
}
func (ctx *validCtx) validateCall(c *Call) error {
- if c.Meta.Attrs.Disabled {
+ if !ctx.opts.allowUnsafe && c.Meta.Attrs.Disabled {
return fmt.Errorf("use of a disabled call")
}
if c.Props.Rerun > 0 && c.Props.FailNth > 0 {
@@ -210,7 +211,7 @@ func (arg *DataArg) validate(ctx *validCtx, dir Dir) error {
typ.Name(), arg.Size(), typ.TypeSize)
}
case BufferFilename:
- if escapingFilename(string(arg.data)) {
+ if !ctx.opts.allowUnsafe && escapingFilename(string(arg.data)) {
return fmt.Errorf("escaping filename %q", arg.data)
}
}