-
Posts
153 -
Joined
-
Last visited
Content Type
Profiles
Forums
Events
Everything posted by Actium
-
Debian 13 "Trixie" was released last weekend. It comes with Wine 10.0, which uses Wayland by default. I've updated the git repo to get rid of the now obsolete Xwayland. A pleasant surprise, presumably dating back to DCS 2.9.16, is a significant decrease in RAM usage that allows running Caucasus and Marianas with 8 GB of RAM. You can now operate a dedicated DCS server for as little as 8 €/month on, e.g., a CX32 Hetzner Cloud server, albeit with mediocre performance (my 100 unit benchmark mission will stall out the server).
-
Let me chime in with both. After a decade of playing (and scripting) ArmA followed by a 5 year milsim hiatus, I've jumped on the DCS train 2 years ago. Generally, I've had a pleasant experience playing the game (after upgrading to 64G of RAM to keep DCS from crashing). I didn't even know DCS is what I've always wanted, until I started playing it after getting sucked in by the Grim Reapers Youtube channel. Right now, nothing else compares to DCS, so until a superior alternative pops up – if ever, DCS will always be the benchmark for a good military aviation milsim experience. While I don't have DCS street cred, I'm a software engineer by trade and I do have 20+ years of coding experience (concurrent, multi-threaded C/C++ systems programming). Eventually, I couldn't resist DCS Lua scripting. At that point, however, my DCS experience changed drastically, as my perspective shifted from mere entertainment seeking to software engineering: The documentation – or better the lack thereof – is frankly embarrassing. Compared to ArmA – which I also cursed at times – and its comprehensive, official scripting docs, DCS is basically undocumented. That's an absolute no go for a product that depends largely on community content creation. The DCS scripting API with its plethora of different, undocumented Lua states and another separate a_do_script() environment is terribly convoluted and thus unnecessarily complicated to work with, obviously exacerbated by the lack of documentation. I implemented a browser-based Lua console as a learning project just to figure out how everything works. What makes matters worse, is the need to maintain this improper API to avoid breaking API compatibility and a lot of community content along with it, as the recent net.dostring_in() change illustrated. Such incisive, breaking API changes should not be released without prior discussion with community developers and advance warning. The scripting API is unnecessarily buggy, up to SEGFAULTS, due to an apparent lack of even basic testing [1, 2, 3, 4, 5]. Modern coding practices, even rudimentary unit tests, and the use of appropriate tools like AddressSanitizer (possibly combined with a bit of fuzzing) should prevent introducing and releasing with such bugs. Although adhering to such practices may sound like overhead, it'll pay for itself multiple times over by obviating a lot of time otherwise wasted by inefficiently debugging code weeks/months after having modified it. The scripting API lacks very basic functions, e.g. Unit.setLife(), with ED hesitant to add it [1, 2, 3]. With the presumably dire state of the scripting system, I do however understand the reluctance to change anything. There seems to be a lack of understanding for the needs of community developers. According to %DCS_INSTALL_DIR%/API/Sim_ControlAPI.html the net.dostring_in() function is entirely obsolete: This is grossly wrong. Many missions, mods, admin scripts, Olympus, etc. would seize to work without that very function. The mission scripting engine is still vulnerable to arbitrary code execution via malicious mission files, despite a (temporary) mitigation being available. This matter deserves urgent attention. All Lua scripting appears to run in the main loop without runtime constraints, allowing a single script with an infinite loop to freeze a client/server. That's an obvious performance issue. The first ArmA already had scheduled script execution. The DCS core presumably relies on a global, locking, all-comprising, single-threaded event loop. Adding a (few) thousand units on the far side of the map (or planet), i.e., far outside of the visibility range, will slow the renderer to a crawl. Rendering is apparently not decoupled from the simulation (i.e., AI, pathfinding, logic, flight models, etc.), although it could and should be for obvious performance reasons. This is most likely owed to DCS' single-threaded legacy. I presume a lot of engineering effort will be required to fix this. The elusive brown crater texture bug and the on-again, off-again multiplayer scoreboard issue, and more importantly the time it took to fix either of them, point towards the DCS core being non-trivial to maintain. All of these issues indicate that there's a lot of technical debt within the DCS core. Eventually, dealing with the bugs and issues caused by such technical debt will crush feature development. I agree with the previous posters that argue for better prioritization of core development time. More time should be allotted to improving the DCS core, including the scripting system and its documentation. Obviously, a full feature moratorium on the DCS core would be too much, as that would interfere with its business model. If strictly required for module releases, features need to be added. However, IMHO, too much development time may have been spent on not strictly necessary features in the past, e.g., the aircraft radio integration of the voice chat system (everyone still uses SRS), the currently incomplete mission state save feature, the botched C-ares integration, and the recent net.dostring_in() mishap to name what's at the top of my head. I love DCS and I'm confident ED can turn the ship around. Take the necessary time to stabilize the DCS core (incl. documentation, pwees!) and postpone not strictly necessary feature work for the time being. I'm hopeful the community will understand. Ask the community for feedback early on before deciding on breaking changes (I feel like the scripting system will eventually need a complete, breaking overhaul). A publicly accessible bug tracker may be another improvement. Using the forum to file bug reports may be susceptible to oversight of straightforward bug reports [1].
-
I finally managed to stumble over your issue. Unfortunately, I've been unable to reliably reproduce it. The root cause is a partially initialized ~/.wine WINEPREFIX directory that lacks basic DLLs like .wine/drive_c/windows/system32/kernel32.dll. There's a straightforward fix. Force a reinitialization with wineboot: rm ~/.wine/.update-timestamp wineboot --init Then simply rerun the install script, which should run without the error.
-
Recently pushed Commit 17647ec, which adds the "scripting" Lua state to WebConsole.lua. This new Lua state appared with DCS 2.9.18.12722, but – obviously – came without any documentation. If anyone knows what its purpose might be, please let me know. I first assumed it might be a shortcut to net.dostring_in("mission", "a_do_script(" .. code .. ")"), but it appears to lead to an entirely different Lua state.
-
Changes to the behaviour of net.dostring_in()
Actium replied to BIGNEWY's topic in Scripting Tips, Tricks & Issues
Any updates you can share with us? Please do solicit public feedback on your idea before actually implementing it. -
It was indeed supposed to pass-thru multiple return values. However, that pass-thru never worked. With the changes being reverted, I'd expect that broken pass-thru to also be reverted, returning to the old behavior. Not quite. Lua's native pcall() demonstrates how to do it properly. It returns the success boolean first and then either an error message or all return values. That enables discriminating between both cases. Unfortunately, net.dostring_in() uses the objectively wrong ordering. Simply returning nil will not allow to differentiate between a net.dostring_in() error and the executed code rightfully returning nil. For lack of an error message in case of a net.dostring_in() error condition, debugging is also complicated.
-
SRS version 2.2 added a native Linux command line server. I've recently pushed commit 2f81056, which uses the native SRS server in place of the Windows GUI server via Wine. That removes quite a bit of complexity. When upgrading an existing installation, you will have to manually update all instance configurations DCS.* from DCS_defaults.
-
The net.dostring_in() function has the following function signature to run code in the Lua environment state (type hints after the colon): net.dostring_in(state: string, code: string) -> return_value: string, success: boolean Example with Valid State (for Comparison) Run the following code via the Scripts/Hooks folder, i.e., from the "gui" state: return {net.dostring_in("mission", "return 42")} Successful return value: { "42", true } Example with Invalid State Try to run the same code inside a non-existing state: return {net.dostring_in("invalid", "return 42")} Up until DCS 2.9.17.12034, using an invalid Lua state name returned a proper error message: { "Invalid state name", false } Since DCS 2.9.18.12722, net.dostring_in() now returns only nil, resulting in an empty table: {} I've said it before: A simple unit test could have prevented releasing DCS with such basic bugs.
-
Changes to the behaviour of net.dostring_in()
Actium replied to BIGNEWY's topic in Scripting Tips, Tricks & Issues
Thank you and the team for the quick revert! Unfortunately, that leaves the DCS client and server vulnerable to arbitrary code execution via maliciously crafted mission files. I believe a temporary mitigation should be applied until a more permanent solution has been found. The net.dostring_in() wrapper I suggested above limits the availability of net.dostring_in() from within mission scripting to the "mission" Lua state. I presume that is the primary use of net.dostring_in() to access the a_*() functions from mission scripts. IIRC, there are mission scripts out there that use net.dostring_in("gui", ...) to change/restart missions via the F10 menu. These would be collateral damage of that fix. Please do chime in if anyone has any concerns regarding that mitigation approach. As the dedicated server is also vulnerable, a suitable configuration method for both client and server (no GUI) should be found. Suggestion for a Permanent Fix IMHO, restricting net.dostring_in() use would be a too radical change in terms of API breakage. Given an option to bypass these restrictions, there will always be countless videos and posts suggesting to enable the bypass. I know quite a few people who simply remove the sanitization from MissionScripting.lua without understanding the security implications of that action. Instead, this should be fixed at the root of the vulnerability, most importantly io.open(), os.execute(), and similar functions in the io, lfs, os modules. Arbitrary read/write file system access and executing arbitrary commands are trivially exploitable vulnerabilities. File system read access should be restricted to the relevant DCS directories, i.e., lfs.currentdir(), lfs.tempdir(), and lfs.writedir(). Write permissions should be restricted even further to prevent shenanigans like changing configuration files (fundamental flaw of the now revoked security option). This is similar to what @cfrag suggested in terms of a sandboxed 'writeString()' method. Mods that require deeper file system access could accomplish that thru a self-compiled Lua .dll module (and take responsibility for whatever vulnerabilites that results in). Access to os.execute() should probably be prohibited unless explicitly enabled. Not sure how to do that securely. The only way I've seen it used is by the SRS scripts to launch the SRS client when connecting to an SRS-enabled server. As above, I'd appreciate feedback on whether any mission/mod makers believe it would break their content. @BIGNEWY Are you and the team interested in concrete implementation suggestions from the community? If so, we could discuss sth. here. If not, I'll save myself the effort. -
The issue described in this post has been resolved with today's hotfix (2.9.18.12899). Hiding the original post in the following spoiler to prevent confusing users with obsolete information: On a side note, the a_do_script() return value pass-thru has returned with 2.9.18.12722. It was initially added with 2.9.13.6818 and silently removed in 2.9.15.9408 to fix a segmentation fault. Following in its first incarnation's footsteps, the reincarnation of a_do_script() return value pass-thru is also broken, so we'll have to stick with the temporary file workaround for now.
-
Changes to the behaviour of net.dostring_in()
Actium replied to BIGNEWY's topic in Scripting Tips, Tricks & Issues
@BIGNEWY As you are soliciting feedback, here's mine. Please forward this to your developers. I've reported an arbitrary code execution vulnerability, initially in December '24, which I presume may be related to this API change. Recently, I've also suggested a straightforward mitigation method that would incur far less collateral damage than the current approach. TL;DR The new net.dostring_in() security option is conceptually flawed: It only mitigates the vulnerability in a basic configuration, its configuration can be easily changed from privileged scripts (rendering it useless), and, most importantly, it cannot be configured to allow required, legitimate use of net.dostring_in(), while simultaneously preventing potential exploits. The changes cause a lot of collateral damage, while not fixing the root cause of the vulnerability. IMHO, this change should be reverted and ultimately substituted with a superior alternative. This alternative should be co-developed with community contributors that rely on the scripting API to find a proper solution. Inofficial Security Advisory What this fails to mention is that DCS versions from at least 2.9.10 (probably sooner) thru 2.9.17 are vulnerable to arbitrary code execution via specially crafted mission files. I'll responsibly refrain from divulging any further information. Suffice it to say that I figured out how to exploit the vulnerability from information that I gleaned from this forum, so the required knowledge is already out there. The exploit does not require the now added return value pass-thru of net.dostring_in(), which is apparently broken anyway. Beware of untrusted mission files in combination with exemplary autoexec.cfg files out there! As predicted by many previous posters, I've already seen a few autoexec.cfg incarnations with potentially unsafe settings. Anything that includes "scripting" in net.allow_unsafe_api is presumably dangerous. Kudos to ED for clearly pointing this out in %DCS_INSTALL_DIR%/API/Sim_ControlAPI.html: net.allow_unsafe_api = { "userhooks", -- will make the API visible in _$WRITE_DIR/Scripts/Hooks/*.lua_ scripts "scripting", -- enables the API in the mission scripting state. DANGEROUS!!! "gui", -- system hooks and GUI state } @BIGNEWY This very important detail is hidden away. I'd suggest to add it to your first post in this thread. Technical Background To comprehensively address the efficacy of the security option, I first have to outline my understanding of the technical background of net.dostring_in(). @Experts: Please correct me if I'm wrong with anything! DCS relies on multiple Lua interpreter instances to isolate different scripting zones/environments/namespaces from each other. They contain entirely separate global environments (_G variable). These are called lua_State in the Lua documentation and are also referred to as states in DCS' documentation. The states are isolated from each other, but some applications require to run code and get return values from other states. That is where net.dostring_in() comes in: AFAIK, the following Lua states exist: "config", "export", "gui", "mission", "server", "scripting" (new since DCS 2.9.18; separate from a_do_script()), and "userhooks" (new since DCS 2.9.18). Some of these states are trusted and privileged, e.g., "gui", "server", and "userhooks". These are allowed to read and write arbitrary files and call external programs, which is how SRS launches the client automatically on SRS-enabled servers. Other, unprivileged states run untrusted code from mission files, e.g., the "mission" state. Potentially dangerous Lua functions, e.g., for writing files and calling executables, are sanitized from these unprivileged states. @BIGNEWY What's the purpose of the new "scripting" state? It appears to be a separate Lua state from both "mission" and a_do_script(). Benefit / Efficacy The implemented security option restricts the use of net.dostring_in() within privileged, trusted Lua states, too. As these states already have access to privileged Lua functions, using net.dostring_in() to access a different state will not result in privilege escalation. Also, if the respective state can write files, it can modify autoexec.cfg and edit net.allow_* to change the security options to more permissible ones (after a game restart). Hence, attempting to restrict these privileged states is entirely useless. Unfortunately, that design choice has an unpleasant side effect: To permit the already privileged states to access all other states, implies permitting the non-privileged states to access all other states, too, because there's only one global net.allow_dostring_in setting shared between all source states (where net.dostring_in() is called from). A real-world example would be the need to let "userhooks" access "server" (e.g., Olympus) and let the mission scripting state ("scripting"?) access the "mission" (triggers) state, e.g., to access functions like a_unit_set_life_percentage(). That would result in the exploitable situation, where mission scripting can access the "server" state. The breaking changes do not fix the root cause of the vulnerability, which is the availability of potentially dangerous functions that allow unrestricted read/write file access and the execution of arbitrary programs. How to deal with these potentially dangerous functions should be the subject of a future discussion. Which missions/mods/scripts need them and how they could be made safe. Cost / Breakage Scripting in DCS is already not trivial due to the fragmented Lua states, requiring workarounds that rely on net.dostring_in("mission", ...) [1, 2] and a general lack of documentation. Incompatible API changes that break these workarounds frustrate the mission makers that desperately rely on them. The alleged obsolescence of net.dostring_in() (see above quote) adds to the feeling that the developers are not fully aware of what their API users actually need. There are many uses for net.dostring_in(), e.g., Olympus, Lua consoles, etc., for which a_do_script() is not an alternative. I'd highly recommend to discuss such drastic API changes with the community well in advance. Breaking changes must always be thoroughly studied and it is painfully obvious that these changes have not received the amount of thought they deserve. Conclusion The design of this new security option is fundametally flawed: It is inherently insecure, i.e., vulnerable to arbitrary code execution, when configured for standard use cases, e.g., Olympus + access to "mission" state from a_do_script(). It adds unnecessary complexity by restricting already privileged Lua states, where the availability of net.dostring_in() does not enable privilege escalation. Hence, this does not improve security. The security option configuration is not tamper-proof. Privileged Lua states can modify autoexec.cfg arbitrarily to bypass all previously configured restrictions after a DCS restart. This design issue renders the security option useless. Above issues illustrate how the security option design is ill-conceived. These issues alone are sufficient to revoke these changes and to restore the scripting system to the behavior of DCS 2.9.17. What makes matters worse, however, is the collateral damage in terms of API incompatibility, which breaks community content. Alternative To alternatively mitigate the arbitrary code execution vulnerability, while simultaneous permitting legitimate use of net.dostring_in() from mission scripting, the following wrapper function could be placed within %DCS_INSTALL_DIR%/Scripts/MissionScripting.lua: ---BEGIN-MISSION-SCRIPTING-EXPLOIT-MITIGATION--- -- insert this block into %DCS_INSTALL%/Scripts/MissionScripting.lua above: -- --Sanitize Mission Scripting environment -- mitigate arbitrary code execution vulnerability with a wrapper for -- `net.dostring_in()` that restricts its access to the "mission" Lua state. -- accessing the "mission" Lua state is required for some advanced scripting: -- * https://forum.dcs.world/topic/354648-add-setlife-function-to-lua-api/ -- * https://forum.dcs.world/topic/358877-lua-function-unitsetlife/ -- * https://forum.dcs.world/topic/371036-outpicturefor-lua-mission-scripting-functions/#findComment-5672179 -- this copies `net.dostring_in()` into a lexically scoped local variable and -- then overwrites the original function with a wrapper, which captures the -- local exclusively, because Lua is scoped lexically: -- https://www.lua.org/pil/6.1.html local _dostring_in = net.dostring_in function net.dostring_in(lua_state, code) if lua_state == "mission" then local _result, _success = _dostring_in("mission", code) return _result, _success else -- TODO: add error logging return "Invalid state name", false end end ---END-MISSION-SCRIPTING-EXPLOIT-MITIGATION--- Obviously, this is provided as is, without any warranty of any kind (as per the stipulations of the MIT license). You should know your code better than me to figure out whether this is safe or not. Regardless, I hope this helps make DCS safer, while keeping mission makers happy. -
Changes to the behaviour of net.dostring_in()
Actium replied to BIGNEWY's topic in Scripting Tips, Tricks & Issues
I can confirm that this does indeed not work as advertised. Running the following code from DCS.openbeta/Scripts/Hooks return {net.dostring_in("mission", "return 1,2,3")} will yield the following return value: [ "1", true ] Maybe there's a mixup with a_do_script() available from the mission environment/zone? See the recently updated %DCS_INSTALL_DIR%/API/Sim_ControlAPI.html: The a_do_script() change is also part of the 2.9.18.12722 changelog. However, it is also broken, despite being the second attempt [1, 2]. -
DCS 2.9.18.12722 re-introduces a_do_script() and a_do_file() return value pass-thru, after a previously failed attempt: Unfortunately, return values are only partially passed thru. Specifically, the last return value is always dropped. That results in no return value being passed thru if a single return value is used: return a_do_script("return 42") Yields a nil return value. %DCS_INSTALL_DIR%/API/Sim_ControlAPI.html gives a more complex example with multiple return values being passed thru: -- original example in Sim_ControlAPI.html local a, b, c = a_do_script("return 1,2,3") -- added return code for illustration return {a = a, b = b, c = c} It results in the following return value (instead of a=1,b=2,c=3): { ["a"] = nil, -- added for illustration purposes ["b"] = 1, ["c"] = 2 } Steps to Reproduce Run the above code snippets in the mission Lua state via a DCS Lua console of your choice, e.g., my WebConsole.lua. Note that this will require modification of autoexec.cfg to provide access to the mission state via net.dostring_in() from the userhooks state. P.S.: This could have been easily caught automatically by a very simple unit test. I'd like to encourage ED to start using these tests to avoid delivering broken releases. As this is not the first occurrence of broken a_do_script() code, it is apparent that your current testing strategies are insufficient.
-
- 1
-
-
No connection issues in the log. Master server just opted to terminate the session for no apparent reason: 2025-05-28 19:12:57.649 INFO ASYNCNET (4100): Login success. 2025-05-28 19:13:02.135 INFO ASYNCNET (4100): Got auth data. 2025-05-28 19:13:02.580 INFO ASYNCNET (Main): ProtocolVersion: 402 2025-05-28 19:13:02.580 INFO ASYNCNET (Main): Adding LAN search interface 0: 127.0.0.1 "IPv4 Loopback" 2025-05-28 19:13:02.580 INFO ASYNCNET (Main): Adding LAN search interface 0: 255.255.255.255 "IPv4 Broadcast" 2025-05-28 19:24:59.022 ERROR ASYNCNET (4100): The session has expired (401). Exiting...
-
In a simple BVR scenario with a flight of 4 MiG-29 air-starting in a line abreast formation, the flight presumably attempts to switch to a grind formation. That typically results in some of the wingmen (usually trailing pair) stalling at 130 kts IAS and 21° AoA on full burn until they snap out of it minutes later when a plane finally gets hit. This is not limited to the Fulcrum, but also occurs with the Flanker. Starting with a trailing formation may result in fewer stalled planes. This has been previously reported for the F/A-18. I've attached a track and a tacview: AI_stall.trkAI_stall.acmi Screenshot of starting position: Screenshot of trailing element stalling after switching to grind:
-
- 1
-
-
Failure to resolve api.digitalcombatsimulator.com will be logged as ASYNCNET errors/warnings in dcs.log (likely sth. to the tune of error 6: Could not resolve hostname). If your dcs.log does not contain such messages, it's definitely not DNS.
-
@Roughneck Have you had a look at your dcs.log for sessions that got terminated? Here's a quick way to grep the relevant ASYNCNET messages from dcs.log via PowerShell: Get-Content "$env:USERPROFILE\Saved Games\DCS.openbeta\Logs\dcs.log" | Select-String ASYNCNET Wondering whether it includes any session check errors/warnings or the The session has expired (401). Exiting... message comes entirely out of the blue.
-
@Hempstead Thanks for sharing. I've had a look. These are all occurrences of ASYNCNET within the log file: 2025-07-03 18:48:27.090 INFO ASYNCNET (34508): Login success. 2025-07-03 18:48:29.799 INFO ASYNCNET (34508): Got auth data. 2025-07-03 18:48:29.854 INFO ASYNCNET (Main): ProtocolVersion: 404 2025-07-03 18:48:29.854 INFO ASYNCNET (Main): Adding LAN search interface 0: 127.0.0.1 "IPv4 Loopback" 2025-07-03 18:48:29.854 INFO ASYNCNET (Main): Adding LAN search interface 0: 255.255.255.255 "IPv4 Broadcast" 2025-07-03 19:00:30.957 ERROR ASYNCNET (34508): The session has expired (401). Exiting... So far, I've only observed and been able to reproduce this issue when the client reconnects to the master server after a 30ish minute connection interruption as I've reported here. That would result in many more ASYNCNET error/warning messages like this: 0000-00-00 00:00:00.000 ERROR ASYNCNET (192): HTTP request dcs:checksession failed with error 7: Could not connect to server 0000-00-00 00:00:00.000 WARNING ASYNCNET (192): Session check failed: -7 However, your occurrence of this issue appears to have happened entirely out of the blue without any prior connection issues. Presumably, the master server decided to just expire your session. Based on a previous post from BN, I've had a hunch that changing your IP address while logged in may cause the master server to terminate your session: I've tried to reproduce this, but changing my public IP address (have the router reconnect) twice for 3 consecutive session checks from 3 different IPs didn't trigger the issue for me. Unfortunately, the master server does not give any reason why it expires your session. Is there anything else on your side that could have caused it? It'd probably be best to open a support ticket, hoping that ED have a server-side master server log with more debug information.
-
There have been issues with memory leaks in the past. Not necessarily related, but probably worth a read:
-
@Simpit While you're in singleplayer, using the offline mode is a workaround for this issue. Would you mind sharing a dcs.log of the session to help figure out what caused the termination?
-
Would you mind sharing a dcs.log for that session? If it kicked you out within 10 minutes of starting the game, there must be more ways this issue is caused than I described here. I doubt you started a second DCS instance while busy bombing those T-72s.
-
Background updates, i.e., running DCS while its being updated, would be another great feature (being worked on, unfortunately, as part to the launcher). Preferably, it should enable already running part of the new version (base DCS + user-selected terrains) while the rest is being updated in the background. Obviously, that requires download speed limits to enable simultaneous multiplayer.
-
Mind sharing one or more dcs.log file(s) of the expired sessions? Unfortunately, the error popup message is identical for a couple of different causes. If it happened that early after starting the game, I wonder what exactly occurred.