cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

local_storage.c (4536B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/*
      4 * Copyright 2020 Google LLC.
      5 */
      6
      7#include "vmlinux.h"
      8#include <errno.h>
      9#include <bpf/bpf_helpers.h>
     10#include <bpf/bpf_tracing.h>
     11
     12char _license[] SEC("license") = "GPL";
     13
     14#define DUMMY_STORAGE_VALUE 0xdeadbeef
     15
     16int monitored_pid = 0;
     17int inode_storage_result = -1;
     18int sk_storage_result = -1;
     19
     20struct local_storage {
     21	struct inode *exec_inode;
     22	__u32 value;
     23};
     24
     25struct {
     26	__uint(type, BPF_MAP_TYPE_INODE_STORAGE);
     27	__uint(map_flags, BPF_F_NO_PREALLOC);
     28	__type(key, int);
     29	__type(value, struct local_storage);
     30} inode_storage_map SEC(".maps");
     31
     32struct {
     33	__uint(type, BPF_MAP_TYPE_SK_STORAGE);
     34	__uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE);
     35	__type(key, int);
     36	__type(value, struct local_storage);
     37} sk_storage_map SEC(".maps");
     38
     39struct {
     40	__uint(type, BPF_MAP_TYPE_SK_STORAGE);
     41	__uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE);
     42	__type(key, int);
     43	__type(value, struct local_storage);
     44} sk_storage_map2 SEC(".maps");
     45
     46struct {
     47	__uint(type, BPF_MAP_TYPE_TASK_STORAGE);
     48	__uint(map_flags, BPF_F_NO_PREALLOC);
     49	__type(key, int);
     50	__type(value, struct local_storage);
     51} task_storage_map SEC(".maps");
     52
     53SEC("lsm/inode_unlink")
     54int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim)
     55{
     56	__u32 pid = bpf_get_current_pid_tgid() >> 32;
     57	struct local_storage *storage;
     58	bool is_self_unlink;
     59
     60	if (pid != monitored_pid)
     61		return 0;
     62
     63	storage = bpf_task_storage_get(&task_storage_map,
     64				       bpf_get_current_task_btf(), 0, 0);
     65	if (storage) {
     66		/* Don't let an executable delete itself */
     67		is_self_unlink = storage->exec_inode == victim->d_inode;
     68		if (is_self_unlink)
     69			return -EPERM;
     70	}
     71
     72	return 0;
     73}
     74
     75SEC("lsm.s/inode_rename")
     76int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry,
     77	     struct inode *new_dir, struct dentry *new_dentry,
     78	     unsigned int flags)
     79{
     80	__u32 pid = bpf_get_current_pid_tgid() >> 32;
     81	struct local_storage *storage;
     82	int err;
     83
     84	/* new_dentry->d_inode can be NULL when the inode is renamed to a file
     85	 * that did not exist before. The helper should be able to handle this
     86	 * NULL pointer.
     87	 */
     88	bpf_inode_storage_get(&inode_storage_map, new_dentry->d_inode, 0,
     89			      BPF_LOCAL_STORAGE_GET_F_CREATE);
     90
     91	storage = bpf_inode_storage_get(&inode_storage_map, old_dentry->d_inode,
     92					0, 0);
     93	if (!storage)
     94		return 0;
     95
     96	if (storage->value != DUMMY_STORAGE_VALUE)
     97		inode_storage_result = -1;
     98
     99	err = bpf_inode_storage_delete(&inode_storage_map, old_dentry->d_inode);
    100	if (!err)
    101		inode_storage_result = err;
    102
    103	return 0;
    104}
    105
    106SEC("lsm.s/socket_bind")
    107int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
    108	     int addrlen)
    109{
    110	__u32 pid = bpf_get_current_pid_tgid() >> 32;
    111	struct local_storage *storage;
    112	int err;
    113
    114	if (pid != monitored_pid)
    115		return 0;
    116
    117	storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0,
    118				     BPF_LOCAL_STORAGE_GET_F_CREATE);
    119	if (!storage)
    120		return 0;
    121
    122	if (storage->value != DUMMY_STORAGE_VALUE)
    123		sk_storage_result = -1;
    124
    125	/* This tests that we can associate multiple elements
    126	 * with the local storage.
    127	 */
    128	storage = bpf_sk_storage_get(&sk_storage_map2, sock->sk, 0,
    129				     BPF_LOCAL_STORAGE_GET_F_CREATE);
    130	if (!storage)
    131		return 0;
    132
    133	err = bpf_sk_storage_delete(&sk_storage_map, sock->sk);
    134	if (err)
    135		return 0;
    136
    137	err = bpf_sk_storage_delete(&sk_storage_map2, sock->sk);
    138	if (!err)
    139		sk_storage_result = err;
    140
    141	return 0;
    142}
    143
    144SEC("lsm.s/socket_post_create")
    145int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
    146	     int protocol, int kern)
    147{
    148	__u32 pid = bpf_get_current_pid_tgid() >> 32;
    149	struct local_storage *storage;
    150
    151	if (pid != monitored_pid)
    152		return 0;
    153
    154	storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0,
    155				     BPF_LOCAL_STORAGE_GET_F_CREATE);
    156	if (!storage)
    157		return 0;
    158
    159	storage->value = DUMMY_STORAGE_VALUE;
    160
    161	return 0;
    162}
    163
    164/* This uses the local storage to remember the inode of the binary that a
    165 * process was originally executing.
    166 */
    167SEC("lsm.s/bprm_committed_creds")
    168void BPF_PROG(exec, struct linux_binprm *bprm)
    169{
    170	__u32 pid = bpf_get_current_pid_tgid() >> 32;
    171	struct local_storage *storage;
    172
    173	if (pid != monitored_pid)
    174		return;
    175
    176	storage = bpf_task_storage_get(&task_storage_map,
    177				       bpf_get_current_task_btf(), 0,
    178				       BPF_LOCAL_STORAGE_GET_F_CREATE);
    179	if (storage)
    180		storage->exec_inode = bprm->file->f_inode;
    181
    182	storage = bpf_inode_storage_get(&inode_storage_map, bprm->file->f_inode,
    183					0, BPF_LOCAL_STORAGE_GET_F_CREATE);
    184	if (!storage)
    185		return;
    186
    187	storage->value = DUMMY_STORAGE_VALUE;
    188}