Control-flow hijacking attacks have been a known threat to computer systems since the 80s. These attacks typically take place through wrongly implemented memory operations that allow arbitrary corruption of values used to point targets in indirect branches. By modifying these values, attackers redirect control-flow as desired, forcing the execution of malicious routines. Although many solutions have been proposed to disable these threats, attackers have been able to bypass these mechanisms, developing new techniques to launch exploits and compromise systems successfully. From these techniques, Return-Oriented Programming (ROP) attacks stand as the most relevant, as they manage to perform arbitrary Turing-complete computation without the need of code injection in the memory space of the attacked software.Kernel software is also targetable by ROP attacks. Since the introduction of W^X policies and the later mitigation of return-to-user attacks, ROP became the most prominent form of kernel control-flow corruption. As kernel runs with higher privileges that allow full system compromise upon exploitation, hardening this software component against these forms of attack became a valuable asset. In this thesis, we propose, analyze and optimize solutions for control-flow assertion in kernel software.First, we propose kCFI, a fine-grained compiler-based Control-Flow Integrity solution for operating system kernels. This protection computes a kernel control-flow graph and instruments its binary with control-flow assertions to ensure that all indirect branches happen through paths foreseen in the graph. To the best of our knowledge, kCFI is the first fine-grained implementation capable of supporting the Linux kernel, presenting an average performance cost of 8% on micro-benchmarks and 2% on macro-benchmarks, which are the smaller observed overheads for a kernel Control-Flow Integrity solution.Given that Control-Flow Integrity solutions can benefit from dynamic context information to create even more restrictive policies, we finish our work presenting a feasibility analysis for a shadow stack implementation to be used on function return validation, in the kernel. In this study, we first propose a shadow stack architecture design that is compliant with kernel requirements and that can be built on top of kCFI. We also explore two different x86-64 architecture extensions to assess their efficiency on selectively protecting the memory regions used by the shadow stack.