chardevs3: the kernel screams

Learning objective

Listen to the sound of a race condition and understand the fix

Overview

  1. Class files in sysfs

  2. Mutexes in the kernel

  3. Atomic types in the kernel

  4. Triggering a race

  5. Preventing the race

Class files

  1. Use sysfs to expose a kernel interface

  2. Can be read-only, write-only, or read-write

  3. More options exist beyond class files

    ->show() == read

    ->store() == write

Class file API

class_create_file()

class_remove_file()

struct class_attribute

Storing properly

sysfs_emit()

offset_in_page()

  1. Buffer checks done for us, write to start of a page

kstrtou8()

  1. Why not *_from_user?

demo

kkey implements RW attributes for velocity and slowdown

Locking: mutex API

Initialization can be static or dynamic

  1. Static: #define DEFINE_MUTEX()

  2. Dynamic: mutex_init()

Destruction is a no-op on unless debugging:

  1. Normal: mutex_destroy()

  2. Debug: mutex_destroy()

Locking: mutex API

mutex_lock()

  1. Uninterruptible: use with caution

mutex_trylock()

  1. Returns immediately

mutex_lock_interruptible()

  1. Generally suitable for our chardevs

mutex_unlock()

BEWARE

Where are these locks forbidden?

Non-sleeping locks

Atomic context certain: spin_lock() and spin_unlock()

Maybe atomic context: spin_lock_irqsave() and spin_unlock_irqrestore()

Small atomic values

  1. Initialize with
    atomic{,64}_t and ATOMIC_INIT()

  2. Read with
    atomic_read() or atomic64_read()

  3. Set with
    atomic_set() or atomic64_set()

  4. Also: atomic_long_t and atomic_ptr_t

Racer strategy overview

  1. Two proceses writing to kkey

  2. Each note is pressed and released

  3. Race condition: a release or press is missing

  4. A press without release will linger

Enhanced contention

Ensure real multiprocessing

  1. Restrict each process to single CPU

CPU restriction implementation

sysconf(3), _SC_NPROCESSORS_ONLN

CPU_SET, CPU_ZERO

sched_setaffinity(2)

D_GNU_SOURCE

demo

Can you fix this race?

Summary

sysfs can provide a nice API to set/get values in the kernel

Summary

Race conditons in the kernel can be subtle and severe

Summary

Utilize the appropriate lock type for your use case

Summary

Never sleep or block in atomic context!

  1. Use spinlocks

End