Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] mac_xattr execution module fails on binary plist attributes #63779

Closed
1 of 9 tasks
sheagcraig opened this issue Feb 27, 2023 · 5 comments · Fixed by #64039
Closed
1 of 9 tasks

[BUG] mac_xattr execution module fails on binary plist attributes #63779

sheagcraig opened this issue Feb 27, 2023 · 5 comments · Fixed by #64039
Assignees
Labels
Bug broken, incorrect, or confusing behavior bytes-vs-strings py2 vs py3 bytes vs strings encode/decode errors Execution-Module MacOS pertains to the OS of fruit

Comments

@sheagcraig
Copy link
Contributor

sheagcraig commented Feb 27, 2023

Description
Apple stores some file attribute information as binary plists, and in such a way that the bytes return from xattr cause a UnicodeDecodeError.

Setup
Salt 3004.2, masterless, on an M1 Mac.

  • on-prem machine
  • VM (Virtualbox, KVM, etc. please specify)
  • VM running on a cloud service, please be explicit and add details
  • container (Kubernetes, Docker, containerd, etc. please specify)
  • or a combination, please be explicit
  • jails if it is FreeBSD
  • classic packaging
  • onedir packaging
  • used bootstrap to install

Steps to Reproduce the behavior

  • Download something with Safari. I did ghostunnel but I suspect basically anything works.
  • sudo salt-call xattr.read ~/Downloads/ghostunnel-darwin-universal com.apple.metadata:kMDItemWhereFroms
