From b1fd71de03ae3843ac556d9b726b5f3b2441c3ed Mon Sep 17 00:00:00 2001
From: Abhijeet Kasurde <akasurde@redhat.com>
Date: Thu, 27 Feb 2020 11:42:12 +0530
Subject: [PATCH] Add whitelisting for package and service module

**security issue** (CVE-2020-1738)
When 'use' parameter is not used in package and service module,
ansible relies on ansible facts such as 'pkg_mgr' and 'service_mgr'.

This would allow arbitrary code execution on the managed node.

Fix is added by adding a whitelist of allowed package manager modules and
service manager modules to avoid arbitrary code execution on the managed node.

Fixes: #67796

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
---
 changelogs/fragments/67796-package-service-fact_fix.yml | 4 ++++
 lib/ansible/plugins/action/package.py                   | 8 ++++++++
 lib/ansible/plugins/action/service.py                   | 5 +++++
 3 files changed, 17 insertions(+)
 create mode 100644 changelogs/fragments/67796-package-service-fact_fix.yml

diff --git a/changelogs/fragments/67796-package-service-fact_fix.yml b/changelogs/fragments/67796-package-service-fact_fix.yml
new file mode 100644
index 0000000000000..ce1ee71da08e0
--- /dev/null
+++ b/changelogs/fragments/67796-package-service-fact_fix.yml
@@ -0,0 +1,4 @@
+bugfixes:
+  - >
+    **security issue** Add a whitelist of modules for package and service module
+    when 'use' is not used and engine relies on pkg_mgr and service_mgr facts (CVE-2020-1738).
diff --git a/lib/ansible/plugins/action/package.py b/lib/ansible/plugins/action/package.py
index 932acccb04b66..8884086d8d6c5 100644
--- a/lib/ansible/plugins/action/package.py
+++ b/lib/ansible/plugins/action/package.py
@@ -56,6 +56,14 @@ def run(self, tmp=None, task_vars=None):
                 module = facts.get('ansible_facts', {}).get('ansible_pkg_mgr', 'auto')
 
             if module != 'auto':
+                if module not in ['apk', 'apt_rpm', 'apt', 'dnf', 'homebrew_cask',
+                                  'homebrew_tap', 'homebrew', 'installp', 'macports', 'mas',
+                                  'openbsd_pkg', 'opkg', 'pacman', 'pkg5', 'pkgin',
+                                  'pkgng', 'pkgutil', 'portage', 'portinstall', 'slackpkg',
+                                  'snap', 'sorcery', 'svr4pkg', 'swdepot', 'swupd',
+                                  'urpmi', 'xbps', 'yum', 'zypper']:
+                    raise AnsibleActionFail('Could not find a module for package manager %s.'
+                                            'Try setting the "use" option.' % module)
 
                 if module not in self._shared_loader_obj.module_loader:
                     raise AnsibleActionFail('Could not find a module for %s.' % module)
diff --git a/lib/ansible/plugins/action/service.py b/lib/ansible/plugins/action/service.py
index 3ebd0ae17dc90..e11ab1e287164 100644
--- a/lib/ansible/plugins/action/service.py
+++ b/lib/ansible/plugins/action/service.py
@@ -61,6 +61,11 @@ def run(self, tmp=None, task_vars=None):
                 module = 'service'
 
             if module != 'auto':
+                # Check if auto detected module is valid module name or not
+                if module not in ['nosh', 'openwrt_init', 'runit',
+                                  'svc', 'systemd', 'sysvinit', 'service']:
+                    raise AnsibleActionFail('Could not find module for "%s" service manager. '
+                                            'Try setting the "use" option.' % module)
                 # run the 'service' module
                 new_module_args = self._task.args.copy()
                 if 'use' in new_module_args:
