Using dm-verity is a very good idea, especially if you are able to fuse a key in hardware to reduce the TCB further. This can greatly help prevent a system from being persistently compromised, as well as ensure integrity, making tampering highly evident. A quick web search shows several TPM implementations for Raspberry Pi, which will allow you to implement SRTM (Static Root-of-Trust for Measurement) on the device, giving you the ability to perform measured boot and remote attestation, augmenting dm-verity to increase the integrity of the device.
Filesystem-level encryption can be useful, but if you are uploading data to the cloud, you must be aware of risks incurred from that behavior as well. Filesystem-level encryption will not protect data which has been uploaded to an insecure "cloud" host. Ideally, you would use client-side encryption instead. If you are only uploading things such as video files, you could encrypt them with an easy to use and popular library like NaCl/libsodium before uploading them, encrypted, to a remote server. Remember also that the password has to come from somewhere. Unless your user is selecting the password themselves, then you will not be providing any confidentiality (for the data on the device). Storing the password on the device would be a bad idea.
Even more important than this and everything that is about to follow is the development of a formal threat model. You need to know who your adversaries are, what your users' assets are and their value, and put it all in context. Write up an attack tree, and use it. Risk assessment and threat modeling are in general extremely important for the security of your product.
This refers to any action to increase the security of the kernel to reduce the risk of exploitation. This is a broad class of techniques that range from patching the kernel with security-oriented patches to simply adjusting sysctls to reduce attack surface.
- Kernel patches such as grsecurity greatly increase the difficulty in exploiting the kernel. Currently, grsecurity has closed itself except to paying customers, so it may be out of your budget range. If you are able to use it, or a forward port of it, you will get a large number of kernel hardening features, quite a bit more than would be possible through configuration alone.
- Custom kernel configurations allow you to remove unnecessary code and features from the kernel, as well as breaking stock exploits. For example, many kernel exploits require the use of obscure or complex drivers. Since you are developing for an embedded system, chances are you will already be using a custom kernel config. You should strip it down to only the drivers you need, and disable some particularly problematic features such as user namespaces, vsyscalls, and unprivileged eBPF. This is one of the most important ways to harden a kernel.
- If you go through the whole sysctl list, you will see many which are security related but have default values that are not ideal. By tweaking sysctls, you can disable unprivileged user namespaces, eBPF, JIT, etc. You can also do things such as increase the randomness provided by ASLR, by increasing the
vm.mmap_rnd_bits sysctls. Additionally, enabling sysctls to panic the kernel on various events such as oopses can also greatly improve security, as many kernel vulnerabilities trigger an oops or a kernel warning, but by default the kernel will continue as if nothing happened, potentially allowing the exploit to succeed. As this is an embedded device, panicking and rebooting immediately would be ideal.
- Kernel module signing is used to prevent an unsigned module from being loaded (though ideally you would build a non-modular kernel with only drivers you need, as you control the hardware). The signing key can be created offline while compiling the kernel. This can be used, along with other security features such as those provided by grsecurity, to prevent even the root user from compromising the system. Protecting the kernel from root is hard, but not at all impossible.
Using grsecurity is by far the most effective form of kernel hardening, but depending on the budget for your product line, it may or may not be cost effective. A custom kernel config is the second most effective, but requires a decent understanding of kernel configuration. I would strongly recommend hiring a security expert to do all this, otherwise you may inadvertently disable important security features or enable unsafe options. The Kconfig help section is not always sufficient to understand the security implications of a given option. For example, many of the "debugging" features are actually extremely useful for security, such as the various sanity checks. Familiarize yourself with the Linux kernel and its various subsystems. This will allow you to greatly improve the security of your device.
Network hardening refers to increasing the difficulty of network exploitation vectors and lateral movement. Exactly what constitutes appropriate network hardening depends heavily on the specific setup and network topology. At its simplest, it involves basic firewall rules, but can be more extensive.
- Whitelisting incoming connections is important to protect potentially insecure services. Whitelisting outgoing connections can also be useful for hampering malicious software or otherwise misbehaving software, making it harder to control a device over a C2.
- Like with kernel hardening, you can tweak various sysctls to improve networking security. The exact tweaks depend very heavily on your use case. For example, disabling IPv6 can reduce attack surface area when it is not necessary. Disabling features only useful for routing can reduce the chance that your device is abused to redirect packets. Other tweaks can improve performance and increase resistance to DoS attacks.
- Unnecessary protocols should be disabled. This is especially important for kernel hardening against remote attackers, as many protocols such as DCCP have a history of vulnerabilities, and yet are enabled by default. Ideally, your kernel should only support TCP, UDP, and ICMP, unless other protocols are absolutely necessary for correct operation of your devices.
Network hardening is usually more relevant for an entire infrastructure with multiple interconnected components. For a single device making only a connection to a server to remotely upload files, network hardening is much closer to kernel hardening, i.e. eliminate unnecessary attack surface area.