From c8f4a56cad557d056534f604aa5ecfad68c413ec Mon Sep 17 00:00:00 2001 From: Dale Sedivec Date: Fri, 19 Apr 2013 20:11:23 -0500 Subject: [PATCH] Don't send unicode instances to the selinux module This fixes #2632. Briefly: specifying things like paths using complex args in a playbook will make the objects unicode instances. The selinux module does not accept unicode instances for its char * arguments; it wants str instances. Per mpdehaan's comment on #2632 I just went ahead and converted all paths to UTF-8. I don't know if it would be better to do something like converting to locale.getpreferredencoding(), but I factored all the conversions out into new method _to_filesystem_str, so there's only one place that needs to be changed in the future. --- lib/ansible/module_common.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/ansible/module_common.py b/lib/ansible/module_common.py index 8e221ad9e75..5c92abfd632 100644 --- a/lib/ansible/module_common.py +++ b/lib/ansible/module_common.py @@ -271,13 +271,26 @@ class AnsibleModule(object): context.append(None) return context + def _to_filesystem_str(self, path): + '''Returns filesystem path as a str, if it wasn't already. + + Used in selinux interactions because it cannot accept unicode + instances, and specifying complex args in a playbook leaves + you with unicode instances. This method currently assumes + that your filesystem encoding is UTF-8. + + ''' + if isinstance(path, unicode): + path = path.encode("utf-8") + return path + # If selinux fails to find a default, return an array of None def selinux_default_context(self, path, mode=0): context = self.selinux_initial_context() if not HAVE_SELINUX or not self.selinux_enabled(): return context try: - ret = selinux.matchpathcon(path, mode) + ret = selinux.matchpathcon(self._to_filesystem_str(path), mode) except OSError: return context if ret[0] == -1: @@ -290,7 +303,7 @@ class AnsibleModule(object): if not HAVE_SELINUX or not self.selinux_enabled(): return context try: - ret = selinux.lgetfilecon(path) + ret = selinux.lgetfilecon(self._to_filesystem_str(path)) except OSError, e: if e.errno == errno.ENOENT: self.fail_json(path=path, msg='path %s does not exist' % path) @@ -340,7 +353,8 @@ class AnsibleModule(object): try: if self.check_mode: return True - rc = selinux.lsetfilecon(path, ':'.join(new_context)) + rc = selinux.lsetfilecon(self._to_filesystem_str(path), + str(':'.join(new_context))) except OSError: self.fail_json(path=path, msg='invalid selinux context', new_context=new_context, cur_context=cur_context, input_was=context) if rc != 0: