diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2019-12-19 19:31:04 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-12-19 19:32:45 +0100 |
| commit | af9047c60a3db32d5e43c29321f8f531db051a63 (patch) | |
| tree | 84ab57a09469473a17dc548d30d6a9b074f25599 /sys/linux | |
| parent | fa392d3014cf619b5aa945efbd8f99cd79e50a71 (diff) | |
sys/linux: prohibit TIOCSSERIAL
Replace TIOCSSERIAL with TIOCGSERIAL.
TIOCSSERIAL can do nasty things under root, like causing writes to random memory
pretty much like /dev/mem, but this is also working as intended.
For details see:
https://groups.google.com/g/syzkaller-bugs/c/1rVENJf9P4U/m/QtGpapRxAgAJ
https://syzkaller.appspot.com/bug?extid=f4f1e871965064ae689e
TODO: TIOCSSERIAL does some other things that are not dangerous
and would be nice to test, if/when we can sanitize based on sandbox value
we could prohibit it only under sandbox=none.
Diffstat (limited to 'sys/linux')
| -rw-r--r-- | sys/linux/init.go | 48 | ||||
| -rw-r--r-- | sys/linux/init_test.go | 17 |
2 files changed, 39 insertions, 26 deletions
diff --git a/sys/linux/init.go b/sys/linux/init.go index 91bf32be8..fe214156e 100644 --- a/sys/linux/init.go +++ b/sys/linux/init.go @@ -42,6 +42,8 @@ func InitTarget(target *prog.Target) { AF_NETROM: target.GetConst("AF_NETROM"), AF_ROSE: target.GetConst("AF_ROSE"), USB_MAJOR: target.GetConst("USB_MAJOR"), + TIOCSSERIAL: target.GetConst("TIOCSSERIAL"), + TIOCGSERIAL: target.GetConst("TIOCGSERIAL"), // These are not present on all arches. ARCH_SET_FS: target.ConstMap["ARCH_SET_FS"], ARCH_SET_GS: target.ConstMap["ARCH_SET_GS"], @@ -142,6 +144,8 @@ type arch struct { AF_NETROM uint64 AF_ROSE uint64 USB_MAJOR uint64 + TIOCSSERIAL uint64 + TIOCGSERIAL uint64 } func (arch *arch) sanitizeCall(c *prog.Call) { @@ -234,28 +238,36 @@ func enforceIntArg(a prog.Arg) { func (arch *arch) sanitizeIoctl(c *prog.Call) { cmd := c.Args[1].(*prog.ConstArg) - // Freeze kills machine. Though, it is an interesting functions, - // so we need to test it somehow. - // TODO: not required if executor drops privileges. - // Fortunately, the value does not conflict with any other ioctl commands for now. - if uint64(uint32(cmd.Val)) == arch.FIFREEZE { + switch uint64(uint32(cmd.Val)) { + case arch.FIFREEZE: + // Freeze kills machine. Though, it is an interesting functions, + // so we need to test it somehow. + // TODO: not required if executor drops privileges. + // Fortunately, the value does not conflict with any other ioctl commands for now. cmd.Val = arch.FITHAW - } - // SNAPSHOT_FREEZE freezes all processes and leaves the machine dead. - if uint64(uint32(cmd.Val)) == arch.SNAPSHOT_FREEZE { + case arch.SNAPSHOT_FREEZE: + // SNAPSHOT_FREEZE freezes all processes and leaves the machine dead. cmd.Val = arch.SNAPSHOT_UNFREEZE - } - // EXT4_IOC_SHUTDOWN on root fs effectively brings the machine down in weird ways. - // Fortunately, the value does not conflict with any other ioctl commands for now. - if uint64(uint32(cmd.Val)) == arch.EXT4_IOC_SHUTDOWN { + case arch.EXT4_IOC_SHUTDOWN: + // EXT4_IOC_SHUTDOWN on root fs effectively brings the machine down in weird ways. + // Fortunately, the value does not conflict with any other ioctl commands for now. cmd.Val = arch.EXT4_IOC_MIGRATE - } - // EXT4_IOC_RESIZE_FS on root fs can shrink it to 0 (or whatever is the minimum size) - // and then creation of new temp dirs for tests will fail. - // TODO: not necessary for sandbox=namespace as it tests in a tmpfs - // and/or if we mount tmpfs for sandbox=none (#971). - if uint64(uint32(cmd.Val)) == arch.EXT4_IOC_RESIZE_FS { + case arch.EXT4_IOC_RESIZE_FS: + // EXT4_IOC_RESIZE_FS on root fs can shrink it to 0 (or whatever is the minimum size) + // and then creation of new temp dirs for tests will fail. + // TODO: not necessary for sandbox=namespace as it tests in a tmpfs + // and/or if we mount tmpfs for sandbox=none (#971). cmd.Val = arch.EXT4_IOC_MIGRATE + case arch.TIOCSSERIAL: + // TIOCSSERIAL can do nasty things under root, like causing writes to random memory + // pretty much like /dev/mem, but this is also working as intended. + // For details see: + // https://groups.google.com/g/syzkaller-bugs/c/1rVENJf9P4U/m/QtGpapRxAgAJ + // https://syzkaller.appspot.com/bug?extid=f4f1e871965064ae689e + // TODO: TIOCSSERIAL does some other things that are not dangerous + // and would be nice to test, if/when we can sanitize based on sandbox value + // we could prohibit it only under sandbox=none. + cmd.Val = arch.TIOCGSERIAL } } diff --git a/sys/linux/init_test.go b/sys/linux/init_test.go index 4358bef35..44a31149c 100644 --- a/sys/linux/init_test.go +++ b/sys/linux/init_test.go @@ -106,8 +106,7 @@ mknod(0x0, 0xc000, 0x0) mknod(0x0, 0x2000, 0x0) mknod(0x0, 0x6000, 0x0) mknod(0x0, 0x6000, 0x700) -`, - ` +`, ` mknod(0x0, 0x1000, 0x0) mknod(0x0, 0x8000, 0x0) mknod(0x0, 0xc000, 0x0) @@ -125,8 +124,7 @@ exit(0xc3) exit_group(0x5a) exit_group(0x43) exit_group(0x443) -`, - ` +`, ` exit(0x3) exit(0x1) exit(0x1) @@ -143,14 +141,13 @@ syz_open_procfs(0x0, &(0x7f0000000000)='exe') syz_open_procfs(0x0, &(0x7f0000000000)='exe\x00') syz_open_procfs(0x0, &(0x7f0000000000)='/exe') syz_open_procfs(0x0, &(0x7f0000000000)='./exe\x00') -`, - ` +`, ` syz_open_procfs(0x0, &(0x7f0000000000)='io') syz_open_procfs(0x0, &(0x7f0000000000)='net\x00') syz_open_procfs(0x0, &(0x7f0000000000)='net\x00') syz_open_procfs(0x0, &(0x7f0000000000)='net\x00') syz_open_procfs(0x0, &(0x7f0000000000)='net\x00') - `, +`, }, { @@ -163,7 +160,11 @@ syz_open_dev$tty1(0xc, 0x4, 0x5) syz_open_dev$tty1(0xc, 0x4, 0x4) syz_open_dev$tty1(0xc, 0x4, 0x4) syz_open_dev$tty1(0xc, 0x4, 0x1) - `, +`, + }, + { + `ioctl$TIOCSSERIAL(0x0, 0x541f, 0x0)`, + `ioctl$TIOCSSERIAL(0x0, 0x541e, 0x0)`, }, } for i, test := range tests { |
