diff options
| -rw-r--r-- | sys/linux/init.go | 49 | ||||
| -rw-r--r-- | sys/linux/init_test.go | 20 |
2 files changed, 69 insertions, 0 deletions
diff --git a/sys/linux/init.go b/sys/linux/init.go index 88bfe919e..6fa9665a8 100644 --- a/sys/linux/init.go +++ b/sys/linux/init.go @@ -230,6 +230,9 @@ func (arch *arch) neutralize(c *prog.Call) { enforceIntArg(c.Args[0]) enforceIntArg(c.Args[1]) enforceIntArg(c.Args[2]) + case "sched_setattr": + // Enabling a SCHED_FIFO or a SCHED_RR policy may lead to false positive stall-related crashes. + neutralizeSchedAttr(c.Args[1]) } switch c.Meta.Name { @@ -238,6 +241,52 @@ func (arch *arch) neutralize(c *prog.Call) { } } +func neutralizeSchedAttr(a prog.Arg) { + switch attr := a.(type) { + case *prog.PointerArg: + if attr.Res == nil { + // If it's just a pointer to somewhere, still set it to NULL as there's a risk that + // it points to the valid memory and it can be interpreted as a sched_attr struct. + attr.Address = 0 + return + } + groupArg, ok := attr.Res.(*prog.GroupArg) + if !ok || len(groupArg.Inner) == 0 { + return + } + if unionArg, ok := groupArg.Inner[0].(*prog.UnionArg); ok { + dataArg, ok := unionArg.Option.(*prog.DataArg) + if !ok { + return + } + if dataArg.Dir() == prog.DirOut { + return + } + // Clear the first 16 bytes to prevent overcoming the limitation by squashing the struct. + data := append([]byte{}, dataArg.Data()...) + for i := 0; i < 16 && i < len(data); i++ { + data[i] = 0 + } + dataArg.SetData(data) + } + + // Most likely it's the intended sched_attr structure. + if len(groupArg.Inner) > 1 { + policyField, ok := groupArg.Inner[1].(*prog.ConstArg) + if !ok { + return + } + const SCHED_FIFO = 0x1 + const SCHED_RR = 0x2 + if policyField.Val == SCHED_FIFO || policyField.Val == SCHED_RR { + policyField.Val = 0 + } + } + case *prog.ConstArg: + attr.Val = 0 + } +} + func enforceIntArg(a prog.Arg) { arg, ok := a.(*prog.ConstArg) if !ok { diff --git a/sys/linux/init_test.go b/sys/linux/init_test.go index ed4cf03a1..8c236af5d 100644 --- a/sys/linux/init_test.go +++ b/sys/linux/init_test.go @@ -145,5 +145,25 @@ ioctl$X86_IOC_RDMSR_REGS(0xa, 0xc02063a0, 0x0) ioctl$X86_IOC_RDMSR_REGS(0xa, 0xc02063a0, 0x0) `, }, + { + In: `sched_setattr(0x0, &(0x7f00000002c0)={0x0, 0x1, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)`, + Out: `sched_setattr(0x0, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, 0x3}, 0x0)`, + }, + { + In: `sched_setattr(0x0, &(0x7f00000002c0)={0x0, 0x2, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)`, + Out: `sched_setattr(0x0, &(0x7f00000002c0)={0x0, 0x0, 0x0, 0x0, 0x3}, 0x0)`, + }, + { + In: `sched_setattr(0x0, &(0x7f00000002c0)={0x0, 0x3, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x0)`, + Out: `sched_setattr(0x0, &(0x7f00000002c0)={0x0, 0x3, 0x0, 0x0, 0x3}, 0x0)`, + }, + { + In: `sched_setattr(0x0, 0x123456, 0x0)`, + Out: `sched_setattr(0x0, 0x0, 0x0)`, + }, + { + 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)`, + }, }) } |
