aboutsummaryrefslogtreecommitdiffstats
path: root/sys/linux/init.go
diff options
context:
space:
mode:
Diffstat (limited to 'sys/linux/init.go')
-rw-r--r--sys/linux/init.go49
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 {