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

fuse_mnt.c (2284B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * memfd test file-system
      4 * This file uses FUSE to create a dummy file-system with only one file /memfd.
      5 * This file is read-only and takes 1s per read.
      6 *
      7 * This file-system is used by the memfd test-cases to force the kernel to pin
      8 * pages during reads(). Due to the 1s delay of this file-system, this is a
      9 * nice way to test race-conditions against get_user_pages() in the kernel.
     10 *
     11 * We use direct_io==1 to force the kernel to use direct-IO for this
     12 * file-system.
     13 */
     14
     15#define FUSE_USE_VERSION 26
     16
     17#include <fuse.h>
     18#include <stdio.h>
     19#include <string.h>
     20#include <errno.h>
     21#include <fcntl.h>
     22#include <unistd.h>
     23
     24static const char memfd_content[] = "memfd-example-content";
     25static const char memfd_path[] = "/memfd";
     26
     27static int memfd_getattr(const char *path, struct stat *st)
     28{
     29	memset(st, 0, sizeof(*st));
     30
     31	if (!strcmp(path, "/")) {
     32		st->st_mode = S_IFDIR | 0755;
     33		st->st_nlink = 2;
     34	} else if (!strcmp(path, memfd_path)) {
     35		st->st_mode = S_IFREG | 0444;
     36		st->st_nlink = 1;
     37		st->st_size = strlen(memfd_content);
     38	} else {
     39		return -ENOENT;
     40	}
     41
     42	return 0;
     43}
     44
     45static int memfd_readdir(const char *path,
     46			 void *buf,
     47			 fuse_fill_dir_t filler,
     48			 off_t offset,
     49			 struct fuse_file_info *fi)
     50{
     51	if (strcmp(path, "/"))
     52		return -ENOENT;
     53
     54	filler(buf, ".", NULL, 0);
     55	filler(buf, "..", NULL, 0);
     56	filler(buf, memfd_path + 1, NULL, 0);
     57
     58	return 0;
     59}
     60
     61static int memfd_open(const char *path, struct fuse_file_info *fi)
     62{
     63	if (strcmp(path, memfd_path))
     64		return -ENOENT;
     65
     66	if ((fi->flags & 3) != O_RDONLY)
     67		return -EACCES;
     68
     69	/* force direct-IO */
     70	fi->direct_io = 1;
     71
     72	return 0;
     73}
     74
     75static int memfd_read(const char *path,
     76		      char *buf,
     77		      size_t size,
     78		      off_t offset,
     79		      struct fuse_file_info *fi)
     80{
     81	size_t len;
     82
     83	if (strcmp(path, memfd_path) != 0)
     84		return -ENOENT;
     85
     86	sleep(1);
     87
     88	len = strlen(memfd_content);
     89	if (offset < len) {
     90		if (offset + size > len)
     91			size = len - offset;
     92
     93		memcpy(buf, memfd_content + offset, size);
     94	} else {
     95		size = 0;
     96	}
     97
     98	return size;
     99}
    100
    101static struct fuse_operations memfd_ops = {
    102	.getattr	= memfd_getattr,
    103	.readdir	= memfd_readdir,
    104	.open		= memfd_open,
    105	.read		= memfd_read,
    106};
    107
    108int main(int argc, char *argv[])
    109{
    110	return fuse_main(argc, argv, &memfd_ops, NULL);
    111}