Giter Club home page Giter Club logo

fscq's Introduction

FSCQ

FSCQ is a file system written and verified in the Coq proof assistant.

Unmaintained research prototype

Warning: the FSCQ software is not maintained. FSCQ's core is verified in Coq, but FSCQ also includes components written in Haskell for interacting with FUSE, and depends on FUSE and Haskell bindings for FUSE, none of which are verified. The unverified portions are likely to have bugs, and we do not recommend that anyone use the FSCQ research prototype in practice.

Although the overall software is not maintained, we would be interested in hearing from others that discover issues with the verified portions of FSCQ.

Branches

There are several branches in this repository, corresponding to different FSCQ-related projects.

  • The master branch contains the source code for the DFSCQ file system, roughly corresponding to the SOSP 2017 paper.

  • The security branch contains the source code for the SFSCQ file system and the DiskSec sealed block framework, roughly corresponding to the OSDI 2018 paper.

fscq's People

Contributors

achlipala avatar akonradi avatar armael avatar atalay-ileri avatar daniel-ziegler avatar davidlazar avatar haogang avatar jbangert avatar jellevandenhooff avatar kaashoek avatar tchajed avatar tomjridge avatar xiw avatar zeldovich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fscq's Issues

Time support

Some applications depend on file system support for accurate (or at least monotonic) modification times in stat.

Advice on refreshing the ocaml extraction target?

Hi, very nice project!

Next week I will be at the 11th MirageOS retreat; my project for the week would be to try to look at FSCQ and see how hard it would be to extract it to OCaml and package it as a MirageOS-compatible library.
I've only quickly looked at the makefile/build instructions currently; it looked to me that there there is some existing setup for OCaml extraction but that ExtractOcaml.v might be outdated?

More generally speaking, I wondered if you'd have any relevant advice that could be helpful for the task :-).
I'm also interested on any information on the structure of the development / what are the entrypoints of the Coq library / the API that should be exposed or not, if you have :-).

sync() fails to persist a new directory entry

Does fscq support sync() system call?
If so, there seems to be a bug which makes sync fail to persist new directory entries. This correspondingly causes an inconsistent file system state after a crash.

Below describes the test case that triggers the bug.

  1. After mounting an empty fscq image:
$ mkdir /tmp/fscqmnt
$ ./fscq/src/fscq empty.img -f -o big_writes,atomic_o_trunc,use_ino /tmp/fscqmnt
  1. Run the PoC which creates a directory, calls sync, then crashes fscq daemon.
    PoC:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    chdir("/tmp/fscqmnt");
    system("ls");
    system("ls");
    system("ls");
    system("ls");
    system("ls");
    system("tree");

    syscall(SYS_mkdir, "foo", 0777);
    syscall(SYS_sync);
    system("killall -9 fscq"); // crash fscq

    return 0;
}
  1. Re-mount the image on another directory
$ mkdir /tmp/fscqmnt2
$ ./fscq/src/fscq empty.img -f -o big_writes,atomic_o_trunc,use_ino /tmp/fscqmnt2
  1. Check inconsistency (foo is not persisted)
$ ls /tmp/fscqmnt2
$ ls /tmp/fscqmnt2
$ ls /tmp/fscqmnt2
$ tree /tmp/fscqmnt2
/tmp/fscqmnt2

0 directories, 0 files

Potential crash consistency bug - fsync fails to persist directory entry

Hi, our team at SSLab, Georgia Tech is fuzz testing various file systems for crash consistency bugs. While testing FSCQ, we found a potential crash consistency bug. Could you take a look at the test case we have?

  1. Mount an empty image:
$ mkdir /tmp/fscqmnt
$ ./fscq/src/fscq empty.img -f -o big_writes,atomic_o_trunc,use_ino /tmp/fscqmnt
  1. Compile and run the test case:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
        chdir("/tmp/fscqmnt");
        system("ls");
        system("ls");
        system("ls");
        system("ls");
        system("ls");
        system("tree");

        unsigned char buf[8192] = { 0, };
        int fd_root = syscall(SYS_open, ".", O_DIRECTORY, 0);
        int fd_foo = syscall(SYS_open, "./foo", O_CREAT | O_RDWR, 0777);
        syscall(SYS_fsync, fd_foo);
        syscall(SYS_mkdir, "./A", 0777);
        syscall(SYS_ftruncate, fd_foo, 5595);
        syscall(SYS_pwrite64, fd_foo, buf, 4000, 1303);
        syscall(SYS_fsync, fd_root);

        system("killall -9 fscq"); // crash fscq
        return 0;
}
  1. Re-mount the image on another directory
