1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * System Use Sharing protocol subroutines for High Sierra filesystem 23 */ 24 /* 25 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <sys/types.h> 32 #include <sys/t_lock.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/sysmacros.h> 36 #include <sys/kmem.h> 37 #include <sys/signal.h> 38 #include <sys/user.h> 39 #include <sys/proc.h> 40 #include <sys/disp.h> 41 #include <sys/buf.h> 42 #include <sys/pathname.h> 43 #include <sys/vfs.h> 44 #include <sys/vnode.h> 45 #include <sys/file.h> 46 #include <sys/uio.h> 47 #include <sys/conf.h> 48 49 #include <vm/page.h> 50 51 #include <sys/fs/hsfs_spec.h> 52 #include <sys/fs/hsfs_isospec.h> 53 #include <sys/fs/hsfs_node.h> 54 #include <sys/fs/hsfs_impl.h> 55 #include <sys/fs/hsfs_susp.h> 56 #include <sys/fs/hsfs_rrip.h> 57 58 #include <sys/statvfs.h> 59 #include <sys/mount.h> 60 #include <sys/swap.h> 61 #include <sys/errno.h> 62 #include <sys/debug.h> 63 #include "fs/fs_subr.h" 64 #include <sys/cmn_err.h> 65 66 /* static declarations */ 67 static void free_cont_area(uchar_t *); 68 static int get_cont_area(struct hsfs *, uchar_t **, cont_info_t *); 69 static int parse_signatures(sig_args_t *, int, uchar_t *, int); 70 71 /* 72 * parse_sua() 73 * 74 * This is the main SUSP routine, that gets all the SUA areas and 75 * continuations. It calls parse_signatures() to actually interpret 76 * the signature fields. 77 * 78 * XXX - need to implement signature searching to speed things up and 79 * which is needed for the api, which isn't done yet. 80 */ 81 int 82 parse_sua( 83 uchar_t *name_p, /* location to copy name */ 84 int *name_len_p, /* location to put name len */ 85 int *name_change_p, /* flags to signal name chg */ 86 uchar_t *dirp, /* pointer to ISO dir entry */ 87 uint_t last_offset, /* last ind. in cur. dirblock */ 88 struct hs_direntry *hdp, /* loc to store dir info */ 89 struct hsfs *fsp, /* filesystem pointer */ 90 uchar_t *search_sig, /* signature to search for */ 91 int search_num) /* n^th sig to search for */ 92 { 93 uchar_t *SUA_p = IDE_sys_use_area(dirp); 94 int SUA_len = IDE_SUA_LEN(dirp); 95 uchar_t *tmp_SUA_p = (SUA_p + fsp->hsfs_sua_off); 96 int tmp_SUA_len = (SUA_len - fsp->hsfs_sua_off); 97 short ret_val = -1; 98 uchar_t *cont_p = (uchar_t *)NULL; 99 sig_args_t sig_args; 100 cont_info_t cont_info; 101 102 /* 103 * If there is no SUA, just return, no error 104 */ 105 106 if (SUA_len == 0) 107 return (0); 108 109 /* 110 * Underflow on the length field means there's a mismatch 111 * between sizes of SUA and ISO directory entry. This entry 112 * is corrupted, return an appropriate error. 113 */ 114 if (SUA_len < 0) { 115 hs_log_bogus_disk_warning(fsp, HSFS_ERR_NEG_SUA_LEN, 0); 116 return (SUA_EINVAL); 117 } 118 119 if ((tmp_SUA_p + tmp_SUA_len) > (dirp + last_offset)) { 120 hs_log_bogus_disk_warning(fsp, HSFS_ERR_BAD_SUA_LEN, 0); 121 return (SUA_EINVAL); 122 } 123 124 /* 125 * Make sure that the continuation lenth is zero, as that is 126 * the way to tell if we must grab another continuation area. 127 */ 128 bzero((char *)&cont_info, sizeof (cont_info)); 129 130 sig_args.dirp = dirp; 131 sig_args.name_p = name_p; 132 sig_args.name_len_p = name_len_p; 133 sig_args.SUF_ptr = tmp_SUA_p; 134 sig_args.hdp = hdp; 135 sig_args.fsp = fsp; 136 sig_args.cont_info_p = &cont_info; 137 sig_args.flags = 0; 138 sig_args.name_flags = 0; 139 140 /* 141 * Get ready to put in a new name. If no "NM" is found, then 142 * hs_namecopy will come to the rescue. Make sure you don't 143 * have NULL names, also. 144 */ 145 if (name_p) 146 *(name_p) = '\0'; 147 if (name_len_p) 148 *(name_len_p) = 0; 149 150 while (ret_val == -1) { 151 switch (parse_signatures(&sig_args, tmp_SUA_len, search_sig, 152 search_num)) { 153 case END_OF_SUA : 154 if (cont_info.cont_len) { 155 156 if (get_cont_area(fsp, &cont_p, &cont_info)) { 157 ret_val = 1; 158 goto clean_up; 159 } 160 161 sig_args.SUF_ptr = cont_p + 162 cont_info.cont_offset; 163 164 tmp_SUA_len = cont_info.cont_len; 165 cont_info.cont_len = 0; 166 167 continue; 168 } 169 sig_args.flags = 0; /* reset */ 170 ret_val = 0; /* keep going */ 171 break; 172 case SUA_NULL_POINTER: 173 ret_val = SUA_NULL_POINTER; 174 goto clean_up; 175 case SUA_ENOMEM: 176 ret_val = SUA_ENOMEM; 177 goto clean_up; 178 case SUA_EINVAL: 179 ret_val = SUA_EINVAL; 180 goto clean_up; 181 case RELOC_DIR: 182 ret_val = RELOC_DIR; 183 goto clean_up; 184 } 185 } 186 187 if (ret_val != 0) 188 goto clean_up; 189 190 if (IS_NAME_BIT_SET(sig_args.name_flags, RRIP_NAME_CHANGE)) 191 SET_NAME_BIT(*(name_change_p), RRIP_NAME_CHANGE); 192 193 clean_up: 194 free_cont_area(cont_p); 195 return (ret_val); 196 197 } 198 199 /* 200 * parse_signatures() 201 * 202 * Find the correct handling function for the signature string that is 203 * passed to this function. 204 * 205 * signature searching: 206 * 207 * The two arguments of search_sig and search_num are for finding the 208 * search_num^th occurance of the signature search_sig. This will come 209 * in handy with searching for the "NM" field and is part of the api 210 * for rrip (which really can be used for any extension). 211 */ 212 /*ARGSUSED*/ 213 static int 214 parse_signatures( 215 sig_args_t *sig_args_p, 216 int SUA_len, 217 uchar_t *search_sig, /* possible signature to search for */ 218 int search_num) /* n^th occurance of search_sig to */ 219 /* search for */ 220 { 221 uchar_t *sig_string = sig_args_p->SUF_ptr; 222 extension_name_t *extnp; 223 ext_signature_t *ext_sigp; 224 int impl_bit_num = 0; 225 int SUA_rem = SUA_len; /* SUA length */ 226 /* remaining to be parsed */ 227 228 /* This should never happen ... just so we don't panic, literally */ 229 if (sig_string == (uchar_t *)NULL) 230 return (SUA_NULL_POINTER); 231 232 if (SUA_len < 0) 233 return (SUA_EINVAL); 234 235 /* 236 * Until the end of SUA, search for the signatures 237 * (check for end of SUA (2 consecutive NULL bytes)) or the 238 * remaining length of the SUA is <= 3. The minimum signature 239 * field is 4. 240 */ 241 242 while ((SUA_rem >= SUF_MIN_LEN) && (*sig_string != '\0') && 243 (*(sig_string + 1) != '\0')) { 244 245 /* 246 * Find appropriate extension and signature table 247 */ 248 for (extnp = extension_name_table, impl_bit_num = 0; 249 extnp->extension_name != (char *)NULL; 250 extnp++, impl_bit_num++) { 251 252 /* 253 * look at an extension only if it is implemented 254 * on the CD-ROM 255 */ 256 if (!IS_IMPL_BIT_SET(sig_args_p->fsp, impl_bit_num)) 257 continue; 258 259 /* 260 * Find the appropriate signature 261 */ 262 for (ext_sigp = extnp->signature_table; 263 ext_sigp->ext_signature != (char *)NULL; 264 ext_sigp++) { 265 266 if (strncmp((char *)sig_string, 267 ext_sigp->ext_signature, 268 SUF_SIG_LEN) == 0) { 269 270 SUA_rem -= SUF_LEN(sig_string); 271 if (SUA_rem < 0) 272 return (END_OF_SUA); 273 274 /* 275 * The SUA_len parameter specifies the 276 * length of the SUA that the kernel 277 * expects. There is also a length 278 * encoded in the SUA data. If they 279 * do not agree, bail out. 280 */ 281 if (SUA_len < SUF_LEN(sig_string)) { 282 cmn_err(CE_NOTE, 283 "parse_signatures: SUA length too big: " 284 "expected=%d, found=%d", 285 SUA_len, 286 SUF_LEN(sig_string)); 287 return (SUA_EINVAL); 288 } 289 290 sig_args_p->SUF_ptr = sig_string; 291 sig_string = 292 (ext_sigp->sig_handler)(sig_args_p); 293 294 switch (sig_args_p->flags) { 295 case END_OF_SUA : 296 return (END_OF_SUA); 297 case SUA_ENOMEM : 298 return (SUA_ENOMEM); 299 case SUA_EINVAL : 300 return (SUA_EINVAL); 301 case RELOC_DIR : 302 return (RELOC_DIR); 303 default : 304 #if NAME_SEARCH 305 case NAME_CONTINUE : 306 /* nothing for now */ 307 case NAME_CHANGE : 308 /* nothing for now */ 309 #endif 310 break; 311 } 312 313 /* reset to be zero */ 314 315 sig_args_p->flags = 0; 316 goto next_signature; 317 } 318 319 /* off to the next signature .... */ 320 321 } /* for ext_sigp */ 322 323 } /* for extnp (extension parsing) */ 324 325 /* 326 * Opps, did not find this signature. We must 327 * advance on the the next signature in the SUA 328 * and pray to persumedly omniscient, omnipresent, 329 * almighty transcendental being(s) that the next 330 * record is in the susp format, or we get hosed. 331 */ 332 if (SUA_rem < SUF_MIN_LEN) 333 return (END_OF_SUA); 334 335 SUA_rem -= SUF_LEN(sig_string); 336 sig_string += SUF_LEN(sig_string); 337 338 next_signature: 339 /* 340 * Failsafe 341 */ 342 if (SUA_rem < SUF_MIN_LEN || 343 sig_string == NULL || SUF_LEN(sig_string) <= 0) { 344 return (END_OF_SUA); 345 } 346 347 } /* while */ 348 349 return (END_OF_SUA); 350 } 351 352 /* 353 * hs_fill_root_dirent() 354 * 355 * 356 * This function reads the root directory extent to get to the SUA of 357 * the "." entry of the root directory. It the checks to see if the 358 * susp is implemented. 359 */ 360 void 361 hs_check_root_dirent(struct vnode *vp, struct hs_direntry *hdp) 362 { 363 struct buf *secbp; 364 uchar_t *root_ptr; 365 uchar_t *secp; 366 uint_t secno; 367 offset_t secoff; 368 sig_args_t sig_args; 369 struct hsfs *fsp; 370 int error; 371 372 if (vp->v_type != VDIR) { 373 cmn_err(CE_NOTE, 374 "hs_check_root_dirent: vp (0x%p) not a directory", 375 (void *)vp); 376 return; 377 } 378 379 bzero((caddr_t)&sig_args, sizeof (sig_args)); 380 381 fsp = VFS_TO_HSFS(vp->v_vfsp); 382 secno = LBN_TO_SEC(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp); 383 secoff = LBN_TO_BYTE(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp) & 384 MAXHSOFFSET; 385 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 386 error = geterror(secbp); 387 388 if (error != 0) { 389 cmn_err(CE_NOTE, 390 "hs_check_root_dirent: bread: error=(%d)", error); 391 goto end; 392 } 393 394 secp = (uchar_t *)secbp->b_un.b_addr; 395 root_ptr = &secp[secoff]; 396 397 /* quick check */ 398 if (hdp->ext_lbn != HDE_EXT_LBN(root_ptr)) { 399 cmn_err(CE_NOTE, "hs_check_root_dirent: dirent not match\n"); 400 /* keep on going */ 401 } 402 403 /* 404 * Here, we know that the "." entry is the first in the sector 405 * just read (ISO 9660). Let's now check for the sharing 406 * protocol and set call the susp sig_handler() if we should. 407 * Then we run through the hs_parsedir() function to catch all 408 * the other possibilities of SUSP fields and continuations. 409 * 410 * If there is no SUA area, just return, and assume ISO. 411 * 412 * If the SUA area length is invalid (negative, due to a mismatch 413 * between dirent size and SUA size), return and hope for the best. 414 */ 415 416 if (IDE_SUA_LEN(root_ptr) <= 0) 417 goto end; 418 419 if (strncmp(SUSP_SP, (char *)IDE_sys_use_area(root_ptr), 420 SUF_SIG_LEN) == 0) { 421 /* 422 * We have a match of the sharing signature, so let's 423 * call the sig_handler to do what is necessary. We can 424 * ignore the return value, as implemented bits are set. 425 */ 426 sig_args.SUF_ptr = IDE_sys_use_area(root_ptr); 427 sig_args.fsp = fsp; 428 429 if ((susp_sp->sig_handler)(&sig_args) == (uchar_t *)NULL) { 430 goto end; 431 } 432 } else { 433 goto end; 434 } 435 436 /* 437 * If the "ER" signature in the root directory is past any non SU 438 * signature, the Rock Ridge signatures will be ignored. This happens 439 * e.g. for filesystems created by mkisofs. In this case, 440 * IS_RRIP_IMPLEMENTED(fsp) will return 0 when the "ER" signature is 441 * parsed. Unfortunately, the results of this run will be cached for 442 * the root vnode. The solution is to run hs_parsedir() a second time 443 * for the root directory. 444 */ 445 if (hs_parsedir(fsp, root_ptr, hdp, (char *)NULL, (int *)NULL, 446 HS_SECTOR_SIZE - secoff) == 0) { 447 (void) hs_parsedir(fsp, root_ptr, hdp, (char *)NULL, 448 (int *)NULL, HS_SECTOR_SIZE - secoff); 449 } 450 451 /* 452 * If we did not get at least 1 extension, let's assume ISO and 453 * NULL out the implementation bits. 454 */ 455 if (fsp->hsfs_ext_impl <= 1L) 456 fsp->hsfs_ext_impl = 0L; 457 458 end: 459 brelse(secbp); 460 } 461 462 463 /* 464 * get_cont_area() 465 * 466 * This function allocates a memory block, if necessary, and reads the 467 * continuation area into the allocated space. 468 * 469 * Return value : 0 if the read and allocation went OK. 470 * 1 if there was an error. 471 */ 472 static int 473 get_cont_area(struct hsfs *fsp, uchar_t **buf_pp, cont_info_t *cont_info_p) 474 { 475 struct buf *secbp; 476 int error; 477 uint_t secno; 478 479 /* 480 * Guard against invalid continuation area records. 481 * Both cont_offset and cont_len must be no longer than 482 * HS_SECTOR_SIZE. If they are, return an error. 483 */ 484 if (cont_info_p->cont_offset > HS_SECTOR_SIZE || 485 cont_info_p->cont_len > HS_SECTOR_SIZE) { 486 cmn_err(CE_NOTE, "get_cont_area: invalid offset/length"); 487 return (1); 488 } 489 490 if (*buf_pp == (uchar_t *)NULL) 491 *buf_pp = kmem_alloc((size_t)HS_SECTOR_SIZE, KM_SLEEP); 492 493 secno = (uint_t)LBN_TO_SEC(cont_info_p->cont_lbn, fsp->hsfs_vfs); 494 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 495 error = geterror(secbp); 496 497 if (error != 0) { 498 cmn_err(CE_NOTE, "get_cont_area: bread: error=(%d)", error); 499 brelse(secbp); 500 return (1); 501 } 502 503 /* 504 * This continuation area does not extend into the next sector 505 * so just copy the data to the buffer. 506 */ 507 if ((cont_info_p->cont_offset + cont_info_p->cont_len) <= 508 HS_SECTOR_SIZE) { 509 bcopy(secbp->b_un.b_addr, (char *)*buf_pp, HS_SECTOR_SIZE); 510 } 511 /* 512 * This continuation area extends into the next sector so we 513 * need to do some dancing: 514 * 515 * - zero the return buffer so nothing random is returned 516 * - copy the partial data to the *beginning* of the return buffer 517 * - release the first sector's buffer 518 * - read the next sector 519 * - copy the remainder of the data to the return buffer 520 */ 521 else { 522 uint_t partial_size; 523 524 bzero((char *)*buf_pp, HS_SECTOR_SIZE); 525 partial_size = HS_SECTOR_SIZE - cont_info_p->cont_offset; 526 bcopy(&secbp->b_un.b_addr[cont_info_p->cont_offset], 527 (char *)*buf_pp, partial_size); 528 cont_info_p->cont_offset = 0; 529 brelse(secbp); 530 531 secbp = bread(fsp->hsfs_devvp->v_rdev, (secno + 1) * 4, 532 HS_SECTOR_SIZE); 533 error = geterror(secbp); 534 if (error != 0) { 535 cmn_err(CE_NOTE, "get_cont_area: bread(2): error=(%d)", 536 error); 537 brelse(secbp); 538 return (1); 539 } 540 bcopy(secbp->b_un.b_addr, (char *)&(*buf_pp)[partial_size], 541 cont_info_p->cont_len - partial_size); 542 } 543 544 brelse(secbp); 545 return (0); 546 } 547 548 549 /* 550 * free_cont_area 551 * 552 * simple function to just free up memory, if it exists 553 * 554 */ 555 static void 556 free_cont_area(uchar_t *cont_p) 557 { 558 if (cont_p) 559 (void) kmem_free((caddr_t)cont_p, (size_t)HS_SECTOR_SIZE); 560 cont_p = (uchar_t *)NULL; 561 } 562