diff options
Diffstat (limited to 'sys/linux/init.go')
| -rw-r--r-- | sys/linux/init.go | 49 |
1 files changed, 49 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 { |
