Control Flow Integrity(CFI) is a security mechanism that disallows changes to the original control flow graph of a compiled binary, making it significantly harder to perform such attacks. init_state_node() assign same function callback to different function pointer declarations. static int init_state_node(struct cpuidle_state *idle_state, const struct of_device_id *matches, struct device_node *state_node) { ... idle_state->enter = match_id->data; ... idle_state->enter_s2idle = match_id->data; } Function declarations: struct cpuidle_state { ... int (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv, int index); void (*enter_s2idle) (struct cpuidle_device *dev, struct cpuidle_driver *drv, int index); }; In this case, either enter() or enter_s2idle() would cause CFI check failed since they use same callee. Align function prototype of enter() since it needs return value for some use cases. The return value of enter_s2idle() is no need currently.
Showing the changes to include/linux (1 of 4 files). Show all
Unified · Split
| @@ -65,10 +65,13 @@ struct cpuidle_state { · 64 unmodified lines | ||
| 65 | 65 | * CPUs execute ->enter_s2idle with the local tick or entire timekeeping |
| 66 | 66 | * suspended, so it must not re-enable interrupts at any point (even |
| 67 | 67 | * temporarily) or attempt to change states of clock event devices. |
| 68 | + * | |
| 69 | + * This callback may point to the same function as ->enter if all of | |
| 70 | + * the above requirements are met by it. | |
| 68 | 71 | */ |
| 69 | − void (*enter_s2idle) (struct cpuidle_device *dev, | |
| 70 | − struct cpuidle_driver *drv, | |
| 71 | − int index); | |
| 72 | + int (*enter_s2idle)(struct cpuidle_device *dev, | |
| 73 | + struct cpuidle_driver *drv, | |
| 74 | + int index); | |
| 72 | 75 | }; |
| 73 | 76 | |
| 74 | 77 | /* Idle State Flags */ |