$ mkdir /tmp/fscqmnt2
$ ./fscq/src/fscq empty.img -f -o big_writes,atomic_o_trunc,use_ino /tmp/fscqmnt2
  1. Check inconsistency (directory A is missing)
$ tree /tmp/fscqmnt2
fscqmnt2
└── foo

0 directories, 1 file

[Description]
If we make a directory "./A" and fsync the root directory ".", the directory entry A is persisted on disk, and is shown after a crash.
However, as in the test case above, if we mkdir A, then perform ftruncate and pwrite on the file descriptor of another file "./foo", fsync'ing the root directory fails to persist directory A.

Any opinion on this?

Thank you,
-Seulbae

fdatasync not working as expected on fscq?

Hi, our team at SSLab, Georgia Tech is testing the crash safety property of fscq and we found that fdatasync is not working as expected maybe? Following is the test case:

  1. Mount an empty image
mkdir -p mptr1
<path-to-fscq-src>/fscq empty.img -f -o big_writes,atomic_o_trunc,use_ino mptr1
  1. Compile and run the test case
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
        chdir("mptr1");
        system("ls");
        system("ls");
        system("ls");
        system("ls");
        system("ls");
        system("tree");
 
        int rv;
 
        unsigned char buf[8192] = { 0 };
        memset(buf, 'a', 8192);
 
        int fd_foo = syscall(SYS_open, "foo", O_CREAT | O_RDWR, 0777);
        printf("fd: %d\n",  fd_foo);
 
        int fd_mntpnt = syscall(SYS_open, ".", O_DIRECTORY, 0);
        printf("root fd: %d\n", fd_mntpnt);
 
        rv = syscall(SYS_fsync, fd_mntpnt);
        printf("fsync mntpnt: %d\n", rv);
 
        rv = syscall(SYS_write, fd_foo, buf, 4000);
        printf("write: %d\n", rv);
 
        rv = syscall(SYS_fdatasync, fd_foo);
        printf("fdatasync: %d\n", rv);
 
        system("killall -9 fscq"); // crash fscq
        return 0;
}

Output of the test case should be:

.

0 directories, 0 files
fd: 3
root fd: 4
fsync mntpnt: 0
write: 4000
fdatasync: 0

Based on the return code of fsync, write, and fdatasync, file foo should be there with 4000 a in its content.

  1. Re-mount the image on another directory
<path-to-fscq-src>/src/fscq empty.img -f -o big_writes,atomic_o_trunc,use_ino mptr2
  1. Check inconsistency: file foo is empty
tree mptr2
mptr2
└── foo

0 directories, 1 file

cat mptr2/foo
<nothing returns back>

wc -c mptr2/foo
0 mptr2/foo

[System Setup]
I am seeing this issue on the master branch of the repo although I see this issue in the sosp17 branch as well. I am using Ubuntu 16.04 with 4.4.0 kernel and compiled fscq with coqc 8.8.1 and ghc 8.0.1.

Let me know if you need further information. Thank you!

Renaming a directory to a non-empty directory results in EIO

On 27c4078, running

#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>

int main() {
  int err;

  mkdir("a", 0700);
  mkdir("b", 0700);
  mkdir("b/0",0);
  errno = 0;
  err = rename("a","b");
  if (err < 0) {
    printf("rename error: %s\n",strerror(errno));
    return 1;
  }

  return 0;
}

prints rename error: Input/output error when the rename call should set errno to ENOTEMPTY or EEXIST. This issue is probably related to #3 and approximately as unlikely cause significant issues for applications.

truncate extension sometimes extends with file names instead of zeros

On an empty file system built from 27c4078, running

#include <unistd.h>
#include <fcntl.h>

int main() {
  close(creat("spaaaaaace"));
  truncate("spaaaaaace",10);

  return 0;
}

results in a file, spaaaaaace, which contains the text spaaaaaace instead of 10 null bytes. For applications which expect POSIX, OS X, Linux, or BSD behavior when using truncate to extend files, this unexpected data can result in incorrectly formatted files.

Multiuser/permissions support

Some security properties of some systems are, at least partially, reliant on file system support for rwx permissions for users, groups, and 'other'. These features are often used in conjunction with multiuser access to a single mounted file system and FS enforcement of user permission policy.

