1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com) 4 */ 5 6 /* 7 * _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines 8 * that. 9 */ 10 #include <unistd.h> 11 #include <errno.h> 12 #include <string.h> 13 #include <arpa/inet.h> 14 #include <endian.h> 15 #include "cow.h" 16 #include "cow_sys.h" 17 18 #define PATH_LEN_V1 256 19 20 typedef __u32 time32_t; 21 22 struct cow_header_v1 { 23 __s32 magic; 24 __s32 version; 25 char backing_file[PATH_LEN_V1]; 26 time32_t mtime; 27 __u64 size; 28 __s32 sectorsize; 29 } __attribute__((packed)); 30 31 /* 32 * Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in 33 * case other systems have different values for MAXPATHLEN. 34 * 35 * The same must hold for V2 - we want file format compatibility, not anything 36 * else. 37 */ 38 #define PATH_LEN_V3 4096 39 #define PATH_LEN_V2 PATH_LEN_V3 40 41 struct cow_header_v2 { 42 __u32 magic; 43 __u32 version; 44 char backing_file[PATH_LEN_V2]; 45 time32_t mtime; 46 __u64 size; 47 __s32 sectorsize; 48 } __attribute__((packed)); 49 50 /* 51 * Changes from V2 - 52 * PATH_LEN_V3 as described above 53 * Explicitly specify field bit lengths for systems with different 54 * lengths for the usual C types. Not sure whether char or 55 * time_t should be changed, this can be changed later without 56 * breaking compatibility 57 * Add alignment field so that different alignments can be used for the 58 * bitmap and data 59 * Add cow_format field to allow for the possibility of different ways 60 * of specifying the COW blocks. For now, the only value is 0, 61 * for the traditional COW bitmap. 62 * Move the backing_file field to the end of the header. This allows 63 * for the possibility of expanding it into the padding required 64 * by the bitmap alignment. 65 * The bitmap and data portions of the file will be aligned as specified 66 * by the alignment field. This is to allow COW files to be 67 * put on devices with restrictions on access alignments, such as 68 * /dev/raw, with a 512 byte alignment restriction. This also 69 * allows the data to be more aligned more strictly than on 70 * sector boundaries. This is needed for ubd-mmap, which needs 71 * the data to be page aligned. 72 * Fixed (finally!) the rounding bug 73 */ 74 75 /* 76 * Until Dec2005, __attribute__((packed)) was left out from the below 77 * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to 78 * align size to 8-byte alignment. This shifted all fields above (no padding 79 * was present on 32-bit, no other padding was added). 80 * 81 * However, this _can be detected_: it means that cow_format (always 0 until 82 * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise 83 * impossible to find 4 zeros. -bb */ 84 85 struct cow_header_v3 { 86 __u32 magic; 87 __u32 version; 88 __u32 mtime; 89 __u64 size; 90 __u32 sectorsize; 91 __u32 alignment; 92 __u32 cow_format; 93 char backing_file[PATH_LEN_V3]; 94 } __attribute__((packed)); 95 96 /* This is the broken layout used by some 64-bit binaries. */ 97 struct cow_header_v3_broken { 98 __u32 magic; 99 __u32 version; 100 __s64 mtime; 101 __u64 size; 102 __u32 sectorsize; 103 __u32 alignment; 104 __u32 cow_format; 105 char backing_file[PATH_LEN_V3]; 106 }; 107 108 /* COW format definitions - for now, we have only the usual COW bitmap */ 109 #define COW_BITMAP 0 110 111 union cow_header { 112 struct cow_header_v1 v1; 113 struct cow_header_v2 v2; 114 struct cow_header_v3 v3; 115 struct cow_header_v3_broken v3_b; 116 }; 117 118 #define COW_MAGIC 0x4f4f4f4d /* MOOO */ 119 #define COW_VERSION 3 120 121 #define DIV_ROUND(x, len) (((x) + (len) - 1) / (len)) 122 #define ROUND_UP(x, align) DIV_ROUND(x, align) * (align) 123 124 void cow_sizes(int version, __u64 size, int sectorsize, int align, 125 int bitmap_offset, unsigned long *bitmap_len_out, 126 int *data_offset_out) 127 { 128 if (version < 3) { 129 *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); 130 131 *data_offset_out = bitmap_offset + *bitmap_len_out; 132 *data_offset_out = (*data_offset_out + sectorsize - 1) / 133 sectorsize; 134 *data_offset_out *= sectorsize; 135 } 136 else { 137 *bitmap_len_out = DIV_ROUND(size, sectorsize); 138 *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8); 139 140 *data_offset_out = bitmap_offset + *bitmap_len_out; 141 *data_offset_out = ROUND_UP(*data_offset_out, align); 142 } 143 } 144 145 static int absolutize(char *to, int size, char *from) 146 { 147 char save_cwd[256], *slash; 148 int remaining; 149 150 if (getcwd(save_cwd, sizeof(save_cwd)) == NULL) { 151 cow_printf("absolutize : unable to get cwd - errno = %d\n", 152 errno); 153 return -1; 154 } 155 slash = strrchr(from, '/'); 156 if (slash != NULL) { 157 *slash = '\0'; 158 if (chdir(from)) { 159 *slash = '/'; 160 cow_printf("absolutize : Can't cd to '%s' - " 161 "errno = %d\n", from, errno); 162 return -1; 163 } 164 *slash = '/'; 165 if (getcwd(to, size) == NULL) { 166 cow_printf("absolutize : unable to get cwd of '%s' - " 167 "errno = %d\n", from, errno); 168 return -1; 169 } 170 remaining = size - strlen(to); 171 if (strlen(slash) + 1 > remaining) { 172 cow_printf("absolutize : unable to fit '%s' into %d " 173 "chars\n", from, size); 174 return -1; 175 } 176 strcat(to, slash); 177 } 178 else { 179 if (strlen(save_cwd) + 1 + strlen(from) + 1 > size) { 180 cow_printf("absolutize : unable to fit '%s' into %d " 181 "chars\n", from, size); 182 return -1; 183 } 184 strcpy(to, save_cwd); 185 strcat(to, "/"); 186 strcat(to, from); 187 } 188 if (chdir(save_cwd)) { 189 cow_printf("absolutize : Can't cd to '%s' - " 190 "errno = %d\n", save_cwd, errno); 191 return -1; 192 } 193 return 0; 194 } 195 196 int write_cow_header(char *cow_file, int fd, char *backing_file, 197 int sectorsize, int alignment, unsigned long long *size) 198 { 199 struct cow_header_v3 *header; 200 unsigned long modtime; 201 int err; 202 203 err = cow_seek_file(fd, 0); 204 if (err < 0) { 205 cow_printf("write_cow_header - lseek failed, err = %d\n", -err); 206 goto out; 207 } 208 209 err = -ENOMEM; 210 header = cow_malloc(sizeof(*header)); 211 if (header == NULL) { 212 cow_printf("write_cow_header - failed to allocate COW V3 " 213 "header\n"); 214 goto out; 215 } 216 header->magic = htobe32(COW_MAGIC); 217 header->version = htobe32(COW_VERSION); 218 219 err = -EINVAL; 220 if (strlen(backing_file) > sizeof(header->backing_file) - 1) { 221 /* Below, %zd is for a size_t value */ 222 cow_printf("Backing file name \"%s\" is too long - names are " 223 "limited to %zd characters\n", backing_file, 224 sizeof(header->backing_file) - 1); 225 goto out_free; 226 } 227 228 if (absolutize(header->backing_file, sizeof(header->backing_file), 229 backing_file)) 230 goto out_free; 231 232 err = os_file_modtime(header->backing_file, &modtime); 233 if (err < 0) { 234 cow_printf("write_cow_header - backing file '%s' mtime " 235 "request failed, err = %d\n", header->backing_file, 236 -err); 237 goto out_free; 238 } 239 240 err = cow_file_size(header->backing_file, size); 241 if (err < 0) { 242 cow_printf("write_cow_header - couldn't get size of " 243 "backing file '%s', err = %d\n", 244 header->backing_file, -err); 245 goto out_free; 246 } 247 248 header->mtime = htobe32(modtime); 249 header->size = htobe64(*size); 250 header->sectorsize = htobe32(sectorsize); 251 header->alignment = htobe32(alignment); 252 header->cow_format = COW_BITMAP; 253 254 err = cow_write_file(fd, header, sizeof(*header)); 255 if (err != sizeof(*header)) { 256 cow_printf("write_cow_header - write of header to " 257 "new COW file '%s' failed, err = %d\n", cow_file, 258 -err); 259 goto out_free; 260 } 261 err = 0; 262 out_free: 263 cow_free(header); 264 out: 265 return err; 266 } 267 268 int file_reader(__u64 offset, char *buf, int len, void *arg) 269 { 270 int fd = *((int *) arg); 271 272 return pread(fd, buf, len, offset); 273 } 274 275 /* XXX Need to sanity-check the values read from the header */ 276 277 int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, 278 __u32 *version_out, char **backing_file_out, 279 time_t *mtime_out, unsigned long long *size_out, 280 int *sectorsize_out, __u32 *align_out, 281 int *bitmap_offset_out) 282 { 283 union cow_header *header; 284 char *file; 285 int err, n; 286 unsigned long version, magic; 287 288 header = cow_malloc(sizeof(*header)); 289 if (header == NULL) { 290 cow_printf("read_cow_header - Failed to allocate header\n"); 291 return -ENOMEM; 292 } 293 err = -EINVAL; 294 n = (*reader)(0, (char *) header, sizeof(*header), arg); 295 if (n < offsetof(typeof(header->v1), backing_file)) { 296 cow_printf("read_cow_header - short header\n"); 297 goto out; 298 } 299 300 magic = header->v1.magic; 301 if (magic == COW_MAGIC) 302 version = header->v1.version; 303 else if (magic == be32toh(COW_MAGIC)) 304 version = be32toh(header->v1.version); 305 /* No error printed because the non-COW case comes through here */ 306 else goto out; 307 308 *version_out = version; 309 310 if (version == 1) { 311 if (n < sizeof(header->v1)) { 312 cow_printf("read_cow_header - failed to read V1 " 313 "header\n"); 314 goto out; 315 } 316 *mtime_out = header->v1.mtime; 317 *size_out = header->v1.size; 318 *sectorsize_out = header->v1.sectorsize; 319 *bitmap_offset_out = sizeof(header->v1); 320 *align_out = *sectorsize_out; 321 file = header->v1.backing_file; 322 } 323 else if (version == 2) { 324 if (n < sizeof(header->v2)) { 325 cow_printf("read_cow_header - failed to read V2 " 326 "header\n"); 327 goto out; 328 } 329 *mtime_out = be32toh(header->v2.mtime); 330 *size_out = be64toh(header->v2.size); 331 *sectorsize_out = be32toh(header->v2.sectorsize); 332 *bitmap_offset_out = sizeof(header->v2); 333 *align_out = *sectorsize_out; 334 file = header->v2.backing_file; 335 } 336 /* This is very subtle - see above at union cow_header definition */ 337 else if (version == 3 && (*((int*)header->v3.backing_file) != 0)) { 338 if (n < sizeof(header->v3)) { 339 cow_printf("read_cow_header - failed to read V3 " 340 "header\n"); 341 goto out; 342 } 343 *mtime_out = be32toh(header->v3.mtime); 344 *size_out = be64toh(header->v3.size); 345 *sectorsize_out = be32toh(header->v3.sectorsize); 346 *align_out = be32toh(header->v3.alignment); 347 if (*align_out == 0) { 348 cow_printf("read_cow_header - invalid COW header, " 349 "align == 0\n"); 350 } 351 *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); 352 file = header->v3.backing_file; 353 } 354 else if (version == 3) { 355 cow_printf("read_cow_header - broken V3 file with" 356 " 64-bit layout - recovering content.\n"); 357 358 if (n < sizeof(header->v3_b)) { 359 cow_printf("read_cow_header - failed to read V3 " 360 "header\n"); 361 goto out; 362 } 363 364 /* 365 * this was used until Dec2005 - 64bits are needed to represent 366 * 2038+. I.e. we can safely do this truncating cast. 367 * 368 * Additionally, we must use be32toh() instead of be64toh(), since 369 * the program used to use the former (tested - I got mtime 370 * mismatch "0 vs whatever"). 371 * 372 * Ever heard about bug-to-bug-compatibility ? ;-) */ 373 *mtime_out = (time32_t) be32toh(header->v3_b.mtime); 374 375 *size_out = be64toh(header->v3_b.size); 376 *sectorsize_out = be32toh(header->v3_b.sectorsize); 377 *align_out = be32toh(header->v3_b.alignment); 378 if (*align_out == 0) { 379 cow_printf("read_cow_header - invalid COW header, " 380 "align == 0\n"); 381 } 382 *bitmap_offset_out = ROUND_UP(sizeof(header->v3_b), *align_out); 383 file = header->v3_b.backing_file; 384 } 385 else { 386 cow_printf("read_cow_header - invalid COW version\n"); 387 goto out; 388 } 389 err = -ENOMEM; 390 *backing_file_out = cow_strdup(file); 391 if (*backing_file_out == NULL) { 392 cow_printf("read_cow_header - failed to allocate backing " 393 "file\n"); 394 goto out; 395 } 396 err = 0; 397 out: 398 cow_free(header); 399 return err; 400 } 401 402 int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, 403 int alignment, int *bitmap_offset_out, 404 unsigned long *bitmap_len_out, int *data_offset_out) 405 { 406 unsigned long long size, offset; 407 char zero = 0; 408 int err; 409 410 err = write_cow_header(cow_file, fd, backing_file, sectorsize, 411 alignment, &size); 412 if (err) 413 goto out; 414 415 *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); 416 cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out, 417 bitmap_len_out, data_offset_out); 418 419 offset = *data_offset_out + size - sizeof(zero); 420 err = cow_seek_file(fd, offset); 421 if (err < 0) { 422 cow_printf("cow bitmap lseek failed : err = %d\n", -err); 423 goto out; 424 } 425 426 /* 427 * does not really matter how much we write it is just to set EOF 428 * this also sets the entire COW bitmap 429 * to zero without having to allocate it 430 */ 431 err = cow_write_file(fd, &zero, sizeof(zero)); 432 if (err != sizeof(zero)) { 433 cow_printf("Write of bitmap to new COW file '%s' failed, " 434 "err = %d\n", cow_file, -err); 435 if (err >= 0) 436 err = -EINVAL; 437 goto out; 438 } 439 440 return 0; 441 out: 442 return err; 443 } 444