Bite-sized Linux and security tips from our LinkedIn series

01

Stop Execution Upon Kernel Oops
or Warning

Set the following sysctls:

kernel.panic_on_oops = 1
kernel.panic_on_warn = 1
#EmbeddedLinuxSecurity
02

Enable YAMA
Security Module

Enable CONFIG_SECURITY_YAMA in your kernel config.

Set /proc/sys/kernel/yama to either:

  • “1”:  Only child processes can be debugged
  • “2”:  Only processes with CAP_SYS_PTRACE can debug anymore
  • “3”:  Disable debugging completely (Once set, cannot undo anymore)
#EmbeddedLinuxSecurity
03

Consider a Hardcoded
Kernel Cmdline

Set in your kernel config:

CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE_OVERRIDE=y
CONFIG_CMDLINE="root=/dev/sda1"
#EmbeddedLinuxSecurity
04

Disable kernel module autoloading

Set the following sysctl:

kernel.modprobe = ""
#EmbeddedLinuxSecurity
05

Enable kASLR

Set in your kernel config:

CONFIG_RANDOMIZE_BASE=y
#EmbeddedLinuxSecurity
06

Don’t Expose Kernel Addresses to Userspace

Set the kernel.kptr_restrict sysctl to either:

“1”: Only users with CAP_SYSLOG see real addresses, everybody else zeros

“2”: Everyone sees just zeros

#EmbeddedLinuxSecurity
07

Restrict Access to the
Kernel Logs (dmesg)

Set the following sysctl:

kernel.dmesg_restrict = 1
#EmbeddedLinuxSecurity
08

Be Careful when Using printf()’s return value

#SecureCoding #C/C++
09

Beware, Compilers are Allowed to Remove
Memset Calls!

#SecureCoding #C/C++
10

Use memcpy with Care!
Use memmove for
Overlapping Memory
Buffers.

#SecureCoding #C/C++
11

Avoid this Realloc Anti-pattern! It Can Leak Memory.

Do not use this:

foo = realloc(foo, ...);

Instead do this:

ret = realloc(foo, ...);
if (ret == NULL) {
    // [...] handle error
    free(foo);
    return ENOMEM;
}
foo = ret;
#SecureCoding #C/C++
12

C can do C++ - Like Destructors too!

Use this:

static inline void cln_fptr(FILE **f) {
    fclose(*f);
}
static void foo(void) {
     __attribute__((cleanup(cln_fptr))) FILE *f;
    f = fopen("/etc/passwd", "r");
    // [...]
}
#SecureCoding #C/C++
13

Don’t Hash your Passwords like LastPass Did!

Instead, use Argon2

#SecureCoding
14

Nonce + Key Reuse Breaks AES-GCM

Key+Nonce reuse will break the security properties of the cipher.

#Cryptography #App Security
15

Always Use Constant-Time Comparison for Verification of MACs

Otherwise, attackers launch timing assaults
against your code.

#Cryptography #App Security
16

Keep Third Party Dependencies Up-to-date!

Depending on your project, use one of these CLI commands to check for outdated dependencies:

$ npm audit 
$ govulncheck ./... 
$ cargo audit
#App Security #Dependency Management
17

Use _FORTIFY_SOURCE

Compile with those flags:

-O2 -D_FORTIFY_SOURCE=2

 
to enable basic bounds checks for functions like memcpy or strcpy.

#SecureCoding #C/C++
18

For Local Communication, Prefer AF_UNIX

Don’t do TCP/UDP on localhost, instead use AF_UNIX.

#SecureCoding #C/C++
19

Be Careful with Parameterless C Functions

Instead of this:

int foo();

Declare it like this:

int foo(void);
#SecureCoding #C/C++
20

Use /dev/kmsg as Early Log Target

Here’s an example:

$ echo "Hello, world" > /dev/kmsg
[734626.551208] Hello, world
#EmbeddedLinux
23

Did You Know? ASAN and UBSAN Can be Combined.

Combine them like that:

# gcc/clang:
$ $CC -fsanitize=address -fsanitize=undefined \
  $CFLAGS
# meson (> 0.55.0):
$ meson compile  -Db_sanitize=address,\
  undefined
24

Have you heard? ASAN can log to a file.

Apply it like that:

$ ASAN_OPTIONS="log_path=asan.log" ./a.out
$ cat asan.log.438963
25

Don’t know how to choose Argon2 parameters?

Use Argon2id with a recommended, universal option
(if acceptable for your use case).

Or tailor to your own Argon2id parameter set
using guide from RFC9106 section 4.

#Cryptography #App Security
26

Generate secrets with cryptographically secure RNG!

Can you find the security problem in this Go snippet?

import "math/rand"
func generateAES256Key() ([]byte, error) {
    var key = make([]byte, 32)
    if _, err := rand.Read(key); err != nil {
        return nil, err
    }
    return key, nil
}
27

Fetch Device Tree at
Runtime

dtc -I fs -O dts /proc/device-tree
#EmbeddedLinux
28

Use the AddressSanitizer (ASAN)

Enable it like that:

gcc/clang:

$ $CC -fsanitize=address $CFLAGS ...

meson (> 0.55.0):

$ meson compile -Db_sanitize=address ...
#SecureCoding #C/C++
29

