Skip to content

Commit

Permalink
sys/linux: add support for reading partition tables
Browse files Browse the repository at this point in the history
  • Loading branch information
dvyukov committed Apr 1, 2018
1 parent 185ac35 commit 99e3b0a
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 38 deletions.
98 changes: 95 additions & 3 deletions executor/common_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
#include <sys/mount.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image)
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
#include <errno.h>
#include <fcntl.h>
#include <linux/loop.h>
Expand Down Expand Up @@ -802,7 +802,7 @@ static uintptr_t syz_genetlink_get_family_id(uintptr_t name)
}
#endif

#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image)
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
extern unsigned long long procid;

struct fs_image_segment {
Expand All @@ -825,7 +825,99 @@ struct fs_image_segment {
#elif defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__)
#define SYZ_memfd_create 360
#endif
#endif

#if defined(SYZ_EXECUTOR) || defined(__NR_syz_read_part_table)
// syz_read_part_table(size intptr, nsegs len[segments], segments ptr[in, array[fs_image_segment]])
static uintptr_t syz_read_part_table(uintptr_t size, uintptr_t nsegs, uintptr_t segments)
{
char loopname[64], linkname[64];
int loopfd, err = 0, res = -1;
uintptr_t i, j;
// See the comment in syz_mount_image.
struct fs_image_segment* segs = (struct fs_image_segment*)segments;

if (nsegs > IMAGE_MAX_SEGMENTS)
nsegs = IMAGE_MAX_SEGMENTS;
for (i = 0; i < nsegs; i++) {
if (segs[i].size > IMAGE_MAX_SIZE)
segs[i].size = IMAGE_MAX_SIZE;
segs[i].offset %= IMAGE_MAX_SIZE;
if (segs[i].offset > IMAGE_MAX_SIZE - segs[i].size)
segs[i].offset = IMAGE_MAX_SIZE - segs[i].size;
if (size < segs[i].offset + segs[i].offset)
size = segs[i].offset + segs[i].offset;
}
if (size > IMAGE_MAX_SIZE)
size = IMAGE_MAX_SIZE;
int memfd = syscall(SYZ_memfd_create, "syz_read_part_table", 0);
if (memfd == -1) {
err = errno;
goto error;
}
if (ftruncate(memfd, size)) {
err = errno;
goto error_close_memfd;
}
for (i = 0; i < nsegs; i++) {
if (pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset) < 0) {
debug("syz_read_part_table: pwrite[%u] failed: %d\n", (int)i, errno);
}
}
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
err = errno;
goto error_close_memfd;
}
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
if (errno != EBUSY) {
err = errno;
goto error_close_loop;
}
ioctl(loopfd, LOOP_CLR_FD, 0);
usleep(1000);
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
err = errno;
goto error_close_loop;
}
}
struct loop_info64 info;
if (ioctl(loopfd, LOOP_GET_STATUS64, &info)) {
err = errno;
goto error_clear_loop;
}
#if defined(SYZ_EXECUTOR)
cover_reset(0);
#endif
info.lo_flags |= LO_FLAGS_PARTSCAN;
if (ioctl(loopfd, LOOP_SET_STATUS64, &info)) {
err = errno;
goto error_clear_loop;
}
res = 0;
// If we managed to parse some partitions, symlink them into our work dir.
for (i = 1, j = 0; i < 8; i++) {
snprintf(loopname, sizeof(loopname), "/dev/loop%llup%d", procid, (int)i);
struct stat statbuf;
if (stat(loopname, &statbuf) == 0) {
snprintf(linkname, sizeof(linkname), "./file%d", (int)j++);
symlink(loopname, linkname);
}
}
error_clear_loop:
ioctl(loopfd, LOOP_CLR_FD, 0);
error_close_loop:
close(loopfd);
error_close_memfd:
close(memfd);
error:
errno = err;
return res;
}
#endif

