1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <zlib.h>
4 
5 #include "alloc-util.h"
6 #include "btrfs-util.h"
7 #include "qcow2-util.h"
8 #include "sparse-endian.h"
9 #include "util.h"
10 
11 #define QCOW2_MAGIC 0x514649fb
12 
13 #define QCOW2_COPIED (1ULL << 63)
14 #define QCOW2_COMPRESSED (1ULL << 62)
15 #define QCOW2_ZERO (1ULL << 0)
16 
17 typedef struct _packed_ Header {
18       be32_t magic;
19       be32_t version;
20 
21       be64_t backing_file_offset;
22       be32_t backing_file_size;
23 
24       be32_t cluster_bits;
25       be64_t size;
26       be32_t crypt_method;
27 
28       be32_t l1_size;
29       be64_t l1_table_offset;
30 
31       be64_t refcount_table_offset;
32       be32_t refcount_table_clusters;
33 
34       be32_t nb_snapshots;
35       be64_t snapshots_offset;
36 
37       /* The remainder is only present on QCOW3 */
38       be64_t incompatible_features;
39       be64_t compatible_features;
40       be64_t autoclear_features;
41 
42       be32_t refcount_order;
43       be32_t header_length;
44 } Header;
45 
46 #define HEADER_MAGIC(header) be32toh((header)->magic)
47 #define HEADER_VERSION(header) be32toh((header)->version)
48 #define HEADER_CLUSTER_BITS(header) be32toh((header)->cluster_bits)
49 #define HEADER_CLUSTER_SIZE(header) (1ULL << HEADER_CLUSTER_BITS(header))
50 #define HEADER_L2_BITS(header) (HEADER_CLUSTER_BITS(header) - 3)
51 #define HEADER_SIZE(header) be64toh((header)->size)
52 #define HEADER_CRYPT_METHOD(header) be32toh((header)->crypt_method)
53 #define HEADER_L1_SIZE(header) be32toh((header)->l1_size)
54 #define HEADER_L2_SIZE(header) (HEADER_CLUSTER_SIZE(header)/sizeof(uint64_t))
55 #define HEADER_L1_TABLE_OFFSET(header) be64toh((header)->l1_table_offset)
56 
HEADER_HEADER_LENGTH(const Header * h)57 static uint32_t HEADER_HEADER_LENGTH(const Header *h) {
58         if (HEADER_VERSION(h) < 3)
59                 return offsetof(Header, incompatible_features);
60 
61         return be32toh(h->header_length);
62 }
63 
copy_cluster(int sfd,uint64_t soffset,int dfd,uint64_t doffset,uint64_t cluster_size,void * buffer)64 static int copy_cluster(
65                 int sfd, uint64_t soffset,
66                 int dfd, uint64_t doffset,
67                 uint64_t cluster_size,
68                 void *buffer) {
69 
70         ssize_t l;
71         int r;
72 
73         r = btrfs_clone_range(sfd, soffset, dfd, doffset, cluster_size);
74         if (r >= 0)
75                 return r;
76 
77         l = pread(sfd, buffer, cluster_size, soffset);
78         if (l < 0)
79                 return -errno;
80         if ((uint64_t) l != cluster_size)
81                 return -EIO;
82 
83         l = pwrite(dfd, buffer, cluster_size, doffset);
84         if (l < 0)
85                 return -errno;
86         if ((uint64_t) l != cluster_size)
87                 return -EIO;
88 
89         return 0;
90 }
91 
decompress_cluster(int sfd,uint64_t soffset,int dfd,uint64_t doffset,uint64_t compressed_size,uint64_t cluster_size,void * buffer1,void * buffer2)92 static int decompress_cluster(
93                 int sfd, uint64_t soffset,
94                 int dfd, uint64_t doffset,
95                 uint64_t compressed_size,
96                 uint64_t cluster_size,
97                 void *buffer1,
98                 void *buffer2) {
99 
100         _cleanup_free_ void *large_buffer = NULL;
101         z_stream s = {};
102         uint64_t sz;
103         ssize_t l;
104         int r;
105 
106         if (compressed_size > cluster_size) {
107                 /* The usual cluster buffer doesn't suffice, let's
108                  * allocate a larger one, temporarily */
109 
110                 large_buffer = malloc(compressed_size);
111                 if (!large_buffer)
112                         return -ENOMEM;
113 
114                 buffer1 = large_buffer;
115         }
116 
117         l = pread(sfd, buffer1, compressed_size, soffset);
118         if (l < 0)
119                 return -errno;
120         if ((uint64_t) l != compressed_size)
121                 return -EIO;
122 
123         s.next_in = buffer1;
124         s.avail_in = compressed_size;
125         s.next_out = buffer2;
126         s.avail_out = cluster_size;
127 
128         r = inflateInit2(&s, -12);
129         if (r != Z_OK)
130                 return -EIO;
131 
132         r = inflate(&s, Z_FINISH);
133         sz = (uint8_t*) s.next_out - (uint8_t*) buffer2;
134         inflateEnd(&s);
135         if (r != Z_STREAM_END || sz != cluster_size)
136                 return -EIO;
137 
138         l = pwrite(dfd, buffer2, cluster_size, doffset);
139         if (l < 0)
140                 return -errno;
141         if ((uint64_t) l != cluster_size)
142                 return -EIO;
143 
144         return 0;
145 }
146 
normalize_offset(const Header * header,uint64_t p,uint64_t * ret,bool * compressed,uint64_t * compressed_size)147 static int normalize_offset(
148                 const Header *header,
149                 uint64_t p,
150                 uint64_t *ret,
151                 bool *compressed,
152                 uint64_t *compressed_size) {
153 
154         uint64_t q;
155 
156         q = be64toh(p);
157 
158         if (q & QCOW2_COMPRESSED) {
159                 uint64_t sz, csize_shift, csize_mask;
160 
161                 if (!compressed)
162                         return -EOPNOTSUPP;
163 
164                 csize_shift = 64 - 2 - (HEADER_CLUSTER_BITS(header) - 8);
165                 csize_mask = (1ULL << (HEADER_CLUSTER_BITS(header) - 8)) - 1;
166                 sz = (((q >> csize_shift) & csize_mask) + 1) * 512 - (q & 511);
167                 q &= ((1ULL << csize_shift) - 1);
168 
169                 if (compressed_size)
170                         *compressed_size = sz;
171 
172                 *compressed = true;
173 
174         } else {
175                 if (compressed)  {
176                         *compressed = false;
177                         *compressed_size = 0;
178                 }
179 
180                 if (q & QCOW2_ZERO) {
181                         /* We make no distinction between zero blocks and holes */
182                         *ret = 0;
183                         return 0;
184                 }
185 
186                 q &= ~QCOW2_COPIED;
187         }
188 
189         *ret = q;
190         return q > 0;  /* returns positive if not a hole */
191 }
192 
verify_header(const Header * header)193 static int verify_header(const Header *header) {
194         assert(header);
195 
196         if (HEADER_MAGIC(header) != QCOW2_MAGIC)
197                 return -EBADMSG;
198 
199         if (!IN_SET(HEADER_VERSION(header), 2, 3))
200                 return -EOPNOTSUPP;
201 
202         if (HEADER_CRYPT_METHOD(header) != 0)
203                 return -EOPNOTSUPP;
204 
205         if (HEADER_CLUSTER_BITS(header) < 9) /* 512K */
206                 return -EBADMSG;
207 
208         if (HEADER_CLUSTER_BITS(header) > 21) /* 2MB */
209                 return -EBADMSG;
210 
211         if (HEADER_SIZE(header) % HEADER_CLUSTER_SIZE(header) != 0)
212                 return -EBADMSG;
213 
214         if (HEADER_L1_SIZE(header) > 32*1024*1024) /* 32MB */
215                 return -EBADMSG;
216 
217         if (HEADER_VERSION(header) == 3) {
218 
219                 if (header->incompatible_features != 0)
220                         return -EOPNOTSUPP;
221 
222                 if (HEADER_HEADER_LENGTH(header) < sizeof(Header))
223                         return -EBADMSG;
224         }
225 
226         return 0;
227 }
228 
qcow2_convert(int qcow2_fd,int raw_fd)229 int qcow2_convert(int qcow2_fd, int raw_fd) {
230         _cleanup_free_ void *buffer1 = NULL, *buffer2 = NULL;
231         _cleanup_free_ be64_t *l1_table = NULL, *l2_table = NULL;
232         uint64_t sz, i;
233         Header header;
234         ssize_t l;
235         int r;
236 
237         l = pread(qcow2_fd, &header, sizeof(header), 0);
238         if (l < 0)
239                 return -errno;
240         if (l != sizeof(header))
241                 return -EIO;
242 
243         r = verify_header(&header);
244         if (r < 0)
245                 return r;
246 
247         l1_table = new(be64_t, HEADER_L1_SIZE(&header));
248         if (!l1_table)
249                 return -ENOMEM;
250 
251         l2_table = malloc(HEADER_CLUSTER_SIZE(&header));
252         if (!l2_table)
253                 return -ENOMEM;
254 
255         buffer1 = malloc(HEADER_CLUSTER_SIZE(&header));
256         if (!buffer1)
257                 return -ENOMEM;
258 
259         buffer2 = malloc(HEADER_CLUSTER_SIZE(&header));
260         if (!buffer2)
261                 return -ENOMEM;
262 
263         /* Empty the file if it exists, we rely on zero bits */
264         if (ftruncate(raw_fd, 0) < 0)
265                 return -errno;
266 
267         if (ftruncate(raw_fd, HEADER_SIZE(&header)) < 0)
268                 return -errno;
269 
270         sz = sizeof(uint64_t) * HEADER_L1_SIZE(&header);
271         l = pread(qcow2_fd, l1_table, sz, HEADER_L1_TABLE_OFFSET(&header));
272         if (l < 0)
273                 return -errno;
274         if ((uint64_t) l != sz)
275                 return -EIO;
276 
277         for (i = 0; i < HEADER_L1_SIZE(&header); i ++) {
278                 uint64_t l2_begin, j;
279 
280                 r = normalize_offset(&header, l1_table[i], &l2_begin, NULL, NULL);
281                 if (r < 0)
282                         return r;
283                 if (r == 0)
284                         continue;
285 
286                 l = pread(qcow2_fd, l2_table, HEADER_CLUSTER_SIZE(&header), l2_begin);
287                 if (l < 0)
288                         return -errno;
289                 if ((uint64_t) l != HEADER_CLUSTER_SIZE(&header))
290                         return -EIO;
291 
292                 for (j = 0; j < HEADER_L2_SIZE(&header); j++) {
293                         uint64_t data_begin, p, compressed_size;
294                         bool compressed;
295 
296                         p = ((i << HEADER_L2_BITS(&header)) + j) << HEADER_CLUSTER_BITS(&header);
297 
298                         r = normalize_offset(&header, l2_table[j], &data_begin, &compressed, &compressed_size);
299                         if (r < 0)
300                                 return r;
301                         if (r == 0)
302                                 continue;
303 
304                         if (compressed)
305                                 r = decompress_cluster(
306                                                 qcow2_fd, data_begin,
307                                                 raw_fd, p,
308                                                 compressed_size, HEADER_CLUSTER_SIZE(&header),
309                                                 buffer1, buffer2);
310                         else
311                                 r = copy_cluster(
312                                                 qcow2_fd, data_begin,
313                                                 raw_fd, p,
314                                                 HEADER_CLUSTER_SIZE(&header), buffer1);
315                         if (r < 0)
316                                 return r;
317                 }
318         }
319 
320         return 0;
321 }
322 
qcow2_detect(int fd)323 int qcow2_detect(int fd) {
324         be32_t id;
325         ssize_t l;
326 
327         l = pread(fd, &id, sizeof(id), 0);
328         if (l < 0)
329                 return -errno;
330         if (l != sizeof(id))
331                 return -EIO;
332 
333         return htobe32(QCOW2_MAGIC) == id;
334 }
335