Use UndefinedBehaviourSanitizer (UBSAN)

Enable it like that:

gcc/clang:

$ $CC -fsanitize=undefined $CFLAGS ...

meson (> 0.55.0):

$ meson compile -Db_sanitize=undefined ...
#EmbeddedLinux
30

Speedup dm-crypt
and Disable Workqueues

With cryptsetup:

$ cryptsetup --perf-no_read_workqueue \
     --perf-no_write_workqueue \
     open /dev/disk name

With crypttab, add these options:

> no-read-workqueue
> no-write-workqueue
#Performance #Linux
31

Force Filesystem Type
While Mounting

At rootfs mount, add to kernel command line:

> rootfstype=TYPE

At userspace, fstab:

/dev/disk /mount/point TYPE defaults 0 0

At userspace, manual mount:

$ mount -t TYPE /dev/disk /mnt/point
#Security #Linux
32

Detect Offline Disk Manipulation

dm-verity

Makes sure every single sector on a block device is authenticated.
It has little overhead but allows no writes!

dm-integrity

Like dm-verity, but offers full read- write access.
It has more overhead since it needs to
maintain a journal!

#Security #Linux
33

Disk Encryption Doesn’t
Detect Manipulations!

Keep in mind:

Although an attacker cannot read your data,
they can change it! While it’s hard to do,
attackers can exchange blocks
on encrypted disks.

Consider using dm-verity/integrity too!

34

How to detect namespacing

Use following commands and compare the outputs:

# List init process namespaces
readlink /proc/1/ns/*

# List target process namespaces (replace <pid>)
readlink /proc/<pid>/ns/*
#Linux #Security
35

Quick QEMU VM setup

Get a Debian VM in QEMU in seconds:

$ wget https://cloud.debian.org/images/cloud/ \
    trixie/latest/debian-13-nocloud-amd64.raw
$ qemu-system-x86_64 -M pc,accel=kvm -m 1G \
        -drive file=debian-13-nocloud-amd64.raw,if=virtio \
        -netdev type=user,hostfwd=tcp::2222-:22,id=net0 \
        -device virtio-net,netdev=net0 -smp 4 -nographic
# Upon first boot, root password is configured
VM$ apt update && apt install openssh-server
VM$ echo "PermitRootLogin yes" > \
        /etc/ssh/sshd_config.d/root_login.conf
VM$ systemctl restart sshd
$ ssh root@localhost -p 2222
36

Recover deleted files via procfs

Run these commands:

# The disk image was deleted by accident
$ ls /srv/disk1.raw
ls: cannot access '/srv/disk1.raw': No such file or directory

# Luckily, PID 1257 still has a reference
$ readlink /proc/1257/fd/* | grep disk
/srv/disk1.raw (deleted)

# Make sure the process does not alter it
# while we read it back
$ kill -STOP 1257

# Read it back
$ cat /proc/1257/fd/18 > /srv/disk1.raw
37

Do not trust process command lines!

Example: A rootkit camouflages itself as httpd:

$ /tmp/rootkit --do=evil --foo bar & 
[1] 21528
$ ps -o pid,args --pid=21528
  PID COMMAND
21528 httpd -DSYSCONFIG
$ cat /proc/21528/cmdline
httpd -DSYSCONFIG
38

Get easy access to container files via procfs

Read container files via procfs:

$ ps fax
[...]
24320 ?     Sl  1:26 /usr/sbin/containerd-shim-runc-v2 [...]
24341 pts/0 Ss+ 0:00  \_ /bin/bash /entry.sh
[...]

$ cat /proc/24341/root/entry.sh
#!/bin/bash
set -e
supervisord -c /etc/supervisord.conf

$ cat /proc/24341/root/etc/hostname
somecontainer
39

Do not trust process command lines! Part II

A shell camouflages itself as arpd

$ unshare -Umr
$ mount --bind /bin/bash /usr/sbin/arpd
$ exec /usr/sbin/arpd
$ # A hidden shell

Inspecting the camouflaged process

$ pidof arpd
1692
$ readlink /proc/1692/exe
/usr/sbin/arpd
$ readlink /proc/$$/ns/mnt /proc/1692/ns/mnt
mnt:[4026531840]
mnt:[4026533296]
40

Sandboxing Applications using Bubblewrap

Bubblewrap at a glance

  • Sandbox is defined via command line options
  • Starts with an empty filesystem, host paths are opt-in
  • NO_NEW_PRIVS bit is set
  • Allows also isolating other namespaces such as networking

Example: Allow everything, but /mnt

$ bwrap --bind / / --tmpfs /mnt /bin/sh
41

No Semantic Versioning in the Linux Kernel

Linux Kernel Versioning: X.Y.Z

  • X: Incremented when Y reaches 20
  • Y: Incremented with every release by Linus Torvalds
  • Z: Incremented with every release by the stable team

Internal Changes Happen Constantly

  • “major” number is irrelevant to compatibility
  • Big API changes can happen in any time
  • The user-visible ABI is set in stone
Icon with a waving hand

Get in touch

sigma star gmbh
Eduard-Bodem-Gasse 6, 1st floor
6020 Innsbruck | Austria

sigma star gmbh logo