← Back to team overview

touch-packages team mailing list archive

[Bug 1310598] Re: AppArmor python tools fail to parse mounts with UTF-8 non-ascii characters

 

Ok, so *I fixed it!*

Sorry guys, the 'patch' process is a bit complicated here, so I'll just
give a diff to what I have done, and explain why:

$ diff aa-status aa-status_orig 
137,140c137,140
<     for p in open("/proc/mounts","rb").readlines():
<         if p.split()[2].decode() == "securityfs" and \
<            os.path.exists(os.path.join(p.split()[1].decode(), "apparmor")):
<             return os.path.join(p.split()[1].decode(), "apparmor")
---
>     for p in open("/proc/mounts").readlines():
>         if p.split()[2] == "securityfs" and \
>            os.path.exists(os.path.join(p.split()[1], "apparmor")):
>             return os.path.join(p.split()[1], "apparmor")


**And I, Alain BENEDETTI, hereby grant Canonical all rights to use this patch as it sees fit!**


Explanation:
- Using readlines() on proc/mounts opened as regular stream is wrong! The kernel considers the mount points as bunch of binary data and does NOT assume any locale. Here, I have exhibited the bug because I'm mounting on a UTF-8 non-ASCII mount point.

- So to fix the bug, we do the same thing as the kernel:
==> we read the /proc/mounts as BINARY data, hence the first modification opening it "rb"

- Then we are searching for the string 'securityfs" on the second split.
But as p is now of binary type, we must .decode() this split()[2] that
contains the filetype. Here it is SAFE to .decode() as we know it is a
filetype, therefore we ALWAYS have ASCII here and the .decode() will
always succeed.

- When this first condition passes, we do the same on the split()[1], we apply .decode(), because join wants 2 strings, and not a binary + a string.
It is also safe here, because securityfs has been mounted on an ASCII mount point. Considering that this piece of code won't be run when the first part of the condition fails. We are in an "and" condition, and pyhton (as many languages) don't evaluate the remaining conditions when the first condition of an "and" is false.


So, it is closed for me with my own code modifications.

... expecting now the "official" patch of aa-status on the repositories,
whether you use my exact patch, or make it even better!

-- 
You received this bug notification because you are a member of Ubuntu
Touch seeded packages, which is subscribed to apparmor in Ubuntu.
https://bugs.launchpad.net/bugs/1310598

Title:
  AppArmor python tools fail to parse mounts with UTF-8 non-ascii
  characters

Status in AppArmor Linux application security framework:
  Triaged
Status in apparmor package in Ubuntu:
  Triaged

Bug description:
  Version:
  14.04 Fresh Install.

  $ uname -a
  Linux alain-Desktop 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

  
  AppArmor crashes with this stack trace:

  PythonArgs: ['/usr/sbin/aa-status']
  Traceback:
   Traceback (most recent call last):
     File "/usr/sbin/aa-status", line 194, in <module>
       commands[cmd]()
     File "/usr/sbin/aa-status", line 17, in cmd_enabled
       if get_profiles() == {}:
     File "/usr/sbin/aa-status", line 82, in get_profiles
       apparmorfs = find_apparmorfs()
     File "/usr/sbin/aa-status", line 137, in find_apparmorfs
       for p in open("/proc/mounts").readlines():
     File "/usr/lib/python3.4/encodings/ascii.py", line 26, in decode
       return codecs.ascii_decode(input, self.errors)[0]
   UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1200: ordinal not in range(128)

  
  That is because I have a UTF-8 non-Ascii character in one of my mounts:
  $ mount
  /dev/sdb1 on / type ext4 (rw,errors=remount-ro)
  proc on /proc type proc (rw,noexec,nosuid,nodev)
  sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)

  (...)
  /dev/sda6 on /home/alain/Vidéos type ext4 (rw,relatime,errors=remount-ro)
  (...)


  
  The Python code of aastatus near line 135 shows:

  def find_apparmorfs():
      '''Finds AppArmor mount point'''
      for p in open("/proc/mounts").readlines():
          if p.split()[2] == "securityfs" and \
             os.path.exists(os.path.join(p.split()[1], "apparmor")):
              return os.path.join(p.split()[1], "apparmor")
      return False


  So if I do:
  $ cat /proc/mounts
  rootfs / rootfs rw 0 0
  sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0

  (...) 
  /dev/sda6 /home/alain/Vidéos ext4 rw,relatime,errors=remount-ro,data=ordered 0 0
  (...)

  There is indeed a line with a 'é'

  UTF-8 code of the 'é' is 0xC3 0xA9

  But apparently the call to .readlines() is set as ASCII and hence does
  NOT support the 0xC3 (first byte of the 'é' in UTF-8) and then it
  crashes.

  I assume the solution could be to correctly read as UTF-8 as there are
  some non-Americans/English out there!

  Sorry my knowledge of Python is just enough to understand the bug, and
  not enough to submit a patch.

  Regards.
  Alain

To manage notifications about this bug go to:
https://bugs.launchpad.net/apparmor/+bug/1310598/+subscriptions