ftruncate to grow a file does not allocate blocks

The implementation of ftruncate calls the wrong function in AsyncFS.v, setting the inode size blindly without allocating new blocks if the size grows. Here's a bug that results from implicitly using block 0 for the new blocks:

test-case.c:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main() {
  chdir("/tmp/fscqmnt");

  unsigned char buf[2] = { 1, 2 };
  int fd_foo = open("foo", O_CREAT | O_RDWR, 0777);
  ftruncate(fd_foo, 5);
  pwrite(fd_foo, buf, 2, 0);

  int fd_bar = open("bar", O_CREAT | O_RDWR, 0777);
  ftruncate(fd_bar, 5);

  unsigned char rbuf[2];
  pread(fd_bar, &rbuf, 2, 0);
  // BUG: this outputs "bar: 01 02" instead of the expected "bar: 00 00"
  printf("bar: %02d %02d\n", (int) rbuf[0], (int) rbuf[1]);
  close(fd_bar);

  // just to demonstrate what gets written
  sync();

  return 0;
}

bug.sh:

#!/bin/bash

set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
FSCQ=$HOME/fscq

start_fscq() {
  "$FSCQ"/src/fscq "$FSCQ"/src/disk.img -f -o big_writes,atomic_o_trunc,use_ino "$1" &
  sleep 0.5
}

unmount_fscq() {
  fusermount -u "$1"
}

mkdir -p /tmp/fscqmnt
gcc "$DIR"/test-case.c -o "$DIR"/test-case
if [ ! -f /tmp/empty.img ]; then
  "$FSCQ"/src/mkfs /tmp/empty.img
fi
cp /tmp/empty.img "$FSCQ"/src/disk.img

start_fscq /tmp/fscqmnt
"$DIR"/test-case
tree -s /tmp/fscqmnt
unmount_fscq /tmp/fscqmnt

Running bug.sh (or compiling and running test-case.c after mounting FSCQ to /tmp/fscqmnt) produces bar: 01 02, since foo and bar point to the same disk blocks.

Potential logic bug: renaming an emptied directory fails

Hi.
While testing FSCQ, I came across this potential logic bug:
Directory A is considered "not empty" after an inode A/foo is created then unlinked, thus prohibiting any other directory from being renamed to A.

To test, first create an empty disk image, and mount it at /tmp/mnt.
Then, compile and run the following PoC:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char *argv[])
{
    chdir("/tmp/mnt");

    syscall(SYS_mkdir, "A");
    int fd_A = syscall(SYS_open, "A", O_DIRECTORY, 0);
    int fd_foo = syscall(SYS_open, "A/foo", O_CREAT | O_RDWR, 0777);
    syscall(SYS_unlink, "A/foo");

    syscall(SYS_fsync, fd_foo);
    syscall(SYS_fsync, fd_A);

    syscall(SYS_mkdir, "B");
    int ret = syscall(SYS_rename, "B", "A");
    if (ret < 0)
        printf("rename B A failed: %d (%s)\n", errno, strerror(errno));
    return 0;
}

The output is rename B A failed: 39 (Directory not empty), even though the directory A is emptied and explicitly fsynced.

$ tree mnt
mnt
├── A
└── B

2 directories, 0 files

Symlink support

Many applications depend on file system support for symlinks.

Subdirectories do not increment parent directory's link count

When a subdirectory is created, the parent directory's link count increases by 1 (for ..) on typical POSIX-like file systems. Using 27c4078, a directory's link count remains 2 when subdirectories are created:

# mkdir foo
# stat foo
  File: ‘foo’
  Size: 4096        Blocks: 1          IO Block: 4096   directory
Device: 29h/41d Inode: 8           Links: 2
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 1970-01-01 01:00:00.000000000 +0100
Modify: 1970-01-01 01:00:00.000000000 +0100
Change: 1970-01-01 01:00:00.000000000 +0100
 Birth: -
# mkdir foo/bar
# stat foo
  File: ‘foo’
  Size: 4096        Blocks: 1          IO Block: 4096   directory
Device: 29h/41d Inode: 8           Links: 2
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 1970-01-01 01:00:00.000000000 +0100
Modify: 1970-01-01 01:00:00.000000000 +0100
Change: 1970-01-01 01:00:00.000000000 +0100
 Birth: -

While many POSIX foreign file systems do not obey directory link count invariants, it can be useful for programs (e.g. find) which perform many directory traversals.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.