pegasus
Well-known member
While looking into this issue, I became aware of some aspects of the Deferred system in XenForo which I feel should be addressed, as it will help prevent future problems like this from being so bad: https://www.vaultwiki.org/articles/160/
Please note that the linked issue only occurs because of a workaround intended to "improve" the behavior of XenForo's Deferred system. If XenForo's deferred system were already like this, potentially dangerous workarounds like those would not even be attempted. Even if such a workaround is still attempted, XenForo will now be smart enough to handle the situation.
#1 Basically, if an add-on adds a manual entry to the defer table, there should be a column that associates the entry with the add-on. This way:
1. If the add-on is disabled, the deferred entry is not run.
2. If the add-on is disabled, the deferred entry is not required to have code to skip itself and allow itself to be removed from the queue (for data integrity purposes, the task should still be queued on add-on re-enable).
3. The add-on will not need to workaround #2, as a failure during a workaround could result in an infinite deferred.php attack.
Once the deferred system knows add-on IDs, it will only run deferred tasks for active add-ons. If there are no more tasks from active add-ons, there is no more next-run time. The next-run time can be recalculated whenever an add-on is enabled or disabled.
#2 Secondly, don't automatically remove a task before it runs! Even if the task fails, it may be necessary for it to run eventually. Instead of removing the task before running, place a lock on the task so it is not valid for next-run until the current run completes (I recommend using a locktime field, so you can log tasks as failed if they have been locked for a long time). After a successful run, instead of adding a new task if 'moreDeferred', simply release the lock.
These simple changes will increase the solidness of the deferred system and help to mitigate situations like those linked above where XenForo unknowingly launches a DDoS attack against itself, or if the deferred task is coded in such a way that still makes it possible, that the attack can be stopped simply by disabling the add-on.
Please note that the linked issue only occurs because of a workaround intended to "improve" the behavior of XenForo's Deferred system. If XenForo's deferred system were already like this, potentially dangerous workarounds like those would not even be attempted. Even if such a workaround is still attempted, XenForo will now be smart enough to handle the situation.
#1 Basically, if an add-on adds a manual entry to the defer table, there should be a column that associates the entry with the add-on. This way:
1. If the add-on is disabled, the deferred entry is not run.
2. If the add-on is disabled, the deferred entry is not required to have code to skip itself and allow itself to be removed from the queue (for data integrity purposes, the task should still be queued on add-on re-enable).
3. The add-on will not need to workaround #2, as a failure during a workaround could result in an infinite deferred.php attack.
Once the deferred system knows add-on IDs, it will only run deferred tasks for active add-ons. If there are no more tasks from active add-ons, there is no more next-run time. The next-run time can be recalculated whenever an add-on is enabled or disabled.
#2 Secondly, don't automatically remove a task before it runs! Even if the task fails, it may be necessary for it to run eventually. Instead of removing the task before running, place a lock on the task so it is not valid for next-run until the current run completes (I recommend using a locktime field, so you can log tasks as failed if they have been locked for a long time). After a successful run, instead of adding a new task if 'moreDeferred', simply release the lock.
These simple changes will increase the solidness of the deferred system and help to mitigate situations like those linked above where XenForo unknowingly launches a DDoS attack against itself, or if the deferred task is coded in such a way that still makes it possible, that the attack can be stopped simply by disabling the add-on.
Last edited:
Upvote
2