Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] sign kernel modules #78

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile.centos-gcc4.8
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ RUN yum -y install \
flex \
make \
cmake \
openssl \
elfutils-devel \
python-lxml && yum clean all

Expand Down
11 changes: 11 additions & 0 deletions builder-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# PROBE_DEVICE_NAME
# PROBE_NAME
# PROBE_VERSION
# SIGN_FILE_HASH_ALGO

# optional env vars
# CLANG
Expand Down Expand Up @@ -56,6 +57,16 @@ build_kmod() {
exit 1
fi

if [ -n "${SIGN_FILE_HASH_ALGO}" ]; then
echo "Signing generated kernel module"
${KERNELDIR}/scripts/sign-file ${SIGN_FILE_HASH_ALGO} \
/code/sysdig-ro/signing-key/key.priv \
/code/sysdig-ro/signing-key/key.der \
driver/${PROBE_NAME}.ko
else
echo "Kernel module will NOT be signed"
fi

cp driver/$PROBE_NAME.ko $OUTPUT/$PROBE_NAME-$PROBE_VERSION-$ARCH-$KERNEL_RELEASE-$HASH.ko
cp driver/$PROBE_NAME.ko $OUTPUT/$PROBE_NAME-$PROBE_VERSION-$ARCH-$KERNEL_RELEASE-$HASH_ORIG.ko
}
Expand Down
5 changes: 3 additions & 2 deletions probe_builder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,11 @@ def cli(debug):
@click.option('-s', '--source-dir')
@click.option('-t', '--download-timeout', type=click.FLOAT)
@click.option('-v', '--probe-version')
@click.option('-x', '--sign', is_flag=True)
@click.argument('package', nargs=-1)
def build(builder_image_prefix,
download_concurrency, jobs, kernel_type, filter, probe_name, retries,
source_dir, download_timeout, probe_version, package):
source_dir, download_timeout, probe_version, sign, package):
workspace_dir = os.getcwd()
builder_source = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Expand All @@ -135,7 +136,7 @@ def build(builder_image_prefix,
with ThreadPoolExecutor(max_workers=jobs) as executor:
kernels_futures = []
for release, target in kernel_dirs:
future = executor.submit(distro_builder.build_kernel, workspace, probe, distro.builder_distro, release, target)
future = executor.submit(distro_builder.build_kernel, workspace, probe, distro.builder_distro, release, target, sign)
kernels_futures.append((release, future))


Expand Down
5 changes: 3 additions & 2 deletions probe_builder/builder/builder_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def build(workspace, dockerfile, dockerfile_tag):
return obj

def run(workspace, probe, kernel_dir, kernel_release,
config_hash, container_name, image_name, args):
config_hash, container_name, image_name, sign_file_hash_algo, args):
volumes = [
docker.DockerVolume(workspace.host_dir(probe.sysdig_dir), '/code/sysdig-ro', True),
docker.DockerVolume(workspace.host_workspace(), '/build/probe', True),
Expand All @@ -53,7 +53,8 @@ def run(workspace, probe, kernel_dir, kernel_release,
docker.EnvVar('KERNELDIR', kernel_dir.replace(workspace.workspace, '/build/probe/')),
docker.EnvVar('KERNEL_RELEASE', kernel_release),
docker.EnvVar('HASH', config_hash),
docker.EnvVar('HASH_ORIG', config_hash)
docker.EnvVar('HASH_ORIG', config_hash),
docker.EnvVar('SIGN_FILE_HASH_ALGO', sign_file_hash_algo),
]

return docker.run(image_name, volumes, args, env, name=container_name)
Expand Down
23 changes: 18 additions & 5 deletions probe_builder/builder/distro/base_builder.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import configparser
import errno
import logging
import os
Expand Down Expand Up @@ -61,17 +62,28 @@ def md5sum(path):
digest.update(fp.read().encode('utf-8'))
return digest.hexdigest()

@staticmethod
def config_module_sig_hash(path):
with open(path, 'r') as f:
config_string = '[DEFAULT]\n' + f.read()
config = configparser.ConfigParser()
config.read_string(config_string)
return config['DEFAULT']['CONFIG_MODULE_SIG_HASH'].replace('"','')

def unpack_kernels(self, workspace, distro, kernels):
raise NotImplementedError

def hash_config(self, release, target):
raise NotImplementedError

def sign_file_hash_algo(self, release, target):
raise NotImplementedError

def get_kernel_dir(self, workspace, release, target):
raise NotImplementedError

@classmethod
def build_kernel_impl(cls, config_hash, container_name, image_name, kernel_dir, probe, release, workspace, bpf,
def build_kernel_impl(cls, config_hash, sign_file_hash_algo, container_name, image_name, kernel_dir, probe, release, workspace, bpf,
skip_reason):
if bpf:
label = 'eBPF'
Expand All @@ -91,7 +103,7 @@ def build_kernel_impl(cls, config_hash, container_name, image_name, kernel_dir,
#docker.rm(container_name)
try:
ts0 = time.time()
stdout = builder_image.run(workspace, probe, kernel_dir, release, config_hash, container_name, image_name, args)
stdout = builder_image.run(workspace, probe, kernel_dir, release, config_hash, container_name, image_name, sign_file_hash_algo, args)
except subprocess.CalledProcessError as e:
took = time.time() - ts0
logger.error("Build failed for {} probe {}-{} (took {:.3f}s)".format(label, release, config_hash, took))
Expand All @@ -107,8 +119,9 @@ def build_kernel_impl(cls, config_hash, container_name, image_name, kernel_dir,
logger.warn(make_string(line))
return cls.ProbeBuildResult(cls.ProbeBuildResult.BUILD_FAILED, took, stdout)

def build_kernel(self, workspace, probe, builder_distro, release, target):
def build_kernel(self, workspace, probe, builder_distro, release, target, do_sign=False):
config_hash = self.hash_config(release, target)
sign_file_hash_algo = self.sign_file_hash_algo(release, target) if do_sign else ""
output_dir = workspace.subdir('output')

kmod_skip_reason = builder_image.skip_build(probe, output_dir, release, config_hash, False)
Expand Down Expand Up @@ -138,9 +151,9 @@ def build_kernel(self, workspace, probe, builder_distro, release, target):
container_name = ''

return self.KernelBuildResult(
self.build_kernel_impl(config_hash, container_name, image_name, kernel_dir, probe, release, workspace, False,
self.build_kernel_impl(config_hash, sign_file_hash_algo, container_name, image_name, kernel_dir, probe, release, workspace, False,
kmod_skip_reason),
self.build_kernel_impl(config_hash, container_name, image_name, kernel_dir, probe, release, workspace, True,
self.build_kernel_impl(config_hash, sign_file_hash_algo, container_name, image_name, kernel_dir, probe, release, workspace, True,
ebpf_skip_reason),
)

Expand Down
11 changes: 11 additions & 0 deletions probe_builder/builder/distro/centos.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ def hash_config(self, release, target):
except IOError:
return self.md5sum(os.path.join(target, 'lib/modules/{}/config'.format(release)))

def sign_file_hash_algo(self, release, target):
boot = os.path.join(target, 'boot/config-{}'.format(release))
lib_modules = os.path.join(target, 'lib/modules/{}/config'.format(release))

if os.path.isfile(boot):
return self.config_module_sig_hash(boot)
elif os.path.isfile(lib_modules):
return self.config_module_sig_hash(lib_modules)
else:
raise Exception("No file found!")

def get_kernel_dir(self, workspace, release, target):
return workspace.subdir(target, 'usr/src/kernels', release)

Expand Down
3 changes: 3 additions & 0 deletions probe_builder/builder/distro/debian.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ def unpack_kernels(self, workspace, distro, kernels):
def hash_config(self, release, target):
return self.md5sum(os.path.join(target, 'boot/config-{}'.format(release)))

def sign_file_hash_algo(self, release, target):
return self.config_module_sig_hash(os.path.join(target, 'boot/config-{}'.format(release)))

def get_kernel_dir(self, workspace, release, target):
return workspace.subdir(target, 'usr/src/linux-headers-{}'.format(release))

Expand Down