kernel: fix unbounded stack usage in atomics
This commit is contained in:
		| @@ -35,8 +35,11 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address | |||||||
|  |  | ||||||
|     // TODO(bunnei): We should call CanAccessAtomic(..) here. |     // TODO(bunnei): We should call CanAccessAtomic(..) here. | ||||||
|  |  | ||||||
|  |     s32 current_value{}; | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|         // Load the value from the address. |         // Load the value from the address. | ||||||
|     const s32 current_value = |         current_value = | ||||||
|             static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); |             static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); | ||||||
|  |  | ||||||
|         // Compare it to the desired one. |         // Compare it to the desired one. | ||||||
| @@ -45,14 +48,17 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address | |||||||
|             const s32 decrement_value = current_value - 1; |             const s32 decrement_value = current_value - 1; | ||||||
|  |  | ||||||
|             // Decrement and try to store. |             // Decrement and try to store. | ||||||
|         if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), |             if (monitor.ExclusiveWrite32(current_core, GetInteger(address), | ||||||
|                                          static_cast<u32>(decrement_value))) { |                                          static_cast<u32>(decrement_value))) { | ||||||
|             // If we failed to store, try again. |                 break; | ||||||
|             DecrementIfLessThan(system, out, address, value); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             // If we failed to store, try again. | ||||||
|         } else { |         } else { | ||||||
|             // Otherwise, clear our exclusive hold and finish |             // Otherwise, clear our exclusive hold and finish | ||||||
|             monitor.ClearExclusive(current_core); |             monitor.ClearExclusive(current_core); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // We're done. |     // We're done. | ||||||
| @@ -70,8 +76,11 @@ bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 | |||||||
|  |  | ||||||
|     // TODO(bunnei): We should call CanAccessAtomic(..) here. |     // TODO(bunnei): We should call CanAccessAtomic(..) here. | ||||||
|  |  | ||||||
|  |     s32 current_value{}; | ||||||
|  |  | ||||||
|     // Load the value from the address. |     // Load the value from the address. | ||||||
|     const s32 current_value = |     while (true) { | ||||||
|  |         current_value = | ||||||
|             static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); |             static_cast<s32>(monitor.ExclusiveRead32(current_core, GetInteger(address))); | ||||||
|  |  | ||||||
|         // Compare it to the desired one. |         // Compare it to the desired one. | ||||||
| @@ -79,14 +88,17 @@ bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 | |||||||
|             // If equal, we want to try to write the new value. |             // If equal, we want to try to write the new value. | ||||||
|  |  | ||||||
|             // Try to store. |             // Try to store. | ||||||
|         if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), |             if (monitor.ExclusiveWrite32(current_core, GetInteger(address), | ||||||
|                                          static_cast<u32>(new_value))) { |                                          static_cast<u32>(new_value))) { | ||||||
|             // If we failed to store, try again. |                 break; | ||||||
|             UpdateIfEqual(system, out, address, value, new_value); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             // If we failed to store, try again. | ||||||
|         } else { |         } else { | ||||||
|             // Otherwise, clear our exclusive hold and finish. |             // Otherwise, clear our exclusive hold and finish. | ||||||
|             monitor.ClearExclusive(current_core); |             monitor.ClearExclusive(current_core); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // We're done. |     // We're done. | ||||||
|   | |||||||
| @@ -33,8 +33,11 @@ bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u | |||||||
|     auto& monitor = system.Monitor(); |     auto& monitor = system.Monitor(); | ||||||
|     const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); |     const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); | ||||||
|  |  | ||||||
|  |     u32 expected{}; | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|         // Load the value from the address. |         // Load the value from the address. | ||||||
|     const auto expected = monitor.ExclusiveRead32(current_core, GetInteger(address)); |         expected = monitor.ExclusiveRead32(current_core, GetInteger(address)); | ||||||
|  |  | ||||||
|         // Orr in the new mask. |         // Orr in the new mask. | ||||||
|         u32 value = expected | new_orr_mask; |         u32 value = expected | new_orr_mask; | ||||||
| @@ -45,9 +48,11 @@ bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Try to store. |         // Try to store. | ||||||
|     if (!monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) { |         if (monitor.ExclusiveWrite32(current_core, GetInteger(address), value)) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         // If we failed to store, try again. |         // If we failed to store, try again. | ||||||
|         return UpdateLockAtomic(system, out, address, if_zero, new_orr_mask); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // We're done. |     // We're done. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user