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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# (c) 2017, Alice Ferrazzi <alice.ferrazzi@gmail.com>
# Distributed under the terms of the GNU General Public License v2 or later
import subprocess
import os
import fileinput
import tempfile
class PaTch(object):
def __init__(self):
pass
def build_livepatch(self, uuid, vmlinux, debug=True):
"""
Function for building the livepatch
:param uuid: UUID session identification
:param vmlinux: path to the vmlinux file
:param debug: copy build.log in the uuid directory
:return: void
"""
kernel_source = os.path.join('/tmp/', 'elivepatch-' + uuid, 'usr/src/linux/')
uuid_dir = os.path.join('/tmp/', 'elivepatch-' + uuid)
vmlinux_source = os.path.join(kernel_source, vmlinux)
kpatch_cachedir = os.path.join(uuid_dir, 'kpatch')
os.makedirs(kpatch_cachedir)
if not os.path.isfile(vmlinux_source):
self.build_kernel(uuid)
bashCommand = ['kpatch-build']
bashCommand.extend(['-s', kernel_source])
bashCommand.extend(['-v', vmlinux_source])
bashCommand.extend(['-c', 'config'])
bashCommand.extend(['main.patch'])
bashCommand.extend(['--skip-gcc-check'])
if debug:
bashCommand.extend(['--skip-cleanup'])
bashCommand.extend(['--debug'])
_command(bashCommand, uuid_dir, {'CACHEDIR': kpatch_cachedir})
if debug:
_command(['cp', '-f', os.path.join(kpatch_cachedir, 'build.log'), uuid_dir])
def get_kernel_sources(self, uuid, kernel_version, debug=True):
"""
Function for download the kernel sources
:return: void
"""
try:
_command(['git', 'clone', 'https://github.com/aliceinwire/gentoo-sources_overlay.git'])
except:
print('git clone failed.')
uuid_dir = os.path.join('/tmp/', 'elivepatch-' + uuid)
ebuild_path = os.path.join('gentoo-sources_overlay', 'sys-kernel', 'gentoo-sources', 'gentoo-sources-' +
kernel_version + '.ebuild')
print(ebuild_path)
if os.path.isfile(ebuild_path):
# Use a private tmpdir for portage
with tempfile.TemporaryDirectory(dir=uuid_dir) as portage_tmpdir:
print('uuid_dir: ' + str(uuid_dir) + ' PORTAGE_TMPDIR: ' + str(portage_tmpdir))
# portage_tmpdir is not always working with root privileges
if debug:
if os.geteuid() != 0:
env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': portage_tmpdir,
'PORTAGE_DEBUG': '1'}
else:
env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': uuid_dir,
'PORTAGE_DEBUG': '1'}
else:
if os.geteuid() != 0:
env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': portage_tmpdir}
else:
env = {'ROOT': uuid_dir, 'PORTAGE_CONFIGROOT': uuid_dir, 'PORTAGE_TMPDIR': uuid_dir}
_command(['ebuild', ebuild_path, 'clean', 'digest', 'merge'], env=env)
kernel_sources_status = True
else:
print('ebuild not present')
kernel_sources_status = None
return kernel_sources_status
def build_kernel(self, uuid):
kernel_source_dir = '/tmp/elivepatch-' + uuid + '/usr/src/linux/'
uuid_dir_config = '/tmp/elivepatch-' + uuid + '/config'
if 'CONFIG_DEBUG_INFO=y' in open(uuid_dir_config).read():
print("DEBUG_INFO correctly present")
elif 'CONFIG_DEBUG_INFO=n' in open(uuid_dir_config).read():
print("changing DEBUG_INFO to yes")
for line in fileinput.input(uuid_dir_config, inplace=1):
print(line.replace("CONFIG_DEBUG_INFO=n", "CONFIG_DEBUG_INFO=y"))
else:
print("Adding DEBUG_INFO for getting kernel debug symbols")
for line in fileinput.input(uuid_dir_config, inplace=1):
print(line.replace("# CONFIG_DEBUG_INFO is not set", "CONFIG_DEBUG_INFO=y"))
_command(['cp', '/tmp/elivepatch-' + uuid + '/config', kernel_source_dir + '.config'])
# olddefconfig default everything that is new from the configuration file
_command(['make', 'olddefconfig'], kernel_source_dir)
_command(['make'], kernel_source_dir)
_command(['make', 'modules'], kernel_source_dir)
def _command(bashCommand, kernel_source_dir=None, env=None):
"""
Popen override function
:param bashCommand: List of command arguments to execute
:param kernel_source_dir: String with the directory where the command is executed
:param env: Dictionary for setting system environment variable
:return: void
"""
# Inherit the parent environment and update the private copy
if env:
process_env = os.environ.copy()
process_env.update(env)
env = process_env
if kernel_source_dir:
print(bashCommand)
process = subprocess.Popen(bashCommand, stdout=subprocess.PIPE, cwd=kernel_source_dir, env=env)
output, error = process.communicate()
for output_line in output.split(b'\n'):
print(output_line.strip())
else:
print(bashCommand)
process = subprocess.Popen(bashCommand, stdout=subprocess.PIPE, env=env)
output, error = process.communicate()
for output_line in output.split(b'\n'):
print(output_line.strip())
|