lin
2025-08-14 dae8bad597b6607a449b32bf76c523423f7720ed
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
// Copyright 2018 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
 
// imagegen generates syz_mount_image/syz_read_part_table calls from disk images.
package main
 
import (
   "bytes"
   "encoding/hex"
   "flag"
   "fmt"
   "io/ioutil"
   "os"
)
 
type Segment struct {
   offset int
   data   []byte
}
 
func main() {
   flagV := flag.Bool("v", false, "verbose output")
   flagImage := flag.String("image", "", "image file")
   flagSkip := flag.Int("skip", 32, "min zero bytes to skip")
   flagAlign := flag.Int("align", 32, "non-zero block alignment")
   flagFS := flag.String("fs", "", "filesystem")
   flag.Parse()
   data, err := ioutil.ReadFile(*flagImage)
   if err != nil {
       fmt.Fprintf(os.Stderr, "failed to read input file: %v\n", err)
       os.Exit(1)
   }
   data0 := data
   zeros := make([]byte, *flagAlign+*flagSkip)
   var segs []Segment
   offset := 0
   for len(data) != 0 {
       pos := bytes.Index(data, zeros)
       if pos == -1 {
           segs = append(segs, Segment{offset, data})
           break
       }
       pos = (pos + *flagAlign - 1) & ^(*flagAlign - 1)
       if pos != 0 {
           segs = append(segs, Segment{offset, data[:pos]})
       }
       for pos < len(data) && data[pos] == 0 {
           pos++
       }
       pos = pos & ^(*flagAlign - 1)
       offset += pos
       data = data[pos:]
   }
   totalData := 0
   for _, seg := range segs {
       totalData += len(seg.data)
   }
   fmt.Fprintf(os.Stderr, "image size: %v, segments: %v, data: %v\n",
       len(data0), len(segs), totalData)
   if *flagV {
       for i, seg := range segs {
           next := len(data0)
           if i != len(segs)-1 {
               next = segs[i+1].offset
           }
           skip := next - seg.offset - len(seg.data)
           fmt.Fprintf(os.Stderr, "segment: %8v-%8v [%8v] -%8v\n",
               seg.offset, seg.offset+len(seg.data), len(seg.data), skip)
       }
   }
   restored := make([]byte, len(data0))
   for _, seg := range segs {
       copy(restored[seg.offset:], seg.data)
   }
   if !bytes.Equal(data0, restored) {
       fmt.Fprintf(os.Stderr, "restored data differs!\n")
       os.Exit(1)
   }
   if *flagFS == "part" {
       fmt.Printf(`syz_read_part_table(0x%x, 0x%x, &(0x7f0000000200)=[`,
           len(data0), len(segs))
       addr := 0x7f0000010000
       for i, seg := range segs {
           if i != 0 {
               fmt.Printf(", ")
           }
           fmt.Printf(`{&(0x%x)="%v", 0x%x, 0x%x}`,
               addr, hex.EncodeToString(seg.data), len(seg.data), seg.offset)
           addr = (addr + len(seg.data) + 0xff) & ^0xff
       }
       fmt.Printf("])\n")
   } else {
       syscallSuffix := *flagFS
       if syscallSuffix == "ext2" || syscallSuffix == "ext3" {
           syscallSuffix = "ext4"
       }
       fmt.Printf(`syz_mount_image$%v(&(0x7f0000000000)='%v\x00', &(0x7f0000000100)='./file0\x00',`+
           ` 0x%x, 0x%x, &(0x7f0000000200)=[`,
           syscallSuffix, *flagFS, len(data0), len(segs))
       addr := 0x7f0000010000
       for i, seg := range segs {
           if i != 0 {
               fmt.Printf(", ")
           }
           fmt.Printf(`{&(0x%x)="%v", 0x%x, 0x%x}`,
               addr, hex.EncodeToString(seg.data), len(seg.data), seg.offset)
           addr = (addr + len(seg.data) + 0xff) & ^0xff
       }
       fmt.Printf("], 0x0, &(0x%x))\n", addr)
   }
}