-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsysdig-probe-loader
executable file
·787 lines (664 loc) · 23.3 KB
/
sysdig-probe-loader
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
#!/bin/bash
#
# Copyright (C) 2013-2018 Draios Inc dba Sysdig.
#
# This file is part of sysdig .
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Simple script that desperately tries to load sysdig-probe looking
# for it in a bunch of ways. Convenient when running sysdig inside
# a container or in other weird environments.
#
#
# --- WORKFLOW ---
#
# By default, the script uses the following approaches to build or fetch
# or find the sysdig-probe, in the following order:
# 1) In the kernel module case, use modprobe, which looks for the kernel
# module already installed in /lib/modules
# 2) Look for the appropriate sysdig-probe (kernel module or eBPF) for the
# currently running kernel, in the .sysdig directory
# 3) Fetch the appropriate sysdig-probe (kernel module or eBPF) for the
# currently running kernel, from download.sysdig.com
#
# Workflow variations:
# A) If the environment variable SYSDIG_FORCE_DOWNLOAD_PROBE is defined,
# the script ONLY tries to download the appropriate sysdig-probe (kernel module or eBPF).
# The script won't try to build the probe.
# B) If the environment variable SYSDIG_FORCE_BUILD_PROBE is defined,
# the script ONLY tries to build the appropriate sysdig-probe (kernel module or eBPF).
# The script won't try to download the probe.
#
# Note:
# SYSDIG_FORCE_DOWNLOAD_PROBE and SYSDIG_FORCE_BUILD_PROBE cannot be simultaneously defined. If so, the
# probe loader raises an error.
#
# --- ENVIRONMENT VARIABLES ---
#
# By default, the following naming conventions are used.
# A) Probe filename
# kernel module: sysdigcloud-probe-<SYSDIG_VERSION>-<ARCH>-<KERNEL_RELEASE>-<KERNEL_CONFIG_HASH>.ko
# eBPF probe: sysdigcloud-probe-bpf-<SYSDIG_VERSION>-<ARCH>-<KERNEL_RELEASE>-<KERNEL_CONFIG_HASH>.o
# Where:
# <SYSDIG_VERSION> = sysdig release version (e.g. 12.0.3)
# <ARCH> = CPU architecture (e.g. x86_64)
# <KERNEL_RELEASE> = uname -r output (e.g. 4.18.0-147.56.1.el8_1.x86_64)
# <KERNEL_CONFIG_HASH> = result of hash, calculated over kernel config file, 32 hex digits
# So, an example kernel module filename would be
# sysdigcloud-probe-12.0.3-x86_64-4.18.0-147.56.1.el8_1.x86_64-2f4c51e1d6af404393d778653f50135.ko
#
# B) Download URL
# <DOWNLOAD_URL_HOST>/<DOWNLOAD_REPOSITORY>/sysdig-probe-binaries/<PROBE_FILENAME>
# Where:
# DOWNLOAD_URL_HOST = "download.sysdig.com" by default
# DOWNLOAD_REPOSITORY = "stable" by default
#
# The following environment variables may be used to override defaults for different
# aspects of the object names:
#
# 1) SYSDIG_PROBE_OVERRIDE_FULL_URL
# - Overrides everything -- URL AND Probe filename
# - This is particularly useful when the user needs to download a probe built onsite,
# from a locally-hosted location, and doesn't want to worry about mimicing any
# naming conventions
# - Also particularly useful when the host doesn't have sufficient files (kernel headers,
# kernel config file) available, because it avoids the necessity of finding and
# calculating the checksum of the kernel config file on the local system.
#
# 2) SYSDIG_PROBE_URL
# - Finer-grain override
# - Allows the user to override only the DOWNLOAD_URL_HOST value from item B above,
# to specify a different host + optional port number (e.g. "probe-host.mydomain.com:80"
# vs. the default "download.sysdig.com"),
# - While retaining/mimicing the standard Sysdig directory structure and filename format
#
# 3) SYSDIG_REPOSITORY
# - Finer-grain override
# - Allows the user (or build script) to override only the DOWNLOAD_REPOSITORY value
# from item B above, to specify a top-level directory (e.g. "dev" instead of "stable")
# - While retaining/mimicing the standard Sysdig directory structure and filename format
#
# Returns 1 if $cos_ver > $base_ver, 0 otherwise
#
cos_version_greater()
{
if [[ $cos_ver == $base_ver ]]; then
return 0
fi
#
# COS build numbers are in the format x.y.z
#
a=`echo $cos_ver | cut -d. -f1`
b=`echo $cos_ver | cut -d. -f2`
c=`echo $cos_ver | cut -d. -f3`
d=`echo $base_ver | cut -d. -f1`
e=`echo $base_ver | cut -d. -f2`
f=`echo $base_ver | cut -d. -f3`
# Test the first component
if [[ $a -gt $d ]]; then
return 1
elif [[ $d -gt $a ]]; then
return 0
fi
# Test the second component
if [[ $b -gt $e ]]; then
return 1
elif [[ $e -gt $b ]]; then
return 0
fi
# Test the third component
if [[ $c -gt $f ]]; then
return 1
elif [[ $f -gt $c ]]; then
return 0
fi
# If we get here, probably malformed version string?
return 0
}
#
# Looks for the kernel configuration and stores its hash in KERNEL_CONFIG_PATH.
# Returns 0 on success, 1 otherwise (cannot find kernel configuration).
#
get_kernel_config_hash() {
echo "* Looking for kernel configuration"
if [ -f /proc/config.gz ]; then
echo " Found kernel config at /proc/config.gz"
KERNEL_CONFIG_PATH=/proc/config.gz
elif [ -f "/boot/config-${KERNEL_RELEASE}" ]; then
echo " Found kernel config at /boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH=/boot/config-${KERNEL_RELEASE}
elif [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/boot/config-${KERNEL_RELEASE}" ]; then
echo " Found kernel config at ${SYSDIG_HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="${SYSDIG_HOST_ROOT}/boot/config-${KERNEL_RELEASE}"
elif [ -f "/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
echo " Found kernel config at /usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
elif [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}" ]; then
echo " Found kernel config at ${SYSDIG_HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
KERNEL_CONFIG_PATH="${SYSDIG_HOST_ROOT}/usr/lib/ostree-boot/config-${KERNEL_RELEASE}"
elif [ -f /lib/modules/${KERNEL_RELEASE}/config ]; then
# this code works both for native host and agent container assuming that
# Dockerfile sets up the desired symlink /lib/modules -> $SYSDIG_HOST_ROOT/lib/modules
echo " Found kernel config at /lib/modules/${KERNEL_RELEASE}/config"
KERNEL_CONFIG_PATH="/lib/modules/${KERNEL_RELEASE}/config"
fi
if [ -z "${KERNEL_CONFIG_PATH}" ]; then
echo "Cannot find kernel configuration"
return 1
fi
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
HASH=$(zcat "${KERNEL_CONFIG_PATH}" | md5sum - | cut -d' ' -f1)
else
HASH=$(md5sum "${KERNEL_CONFIG_PATH}" | cut -d' ' -f1)
fi
return 0
}
#
# Tries to remove the kernel probe.
# Returns 0 on success, 1 otherwise (kernel probe still loaded).
#
remove_kernel_probe() {
echo "* Unloading ${PROBE_NAME}, if present"
# Tries to remove the module within a predefined time ($MAX_RMMOD_WAIT)
rmmod "${PROBE_NAME}" 2>/dev/null
WAIT_TIME=0
KMOD_NAME=$(echo "${PROBE_NAME}" | tr "-" "_")
while lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1 && [ $WAIT_TIME -lt $MAX_RMMOD_WAIT ]; do
if rmmod "${PROBE_NAME}" 2>/dev/null; then
echo "* Unloading ${PROBE_NAME} succeeded after ${WAIT_TIME}s"
break
fi
((++WAIT_TIME))
if (( $WAIT_TIME % 5 == 0 )); then
echo "* ${PROBE_NAME} still loaded, waited ${WAIT_TIME}s (max wait ${MAX_RMMOD_WAIT}s)"
fi
sleep 1
done
# Still loaded
if lsmod | grep "${KMOD_NAME}" > /dev/null 2>&1; then
echo "* ${PROBE_NAME} seems to still be loaded, hoping the best"
return 1
fi
return 0
}
#
# Evaluates variables override.
# Returns 1 on success, 0 otherwise.
#
get_variable_override_kernel_probe() {
echo "* Evaluating override of environment variables"
if [ ! -z ${SYSDIG_PROBE_OVERRIDE_FULL_URL} ]; then
SYSDIG_PROBE_FILENAME=$(basename "${SYSDIG_PROBE_OVERRIDE_FULL_URL}")
URL=$(echo "${SYSDIG_PROBE_OVERRIDE_FULL_URL}" | sed s/+/%2B/g)
else
# Tries to get the hash of the kernel configuration
get_kernel_config_hash
if [ $? -eq 1 ]; then
return 1
fi
SYSDIG_PROBE_FILENAME="${PROBE_NAME}-${SYSDIG_VERSION}-${ARCH}-${KERNEL_RELEASE}-${HASH}.ko"
URL=$(echo "${SYSDIG_PROBE_URL}/${SYSDIG_REPOSITORY}/sysdig-probe-binaries/${SYSDIG_PROBE_FILENAME}" | sed s/+/%2B/g)
fi
return 0
}
#
# Loads a precompiled kernel probe for the current kernel via insmod.
# Returns 0 on success, 1 otherwise.
#
load_precompiled_kernel_probe() {
echo "* Loading module"
insmod_out1=$(insmod "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}" 2>&1)
exit_status1=$?
if [ $exit_status1 -ne 0 ]; then
# Fedora 35+ distros on some cloud variants like AWS will
# carry some default SELinux policy preventing it from
# loading a .ko from a file descriptor through finit_module()
# (which is what insmod does).
# Compressing it with .xz forces insmod to decompress it into memory first,
# and load it through init_module() instead, circumventing the issue.
echo "* Loading module (xz)"
xz -zkf "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}"
insmod_out2=$(insmod "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}.xz" 2>&1)
exit_status2=$?
if [ $exit_status2 -ne 0 ]; then
echo "Cannot insmod, exit status $exit_status1, error: $insmod_out1"
echo "Cannot insmod even after xz, exit status $exit_status1, error: $insmod_out2"
return 1
fi
fi
return 0
}
#
# Downloads a precompiled kernel probe for the current kernel.
# Returns 0 on success, 1 otherwise (download failed).
#
download_kernel_probe() {
echo "* Trying to download precompiled module from ${URL}"
curl_out=$(curl --create-dirs "${SYSDIG_PROBE_CURL_OPTIONS}" -o "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}" "${URL}" 2>&1)
if [ "$?" = "0" ]; then
echo " Download succeeded"
return 0
fi
echo "Download of ${PROBE_NAME} for version ${SYSDIG_VERSION} failed."
# "curl: (22) The requested URL returned error: 404 Not Found" - The probe doesn't exist in the repo.
if [[ "$curl_out" =~ "404 Not Found" ]]; then
echo "The probe for this version does not exist in the repo."
# Enriches error message
if [ ! -z "${KERNEL_ERR_MESSAGE}" ]; then
echo "${KERNEL_ERR_MESSAGE}"
else
echo "Consider compiling your own ${PROBE_NAME} and loading it or getting in touch with the Sysdig community."
fi
else
echo "$curl_out"
fi
return 1
}
#
# Builds and installs the probe kernel module via dkms.
# Returns 0 on success, 1 otherwise.
#
build_kernel_probe() {
echo "* Running dkms install for ${PACKAGE_NAME}"
if dkms install -m "${PACKAGE_NAME}" -v "${SYSDIG_VERSION}" -k "${KERNEL_RELEASE}"; then
echo " dkms install done"
echo "* Trying to load the dkms ${PROBE_NAME} via insmod"
# Try all possible extensions a kernel module built by dkms can have
for ext in ko ko.xz ko.gz ko.zst ; do
ko_file="/var/lib/dkms/${PACKAGE_NAME}/${SYSDIG_VERSION}/${KERNEL_RELEASE}/${ARCH}/module/${PROBE_NAME}.${ext}"
echo "* Looking for ${ko_file}"
if [ -f $ko_file ]; then
echo "* Found ${ko_file}; trying to insmod"
if insmod $ko_file > /dev/null 2>&1; then
echo " ${PROBE_NAME}.${ext} found and loaded in dkms"
return 0
fi
fi
done
echo " Unable to insmod"
else
DKMS_LOG="/var/lib/dkms/${PACKAGE_NAME}/${SYSDIG_VERSION}/build/make.log"
if [ -f "${DKMS_LOG}" ]; then
echo " Running dkms build failed, dumping ${DKMS_LOG}"
cat "${DKMS_LOG}"
else
echo " Running dkms build failed, couldn't find ${DKMS_LOG}"
fi
fi
return 1
}
#
# Tries to load the appropriate kernel probe.
# Returns 0 on success, 1 otherwise.
#
load_kernel_probe() {
echo "* Loading kernel probe"
# Required utils
if ! hash lsmod > /dev/null 2>&1; then
echo "This program requires lsmod"
return 1
fi
if ! hash modprobe > /dev/null 2>&1; then
echo "This program requires modprobe"
return 1
fi
if ! hash rmmod > /dev/null 2>&1; then
echo "This program requires rmmod"
return 1
fi
# Removes leftover kernel probe
remove_kernel_probe
if [ $? -eq 1 ]; then
return 0
fi
# Forces probe download, skips build
if [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ]; then
echo "* Skipping build, FORCE_DOWNLOAD_PROBE is enabled"
else
# Builds the probe via dkms; skips UEK hosts, the build will always fail
if [[ $(uname -r) == *uek* ]]; then
echo "* Skipping dkms install for UEK host"
else
build_kernel_probe
if [ $? -eq 0 ]; then
return 0
fi
fi
echo "* Trying to load a system ${PROBE_NAME}, if present"
if modprobe "${PROBE_NAME}" > /dev/null 2>&1; then
echo "${PROBE_NAME} found and loaded with modprobe"
return 0
fi
fi
echo "* Trying to find precompiled ${PROBE_NAME} for ${KERNEL_RELEASE}"
# Evaluates variables override, returns if cannot (cannot find kernel config)
local SYSDIG_PROBE_FILENAME
local URL
get_variable_override_kernel_probe
if [ $? -eq 1 ]; then
return 1
fi
# Look for a precompiled kernel probe locally
if [ ! -v SYSDIG_FORCE_DOWNLOAD_PROBE ]; then
echo "* Trying to find precompiled ${PROBE_NAME} for ${KERNEL_RELEASE}"
if [ -f "${HOME}/.sysdig/${SYSDIG_PROBE_FILENAME}" ]; then
echo " Found precompiled module at ~/.sysdig/${SYSDIG_PROBE_FILENAME}"
load_precompiled_kernel_probe
return $?
fi
fi
# Skip download, the probe build has failed
if [ -v SYSDIG_FORCE_BUILD_PROBE ]; then
echo "* Skipping download, FORCE_BUILD_PROBE is enabled"
return 1;
fi;
download_kernel_probe
if [ $? -eq 1 ]; then
return 1
fi
load_precompiled_kernel_probe
return $?
}
#
# Makes a symlink to the BPF probe.
# Return 0 on success, 1 otherwise.
#
function make_symlink_bpf_probe() {
echo "* Making symlink to BPF probe"
if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
echo " BPF probe not found"
return 1
fi
if [ ! -f /proc/sys/net/core/bpf_jit_enable ]; then
echo "**********************************************************"
echo "** BPF doesn't have JIT enabled, performance might be **"
echo "** degraded. Please ensure to run on a kernel with **"
echo "** CONFIG_BPF_JIT enabled and/or use --net=host if **"
echo "** running inside a container. **"
echo "**********************************************************"
fi
echo " BPF probe located, it's now possible to start Sysdig"
symlink_out=$(ln -sf "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" "${HOME}/.sysdig/${BPF_PROBE_NAME}.o")
if [ $? -ne 0 ]; then
echo " Cannot ln, error $symlink_out"
return 1
fi
return 0
}
#
# Downloads the BPF probe.
# Returns 0 on success, 1 otherwise.
#
download_bpf_probe() {
echo "* Trying to download precompiled BPF probe from ${URL}"
curl --create-dirs "${SYSDIG_PROBE_CURL_OPTIONS}" -o "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" "${URL}"
if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
echo " Download failed"
return 1
fi
echo " Download succeeded"
return 0
}
#
# Evaluates variables override.
# Returns 1 on success, 0 otherwise.
#
get_variable_override_bpf_probe() {
echo "* Evaluating override of environment variables"
if [ ! -z ${SYSDIG_PROBE_OVERRIDE_FULL_URL} ]; then
BPF_PROBE_FILENAME=$(basename "${SYSDIG_PROBE_OVERRIDE_FULL_URL}")
URL=$(echo "${SYSDIG_PROBE_OVERRIDE_FULL_URL}" | sed s/+/%2B/g)
else
# Tries to get the hash of the kernel configuration
get_kernel_config_hash
if [ $? -eq 1 ]; then
return 1
fi
BPF_PROBE_FILENAME="${BPF_PROBE_NAME}-${SYSDIG_VERSION}-${ARCH}-${KERNEL_RELEASE}-${HASH}.o"
URL=$(echo "${SYSDIG_PROBE_URL}/${SYSDIG_REPOSITORY}/sysdig-probe-binaries/${BPF_PROBE_FILENAME}" | sed s/+/%2B/g)
fi
return 0
}
#
# Builds the BPF probe.
# Returns 0, always.
#
build_bpf_probe() {
local BPF_KERNEL_SOURCES_URL=""
local STRIP_COMPONENTS=1
customize_kernel_build() {
if [ -n "${KERNEL_EXTRA_VERSION}" ]; then
sed -i "s/LOCALVERSION=\"\"/LOCALVERSION=\"${KERNEL_EXTRA_VERSION}\"/" .config
fi
make olddefconfig > /dev/null
make modules_prepare > /dev/null
}
if [ -n "${COS}" ]; then
echo " COS detected (build ${BUILD_ID}), using cos kernel headers..."
BPF_KERNEL_SOURCES_URL="https://storage.googleapis.com/cos-tools/${BUILD_ID}/kernel-headers.tgz"
KERNEL_EXTRA_VERSION="+"
STRIP_COMPONENTS=0
customize_kernel_build() {
pushd usr/src/* > /dev/null
# Note: this overrides the KERNELDIR set while untarring the tarball
export KERNELDIR=`pwd`
sed -i '/^#define randomized_struct_fields_start struct {$/d' include/linux/compiler-clang.h
sed -i '/^#define randomized_struct_fields_end };$/d' include/linux/compiler-clang.h
popd > /dev/null
# Might need to configure our own sources depending on COS version
cos_ver=${BUILD_ID}
base_ver=11553.0.0
cos_version_greater
greater_ret=$?
if [[ greater_ret -eq 1 ]]; then
export KBUILD_EXTRA_CPPFLAGS=-DCOS_73_WORKAROUND
fi
}
fi
if [ -n "${MINIKUBE}" ]; then
echo " Minikube detected (${MINIKUBE_VERSION}), using linux kernel sources for minikube kernel"
local kernel_version=$(uname -r)
local -r kernel_version_major=$(echo ${kernel_version} | cut -d. -f1)
local -r kernel_version_minor=$(echo ${kernel_version} | cut -d. -f2)
local -r kernel_version_patch=$(echo ${kernel_version} | cut -d. -f3)
if [ "${kernel_version_patch}" == "0" ]; then
kernel_version="${kernel_version_major}.${kernel_version_minor}"
fi
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${SYSDIG_BPF_USE_LOCAL_KERNEL_SOURCES}" ]; then
local -r kernel_version_major=$(uname -r | cut -d. -f1)
local -r kernel_version=$(uname -r | cut -d- -f1)
KERNEL_EXTRA_VERSION="-$(uname -r | cut -d- -f2)"
echo " Using downloaded kernel sources for kernel version ${kernel_version}..."
BPF_KERNEL_SOURCES_URL="http://mirrors.edge.kernel.org/pub/linux/kernel/v${kernel_version_major}.x/linux-${kernel_version}.tar.gz"
fi
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
echo " Downloading kernel sources from ${BPF_KERNEL_SOURCES_URL}"
mkdir -p /tmp/kernel
cd /tmp/kernel
cd `mktemp -d -p /tmp/kernel`
if ! curl -o kernel-sources.tgz --create-dirs "${SYSDIG_PROBE_CURL_OPTIONS}" "${BPF_KERNEL_SOURCES_URL}"; then
exit 1;
fi
echo " Extracting kernel sources"
mkdir kernel-sources && tar xf kernel-sources.tgz -C kernel-sources --strip-components "${STRIP_COMPONENTS}"
cd kernel-sources
export KERNELDIR=`pwd`
if [[ "${KERNEL_CONFIG_PATH}" == *.gz ]]; then
zcat "${KERNEL_CONFIG_PATH}" > .config
else
cat "${KERNEL_CONFIG_PATH}" > .config
fi
echo " Configuring kernel"
customize_kernel_build
fi
echo " Trying to compile BPF probe ${BPF_PROBE_NAME} (${BPF_PROBE_FILENAME})"
make -C "/usr/src/${PACKAGE_NAME}-${SYSDIG_VERSION}/bpf" > /dev/null
mkdir -p ~/.sysdig
mv "/usr/src/${PACKAGE_NAME}-${SYSDIG_VERSION}/bpf/probe.o" "${HOME}/.sysdig/${BPF_PROBE_FILENAME}"
if [ -n "${BPF_KERNEL_SOURCES_URL}" ]; then
rm -r /tmp/kernel
fi
return 0
}
#
# Tries to load the appropriate BPF probe.
# Returns 0 on success, a non zero value otherwise.
#
load_bpf_probe() {
echo "* Loading BPF probe"
# Makes checks and set variables
if [ ! -d /sys/kernel/debug/tracing ]; then
echo "* Mounting debugfs"
mount -t debugfs nodev /sys/kernel/debug
fi
if [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/etc/os-release" ]; then
. "${SYSDIG_HOST_ROOT}/etc/os-release"
if [ "${ID}" == "cos" ]; then
COS=1
fi
fi
if [ ! -z "${SYSDIG_HOST_ROOT}" ] && [ -f "${SYSDIG_HOST_ROOT}/etc/VERSION" ]; then
MINIKUBE=1
MINIKUBE_VERSION="$(cat ${SYSDIG_HOST_ROOT}/etc/VERSION)"
fi
local BPF_PROBE_FILENAME
local URL
# Evaluates variables override, returns if cannot (cannot find kernel config)
get_variable_override_bpf_probe
if [ $? -eq 1 ]; then
return 1
fi
# Forces probe download, skips build
if [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ]; then
echo "* Skipping build, FORCE_DOWNLOAD_PROBE is enabled"
else
# Builds the bpf probe
echo "* Building BPF probe"
if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
build_bpf_probe
else
echo " Will not build, the BPF probe ${BPF_PROBE_FILENAME} already exists at ${HOME}/.sysdig/"
fi
fi
# Skip download
if [ -v SYSDIG_FORCE_BUILD_PROBE ]; then
echo "* Skipping download, FORCE_BUILD_PROBE is enabled"
make_symlink_bpf_probe
return $?;
fi;
# Prevents installing a leftover probe
if [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ] && [ -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
rm ${HOME}/.sysdig/${BPF_PROBE_FILENAME}
if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
echo "* Removed existing bpf probe ${HOME}/.sysdig/${BPF_PROBE_FILENAME}"
else
echo "* Cannot remove existing bpf probe ${HOME}/.sysdig/${BPF_PROBE_FILENAME}"
fi
fi
# Downloads the bpf probe
if [ ! -f "${HOME}/.sysdig/${BPF_PROBE_FILENAME}" ]; then
download_bpf_probe
if [ $? -eq 1 ]; then
return 1;
fi
else
echo " Will not download, the BPF probe ${BPF_PROBE_FILENAME} already exists at ${HOME}/.sysdig/"
fi
make_symlink_bpf_probe
return $?
}
###################
### Entry point ###
###################
# Inits variables and makes required checks
ARCH=$(uname -m)
KERNEL_RELEASE=$(uname -r)
SCRIPT_NAME=$(basename "${0}")
SYSDIG_PROBE_URL=${SYSDIG_PROBE_URL:-https://download.sysdig.com}
if [ -n "$SYSDIG_PROBE_INSECURE_DOWNLOAD" ]
then
SYSDIG_PROBE_CURL_OPTIONS=-fsSk
else
SYSDIG_PROBE_CURL_OPTIONS=-fsS
fi
if [ -n "$SYSDIG_PROBE_BASIC_AUTH" ]
then
SYSDIG_PROBE_CURL_OPTIONS="-u ${SYSDIG_PROBE_BASIC_AUTH_USER} ${SYSDIG_PROBE_CURL_OPTIONS}"
fi
MAX_RMMOD_WAIT=60
KERNEL_ERR_MESSAGE=""
if [[ $# -ge 1 ]]; then
KERNEL_ERR_MESSAGE="$1"
fi
if [ -z "${SYSDIG_REPOSITORY}" ]; then
SYSDIG_REPOSITORY="stable"
fi
if [ "${SCRIPT_NAME}" = "sysdig-probe-loader" ]; then
if [ -z "$SYSDIG_VERSION" ]; then
SYSDIG_VERSION=$(sysdig --version | cut -d' ' -f3)
fi
PROBE_NAME="sysdig-probe"
BPF_PROBE_NAME="sysdig-probe-bpf"
PACKAGE_NAME="sysdig"
elif [ "${SCRIPT_NAME}" = "sysdigcloud-probe-loader" ]; then
EXEPATH=$(dirname "$(readlink -f "${0}")")
if [ -z "$SYSDIG_VERSION" ]; then
SYSDIG_VERSION=$("${EXEPATH}"/dragent --version)
fi
PROBE_NAME="sysdigcloud-probe"
BPF_PROBE_NAME="sysdigcloud-probe-bpf"
PACKAGE_NAME="draios-agent"
else
echo "This script must be called as sysdig-probe-loader or sysdigcloud-probe-loader"
exit 1
fi
if [ "$(id -u)" != 0 ]; then
echo "Installer must be run as root (or with sudo)."
exit 1
fi
if [ "$SYSDIG_AGENT_DRIVER" != universal_ebpf ]; then
if ! hash curl > /dev/null 2>&1; then
echo "This program requires curl"
exit 1
fi
fi
if [ -v SYSDIG_FORCE_BUILD_PROBE ] && [ -v SYSDIG_FORCE_DOWNLOAD_PROBE ] ; then
echo "Cannot define SYSDIG_FORCE_BUILD_PROBE and SYSDIG_FORCE_DOWNLOAD_PROBE simultaneously."
echo "Cannot load the probe"
exit 1
fi
# Detect and bail on conflicting env vars, first
if ([ "$SYSDIG_AGENT_DRIVER" = universal_ebpf ] || [ "$SYSDIG_AGENT_DRIVER" = kmod ]) && \
[ "${SYSDIG_BPF_PROBE+x}" = x ]; then
echo "ERROR: Conflicting values specified for 'SYSDIG_AGENT_DRIVER' and 'SYSDIG_BPF_PROBE' environment variables."
exit 1
elif [ "$SYSDIG_AGENT_DRIVER" = universal_ebpf ]; then
# We don't need the kmod for Universal eBPF
/sbin/rmmod "$PROBE_NAME" || true
# Loads the probe
elif [ "$SYSDIG_AGENT_DRIVER" = legacy_ebpf ] || [ "${SYSDIG_BPF_PROBE+x}" = x ]; then
load_bpf_probe
else
load_kernel_probe
fi
# Echoes the result
if [ $? -eq 1 ]; then
echo "Cannot load the probe"
exit 1
fi
echo "Probe loaded"
exit 0