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