1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2013 Juniper Networks, Inc. 5 * Copyright (c) 2022-2024 Klara, Inc. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "opt_tarfs.h" 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/buf.h> 34 #include <sys/conf.h> 35 #include <sys/fcntl.h> 36 #include <sys/libkern.h> 37 #include <sys/limits.h> 38 #include <sys/lock.h> 39 #include <sys/malloc.h> 40 #include <sys/mount.h> 41 #include <sys/mutex.h> 42 #include <sys/namei.h> 43 #include <sys/priv.h> 44 #include <sys/proc.h> 45 #include <sys/queue.h> 46 #include <sys/sbuf.h> 47 #include <sys/stat.h> 48 #include <sys/uio.h> 49 #include <sys/vnode.h> 50 51 #include <vm/vm_param.h> 52 53 #include <geom/geom.h> 54 #include <geom/geom_vfs.h> 55 56 #include <fs/tarfs/tarfs.h> 57 #include <fs/tarfs/tarfs_dbg.h> 58 59 CTASSERT(ZERO_REGION_SIZE >= TARFS_BLOCKSIZE); 60 61 struct ustar_header { 62 char name[100]; /* File name */ 63 char mode[8]; /* Mode flags */ 64 char uid[8]; /* User id */ 65 char gid[8]; /* Group id */ 66 char size[12]; /* Size */ 67 char mtime[12]; /* Modified time */ 68 char checksum[8]; /* Checksum */ 69 char typeflag[1]; /* Type */ 70 char linkname[100]; /* "old format" stops here */ 71 char magic[6]; /* POSIX UStar "ustar\0" indicator */ 72 char version[2]; /* POSIX UStar version "00" */ 73 char uname[32]; /* User name */ 74 char gname[32]; /* Group name */ 75 char major[8]; /* Device major number */ 76 char minor[8]; /* Device minor number */ 77 char prefix[155]; /* Path prefix */ 78 char _pad[12]; 79 }; 80 81 CTASSERT(sizeof(struct ustar_header) == TARFS_BLOCKSIZE); 82 83 #define TAR_EOF ((size_t)-1) 84 85 #define TAR_TYPE_FILE '0' 86 #define TAR_TYPE_HARDLINK '1' 87 #define TAR_TYPE_SYMLINK '2' 88 #define TAR_TYPE_CHAR '3' 89 #define TAR_TYPE_BLOCK '4' 90 #define TAR_TYPE_DIRECTORY '5' 91 #define TAR_TYPE_FIFO '6' 92 #define TAR_TYPE_CONTIG '7' 93 #define TAR_TYPE_GLOBAL_EXTHDR 'g' 94 #define TAR_TYPE_EXTHDR 'x' 95 #define TAR_TYPE_GNU_SPARSE 'S' 96 97 #define USTAR_MAGIC (uint8_t []){ 'u', 's', 't', 'a', 'r', 0 } 98 #define USTAR_VERSION (uint8_t []){ '0', '0' } 99 #define GNUTAR_MAGIC (uint8_t []){ 'u', 's', 't', 'a', 'r', ' ' } 100 #define GNUTAR_VERSION (uint8_t []){ ' ', '\x0' } 101 102 #define DEFDIRMODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 103 104 MALLOC_DEFINE(M_TARFSMNT, "tarfs mount", "tarfs mount structures"); 105 MALLOC_DEFINE(M_TARFSNODE, "tarfs node", "tarfs node structures"); 106 107 static vfs_mount_t tarfs_mount; 108 static vfs_unmount_t tarfs_unmount; 109 static vfs_root_t tarfs_root; 110 static vfs_statfs_t tarfs_statfs; 111 static vfs_fhtovp_t tarfs_fhtovp; 112 113 static const char *tarfs_opts[] = { 114 "as", "from", "gid", "mode", "uid", "verify", 115 NULL 116 }; 117 118 /* 119 * Reads a len-width signed octal number from strp. Returns 0 on success 120 * and non-zero on error. 121 */ 122 static int 123 tarfs_str2octal(const char *strp, size_t len, int64_t *num) 124 { 125 int64_t val; 126 size_t idx; 127 int sign; 128 129 idx = 0; 130 if (strp[idx] == '-') { 131 sign = -1; 132 idx++; 133 } else { 134 sign = 1; 135 } 136 137 val = 0; 138 for (; idx < len && strp[idx] != '\0' && strp[idx] != ' '; idx++) { 139 if (strp[idx] < '0' || strp[idx] > '7') 140 return (EINVAL); 141 val <<= 3; 142 val += strp[idx] - '0'; 143 if (val > INT64_MAX / 8) 144 return (ERANGE); 145 } 146 147 *num = val * sign; 148 return (0); 149 } 150 151 /* 152 * Reads a len-byte extended numeric value from strp. The first byte has 153 * bit 7 set to indicate the format; the remaining 7 bits + the (len - 1) 154 * bytes that follow form a big-endian signed two's complement binary 155 * number. Returns 0 on success and non-zero on error; 156 */ 157 static int 158 tarfs_str2base256(const char *strp, size_t len, int64_t *num) 159 { 160 int64_t val; 161 size_t idx; 162 163 KASSERT(strp[0] & 0x80, ("not an extended numeric value")); 164 165 /* Sign-extend the first byte */ 166 if ((strp[0] & 0x40) != 0) 167 val = (int64_t)-1; 168 else 169 val = 0; 170 val <<= 6; 171 val |= (strp[0] & 0x3f); 172 173 /* Read subsequent bytes */ 174 for (idx = 1; idx < len; idx++) { 175 val <<= 8; 176 val |= (0xff & (int64_t)strp[idx]); 177 if (val > INT64_MAX / 256 || val < INT64_MIN / 256) 178 return (ERANGE); 179 } 180 181 *num = val; 182 return (0); 183 } 184 185 /* 186 * Read a len-byte numeric field from strp. If bit 7 of the first byte it 187 * set, assume an extended numeric value (signed two's complement); 188 * otherwise, assume a signed octal value. 189 */ 190 static int 191 tarfs_str2int64(const char *strp, size_t len, int64_t *num) 192 { 193 if (len < 1) 194 return (EINVAL); 195 if ((strp[0] & 0x80) != 0) 196 return (tarfs_str2base256(strp, len, num)); 197 return (tarfs_str2octal(strp, len, num)); 198 } 199 200 /* 201 * Verifies the checksum of a header. Returns true if the checksum is 202 * valid, false otherwise. 203 */ 204 static boolean_t 205 tarfs_checksum(struct ustar_header *hdrp) 206 { 207 const unsigned char *ptr; 208 int64_t checksum, hdrsum; 209 210 if (tarfs_str2int64(hdrp->checksum, sizeof(hdrp->checksum), &hdrsum) != 0) { 211 TARFS_DPF(CHECKSUM, "%s: invalid header checksum \"%.*s\"\n", 212 __func__, (int)sizeof(hdrp->checksum), hdrp->checksum); 213 return (false); 214 } 215 TARFS_DPF(CHECKSUM, "%s: header checksum \"%.*s\" = %#lo\n", __func__, 216 (int)sizeof(hdrp->checksum), hdrp->checksum, hdrsum); 217 218 checksum = 0; 219 for (ptr = (const unsigned char *)hdrp; 220 ptr < (const unsigned char *)hdrp->checksum; ptr++) 221 checksum += *ptr; 222 for (; 223 ptr < (const unsigned char *)hdrp->typeflag; ptr++) 224 checksum += 0x20; 225 for (; 226 ptr < (const unsigned char *)(hdrp + 1); ptr++) 227 checksum += *ptr; 228 TARFS_DPF(CHECKSUM, "%s: calc unsigned checksum %#lo\n", __func__, 229 checksum); 230 if (hdrsum == checksum) 231 return (true); 232 233 /* 234 * Repeat test with signed bytes, some older formats use a broken 235 * form of the calculation 236 */ 237 checksum = 0; 238 for (ptr = (const unsigned char *)hdrp; 239 ptr < (const unsigned char *)&hdrp->checksum; ptr++) 240 checksum += *((const signed char *)ptr); 241 for (; 242 ptr < (const unsigned char *)&hdrp->typeflag; ptr++) 243 checksum += 0x20; 244 for (; 245 ptr < (const unsigned char *)(hdrp + 1); ptr++) 246 checksum += *((const signed char *)ptr); 247 TARFS_DPF(CHECKSUM, "%s: calc signed checksum %#lo\n", __func__, 248 checksum); 249 if (hdrsum == checksum) 250 return (true); 251 252 return (false); 253 } 254 255 256 /* 257 * Looks up a path in the tarfs node tree. 258 * 259 * - If the path exists, stores a pointer to the corresponding tarfs_node 260 * in retnode and a pointer to its parent in retparent. 261 * 262 * - If the path does not exist, but create_dirs is true, creates ancestor 263 * directories and returns NULL in retnode and the parent in retparent. 264 * 265 * - If the path does not exist and create_dirs is false, stops at the 266 * first missing path name component. 267 * 268 * - In all cases, on return, endp and sepp point to the beginning and 269 * end, respectively, of the last-processed path name component. 270 * 271 * - Returns 0 if the node was found, ENOENT if it was not, and some other 272 * positive errno value on failure. 273 */ 274 static int 275 tarfs_lookup_path(struct tarfs_mount *tmp, char *name, size_t namelen, 276 char **endp, char **sepp, struct tarfs_node **retparent, 277 struct tarfs_node **retnode, boolean_t create_dirs) 278 { 279 struct componentname cn = { }; 280 struct tarfs_node *parent, *tnp; 281 char *sep; 282 size_t len; 283 int error; 284 boolean_t do_lookup; 285 286 MPASS(name != NULL && namelen != 0); 287 288 do_lookup = true; 289 error = 0; 290 parent = tnp = tmp->root; 291 if (tnp == NULL) 292 panic("%s: root node not yet created", __func__); 293 294 TARFS_DPF(LOOKUP, "%s: full path: %.*s\n", __func__, 295 (int)namelen, name); 296 297 sep = NULL; 298 for (;;) { 299 /* skip leading slash(es) */ 300 while (name[0] == '/' && namelen > 0) 301 name++, namelen--; 302 303 /* did we reach the end? */ 304 if (namelen == 0 || name[0] == '\0') { 305 name = do_lookup ? NULL : cn.cn_nameptr; 306 namelen = do_lookup ? 0 : cn.cn_namelen; 307 break; 308 } 309 310 /* we're not at the end, so we must be in a directory */ 311 if (tnp != NULL && tnp->type != VDIR) { 312 TARFS_DPF(LOOKUP, "%s: %.*s is not a directory\n", __func__, 313 (int)tnp->namelen, tnp->name); 314 error = ENOTDIR; 315 break; 316 } 317 318 /* locate the next separator */ 319 for (sep = name, len = 0; 320 *sep != '\0' && *sep != '/' && len < namelen; 321 sep++, len++) 322 /* nothing */ ; 323 324 /* check for . and .. */ 325 if (name[0] == '.' && len == 1) { 326 name += len; 327 namelen -= len; 328 continue; 329 } 330 if (name[0] == '.' && name[1] == '.' && len == 2) { 331 if (tnp == tmp->root) { 332 error = EINVAL; 333 break; 334 } 335 tnp = parent; 336 parent = tnp->parent; 337 cn.cn_nameptr = tnp->name; 338 cn.cn_namelen = tnp->namelen; 339 do_lookup = true; 340 TARFS_DPF(LOOKUP, "%s: back to %.*s/\n", __func__, 341 (int)tnp->namelen, tnp->name); 342 name += len; 343 namelen -= len; 344 continue; 345 } 346 347 /* create parent if necessary */ 348 if (!do_lookup) { 349 TARFS_DPF(ALLOC, "%s: creating %.*s\n", __func__, 350 (int)cn.cn_namelen, cn.cn_nameptr); 351 error = tarfs_alloc_node(tmp, cn.cn_nameptr, 352 cn.cn_namelen, VDIR, -1, 0, tmp->mtime, 0, 0, 353 DEFDIRMODE, 0, NULL, NODEV, parent, &tnp); 354 if (error != 0) 355 break; 356 } 357 358 parent = tnp; 359 tnp = NULL; 360 cn.cn_nameptr = name; 361 cn.cn_namelen = len; 362 TARFS_DPF(LOOKUP, "%s: looking up %.*s in %.*s/\n", __func__, 363 (int)cn.cn_namelen, cn.cn_nameptr, 364 (int)parent->namelen, parent->name); 365 if (do_lookup) { 366 tnp = tarfs_lookup_node(parent, NULL, &cn); 367 if (tnp == NULL) { 368 do_lookup = false; 369 if (!create_dirs) { 370 error = ENOENT; 371 break; 372 } 373 } 374 } 375 name += cn.cn_namelen; 376 namelen -= cn.cn_namelen; 377 } 378 379 TARFS_DPF(LOOKUP, "%s: parent %p node %p\n", __func__, parent, tnp); 380 381 if (retparent) 382 *retparent = parent; 383 if (retnode) 384 *retnode = tnp; 385 if (endp) { 386 if (namelen > 0) 387 *endp = name; 388 else 389 *endp = NULL; 390 } 391 if (sepp) 392 *sepp = sep; 393 return (error); 394 } 395 396 /* 397 * Frees a tarfs_mount structure and everything it references. 398 */ 399 static void 400 tarfs_free_mount(struct tarfs_mount *tmp) 401 { 402 struct mount *mp; 403 struct tarfs_node *tnp, *tnp_next; 404 405 MPASS(tmp != NULL); 406 407 TARFS_DPF(ALLOC, "%s: Freeing mount structure %p\n", __func__, tmp); 408 409 TARFS_DPF(ALLOC, "%s: freeing tarfs_node structures\n", __func__); 410 TAILQ_FOREACH_SAFE(tnp, &tmp->allnodes, entries, tnp_next) { 411 tarfs_free_node(tnp); 412 } 413 414 (void)tarfs_io_fini(tmp); 415 416 TARFS_DPF(ALLOC, "%s: deleting unr header\n", __func__); 417 delete_unrhdr(tmp->ino_unr); 418 mp = tmp->vfs; 419 mp->mnt_data = NULL; 420 421 TARFS_DPF(ALLOC, "%s: freeing structure\n", __func__); 422 free(tmp, M_TARFSMNT); 423 } 424 425 /* 426 * Processes the tar file header at block offset blknump and allocates and 427 * populates a tarfs_node structure for the file it describes. Updated 428 * blknump to point to the next unread tar file block, or TAR_EOF if EOF 429 * is reached. Returns 0 on success or EOF and a positive errno value on 430 * failure. 431 */ 432 static int 433 tarfs_alloc_one(struct tarfs_mount *tmp, size_t *blknump) 434 { 435 char block[TARFS_BLOCKSIZE]; 436 struct ustar_header *hdrp = (struct ustar_header *)block; 437 struct sbuf *namebuf = NULL; 438 char *exthdr = NULL, *name = NULL, *link = NULL; 439 size_t blknum = *blknump; 440 int64_t num; 441 int endmarker = 0; 442 char *namep, *sep; 443 struct tarfs_node *parent, *tnp, *other; 444 size_t namelen = 0, linklen = 0, realsize = 0, sz; 445 ssize_t res; 446 dev_t rdev; 447 gid_t gid; 448 mode_t mode; 449 time_t mtime; 450 uid_t uid; 451 long major = -1, minor = -1; 452 unsigned int flags = 0; 453 int error; 454 boolean_t sparse = false; 455 456 again: 457 /* read next header */ 458 res = tarfs_io_read_buf(tmp, false, block, 459 TARFS_BLOCKSIZE * blknum, TARFS_BLOCKSIZE); 460 if (res < 0) { 461 error = -res; 462 goto bad; 463 } else if (res < TARFS_BLOCKSIZE) { 464 goto eof; 465 } 466 blknum++; 467 468 /* check for end marker */ 469 if (memcmp(block, zero_region, TARFS_BLOCKSIZE) == 0) { 470 if (endmarker++) { 471 if (exthdr != NULL) { 472 TARFS_DPF(IO, "%s: orphaned extended header at %zu\n", 473 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 474 free(exthdr, M_TEMP); 475 } 476 TARFS_DPF(IO, "%s: end of archive at %zu\n", __func__, 477 TARFS_BLOCKSIZE * blknum); 478 tmp->nblocks = blknum; 479 *blknump = TAR_EOF; 480 return (0); 481 } 482 goto again; 483 } 484 485 /* verify magic */ 486 if (memcmp(hdrp->magic, USTAR_MAGIC, sizeof(USTAR_MAGIC)) == 0 && 487 memcmp(hdrp->version, USTAR_VERSION, sizeof(USTAR_VERSION)) == 0) { 488 /* POSIX */ 489 } else if (memcmp(hdrp->magic, GNUTAR_MAGIC, sizeof(GNUTAR_MAGIC)) == 0 && 490 memcmp(hdrp->magic, GNUTAR_MAGIC, sizeof(GNUTAR_MAGIC)) == 0) { 491 TARFS_DPF(ALLOC, "%s: GNU tar format at %zu\n", __func__, 492 TARFS_BLOCKSIZE * (blknum - 1)); 493 error = EFTYPE; 494 goto bad; 495 } else { 496 TARFS_DPF(ALLOC, "%s: unsupported TAR format at %zu\n", 497 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 498 error = EINVAL; 499 goto bad; 500 } 501 502 /* verify checksum */ 503 if (!tarfs_checksum(hdrp)) { 504 TARFS_DPF(ALLOC, "%s: header checksum failed at %zu\n", 505 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 506 error = EINVAL; 507 goto bad; 508 } 509 510 /* get standard attributes */ 511 if (tarfs_str2int64(hdrp->mode, sizeof(hdrp->mode), &num) != 0 || 512 num < 0 || num > (S_IFMT|ALLPERMS)) { 513 TARFS_DPF(ALLOC, "%s: invalid file mode at %zu\n", 514 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 515 mode = S_IRUSR; 516 } else { 517 mode = num & ALLPERMS; 518 } 519 if (tarfs_str2int64(hdrp->uid, sizeof(hdrp->uid), &num) != 0 || 520 num < 0 || num > UID_MAX) { 521 TARFS_DPF(ALLOC, "%s: invalid UID at %zu\n", 522 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 523 uid = tmp->root->uid; 524 mode &= ~S_ISUID; 525 } else { 526 uid = num; 527 } 528 if (tarfs_str2int64(hdrp->gid, sizeof(hdrp->gid), &num) != 0 || 529 num < 0 || num > GID_MAX) { 530 TARFS_DPF(ALLOC, "%s: invalid GID at %zu\n", 531 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 532 gid = tmp->root->gid; 533 mode &= ~S_ISGID; 534 } else { 535 gid = num; 536 } 537 if (tarfs_str2int64(hdrp->size, sizeof(hdrp->size), &num) != 0 || 538 num < 0) { 539 TARFS_DPF(ALLOC, "%s: invalid size at %zu\n", 540 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 541 error = EINVAL; 542 goto bad; 543 } 544 sz = num; 545 if (tarfs_str2int64(hdrp->mtime, sizeof(hdrp->mtime), &num) != 0) { 546 TARFS_DPF(ALLOC, "%s: invalid modification time at %zu\n", 547 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 548 error = EINVAL; 549 goto bad; 550 } 551 mtime = num; 552 rdev = NODEV; 553 TARFS_DPF(ALLOC, "%s: [%c] %zu @%jd %o %d:%d\n", __func__, 554 hdrp->typeflag[0], sz, (intmax_t)mtime, mode, uid, gid); 555 556 /* global extended header? */ 557 if (hdrp->typeflag[0] == TAR_TYPE_GLOBAL_EXTHDR) { 558 TARFS_DPF(ALLOC, "%s: %zu-byte global extended header at %zu\n", 559 __func__, sz, TARFS_BLOCKSIZE * (blknum - 1)); 560 goto skip; 561 } 562 563 /* extended header? */ 564 if (hdrp->typeflag[0] == TAR_TYPE_EXTHDR) { 565 if (exthdr != NULL) { 566 TARFS_DPF(IO, "%s: multiple extended headers at %zu\n", 567 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 568 error = EFTYPE; 569 goto bad; 570 } 571 /* read the contents of the exthdr */ 572 TARFS_DPF(ALLOC, "%s: %zu-byte extended header at %zu\n", 573 __func__, sz, TARFS_BLOCKSIZE * (blknum - 1)); 574 exthdr = malloc(sz, M_TEMP, M_WAITOK); 575 res = tarfs_io_read_buf(tmp, false, exthdr, 576 TARFS_BLOCKSIZE * blknum, sz); 577 if (res < 0) { 578 error = -res; 579 goto bad; 580 } 581 if (res < sz) { 582 goto eof; 583 } 584 blknum += TARFS_SZ2BLKS(res); 585 /* XXX TODO: refactor this parser */ 586 char *line = exthdr; 587 while (line < exthdr + sz) { 588 char *eol, *key, *value, *sep; 589 size_t len = strtoul(line, &sep, 10); 590 if (len == 0 || sep == line || *sep != ' ') { 591 TARFS_DPF(ALLOC, "%s: exthdr syntax error\n", 592 __func__); 593 error = EINVAL; 594 goto bad; 595 } 596 if ((uintptr_t)line + len < (uintptr_t)line || 597 line + len > exthdr + sz) { 598 TARFS_DPF(ALLOC, "%s: exthdr overflow\n", 599 __func__); 600 error = EINVAL; 601 goto bad; 602 } 603 eol = line + len - 1; 604 *eol = '\0'; 605 line += len; 606 key = sep + 1; 607 sep = strchr(key, '='); 608 if (sep == NULL) { 609 TARFS_DPF(ALLOC, "%s: exthdr syntax error\n", 610 __func__); 611 error = EINVAL; 612 goto bad; 613 } 614 *sep = '\0'; 615 value = sep + 1; 616 TARFS_DPF(ALLOC, "%s: exthdr %s=%s\n", __func__, 617 key, value); 618 if (strcmp(key, "path") == 0) { 619 name = value; 620 namelen = eol - value; 621 } else if (strcmp(key, "linkpath") == 0) { 622 link = value; 623 linklen = eol - value; 624 } else if (strcmp(key, "GNU.sparse.major") == 0) { 625 sparse = true; 626 major = strtol(value, &sep, 10); 627 if (sep != eol) { 628 printf("exthdr syntax error\n"); 629 error = EINVAL; 630 goto bad; 631 } 632 } else if (strcmp(key, "GNU.sparse.minor") == 0) { 633 sparse = true; 634 minor = strtol(value, &sep, 10); 635 if (sep != eol) { 636 printf("exthdr syntax error\n"); 637 error = EINVAL; 638 goto bad; 639 } 640 } else if (strcmp(key, "GNU.sparse.name") == 0) { 641 sparse = true; 642 name = value; 643 namelen = eol - value; 644 if (namelen == 0) { 645 printf("exthdr syntax error\n"); 646 error = EINVAL; 647 goto bad; 648 } 649 } else if (strcmp(key, "GNU.sparse.realsize") == 0) { 650 sparse = true; 651 realsize = strtoul(value, &sep, 10); 652 if (sep != eol) { 653 printf("exthdr syntax error\n"); 654 error = EINVAL; 655 goto bad; 656 } 657 } else if (strcmp(key, "SCHILY.fflags") == 0) { 658 flags |= tarfs_strtofflags(value, &sep); 659 if (sep != eol) { 660 printf("exthdr syntax error\n"); 661 error = EINVAL; 662 goto bad; 663 } 664 } 665 } 666 goto again; 667 } 668 669 /* sparse file consistency checks */ 670 if (sparse) { 671 TARFS_DPF(ALLOC, "%s: %s: sparse %ld.%ld (%zu bytes)\n", __func__, 672 name, major, minor, realsize); 673 if (major != 1 || minor != 0 || name == NULL || realsize == 0 || 674 hdrp->typeflag[0] != TAR_TYPE_FILE) { 675 TARFS_DPF(ALLOC, "%s: invalid sparse format\n", __func__); 676 error = EINVAL; 677 goto bad; 678 } 679 } 680 681 /* file name */ 682 if (name == NULL) { 683 if (hdrp->prefix[0] != '\0') { 684 namebuf = sbuf_new_auto(); 685 sbuf_printf(namebuf, "%.*s/%.*s", 686 (int)sizeof(hdrp->prefix), hdrp->prefix, 687 (int)sizeof(hdrp->name), hdrp->name); 688 sbuf_finish(namebuf); 689 name = sbuf_data(namebuf); 690 namelen = sbuf_len(namebuf); 691 } else { 692 name = hdrp->name; 693 namelen = strnlen(hdrp->name, sizeof(hdrp->name)); 694 } 695 } 696 697 error = tarfs_lookup_path(tmp, name, namelen, &namep, 698 &sep, &parent, &tnp, true); 699 if (error != 0) { 700 TARFS_DPF(ALLOC, "%s: failed to look up %.*s\n", __func__, 701 (int)namelen, name); 702 error = EINVAL; 703 goto bad; 704 } 705 if (tnp != NULL) { 706 if (hdrp->typeflag[0] == TAR_TYPE_DIRECTORY) { 707 /* XXX set attributes? */ 708 goto skip; 709 } 710 TARFS_DPF(ALLOC, "%s: duplicate file %.*s\n", __func__, 711 (int)namelen, name); 712 error = EINVAL; 713 goto bad; 714 } 715 switch (hdrp->typeflag[0]) { 716 case TAR_TYPE_DIRECTORY: 717 error = tarfs_alloc_node(tmp, namep, sep - namep, VDIR, 718 0, 0, mtime, uid, gid, mode, flags, NULL, 0, 719 parent, &tnp); 720 break; 721 case TAR_TYPE_FILE: 722 error = tarfs_alloc_node(tmp, namep, sep - namep, VREG, 723 blknum * TARFS_BLOCKSIZE, sz, mtime, uid, gid, mode, 724 flags, NULL, 0, parent, &tnp); 725 if (error == 0 && sparse) { 726 error = tarfs_load_blockmap(tnp, realsize); 727 } 728 break; 729 case TAR_TYPE_HARDLINK: 730 if (link == NULL) { 731 link = hdrp->linkname; 732 linklen = strnlen(link, sizeof(hdrp->linkname)); 733 } 734 if (linklen == 0) { 735 TARFS_DPF(ALLOC, "%s: %.*s: link without target\n", 736 __func__, (int)namelen, name); 737 error = EINVAL; 738 goto bad; 739 } 740 error = tarfs_lookup_path(tmp, link, linklen, NULL, 741 NULL, NULL, &other, false); 742 if (error != 0 || other == NULL || 743 other->type != VREG || other->other != NULL) { 744 TARFS_DPF(ALLOC, "%s: %.*s: invalid link to %.*s\n", 745 __func__, (int)namelen, name, (int)linklen, link); 746 error = EINVAL; 747 goto bad; 748 } 749 error = tarfs_alloc_node(tmp, namep, sep - namep, VREG, 750 0, 0, 0, 0, 0, 0, 0, NULL, 0, parent, &tnp); 751 if (error == 0) { 752 tnp->other = other; 753 tnp->other->nlink++; 754 } 755 break; 756 case TAR_TYPE_SYMLINK: 757 if (link == NULL) { 758 link = hdrp->linkname; 759 linklen = strnlen(link, sizeof(hdrp->linkname)); 760 } 761 if (linklen == 0) { 762 TARFS_DPF(ALLOC, "%s: %.*s: link without target\n", 763 __func__, (int)namelen, name); 764 error = EINVAL; 765 goto bad; 766 } 767 error = tarfs_alloc_node(tmp, namep, sep - namep, VLNK, 768 0, linklen, mtime, uid, gid, mode, flags, link, 0, 769 parent, &tnp); 770 break; 771 case TAR_TYPE_BLOCK: 772 if (tarfs_str2int64(hdrp->major, sizeof(hdrp->major), &num) != 0 || 773 num < 0 || num > INT_MAX) { 774 TARFS_DPF(ALLOC, "%s: %.*s: invalid device major\n", 775 __func__, (int)namelen, name); 776 error = EINVAL; 777 goto bad; 778 } 779 major = num; 780 if (tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor), &num) != 0 || 781 num < 0 || num > INT_MAX) { 782 TARFS_DPF(ALLOC, "%s: %.*s: invalid device minor\n", 783 __func__, (int)namelen, name); 784 error = EINVAL; 785 goto bad; 786 } 787 minor = num; 788 rdev = makedev(major, minor); 789 error = tarfs_alloc_node(tmp, namep, sep - namep, VBLK, 790 0, 0, mtime, uid, gid, mode, flags, NULL, rdev, 791 parent, &tnp); 792 break; 793 case TAR_TYPE_CHAR: 794 if (tarfs_str2int64(hdrp->major, sizeof(hdrp->major), &num) != 0 || 795 num < 0 || num > INT_MAX) { 796 TARFS_DPF(ALLOC, "%s: %.*s: invalid device major\n", 797 __func__, (int)namelen, name); 798 error = EINVAL; 799 goto bad; 800 } 801 major = num; 802 if (tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor), &num) != 0 || 803 num < 0 || num > INT_MAX) { 804 TARFS_DPF(ALLOC, "%s: %.*s: invalid device minor\n", 805 __func__, (int)namelen, name); 806 error = EINVAL; 807 goto bad; 808 } 809 minor = num; 810 rdev = makedev(major, minor); 811 error = tarfs_alloc_node(tmp, namep, sep - namep, VCHR, 812 0, 0, mtime, uid, gid, mode, flags, NULL, rdev, 813 parent, &tnp); 814 break; 815 default: 816 TARFS_DPF(ALLOC, "%s: unsupported type %c for %.*s\n", 817 __func__, hdrp->typeflag[0], (int)namelen, name); 818 error = EINVAL; 819 break; 820 } 821 if (error != 0) 822 goto bad; 823 824 skip: 825 blknum += TARFS_SZ2BLKS(sz); 826 tmp->nblocks = blknum; 827 *blknump = blknum; 828 if (exthdr != NULL) { 829 free(exthdr, M_TEMP); 830 } 831 if (namebuf != NULL) { 832 sbuf_delete(namebuf); 833 } 834 return (0); 835 eof: 836 TARFS_DPF(IO, "%s: premature end of file\n", __func__); 837 error = EIO; 838 goto bad; 839 bad: 840 if (exthdr != NULL) { 841 free(exthdr, M_TEMP); 842 } 843 if (namebuf != NULL) { 844 sbuf_delete(namebuf); 845 } 846 return (error); 847 } 848 849 /* 850 * Allocates and populates the metadata structures for the tar file 851 * referenced by vp. On success, a pointer to the tarfs_mount structure 852 * is stored in tmpp. Returns 0 on success or a positive errno value on 853 * failure. 854 */ 855 static int 856 tarfs_alloc_mount(struct mount *mp, struct vnode *vp, 857 uid_t root_uid, gid_t root_gid, mode_t root_mode, 858 struct tarfs_mount **tmpp) 859 { 860 struct vattr va; 861 struct thread *td = curthread; 862 struct tarfs_mount *tmp; 863 struct tarfs_node *root; 864 size_t blknum; 865 time_t mtime; 866 int error; 867 868 KASSERT(tmpp != NULL, ("tarfs mount return is NULL")); 869 ASSERT_VOP_LOCKED(vp, __func__); 870 871 tmp = NULL; 872 873 TARFS_DPF(ALLOC, "%s: Allocating tarfs mount structure for vp %p\n", 874 __func__, vp); 875 876 /* Get source metadata */ 877 error = VOP_GETATTR(vp, &va, td->td_ucred); 878 if (error != 0) { 879 return (error); 880 } 881 VOP_UNLOCK(vp); 882 mtime = va.va_mtime.tv_sec; 883 884 mp->mnt_iosize_max = vp->v_mount->mnt_iosize_max; 885 886 /* Allocate and initialize tarfs mount structure */ 887 tmp = malloc(sizeof(*tmp), M_TARFSMNT, M_WAITOK | M_ZERO); 888 TARFS_DPF(ALLOC, "%s: Allocated mount structure\n", __func__); 889 mp->mnt_data = tmp; 890 891 mtx_init(&tmp->allnode_lock, "tarfs allnode lock", NULL, 892 MTX_DEF); 893 TAILQ_INIT(&tmp->allnodes); 894 tmp->ino_unr = new_unrhdr(TARFS_MININO, INT_MAX, &tmp->allnode_lock); 895 tmp->vp = vp; 896 tmp->vfs = mp; 897 tmp->mtime = mtime; 898 899 /* Initialize I/O layer */ 900 tmp->iosize = 1U << tarfs_ioshift; 901 error = tarfs_io_init(tmp); 902 if (error != 0) 903 goto bad; 904 905 error = tarfs_alloc_node(tmp, NULL, 0, VDIR, 0, 0, mtime, root_uid, 906 root_gid, root_mode & ALLPERMS, 0, NULL, NODEV, NULL, &root); 907 if (error != 0 || root == NULL) 908 goto bad; 909 tmp->root = root; 910 911 blknum = 0; 912 do { 913 if ((error = tarfs_alloc_one(tmp, &blknum)) != 0) { 914 printf("unsupported or corrupt tar file at %zu\n", 915 TARFS_BLOCKSIZE * blknum); 916 goto bad; 917 } 918 } while (blknum != TAR_EOF); 919 920 *tmpp = tmp; 921 922 TARFS_DPF(ALLOC, "%s: pfsmnt_root %p\n", __func__, tmp->root); 923 return (0); 924 925 bad: 926 tarfs_free_mount(tmp); 927 return (error); 928 } 929 930 /* 931 * VFS Operations. 932 */ 933 934 static int 935 tarfs_mount(struct mount *mp) 936 { 937 struct nameidata nd; 938 struct vattr va; 939 struct tarfs_mount *tmp = NULL; 940 struct thread *td = curthread; 941 struct vnode *vp; 942 char *as, *from; 943 uid_t root_uid; 944 gid_t root_gid; 945 mode_t root_mode; 946 int error, flags, aslen, len; 947 948 if (mp->mnt_flag & MNT_UPDATE) 949 return (EOPNOTSUPP); 950 951 if (vfs_filteropt(mp->mnt_optnew, tarfs_opts)) 952 return (EINVAL); 953 954 vn_lock(mp->mnt_vnodecovered, LK_SHARED | LK_RETRY); 955 error = VOP_GETATTR(mp->mnt_vnodecovered, &va, mp->mnt_cred); 956 VOP_UNLOCK(mp->mnt_vnodecovered); 957 if (error) 958 return (error); 959 960 if (mp->mnt_cred->cr_ruid != 0 || 961 vfs_scanopt(mp->mnt_optnew, "gid", "%d", &root_gid) != 1) 962 root_gid = va.va_gid; 963 if (mp->mnt_cred->cr_ruid != 0 || 964 vfs_scanopt(mp->mnt_optnew, "uid", "%d", &root_uid) != 1) 965 root_uid = va.va_uid; 966 if (mp->mnt_cred->cr_ruid != 0 || 967 vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1) 968 root_mode = va.va_mode; 969 970 error = vfs_getopt(mp->mnt_optnew, "from", (void **)&from, &len); 971 if (error != 0 || from[len - 1] != '\0') 972 return (EINVAL); 973 error = vfs_getopt(mp->mnt_optnew, "as", (void **)&as, &aslen); 974 if (error != 0 || as[aslen - 1] != '\0') 975 as = from; 976 977 /* Find the source tarball */ 978 TARFS_DPF(FS, "%s(%s%s%s, uid=%u, gid=%u, mode=%o)\n", __func__, 979 from, (as != from) ? " as " : "", (as != from) ? as : "", 980 root_uid, root_gid, root_mode); 981 flags = FREAD; 982 if (vfs_flagopt(mp->mnt_optnew, "verify", NULL, 0)) { 983 flags |= O_VERIFY; 984 } 985 NDINIT(&nd, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF, UIO_SYSSPACE, from); 986 error = namei(&nd); 987 if (error != 0) 988 return (error); 989 NDFREE_PNBUF(&nd); 990 vp = nd.ni_vp; 991 TARFS_DPF(FS, "%s: N: hold %u use %u lock 0x%x\n", __func__, 992 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 993 /* vp is now held and locked */ 994 995 /* Open the source tarball */ 996 error = vn_open_vnode(vp, flags, td->td_ucred, td, NULL); 997 if (error != 0) { 998 TARFS_DPF(FS, "%s: failed to open %s: %d\n", __func__, 999 from, error); 1000 vput(vp); 1001 goto bad; 1002 } 1003 TARFS_DPF(FS, "%s: O: hold %u use %u lock 0x%x\n", __func__, 1004 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1005 if (vp->v_type != VREG) { 1006 TARFS_DPF(FS, "%s: not a regular file\n", __func__); 1007 error = EOPNOTSUPP; 1008 goto bad_open_locked; 1009 } 1010 error = priv_check(td, PRIV_VFS_MOUNT_PERM); 1011 if (error != 0) { 1012 TARFS_DPF(FS, "%s: not permitted to mount\n", __func__); 1013 goto bad_open_locked; 1014 } 1015 if (flags & O_VERIFY) { 1016 mp->mnt_flag |= MNT_VERIFIED; 1017 } 1018 1019 /* Allocate the tarfs mount */ 1020 error = tarfs_alloc_mount(mp, vp, root_uid, root_gid, root_mode, &tmp); 1021 /* vp is now held but unlocked */ 1022 if (error != 0) { 1023 TARFS_DPF(FS, "%s: failed to mount %s: %d\n", __func__, 1024 from, error); 1025 goto bad_open_unlocked; 1026 } 1027 TARFS_DPF(FS, "%s: M: hold %u use %u lock 0x%x\n", __func__, 1028 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1029 1030 /* Unconditionally mount as read-only */ 1031 MNT_ILOCK(mp); 1032 mp->mnt_flag |= (MNT_LOCAL | MNT_RDONLY); 1033 MNT_IUNLOCK(mp); 1034 1035 vfs_getnewfsid(mp); 1036 vfs_mountedfrom(mp, as); 1037 TARFS_DPF(FS, "%s: success\n", __func__); 1038 1039 return (0); 1040 1041 bad_open_locked: 1042 /* vp must be held and locked */ 1043 TARFS_DPF(FS, "%s: L: hold %u use %u lock 0x%x\n", __func__, 1044 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1045 VOP_UNLOCK(vp); 1046 bad_open_unlocked: 1047 /* vp must be held and unlocked */ 1048 TARFS_DPF(FS, "%s: E: hold %u use %u lock 0x%x\n", __func__, 1049 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1050 (void)vn_close(vp, flags, td->td_ucred, td); 1051 bad: 1052 /* vp must be released and unlocked */ 1053 TARFS_DPF(FS, "%s: X: hold %u use %u lock 0x%x\n", __func__, 1054 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1055 return (error); 1056 } 1057 1058 /* 1059 * Unmounts a tarfs filesystem. 1060 */ 1061 static int 1062 tarfs_unmount(struct mount *mp, int mntflags) 1063 { 1064 struct thread *td = curthread; 1065 struct tarfs_mount *tmp; 1066 struct vnode *vp; 1067 int error; 1068 int flags = 0; 1069 1070 TARFS_DPF(FS, "%s: Unmounting %p\n", __func__, mp); 1071 1072 /* Handle forced unmounts */ 1073 if (mntflags & MNT_FORCE) 1074 flags |= FORCECLOSE; 1075 1076 /* Finalize all pending I/O */ 1077 error = vflush(mp, 0, flags, curthread); 1078 if (error != 0) 1079 return (error); 1080 tmp = MP_TO_TARFS_MOUNT(mp); 1081 vp = tmp->vp; 1082 1083 MPASS(vp != NULL); 1084 TARFS_DPF(FS, "%s: U: hold %u use %u lock 0x%x\n", __func__, 1085 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1086 vn_close(vp, FREAD, td->td_ucred, td); 1087 TARFS_DPF(FS, "%s: C: hold %u use %u lock 0x%x\n", __func__, 1088 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1089 tarfs_free_mount(tmp); 1090 1091 return (0); 1092 } 1093 1094 /* 1095 * Gets the root of a tarfs filesystem. Returns 0 on success or a 1096 * positive errno value on failure. 1097 */ 1098 static int 1099 tarfs_root(struct mount *mp, int flags, struct vnode **vpp) 1100 { 1101 struct vnode *nvp; 1102 int error; 1103 1104 TARFS_DPF(FS, "%s: Getting root vnode\n", __func__); 1105 1106 error = VFS_VGET(mp, TARFS_ROOTINO, LK_EXCLUSIVE, &nvp); 1107 if (error != 0) 1108 return (error); 1109 1110 nvp->v_vflag |= VV_ROOT; 1111 *vpp = nvp; 1112 return (0); 1113 } 1114 1115 /* 1116 * Gets statistics for a tarfs filesystem. Returns 0. 1117 */ 1118 static int 1119 tarfs_statfs(struct mount *mp, struct statfs *sbp) 1120 { 1121 struct tarfs_mount *tmp; 1122 1123 tmp = MP_TO_TARFS_MOUNT(mp); 1124 1125 sbp->f_bsize = TARFS_BLOCKSIZE; 1126 sbp->f_iosize = tmp->iosize; 1127 sbp->f_blocks = tmp->nblocks; 1128 sbp->f_bfree = 0; 1129 sbp->f_bavail = 0; 1130 sbp->f_files = tmp->nfiles; 1131 sbp->f_ffree = 0; 1132 1133 return (0); 1134 } 1135 1136 /* 1137 * Gets a vnode for the given inode. On success, a pointer to the vnode 1138 * is stored in vpp. Returns 0 on success or a positive errno value on 1139 * failure. 1140 */ 1141 static int 1142 tarfs_vget(struct mount *mp, ino_t ino, int lkflags, struct vnode **vpp) 1143 { 1144 struct tarfs_mount *tmp; 1145 struct tarfs_node *tnp; 1146 struct thread *td; 1147 struct vnode *vp; 1148 int error; 1149 1150 TARFS_DPF(FS, "%s: mp %p, ino %lu, lkflags %d\n", __func__, mp, ino, 1151 lkflags); 1152 1153 td = curthread; 1154 error = vfs_hash_get(mp, ino, lkflags, td, vpp, NULL, NULL); 1155 if (error != 0) 1156 return (error); 1157 1158 if (*vpp != NULL) { 1159 TARFS_DPF(FS, "%s: found hashed vnode %p\n", __func__, *vpp); 1160 return (error); 1161 } 1162 1163 TARFS_DPF(FS, "%s: no hashed vnode for inode %lu\n", __func__, ino); 1164 1165 tmp = MP_TO_TARFS_MOUNT(mp); 1166 1167 if (ino == TARFS_ZIOINO) { 1168 error = vget(tmp->znode, lkflags); 1169 if (error != 0) 1170 return (error); 1171 *vpp = tmp->znode; 1172 return (0); 1173 } 1174 1175 /* XXX Should use hash instead? */ 1176 TAILQ_FOREACH(tnp, &tmp->allnodes, entries) { 1177 if (tnp->ino == ino) 1178 break; 1179 } 1180 TARFS_DPF(FS, "%s: search of all nodes found %p\n", __func__, tnp); 1181 if (tnp == NULL) 1182 return (ENOENT); 1183 1184 (void)getnewvnode("tarfs", mp, &tarfs_vnodeops, &vp); 1185 TARFS_DPF(FS, "%s: allocated vnode\n", __func__); 1186 vp->v_data = tnp; 1187 vp->v_type = tnp->type; 1188 tnp->vnode = vp; 1189 1190 lockmgr(vp->v_vnlock, lkflags, NULL); 1191 error = insmntque(vp, mp); 1192 if (error != 0) 1193 goto bad; 1194 TARFS_DPF(FS, "%s: inserting entry into VFS hash\n", __func__); 1195 error = vfs_hash_insert(vp, ino, lkflags, td, vpp, NULL, NULL); 1196 if (error != 0 || *vpp != NULL) 1197 return (error); 1198 1199 vn_set_state(vp, VSTATE_CONSTRUCTED); 1200 *vpp = vp; 1201 return (0); 1202 1203 bad: 1204 *vpp = NULLVP; 1205 return (error); 1206 } 1207 1208 static int 1209 tarfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) 1210 { 1211 struct tarfs_node *tnp; 1212 struct tarfs_fid *tfp; 1213 struct vnode *nvp; 1214 int error; 1215 1216 tfp = (struct tarfs_fid *)fhp; 1217 MP_TO_TARFS_MOUNT(mp); 1218 if (tfp->ino < TARFS_ROOTINO || tfp->ino > INT_MAX) 1219 return (ESTALE); 1220 1221 error = VFS_VGET(mp, tfp->ino, LK_EXCLUSIVE, &nvp); 1222 if (error != 0) { 1223 *vpp = NULLVP; 1224 return (error); 1225 } 1226 tnp = VP_TO_TARFS_NODE(nvp); 1227 if (tnp->mode == 0 || 1228 tnp->gen != tfp->gen || 1229 tnp->nlink <= 0) { 1230 vput(nvp); 1231 *vpp = NULLVP; 1232 return (ESTALE); 1233 } 1234 *vpp = nvp; 1235 return (0); 1236 } 1237 1238 static struct vfsops tarfs_vfsops = { 1239 .vfs_fhtovp = tarfs_fhtovp, 1240 .vfs_mount = tarfs_mount, 1241 .vfs_root = tarfs_root, 1242 .vfs_statfs = tarfs_statfs, 1243 .vfs_unmount = tarfs_unmount, 1244 .vfs_vget = tarfs_vget, 1245 }; 1246 VFS_SET(tarfs_vfsops, tarfs, VFCF_READONLY); 1247 MODULE_VERSION(tarfs, 1); 1248 MODULE_DEPEND(tarfs, xz, 1, 1, 1); 1249