Esempio n. 1
0
    def setUp(self) -> None:
        self.kernels = [
            Kernel('1.old'),
            Kernel('2.new'),
            Kernel('3.stray'),
            Kernel('4.stray-files'),
        ]

        self.td = tempfile.TemporaryDirectory()
        td = Path(self.td.name)
        write_bzImage(td / 'kernel.old', b'old built on test')
        write_bzImage(td / 'kernel.new', b'new built on test')
        with open(td / 'config-stray', 'w'):
            pass
        with open(td / 'initrd-stray.img', 'w'):
            pass
        os.mkdir(td / 'build')

        build = GenericFile(td / 'build', KernelFileType.BUILD)
        self.kernels[0].all_files = [
            KernelImage(td / 'kernel.old'),
            build,
        ]
        self.kernels[1].all_files = [
            KernelImage(td / 'kernel.new'),
            build,
        ]
        self.kernels[2].all_files = [
            build,
        ]
        self.kernels[3].all_files = [
            GenericFile(td / 'config-stray', KernelFileType.CONFIG),
            GenericFile(td / 'initrd-stray.img', KernelFileType.INITRAMFS),
        ]
Esempio n. 2
0
    def test_exclude_build(self) -> None:
        with self.create_layout() as td:
            path = Path(td)
            boot = path / 'boot'
            modules = path / 'lib/modules'

            self.assertEqual(
                sorted(
                    kernel_paths(
                        StdLayout(root=path).find_kernels(
                            exclusions=[KFT.BUILD]))),
                [('1.2.2', [
                    GenericFile(boot / 'System.map-1.2.2', KFT.SYSTEM_MAP),
                    KernelImage(boot / 'vmlinuz-1.2.2'),
                    ModuleDirectory(modules / '1.2.2'),
                ], '1.2.2'),
                 ('1.2.3', [
                     GenericFile(boot / 'System.map-1.2.3', KFT.SYSTEM_MAP),
                     GenericFile(boot / 'config-1.2.3', KFT.CONFIG),
                     GenericFile(boot / 'initrd-1.2.3.img', KFT.INITRAMFS),
                     KernelImage(boot / 'vmlinuz-1.2.3'),
                     ModuleDirectory(modules / '1.2.3'),
                 ], '1.2.3'),
                 ('1.2.3.old', [
                     GenericFile(boot / 'System.map-1.2.3.old',
                                 KFT.SYSTEM_MAP),
                     GenericFile(boot / 'config-1.2.3.old', KFT.CONFIG),
                     GenericFile(boot / 'initrd-1.2.3.img.old', KFT.INITRAMFS),
                     KernelImage(boot / 'vmlinuz-1.2.3.old'),
                     ModuleDirectory(modules / '1.2.3'),
                 ], '1.2.3'),
                 ('1.2.4', [
                     GenericFile(boot / 'config-1.2.4', KFT.CONFIG),
                     ModuleDirectory(modules / '1.2.4'),
                 ], None)])
Esempio n. 3
0
 def test_missing_decompressor(self) -> None:
     if util.find_spec('lzo'):
         self.skipTest('the missing decompressor is installed')
     path = Path(self.td.name) / 'vmlinuz'
     with open(path, 'wb') as f:
         f.write(b'\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a')
         f.write(0x210 * b'\0')
     with self.assertRaises(MissingDecompressorError):
         KernelImage(path).read_internal_version()
Esempio n. 4
0
 def test_short(self) -> None:
     path = Path(self.td.name) / 'vmlinuz'
     with open(path, 'wb') as f:
         f.write(0x202 * b'\0')
         f.write(b'HdrS')
         f.write(8 * b'\0')
         f.write(b'\x10\x00')
     with self.assertRaises(UnrecognizedKernelError):
         KernelImage(path).read_internal_version()
Esempio n. 5
0
 def test_missing_decompressor(self, import_module: MagicMock) -> None:
     path = Path(self.td.name) / 'vmlinuz'
     with open(path, 'wb') as f:
         f.write(b'\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a')
         f.write(0x210 * b'\0')
     import_module.side_effect = ModuleNotFoundError(
         "No module named 'lzo'")
     with self.assertRaises(MissingDecompressorError):
         KernelImage(path).read_internal_version()
Esempio n. 6
0
    def test_exclude_misc(self) -> None:
        with self.create_layout() as td:
            path = Path(td)
            boot = path / f'boot/{self.machine_id}'
            modules = path / 'lib/modules'

            self.assertEqual(
                sorted(
                    kernel_paths(
                        BlSpecLayout(root=path).find_kernels(
                            exclusions=[KFT.MISC]))),
                [
                    ('1.2.1', [
                        EmptyDirectory(boot / '1.2.1'),
                        GenericFile(boot / '1.2.1/initrd', KFT.INITRAMFS),
                        KernelImage(boot / '1.2.1/linux'),
                        ModuleDirectory(modules / '1.2.1'),
                    ], '1.2.1'),
                    ('1.2.2', [
                        EmptyDirectory(boot / '1.2.2'),
                        GenericFile(boot / '1.2.2/initrd', KFT.INITRAMFS),
                        KernelImage(boot / '1.2.2/linux'),
                        ModuleDirectory(modules / '1.2.2'),
                        GenericFile(modules / '1.2.2/../../../usr/src/linux',
                                    KFT.BUILD),
                    ], '1.2.2'),
                    ('1.2.3', [
                        EmptyDirectory(boot / '1.2.3'),
                        GenericFile(boot / '1.2.3/initrd', KFT.INITRAMFS),
                        KernelImage(boot / '1.2.3/linux'),
                        ModuleDirectory(modules / '1.2.3'),
                        GenericFile(modules / '1.2.3/../../../usr/src/linux',
                                    KFT.BUILD),
                    ], '1.2.3'),
                    ('1.2.4', [
                        EmptyDirectory(boot / '1.2.4'),
                        GenericFile(boot / '1.2.4/initrd', KFT.INITRAMFS),
                        ModuleDirectory(modules / '1.2.4'),
                    ], None),
                ])
