'module' object has no attribute 'O_PATH'

Bug #1851806 reported by Karl-Philipp Richter
16
This bug affects 3 people
Affects Status Importance Assigned to Milestone
Apport
Fix Released
High
Unassigned
apport (Ubuntu)
Fix Released
High
Tiago Stürmer Daitx

Bug Description

I encountered the following exception in python-apport while encountering an exception `bup` which uses `python-apport`. I'm sure that the exception lies in the responsibility of `python-apport` (the `AttributeError` stacktrace is relevant):

```
Traceback (most recent call last):
  File "/usr/lib/bup/cmd/bup-index", line 269, in <module>
    update_index(rp, excluded_paths, exclude_rxs, xdev_exceptions=xexcept)
  File "/usr/lib/bup/cmd/bup-index", line 191, in update_index
    mi.close()
  File "/usr/lib/bup/bup/index.py", line 528, in close
    os.rename(self.tmpname, self.filename)
OSError: [Errno 13] Permission denied
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/bup/bup/helpers.py", line 916, in newhook
    return oldhook(exctype, value, traceback)
  File "/usr/lib/python2.7/dist-packages/apport_python_hook.py", line 109, in apport_excepthook
    pr.add_proc_info(extraenv=['PYTHONPATH', 'PYTHONHOME'])
  File "/usr/lib/python2.7/dist-packages/apport/report.py", line 544, in add_proc_info
    proc_pid_fd = os.open('/proc/%s' % pid, os.O_RDONLY | os.O_PATH | os.O_DIRECTORY)
AttributeError: 'module' object has no attribute 'O_PATH'

Original exception was:
Traceback (most recent call last):
  File "/usr/lib/bup/cmd/bup-index", line 269, in <module>
    update_index(rp, excluded_paths, exclude_rxs, xdev_exceptions=xexcept)
  File "/usr/lib/bup/cmd/bup-index", line 191, in update_index
    mi.close()
  File "/usr/lib/bup/bup/index.py", line 528, in close
    os.rename(self.tmpname, self.filename)
OSError: [Errno 13] Permission denied
```

ProblemType: Bug
DistroRelease: Ubuntu 19.10
Package: python-apport 2.20.11-0ubuntu8.2
ProcVersionSignature: Ubuntu 5.3.0-19.20-generic 5.3.1
Uname: Linux 5.3.0-19-generic x86_64
NonfreeKernelModules: zfs zunicode zavl icp zcommon znvpair
ApportLog: Error: [Errno 13] Keine Berechtigung: '/var/log/apport.log'
ApportVersion: 2.20.11-0ubuntu8.2
Architecture: amd64
CurrentDesktop: ubuntu:GNOME
Date: Fri Nov 8 10:43:02 2019
PackageArchitecture: all
SourcePackage: apport
UpgradeStatus: Upgraded to eoan on 2019-10-25 (13 days ago)

Revision history for this message
Karl-Philipp Richter (krichter722) wrote :
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thank you for your bug report. Could you give some steps to trigger the issue?

Changed in apport (Ubuntu):
status: New → Incomplete
Revision history for this message
Benjamin Curtiss (bencurtiss6458) wrote :

I'm not exactly sure how to reproduce this bug, but I did encounter the same issue. It looks like the bug was recently introduced in this commit: https://git.launchpad.net/ubuntu/+source/apport/commit/?h=applied/ubuntu/xenial-security&id=ecd7418b02911c6649b69a592cca74cfbac8813d

```
@@ -510,22 +510,24 @@ class Report(problem_report.ProblemReport):
         - _LogindSession: logind cgroup path, if present (Used for filtering
           out crashes that happened in a session that is not running any more)
         '''
- if not pid:
- pid = self.pid or os.getpid()
- if not self.pid:
- self.pid = int(pid)
- pid = str(pid)
+ if not proc_pid_fd:
+ if not pid:
+ pid = self.pid or os.getpid()
+ if not self.pid:
+ self.pid = int(pid)
+ pid = str(pid)
+ proc_pid_fd = os.open('/proc/%s' % pid, os.O_RDONLY | os.O_PATH | os.O_DIRECTORY)

         try:
- self['ProcCwd'] = os.readlink('/proc/' + pid + '/cwd')
+ self['ProcCwd'] = os.readlink('cwd', dir_fd=proc_pid_fd)
         except OSError:
             pass
         self.add_proc_environ(pid, extraenv)
- self['ProcStatus'] = _read_file('/proc/' + pid + '/status')
- self['ProcCmdline'] = _read_file('/proc/' + pid + '/cmdline').rstrip('\0')
- self['ProcMaps'] = _read_maps(int(pid))
+ self['ProcStatus'] = _read_file('status', dir_fd=proc_pid_fd)
+ self['ProcCmdline'] = _read_file('cmdline', dir_fd=proc_pid_fd).rstrip('\0')
+ self['ProcMaps'] = _read_maps(proc_pid_fd)
         try:
- self['ExecutablePath'] = os.readlink('/proc/' + pid + '/exe')
+ self['ExecutablePath'] = os.readlink('exe', dir_fd=proc_pid_fd)
         except OSError as e:
             if e.errno == errno.ENOENT:
                 raise ValueError('invalid process')
```