#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image)
//syz_mount_image(fs ptr[in, string[disk_filesystems]], dir ptr[in, filename], size intptr, nsegs len[segments], segments ptr[in, array[fs_image_segment]], flags flags[mount_flags], opts ptr[in, fs_options[vfat_options]])
//fs_image_segment {
// data ptr[in, array[int8]]
Expand Down Expand Up @@ -1827,7 +1919,7 @@ static void loop()
if (mkdir(cwdbuf, 0777))
fail("failed to mkdir");
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_fs) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
char buf[64];
snprintf(buf, sizeof(buf), "/dev/loop%llu", procid);
int loopfd = open(buf, O_RDWR);
Expand Down
25 changes: 15 additions & 10 deletions executor/syscalls_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

#if defined(__i386__) || 0
#define GOARCH "386"
#define SYZ_REVISION "7424a62ff2a634075d9352a6bf1ba14b9377cce8"
#define SYZ_REVISION "95c0c5827460dd0db116e00429bad9d3fe5778de"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1678;
unsigned syscall_count = 1679;
call_t syscalls[] = {
{"accept4", 364},
{"accept4$alg", 364},
Expand Down Expand Up @@ -1639,6 +1639,7 @@ call_t syscalls[] = {
{"syz_open_dev$vcsn", 0, (syscall_t)syz_open_dev},
{"syz_open_procfs", 0, (syscall_t)syz_open_procfs},
{"syz_open_pts", 0, (syscall_t)syz_open_pts},
{"syz_read_part_table", 0, (syscall_t)syz_read_part_table},
{"tee", 315},
{"tgkill", 270},
{"time", 13},
Expand Down Expand Up @@ -1692,11 +1693,11 @@ call_t syscalls[] = {

#if defined(__x86_64__) || 0
#define GOARCH "amd64"
#define SYZ_REVISION "f52cb963bdf72aed0f98688ac20cb16e40b3b2d3"
#define SYZ_REVISION "14883eb285af454acfe15491ef6052eed4b8d77c"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1730;
unsigned syscall_count = 1731;
call_t syscalls[] = {
{"accept", 43},
{"accept$alg", 43},
Expand Down Expand Up @@ -3381,6 +3382,7 @@ call_t syscalls[] = {
{"syz_open_dev$vcsn", 0, (syscall_t)syz_open_dev},
{"syz_open_procfs", 0, (syscall_t)syz_open_procfs},
{"syz_open_pts", 0, (syscall_t)syz_open_pts},
{"syz_read_part_table", 0, (syscall_t)syz_read_part_table},
{"tee", 276},
{"tgkill", 234},
{"time", 201},
Expand Down Expand Up @@ -3434,11 +3436,11 @@ call_t syscalls[] = {

#if defined(__arm__) || 0
#define GOARCH "arm"
#define SYZ_REVISION "3972faa5a8bbad692d1ecd42060d3a0876823259"
#define SYZ_REVISION "f64917dfdea0e40f17c49a8c12080a688ebb9a4d"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1675;
unsigned syscall_count = 1676;
call_t syscalls[] = {
{"accept", 285},
{"accept$alg", 285},
Expand Down Expand Up @@ -5070,6 +5072,7 @@ call_t syscalls[] = {
{"syz_open_dev$vcsn", 0, (syscall_t)syz_open_dev},
{"syz_open_procfs", 0, (syscall_t)syz_open_procfs},
{"syz_open_pts", 0, (syscall_t)syz_open_pts},
{"syz_read_part_table", 0, (syscall_t)syz_read_part_table},
{"tee", 342},
{"tgkill", 268},
{"timer_create", 257},
Expand Down Expand Up @@ -5121,11 +5124,11 @@ call_t syscalls[] = {

#if defined(__aarch64__) || 0
#define GOARCH "arm64"
#define SYZ_REVISION "527e225af73003b7222cbf51076b057e824248f6"
#define SYZ_REVISION "6126db2a2079d8fe161c7d1e9c6179cf9a660b2d"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1659;
unsigned syscall_count = 1660;
call_t syscalls[] = {
{"accept", 202},
{"accept$alg", 202},
Expand Down Expand Up @@ -6745,6 +6748,7 @@ call_t syscalls[] = {
{"syz_open_dev$vcsn", 0, (syscall_t)syz_open_dev},
{"syz_open_procfs", 0, (syscall_t)syz_open_procfs},
{"syz_open_pts", 0, (syscall_t)syz_open_pts},
{"syz_read_part_table", 0, (syscall_t)syz_read_part_table},
{"tee", 77},
{"tgkill", 131},
{"timer_create", 107},
Expand Down Expand Up @@ -6792,11 +6796,11 @@ call_t syscalls[] = {

#if defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__) || 0
#define GOARCH "ppc64le"
#define SYZ_REVISION "40f069e17536ef2ffed3727cb6238f8ba8d003ef"
#define SYZ_REVISION "f4f6f2409448b0704d85d908ec0968994157ae6a"
#define SYZ_PAGE_SIZE 4096
#define SYZ_NUM_PAGES 4096
#define SYZ_DATA_OFFSET 536870912
unsigned syscall_count = 1649;
unsigned syscall_count = 1650;
call_t syscalls[] = {
{"accept", 330},
{"accept$alg", 330},
Expand Down Expand Up @@ -8400,6 +8404,7 @@ call_t syscalls[] = {
{"syz_open_dev$vcsn", 0, (syscall_t)syz_open_dev},
{"syz_open_procfs", 0, (syscall_t)syz_open_procfs},
{"syz_open_pts", 0, (syscall_t)syz_open_pts},
{"syz_read_part_table", 0, (syscall_t)syz_read_part_table},
{"tee", 284},
{"tgkill", 250},
{"time", 13},
Expand Down
3 changes: 2 additions & 1 deletion pkg/csource/csource.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
}
needProcID := opts.Procs > 1 || opts.EnableCgroups
for _, c := range p.Calls {
if c.Meta.CallName == "syz_mount_image" {
if c.Meta.CallName == "syz_mount_image" ||
c.Meta.CallName == "syz_read_part_table" {
needProcID = true
}
}
Expand Down
95 changes: 92 additions & 3 deletions pkg/csource/linux_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ var commonHeaderLinux = `
#if defined(SYZ_EXECUTOR) || defined(SYZ_ENABLE_CGROUPS)
#include <sys/mount.h>
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image)
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
#include <errno.h>
#include <fcntl.h>
#include <linux/loop.h>
Expand Down Expand Up @@ -921,7 +921,7 @@ static uintptr_t syz_genetlink_get_family_id(uintptr_t name)
}
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image)
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
extern unsigned long long procid;
struct fs_image_segment {
Expand All @@ -944,7 +944,96 @@ struct fs_image_segment {
#elif defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__)
#define SYZ_memfd_create 360
#endif
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_read_part_table)
static uintptr_t syz_read_part_table(uintptr_t size, uintptr_t nsegs, uintptr_t segments)
{
char loopname[64], linkname[64];
int loopfd, err = 0, res = -1;
uintptr_t i, j;
struct fs_image_segment* segs = (struct fs_image_segment*)segments;
if (nsegs > IMAGE_MAX_SEGMENTS)
nsegs = IMAGE_MAX_SEGMENTS;
for (i = 0; i < nsegs; i++) {
if (segs[i].size > IMAGE_MAX_SIZE)
segs[i].size = IMAGE_MAX_SIZE;
segs[i].offset %= IMAGE_MAX_SIZE;
if (segs[i].offset > IMAGE_MAX_SIZE - segs[i].size)
segs[i].offset = IMAGE_MAX_SIZE - segs[i].size;
if (size < segs[i].offset + segs[i].offset)
size = segs[i].offset + segs[i].offset;
}
if (size > IMAGE_MAX_SIZE)
size = IMAGE_MAX_SIZE;
int memfd = syscall(SYZ_memfd_create, "syz_read_part_table", 0);
if (memfd == -1) {
err = errno;
goto error;
}
if (ftruncate(memfd, size)) {
err = errno;
goto error_close_memfd;
}
for (i = 0; i < nsegs; i++) {
if (pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset) < 0) {
debug("syz_read_part_table: pwrite[%u] failed: %d\n", (int)i, errno);
}
}
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
err = errno;
goto error_close_memfd;
}
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
if (errno != EBUSY) {
err = errno;
goto error_close_loop;
}
ioctl(loopfd, LOOP_CLR_FD, 0);
usleep(1000);
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
err = errno;
goto error_close_loop;
}
}
struct loop_info64 info;
if (ioctl(loopfd, LOOP_GET_STATUS64, &info)) {
err = errno;
goto error_clear_loop;
}
#if defined(SYZ_EXECUTOR)
cover_reset(0);
#endif
info.lo_flags |= LO_FLAGS_PARTSCAN;
if (ioctl(loopfd, LOOP_SET_STATUS64, &info)) {
err = errno;
goto error_clear_loop;
}
res = 0;
for (i = 1, j = 0; i < 8; i++) {
snprintf(loopname, sizeof(loopname), "/dev/loop%llup%d", procid, (int)i);
struct stat statbuf;
if (stat(loopname, &statbuf) == 0) {
snprintf(linkname, sizeof(linkname), "./file%d", (int)j++);
symlink(loopname, linkname);
}
}
error_clear_loop:
ioctl(loopfd, LOOP_CLR_FD, 0);
error_close_loop:
close(loopfd);
error_close_memfd:
close(memfd);
error:
errno = err;
return res;
}
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image)
static uintptr_t syz_mount_image(uintptr_t fs, uintptr_t dir, uintptr_t size, uintptr_t nsegs, uintptr_t segments, uintptr_t flags, uintptr_t opts)
{
char loopname[64];
Expand Down Expand Up @@ -2843,7 +2932,7 @@ static void loop()
if (mkdir(cwdbuf, 0777))
fail("failed to mkdir");
#endif
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_fs) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
#if defined(SYZ_EXECUTOR) || defined(__NR_syz_mount_image) || defined(__NR_syz_read_part_table)
char buf[64];
snprintf(buf, sizeof(buf), "/dev/loop%llu", procid);
int loopfd = open(buf, O_RDWR);
Expand Down
2 changes: 2 additions & 0 deletions pkg/host/host_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ func isSupportedSyzkall(sandbox string, c *prog.Syscall) bool {
return true
case "syz_mount_image":
return sandbox != "setuid"
case "syz_read_part_table":
return sandbox == "none" && syscall.Getuid() == 0
}
panic("unknown syzkall: " + c.Name)
}
Expand Down
7 changes: 6 additions & 1 deletion sys/linux/386.go
Original file line number Diff line number Diff line change
Expand Up @@ -23257,6 +23257,11 @@ var syscalls_386 = []*Syscall{
&ResourceType{TypeCommon: TypeCommon{TypeName: "fd_tty", FldName: "fd", TypeSize: 4}},
&FlagsType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "open_flags", FldName: "flags", TypeSize: 4}}, Vals: []uint64{0, 1, 2, 1024, 8192, 524288, 64, 16384, 65536, 128, 32768, 262144, 256, 131072, 2048, 2097152, 1052672, 512, 4194304}},
}, Ret: &ResourceType{TypeCommon: TypeCommon{TypeName: "fd_tty", FldName: "ret", TypeSize: 4, ArgDir: 1}}},
{Name: "syz_read_part_table", CallName: "syz_read_part_table", Args: []Type{
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "intptr", FldName: "size", TypeSize: 4}}},
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "len", FldName: "nsegs", TypeSize: 4}}, Buf: "segments"},
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "segments", TypeSize: 4}, Type: &ArrayType{TypeCommon: TypeCommon{TypeName: "array", IsVarlen: true}, Type: &StructType{Key: StructKey{Name: "fs_image_segment"}}}},
}},
{NR: 315, Name: "tee", CallName: "tee", Args: []Type{
&ResourceType{TypeCommon: TypeCommon{TypeName: "fd", FldName: "fdin", TypeSize: 4}},
&ResourceType{TypeCommon: TypeCommon{TypeName: "fd", FldName: "fdout", TypeSize: 4}},
Expand Down Expand Up @@ -27825,4 +27830,4 @@ var consts_386 = []ConstValue{
{Name: "bpf_insn_load_imm_dw", Value: 24},
}

const revision_386 = "7424a62ff2a634075d9352a6bf1ba14b9377cce8"
const revision_386 = "95c0c5827460dd0db116e00429bad9d3fe5778de"
Loading

0 comments on commit 99e3b0a

Please sign in to comment.