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 ((off_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, off_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 off_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 /* extended header? */ 557 if (hdrp->typeflag[0] == TAR_TYPE_GLOBAL_EXTHDR) { 558 printf("%s: unsupported global extended header at %zu\n", 559 __func__, (size_t)(TARFS_BLOCKSIZE * (blknum - 1))); 560 error = EFTYPE; 561 goto bad; 562 } 563 if (hdrp->typeflag[0] == TAR_TYPE_EXTHDR) { 564 if (exthdr != NULL) { 565 TARFS_DPF(IO, "%s: multiple extended headers at %zu\n", 566 __func__, TARFS_BLOCKSIZE * (blknum - 1)); 567 error = EFTYPE; 568 goto bad; 569 } 570 /* read the contents of the exthdr */ 571 TARFS_DPF(ALLOC, "%s: %zu-byte extended header at %zd\n", 572 __func__, sz, TARFS_BLOCKSIZE * (blknum - 1)); 573 exthdr = malloc(sz, M_TEMP, M_WAITOK); 574 res = tarfs_io_read_buf(tmp, false, exthdr, 575 TARFS_BLOCKSIZE * blknum, sz); 576 if (res < 0) { 577 error = -res; 578 goto bad; 579 } 580 if (res < sz) { 581 goto eof; 582 } 583 blknum += TARFS_SZ2BLKS(res); 584 /* XXX TODO: refactor this parser */ 585 char *line = exthdr; 586 while (line < exthdr + sz) { 587 char *eol, *key, *value, *sep; 588 size_t len = strtoul(line, &sep, 10); 589 if (len == 0 || sep == line || *sep != ' ') { 590 TARFS_DPF(ALLOC, "%s: exthdr syntax error\n", 591 __func__); 592 error = EINVAL; 593 goto bad; 594 } 595 if ((uintptr_t)line + len < (uintptr_t)line || 596 line + len > exthdr + sz) { 597 TARFS_DPF(ALLOC, "%s: exthdr overflow\n", 598 __func__); 599 error = EINVAL; 600 goto bad; 601 } 602 eol = line + len - 1; 603 *eol = '\0'; 604 line += len; 605 key = sep + 1; 606 sep = strchr(key, '='); 607 if (sep == NULL) { 608 TARFS_DPF(ALLOC, "%s: exthdr syntax error\n", 609 __func__); 610 error = EINVAL; 611 goto bad; 612 } 613 *sep = '\0'; 614 value = sep + 1; 615 TARFS_DPF(ALLOC, "%s: exthdr %s=%s\n", __func__, 616 key, value); 617 if (strcmp(key, "linkpath") == 0) { 618 link = value; 619 linklen = eol - value; 620 } else if (strcmp(key, "GNU.sparse.major") == 0) { 621 sparse = true; 622 major = strtol(value, &sep, 10); 623 if (sep != eol) { 624 printf("exthdr syntax error\n"); 625 error = EINVAL; 626 goto bad; 627 } 628 } else if (strcmp(key, "GNU.sparse.minor") == 0) { 629 sparse = true; 630 minor = strtol(value, &sep, 10); 631 if (sep != eol) { 632 printf("exthdr syntax error\n"); 633 error = EINVAL; 634 goto bad; 635 } 636 } else if (strcmp(key, "GNU.sparse.name") == 0) { 637 sparse = true; 638 name = value; 639 namelen = eol - value; 640 if (namelen == 0) { 641 printf("exthdr syntax error\n"); 642 error = EINVAL; 643 goto bad; 644 } 645 } else if (strcmp(key, "GNU.sparse.realsize") == 0) { 646 sparse = true; 647 realsize = strtoul(value, &sep, 10); 648 if (sep != eol) { 649 printf("exthdr syntax error\n"); 650 error = EINVAL; 651 goto bad; 652 } 653 } else if (strcmp(key, "SCHILY.fflags") == 0) { 654 flags |= tarfs_strtofflags(value, &sep); 655 if (sep != eol) { 656 printf("exthdr syntax error\n"); 657 error = EINVAL; 658 goto bad; 659 } 660 } 661 } 662 goto again; 663 } 664 665 /* sparse file consistency checks */ 666 if (sparse) { 667 TARFS_DPF(ALLOC, "%s: %s: sparse %ld.%ld (%zu bytes)\n", __func__, 668 name, major, minor, realsize); 669 if (major != 1 || minor != 0 || name == NULL || realsize == 0 || 670 hdrp->typeflag[0] != TAR_TYPE_FILE) { 671 TARFS_DPF(ALLOC, "%s: invalid sparse format\n", __func__); 672 error = EINVAL; 673 goto bad; 674 } 675 } 676 677 /* file name */ 678 if (name == NULL) { 679 if (hdrp->prefix[0] != '\0') { 680 namebuf = sbuf_new_auto(); 681 sbuf_printf(namebuf, "%.*s/%.*s", 682 (int)sizeof(hdrp->prefix), hdrp->prefix, 683 (int)sizeof(hdrp->name), hdrp->name); 684 sbuf_finish(namebuf); 685 name = sbuf_data(namebuf); 686 namelen = sbuf_len(namebuf); 687 } else { 688 name = hdrp->name; 689 namelen = strnlen(hdrp->name, sizeof(hdrp->name)); 690 } 691 } 692 693 error = tarfs_lookup_path(tmp, name, namelen, &namep, 694 &sep, &parent, &tnp, true); 695 if (error != 0) { 696 TARFS_DPF(ALLOC, "%s: failed to look up %.*s\n", __func__, 697 (int)namelen, name); 698 error = EINVAL; 699 goto bad; 700 } 701 if (tnp != NULL) { 702 if (hdrp->typeflag[0] == TAR_TYPE_DIRECTORY) { 703 /* XXX set attributes? */ 704 goto skip; 705 } 706 TARFS_DPF(ALLOC, "%s: duplicate file %.*s\n", __func__, 707 (int)namelen, name); 708 error = EINVAL; 709 goto bad; 710 } 711 switch (hdrp->typeflag[0]) { 712 case TAR_TYPE_DIRECTORY: 713 error = tarfs_alloc_node(tmp, namep, sep - namep, VDIR, 714 0, 0, mtime, uid, gid, mode, flags, NULL, 0, 715 parent, &tnp); 716 break; 717 case TAR_TYPE_FILE: 718 error = tarfs_alloc_node(tmp, namep, sep - namep, VREG, 719 blknum * TARFS_BLOCKSIZE, sz, mtime, uid, gid, mode, 720 flags, NULL, 0, parent, &tnp); 721 if (error == 0 && sparse) { 722 error = tarfs_load_blockmap(tnp, realsize); 723 } 724 break; 725 case TAR_TYPE_HARDLINK: 726 if (link == NULL) { 727 link = hdrp->linkname; 728 linklen = strnlen(link, sizeof(hdrp->linkname)); 729 } 730 if (linklen == 0) { 731 TARFS_DPF(ALLOC, "%s: %.*s: link without target\n", 732 __func__, (int)namelen, name); 733 error = EINVAL; 734 goto bad; 735 } 736 error = tarfs_lookup_path(tmp, link, linklen, NULL, 737 NULL, NULL, &other, false); 738 if (error != 0 || other == NULL || 739 other->type != VREG || other->other != NULL) { 740 TARFS_DPF(ALLOC, "%s: %.*s: invalid link to %.*s\n", 741 __func__, (int)namelen, name, (int)linklen, link); 742 error = EINVAL; 743 goto bad; 744 } 745 error = tarfs_alloc_node(tmp, namep, sep - namep, VREG, 746 0, 0, 0, 0, 0, 0, 0, NULL, 0, parent, &tnp); 747 if (error == 0) { 748 tnp->other = other; 749 tnp->other->nlink++; 750 } 751 break; 752 case TAR_TYPE_SYMLINK: 753 if (link == NULL) { 754 link = hdrp->linkname; 755 linklen = strnlen(link, sizeof(hdrp->linkname)); 756 } 757 if (linklen == 0) { 758 TARFS_DPF(ALLOC, "%s: %.*s: link without target\n", 759 __func__, (int)namelen, name); 760 error = EINVAL; 761 goto bad; 762 } 763 error = tarfs_alloc_node(tmp, namep, sep - namep, VLNK, 764 0, linklen, mtime, uid, gid, mode, flags, link, 0, 765 parent, &tnp); 766 break; 767 case TAR_TYPE_BLOCK: 768 if (tarfs_str2int64(hdrp->major, sizeof(hdrp->major), &num) != 0 || 769 num < 0 || num > INT_MAX) { 770 TARFS_DPF(ALLOC, "%s: %.*s: invalid device major\n", 771 __func__, (int)namelen, name); 772 error = EINVAL; 773 goto bad; 774 } 775 major = num; 776 if (tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor), &num) != 0 || 777 num < 0 || num > INT_MAX) { 778 TARFS_DPF(ALLOC, "%s: %.*s: invalid device minor\n", 779 __func__, (int)namelen, name); 780 error = EINVAL; 781 goto bad; 782 } 783 minor = num; 784 rdev = makedev(major, minor); 785 error = tarfs_alloc_node(tmp, namep, sep - namep, VBLK, 786 0, 0, mtime, uid, gid, mode, flags, NULL, rdev, 787 parent, &tnp); 788 break; 789 case TAR_TYPE_CHAR: 790 if (tarfs_str2int64(hdrp->major, sizeof(hdrp->major), &num) != 0 || 791 num < 0 || num > INT_MAX) { 792 TARFS_DPF(ALLOC, "%s: %.*s: invalid device major\n", 793 __func__, (int)namelen, name); 794 error = EINVAL; 795 goto bad; 796 } 797 major = num; 798 if (tarfs_str2int64(hdrp->minor, sizeof(hdrp->minor), &num) != 0 || 799 num < 0 || num > INT_MAX) { 800 TARFS_DPF(ALLOC, "%s: %.*s: invalid device minor\n", 801 __func__, (int)namelen, name); 802 error = EINVAL; 803 goto bad; 804 } 805 minor = num; 806 rdev = makedev(major, minor); 807 error = tarfs_alloc_node(tmp, namep, sep - namep, VCHR, 808 0, 0, mtime, uid, gid, mode, flags, NULL, rdev, 809 parent, &tnp); 810 break; 811 default: 812 TARFS_DPF(ALLOC, "%s: unsupported type %c for %.*s\n", 813 __func__, hdrp->typeflag[0], (int)namelen, name); 814 error = EINVAL; 815 break; 816 } 817 if (error != 0) 818 goto bad; 819 820 skip: 821 blknum += TARFS_SZ2BLKS(sz); 822 tmp->nblocks = blknum; 823 *blknump = blknum; 824 if (exthdr != NULL) { 825 free(exthdr, M_TEMP); 826 } 827 if (namebuf != NULL) { 828 sbuf_delete(namebuf); 829 } 830 return (0); 831 eof: 832 TARFS_DPF(IO, "%s: premature end of file\n", __func__); 833 error = EIO; 834 goto bad; 835 bad: 836 if (exthdr != NULL) { 837 free(exthdr, M_TEMP); 838 } 839 if (namebuf != NULL) { 840 sbuf_delete(namebuf); 841 } 842 return (error); 843 } 844 845 /* 846 * Allocates and populates the metadata structures for the tar file 847 * referenced by vp. On success, a pointer to the tarfs_mount structure 848 * is stored in tmpp. Returns 0 on success or a positive errno value on 849 * failure. 850 */ 851 static int 852 tarfs_alloc_mount(struct mount *mp, struct vnode *vp, 853 uid_t root_uid, gid_t root_gid, mode_t root_mode, 854 struct tarfs_mount **tmpp) 855 { 856 struct vattr va; 857 struct thread *td = curthread; 858 struct tarfs_mount *tmp; 859 struct tarfs_node *root; 860 off_t blknum; 861 time_t mtime; 862 int error; 863 864 KASSERT(tmpp != NULL, ("tarfs mount return is NULL")); 865 ASSERT_VOP_LOCKED(vp, __func__); 866 867 tmp = NULL; 868 869 TARFS_DPF(ALLOC, "%s: Allocating tarfs mount structure for vp %p\n", 870 __func__, vp); 871 872 /* Get source metadata */ 873 error = VOP_GETATTR(vp, &va, td->td_ucred); 874 if (error != 0) { 875 return (error); 876 } 877 VOP_UNLOCK(vp); 878 mtime = va.va_mtime.tv_sec; 879 880 /* Allocate and initialize tarfs mount structure */ 881 tmp = malloc(sizeof(*tmp), M_TARFSMNT, M_WAITOK | M_ZERO); 882 TARFS_DPF(ALLOC, "%s: Allocated mount structure\n", __func__); 883 mp->mnt_data = tmp; 884 885 mtx_init(&tmp->allnode_lock, "tarfs allnode lock", NULL, 886 MTX_DEF); 887 TAILQ_INIT(&tmp->allnodes); 888 tmp->ino_unr = new_unrhdr(TARFS_MININO, INT_MAX, &tmp->allnode_lock); 889 tmp->vp = vp; 890 tmp->vfs = mp; 891 tmp->mtime = mtime; 892 893 /* Initialize I/O layer */ 894 tmp->iosize = 1U << tarfs_ioshift; 895 error = tarfs_io_init(tmp); 896 if (error != 0) 897 goto bad; 898 899 error = tarfs_alloc_node(tmp, NULL, 0, VDIR, 0, 0, mtime, root_uid, 900 root_gid, root_mode & ALLPERMS, 0, NULL, NODEV, NULL, &root); 901 if (error != 0 || root == NULL) 902 goto bad; 903 tmp->root = root; 904 905 blknum = 0; 906 do { 907 if ((error = tarfs_alloc_one(tmp, &blknum)) != 0) { 908 goto bad; 909 } 910 } while (blknum != TAR_EOF); 911 912 *tmpp = tmp; 913 914 TARFS_DPF(ALLOC, "%s: pfsmnt_root %p\n", __func__, tmp->root); 915 return (0); 916 917 bad: 918 tarfs_free_mount(tmp); 919 return (error); 920 } 921 922 /* 923 * VFS Operations. 924 */ 925 926 static int 927 tarfs_mount(struct mount *mp) 928 { 929 struct nameidata nd; 930 struct vattr va; 931 struct tarfs_mount *tmp = NULL; 932 struct thread *td = curthread; 933 struct vnode *vp; 934 char *as, *from; 935 uid_t root_uid; 936 gid_t root_gid; 937 mode_t root_mode; 938 int error, flags, aslen, len; 939 940 if (mp->mnt_flag & MNT_UPDATE) 941 return (EOPNOTSUPP); 942 943 if (vfs_filteropt(mp->mnt_optnew, tarfs_opts)) 944 return (EINVAL); 945 946 vn_lock(mp->mnt_vnodecovered, LK_SHARED | LK_RETRY); 947 error = VOP_GETATTR(mp->mnt_vnodecovered, &va, mp->mnt_cred); 948 VOP_UNLOCK(mp->mnt_vnodecovered); 949 if (error) 950 return (error); 951 952 if (mp->mnt_cred->cr_ruid != 0 || 953 vfs_scanopt(mp->mnt_optnew, "gid", "%d", &root_gid) != 1) 954 root_gid = va.va_gid; 955 if (mp->mnt_cred->cr_ruid != 0 || 956 vfs_scanopt(mp->mnt_optnew, "uid", "%d", &root_uid) != 1) 957 root_uid = va.va_uid; 958 if (mp->mnt_cred->cr_ruid != 0 || 959 vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1) 960 root_mode = va.va_mode; 961 962 error = vfs_getopt(mp->mnt_optnew, "from", (void **)&from, &len); 963 if (error != 0 || from[len - 1] != '\0') 964 return (EINVAL); 965 error = vfs_getopt(mp->mnt_optnew, "as", (void **)&as, &aslen); 966 if (error != 0 || as[aslen - 1] != '\0') 967 as = from; 968 969 /* Find the source tarball */ 970 TARFS_DPF(FS, "%s(%s%s%s, uid=%u, gid=%u, mode=%o)\n", __func__, 971 from, (as != from) ? " as " : "", (as != from) ? as : "", 972 root_uid, root_gid, root_mode); 973 flags = FREAD; 974 if (vfs_flagopt(mp->mnt_optnew, "verify", NULL, 0)) { 975 flags |= O_VERIFY; 976 } 977 NDINIT(&nd, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF, UIO_SYSSPACE, from); 978 error = namei(&nd); 979 if (error != 0) 980 return (error); 981 NDFREE_PNBUF(&nd); 982 vp = nd.ni_vp; 983 TARFS_DPF(FS, "%s: N: hold %u use %u lock 0x%x\n", __func__, 984 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 985 /* vp is now held and locked */ 986 987 /* Open the source tarball */ 988 error = vn_open_vnode(vp, flags, td->td_ucred, td, NULL); 989 if (error != 0) { 990 TARFS_DPF(FS, "%s: failed to open %s: %d\n", __func__, 991 from, error); 992 vput(vp); 993 goto bad; 994 } 995 TARFS_DPF(FS, "%s: O: hold %u use %u lock 0x%x\n", __func__, 996 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 997 if (vp->v_type != VREG) { 998 TARFS_DPF(FS, "%s: not a regular file\n", __func__); 999 error = EOPNOTSUPP; 1000 goto bad_open_locked; 1001 } 1002 error = priv_check(td, PRIV_VFS_MOUNT_PERM); 1003 if (error != 0) { 1004 TARFS_DPF(FS, "%s: not permitted to mount\n", __func__); 1005 goto bad_open_locked; 1006 } 1007 if (flags & O_VERIFY) { 1008 mp->mnt_flag |= MNT_VERIFIED; 1009 } 1010 1011 /* Allocate the tarfs mount */ 1012 error = tarfs_alloc_mount(mp, vp, root_uid, root_gid, root_mode, &tmp); 1013 /* vp is now held but unlocked */ 1014 if (error != 0) { 1015 TARFS_DPF(FS, "%s: failed to mount %s: %d\n", __func__, 1016 from, error); 1017 goto bad_open_unlocked; 1018 } 1019 TARFS_DPF(FS, "%s: M: hold %u use %u lock 0x%x\n", __func__, 1020 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1021 1022 /* Unconditionally mount as read-only */ 1023 MNT_ILOCK(mp); 1024 mp->mnt_flag |= (MNT_LOCAL | MNT_RDONLY); 1025 MNT_IUNLOCK(mp); 1026 1027 vfs_getnewfsid(mp); 1028 vfs_mountedfrom(mp, as); 1029 TARFS_DPF(FS, "%s: success\n", __func__); 1030 1031 return (0); 1032 1033 bad_open_locked: 1034 /* vp must be held and locked */ 1035 TARFS_DPF(FS, "%s: L: hold %u use %u lock 0x%x\n", __func__, 1036 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1037 VOP_UNLOCK(vp); 1038 bad_open_unlocked: 1039 /* vp must be held and unlocked */ 1040 TARFS_DPF(FS, "%s: E: hold %u use %u lock 0x%x\n", __func__, 1041 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1042 (void)vn_close(vp, flags, td->td_ucred, td); 1043 bad: 1044 /* vp must be released and unlocked */ 1045 TARFS_DPF(FS, "%s: X: hold %u use %u lock 0x%x\n", __func__, 1046 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1047 return (error); 1048 } 1049 1050 /* 1051 * Unmounts a tarfs filesystem. 1052 */ 1053 static int 1054 tarfs_unmount(struct mount *mp, int mntflags) 1055 { 1056 struct thread *td = curthread; 1057 struct tarfs_mount *tmp; 1058 struct vnode *vp; 1059 int error; 1060 int flags = 0; 1061 1062 TARFS_DPF(FS, "%s: Unmounting %p\n", __func__, mp); 1063 1064 /* Handle forced unmounts */ 1065 if (mntflags & MNT_FORCE) 1066 flags |= FORCECLOSE; 1067 1068 /* Finalize all pending I/O */ 1069 error = vflush(mp, 0, flags, curthread); 1070 if (error != 0) 1071 return (error); 1072 tmp = MP_TO_TARFS_MOUNT(mp); 1073 vp = tmp->vp; 1074 1075 MPASS(vp != NULL); 1076 TARFS_DPF(FS, "%s: U: hold %u use %u lock 0x%x\n", __func__, 1077 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1078 vn_close(vp, FREAD, td->td_ucred, td); 1079 TARFS_DPF(FS, "%s: C: hold %u use %u lock 0x%x\n", __func__, 1080 vp->v_holdcnt, vp->v_usecount, VOP_ISLOCKED(vp)); 1081 tarfs_free_mount(tmp); 1082 1083 return (0); 1084 } 1085 1086 /* 1087 * Gets the root of a tarfs filesystem. Returns 0 on success or a 1088 * positive errno value on failure. 1089 */ 1090 static int 1091 tarfs_root(struct mount *mp, int flags, struct vnode **vpp) 1092 { 1093 struct vnode *nvp; 1094 int error; 1095 1096 TARFS_DPF(FS, "%s: Getting root vnode\n", __func__); 1097 1098 error = VFS_VGET(mp, TARFS_ROOTINO, LK_EXCLUSIVE, &nvp); 1099 if (error != 0) 1100 return (error); 1101 1102 nvp->v_vflag |= VV_ROOT; 1103 *vpp = nvp; 1104 return (0); 1105 } 1106 1107 /* 1108 * Gets statistics for a tarfs filesystem. Returns 0. 1109 */ 1110 static int 1111 tarfs_statfs(struct mount *mp, struct statfs *sbp) 1112 { 1113 struct tarfs_mount *tmp; 1114 1115 tmp = MP_TO_TARFS_MOUNT(mp); 1116 1117 sbp->f_bsize = TARFS_BLOCKSIZE; 1118 sbp->f_iosize = tmp->iosize; 1119 sbp->f_blocks = tmp->nblocks; 1120 sbp->f_bfree = 0; 1121 sbp->f_bavail = 0; 1122 sbp->f_files = tmp->nfiles; 1123 sbp->f_ffree = 0; 1124 1125 return (0); 1126 } 1127 1128 /* 1129 * Gets a vnode for the given inode. On success, a pointer to the vnode 1130 * is stored in vpp. Returns 0 on success or a positive errno value on 1131 * failure. 1132 */ 1133 static int 1134 tarfs_vget(struct mount *mp, ino_t ino, int lkflags, struct vnode **vpp) 1135 { 1136 struct tarfs_mount *tmp; 1137 struct tarfs_node *tnp; 1138 struct thread *td; 1139 struct vnode *vp; 1140 int error; 1141 1142 TARFS_DPF(FS, "%s: mp %p, ino %lu, lkflags %d\n", __func__, mp, ino, 1143 lkflags); 1144 1145 td = curthread; 1146 error = vfs_hash_get(mp, ino, lkflags, td, vpp, NULL, NULL); 1147 if (error != 0) 1148 return (error); 1149 1150 if (*vpp != NULL) { 1151 TARFS_DPF(FS, "%s: found hashed vnode %p\n", __func__, *vpp); 1152 return (error); 1153 } 1154 1155 TARFS_DPF(FS, "%s: no hashed vnode for inode %lu\n", __func__, ino); 1156 1157 tmp = MP_TO_TARFS_MOUNT(mp); 1158 1159 if (ino == TARFS_ZIOINO) { 1160 error = vget(tmp->znode, lkflags); 1161 if (error != 0) 1162 return (error); 1163 *vpp = tmp->znode; 1164 return (0); 1165 } 1166 1167 /* XXX Should use hash instead? */ 1168 TAILQ_FOREACH(tnp, &tmp->allnodes, entries) { 1169 if (tnp->ino == ino) 1170 break; 1171 } 1172 TARFS_DPF(FS, "%s: search of all nodes found %p\n", __func__, tnp); 1173 if (tnp == NULL) 1174 return (ENOENT); 1175 1176 (void)getnewvnode("tarfs", mp, &tarfs_vnodeops, &vp); 1177 TARFS_DPF(FS, "%s: allocated vnode\n", __func__); 1178 vp->v_data = tnp; 1179 vp->v_type = tnp->type; 1180 tnp->vnode = vp; 1181 1182 lockmgr(vp->v_vnlock, lkflags, NULL); 1183 error = insmntque(vp, mp); 1184 if (error != 0) 1185 goto bad; 1186 TARFS_DPF(FS, "%s: inserting entry into VFS hash\n", __func__); 1187 error = vfs_hash_insert(vp, ino, lkflags, td, vpp, NULL, NULL); 1188 if (error != 0 || *vpp != NULL) 1189 return (error); 1190 1191 vn_set_state(vp, VSTATE_CONSTRUCTED); 1192 *vpp = vp; 1193 return (0); 1194 1195 bad: 1196 *vpp = NULLVP; 1197 return (error); 1198 } 1199 1200 static int 1201 tarfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) 1202 { 1203 struct tarfs_node *tnp; 1204 struct tarfs_fid *tfp; 1205 struct vnode *nvp; 1206 int error; 1207 1208 tfp = (struct tarfs_fid *)fhp; 1209 MP_TO_TARFS_MOUNT(mp); 1210 if (tfp->ino < TARFS_ROOTINO || tfp->ino > INT_MAX) 1211 return (ESTALE); 1212 1213 error = VFS_VGET(mp, tfp->ino, LK_EXCLUSIVE, &nvp); 1214 if (error != 0) { 1215 *vpp = NULLVP; 1216 return (error); 1217 } 1218 tnp = VP_TO_TARFS_NODE(nvp); 1219 if (tnp->mode == 0 || 1220 tnp->gen != tfp->gen || 1221 tnp->nlink <= 0) { 1222 vput(nvp); 1223 *vpp = NULLVP; 1224 return (ESTALE); 1225 } 1226 *vpp = nvp; 1227 return (0); 1228 } 1229 1230 static struct vfsops tarfs_vfsops = { 1231 .vfs_fhtovp = tarfs_fhtovp, 1232 .vfs_mount = tarfs_mount, 1233 .vfs_root = tarfs_root, 1234 .vfs_statfs = tarfs_statfs, 1235 .vfs_unmount = tarfs_unmount, 1236 .vfs_vget = tarfs_vget, 1237 }; 1238 VFS_SET(tarfs_vfsops, tarfs, VFCF_READONLY); 1239 MODULE_VERSION(tarfs, 1); 1240 MODULE_DEPEND(tarfs, xz, 1, 1, 1); 1241