# Observing interrupts from userland on x86

DevFeed: [Observing interrupts from userland on x86](<https://devfeed.tech/articles/observing-interrupts-from-userland-on-x86-21575.md>)

Original publisher: [Read original article](<http://lackingrhoticity.blogspot.com/2018/01/observing-interrupts-from-userland-on-x86.html>)

Author: Mark Seaborn (noreply@blogger.com)

Published: 2018-01-08T20:39:00Z

Content type: tutorial

Language: en

Sources: [Mark Seaborn](<https://devfeed.tech/sources/mark-seaborn.md>)

Topics: [x86](<https://devfeed.tech/topics/x86.md>), [cpu](<https://devfeed.tech/topics/cpu.md>), [Kernel](<https://devfeed.tech/topics/kernel.md>), [Linux](<https://devfeed.tech/topics/linux.md>), [Processes](<https://devfeed.tech/topics/processes.md>)

Tags: [architecture](<https://devfeed.tech/tags/architecture.md>), [c](<https://devfeed.tech/tags/c.md>), [cpu](<https://devfeed.tech/tags/cpu.md>), [kernel](<https://devfeed.tech/tags/kernel.md>), [linux](<https://devfeed.tech/tags/linux.md>), [process](<https://devfeed.tech/tags/process.md>), [side-channel](<https://devfeed.tech/tags/side-channel.md>), [x86](<https://devfeed.tech/tags/x86.md>)

## AI overview

This article explains how a userland process on x86 can detect that it has been interrupted without timing measurements. Setting %fs or %gs to 1 allows the x86 IRET instruction to reset the register to 0 when returning from an interrupt handler; a C program demonstrates the behavior on Linux.

## Source excerpt

In 2016, I noticed a quirk of the x86 architecture that leads to an interesting side channel. On x86, it is possible for a userland process to detect when it has been interrupted by an interrupt handler, without resorting to timing. This is because the usual mechanism for handling interrupts (without using virtualisation) doesn't always preserve all userland registers across an interrupt handler. If a process sets a segment selector register such as %fs or %gs to 1, the register will get set to 0 when the process gets interrupted by an interrupt. Specifically, the x86 IRET instruction will reset the register to 0 when returning to userland -- this is the instruction that kernels use for returning from an interrupt handler. I have not seen this quirk explicitly documented anywhere, so I thought it was worthwhile documenting it via this blog post. The following C program demonstrates the effect: #include <stdint.h> #include <stdio.h> void set_gs(uint16_t value) { __asm__ volatile("mov %0, %%gs" : : "r"(value)); } uint16_t get_gs() { uint16_t value; __asm__ volatile("mov %%gs, %0" : "=r"(value)); return value; } int main() { uint16_t orig_gs = get_gs(); set_gs(1); unsigned int count = 0; /* Loop until %gs gets reset by an interrupt handler. */ while (get_gs() == 1) ++count; /* Restore register so as not to break TLS on x86-32 Linux. This is not necessary on x86-64 Linux, which uses %fs for TLS. */ set_gs(orig_gs); printf("%%gs was reset after %u iterations\n", count); return 0; } This works on x86-32 or x86-64. I tested it on Linux. It will print a non-deterministic number of iterations. For example: %gs was reset after 1807364 iterations Why this happens x86 segment registers are a bit weird, because each one has two parts: A program-visible 16-bit "segment selector" value, which can be read and written by the MOV instruction. A hidden part. When you write to a segment register using the MOV instruction, the CPU also fills out the hidden part. The hidden part includes