~ubuntu-branches/ubuntu/intrepid/apport/intrepid-security

« back to all changes in this revision

Viewing changes to apport/chroot.py

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2008-05-17 12:44:21 UTC
  • Revision ID: package-import@ubuntu.com-20080517124421-mxhqqgu38wqrcnr3
Tags: 0.110
* apport/chroot.py: In the test suite, copy some system binaries/libraries
  into a fakechroot and exercise a lot of standard shell commands (cp, ln
  -s, rm, rm -r, mkdir, echo, chmod, chown, etc.) with absolute/relative
  paths.  This reproduces the total breakage of rm'ing, chmod'ing, and
  chown'ing absolute paths in hardy fakechroots.
* bin/crash-digger: Intercept exceptions when downloading crash reports for
  duplicate checking, so that the retracer does not crash on malformed bug
  reports. (LP: #205178)
* apport/packaging.py: Introduce a new function enabled() which reports
  whether Apport should create crash reports. Signal crashes are controlled
  by /proc/sys/kernel/core_pattern, but we need that to control whether
  reports for Python, package, or kernel crashes are generated.
* backends/packaging-apt-dpkg.py: Provide implementation for
  PackageInfo.enabled() for Debian/Ubuntu by evaluating /etc/default/apport.
  Add various test cases for different configuration files and absent files.
* apport_python_hook.py: Do not create reports if Apport is disabled (in
  /etc/default/apport). (LP: #222260)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
'''Class for representing and working with chroots.'''
2
2
 
3
 
# (c) 2007 Canonical Ltd.
 
3
# (c) 2007, 2008 Canonical Ltd.
4
4
# Author: Martin Pitt <martin.pitt@ubuntu.com>
5
5
#
6
6
# This program is free software; you can redistribute it and/or modify it
164
164
#
165
165
 
166
166
if __name__ == '__main__':
167
 
    import unittest, os, tarfile
 
167
    import unittest, os, tarfile, re, shutil
168
168
 
169
169
    class ChrootTest(unittest.TestCase):
170
170
        def test_null(self):
308
308
            finally:
309
309
                shutil.rmtree(d)
310
310
 
 
311
        @classmethod
 
312
        def _install_file(klass, path, root):
 
313
            '''Install given file into a chroot, preserving the path.
 
314
            
 
315
            Do nothing if the target file already exists.'''
 
316
 
 
317
            destpath = root + os.path.abspath(path)
 
318
            if os.path.exists(destpath):
 
319
                return
 
320
            destdir = os.path.dirname(destpath)
 
321
            if not os.path.isdir(destdir):
 
322
                os.makedirs(destdir)
 
323
            shutil.copy(path, destdir)
 
324
 
 
325
        @classmethod
 
326
        def _install_exe(klass, exepath, root):
 
327
            '''Install an executable and all linked shlibs into a chroot.'''
 
328
 
 
329
            klass._install_file(exepath, root)
 
330
            ldd = subprocess.Popen(['ldd', exepath], stdout=subprocess.PIPE)
 
331
            out = ldd.communicate()[0]
 
332
            assert ldd.returncode == 0
 
333
            for m in re.finditer(' => (/[^ ]+)', out):
 
334
                klass._install_file(m.group(1), root)
 
335
            for m in re.finditer('^\s*(/[^ ]+)', out, re.M):
 
336
                klass._install_file(m.group(1), root)
 
337
 
 
338
        def test_shell_ops(self):
 
339
            '''Test various shell operations in the chroot.'''
 
340
 
 
341
            d = tempfile.mkdtemp()
 
342
            ldir = os.path.join(d, 'lib')
 
343
            os.mkdir(ldir)
 
344
            assert subprocess.call('cp -a /lib/*.so ' + ldir, shell=True) == 0
 
345
            try:
 
346
                for cmd in ('bash', 'echo', 'cat', 'cp', 'ln', 'ls', 'rm',
 
347
                    'mkdir', 'rmdir', 'chmod', 'chown'):
 
348
                    self._install_exe('/bin/' + cmd, d)
 
349
                self._install_exe('/usr/bin/stat', d)
 
350
 
 
351
                c = Chroot(d)
 
352
 
 
353
                self.assertEqual(c.run_capture(['echo', 'hello']),
 
354
                    ('hello\n', '', 0))
 
355
                self.assertEqual(c.run_capture(['cat'], 'hello'),
 
356
                    ('hello', '', 0))
 
357
                self.assertEqual(c.run_capture(['/bin/bash'], 'type echo'),
 
358
                    ('echo is a shell builtin\n', '', 0))
 
359
                self.assertEqual(c.run_capture(['/bin/bash'], 'set -e; false'),
 
360
                    ('', '', 1))
 
361
 
 
362
                # check ls
 
363
                (out, err, result) = c.run_capture(['ls'])
 
364
                self.assertEqual(err, '')
 
365
                self.assertEqual(result, 0)
 
366
                files = out.splitlines()
 
367
                self.assert_('bin' in files)
 
368
                self.assert_('lib' in files)
 
369
 
 
370
                # complex shell commands: relative symlinks and paths
 
371
                self.assertEqual(c.run_capture(['bash'], '''set -e
 
372
cd /
 
373
mkdir test
 
374
echo world > test/file
 
375
ln -s file test/link
 
376
cat test/file
 
377
cat test/link
 
378
stat -c '%f %s %n' test/file
 
379
stat -c '%f %n' test/link
 
380
stat -L -c '%f %s %n' test/link
 
381
chmod 600 test/file
 
382
chown 0:0 test/file
 
383
stat -c '%f %s %n' test/file
 
384
rm test/link
 
385
rm test/file
 
386
rmdir test
 
387
mkdir test
 
388
echo world > test/file
 
389
rm -r test
 
390
! test -e test
 
391
'''), ('world\nworld\n81a4 6 test/file\na1ff test/link\n81a4 6 test/link\n8180 6 test/file\n', '', 0))
 
392
 
 
393
                # complex shell commands: relative symlink to executable
 
394
                self.assertEqual(c.run_capture(['bash'], '''set -e
 
395
cd /
 
396
ln -s echo bin/eco
 
397
stat -c '%f %n' bin/eco
 
398
stat -L -c '%f %n' bin/eco
 
399
eco -n hello
 
400
rm bin/eco
 
401
'''), ('a1ff bin/eco\n81ed bin/eco\nhello', '', 0))
 
402
 
 
403
                # complex shell commands: absolute symlinks and paths
 
404
                self.assertEqual(c.run_capture(['bash'], '''set -e
 
405
mkdir /test
 
406
echo world > /test/file
 
407
ln -s /test/file /test/link
 
408
cat /test/file
 
409
cat /test/link
 
410
stat -c '%f %s %n' /test/file
 
411
stat -c '%f %n' /test/link
 
412
stat -L -c '%f %s %n' /test/link
 
413
chmod 600 /test/file
 
414
chown 0:0 /test/file
 
415
stat -c '%f %s %n' /test/file
 
416
rm /test/link
 
417
rm /test/file
 
418
rmdir /test
 
419
mkdir /test
 
420
echo world > /test/file
 
421
rm -r /test
 
422
! test -e test
 
423
'''), ('world\nworld\n81a4 6 /test/file\na1ff /test/link\n81a4 6 /test/link\n8180 6 /test/file\n', '', 0))
 
424
 
 
425
                # complex shell commands: absolute symlink to executable
 
426
                self.assertEqual(c.run_capture(['bash'], '''set -e
 
427
ln -s /bin/echo /bin/eco
 
428
/bin/eco -n hello
 
429
rm /bin/eco
 
430
'''), ('hello', '', 0))
 
431
 
 
432
                # complex shell commands: cp/cat/rm of relative paths
 
433
                self.assertEqual(c.run_capture(['bash'], '''set -e
 
434
cd /
 
435
mkdir etc
 
436
echo "/bin/bash" > etc/shells
 
437
cp etc/shells etc/shells.tmp
 
438
cat etc/shells.tmp
 
439
rm etc/shells.tmp
 
440
rm etc/shells
 
441
rmdir etc
 
442
'''), ('/bin/bash\n', '', 0))
 
443
 
 
444
                # complex shell commands: cp/cat/rm of absolute paths
 
445
                self.assertEqual(c.run_capture(['bash'], '''set -e
 
446
mkdir /etc
 
447
echo "/bin/bash" > /etc/shells
 
448
cp /etc/shells /etc/shells.tmp
 
449
cat /etc/shells.tmp
 
450
rm /etc/shells.tmp
 
451
rm /etc/shells
 
452
rmdir /etc
 
453
'''), ('/bin/bash\n', '', 0))
 
454
 
 
455
            finally:
 
456
                shutil.rmtree(d)
 
457
 
311
458
    unittest.main()