Skip to content

Commit

Permalink
sys/linux: sanitize mount()
Browse files Browse the repository at this point in the history
If an ext* superblock has a "panic on error" bit set, we may end up with
a kernel crash unless it was prohibited via mount options.

For syz_mount_image(), we do ensure that mount options prevent this from
happening.

Perform similar sanitization also for plain mount() calls.
  • Loading branch information
a-nogikh committed Aug 18, 2023
1 parent d216d8a commit 4fdba27
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
41 changes: 41 additions & 0 deletions sys/linux/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
package linux

import (
"regexp"
"runtime"
"strings"

"github.com/google/syzkaller/prog"
"github.com/google/syzkaller/sys/targets"
Expand Down Expand Up @@ -244,6 +246,8 @@ func (arch *arch) neutralize(c *prog.Call, fixStructure bool) error {
case "sched_setattr":
// Enabling a SCHED_FIFO or a SCHED_RR policy may lead to false positive stall-related crashes.
neutralizeSchedAttr(c.Args[1])
case "mount":
neutralizeMount(c)
}

switch c.Meta.Name {
Expand Down Expand Up @@ -299,6 +303,43 @@ func neutralizeSchedAttr(a prog.Arg) {
}
}

var dropMountErrorsRe = regexp.MustCompile(`(?m)(^\s*errors=[^,]+,?\s*|,?\s*errors=[^,]+)`)

func neutralizeMount(c *prog.Call) {
typePtr, ok := c.Args[2].(*prog.PointerArg)
if !ok || typePtr.Res == nil {
return
}
typeData, ok := typePtr.Res.(*prog.DataArg)
if !ok {
return
}
// Only patch ext* mounts for now.
if !strings.HasPrefix(string(typeData.Data()), "ext") {
return
}
optsPtr, ok := c.Args[4].(*prog.PointerArg)
if !ok {
return
}
opts := ""
if optsPtr.Res != nil {
optsPtrData, ok := optsPtr.Res.(*prog.DataArg)
if !ok {
return
}
opts = string(optsPtrData.Data())
}
hadRemount := strings.Contains(opts, "errors=remount-ro")
opts = dropMountErrorsRe.ReplaceAllString(opts, "")
if hadRemount {
opts = "errors=remount-ro," + opts
} else {
opts = "errors=continue," + opts
}
optsPtr.Res = prog.MakeDataArg(typeData.Type(), prog.DirIn, []byte(opts))
}

func enforceIntArg(a prog.Arg) {
arg, ok := a.(*prog.ConstArg)
if !ok {
Expand Down
20 changes: 20 additions & 0 deletions sys/linux/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/google/syzkaller/sys/targets"
)

// nolint: lll
func TestNeutralize(t *testing.T) {
prog.TestDeserializeHelper(t, targets.Linux, targets.AMD64, nil, []prog.DeserializeTest{
{
Expand Down Expand Up @@ -152,5 +153,24 @@ syz_open_dev$tty1(0xc, 0x4, 0x1)
In: `sched_setattr(0x0, &(0x7f00000001c0)=ANY=[@ANYBLOB="1234567812345678"], 0x0)`,
Out: `sched_setattr(0x0, &(0x7f00000001c0)=ANY=[@ANYBLOB='\x00\x00\x00\x00\x00\x00\x00\x00'], 0x0)`,
},
{
In: `mount(0x0, 0x0, &(0x7f00000001c0)='ext4\x00', 0x3f000000, 0x0)`,
Out: `mount(0x0, 0x0, &(0x7f00000001c0)='ext4\x00', 0x3f000000, &(0x7f0000000000)='errors=continue,')`,
},
{
In: `mount(0x0, 0x0, &(0x7f00000001c0)='ext4\x00', 0x3f000000, &(0x7f0000000000)='errors=remount-ro')`,
Out: `mount(0x0, 0x0, &(0x7f00000001c0)='ext4\x00', 0x3f000000, &(0x7f0000000000)='errors=remount-ro,')`,
},
{
In: `mount(0x0, 0x0, &(0x7f00000001c0)='ext2\x00', 0x3f000000, &(0x7f0000000000)='errors=panic,key1,key2')`,
Out: `mount(0x0, 0x0, &(0x7f00000001c0)='ext2\x00', 0x3f000000, &(0x7f0000000000)='errors=continue,key1,key2')`,
},
{
In: `mount(0x0, 0x0, &(0x7f00000001c0)='ext2\x00', 0x3f000000, &(0x7f0000000000)='errors=panic,errors=panic,errors=continue')`,
Out: `mount(0x0, 0x0, &(0x7f00000001c0)='ext2\x00', 0x3f000000, &(0x7f0000000000)='errors=continue,')`,
},
{
In: `mount(0x0, 0x0, &(0x7f00000001c0)='ntfs\x00', 0x3f000000, 0x0)`,
},
})
}

0 comments on commit 4fdba27

Please sign in to comment.