aboutsummaryrefslogtreecommitdiff
blob: c322b0a0a44aa54166961f208e72b7cd6e26fd18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from git import Repo
import os
import urllib.request as request
import shutil


class CVE(object):
    """
    Check the kernel against a CVE repository
    """
    def __init__(self):
        self.git_url = "https://github.com/nluedtke/linux_kernel_cves"
        self.repo_dir = "/tmp/kernel_cve/"
        self.cve_patches_dir = "/tmp/patches_cve/"
        pass

    def download(self):
        Repo.clone_from(self.git_url, self.repo_dir)

    def set_repo(self, git_url, repo_dir):
        self.git_url = git_url
        self.repo_dir = repo_dir

    def cve_git_id(self):
        major_version, minor_version, revision_version = _current_kernel_version()
        major_version, minor_version, revision_version = 4,9,25
        security_file = open("/tmp/kernel_cve/"+str(major_version)+"."+str(minor_version)+
                             "/"+str(major_version)+"."+str(minor_version)+"_security.txt", "r")
        security_versions = []
        for line in security_file:
            if "CVEs fixed in" in line:
                security_versions_tmp = line.strip().split(' ')[3][:-1]
                # if there is not revision, set revision as 0
                if len(security_versions_tmp) == 3:
                    security_versions.append(0)
                else:
                    security_versions.append(security_versions_tmp.split('.')[2])
        security_file.close()

        print('[debug] security versions: ' + str(security_versions))

        cve_2d_list = []
        for version in security_versions:
            if int(version) > revision_version:
                cve_2d_list.append(self.cve_id(major_version, minor_version, version))

        patch_index = 0
        if not os.path.exists(self.cve_patches_dir):
            os.mkdir(self.cve_patches_dir)
        for cve_list in cve_2d_list:
            print(cve_list)
            print([ii for n,ii in enumerate(cve_list) if ii not in cve_list[:n]])
            for cve_id in cve_list:
                self.download_cve_patch(cve_id, str(patch_index))
                patch_index +=1

    def download_cve_patch(self, cve_id, patch_index):
        file_name= self.cve_patches_dir + patch_index + '.patch'

        # Download the file from `url` and save it locally under `file_name`:
        with request.urlopen('https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/patch/?id=' + cve_id) as response, \
                open(file_name, 'wb') as out_file:
            shutil.copyfileobj(response, out_file)

    def cve_id(self, major_version, minor_version, revision_version):
        security_file = open("/tmp/kernel_cve/"+str(major_version)+"."+str(minor_version)+
                             "/"+str(major_version)+"."+str(minor_version)+"_security.txt", "r")

        git_security_id = []
        # return cve for a kernel version
        for excluded_line in security_file:
            if ("CVEs fixed in "+str(major_version)+
                    "."+str(minor_version)+
                    "."+str(revision_version)+
                    ":") in excluded_line:
                for included_line in security_file:
                    if not "\n" is included_line:
                        git_security_id.append(included_line.strip().split(' ')[1])
                    else:
                        # debug
                        # print('got cve for '+str(major_version)+
                        #       "."+str(minor_version)+
                        #       "."+str(revision_version))
                        break
        security_file.close()
        return git_security_id


def _current_kernel_version():
    kernel_version = os.uname()[2]
    major_version = int(kernel_version.split('.')[0])
    minor_version = int(kernel_version.split('.')[1])
    revision_version = int((kernel_version.split('.')[2]).split('-')[0])
    return major_version, minor_version, revision_version