Esempio n. 7
0
    def find_kernels(
        self,
        exclusions: typing.Container[KernelFileType] = [],
    ) -> typing.List[Kernel]:
        # this would wreak havok all around the place
        assert KernelFileType.KERNEL not in exclusions

        # collect all module directories first
        module_dict = self.get_module_dict(exclusions=exclusions,
                                           module_directory=self.root /
                                           'lib/modules')

        # collect from /boot
        kernels: typing.Dict[str, Kernel] = {}
        for ver in os.listdir(self.bootdir):
            if ver.startswith('.'):
                continue
            dir_path = self.bootdir / ver
            if dir_path.is_symlink() or not dir_path.is_dir():
                continue

            k = Kernel(ver)
            for fn in os.listdir(dir_path):
                if fn.startswith('.'):
                    continue
                path = dir_path / fn
                ftype = self.name_map.get(fn, KernelFileType.MISC)
                fobj = GenericFile(path, ftype)
                if ftype == KernelFileType.KERNEL:
                    try:
                        kobj = KernelImage(path)
                    except UnrecognizedKernelError:
                        pass
                    else:
                        # associate the module directory
                        k.all_files.extend(
                            module_dict.get(kobj.internal_version, []))
                        fobj = kobj
                if ftype not in exclusions:
                    k.all_files.append(fobj)
            k.all_files.append(EmptyDirectory(dir_path))
            kernels[ver] = k

        # merge unassociated modules into kernel groups
        for mkv, fobjs in module_dict.items():
            if any(mkv == k.real_kv for k in kernels.values()):
                continue
            kernels.setdefault(mkv, Kernel(mkv)).all_files.extend(fobjs)

        return list(kernels.values())
Esempio n. 8
0
 def test_bad_file_magic(self) -> None:
     path = Path(self.td.name) / 'vmlinuz'
     with open(path, 'w') as f:
         f.write('Hello World')
     with self.assertRaises(UnrecognizedKernelError):
         KernelImage(path).read_internal_version()
Esempio n. 9
0
 def test_read_internal_version_compress(self) -> None:
     path = Path(self.td.name) / 'vmlinuz'
     write_compress(path, b'Linux version 1.2.3 built on test')
     self.assertEqual(KernelImage(path).read_internal_version(), '1.2.3')
Esempio n. 10
0
 def test_overflow_ver_string_raw(self) -> None:
     path = Path(self.td.name) / 'vmlinuz'
     write_raw(path, b'Linux version 1.2.3' + 0xffff * b'\0')
     with self.assertRaises(UnrecognizedKernelError):
         KernelImage(path).read_internal_version()
Esempio n. 11
0
    def find_kernels(
        self,
        exclusions: typing.Container[KernelFileType] = [],
    ) -> typing.List[Kernel]:
        # this would wreak havok all around the place
        assert KernelFileType.KERNEL not in exclusions

        # collect all module directories first
        module_dict = self.get_module_dict(exclusions=exclusions,
                                           module_directory=self.root /
                                           'lib/modules')

        # collect from /boot
        kernels: typing.Dict[str, typing.Dict[str, Kernel]] = {}
        other_files: typing.List[typing.Tuple[GenericFile, str]] = []
        boot_directory = self.root / 'boot'
        try:
            diter = os.listdir(boot_directory)
        except FileNotFoundError:
            pass
        else:
            for fn in diter:
                # skip hidden and GRUB signature files
                if fn.startswith('.') or fn.endswith('.sig'):
                    continue
                path = boot_directory / fn
                if path.is_symlink() or not path.is_file():
                    continue
                # skip unversioned files
                ver = fn.partition('-')[2]
                if not ver:
                    continue

                # strip suffix from filename to get the correct version
                for suffix in self.suffixes:
                    if ver.endswith(suffix):
                        ver = ver[:-len(suffix)]
                        break
                    elif ver.endswith(suffix + '.old'):
                        ver = ver[:-len(suffix) - 4] + '.old'

                # try recognizing kernel image via magic
                try:
                    kobj = KernelImage(path)
                except UnrecognizedKernelError:
                    # fall back to filename
                    for ftype, prefix in self.prefixes:
                        if ftype not in exclusions:
                            if fn.startswith(prefix):
                                other_files.append((GenericFile(path,
                                                                ftype), ver))
                                break
                    continue

                # the following is done only for kernel images
                assert isinstance(kobj, KernelImage)
                kg = kernels.setdefault(ver, {})
                k = kg.setdefault(kobj.internal_version, Kernel(ver))
                k.all_files.append(kobj)

                # associate the module directory
                k.all_files.extend(module_dict.get(kobj.internal_version, []))

        # merge other files into kernel groups
        for fobj, ver in other_files:
            kg = kernels.setdefault(ver, {})
            # if we had some images with matching apparent version,
            # append to all of their Kernels; if we had none, create
            # a single Kernel object
            if not kg:
                kg[''] = Kernel(ver)
            for k in kg.values():
                k.all_files.append(fobj)

        # merge unassociated modules into kernel groups
        for mkv, fobjs in module_dict.items():
            if any(mkv == kv for kg in kernels.values() for kv in kg):
                continue
            (kernels.setdefault(mkv, {}).setdefault(
                '', Kernel(mkv)).all_files.extend(fobjs))

        return list(
            itertools.chain.from_iterable(kg.values()
                                          for kg in kernels.values()))