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