sudo salt-call xattr.read ~/Downloads/ghostunnel-darwin-universal com.apple.metadata:kMDItemWhereFroms
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa2 in position 8: invalid start byte
Traceback (most recent call last):
  File "/opt/local/bin/salt-call", line 33, in <module>
    sys.exit(load_entry_point('salt==3004.2', 'console_scripts', 'salt-call')())
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/scripts.py", line 432, in salt_call
    client.run()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/cli/call.py", line 55, in run
    caller.run()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/cli/caller.py", line 111, in run
    ret = self.call()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/cli/caller.py", line 219, in call
    self.opts, data, func, args, kwargs
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 149, in __call__
    return self.loader.run(run_func, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1201, in run
    return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1216, in _run_as
    return _func_or_method(*args, **kwargs)
  File "/opt/salt/.pyenv/versions/3.7.12/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/executors/direct_call.py", line 10, in execute
    return func(*args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 149, in __call__
    return self.loader.run(run_func, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1201, in run
    return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1216, in _run_as
    return _func_or_method(*args, **kwargs)
  File "/opt/cpe-salt/salt/_modules/mac_xattr.py", line 116, in read
    ret = salt.utils.mac_utils.execute_return_result(cmd)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/mac_utils.py", line 178, in execute_return_result
    ret = _run_all(cmd)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/mac_utils.py", line 117, in _run_all
    out = salt.utils.stringutils.to_str(out).rstrip()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/stringutils.py", line 90, in to_str
    raise exc  # pylint: disable=raising-bad-type
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/stringutils.py", line 83, in to_str
    return _normalize(s.decode(enc, errors))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa2 in position 8: invalid start byte
Traceback (most recent call last):
  File "/opt/local/bin/salt-call", line 33, in <module>
    sys.exit(load_entry_point('salt==3004.2', 'console_scripts', 'salt-call')())
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/scripts.py", line 432, in salt_call
    client.run()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/cli/call.py", line 55, in run
    caller.run()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/cli/caller.py", line 111, in run
    ret = self.call()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/cli/caller.py", line 219, in call
    self.opts, data, func, args, kwargs
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 149, in __call__
    return self.loader.run(run_func, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1201, in run
    return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1216, in _run_as
    return _func_or_method(*args, **kwargs)
  File "/opt/salt/.pyenv/versions/3.7.12/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/executors/direct_call.py", line 10, in execute
    return func(*args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 149, in __call__
    return self.loader.run(run_func, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1201, in run
    return self._last_context.run(self._run_as, _func_or_method, *args, **kwargs)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/loader/lazy.py", line 1216, in _run_as
    return _func_or_method(*args, **kwargs)
  File "/opt/cpe-salt/salt/_modules/mac_xattr.py", line 116, in read
    ret = salt.utils.mac_utils.execute_return_result(cmd)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/mac_utils.py", line 178, in execute_return_result
    ret = _run_all(cmd)
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/mac_utils.py", line 117, in _run_all
    out = salt.utils.stringutils.to_str(out).rstrip()
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/stringutils.py", line 90, in to_str
    raise exc  # pylint: disable=raising-bad-type
  File "/opt/salt/lib/python3.7/site-packages/salt-3004.2-py3.7.egg/salt/utils/stringutils.py", line 83, in to_str
    return _normalize(s.decode(enc, errors))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa2 in position 8: invalid start byte

For what it's worth, the bytes returned also fail when trying to plistlib.loads so there's not an easy path here to just use that.

Expected behavior
Ideally the plist would be parsed and returned in a nicely formatted str, but I can't figure out how to coerce the builtin plistlib to handle it.

Screenshots
If applicable, add screenshots to help explain your problem.

Versions Report

salt --versions-report (Provided by running salt --versions-report. Please also mention any differences in master/minion versions.)
Salt Version:
          Salt: 3004.2

Dependency Versions:
          cffi: 1.14.6
      cherrypy: 18.6.1
      dateutil: 2.8.0
     docker-py: Not Installed
         gitdb: 4.0.5
     gitpython: 3.1.12
        Jinja2: 2.11.3
       libgit2: Not Installed
      M2Crypto: Not Installed
          Mako: 1.1.4
       msgpack: 1.0.2
  msgpack-pure: Not Installed
  mysql-python: Not Installed
     pycparser: 2.19
      pycrypto: 3.15.0
  pycryptodome: 3.9.8
        pygit2: Not Installed
        Python: 3.7.12 (default, May 13 2022, 19:05:09)
  python-gnupg: 0.4.4
        PyYAML: 5.4.1
         PyZMQ: 18.0.1
         smmap: 3.0.2
       timelib: 0.2.4
       Tornado: 4.5.3
           ZMQ: 4.3.1

System Versions:
          dist: darwin 22.4.0
        locale: UTF-8
       machine: x86_64
       release: 22.4.0
        system: Darwin
       version: 13.3 x86_64

Additional context
Add any other context about the problem here.

@sheagcraig sheagcraig added Bug broken, incorrect, or confusing behavior needs-triage labels Feb 27, 2023
@sheagcraig
Copy link
Contributor Author

I'm happy to submit a PR to fix this; we've been providing our own mac_xattr.py to solve this, but I'm wondering if there's any direction preferred for the solution.

  • Decode the binary plist bytes with the errors argument using either ignore or replace and just return a str.
  • Use the xattr -x argument to just spit out the hex values
  • Someone with mad skillz makes it work with plistlib.

@OrangeDog OrangeDog added Execution-Module MacOS pertains to the OS of fruit bytes-vs-strings py2 vs py3 bytes vs strings encode/decode errors labels Feb 27, 2023
@garethgreenaway
Copy link
Contributor

garethgreenaway commented Mar 6, 2023

@sheagcraig If you're able to provide a PR with the fix that would be great. If you can create two PRs, one against the master branch and another against the 3006 branch. Thanks!

@sheagcraig
Copy link
Contributor Author

Okay @garethgreenaway both PRs are up. The 3006.x one had some tests fail but I don't imagine it's due to my changes; probably just need to run again (100% passed on the Master branch).

@sheagcraig sheagcraig self-assigned this Apr 11, 2023
@garethgreenaway
Copy link
Contributor

@sheagcraig Thanks! The one against 3006.x needs a changelog file.

@sheagcraig
Copy link
Contributor Author

Just pending the #64039 to close this one out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug broken, incorrect, or confusing behavior bytes-vs-strings py2 vs py3 bytes vs strings encode/decode errors Execution-Module MacOS pertains to the OS of fruit
Projects
None yet
3 participants