summaryrefslogtreecommitdiffstats
path: root/tests/fuzz/ext2fs_image_read_write_fuzzer.cc
blob: 8aa0cb8459ad2cc0664a2ffa840b594617c6b390 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// #define USE_FLAGS
// #define DUMP_SUPER
// #define SAVE_FS_IMAGE

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <linux/memfd.h>
#include <fuzzer/FuzzedDataProvider.h>

#include "ext2fs/ext2fs.h"
extern "C" {
#include "e2p/e2p.h"
#include "support/print_fs_flags.h"
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {

  const char *progname = "ext2fs_image_read_write_fuzzer";
  add_error_table(&et_ext2_error_table);

  enum FuzzerType {
    ext2fsImageBitmapRead,
    ext2fsImageInodeRead,
    ext2fsImageSuperRead,
    ext2fsImageBitmapWrite,
    ext2fsImageInodeWrite,
    ext2fsImageSuperWrite,
    kMaxValue = ext2fsImageSuperWrite
  };

  FuzzedDataProvider stream(data, size);
  const FuzzerType f = stream.ConsumeEnum<FuzzerType>();
  int flags = stream.ConsumeIntegral<int>();
#ifndef USE_FLAGS
  flags = 0;
#endif

  static const char* fname = "/tmp/ext2_test_file";

  // Write our data to a temp file.
#ifdef SAVE_FS_IMAGE
  int fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0644);
#else
  int fd = syscall(SYS_memfd_create, fname, 0);
#endif
  std::vector<char> buffer = stream.ConsumeRemainingBytes<char>();
  write(fd, buffer.data(), buffer.size());

  std::string fspath("/proc/self/fd/" + std::to_string(fd));

  ext2_filsys fs;
#ifdef USE_FLAGS
  printf("Flags: 0x%08x ", flags);
  print_fs_flags(stdout, flags);
  flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
#endif
  errcode_t retval = ext2fs_open(
      fspath.c_str(),
      flags | EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0,
      unix_io_manager,
      &fs);

  if (retval) {
    com_err(progname, retval, "while trying to open file system");
  } else {
#ifdef DUMP_SUPER
    list_super2(fs->super, stdout);
#endif
    printf("FuzzerType: %d\n", (int) f);
    switch (f) {
      case ext2fsImageBitmapRead: {
        retval = ext2fs_image_bitmap_read(fs, fd, 0);
        if (retval)
          com_err(progname, retval, "while trying to read image bitmap");
        break;
      }
      case ext2fsImageInodeRead: {
        retval = ext2fs_image_inode_read(fs, fd, 0);
        if (retval)
          com_err(progname, retval, "while trying to read image inode");
        break;
      }
      case ext2fsImageSuperRead: {
        retval = ext2fs_image_super_read(fs, fd, 0);
        if (retval)
          com_err(progname, retval, "while trying to read image superblock");
        break;
      }
      case ext2fsImageBitmapWrite: {
        retval = ext2fs_image_bitmap_write(fs, fd, 0);
        if (retval)
          com_err(progname, retval, "while trying to write image bitmap");
        break;
      }
      case ext2fsImageInodeWrite: {
        retval = ext2fs_image_inode_write(fs, fd, 0);
        if (retval)
          com_err(progname, retval, "while trying to write image inode");
        break;
      }
      case ext2fsImageSuperWrite: {
        retval = ext2fs_image_super_write(fs, fd, 0);
        if (retval)
          com_err(progname, retval, "while trying to write image superblock");
        break;
      }
      default: {
        assert(false);
      }
    }
    ext2fs_close(fs);
  }
  close(fd);

  return 0;
}