The problem is that os.O_PATH does not exist in python2, and only exists in python3. However, python-apport is a python2 package.

```
bcurtiss@bcurtiss-laptop:~$ python3 -c 'import os; print(os.O_PATH)'
2097152
bcurtiss@bcurtiss-laptop:~$ python -c 'import os; print(os.O_PATH)'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: 'module' object has no attribute 'O_PATH'
bcurtiss@bcurtiss-laptop:~$
```

Revision history for this message
Benjamin Curtiss (bencurtiss6458) wrote :

Here's a reproduction of the error:

bcurtiss@bcurtiss-laptop:~$ ipython
Python 2.7.12 (default, Oct 8 2019, 14:14:10)
Type "copyright", "credits" or "license" for more information.

IPython 2.4.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.

In [1]: import apport_python_hook; apport_python_hook.apport_excepthook(Exception, Exception(), None)
Exception
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-1-e8f288b62cb1> in <module>()
----> 1 import apport_python_hook; apport_python_hook.apport_excepthook(Exception, Exception(), None)

/usr/lib/python2.7/dist-packages/apport_python_hook.pyc in apport_excepthook(exc_type, exc_obj, exc_tb)
    107 traceback.print_exception(exc_type, exc_obj, exc_tb, file=tb_file)
    108 pr['Traceback'] = tb_file.getvalue().strip()
--> 109 pr.add_proc_info(extraenv=['PYTHONPATH', 'PYTHONHOME'])
    110 pr.add_user_info()
    111 # override the ExecutablePath with the script that was actually running

/usr/lib/python2.7/dist-packages/apport/report.pyc in add_proc_info(self, pid, proc_pid_fd, extraenv)
    517 self.pid = int(pid)
    518 pid = str(pid)
--> 519 proc_pid_fd = os.open('/proc/%s' % pid, os.O_RDONLY | os.O_PATH | os.O_DIRECTORY)
    520
    521 try:

AttributeError: 'module' object has no attribute 'O_PATH'

In [2]: exit
bcurtiss@bcurtiss-laptop:~$ ipython3
Python 3.5.2 (default, Oct 8 2019, 13:06:37)
Type "copyright", "credits" or "license" for more information.

IPython 2.4.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.

In [1]: import apport_python_hook; apport_python_hook.apport_excepthook(Exception, Exception(), None)
Exception

In [2]: exit
bcurtiss@bcurtiss-laptop:~$

tags: added: regression-update
Changed in apport (Ubuntu):
status: Incomplete → New
Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in apport (Ubuntu):
status: New → Confirmed
Revision history for this message
Albert Pool (albertpool) wrote :

Simply removing O_PATH from the line in question leads to:

Traceback (most recent call last):
  File "/usr/share/apport/apport-gtk", line 597, in <module>
    app.run_argv()
  File "/usr/lib/python2.7/dist-packages/apport/ui.py", line 661, in run_argv
    return self.run_update_report()
  File "/usr/lib/python2.7/dist-packages/apport/ui.py", line 559, in run_update_report
    self.report.add_proc_environ()
  File "/usr/lib/python2.7/dist-packages/apport/report.py", line 592, in add_proc_environ
    env = _read_file('environ', dir_fd=proc_pid_fd).replace('\n', '\\n')
  File "/usr/lib/python2.7/dist-packages/apport/report.py", line 73, in _read_file
    with open(path, 'rb', opener=lambda path, mode: os.open(path, mode, dir_fd=dir_fd)) as fd:
TypeError: 'opener' is an invalid keyword argument for this function

(Linux Mint 18.2, python-apport 2.20.1-0ubuntu2.21)

Revision history for this message
Albert Pool (albertpool) wrote :

The above looks like some Python 3 code ended up in a Python 2.7 document, given opener= was added in Python 3.3 it seems.

tags: added: id-5dd454a1dd84728273703743
Changed in apport (Ubuntu):
assignee: nobody → Tiago Stürmer Daitx (tdaitx)
importance: Undecided → High
status: Confirmed → In Progress
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package apport - 2.20.11-0ubuntu16

---------------
apport (2.20.11-0ubuntu16) focal; urgency=medium

  * SECURITY REGRESSION: 'module' object has no attribute 'O_PATH'
    (LP: #1851806)
    - apport/report.py, apport/ui.py: use file descriptors for /proc/pid
      directory access only when running under python 3; prevent reading /proc
      maps under python 2 as it does not provide a secure way to do so; use
      io.open for better compatibility between python 2 and 3.
  * data/apport: fix number of arguments passed through socks into a container.
  * test/test_report.py: test login session with both pid and proc_pid_fd.

 -- Tiago Stürmer Daitx <email address hidden> Mon, 06 Jan 2020 13:28:40 +0000

Changed in apport (Ubuntu):
status: In Progress → Fix Released
tags: added: id-5e540609ebb75b15e089ff0e
Benjamin Drung (bdrung)
Changed in apport:
status: New → Fix Released
milestone: none → 2.21.0
importance: Undecided → High
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.