CVE-2024-31446 (published 2024-04-16T20:15Z)

OpenComputers is a Minecraft mod that adds programmable computers and robots to the game. A user can use OpenComputers to get a Computer thread stuck in the Lua VM, which eventually blocks the Server thread, requiring the server to be forcibly shut down. This can be accomplished using any device in the mod and can be performed by anyone who can execute Lua code on them. This occurs while using the native Lua library. LuaJ appears to not have this issue. This vulnerability is fixed in 1.8.4. The GregTech: New Horizons modpack uses its own modified version of OpenComputers. They have applied the relevant patch in version 1.10.10-GTNH.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/MightyPirates/OpenComputers
commit_details: repo_url: https://github.com/MightyPirates/OpenComputers
author: Adrian Siekierka
author_date: 2024-04-16 18:39:11+02:00
msg: Fix pcall()/xpcall() bug.
repository: repo_url: https://github.com/MightyPirates/OpenComputers
repo_name: MightyPirates/OpenComputers
description: Home of the OpenComputers mod for Minecraft.
repo_language: Scala
owner: MightyPirates
file_changes: filename: machine.lua
change_type: ModificationType.MODIFY
diff: @@ -761,6 +761,10 @@ sandbox = {
   next = next,
   pairs = pairs,
   pcall = function(...)
+    -- prevent infinite pcall() loops by checking deadline before pcall()
+    local status, err = pcall(checkDeadline)
+    if not status then return false, err end
+
     return pcallTimeoutCheck(pcall(...))
   end,
   print = nil, -- in boot/*_base.lua
@@ -807,18 +811,27 @@ sandbox = {
   type = type,
   _VERSION = _VERSION:match("Luaj") and "Luaj" or _VERSION:match("5.4") and "Lua 5.4" or _VERSION:match("5.3") and "Lua 5.3" or "Lua 5.2",
   xpcall = function(f, msgh, ...)
-    local handled = false
+    -- allow xpcall() to call the message handler recursively, per manual 2.3
+    -- Lua itself promises to break the infinite loop; failing that, the timeout
+    -- check will take care of this.
+    local errorCapture
+    errorCapture = function(ff, ...)
+      -- prevent infinite xpcall() loops by checking deadline before xpcall()
+      local status, err = pcall(checkDeadline)
+      if not status then return false, err end
+
+      return xpcall(ff, function(...)
+        if rawequal((...), tooLongWithoutYielding) then
+          return tooLongWithoutYielding
+        else
+          return select(2, errorCapture(msgh, ...))
+        end
+      end, ...)
+    end
+
     checkArg(2, msgh, "function")
-    local result = table.pack(xpcall(f, function(...)
-      if rawequal((...), tooLongWithoutYielding) then
-        return tooLongWithoutYielding
-      elseif handled then
-        return ...
-      else
-        handled = true
-        return msgh(...)
-      end
-    end, ...))
+    local result = table.pack(errorCapture(f, ...))
+    -- if the final returned error is due to timeout, run handler one last time
     if rawequal(result[2], tooLongWithoutYielding) then
       result = table.pack(result[1], select(2, pcallTimeoutCheck(pcall(msgh, tostring(tooLongWithoutYielding)))))
     end

programming_language: Lua