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.
Unified · Split
| @@ -655,8 +655,8 @@ static int acpi_idle_enter(struct cpuidle_device *dev, · 654 unmodified lines | ||
| 655 | 655 | return index; |
| 656 | 656 | } |
| 657 | 657 | |
| 658 | −static void acpi_idle_enter_s2idle(struct cpuidle_device *dev, | |
| 659 | − struct cpuidle_driver *drv, int index) | |
| 658 | +static int acpi_idle_enter_s2idle(struct cpuidle_device *dev, | |
| 659 | + struct cpuidle_driver *drv, int index) | |
| 660 | 660 | { |
| 661 | 661 | struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); |
| 662 | 662 | |
| @@ -674,6 +674,8 @@ static void acpi_idle_enter_s2idle(struct cpuidle_device *dev, · 11 unmodified lines | ||
| 674 | 674 | } |
| 675 | 675 | } |
| 676 | 676 | acpi_idle_do_entry(cx); |
| 677 | + | |
| 678 | + return 0; | |
| 677 | 679 | } |
| 678 | 680 | |
| 679 | 681 | static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, |
| @@ -253,11 +253,13 @@ static int tegra_cpuidle_enter(struct cpuidle_device *dev, · 252 unmodified lines | ||
| 253 | 253 | return err ? -1 : index; |
| 254 | 254 | } |
| 255 | 255 | |
| 256 | −static void tegra114_enter_s2idle(struct cpuidle_device *dev, | |
| 257 | − struct cpuidle_driver *drv, | |
| 258 | − int index) | |
| 256 | +static int tegra114_enter_s2idle(struct cpuidle_device *dev, | |
| 257 | + struct cpuidle_driver *drv, | |
| 258 | + int index) | |
| 259 | 259 | { |
| 260 | 260 | tegra_cpuidle_enter(dev, drv, index); |
| 261 | + | |
| 262 | + return 0; | |
| 261 | 263 | } |
| 262 | 264 | |
| 263 | 265 | /* |
| @@ -173,13 +173,15 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev, · 172 unmodified lines | ||
| 173 | 173 | * Invoked as a suspend-to-idle callback routine with frozen user space, frozen |
| 174 | 174 | * scheduler tick and suspended scheduler clock on the target CPU. |
| 175 | 175 | */ |
| 176 | −static __cpuidle void intel_idle_s2idle(struct cpuidle_device *dev, | |
| 177 | − struct cpuidle_driver *drv, int index) | |
| 176 | +static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev, | |
| 177 | + struct cpuidle_driver *drv, int index) | |
| 178 | 178 | { |
| 179 | 179 | unsigned long eax = flg2MWAIT(drv->states[index].flags); |
| 180 | 180 | unsigned long ecx = 1; /* break on interrupt flag */ |
| 181 | 181 | |
| 182 | 182 | mwait_idle_with_hints(eax, ecx); |
| 183 | + | |
| 184 | + return 0; | |
| 183 | 185 | } |
| 184 | 186 | |
| 185 | 187 | /* |
| @@ -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 */ |