Windows Service Silent Update: Difference between revisions
No edit summary |
|||
| Line 18: | Line 18: | ||
== New Windows Service component information == | == New Windows Service component information == | ||
The | The service information is: | ||
'''Display name:''' Mozilla Maintenance<br>'''Service name:''' MozillaMaintenance<br>'''File name:''' mozilla_maintenance.exe<br>'''Installation directory:''' %PROGRAMFILES%\Mozilla Maintenance Service | '''Display name:''' Mozilla Maintenance<br>'''Service name:''' MozillaMaintenance<br>'''File name:''' mozilla_maintenance.exe<br>'''Installation directory:''' %PROGRAMFILES%\Mozilla Maintenance Service | ||
| Line 25: | Line 25: | ||
*The service will be dealing with user tokens and therefore must be run as the SYSTEM account. | *The service will be dealing with user tokens and therefore must be run as the SYSTEM account. | ||
*The service will be located in the tree under /toolkit/components/maintenanceservice | *The service will be located in the tree under /toolkit/components/maintenanceservice | ||
To test and see if the service is installed, from a command prompt you can run: | |||
sc query MozillaMaintenance | |||
== How the service works == | == How the service works == | ||
Revision as of 13:53, 6 January 2012
Overview
Before this task, when a user installs into the default Program Files directory, updates cannot be applied without us first prompting the user for elevated permissions with a User Account Control (UAC) dialog.
After this task, Firefox will use a service to execute updates so that UAC prompts are not displayed.
The service is an on demand service and will remain stopped until it is needed, when it is needed it will be started again for the period of the update.
The task related to creating a service and not prompting the user for UAC is in bug 481815.
The feature page is located at: this feature page.
The security related bugs identified during the development of 481815, possibly blocking landing of 481815 are: bug 708688, bug 708697, bug 708690, bug 708778, bug 708854, bug 699700, bug 704285, bug 709173, bug 709183, and bug 709158.
New Windows Service component information
The service information is:
Display name: Mozilla Maintenance
Service name: MozillaMaintenance
File name: mozilla_maintenance.exe
Installation directory: %PROGRAMFILES%\Mozilla Maintenance Service
Other details about the service:
- The service will be dealing with user tokens and therefore must be run as the SYSTEM account.
- The service will be located in the tree under /toolkit/components/maintenanceservice
To test and see if the service is installed, from a command prompt you can run:
sc query MozillaMaintenance
How the service works
As soon as the service is started, it will watch a directory for new files. These new files are called 'work items'.
The directory being watched on Vista and above can be found here:
C:\ProgramData\Mozilla\updates
The directory being watched on Windows XP and below can be found in:
C:\Documents and Settings\All Users\Application Data\Mozilla\updates
Since the service is currently planned to only be started when needed, we may just have it scan a directory, do the work items it needs to, and then stop itself automatically. The service security will be modified with a special ACE which allows non elevated processes to start and stop it. Setting these permissions on the service is needed because by default services can only be started and stopped by elevated processes. This is possible via the Win32 API SetServiceObjectSecurity.
The service will log all operations of the last update, as well as backup the 5 update operation logs before it. The install process and update processes will also be logged separately. The logs will live in a directory alongside the updates directory being watched called logs.
Since the service executes an update via updater.exe in session 0, no UI will be displayed. A UI could be displayed by running updater.exe with a user token instead, but to avoid permission problems on files, and inconsistencies in different OS versions, the update will always be run as session 0.
A single service and service versioning
We plan to have only one Windows service which will service every product and every development channel.
- If a service is already installed, the service will be replaced on updates and installs only if it is newer than what is installed.
- If the user is running on an x64 computer with a native x64 build, then the service will not be installed nor used by that build. If the user is on an x64 computer with an x86 build, then the service will be used and installed by the build as an x86 process.
The service decides whether or not it is newer by looking at the updater file's version number in comparison to a new one being updated/installed. Only if the newer version number is greater will it be replaced. This means that if the user runs builds like Nightly, then the Nightly service would update all other channels. It will therefore always be backwards compatible.
Service work items
A 'work item' is just a file that contains the info that is usually passed to updater.exe to perform an update. Firefox writes out work items, and the service consumes those work items and performs the action specified within. The only action currently supported is to execute updater.exe.
Later we plan to also support commands for clearing prefetch for faster startup, defraging user profile data, and other actions not yet planned.
The very simple file format of these work items is:
- A 4 byte command ID.
- The application path to updater.exe to use
- The command line string to pass to updater.exe: updater.exe update-dir apply [wait-pid [callback-dir callback-path args]]
The 4 byte command ID is to help identify future commands. A value of 1 is the only accepted value for now and all other values will not perform any action from the service.
Applying an update from Firefox's perspective
- On Firefox (or any other Mozilla application that uses the service) startup, Firefox detects an update is ready to be applied
- Whether or not the service should be used, Firefox executes updater.exe unelevated.
- Firefox shuts itself down.
- updater.exe unelevated checks to see if the service should be used, and if so tries to start the service.
- updater.exe unelevated will write out a 'work item' file into the directory being watched with the work item details.
- If the service can't be started, is disabled, or does not exist, Firefox will execute updater.exe as it used to without the service.
- If the service was used, updater.exe unelevated waits for a global named event to be set which indicates the update is done.
- Once done updater.exe unelevated will run the callback application and the post update process.
Applying an update from the service's perspective
- The service gets started
- The service watches the work item directory for work items.
- The service detects that a 'work item' is written.
- The service parses the information from the work item file.
- The service verifies that updater.exe, and the callback application is our files (See section Signing builds below)
- The service will execute the update with updater.exe under the context of its own session (session 0) using CreateProcess.
- The path of updater.exe will be a copy of the updater.exe which exists inside the service directory. (A copy in case the original gets overwritten during the update).
- The post update process (helper.exe) currently does i) system level stuff, and ii) user level stuff. This component will be executed twice. The system level stuff will also be executed under session 0 using CreateProcess. The user level stuff will be executed by the unelevated updater.exe with its own session ID.
- The service sets a global named event to let the unelevated udpater.exe know it is done working.
When the service fails
- If there is an error creating the work item, we will fall back to the old way of updating: using updater.exe.
- If there is an error parsing the `work item` we assume it is not a valid work item that will be processed by the service.
- If there is an error creating the process, or during update, or a sign check error, an error is written to update.status and info is reported via telemetry on the next restart of the callback application. The next restart of the callback application will also set the status back to pending so that the update will be applied next time without the service.
Service as an optional component
If the service is not installed, or disabled, we will fall back to the old way of updating: using updater.exe
Limited user accounts
Whether a user is an administrator or a limited user account, they can initiate an update.
Service installation
- The service will be installed for users automatically via software update.
- There will be a checkbox in the installer for whether or not to install the service component.
- The service will be able to be uninstalled separately; it will show up as a new item under add/remove programs.
Signing builds
To ensure we execute our own binary, we will verify the signature of updater.exe to make sure it is signed by us. Currently we do not sign Nightly builds (I don't think Aurora either), we would like to have this fixed so that the udpate process gets more testing before this hits mozilla-central.
Spoofing the wrong session ID
All commands will be executed in the context of session 0. Only the post update process and callback will be executed with the user session ID. These commands will not be executed by the service though so there is no chance of spoofing the session ID via work item file.
The session ID is not included in the work item files because a limited user account could launch a valid Firefox.exe into an admin session with the URL of a dangerous page.
Applying updates faster
Another bug which is not part of this task plans to move updates away from on startup, and to perform them to an alternate directory in the background.
Preferences
- There will be a new about:config option for whether or not to use the service. It will also be exposed in update preferences.
- The new setting will be a boolean setting called app.update.service.enabled.
- This will be defaulted to False if it does not exist, but we will set this to True for Firefox in new profiles. So for other products it will be defaulted to false, but for Firefox it will be defaulted to True.
- Other products who want to use the service in the future should mark the setting as True.
- There will be a new about:config option for keeping track of the number of service errors called app.update.service.errors.
- There will be a new about:config option for keeping track of the max number of service errors to occur before disabling the service via app.update.service.enabled.
- When app.update.service.errors reaches app.update.service.maxerrors, or 10 if maxerrors does not exist, the service will be disabled and app.update.service.errors will be reset to 0.
Test cases
Below I describe some important things that come to mind that we should be testing. All of the usual update tests and more should also be tested.
- Test that using a limited user account does not install the service, nor prompt to install the service.
- Test that if the service is already installed, installing an update of a higher service number will replace the old service.
- Test that if the service is already installed, installing an update of a lower service number will NOT replace the old service.
- Test that if the service is already installed, and another product with a higher version number gets installed, it will replace the old service.
- Test that if the service is already installed, and another product with a lower version number gets installed, it will NOT replace the old service.
- Test the same above rules cross architecture, from both x86 and x64.
- Test applying updates from a limited user account.
- Test applying updates from a Windows 2000 machine.
- Test applying updates from a Windows XP machine.
- Test applying updates from a Windows Vista machine at each of the UAC levels.
- Test applying updates from a Windows 7 machine at each of the UAC levels.
- Test doing 2 updates at once.
- Test having a service with the same name that is not ours, we should apply update the old way on the next browser startup after the one that should have updated.
- Test that limited user accounts have access to all of their files after an upgrade through the service.
QA's test plan can be found here: https://wiki.mozilla.org/Silent_Update_OS_Dialogs/TestPlan
Individual tests (Simona): http://bit.ly/v74fFt
Test slave requirements for automated testing (Ehsan): https://wiki.mozilla.org/Silent_Update_OS_Dialogs/Automated_testing/Test_slaves_requirements
