supported_features.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. # -*- encoding: utf-8 -*-
  2. #
  3. # The Qubes OS Project, http://www.qubes-os.org
  4. #
  5. # Copyright (C) 2020 Marek Marczykowski-Górecki
  6. # <marmarek@invisiblethingslab.com>
  7. #
  8. # This library is free software; you can redistribute it and/or
  9. # modify it under the terms of the GNU Lesser General Public
  10. # License as published by the Free Software Foundation; either
  11. # version 2.1 of the License, or (at your option) any later version.
  12. #
  13. # This library is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. # Lesser General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Lesser General Public
  19. # License along with this library; if not, see <https://www.gnu.org/licenses/>.
  20. """Extension responsible for announcing supported features"""
  21. import qubes.ext
  22. import qubes.config
  23. # pylint: disable=too-few-public-methods
  24. class SupportedFeaturesExtension(qubes.ext.Extension):
  25. """This extension handles VM announcing non-service features as
  26. 'supported-feature.*' features.
  27. """
  28. @qubes.ext.handler('features-request')
  29. def supported_features(self, vm, event, untrusted_features):
  30. """Handle advertisement of supported features"""
  31. # pylint: disable=no-self-use,unused-argument
  32. if getattr(vm, 'template', None):
  33. vm.log.warning(
  34. 'Ignoring qubes.FeaturesRequest from template-based VM')
  35. return
  36. new_supported_features = set()
  37. for requested_feature in untrusted_features:
  38. if not requested_feature.startswith('supported-feature.'):
  39. continue
  40. if untrusted_features[requested_feature] == '1':
  41. # only allow to advertise feature as supported, lack of entry
  42. # means feature is not supported
  43. new_supported_features.add(requested_feature)
  44. del untrusted_features
  45. # if no feature is supported, ignore the whole thing - do not clear
  46. # all features in case of empty request (manual or such)
  47. if not new_supported_features:
  48. return
  49. old_supported_features = set(
  50. feat for feat in vm.features
  51. if feat.startswith('supported-feature.') and vm.features[feat])
  52. for feature in new_supported_features.difference(
  53. old_supported_features):
  54. vm.features[feature] = True
  55. for feature in old_supported_features.difference(
  56. new_supported_features):
  57. del vm.features[feature]