1 #include <magic.h> 2 #include <magic_mem.h> 3 #include <magic_analysis.h> 4 #include <magic_asr.h> 5 #include <stdarg.h> 6 #include <st/state_transfer.h> 7 #include <st/metadata_transfer.h> 8 #include <st/typedefs.h> 9 #include <st/private.h> 10 11 #define printf _magic_printf 12 13 #ifdef __MINIX 14 EXTERN endpoint_t sef_self_endpoint; 15 #else 16 #define DO_SKIP_ENVIRON_HACK 1 17 #define TODO_DSENTRY_PARENT_NAME_BUG 1 18 #define DO_SKIP_UNPAIRED_PTR_TARGETS 1 19 #endif 20 21 #define DO_SKIP_INVARIANTS_VIOLATIONS 0 22 23 PRIVATE st_alloc_pages *st_alloc_pages_current = NULL; 24 PRIVATE size_t st_alloc_buff_available = 0; 25 PRIVATE char *st_alloc_buff_pt = NULL; 26 PRIVATE char *st_pre_allocated_page_pt = NULL; 27 PRIVATE struct _magic_dsentry *st_dsentry_buff = NULL; 28 PRIVATE void *st_data_buff = NULL; 29 PRIVATE unsigned st_num_type_transformations = 0; 30 31 /* Magic variables and counterparts. */ 32 struct _magic_vars_t st_remote_magic_vars, st_cached_magic_vars; 33 struct _magic_vars_t *st_local_magic_vars_ptr = &_magic_vars_buff; 34 st_counterparts_t st_counterparts; 35 36 /* Private variables. */ 37 PRIVATE int st_init_done = FALSE; 38 PRIVATE int st_policies = ST_POLICIES_DEFAULT; 39 PRIVATE double st_unpaired_types_ratio = ST_UNPAIRED_TYPES_RATIO_DEFAULT; 40 PRIVATE double st_unpaired_struct_types_ratio = ST_UNPAIRED_STRUCT_TYPES_RATIO_DEFAULT; 41 42 /* Forward declarations. */ 43 PRIVATE INLINE int default_transfer_selement_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info); 44 45 /* State transfer callbacks. */ 46 47 PRIVATE struct st_cbs_t st_cbs = { 48 ST_CB_PAGES_ALLOCATE_DEFAULT, 49 ST_CB_PAGES_FREE_DEFAULT, 50 ST_CB_STATE_CLEANUP_DEFAULT, 51 ST_CB_STATE_CHECKING_DEFAULT, 52 ST_CB_SELEMENT_MAP_DEFAULT, 53 ST_CB_SELEMENT_TRANSFER_EMPTY 54 }; 55 56 /* OS dependent callbacks. */ 57 PRIVATE struct st_cbs_os_t st_cbs_os = { 58 ST_CB_OS_PANIC_EMPTY, 59 ST_CB_OS_OLD_STATE_TABLE_LOOKUP_EMPTY, 60 ST_CB_OS_COPY_STATE_REGION_EMPTY, 61 ST_CB_OS_ALLOC_CONTIG_EMPTY, 62 ST_CB_OS_FREE_CONTIG_EMPTY, 63 ST_CB_OS_DEBUG_HEADER_EMPTY 64 }; 65 66 /* State transfer prototypes for st_receive(). */ 67 PUBLIC void do_st_before_receive(void); 68 69 /* Callback setters */ 70 71 PUBLIC void st_setcb_pages_allocate (st_cb_pages_allocate_t cb) 72 { 73 assert(cb != NULL); 74 st_cbs.st_cb_pages_allocate = cb; 75 } 76 77 PUBLIC void st_setcb_pages_free (st_cb_pages_free_t cb) 78 { 79 assert(cb != NULL); 80 st_cbs.st_cb_pages_free = cb; 81 } 82 83 PUBLIC void st_setcb_state_cleanup (st_cb_state_cleanup_t cb) 84 { 85 assert(cb != NULL); 86 st_cbs.st_cb_state_cleanup = cb; 87 magic_setcb_sentries_analyze_pre(cb); 88 } 89 90 PUBLIC void st_setcb_state_checking (st_cb_state_checking_t cb) 91 { 92 assert(cb != NULL); 93 st_cbs.st_cb_state_checking = cb; 94 } 95 96 PUBLIC void st_setcb_selement_map(st_cb_selement_map_t cb) 97 { 98 assert(cb != NULL); 99 st_cbs.st_cb_selement_map = cb; 100 } 101 102 PUBLIC void st_setcb_selement_transfer(st_cb_selement_transfer_t cb, int flags) 103 { 104 int i, j; 105 for (i = 0 ; i < NUM_CB_ARRAYS ; i++) { 106 if (i & flags) { 107 int is_registered = FALSE; 108 for (j = 0; j < MAX_NUM_CBS ; j++) { 109 if (st_cbs.st_cb_selement_transfer[i][j] == NULL) { 110 st_cbs.st_cb_selement_transfer[i][j] = cb; 111 is_registered = TRUE; 112 break; 113 } 114 } 115 assert(is_registered && "Number of registered callbacks exceeds MAX_NUM_CBS"); 116 } 117 } 118 } 119 120 /* OS Callback setters. */ 121 122 PUBLIC void st_setcb_os_panic(st_cb_os_panic_t cb) 123 { 124 assert(cb != NULL && "No callback defined for panic()."); 125 st_cbs_os.panic = cb; 126 } 127 128 PUBLIC void st_setcb_os_old_state_table_lookup(st_cb_os_old_state_table_lookup_t cb) 129 { 130 assert(cb != NULL && "No callback defined for old_state_table_lookup()."); 131 st_cbs_os.old_state_table_lookup = cb; 132 } 133 134 PUBLIC void st_setcb_os_copy_state_region(st_cb_os_copy_state_region_t cb) 135 { 136 assert(cb != NULL && "No callback defined for copy_state_region()."); 137 st_cbs_os.copy_state_region = cb; 138 } 139 140 PUBLIC void st_setcb_os_alloc_contig(st_cb_os_alloc_contig_t cb) 141 { 142 assert(cb != NULL && "No callback defined for alloc_contig()."); 143 st_cbs_os.alloc_contig = cb; 144 } 145 146 PUBLIC void st_setcb_os_free_contig(st_cb_os_free_contig_t cb) 147 { 148 assert(cb != NULL && "No callback defined for free_contig()."); 149 st_cbs_os.free_contig = cb; 150 } 151 152 PUBLIC void st_setcb_os_debug_header(st_cb_os_debug_header_t cb) 153 { 154 assert(cb != NULL && "No callback defined for debug_header()."); 155 st_cbs_os.debug_header = cb; 156 } 157 158 159 PUBLIC void st_setcb_os_all(struct st_cbs_os_t *cbs) 160 { 161 st_setcb_os_panic(cbs->panic); 162 st_setcb_os_old_state_table_lookup(cbs->old_state_table_lookup); 163 st_setcb_os_copy_state_region(cbs->copy_state_region); 164 st_setcb_os_alloc_contig(cbs->alloc_contig); 165 st_setcb_os_free_contig(cbs->free_contig); 166 st_setcb_os_debug_header(cbs->debug_header); 167 } 168 169 /* Status variables to be transfered at state transfer time. */ 170 PUBLIC int __st_before_receive_enabled = 0; 171 PRIVATE int __st_before_receive_sc_max_cycles; 172 PRIVATE int __st_before_receive_sc_max_violations; 173 174 /* Typedef registration and lookup */ 175 176 int st_strcmp_wildcard(const char *with_wildcard, const char *without_wildcard) 177 { 178 /* Note: this implementation only supports basic regexes with a '*' 179 * at the beginning or the end of the string. 180 */ 181 const char *star = strchr(with_wildcard, '*'); 182 if (star) { 183 if (star == with_wildcard) { 184 size_t len = strlen(with_wildcard+1); 185 size_t len_without_wildcard = strlen(without_wildcard); 186 const char *match_without_wildcard = without_wildcard+ 187 len_without_wildcard-len; 188 if (match_without_wildcard < without_wildcard) { 189 return -1; 190 } 191 return strncmp(with_wildcard+1, match_without_wildcard, len); 192 } 193 return strncmp(with_wildcard, without_wildcard, star - with_wildcard); 194 } 195 return strcmp(with_wildcard, without_wildcard); 196 } 197 198 const char *st_typename_noxfers[] = { ST_TYPENAME_NO_TRANSFER_NAMES, NULL }; 199 const char *st_typename_ixfers[] = { ST_TYPENAME_IDENTITY_TRANSFER_NAMES, NULL }; 200 const char *st_typename_cixfers[] = { ST_TYPENAME_CIDENTITY_TRANSFER_NAMES, NULL }; 201 const char *st_typename_pxfers[] = { ST_TYPENAME_PTR_TRANSFER_NAMES, NULL }; 202 const char *st_typename_sxfers[] = { ST_TYPENAME_STRUCT_TRANSFER_NAMES, NULL }; 203 const char *st_sentryname_ixfers[] = { ST_SENTRYNAME_IDENTITY_TRANSFER_NAMES, NULL }; 204 const char *st_sentryname_cixfers[] = { ST_SENTRYNAME_CIDENTITY_TRANSFER_NAMES, NULL}; 205 const char *st_sentryname_pxfers[] = { ST_SENTRYNAME_PTR_TRANSFER_NAMES, NULL }; 206 207 /* Exclude stack references in addition to the default sentry names from state transfer. */ 208 const char *st_sentryname_noxfers[] = { 209 ST_SENTRYNAME_NO_TRANSFER_NAMES, 210 #define __X(R) #R /* Stringify the symbol names. */ 211 ST_STACK_REFS_INT_LIST, 212 #if ST_STACK_REFS_CUSTOM_NUM > 0 213 ST_STACK_REFS_CUSTOM_LIST, 214 #endif 215 #undef __X 216 NULL }; 217 const char *st_sentryname_noxfers_mem[] = { ST_SENTRYNAME_NO_TRANSFER_MEM_NAMES, NULL }; 218 219 /* Exclude the data segments of certain libs from state transfer. */ 220 const char *st_dsentry_lib_noxfer[] = { 221 #ifdef ST_DSENTRYLIB_NO_TRANSFER_NAMES 222 ST_DSENTRYLIB_NO_TRANSFER_NAMES, 223 #endif 224 NULL }; 225 226 const char *st_typename_key_registrations[MAX_NUM_TYPENAMES]; 227 228 static int is_typename(const char *search_key, struct _magic_type *type) 229 { 230 unsigned int i; 231 /* We can't use a cached lookup result */ 232 if (!st_strcmp_wildcard(search_key, type->name)) { 233 /* The name matches */ 234 return TRUE; 235 } 236 for (i = 0 ; i < type->num_names ; i++) { 237 if(!st_strcmp_wildcard(search_key, type->names[i])) { 238 /* One of the typename names matches */ 239 return TRUE; 240 } 241 } 242 /* No match is found */ 243 return FALSE; 244 } 245 246 PUBLIC void st_register_typename_key(const char *key) 247 { 248 int i, is_registered = FALSE; 249 for(i = 0 ; i < MAX_NUM_TYPENAMES ; i++) { 250 if (st_typename_key_registrations[i] == NULL) { 251 st_typename_key_registrations[i] = key; 252 is_registered = TRUE; 253 break; 254 } 255 } 256 assert(is_registered && "Error, number of typename registrations > MAX_NUM_TYPENAMES.\n"); 257 } 258 259 PUBLIC void st_register_typename_keys(const char **keys) 260 { 261 int i = 0; 262 while (keys[i] != NULL) { 263 st_register_typename_key(keys[i]); 264 i++; 265 } 266 } 267 268 PRIVATE void set_typename_key(struct _magic_type *type) 269 { 270 const char **registration = st_typename_key_registrations; 271 272 while (*registration != NULL) { 273 if (is_typename(*registration, type)) { 274 type->ext = *registration; 275 break; 276 } 277 registration++; 278 } 279 } 280 281 PRIVATE void register_typenames(void) 282 { 283 284 int i; 285 286 /* Register typenames */ 287 st_register_typename_keys(st_typename_noxfers); 288 st_register_typename_keys(st_typename_ixfers); 289 st_register_typename_keys(st_typename_cixfers); 290 st_register_typename_keys(st_typename_pxfers); 291 st_register_typename_keys(st_typename_sxfers); 292 293 for(i = 0 ; i < _magic_types_num ; i++) { 294 set_typename_key(&_magic_types[i]); 295 } 296 297 } 298 299 PRIVATE INLINE void register_typenames_and_callbacks(void) 300 { 301 302 static int st_is_registered = FALSE; 303 if(st_is_registered) { 304 return; 305 } 306 307 register_typenames(); 308 309 st_setcb_selement_transfer(st_cb_transfer_sentry_default, ST_CB_TYPE_SENTRY); 310 st_setcb_selement_transfer(st_cb_transfer_typename_default, ST_CB_TYPE_TYPENAME); 311 312 st_is_registered = TRUE; 313 314 } 315 316 PRIVATE int st_type_name_match_any(const char **registered_type_name_keys, 317 const char *key) 318 { 319 int i = 0; 320 while (registered_type_name_keys[i] != NULL) { 321 if (ST_TYPE_NAME_MATCH(registered_type_name_keys[i], key)) { 322 return TRUE; 323 } 324 i++; 325 } 326 return FALSE; 327 } 328 329 PRIVATE int st_sentry_name_match_any(const char **sentry_wildcard_names, 330 const char *name) 331 { 332 int i = 0; 333 while (sentry_wildcard_names[i] != NULL) { 334 if (ST_SENTRY_NAME_MATCH(sentry_wildcard_names[i], name)) { 335 return TRUE; 336 } 337 i++; 338 } 339 return FALSE; 340 } 341 342 PRIVATE int st_dsentry_parent_name_match_any(const char **wildcard_names, 343 const char *name) 344 { 345 int i = 0; 346 while (wildcard_names[i] != NULL) { 347 if (ST_DSENTRY_PARENT_NAME_MATCH(wildcard_names[i], name)) { 348 return TRUE; 349 } 350 i++; 351 } 352 return FALSE; 353 } 354 355 /* Utilities. */ 356 PUBLIC void st_cb_print(int level, const char *msg, _magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 357 { 358 if (ST_CB_PRINT_LEVEL(level)) { 359 _magic_printf("[%s] %s. Current state element:\n", 360 ST_CB_LEVEL_TO_STR(level), msg); 361 MAGIC_SELEMENT_PRINT(selement, MAGIC_EXPAND_TYPE_STR); 362 _magic_printf("\n"); 363 MAGIC_SEL_ANALYZED_PRINT(sel_analyzed, MAGIC_EXPAND_TYPE_STR); 364 _magic_printf("\n"); 365 MAGIC_SEL_STATS_PRINT(sel_stats); 366 _magic_printf("\n\n"); 367 } 368 } 369 370 PUBLIC void st_cb_selement_type_cast(const struct _magic_type* new_selement_type, const struct _magic_type* new_local_selement_type, _magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 371 { 372 magic_selement_type_cast(selement, ST_SEL_ANALYZE_FLAGS, 373 new_selement_type, sel_analyzed, sel_stats); 374 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) { 375 cb_info->local_selement->type = new_local_selement_type; 376 } 377 } 378 379 /* Stack management. */ 380 381 PUBLIC void st_stack_refs_save_restore(char* stack_buff, int is_save) 382 { 383 struct _magic_dsentry *prev_dsentry, *dsentry; 384 struct _magic_sentry* sentry; 385 struct st_stack_refs_buff *buff_ptr; 386 int i; 387 388 #define __X(P) P 389 extern int ST_STACK_REFS_INT_LIST; 390 #undef __X 391 #define __X(P) ((int *)&(P)) 392 int* int_ptrs[] = { ST_STACK_REFS_INT_LIST, ST_STACK_REFS_CUSTOM_LIST }; 393 #undef __X 394 395 assert((ST_STACK_REFS_NUM) == sizeof(int_ptrs)/sizeof(int_ptrs[0])); 396 assert(sizeof(int) == sizeof(void*)); 397 buff_ptr = (struct st_stack_refs_buff*) stack_buff; 398 399 /* Save. */ 400 if (is_save) { 401 buff_ptr->first_stack_dsentry = _magic_first_stack_dsentry; 402 buff_ptr->last_stack_dsentry = _magic_last_stack_dsentry; 403 if (_magic_first_stack_dsentry) { 404 buff_ptr->first_stack_obdsentry_buff = *MAGIC_OBDSENTRY_FROM_DSENTRY(_magic_first_stack_dsentry); 405 } 406 memcpy(buff_ptr->stack_range, magic_stack_range, 2*sizeof(void*)); 407 for (i = 0 ; i < ST_STACK_REFS_NUM ; i++) { 408 memcpy(&buff_ptr->stack_int_refs[i], int_ptrs[i], sizeof(int)); 409 } 410 return; 411 } 412 413 /* Restore. */ 414 if (_magic_first_dsentry == _magic_last_stack_dsentry) { 415 _magic_first_dsentry = buff_ptr->last_stack_dsentry; 416 } 417 else { 418 MAGIC_DSENTRY_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry, 419 if (MAGIC_DSENTRY_HAS_NEXT(dsentry) 420 && MAGIC_DSENTRY_NEXT(dsentry) == _magic_last_stack_dsentry) { 421 MAGIC_DSENTRY_NEXT(dsentry) = buff_ptr->last_stack_dsentry; 422 break; 423 } 424 ); 425 } 426 427 _magic_first_stack_dsentry = buff_ptr->first_stack_dsentry; 428 _magic_last_stack_dsentry = buff_ptr->last_stack_dsentry; 429 if (_magic_first_stack_dsentry) { 430 *MAGIC_OBDSENTRY_FROM_DSENTRY(_magic_first_stack_dsentry) = buff_ptr->first_stack_obdsentry_buff; 431 } 432 memcpy(magic_stack_range, buff_ptr->stack_range, 2*sizeof(void*)); 433 for (i = 0 ; i < ST_STACK_REFS_NUM ; i++) { 434 memcpy(int_ptrs[i], &buff_ptr->stack_int_refs[i], sizeof(int)); 435 } 436 } 437 438 /* Metadata management. */ 439 PUBLIC int st_add_special_mmapped_region(void *address, size_t size, 440 const char* name) 441 { 442 struct _magic_obdsentry* obdsentry; 443 char addr_name[24]; 444 445 if (!_magic_enabled) return OK; 446 447 if (!name) { 448 snprintf(addr_name, sizeof(addr_name), "%%MMAP_0x%08x", 449 (unsigned int) address); 450 name = addr_name; 451 } 452 obdsentry = magic_create_obdsentry(address, MAGIC_VOID_TYPE, 453 size, MAGIC_STATE_MAP, name, NULL); 454 return obdsentry ? OK : EINVAL; 455 } 456 457 PUBLIC int st_del_special_mmapped_region_by_addr(void *address) 458 { 459 int ret; 460 461 if (!_magic_enabled) return OK; 462 463 ret = magic_destroy_obdsentry_by_addr(address); 464 if (ret < 0) { 465 return EINVAL; 466 } 467 return OK; 468 } 469 470 /* Selement transfer callbacks. */ 471 472 PRIVATE INLINE int transfer_walkable_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 473 { 474 /* Do nothing for complex type. process only its members, not the complex type itself */ 475 return MAGIC_SENTRY_ANALYZE_CONTINUE; 476 } 477 478 PRIVATE INLINE int transfer_try_raw_copy_sel_cb(_magic_selement_t *selement, struct st_cb_info *cb_info) 479 { 480 /* Only do raw copying if there are no type transformations. */ 481 if ((selement->type->num_child_types == 0 && selement->type->size == cb_info->local_selement->type->size) || selement->type == cb_info->local_selement->type || ST_TYPE_IS_CACHED_COUNTERPART(selement->type, cb_info->local_selement->type)) { 482 memcpy(cb_info->local_selement->address, selement->address, cb_info->local_selement->type->size); 483 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 484 } 485 486 return MAGIC_SENTRY_ANALYZE_CONTINUE; 487 } 488 489 PRIVATE INLINE int transfer_identity_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 490 { 491 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) { 492 /* First try to do raw copying, assuming there are no type transformations. */ 493 if (transfer_try_raw_copy_sel_cb(selement, cb_info) == MAGIC_SENTRY_ANALYZE_SKIP_PATH) 494 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 495 496 #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES 497 if (cb_info->init_info->flags & ST_LU_ASR) { 498 st_cbs_os.panic("ASR should never get here!"); 499 } 500 #endif 501 if (selement->type->type_id == MAGIC_TYPE_UNION) { 502 ST_CB_PRINT(ST_CB_ERR, "uncaught ixfer union with type changes", selement, sel_analyzed, sel_stats, cb_info); 503 return EFAULT; 504 } 505 cb_info->st_cb_flags |= ST_CB_FORCE_IXFER; 506 return MAGIC_SENTRY_ANALYZE_CONTINUE; 507 } 508 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 509 } 510 511 PRIVATE INLINE int transfer_cond_identity_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 512 { 513 int r; 514 int saved_flags = cb_info->st_cb_flags; 515 cb_info->st_cb_flags &= ~ST_CB_PRINT_ERR; 516 r = default_transfer_selement_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 517 cb_info->st_cb_flags = saved_flags; 518 if (r < 0) { 519 ST_CB_PRINT(ST_CB_DBG, "conditional ixfer resorting to ixfer", selement, sel_analyzed, sel_stats, cb_info); 520 return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 521 } 522 return r; 523 } 524 525 PRIVATE INLINE int transfer_nonptr_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 526 { 527 if (sel_analyzed->flags & MAGIC_SEL_FOUND_VIOLATIONS) { 528 ST_CB_PRINT(ST_CB_ERR, "uncaught non-ptr with violations", selement, sel_analyzed, sel_stats, cb_info); 529 return EFAULT; 530 } 531 return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 532 } 533 534 PRIVATE int transfer_ptr_sel_with_trg_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 535 { 536 int trg_flags, trg_extf_flags, trg_transferred, trg_paired; 537 _magic_selement_t cached_trg_selement, local_trg_selement; 538 void **local_selement_address = cb_info->local_selement->address; 539 int r; 540 541 r = lookup_trg_info(selement, sel_analyzed, sel_stats, cb_info, &cached_trg_selement, &local_trg_selement); 542 if (r != OK) { 543 return r; 544 } 545 546 trg_flags = sel_analyzed->u.ptr.trg_flags; 547 trg_extf_flags = MAGIC_STATE_FLAGS_TO_EXTF(trg_flags); 548 trg_transferred = (trg_extf_flags & (ST_NEEDS_TRANSFER | ST_TRANSFER_DONE)); 549 trg_paired = (local_trg_selement.type != NULL); 550 551 if (!trg_transferred && trg_paired && (trg_extf_flags & ST_ON_PTRXFER_CASCADE)) { 552 /* Propagate transfer on the target. */ 553 if (cached_trg_selement.sentry && !(trg_extf_flags & ST_NEEDS_TRANSFER)) { 554 ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in cascade transfer for the target", selement, sel_analyzed, sel_stats, cb_info); 555 st_set_status_by_sentry_id(ST_NEEDS_TRANSFER, ST_OP_ADD, MAGIC_SENTRY_ID(cached_trg_selement.sentry)); 556 } 557 /* Force code below to transfer the pointer normally. */ 558 trg_transferred = TRUE; 559 } 560 561 if (trg_transferred && trg_paired) { 562 *local_selement_address = local_trg_selement.address; 563 } 564 else if (trg_extf_flags & ST_ON_PTRXFER_SET_NULL) { 565 ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in forcefully setting ptr to NULL", selement, sel_analyzed, sel_stats, cb_info); 566 *local_selement_address = NULL; 567 } 568 else if(trg_extf_flags & ST_ON_PTRXFER_SET_DEFAULT) { 569 ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in forcefully setting ptr to default value", selement, sel_analyzed, sel_stats, cb_info); 570 if (trg_flags & MAGIC_STATE_STRING) { 571 *((char**)local_selement_address) = __UNCONST(""); 572 } 573 else { 574 *local_selement_address = NULL; 575 } 576 } 577 else if (trg_extf_flags & ST_ON_PTRXFER_SKIP) { 578 ST_CB_PRINT(ST_CB_DBG, "ptr lookup results in skipping ptr transfer", selement, sel_analyzed, sel_stats, cb_info); 579 } 580 else { 581 if (trg_paired) { 582 ST_CB_PRINT(ST_CB_ERR, "uncaught ptr lookup for non-transferred target", selement, sel_analyzed, sel_stats, cb_info); 583 } 584 else { 585 ST_CB_PRINT(ST_CB_ERR, "uncaught ptr lookup for unpaired target", selement, sel_analyzed, sel_stats, cb_info); 586 } 587 #if DO_SKIP_UNPAIRED_PTR_TARGETS 588 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 589 #else 590 return ENOENT; 591 #endif 592 } 593 594 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 595 } 596 597 PRIVATE INLINE int transfer_ptr_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 598 { 599 const struct _magic_type *first_trg_type; 600 if (selement->type->type_id != MAGIC_TYPE_POINTER) { 601 if (selement->type->size != sizeof(void*)) { 602 ST_CB_PRINT(ST_CB_ERR, "wrong pointer size", selement, sel_analyzed, sel_stats, cb_info); 603 return EFAULT; 604 } 605 ST_CB_PRINT(ST_CB_DBG, "casting non-ptr to ptr element", selement, sel_analyzed, sel_stats, cb_info); 606 st_cb_selement_type_cast(MAGIC_VOID_PTR_INT_CAST_TYPE, MAGIC_VOID_PTR_INT_CAST_TYPE, selement, sel_analyzed, sel_stats, cb_info); 607 } 608 first_trg_type = MAGIC_SEL_ANALYZED_PTR_FIRST_TRG_TYPE(sel_analyzed); 609 if (first_trg_type == MAGIC_TYPE_NULL_ENTRY 610 || first_trg_type == MAGIC_TYPE_VALUE_FOUND) { 611 612 /* NULL pointer or special value. Don't adjust value */ 613 return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 614 615 } else if (!(sel_analyzed->flags & MAGIC_SEL_FOUND_VIOLATIONS)) { 616 /* Valid pointer found */ 617 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) { 618 return transfer_ptr_sel_with_trg_cb(selement, sel_analyzed, sel_stats, cb_info); 619 } 620 621 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 622 623 } else if(MAGIC_STATE_FLAG(selement->sentry, MAGIC_STATE_STACK)) { 624 struct _magic_sentry *trg_sentry = magic_sentry_lookup_by_range(sel_analyzed->u.ptr.value, NULL); 625 if (trg_sentry && !strcmp(trg_sentry->name, MAGIC_ALLOC_INITIAL_STACK_NAME)) { 626 /* Stack pointer to initial stack area. This is common (e.g., argv). 627 * We can safely assume the pointer will be already correctly 628 * initialized in the new version and simply skip transfer. 629 */ 630 ST_CB_PRINT(ST_CB_DBG, "skipping stack ptr element pointing to initial stack area", selement, sel_analyzed, sel_stats, cb_info); 631 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 632 } 633 } 634 #ifdef __MINIX 635 #define IS_KERNEL_PTR(p) (((intptr_t)(p) & 0xf0000000) == 0xf0000000) /* TODO: make this more dynamic */ 636 else if (IS_KERNEL_PTR(sel_analyzed->u.ptr.value)) 637 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; /* Kernel-mapped pointer */ 638 #endif 639 640 /* Pointer with violations found */ 641 ST_CB_PRINT(ST_CB_ERR, "uncaught ptr with violations", selement, sel_analyzed, sel_stats, cb_info); 642 #if DO_SKIP_INVARIANTS_VIOLATIONS 643 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 644 #else 645 return EFAULT; 646 #endif 647 } 648 649 PRIVATE INLINE int transfer_struct_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 650 { 651 static int st_counter = 0; 652 unsigned parent_offset, offset; 653 int walk_flags, ret; 654 655 if (selement->type->type_id != MAGIC_TYPE_UNION && selement->type->type_id != MAGIC_TYPE_STRUCT) { 656 ST_CB_PRINT(ST_CB_ERR, "struct transfer is only for structs and unions!", selement, sel_analyzed, sel_stats, cb_info); 657 return EFAULT; 658 } 659 if (selement->type->type_id == MAGIC_TYPE_STRUCT || st_counter > 0) { 660 return MAGIC_SENTRY_ANALYZE_CONTINUE; 661 } 662 663 /* Walk the union as a struct. */ 664 walk_flags = cb_info->walk_flags; 665 cb_info->walk_flags = (MAGIC_TYPE_WALK_DEFAULT_FLAGS & (~MAGIC_TYPE_WALK_UNIONS_AS_VOID)); 666 st_counter++; 667 parent_offset = (unsigned)selement->parent_address - (unsigned)selement->sentry->address; 668 offset = (unsigned)selement->address - (unsigned)selement->sentry->address; 669 ret = magic_type_walk_flags(selement->parent_type, parent_offset, 670 selement->child_num, selement->type, offset, 671 0, ULONG_MAX, magic_type_analyzer_cb, selement->cb_args, cb_info->walk_flags); 672 st_counter--; 673 cb_info->walk_flags = walk_flags; 674 if (ret != 0) { 675 return ret == MAGIC_TYPE_WALK_STOP ? MAGIC_SENTRY_ANALYZE_STOP : ret; 676 } 677 678 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 679 } 680 681 PRIVATE INLINE int default_transfer_selement_sel_cb(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 682 { 683 /* Default handler for walkable, ptr and nonptr types. */ 684 #if ST_TRANSFER_IDENTITY_FOR_NO_INNER_PTRS 685 if (MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_NO_INNER_PTRS)) { 686 /* If the type has no inner pointers, try to do raw copying. */ 687 if (transfer_try_raw_copy_sel_cb(selement, cb_info) == MAGIC_SENTRY_ANALYZE_SKIP_PATH) 688 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 689 } 690 #endif 691 if (selement->type->type_id == MAGIC_TYPE_UNION) { 692 if (!(st_policies & ST_IXFER_UNCAUGHT_UNIONS) && !MAGIC_TYPE_FLAG(selement->type, MAGIC_TYPE_NO_INNER_PTRS)) { 693 ST_CB_PRINT(ST_CB_ERR, "uncaught union", selement, sel_analyzed, sel_stats, cb_info); 694 return EFAULT; 695 } 696 else { 697 int level = (st_policies & ST_REPORT_UNCAUGHT_UNIONS) ? ST_CB_ERR : ST_CB_DBG; 698 ST_CB_PRINT(level, "uncaught union", selement, sel_analyzed, sel_stats, cb_info); 699 return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 700 } 701 } else if (MAGIC_TYPE_IS_WALKABLE(selement->type)) { 702 return transfer_walkable_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 703 } else if (selement->type->type_id == MAGIC_TYPE_POINTER) { 704 return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 705 } else { 706 return transfer_nonptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 707 } 708 709 /* Not reachable. */ 710 ST_CB_PRINT(ST_CB_ERR, "Bug!", selement, sel_analyzed, sel_stats, cb_info); 711 return EINTR; 712 } 713 714 PUBLIC int st_cb_transfer_sentry_default(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 715 { 716 const char *sentry_name = selement->sentry->name; 717 718 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 719 if (MAGIC_STATE_FLAGS(selement->sentry, MAGIC_STATE_DYNAMIC)) { 720 if (MAGIC_STATE_FLAG(selement->sentry, MAGIC_STATE_LIB) || MAGIC_SENTRY_IS_EXT_ALLOC(selement->sentry)) 721 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 722 } 723 #endif 724 725 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_ixfers, sentry_name)) { 726 ST_CB_PRINT(ST_CB_DBG, "sentry name matches ixfer", selement, sel_analyzed, sel_stats, cb_info); 727 return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 728 } 729 730 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_cixfers, sentry_name)) { 731 ST_CB_PRINT(ST_CB_DBG, "sentry name matches cixfer", selement, sel_analyzed, sel_stats, cb_info); 732 return transfer_cond_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 733 } 734 735 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_noxfers, sentry_name)) { 736 ST_CB_PRINT(ST_CB_DBG, "sentry name matches noxfer", selement, sel_analyzed, sel_stats, cb_info); 737 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 738 } 739 740 /* Skip memory management related sentries only when memory functions have 741 * been instrumented (which is *not* the case for the MINIX3 VM service). 742 */ 743 if (_magic_no_mem_inst == 0 && ST_SENTRY_NAME_MATCH_ANY(st_sentryname_noxfers_mem, sentry_name)) { 744 ST_CB_PRINT(ST_CB_DBG, "sentry name matches noxfer", selement, sel_analyzed, sel_stats, cb_info); 745 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 746 } 747 748 if (ST_SENTRY_NAME_MATCH_ANY(st_sentryname_pxfers, sentry_name)) { 749 ST_CB_PRINT(ST_CB_DBG, "sentry name matches pxfer", selement, sel_analyzed, sel_stats, cb_info); 750 return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 751 } 752 753 if (MAGIC_STATE_FLAGS(selement->sentry, MAGIC_STATE_DYNAMIC | MAGIC_STATE_MAP | MAGIC_STATE_LIB)) { 754 struct _magic_dsentry *dsentry = MAGIC_DSENTRY_FROM_SENTRY(selement->sentry); 755 if (ST_DSENTRY_PARENT_NAME_MATCH_ANY(st_dsentry_lib_noxfer, dsentry->parent_name)) { 756 ST_CB_PRINT(ST_CB_DBG, "dsentry is a lib map and parent_name matches dsentry_lib_noxfer", selement, sel_analyzed, sel_stats, cb_info); 757 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 758 } 759 } 760 761 return ST_CB_NOT_PROCESSED; 762 } 763 764 PUBLIC int st_cb_transfer_typename_default(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 765 { 766 const char *typename_key = ST_TYPE_NAME_KEY(selement->type); 767 if (ST_TYPE_NAME_MATCH_ANY(st_typename_ixfers, typename_key)) { 768 return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 769 } 770 771 if (ST_TYPE_NAME_MATCH_ANY(st_typename_cixfers, typename_key)) { 772 return transfer_cond_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 773 } 774 775 if (ST_TYPE_NAME_MATCH_ANY(st_typename_noxfers, typename_key)) { 776 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 777 } 778 779 if (ST_TYPE_NAME_MATCH_ANY(st_typename_pxfers, typename_key)) { 780 return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 781 } 782 783 if (ST_TYPE_NAME_MATCH_ANY(st_typename_sxfers, typename_key)) { 784 return transfer_struct_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 785 } 786 787 return ST_CB_NOT_PROCESSED; 788 } 789 790 PUBLIC int st_cb_transfer_walkable(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 791 { 792 return transfer_walkable_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 793 } 794 795 PUBLIC int st_cb_transfer_ptr(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 796 { 797 return transfer_ptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 798 } 799 800 PUBLIC int st_cb_transfer_identity(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 801 { 802 return transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 803 } 804 805 PUBLIC int st_cb_transfer_cond_identity(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 806 { 807 return transfer_cond_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 808 } 809 810 PUBLIC int st_cb_transfer_nonptr(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 811 { 812 return transfer_nonptr_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 813 } 814 815 PUBLIC int st_cb_transfer_struct(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 816 { 817 return transfer_struct_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 818 } 819 820 PUBLIC int st_cb_transfer_selement_base(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 821 { 822 return default_transfer_selement_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 823 } 824 825 PUBLIC int st_cb_transfer_selement_generic(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info) 826 { 827 return transfer_data_selement(selement, sel_analyzed, sel_stats, cb_info); 828 } 829 830 /* Selement mapping functions and callbacks. */ 831 832 PRIVATE int st_map_selement_from_sentry_cb(const struct _magic_type* parent_type, 833 const unsigned parent_offset, int child_num, 834 const struct _magic_type* type, const unsigned offset, int depth, void* cb_args) 835 { 836 void **args_array = (void**) cb_args; 837 _magic_selement_t cached_selement; 838 _magic_selement_t *local_selement = (_magic_selement_t*) args_array[1]; 839 _magic_selement_t *selement = (_magic_selement_t*) args_array[0]; 840 struct _magic_sentry *sentry = selement->sentry; 841 void *address = (char*)sentry->address + offset; 842 void *selement_address = selement->address; 843 int is_trg_mapping; 844 struct st_cb_info *cb_info; 845 if ((char*) selement_address >= ((char*) address + type->size)) { 846 return MAGIC_TYPE_WALK_SKIP_PATH; 847 } 848 cb_info = (struct st_cb_info*) args_array[2]; 849 is_trg_mapping = (int) args_array[3]; 850 cached_selement.sentry = sentry; 851 cached_selement.parent_type = parent_type; 852 cached_selement.parent_address = (char*)sentry->address + parent_offset; 853 cached_selement.child_num = child_num; 854 cached_selement.type = type; 855 cached_selement.address = address; 856 cached_selement.depth = depth; 857 st_map_selement(&cached_selement, local_selement, cb_info, is_trg_mapping); 858 if (local_selement->type == NULL) { 859 return ENOENT; 860 } 861 if (address == selement_address && type == selement->type) { 862 return MAGIC_TYPE_WALK_STOP; 863 } 864 if (type->num_child_types == 0) { 865 return EINVAL; 866 } 867 local_selement->parent_type = local_selement->type; 868 local_selement->parent_address = local_selement->address; 869 return MAGIC_TYPE_WALK_CONTINUE; 870 } 871 872 PRIVATE INLINE void st_map_selement_from_sentry(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct _magic_sentry *local_sentry, struct st_cb_info *cb_info, int is_trg_mapping) 873 { 874 unsigned max_offset; 875 int r; 876 void *args_array[4]; 877 max_offset = (unsigned) ( (char *)cached_selement->address - (char *)cached_selement->sentry->address); 878 args_array[0] = cached_selement; 879 args_array[1] = magic_selement_from_sentry(local_sentry, local_selement); 880 args_array[2] = cb_info; 881 args_array[3] = (void*) is_trg_mapping; 882 r = magic_type_walk_root(cached_selement->sentry->type, 0, max_offset, st_map_selement_from_sentry_cb, (void*) args_array); 883 if (r < 0) { 884 assert(r == ENOENT); 885 local_selement->type = NULL; 886 } 887 } 888 889 PRIVATE INLINE void st_map_sel_analyzed_from_target(_magic_sel_analyzed_t *cached_sel_analyzed, _magic_sel_analyzed_t *local_sel_analyzed, struct _magic_sentry *local_trg_sentry, struct _magic_function *local_trg_function, struct st_cb_info *cb_info) 890 { 891 _magic_selement_t *csel, *lsel; 892 assert(local_trg_sentry || local_trg_function); 893 assert(cached_sel_analyzed->type_id == MAGIC_TYPE_POINTER); 894 assert(cached_sel_analyzed->u.ptr.first_legal_trg_type>=0); 895 local_sel_analyzed->type_id = cached_sel_analyzed->type_id; 896 local_sel_analyzed->num = cached_sel_analyzed->num; 897 local_sel_analyzed->flags = cached_sel_analyzed->flags; 898 local_sel_analyzed->u.ptr.trg_flags = local_trg_sentry ? local_trg_sentry->flags : local_trg_function->flags; 899 local_sel_analyzed->u.ptr.first_legal_trg_type = -1; 900 local_sel_analyzed->u.ptr.num_legal_trg_types = 0; 901 if (local_trg_function) { 902 assert(cached_sel_analyzed->u.ptr.num_legal_trg_types == 1); 903 lsel = &local_sel_analyzed->u.ptr.trg_selements[0]; 904 memset(lsel, 0, sizeof(_magic_selement_t)); 905 lsel->sentry = NULL; 906 lsel->type = local_trg_function->type; 907 lsel->address = local_trg_function->address; 908 local_sel_analyzed->u.ptr.num_trg_types = 1; 909 } 910 else { 911 unsigned int i; 912 void *address = NULL; 913 local_sel_analyzed->u.ptr.num_trg_types = 0; 914 for (i = cached_sel_analyzed->u.ptr.first_legal_trg_type ; i < cached_sel_analyzed->u.ptr.num_trg_types ; i++) { 915 _magic_trg_stats_t trg_stats = cached_sel_analyzed->u.ptr.trg_stats[i]; 916 if (MAGIC_SEL_ANALYZED_TRG_STATS_HAS_VIOLATIONS(trg_stats)) { 917 continue; 918 } 919 csel = &cached_sel_analyzed->u.ptr.trg_selements[i]; 920 lsel = &local_sel_analyzed->u.ptr.trg_selements[local_sel_analyzed->u.ptr.num_trg_types++]; 921 st_map_selement_from_sentry(csel, lsel, local_trg_sentry, cb_info, TRUE); 922 if (lsel->type == NULL || (address && lsel->address != address)) { 923 /* Unpaired selement or ambiguous local address. */ 924 local_sel_analyzed->u.ptr.num_trg_types = 0; 925 return; 926 } 927 address = lsel->address; 928 } 929 assert(local_sel_analyzed->u.ptr.num_trg_types > 0); 930 } 931 } 932 933 PUBLIC void st_map_local_selement_from_child_num(_magic_selement_t *local_selement, struct st_cb_info *cb_info, int child_num) 934 { 935 local_selement->child_num = child_num; 936 magic_selement_fill_from_parent_info(local_selement, cb_info->walk_flags); 937 } 938 939 PUBLIC void st_cb_map_from_parent_array_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 940 { 941 int cached_num_elements, local_num_elements, is_trg_at_array_end, is_trg_at_str_end; 942 /* Match arrays/vectors with arrays/vectors. */ 943 assert(cached_selement->parent_type->type_id == MAGIC_TYPE_ARRAY || cached_selement->parent_type->type_id == MAGIC_TYPE_VECTOR); 944 if (local_selement->parent_type->type_id != MAGIC_TYPE_ARRAY && local_selement->parent_type->type_id != MAGIC_TYPE_VECTOR) { 945 local_selement->type = NULL; 946 return; 947 } 948 cached_num_elements = cached_selement->parent_type->num_child_types; 949 local_num_elements = local_selement->parent_type->num_child_types; 950 /* Same size or first child? We are done. */ 951 if (cached_num_elements == local_num_elements || local_selement->child_num == 0) { 952 st_map_local_selement_from_child_num(local_selement, cb_info, cached_selement->child_num); 953 return; 954 } 955 assert(local_num_elements > 0); 956 is_trg_at_str_end = FALSE; 957 is_trg_at_array_end = FALSE; 958 if (is_trg_mapping && cached_selement->child_num == cached_num_elements-1) { 959 is_trg_at_str_end = MAGIC_SENTRY_IS_STRING(cached_selement->sentry) || MAGIC_SENTRY_IS_STRING(local_selement->sentry); 960 is_trg_at_array_end = !is_trg_at_str_end; 961 } 962 if (is_trg_at_array_end && (st_policies & ST_DEFAULT_MAP_GUARD_PTRS_TO_ARRAY_END)) { 963 /* This should be interpreted as a target of a guard pointer pointing to the last element of an array and needs to be remapped as such. */ 964 st_map_local_selement_from_child_num(local_selement, cb_info, local_num_elements-1); 965 } 966 else if (is_trg_at_str_end && (st_policies & ST_DEFAULT_MAP_GUARD_PTRS_TO_STR_END)) { 967 /* This should be interpreted as a target of a guard pointer pointing to the last element of a string and needs to be remapped as such. */ 968 st_map_local_selement_from_child_num(local_selement, cb_info, local_num_elements-1); 969 } 970 else if (cached_selement->child_num >= local_num_elements) { 971 /* New array got truncated and this element is gone. */ 972 local_selement->type = NULL; 973 } 974 else { 975 /* New array is bigger, just keep the original position in the array. */ 976 st_map_local_selement_from_child_num(local_selement, cb_info, cached_selement->child_num); 977 } 978 } 979 980 PUBLIC void st_cb_map_child_array_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 981 { 982 size_t cached_size = cached_selement->type->num_child_types, local_size = local_selement->type->num_child_types; 983 984 /* Match arrays/vectors with arrays/vectors. */ 985 assert(cached_selement->type->type_id == MAGIC_TYPE_ARRAY || cached_selement->type->type_id == MAGIC_TYPE_VECTOR); 986 if (local_selement->type->type_id != MAGIC_TYPE_ARRAY && local_selement->type->type_id != MAGIC_TYPE_VECTOR) { 987 local_selement->type = NULL; 988 return; 989 } 990 991 /* Varsized arrays have to be consistent across versions. */ 992 if (MAGIC_TYPE_FLAG(cached_selement->type, MAGIC_TYPE_VARSIZE) != MAGIC_TYPE_FLAG(local_selement->type, MAGIC_TYPE_VARSIZE)) { 993 local_selement->type = NULL; 994 return; 995 } 996 997 /* Check size. */ 998 if (cached_size != local_size) { 999 int report; 1000 int is_string = MAGIC_SENTRY_IS_STRING(cached_selement->sentry) || MAGIC_SENTRY_IS_STRING(local_selement->sentry); 1001 if (local_size < cached_size) { 1002 report = is_string ? (st_policies & ST_REPORT_SMALLER_STRINGS) : (st_policies & ST_REPORT_SMALLER_ARRAYS); 1003 } 1004 else { 1005 report = is_string ? (st_policies & ST_REPORT_LARGER_STRINGS) : (st_policies & ST_REPORT_LARGER_ARRAYS); 1006 } 1007 1008 if (report) { 1009 printf("st_cb_map_child_array_selement_generic: %s size found while mapping array selements:\n", local_size < cached_size ? "Smaller" : "Larger"); 1010 MAGIC_SELEMENT_PRINT(cached_selement, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1011 MAGIC_SELEMENT_PRINT(local_selement, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1012 } 1013 } 1014 } 1015 1016 PUBLIC void st_cb_map_from_parent_union_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1017 { 1018 /* This should only be called in case of unions transferred as structs. */ 1019 st_cb_map_from_parent_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1020 } 1021 1022 PUBLIC void st_cb_map_child_union_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1023 { 1024 /* Match unions just like structs. */ 1025 st_cb_map_child_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1026 } 1027 1028 PUBLIC void st_cb_map_from_parent_struct_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1029 { 1030 unsigned int i; 1031 const char *cached_member_name; 1032 /* Match struct/unions with struct/unions. */ 1033 assert(cached_selement->parent_type->type_id == MAGIC_TYPE_STRUCT || cached_selement->parent_type->type_id == MAGIC_TYPE_UNION); 1034 if (local_selement->parent_type->type_id != MAGIC_TYPE_STRUCT && local_selement->parent_type->type_id != MAGIC_TYPE_UNION) { 1035 local_selement->type = NULL; 1036 return; 1037 } 1038 /* Match struct/unions members by name. */ 1039 cached_member_name = cached_selement->parent_type->member_names[cached_selement->child_num]; 1040 for (i = 0 ; i < local_selement->parent_type->num_child_types ; i++) { 1041 if (!strcmp(local_selement->parent_type->member_names[i], cached_member_name)) { 1042 st_map_local_selement_from_child_num(local_selement, cb_info, i); 1043 return; 1044 } 1045 } 1046 local_selement->type = NULL; 1047 } 1048 1049 PUBLIC void st_cb_map_child_struct_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1050 { 1051 unsigned int i, j; 1052 const struct _magic_type *cached_type = cached_selement->type; 1053 const struct _magic_type *local_type = local_selement->type; 1054 assert(cached_type->type_id == MAGIC_TYPE_STRUCT || cached_type->type_id == MAGIC_TYPE_UNION); 1055 if (local_type->type_id != MAGIC_TYPE_STRUCT && local_type->type_id != MAGIC_TYPE_UNION) { 1056 local_selement->type = NULL; 1057 return; 1058 } 1059 /* Match struct/unions by name(s). */ 1060 if (!strcmp(cached_type->name, local_type->name)) { 1061 return; 1062 } 1063 if (cached_type->num_names > 1 || local_type->num_names > 1 ) { 1064 for (i = 0 ; i < cached_type->num_names ; i++) { 1065 for (j = 0 ; j < local_type->num_names ; j++) { 1066 if (!strcmp(cached_type->names[i], local_type->names[j])) { 1067 return; 1068 } 1069 } 1070 } 1071 } 1072 1073 local_selement->type = NULL; 1074 } 1075 1076 PUBLIC void st_cb_map_child_nonaggr_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1077 { 1078 int r; 1079 static char magic_value_buffer[32]; 1080 1081 r = magic_selement_value_cast(cached_selement, local_selement, magic_value_buffer); 1082 if (r == 0) { 1083 return; 1084 } 1085 if (r < 0 && r != MAGIC_ERANGE && r != MAGIC_ESIGN) { 1086 local_selement->type = NULL; 1087 return; 1088 } 1089 if ((r == MAGIC_ERANGE && (st_policies & ST_REPORT_PRECISION_LOSS)) 1090 || (r == MAGIC_ESIGN && (st_policies & ST_REPORT_SIGN_CHANGE))) { 1091 _magic_selement_t converted_selement = *cached_selement; 1092 converted_selement.address = magic_value_buffer; 1093 converted_selement.type = local_selement->type; 1094 printf("st_cb_map_child_nonaggr_selement_generic: %s while mapping non-aggregate selements:\n", r == MAGIC_ERANGE ? "Precision loss" : "Sign change"); 1095 MAGIC_SELEMENT_PRINT(cached_selement, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1096 MAGIC_SELEMENT_PRINT(local_selement, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1097 printf(" - ORIGINAL VALUE: "); magic_selement_print_value(cached_selement); printf("\n"); 1098 printf(" - MAPPED VALUE: "); magic_selement_print_value(&converted_selement); printf("\n"); 1099 } 1100 cached_selement->address = magic_value_buffer; 1101 } 1102 1103 PUBLIC void st_cb_map_from_parent_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1104 { 1105 assert(cached_selement->parent_type && local_selement->parent_type); 1106 switch(cached_selement->parent_type->type_id) { 1107 case MAGIC_TYPE_ARRAY: 1108 case MAGIC_TYPE_VECTOR: 1109 st_cb_map_from_parent_array_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1110 break; 1111 1112 case MAGIC_TYPE_UNION: 1113 st_cb_map_from_parent_union_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1114 break; 1115 1116 case MAGIC_TYPE_STRUCT: 1117 st_cb_map_from_parent_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1118 break; 1119 1120 default: 1121 st_cbs_os.panic("Invalid parent type!"); 1122 break; 1123 } 1124 } 1125 1126 PUBLIC void st_cb_map_child_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1127 { 1128 assert(cached_selement->type); 1129 if (local_selement->type == NULL) { 1130 return; 1131 } 1132 if (cached_selement->type->num_child_types == 0 || cached_selement->type->type_id == MAGIC_TYPE_POINTER) { 1133 st_cb_map_child_nonaggr_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1134 return; 1135 } 1136 switch (cached_selement->type->type_id) { 1137 case MAGIC_TYPE_ARRAY: 1138 case MAGIC_TYPE_VECTOR: 1139 st_cb_map_child_array_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1140 break; 1141 1142 case MAGIC_TYPE_UNION: 1143 st_cb_map_child_union_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1144 break; 1145 1146 case MAGIC_TYPE_STRUCT: 1147 st_cb_map_child_struct_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1148 break; 1149 1150 default: 1151 st_cbs_os.panic("Invalid parent type!"); 1152 break; 1153 } 1154 } 1155 1156 1157 PUBLIC void st_cb_map_selement_generic(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1158 { 1159 int i; 1160 assert(cached_selement->type->type_id != MAGIC_TYPE_FUNCTION); 1161 for (i = 0 ; i < MAGIC_ST_TYPE_TRANS_ITERATIONS ; i++) { 1162 if (cached_selement->parent_type) { 1163 st_cb_map_from_parent_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1164 } 1165 st_cb_map_child_selement_generic(cached_selement, local_selement, cb_info, is_trg_mapping); 1166 } 1167 } 1168 1169 PRIVATE INLINE void st_map_selement(_magic_selement_t *cached_selement, _magic_selement_t *local_selement, struct st_cb_info *cb_info, int is_trg_mapping) 1170 { 1171 const struct _magic_type *cached_parent_type = cached_selement->parent_type; 1172 const struct _magic_type *local_parent_type = local_selement->parent_type; 1173 const struct _magic_type *cached_type = cached_selement->type; 1174 1175 if (cached_parent_type) { 1176 if (cached_parent_type == local_parent_type) { 1177 /* Quickly propagate perfect type pairs from parents. */ 1178 local_selement->address = (char *)local_selement->parent_address + ((char *)cached_selement->address - (char *)cached_selement->parent_address); 1179 local_selement->type = cached_type; 1180 return; 1181 } 1182 else if (ST_TYPE_IS_CACHED_COUNTERPART(cached_parent_type, local_parent_type)) { 1183 /* Quickly propagate type pairs from parents. */ 1184 st_map_local_selement_from_child_num(local_selement, cb_info, cached_selement->child_num); 1185 return; 1186 } 1187 else { 1188 local_selement->type = NULL; 1189 } 1190 } 1191 else { 1192 /* In case of target mapping, we don't care about compatible types. When paired types are found, add a perfect type pair to speed up subsequent lookups. */ 1193 if (ST_TYPE_IS_CACHED_COUNTERPART(cached_type, local_selement->type)) { 1194 if (is_trg_mapping) local_selement->type = cached_type; 1195 return; 1196 } 1197 } 1198 #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES 1199 if (cb_info->init_info->flags & ST_LU_ASR) { 1200 st_cbs_os.panic("ASR should never get here!"); 1201 } 1202 #endif 1203 1204 st_num_type_transformations++; 1205 st_cbs.st_cb_selement_map(cached_selement, local_selement, cb_info, is_trg_mapping); 1206 1207 /* Check again for paired types and add a perfect type pair to speed up subsequent lookups in case of target mapping. */ 1208 if (is_trg_mapping && local_selement->type != NULL && local_selement->type != cached_selement->type) { 1209 if (ST_TYPE_IS_CACHED_COUNTERPART(cached_selement->type, local_selement->type)) { 1210 local_selement->type = cached_selement->type; 1211 } 1212 } 1213 } 1214 1215 /* main functions */ 1216 1217 PUBLIC int st_state_transfer(st_init_info_t *info) 1218 { 1219 int r; 1220 1221 /* 1222 * Set all OS dependent callbacks first. 1223 */ 1224 st_setcb_os_all(&info->st_cbs_os); 1225 1226 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 1227 _magic_vars->fake_malloc = 1; 1228 #endif 1229 1230 r = st_init(info); 1231 1232 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 1233 _magic_vars->fake_malloc = 0; 1234 #endif 1235 1236 if (r != OK) { 1237 return r; 1238 } 1239 1240 r = st_data_transfer(info); 1241 if (r != OK) { 1242 return r; 1243 } 1244 1245 #if ST_DEBUG_LEVEL > 0 1246 printf("st_state_transfer: state transfer is done, num type transformations: %u.\n", st_num_type_transformations); 1247 #endif 1248 1249 st_cleanup(info); 1250 1251 return OK; 1252 } 1253 1254 #if APPARENTLY_UNUSED 1255 PUBLIC void st_set_policies(int policies) 1256 { 1257 st_policies = policies; 1258 } 1259 #endif 1260 1261 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX 1262 PRIVATE void st_init_rl_index(st_init_info_t *info, 1263 struct _magic_vars_t *magic_vars) 1264 { 1265 size_t buff_size; 1266 void *buff; 1267 1268 EXEC_WITH_MAGIC_VARS( 1269 buff_size = magic_sentry_rl_estimate_index_buff_size(0); 1270 , magic_vars 1271 ); 1272 buff = st_buff_allocate(info, buff_size); 1273 1274 EXEC_WITH_MAGIC_VARS( 1275 magic_sentry_rl_build_index(buff, buff_size); 1276 , magic_vars 1277 ); 1278 } 1279 1280 PRIVATE void st_cleanup_rl_index(st_init_info_t *info, 1281 struct _magic_vars_t *magic_vars) 1282 { 1283 EXEC_WITH_MAGIC_VARS( 1284 magic_sentry_rl_destroy_index(); 1285 , magic_vars 1286 ); 1287 } 1288 #endif 1289 1290 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH 1291 PRIVATE void st_init_sentry_hash(st_init_info_t *info, 1292 struct _magic_vars_t *magic_vars) 1293 { 1294 size_t buff_size; 1295 void *buff; 1296 1297 EXEC_WITH_MAGIC_VARS( 1298 buff_size = magic_sentry_hash_estimate_buff_size(0); 1299 , magic_vars 1300 ); 1301 buff = st_buff_allocate(info, buff_size); 1302 1303 EXEC_WITH_MAGIC_VARS( 1304 magic_sentry_hash_build(buff, buff_size); 1305 , magic_vars 1306 ); 1307 } 1308 1309 PRIVATE void st_cleanup_sentry_hash(st_init_info_t *info, 1310 struct _magic_vars_t *magic_vars) 1311 { 1312 EXEC_WITH_MAGIC_VARS( 1313 magic_sentry_hash_destroy(); 1314 , magic_vars 1315 ); 1316 } 1317 #endif 1318 1319 #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH 1320 PRIVATE void st_init_function_hash(st_init_info_t *info, 1321 struct _magic_vars_t *magic_vars) 1322 { 1323 size_t buff_size; 1324 void *buff; 1325 1326 EXEC_WITH_MAGIC_VARS( 1327 buff_size = magic_function_hash_estimate_buff_size(0); 1328 , magic_vars 1329 ); 1330 buff = st_buff_allocate(info, buff_size); 1331 1332 EXEC_WITH_MAGIC_VARS( 1333 magic_function_hash_build(buff, buff_size); 1334 , magic_vars 1335 ); 1336 } 1337 1338 PRIVATE void st_cleanup_function_hash(st_init_info_t *info, 1339 struct _magic_vars_t *magic_vars) 1340 { 1341 EXEC_WITH_MAGIC_VARS( 1342 magic_function_hash_destroy(); 1343 , magic_vars 1344 ); 1345 } 1346 #endif 1347 1348 PRIVATE void st_vars_clear_ptrs(struct _magic_vars_t *magic_vars) 1349 { 1350 #undef __X 1351 #define __X(x) offsetof(struct _magic_vars_t, x) 1352 size_t offset_list[] = { ST_MAGIC_VARS_PTR_CLEAR_LIST }; 1353 #undef __X 1354 unsigned int i; 1355 1356 for (i = 0 ; i < sizeof(offset_list) / sizeof(size_t) ; i++) 1357 *((void **)(((char *)magic_vars) + offset_list[i])) = NULL; 1358 } 1359 1360 1361 #ifdef __MINIX 1362 PRIVATE void st_unmap_mem(struct _magic_vars_t *magic_vars) 1363 { 1364 int i, r; 1365 1366 for (i = 0; i < MAGIC_UNMAP_MEM_ENTRIES; i++) { 1367 if (magic_vars->unmap_mem[i].length != 0) { 1368 #if ST_DEBUG_LEVEL > 0 1369 printf("st_unmap_mem: unmapping (%p, %zu)\n", 1370 magic_vars->unmap_mem[i].start, 1371 magic_vars->unmap_mem[i].length); 1372 #endif 1373 r = munmap(magic_vars->unmap_mem[i].start, 1374 magic_vars->unmap_mem[i].length); 1375 assert(r == 0); 1376 } 1377 } 1378 } 1379 #endif 1380 1381 PUBLIC int st_init(st_init_info_t *info) 1382 { 1383 size_t max_buff_sz = 0; 1384 int r, dsentries_num; 1385 int allow_unpaired_types = TRUE; 1386 if (st_init_done) { 1387 return OK; 1388 } 1389 if (!_magic_enabled) return ENOSYS; 1390 st_init_done = TRUE; 1391 1392 /* Ignore nested mempool dsentries for now. */ 1393 magic_lookup_nested_dsentries = 0; 1394 1395 /* Override default state transfer policies for ASR. */ 1396 if ((info->flags & ST_LU_ASR) && st_policies == ST_POLICIES_DEFAULT) { 1397 st_policies = ST_POLICIES_DEFAULT_TRANSFER_ASR; 1398 } 1399 1400 /* Fixup state transfer policies based on current configuration. */ 1401 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 1402 st_policies &= (~ST_DEFAULT_ALLOC_CASCADE_XFER); 1403 #elif !defined(__MINIX) 1404 st_policies |= ST_TRANSFER_DIRTY_ONLY; 1405 #endif 1406 1407 assert((!info->init_buff_start || (info->flags & ST_LU_NOMMAP)) && "st_init: no mmapping allowed, and no buffer is available"); 1408 register_typenames_and_callbacks(); 1409 1410 /* Transfer _magic_vars, which contain addresses of the magic variables */ 1411 r = st_cbs_os.old_state_table_lookup(info->info_opaque, &st_remote_magic_vars); 1412 assert( r == OK && "ERROR occurred during transfer of _magic_vars."); 1413 /* 1414 * Clear all pointers not explictly transferred, as they are not valid in 1415 * the new address space. 1416 */ 1417 st_vars_clear_ptrs(&st_remote_magic_vars); 1418 1419 /* 1420 * Some magic_vars members do not need transfer or adjustment 1421 * (e.g. the memory ranges). They are copied to st_cached_magic_vars 1422 * this way. 1423 */ 1424 st_cached_magic_vars = st_remote_magic_vars; 1425 1426 /* Transfer and adjust metadata */ 1427 r = st_transfer_metadata_types(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts); 1428 assert( r == OK && "ERROR occurred during transfer of type metadata."); 1429 r = transfer_metadata_functions(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts); 1430 assert( r == OK && "ERROR occurred during transfer of function metadata."); 1431 r = transfer_metadata_dfunctions(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts); 1432 assert( r == OK && "ERROR occurred during transfer of dfunction metadata."); 1433 r = transfer_metadata_sentries(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts, &max_buff_sz); 1434 assert( r == OK && "ERROR occurred during transfer of sentry metadata."); 1435 r = st_transfer_metadata_dsentries(info, &st_cached_magic_vars, &st_remote_magic_vars, &st_counterparts, &max_buff_sz, &dsentries_num); 1436 assert( r == OK && "ERROR occurred during transfer of dsentry metadata."); 1437 1438 /* Allocate buffer for data transfer */ 1439 st_dsentry_buff = st_buff_allocate(info, max_buff_sz + sizeof(struct _magic_dsentry)); 1440 if (!st_dsentry_buff) { 1441 printf("st_dsentry_buff could not be allocated.\n"); 1442 return EGENERIC; 1443 } 1444 st_data_buff = &st_dsentry_buff[1]; 1445 1446 /* Allocate and initialize counterparts buffers. */ 1447 st_counterparts.functions_size = st_cached_magic_vars.functions_num; 1448 st_counterparts.functions = st_buff_allocate(info, st_counterparts.functions_size * sizeof(st_ptr_mapping)); 1449 assert(st_counterparts.functions && "st_counterparts.functions could not be allocated."); 1450 1451 st_counterparts.types_size = st_cached_magic_vars.types_num; 1452 st_counterparts.types = st_buff_allocate(info, st_counterparts.types_size * sizeof(st_ptr_mapping)); 1453 assert(st_counterparts.types && "st_counterparts.types could not be allocated."); 1454 st_counterparts.ptr_types = st_buff_allocate(info, st_counterparts.types_size * sizeof(st_ptr_mapping)); 1455 assert(st_counterparts.ptr_types && "st_counterparts.ptr_types could not be allocated."); 1456 1457 st_counterparts.sentries_size = st_cached_magic_vars.sentries_num + dsentries_num; 1458 st_counterparts.sentries = st_buff_allocate(info, st_counterparts.sentries_size * sizeof(st_ptr_mapping)); 1459 assert(st_counterparts.sentries && "st_counterparts.sentries could not be allocated."); 1460 st_counterparts.sentries_data = st_buff_allocate(info, st_counterparts.sentries_size * sizeof(st_ptr_mapping)); 1461 assert(st_counterparts.sentries_data && "st_counterparts.sentries_data could not be allocated."); 1462 1463 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX 1464 st_init_rl_index(info, &st_cached_magic_vars); 1465 #endif 1466 1467 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH 1468 st_init_sentry_hash(info, &st_cached_magic_vars); 1469 st_init_sentry_hash(info, _magic_vars); 1470 #endif 1471 1472 #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH 1473 st_init_function_hash(info, &st_cached_magic_vars); 1474 st_init_function_hash(info, _magic_vars); 1475 #endif 1476 1477 #ifdef __MINIX 1478 /* Unmap any memory ranges that are not needed in the new process. */ 1479 st_unmap_mem(&st_cached_magic_vars); 1480 #endif 1481 1482 /* Pair metadata entities */ 1483 r = pair_metadata_types(info, &st_cached_magic_vars, &st_counterparts, allow_unpaired_types); 1484 assert( r == OK && "ERROR occurred during call to pair_metadata_types()."); 1485 r = pair_metadata_functions(info, &st_cached_magic_vars, &st_counterparts); 1486 assert( r == OK && "ERROR occurred during call to pair_metadata_functions()."); 1487 r = pair_metadata_sentries(info, &st_cached_magic_vars, &st_counterparts); 1488 assert( r == OK && "ERROR occurred during call to pair_metadata_sentries()."); 1489 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 1490 r = allocate_pair_metadata_dsentries_from_raw_copy(info, &st_cached_magic_vars, &st_counterparts); 1491 assert( r == OK && "ERROR occurred during call to allocate_pair_metadata_dsentries()."); 1492 #else 1493 r = allocate_pair_metadata_dsentries(info, &st_cached_magic_vars, &st_counterparts); 1494 assert( r == OK && "ERROR occurred during call to allocate_pair_metadata_dsentries()."); 1495 #endif 1496 1497 /* Set state transfer status defaults from the predefined policies. */ 1498 st_set_status_defaults(info); 1499 1500 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX 1501 st_init_rl_index(info, _magic_vars); 1502 #endif 1503 1504 return OK; 1505 } 1506 1507 PRIVATE INLINE char* st_lookup_str_local_data(struct _magic_sentry *cached_sentry) 1508 { 1509 void *local_data_addr; 1510 assert(cached_sentry && MAGIC_SENTRY_IS_STRING(cached_sentry)); 1511 ST_GET_CACHED_COUNTERPART(cached_sentry, sentries, sentries_data, local_data_addr); 1512 assert(local_data_addr && "String data not in cache!"); 1513 return (char*) local_data_addr; 1514 } 1515 1516 #if ST_DEBUG_DATA_TRANSFER 1517 PRIVATE void st_print_sentities(struct _magic_vars_t *magic_vars) 1518 { 1519 struct _magic_dsentry *dsentry = magic_vars->first_dsentry; 1520 int i; 1521 1522 for (i = 0 ; i < magic_vars->sentries_num ; i++) { 1523 struct _magic_sentry *sentry = &magic_vars->sentries[i]; 1524 ST_SENTRY_PRINT(sentry, 0); 1525 printf("\n"); 1526 } 1527 1528 while (dsentry != NULL) { 1529 ST_DSENTRY_PRINT(dsentry, 0); 1530 printf("\n"); 1531 dsentry = dsentry->next; 1532 } 1533 1534 for (i = 0 ; i < magic_vars->functions_num ; i++) { 1535 struct _magic_function *function = &magic_vars->functions[i]; 1536 ST_FUNCTION_PRINT(function, 0); 1537 printf("\n"); 1538 } 1539 } 1540 #endif 1541 1542 PUBLIC void st_map_str_sentries(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr) 1543 { 1544 struct _magic_sentry *cached_sentry = *cached_sentry_ptr; 1545 struct _magic_sentry *local_sentry = *local_sentry_ptr; 1546 struct _magic_sentry *sentry = cached_sentry ? cached_sentry : local_sentry; 1547 int string_flags, match_by_name, match_by_content; 1548 ST_CHECK_INIT(); 1549 assert((cached_sentry == NULL) ^ (local_sentry == NULL)); 1550 1551 string_flags = sentry->flags & (MAGIC_STATE_STRING|MAGIC_STATE_NAMED_STRING); 1552 assert(string_flags & MAGIC_STATE_STRING); 1553 match_by_name = (string_flags & MAGIC_STATE_NAMED_STRING) && (st_policies & ST_MAP_NAMED_STRINGS_BY_NAME); 1554 match_by_content = ((string_flags & MAGIC_STATE_NAMED_STRING) && (st_policies & ST_MAP_NAMED_STRINGS_BY_CONTENT)) 1555 || (!(string_flags & MAGIC_STATE_NAMED_STRING) && (st_policies & ST_MAP_STRINGS_BY_CONTENT)); 1556 if (match_by_name) { 1557 /* Pretend it's a regular sentry and match by name */ 1558 sentry->flags &= ~string_flags; 1559 st_map_sentries(cached_sentry_ptr, local_sentry_ptr); 1560 sentry->flags |= string_flags; 1561 if (*cached_sentry_ptr && *local_sentry_ptr) { 1562 /* Found by name. */ 1563 return; 1564 } 1565 } 1566 if (!match_by_content) { 1567 /* No match. */ 1568 return; 1569 } 1570 if (cached_sentry) { 1571 EXEC_WITH_MAGIC_VARS( 1572 local_sentry = magic_sentry_lookup_by_string(st_lookup_str_local_data(cached_sentry)); 1573 , st_local_magic_vars_ptr 1574 ); 1575 } 1576 else { 1577 int i; 1578 for(i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) { 1579 sentry = &st_cached_magic_vars.sentries[i]; 1580 if (MAGIC_SENTRY_IS_STRING(sentry) && !strcmp(st_lookup_str_local_data(sentry), (char*)local_sentry->address)) { 1581 cached_sentry = sentry; 1582 break; 1583 } 1584 } 1585 } 1586 *cached_sentry_ptr = cached_sentry; 1587 *local_sentry_ptr = local_sentry; 1588 } 1589 1590 PUBLIC void st_map_sentries(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr) 1591 { 1592 struct _magic_sentry *cached_sentry = *cached_sentry_ptr; 1593 struct _magic_sentry *local_sentry = *local_sentry_ptr; 1594 struct _magic_dsentry *cached_dsentry = cached_sentry ? (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC) ? MAGIC_DSENTRY_FROM_SENTRY(cached_sentry) : NULL) : NULL; 1595 struct _magic_dsentry *local_dsentry = local_sentry ? (MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_DYNAMIC) ? MAGIC_DSENTRY_FROM_SENTRY(local_sentry) : NULL) : NULL; 1596 ST_CHECK_INIT(); 1597 assert((cached_sentry == NULL) ^ (local_sentry == NULL)); 1598 1599 if ((cached_sentry && MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_STRING)) 1600 || (local_sentry && MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_STRING))) { 1601 st_map_str_sentries(cached_sentry_ptr, local_sentry_ptr); 1602 return; 1603 } 1604 else if (cached_sentry) { 1605 EXEC_WITH_MAGIC_VARS( 1606 local_sentry = magic_sentry_lookup_by_name(cached_dsentry ? cached_dsentry->parent_name : "", cached_sentry->name, cached_dsentry ? cached_dsentry->site_id : 0, NULL); 1607 , st_local_magic_vars_ptr 1608 ); 1609 assert(!local_sentry || MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC) == MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_DYNAMIC)); 1610 } 1611 else { 1612 EXEC_WITH_MAGIC_VARS( 1613 cached_sentry = magic_sentry_lookup_by_name(local_dsentry ? local_dsentry->parent_name : "", local_sentry->name, local_dsentry ? local_dsentry->site_id : 0, NULL); 1614 , &st_cached_magic_vars 1615 ); 1616 assert(!cached_sentry || MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_DYNAMIC) == MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC)); 1617 } 1618 *cached_sentry_ptr = cached_sentry; 1619 *local_sentry_ptr = local_sentry; 1620 } 1621 1622 PRIVATE struct _magic_sentry *st_lookup_cached_sentry(struct _magic_sentry *local_sentry) 1623 { 1624 int i; 1625 struct _magic_dsentry *cached_dsentry; 1626 assert(local_sentry); 1627 1628 for (i = 0 ; i < st_counterparts.sentries_size ; i++) { 1629 if (st_counterparts.sentries[i].counterpart == local_sentry) { 1630 break; 1631 } 1632 } 1633 if (i >= st_counterparts.sentries_size) { 1634 return NULL; 1635 } 1636 if (i < st_cached_magic_vars.sentries_num) { 1637 return &st_cached_magic_vars.sentries[i]; 1638 } 1639 i -= st_cached_magic_vars.sentries_num; 1640 cached_dsentry = st_cached_magic_vars.first_dsentry; 1641 assert(i >= 0); 1642 assert(cached_dsentry); 1643 while (i > 0) { 1644 cached_dsentry = cached_dsentry->next; 1645 assert(cached_dsentry); 1646 i--; 1647 } 1648 return MAGIC_DSENTRY_TO_SENTRY(cached_dsentry); 1649 } 1650 1651 PUBLIC void st_lookup_sentry_pair(struct _magic_sentry **cached_sentry_ptr, struct _magic_sentry **local_sentry_ptr) 1652 { 1653 struct _magic_sentry *cached_sentry = *cached_sentry_ptr; 1654 struct _magic_sentry *local_sentry = *local_sentry_ptr; 1655 ST_CHECK_INIT(); 1656 assert((cached_sentry == NULL) ^ (local_sentry == NULL)); 1657 1658 if (cached_sentry) { 1659 ST_GET_CACHED_COUNTERPART(cached_sentry, sentries, sentries, local_sentry); 1660 } 1661 else if (MAGIC_SENTRY_IS_STRING(local_sentry)) { 1662 /* strings are special, they may have multiple local duplicates */ 1663 struct _magic_sentry *csentry = NULL, *lsentry = NULL; 1664 st_map_str_sentries(&csentry, &local_sentry); 1665 if (csentry) { 1666 st_lookup_sentry_pair(&csentry, &lsentry); 1667 if (lsentry) { 1668 cached_sentry = csentry; 1669 } 1670 } 1671 } 1672 else { 1673 cached_sentry = st_lookup_cached_sentry(local_sentry); 1674 } 1675 *cached_sentry_ptr = cached_sentry; 1676 *local_sentry_ptr = local_sentry; 1677 } 1678 1679 PRIVATE INLINE void st_unpair_local_alloc_sentry(struct _magic_sentry *local_sentry) 1680 { 1681 if (st_policies & ST_ON_ALLOC_UNPAIR_ERROR) { 1682 st_cbs_os.panic("st_unpair_local_alloc_sentry: Error: attempting to unpair a local alloc sentry!"); 1683 } 1684 else if (st_policies & ST_ON_ALLOC_UNPAIR_DEALLOCATE) { 1685 deallocate_local_dsentry(MAGIC_DSENTRY_FROM_SENTRY(local_sentry)); 1686 } 1687 } 1688 1689 PUBLIC void st_add_sentry_pair(struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry) 1690 { 1691 ST_CHECK_INIT(); 1692 assert(cached_sentry || local_sentry); 1693 1694 if (local_sentry) { 1695 struct _magic_sentry *csentry = NULL; 1696 st_lookup_sentry_pair(&csentry, &local_sentry); 1697 if (csentry) { 1698 ST_SET_CACHED_COUNTERPART(csentry, sentries, sentries, NULL); 1699 } 1700 if (!cached_sentry && MAGIC_SENTRY_IS_ALLOC(local_sentry)) { 1701 st_unpair_local_alloc_sentry(local_sentry); 1702 } 1703 } 1704 if (cached_sentry) { 1705 struct _magic_sentry *lsentry = NULL; 1706 st_lookup_sentry_pair(&cached_sentry, &lsentry); 1707 if (lsentry && MAGIC_SENTRY_IS_ALLOC(lsentry)) { 1708 st_unpair_local_alloc_sentry(lsentry); 1709 } 1710 ST_SET_CACHED_COUNTERPART(cached_sentry, sentries, sentries, local_sentry); 1711 } 1712 } 1713 1714 PUBLIC int st_add_sentry_pair_alloc_by_dsindex(st_init_info_t *info, struct _magic_sentry *cached_sentry, struct _magic_dsindex *local_dsindex, int num_elements, const union __alloc_flags *p_alloc_flags) 1715 { 1716 int r; 1717 struct _magic_dsentry *local_dsentry; 1718 ST_CHECK_INIT(); 1719 assert(cached_sentry); 1720 1721 if (!local_dsindex) { 1722 st_add_sentry_pair(cached_sentry, NULL); 1723 return OK; 1724 } 1725 1726 r = allocate_local_dsentry(info, local_dsindex, num_elements, MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_TYPE_SIZE_MISMATCH), p_alloc_flags, &local_dsentry, NULL, MAGIC_PTR_TO_DSENTRY(cached_sentry->address)); 1727 if (r != OK) { 1728 return r; 1729 } 1730 st_add_sentry_pair(cached_sentry, MAGIC_DSENTRY_TO_SENTRY(local_dsentry)); 1731 return OK; 1732 } 1733 1734 PUBLIC void st_map_functions(struct _magic_function **cached_function_ptr, struct _magic_function **local_function_ptr) 1735 { 1736 struct _magic_function *cached_function = *cached_function_ptr; 1737 struct _magic_function *local_function = *local_function_ptr; 1738 ST_CHECK_INIT(); 1739 assert((cached_function == NULL) ^ (local_function == NULL)); 1740 1741 if (cached_function) { 1742 EXEC_WITH_MAGIC_VARS( 1743 local_function = magic_function_lookup_by_name(NULL, cached_function->name); 1744 , st_local_magic_vars_ptr 1745 ); 1746 } 1747 else { 1748 EXEC_WITH_MAGIC_VARS( 1749 cached_function = magic_function_lookup_by_name(NULL, local_function->name); 1750 , &st_cached_magic_vars 1751 ); 1752 } 1753 *cached_function_ptr = cached_function; 1754 *local_function_ptr = local_function; 1755 } 1756 1757 PUBLIC void st_lookup_function_pair(struct _magic_function **cached_function_ptr, struct _magic_function **local_function_ptr) 1758 { 1759 struct _magic_function *cached_function = *cached_function_ptr; 1760 struct _magic_function *local_function = *local_function_ptr; 1761 int i; 1762 ST_CHECK_INIT(); 1763 assert((cached_function == NULL) ^ (local_function == NULL)); 1764 1765 if (cached_function) { 1766 if ((int)cached_function->id - 1 >= st_counterparts.functions_size) { 1767 /* 1768 * Try to check if this is a function 1769 * from an external shared object. 1770 * XXX: The number of dfunctions can be quite large, 1771 * so this needs to be done more efficiently. 1772 */ 1773 struct _magic_dfunction *dfunc; 1774 struct _magic_function *func; 1775 MAGIC_DFUNCTION_FUNC_ITER(_magic_vars->first_dfunction, dfunc, func, 1776 if (func->address == cached_function->address) { 1777 local_function = func; 1778 break; 1779 } 1780 ); 1781 assert(local_function != NULL && "No counterpart found for function."); 1782 } else { 1783 ST_GET_CACHED_COUNTERPART(cached_function, functions, functions, local_function); 1784 } 1785 } 1786 else { 1787 assert(st_counterparts.functions_size == st_cached_magic_vars.functions_num); 1788 for(i = 0 ; i < st_counterparts.functions_size ; i++) { 1789 if(st_counterparts.functions[i].counterpart == local_function) { 1790 cached_function = &st_cached_magic_vars.functions[i]; 1791 break; 1792 } 1793 } 1794 } 1795 *cached_function_ptr = cached_function; 1796 *local_function_ptr = local_function; 1797 } 1798 1799 PUBLIC void st_add_function_pair(struct _magic_function *cached_function, struct _magic_function *local_function) 1800 { 1801 ST_CHECK_INIT(); 1802 assert(cached_function || local_function); 1803 1804 if (local_function) { 1805 struct _magic_function *cfunction = NULL; 1806 st_lookup_function_pair(&cfunction, &local_function); 1807 if (cfunction) { 1808 ST_SET_CACHED_COUNTERPART(cfunction, functions, functions, NULL); 1809 } 1810 } 1811 if (cached_function) { 1812 ST_SET_CACHED_COUNTERPART(cached_function, functions, functions, local_function); 1813 } 1814 } 1815 1816 PUBLIC int st_sentry_equals(struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry) 1817 { 1818 const char *cached_parent_name = "", *local_parent_name = ""; 1819 int cached_flags = MAGIC_STATE_FLAGS_TO_NONEXTF(cached_sentry->flags) & (~MAGIC_STATE_ADDR_NOT_TAKEN); 1820 int local_flags = MAGIC_STATE_FLAGS_TO_NONEXTF(local_sentry->flags) & (~MAGIC_STATE_ADDR_NOT_TAKEN); 1821 if (cached_flags != local_flags) { 1822 return FALSE; 1823 } 1824 if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_STRING)) { 1825 return !strcmp(st_lookup_str_local_data(cached_sentry), (char*)local_sentry->address); 1826 } 1827 if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC)) { 1828 cached_parent_name = MAGIC_DSENTRY_FROM_SENTRY(cached_sentry)->parent_name; 1829 local_parent_name = MAGIC_DSENTRY_FROM_SENTRY(local_sentry)->parent_name; 1830 } 1831 if (strcmp(cached_sentry->name, local_sentry->name) || strcmp(cached_parent_name, local_parent_name)) { 1832 return FALSE; 1833 } 1834 return magic_type_compatible(cached_sentry->type, local_sentry->type, MAGIC_TYPE_COMPARE_ALL); 1835 } 1836 1837 PUBLIC int st_function_equals(struct _magic_function *cached_function, struct _magic_function *local_function) 1838 { 1839 if (MAGIC_STATE_FLAGS_TO_NONEXTF(local_function->flags) != MAGIC_STATE_FLAGS_TO_NONEXTF(cached_function->flags)) { 1840 return FALSE; 1841 } 1842 return !strcmp(cached_function->name, local_function->name); 1843 } 1844 1845 PUBLIC void st_print_sentry_diff(st_init_info_t *info, struct _magic_sentry *cached_sentry, struct _magic_sentry *local_sentry, int raw_diff, int print_changed) 1846 { 1847 int is_paired_sentry; 1848 ST_CHECK_INIT(); 1849 1850 if (!cached_sentry || !local_sentry) { 1851 if (raw_diff) { 1852 st_map_sentries(&cached_sentry, &local_sentry); 1853 } 1854 else { 1855 st_lookup_sentry_pair(&cached_sentry, &local_sentry); 1856 } 1857 } 1858 is_paired_sentry = (cached_sentry != NULL && local_sentry != NULL); 1859 if (is_paired_sentry && st_sentry_equals(cached_sentry, local_sentry)) { 1860 return; 1861 } 1862 if (is_paired_sentry && !print_changed) { 1863 return; 1864 } 1865 if (cached_sentry) { 1866 printf("-"); ST_SENTRY_PRINT(cached_sentry, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1867 } 1868 if (local_sentry) { 1869 printf("+"); ST_SENTRY_PRINT(local_sentry, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1870 } 1871 printf("\n"); 1872 } 1873 1874 PUBLIC void st_print_function_diff(st_init_info_t *info, struct _magic_function *cached_function, struct _magic_function *local_function, int raw_diff, int print_changed) 1875 { 1876 int is_paired_function; 1877 ST_CHECK_INIT(); 1878 1879 if (!cached_function || !local_function) { 1880 if (raw_diff) { 1881 st_map_functions(&cached_function, &local_function); 1882 } 1883 else { 1884 st_lookup_function_pair(&cached_function, &local_function); 1885 } 1886 } 1887 is_paired_function = (cached_function != NULL && local_function != NULL); 1888 if (is_paired_function && st_function_equals(cached_function, local_function)) { 1889 return; 1890 } 1891 if (is_paired_function && !print_changed) { 1892 return; 1893 } 1894 if (cached_function) { 1895 printf("-"); ST_FUNCTION_PRINT(cached_function, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1896 } 1897 if (local_function) { 1898 printf("+"); ST_FUNCTION_PRINT(local_function, MAGIC_EXPAND_TYPE_STR); printf("\n"); 1899 } 1900 printf("\n"); 1901 } 1902 1903 PUBLIC void st_print_sentries_diff(st_init_info_t *info, int raw_diff, int print_changed) 1904 { 1905 int i; 1906 ST_CHECK_INIT(); 1907 1908 for (i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) { 1909 struct _magic_sentry *cached_sentry = &st_cached_magic_vars.sentries[i]; 1910 st_print_sentry_diff(info, cached_sentry, NULL, raw_diff, print_changed); 1911 } 1912 1913 print_changed = FALSE; 1914 for (i = 0 ; i < st_local_magic_vars_ptr->sentries_num ; i++) { 1915 struct _magic_sentry *local_sentry = &st_local_magic_vars_ptr->sentries[i]; 1916 st_print_sentry_diff(info, NULL, local_sentry, raw_diff, print_changed); 1917 } 1918 } 1919 1920 PUBLIC void st_print_dsentries_diff(st_init_info_t *info, int raw_diff, int print_changed) 1921 { 1922 struct _magic_dsentry *dsentry; 1923 ST_CHECK_INIT(); 1924 1925 dsentry = st_cached_magic_vars.first_dsentry; 1926 while (dsentry != NULL) { 1927 struct _magic_sentry *cached_sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 1928 st_print_sentry_diff(info, cached_sentry, NULL, raw_diff, print_changed); 1929 dsentry = dsentry->next; 1930 } 1931 1932 dsentry = st_local_magic_vars_ptr->first_dsentry; 1933 print_changed = FALSE; 1934 while (dsentry != NULL) { 1935 struct _magic_sentry *local_sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 1936 st_print_sentry_diff(info, NULL, local_sentry, raw_diff, print_changed); 1937 dsentry = dsentry->next; 1938 } 1939 } 1940 1941 PUBLIC void st_print_functions_diff(st_init_info_t *info, int raw_diff, int print_changed) 1942 { 1943 int i; 1944 ST_CHECK_INIT(); 1945 1946 for(i = 0 ; i < st_cached_magic_vars.functions_num ; i++) { 1947 struct _magic_function *cached_function = &st_cached_magic_vars.functions[i]; 1948 st_print_function_diff(info, cached_function, NULL, raw_diff, print_changed); 1949 } 1950 1951 print_changed = FALSE; 1952 for (i = 0 ; i < st_local_magic_vars_ptr->functions_num ; i++) { 1953 struct _magic_function *local_function = &st_local_magic_vars_ptr->functions[i]; 1954 st_print_function_diff(info, NULL, local_function, raw_diff, print_changed); 1955 } 1956 } 1957 1958 PUBLIC void st_print_state_diff(st_init_info_t *info, int raw_diff, int print_changed) 1959 { 1960 ST_CHECK_INIT(); 1961 1962 printf("Index: sentries\n"); 1963 printf("===================================================================\n"); 1964 st_print_sentries_diff(info, raw_diff, print_changed); 1965 1966 printf("\nIndex: dsentries\n"); 1967 printf("===================================================================\n"); 1968 st_print_dsentries_diff(info, raw_diff, print_changed); 1969 1970 printf("\nIndex: functions\n"); 1971 printf("===================================================================\n"); 1972 st_print_functions_diff(info, raw_diff, print_changed); 1973 printf("\n"); 1974 } 1975 1976 PUBLIC int st_data_transfer(st_init_info_t *info) 1977 { 1978 struct _magic_dsentry *dsentry; 1979 int i, r; 1980 int sentry_transferred; 1981 #if ST_DEBUG_DATA_TRANSFER 1982 int counter = 1; 1983 #endif 1984 ST_CHECK_INIT(); 1985 1986 /* Check unpaired sentries. */ 1987 for (i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) { 1988 struct _magic_sentry *sentry = &st_cached_magic_vars.sentries[i]; 1989 int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries); 1990 if (!is_paired_sentry) { 1991 r = check_unpaired_sentry(info, sentry); 1992 if (r != OK) { 1993 return r; 1994 } 1995 } 1996 } 1997 1998 /* Check unpaired dsentries. */ 1999 dsentry = st_cached_magic_vars.first_dsentry; 2000 while (dsentry != NULL) { 2001 struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 2002 int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries); 2003 if (!is_paired_sentry) { 2004 r = check_unpaired_sentry(info, sentry); 2005 if (r != OK) { 2006 return r; 2007 } 2008 } 2009 dsentry = dsentry->next; 2010 } 2011 2012 /* Data transfer. */ 2013 do { 2014 sentry_transferred = 0; 2015 2016 #if ST_DEBUG_DATA_TRANSFER 2017 printf("st_data_transfer: Round %d\n", counter++); 2018 st_print_sentities(&st_cached_magic_vars); 2019 #endif 2020 2021 /* process sentries */ 2022 #if ST_DEBUG_LEVEL > 0 2023 printf("st_data_transfer: processing sentries\n"); 2024 #endif 2025 for(i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) { 2026 struct _magic_sentry *sentry = &st_cached_magic_vars.sentries[i]; 2027 int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries); 2028 int sentry_needs_transfer = MAGIC_STATE_EXTF_GET(sentry, ST_NEEDS_TRANSFER | ST_TRANSFER_DONE) == ST_NEEDS_TRANSFER; 2029 if (sentry_needs_transfer && is_paired_sentry) { 2030 r = transfer_data_sentry(info, sentry); 2031 if (r != OK) { 2032 return r; 2033 } 2034 sentry_transferred = 1; 2035 } 2036 } 2037 2038 /* process dsentries */ 2039 #if ST_DEBUG_LEVEL > 0 2040 printf("st_data_transfer: processing dsentries\n"); 2041 #endif 2042 dsentry = st_cached_magic_vars.first_dsentry; 2043 while (dsentry != NULL) { 2044 struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 2045 int is_paired_sentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries); 2046 int sentry_needs_transfer = MAGIC_STATE_EXTF_GET(sentry, ST_NEEDS_TRANSFER | ST_TRANSFER_DONE) == ST_NEEDS_TRANSFER; 2047 if (sentry_needs_transfer && is_paired_sentry) { 2048 r = transfer_data_sentry(info, sentry); 2049 if (r != OK) { 2050 return r; 2051 } 2052 sentry_transferred = 1; 2053 } 2054 dsentry = dsentry->next; 2055 } 2056 2057 } while(sentry_transferred); 2058 2059 return OK; 2060 } 2061 2062 PRIVATE INLINE void st_set_transfer_status(int status_flags, int status_op, 2063 struct _magic_sentry *cached_sentry, struct _magic_function *cached_function) 2064 { 2065 #define __st_set_transfer_status(X) \ 2066 switch(status_op) { \ 2067 case ST_OP_NONE: \ 2068 return; \ 2069 break; \ 2070 case ST_OP_ADD: \ 2071 MAGIC_STATE_EXTF_ADD(X, status_flags); \ 2072 break; \ 2073 case ST_OP_DEL: \ 2074 MAGIC_STATE_EXTF_DEL(X, status_flags); \ 2075 break; \ 2076 case ST_OP_SET: \ 2077 MAGIC_STATE_EXTF_SET(X, status_flags); \ 2078 break; \ 2079 case ST_OP_CLEAR: \ 2080 MAGIC_STATE_EXTF_CLEAR(X); \ 2081 break; \ 2082 default: \ 2083 st_cbs_os.panic("Invalid operation!"); \ 2084 break; \ 2085 } \ 2086 2087 if (cached_sentry) { 2088 __st_set_transfer_status(cached_sentry); 2089 } 2090 else { 2091 assert(cached_function); 2092 __st_set_transfer_status(cached_function); 2093 } 2094 } 2095 2096 PUBLIC void st_set_unpaired_types_ratios(float unpaired_types_ratio, 2097 float unpaired_struct_types_ratio) 2098 { 2099 st_unpaired_types_ratio = unpaired_types_ratio; 2100 st_unpaired_struct_types_ratio = unpaired_struct_types_ratio; 2101 } 2102 2103 PUBLIC void st_set_status_defaults(st_init_info_t *info) 2104 { 2105 int match_all = ~0, skip_none = 0; 2106 int skip_state_flags = (st_policies & ST_DEFAULT_SKIP_STACK) ? MAGIC_STATE_STACK : 0; 2107 2108 if (!(st_policies & ST_DEFAULT_TRANSFER_NONE)) { 2109 /* 2110 * Transfer all the (d)sentries by default. Skip stack dsentries when 2111 * requested. In that case, stack dsentries won't be transferred and an 2112 * error will be raised on stack pointer transfer. 2113 */ 2114 st_set_status_by_state_flags(ST_NEEDS_TRANSFER, ST_OP_SET, 2115 match_all, skip_state_flags); 2116 if (st_policies & ST_DEFAULT_ALLOC_CASCADE_XFER) { 2117 /* 2118 * If requested, mark non-stack dsentries for cascade transfer 2119 * instead of regular transfer. 2120 */ 2121 st_set_status_by_state_flags(ST_ON_PTRXFER_CASCADE, ST_OP_SET, 2122 MAGIC_STATE_HEAP | MAGIC_STATE_MAP, skip_none); 2123 } 2124 } 2125 else { 2126 /* 2127 * Don't transfer any (d)sentries by default. Mark all the (d)sentries 2128 * for cascade transfer (except for stack dsentries when requested). 2129 */ 2130 st_set_status_by_state_flags(ST_ON_PTRXFER_CASCADE, ST_OP_SET, 2131 match_all, skip_state_flags); 2132 } 2133 2134 /* 2135 * Always transfer all immutable objects. 2136 */ 2137 st_set_status_by_state_flags(ST_NEEDS_TRANSFER, ST_OP_SET, 2138 MAGIC_STATE_IMMUTABLE, skip_none); 2139 2140 /* 2141 * If requested, mark library state dsentries as already transferred too. 2142 */ 2143 if (st_policies & ST_DEFAULT_SKIP_LIB_STATE) { 2144 st_set_status_by_state_flags(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE, 2145 ST_OP_ADD, MAGIC_STATE_LIB, skip_none); 2146 } 2147 2148 /* 2149 * In addition, mark functions, out-of-band/string sentries 2150 * and shared dsentries as already transferred. 2151 */ 2152 st_set_status_by_state_flags(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE, 2153 ST_OP_ADD, MAGIC_STATE_TEXT | MAGIC_STATE_OUT_OF_BAND | 2154 MAGIC_STATE_STRING | MAGIC_STATE_CONSTANT | MAGIC_STATE_SHM, skip_none); 2155 2156 /* 2157 * Finally, if we only want to transfer dirty sentries, mark all the other ones 2158 * as already transferred. 2159 */ 2160 if (st_policies & ST_TRANSFER_DIRTY_ONLY) { 2161 st_set_status_by_state_flags(ST_TRANSFER_DONE, ST_OP_ADD, match_all, MAGIC_STATE_DIRTY_PAGE); 2162 } 2163 2164 #if DO_SKIP_ENVIRON_HACK 2165 st_set_status_by_name(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE, 2166 ST_OP_ADD, NULL, "__environ", MAGIC_DSENTRY_SITE_ID_NULL); 2167 st_set_status_by_name(ST_NEEDS_TRANSFER | ST_TRANSFER_DONE, 2168 ST_OP_ADD, NULL, "stderr", MAGIC_DSENTRY_SITE_ID_NULL); 2169 #endif 2170 } 2171 2172 PUBLIC void st_set_status_by_state_flags(int status_flags, int status_op, 2173 int match_state_flags, int skip_state_flags) 2174 { 2175 struct _magic_dsentry *dsentry = st_cached_magic_vars.first_dsentry; 2176 int i; 2177 int candidate_sentry_flags = MAGIC_STATE_DATA | MAGIC_STATE_STRING | MAGIC_STATE_CONSTANT | MAGIC_STATE_ADDR_NOT_TAKEN; 2178 int candidate_function_flags = MAGIC_STATE_TEXT; 2179 int candidate_dsentry_flags = ~(candidate_sentry_flags | candidate_function_flags); 2180 ST_CHECK_INIT(); 2181 2182 /* process sentries */ 2183 if (match_state_flags & candidate_sentry_flags) { 2184 for (i = 0 ; i < st_cached_magic_vars.sentries_num ; i++) { 2185 int state_flags = st_cached_magic_vars.sentries[i].flags; 2186 if ((state_flags & match_state_flags) && !(state_flags & skip_state_flags)) { 2187 st_set_transfer_status(status_flags, status_op, &st_cached_magic_vars.sentries[i], NULL); 2188 } 2189 } 2190 } 2191 2192 /* process dsentries */ 2193 if (match_state_flags & candidate_dsentry_flags) { 2194 while (dsentry != NULL) { 2195 int state_flags = dsentry->sentry.flags; 2196 if ((state_flags & match_state_flags) && !(state_flags & skip_state_flags)) { 2197 st_set_transfer_status(status_flags, status_op, MAGIC_DSENTRY_TO_SENTRY(dsentry), NULL); 2198 } 2199 dsentry = dsentry->next; 2200 } 2201 } 2202 2203 /* process functions */ 2204 if (match_state_flags & candidate_function_flags) { 2205 for (i = 0 ; i < st_cached_magic_vars.functions_num ; i++) { 2206 int state_flags = st_cached_magic_vars.functions[i].flags; 2207 if ((state_flags & match_state_flags) && !(state_flags & skip_state_flags)) { 2208 st_set_transfer_status(status_flags, status_op, NULL, &st_cached_magic_vars.functions[i]); 2209 } 2210 } 2211 } 2212 } 2213 2214 PUBLIC int st_set_status_by_function_ids(int status_flags, int status_op, _magic_id_t *ids) 2215 { 2216 int r, i = 0; 2217 while (ids[i] != 0) { 2218 r = st_set_status_by_function_id(status_flags, status_op, ids[i]); 2219 if (r != OK) { 2220 return r; 2221 } 2222 i++; 2223 } 2224 return OK; 2225 } 2226 2227 PUBLIC int st_set_status_by_sentry_ids(int status_flags, int status_op, _magic_id_t *ids) 2228 { 2229 int r, i=0; 2230 while (ids[i] != 0) { 2231 r = st_set_status_by_sentry_id(status_flags, status_op, ids[i]); 2232 if (r != OK) { 2233 return r; 2234 } 2235 i++; 2236 } 2237 return OK; 2238 } 2239 2240 PUBLIC int st_set_status_by_names(int status_flags, int status_op, 2241 const char **parent_names, const char **names, 2242 _magic_id_t *dsentry_site_ids) 2243 { 2244 int r, i = 0; 2245 while (names[i] != NULL) { 2246 r = st_set_status_by_name(status_flags, status_op, 2247 parent_names ? parent_names[i] : NULL, names[i], 2248 dsentry_site_ids ? dsentry_site_ids[i] : 2249 MAGIC_DSENTRY_SITE_ID_NULL); 2250 if (r != OK) { 2251 return r; 2252 } 2253 i++; 2254 } 2255 return OK; 2256 } 2257 2258 PUBLIC int st_set_status_by_local_addrs(int status_flags, int status_op, 2259 void **addrs) 2260 { 2261 int r, i=0; 2262 while (addrs[i] != NULL) { 2263 r = st_set_status_by_local_addr(status_flags, status_op, addrs[i]); 2264 if (r != OK) { 2265 return r; 2266 } 2267 i++; 2268 } 2269 return OK; 2270 } 2271 2272 PUBLIC void st_set_status_by_sentry(int status_flags, int status_op, 2273 void *cached_sentry) 2274 { 2275 ST_CHECK_INIT(); 2276 2277 st_set_transfer_status(status_flags, status_op, 2278 (struct _magic_sentry*) cached_sentry, NULL); 2279 } 2280 2281 PUBLIC void st_set_status_by_function(int status_flags, int status_op, 2282 void *cached_function) 2283 { 2284 ST_CHECK_INIT(); 2285 2286 st_set_transfer_status(status_flags, status_op, 2287 NULL, (struct _magic_function*) cached_function); 2288 } 2289 2290 PUBLIC int st_set_status_by_name(int status_flags, int status_op, 2291 const char *parent_name, const char *name, _magic_id_t dsentry_site_id) 2292 { 2293 struct _magic_sentry *cached_sentry = NULL; 2294 struct _magic_function *cached_function = NULL; 2295 ST_CHECK_INIT(); 2296 2297 EXEC_WITH_MAGIC_VARS( 2298 cached_sentry = magic_sentry_lookup_by_name(parent_name ? parent_name : "", name, dsentry_site_id, NULL); 2299 if (!cached_sentry) { 2300 cached_function = magic_function_lookup_by_name(parent_name, name); 2301 } 2302 , &st_cached_magic_vars 2303 ); 2304 if (!cached_sentry && !cached_function) { 2305 return ENOENT; 2306 } 2307 st_set_transfer_status(status_flags, status_op, cached_sentry, cached_function); 2308 if (cached_sentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) { 2309 struct _magic_dsentry *prev_dsentry, *dsentry, *next_dsentry = MAGIC_DSENTRY_NEXT(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry)); 2310 struct _magic_sentry* sentry; 2311 /* 2312 * Alloc sentries may have multiple instances with the same name. 2313 * Use the site_id to distinguish between them. 2314 */ 2315 assert(parent_name && name); 2316 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(next_dsentry, prev_dsentry, dsentry, sentry, 2317 parent_name, name, dsentry_site_id, 2318 st_set_transfer_status(status_flags, status_op, sentry, NULL); 2319 ); 2320 } 2321 return OK; 2322 } 2323 2324 PUBLIC int st_set_status_by_function_id(int status_flags, int status_op, 2325 _magic_id_t id) 2326 { 2327 struct _magic_function *cached_function = NULL; 2328 ST_CHECK_INIT(); 2329 2330 EXEC_WITH_MAGIC_VARS( 2331 cached_function = magic_function_lookup_by_id(id, NULL); 2332 , &st_cached_magic_vars 2333 ); 2334 2335 if (!cached_function) { 2336 return ENOENT; 2337 } 2338 2339 st_set_transfer_status(status_flags, status_op, NULL, cached_function); 2340 return OK; 2341 } 2342 2343 PUBLIC int st_set_status_by_sentry_id(int status_flags, int status_op, 2344 _magic_id_t id) 2345 { 2346 struct _magic_sentry *cached_sentry = NULL; 2347 ST_CHECK_INIT(); 2348 2349 EXEC_WITH_MAGIC_VARS( 2350 cached_sentry = magic_sentry_lookup_by_id(id, NULL); 2351 , &st_cached_magic_vars 2352 ); 2353 2354 if (!cached_sentry) { 2355 return ENOENT; 2356 } 2357 2358 st_set_transfer_status(status_flags, status_op, cached_sentry, NULL); 2359 return OK; 2360 } 2361 2362 PUBLIC int st_set_status_by_local_addr(int status_flags, int status_op, 2363 void *addr) 2364 { 2365 const char *parent_name, *name; 2366 _magic_id_t dsentry_site_id = MAGIC_DSENTRY_SITE_ID_NULL; 2367 struct _magic_sentry *sentry = NULL; 2368 struct _magic_function *function = NULL; 2369 ST_CHECK_INIT(); 2370 2371 sentry = magic_sentry_lookup_by_addr(addr, NULL); 2372 if (!sentry) { 2373 function = magic_function_lookup_by_addr(addr, NULL); 2374 } 2375 if (sentry && !MAGIC_STATE_FLAG(sentry, MAGIC_STATE_DYNAMIC)) { 2376 name = sentry->name; 2377 parent_name = MAGIC_SENTRY_PARENT(sentry); 2378 dsentry_site_id = MAGIC_SENTRY_SITE_ID(sentry); 2379 } 2380 else if (function && !MAGIC_STATE_FLAG(function, MAGIC_STATE_DYNAMIC)) { 2381 name = function->name; 2382 parent_name = MAGIC_FUNCTION_PARENT(function); 2383 } 2384 else { 2385 return ENOENT; 2386 } 2387 st_set_status_by_name(status_flags, status_op, parent_name, name, dsentry_site_id); 2388 return OK; 2389 } 2390 2391 PUBLIC int st_pair_by_function_ids(unsigned long *cached_ids, unsigned long *local_ids, int status_flags, int status_op) 2392 { 2393 int r, i=0; 2394 ST_CHECK_INIT(); 2395 2396 while (cached_ids[i] != 0) { 2397 assert(local_ids[i] != 0); 2398 r = st_pair_by_function_id(cached_ids[i], local_ids[i], status_flags, status_op); 2399 if (r != OK) { 2400 return r; 2401 } 2402 i++; 2403 } 2404 return OK; 2405 } 2406 2407 PUBLIC int st_pair_by_sentry_ids(unsigned long *cached_ids, unsigned long *local_ids, int status_flags, int status_op) 2408 { 2409 int r, i=0; 2410 ST_CHECK_INIT(); 2411 2412 while (cached_ids[i] != 0) { 2413 assert(local_ids[i] != 0); 2414 r = st_pair_by_sentry_id(cached_ids[i], local_ids[i], status_flags, status_op); 2415 if (r != OK) { 2416 return r; 2417 } 2418 i++; 2419 } 2420 return OK; 2421 } 2422 2423 PUBLIC int st_pair_by_names(char **cached_parent_names, char **cached_names, 2424 char **local_parent_names, char **local_names, _magic_id_t *dsentry_site_ids, 2425 int status_flags, int status_op) 2426 { 2427 int r, i=0; 2428 while (cached_names[i] != NULL) { 2429 assert(local_names[i]); 2430 r = st_pair_by_name(cached_parent_names ? cached_parent_names[i] : NULL, cached_names[i], 2431 local_parent_names ? local_parent_names[i] : NULL, local_names[i], 2432 dsentry_site_ids ? dsentry_site_ids[i] : MAGIC_DSENTRY_SITE_ID_NULL, 2433 status_flags, status_op); 2434 if (r != OK) { 2435 return r; 2436 } 2437 i++; 2438 } 2439 return OK; 2440 } 2441 2442 PUBLIC void st_pair_by_sentry(void *cached_sentry, void *local_sentry, int status_flags, int status_op) 2443 { 2444 ST_CHECK_INIT(); 2445 2446 st_add_sentry_pair(cached_sentry, local_sentry); 2447 if (cached_sentry) { 2448 st_set_status_by_sentry(status_flags, status_op, cached_sentry); 2449 } 2450 } 2451 2452 PUBLIC void st_pair_by_function(void *cached_function, void* local_function, int status_flags, int status_op) 2453 { 2454 ST_CHECK_INIT(); 2455 2456 st_add_function_pair(cached_function, local_function); 2457 if (cached_function) { 2458 st_set_status_by_function(status_flags, status_op, cached_function); 2459 } 2460 } 2461 2462 PUBLIC int st_pair_alloc_by_dsindex(st_init_info_t *info, void *cached_sentry, void *local_dsindex, int num_elements, const union __alloc_flags *p_alloc_flags, int status_flags, int status_op) 2463 { 2464 int r; 2465 ST_CHECK_INIT(); 2466 2467 r = st_add_sentry_pair_alloc_by_dsindex(info, cached_sentry, local_dsindex, num_elements, p_alloc_flags); 2468 if (r != OK) { 2469 return r; 2470 } 2471 if (cached_sentry) { 2472 st_set_status_by_sentry(status_flags, status_op, cached_sentry); 2473 } 2474 return OK; 2475 } 2476 2477 PUBLIC int st_pair_by_function_id(unsigned long cached_id, unsigned long local_id, int status_flags, int status_op) 2478 { 2479 struct _magic_function *cached_function = NULL, *local_function = NULL; 2480 ST_CHECK_INIT(); 2481 assert(cached_id || local_id); 2482 2483 if (cached_id) { 2484 EXEC_WITH_MAGIC_VARS( 2485 cached_function = magic_function_lookup_by_id(cached_id, NULL); 2486 , &st_cached_magic_vars 2487 ); 2488 if (!cached_function) { 2489 return ENOENT; 2490 } 2491 } 2492 if (local_id) { 2493 EXEC_WITH_MAGIC_VARS( 2494 local_function = magic_function_lookup_by_id(local_id, NULL); 2495 , st_local_magic_vars_ptr 2496 ); 2497 if (!local_function) { 2498 return ENOENT; 2499 } 2500 } 2501 2502 st_pair_by_function(cached_function, local_function, status_flags, status_op); 2503 return OK; 2504 } 2505 2506 PUBLIC int st_pair_by_sentry_id(unsigned long cached_id, unsigned long local_id, int status_flags, int status_op) 2507 { 2508 struct _magic_sentry *cached_sentry = NULL, *local_sentry = NULL; 2509 ST_CHECK_INIT(); 2510 assert(cached_id || local_id); 2511 2512 if (cached_id) { 2513 EXEC_WITH_MAGIC_VARS( 2514 cached_sentry = magic_sentry_lookup_by_id(cached_id, NULL); 2515 , &st_cached_magic_vars 2516 ); 2517 if (!cached_sentry) { 2518 return ENOENT; 2519 } 2520 } 2521 if (local_id) { 2522 EXEC_WITH_MAGIC_VARS( 2523 local_sentry = magic_sentry_lookup_by_id(local_id, NULL); 2524 , st_local_magic_vars_ptr 2525 ); 2526 if (!local_sentry) { 2527 return ENOENT; 2528 } 2529 } 2530 2531 st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op); 2532 return OK; 2533 } 2534 2535 PUBLIC int st_pair_by_name(char *cached_parent_name, char *cached_name, 2536 char *local_parent_name, char *local_name, _magic_id_t dsentry_site_id, 2537 int status_flags, int status_op) 2538 { 2539 struct _magic_function *cached_function = NULL, *local_function = NULL; 2540 struct _magic_sentry *cached_sentry = NULL, *local_sentry = NULL; 2541 ST_CHECK_INIT(); 2542 assert(cached_name || local_name); 2543 2544 if (cached_name) { 2545 EXEC_WITH_MAGIC_VARS( 2546 cached_sentry = magic_sentry_lookup_by_name(cached_parent_name ? cached_parent_name : "", cached_name, dsentry_site_id, NULL); 2547 if (cached_sentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) { 2548 return EINVAL; 2549 } 2550 if (!cached_sentry) { 2551 cached_function = magic_function_lookup_by_name(NULL, cached_name); 2552 } 2553 , &st_cached_magic_vars 2554 ); 2555 if (!cached_sentry && !cached_function) { 2556 return ENOENT; 2557 } 2558 } 2559 if (local_name) { 2560 EXEC_WITH_MAGIC_VARS( 2561 if (!cached_function) { 2562 local_sentry = magic_sentry_lookup_by_name(local_parent_name ? local_parent_name : "", local_name, dsentry_site_id, NULL); 2563 if (local_sentry && MAGIC_SENTRY_IS_ALLOC(local_sentry)) { 2564 return EINVAL; 2565 } 2566 } 2567 if (!cached_sentry && !local_sentry) { 2568 local_function = magic_function_lookup_by_name(NULL, local_name); 2569 } 2570 , st_local_magic_vars_ptr 2571 ); 2572 if (!local_sentry && !local_function) { 2573 return ENOENT; 2574 } 2575 } 2576 if (cached_function || local_function) { 2577 assert(!cached_sentry && !local_sentry); 2578 st_pair_by_function(cached_function, local_function, status_flags, status_op); 2579 return OK; 2580 } 2581 assert(cached_sentry || local_sentry); 2582 st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op); 2583 return OK; 2584 } 2585 2586 PUBLIC int st_pair_by_alloc_name_policies(st_init_info_t *info, char *cached_parent_name, char *cached_name, _magic_id_t cached_dsentry_site_id, char *local_parent_name, char *local_name, _magic_id_t local_dsentry_site_id, int num_elements, const union __alloc_flags *p_alloc_flags, int alloc_policies, int status_flags, int status_op) 2587 { 2588 int r, saved_policies = st_policies; 2589 st_policies &= ~(ST_ON_ALLOC_UNPAIR_MASK); 2590 st_policies |= (alloc_policies & ST_ON_ALLOC_UNPAIR_MASK); 2591 r = st_pair_by_alloc_name(info, cached_parent_name, cached_name, cached_dsentry_site_id, local_parent_name, local_name, local_dsentry_site_id, num_elements, p_alloc_flags, status_flags, status_op); 2592 st_policies = saved_policies; 2593 return r; 2594 } 2595 2596 PUBLIC int st_pair_by_alloc_name(st_init_info_t *info, char *cached_parent_name, char *cached_name, _magic_id_t cached_dsentry_site_id, char *local_parent_name, char *local_name, _magic_id_t local_dsentry_site_id, int num_elements, const union __alloc_flags *p_alloc_flags, int status_flags, int status_op) 2597 { 2598 struct _magic_sentry *cached_sentry = NULL, *local_sentry = NULL; 2599 struct _magic_dsindex *local_dsindex = NULL; 2600 struct _magic_dsentry *prev_dsentry, *dsentry, *head_dsentry; 2601 struct _magic_sentry* sentry; 2602 int r; 2603 int is_cached_alloc = FALSE, is_local_alloc = FALSE; 2604 ST_CHECK_INIT(); 2605 assert(cached_name || local_name); 2606 assert(!((cached_name == NULL) ^ (cached_parent_name == NULL))); 2607 assert(!((local_name == NULL) ^ (local_parent_name == NULL))); 2608 2609 if (cached_name) { 2610 EXEC_WITH_MAGIC_VARS( 2611 cached_sentry = magic_sentry_lookup_by_name(cached_parent_name, 2612 cached_name, cached_dsentry_site_id, NULL); 2613 if (cached_sentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) { 2614 is_cached_alloc = TRUE; 2615 } 2616 , &st_cached_magic_vars 2617 ); 2618 } 2619 if (local_name) { 2620 EXEC_WITH_MAGIC_VARS( 2621 local_sentry = magic_sentry_lookup_by_name(local_parent_name, 2622 local_name, local_dsentry_site_id, NULL); 2623 if (local_sentry && MAGIC_SENTRY_IS_ALLOC(local_sentry)) { 2624 is_local_alloc = TRUE; 2625 } 2626 if (!local_sentry || is_local_alloc) { 2627 local_dsindex = magic_dsindex_lookup_by_name(local_parent_name, local_name); 2628 if (local_dsindex && !MAGIC_DSINDEX_IS_ALLOC(local_dsindex)) { 2629 local_dsindex = NULL; 2630 } 2631 if (local_sentry) assert(local_dsindex); 2632 is_local_alloc = is_local_alloc || local_dsindex != NULL; 2633 } 2634 , st_local_magic_vars_ptr 2635 ); 2636 } 2637 if (!is_cached_alloc && !is_local_alloc) { 2638 if (cached_sentry || local_sentry) { 2639 st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op); 2640 return OK; 2641 } 2642 return ENOENT; 2643 } 2644 if (local_sentry) { 2645 if (!is_local_alloc) { 2646 /* Alloc sentries may have multiple instances with the same name. */ 2647 assert(cached_sentry && is_cached_alloc); 2648 head_dsentry = MAGIC_DSENTRY_NEXT(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry)); 2649 assert(cached_parent_name && cached_name); 2650 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry, prev_dsentry, dsentry, sentry, cached_parent_name, cached_name, cached_dsentry_site_id, 2651 /* Cannot map multiple cached alloc sentries to a single local non-alloc sentry. */ 2652 return E2BIG; 2653 ); 2654 /* Map a single cached alloc sentry to a single local non-alloc sentry. */ 2655 st_pair_by_sentry(cached_sentry, local_sentry, status_flags, status_op); 2656 return OK; 2657 } 2658 else { 2659 /* Unpair all the local alloc sentries. */ 2660 head_dsentry = MAGIC_DSENTRY_FROM_SENTRY(local_sentry); 2661 assert(local_parent_name && local_name); 2662 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry, prev_dsentry, dsentry, sentry, local_parent_name, local_name, local_dsentry_site_id, 2663 st_pair_by_sentry(NULL, sentry, status_flags, status_op); 2664 ); 2665 } 2666 } 2667 if (!cached_sentry) { 2668 return OK; 2669 } 2670 2671 /* Map a single cached non-alloc sentry to a local to-be-alloc sentry. */ 2672 if (!is_cached_alloc) { 2673 assert(local_dsindex); 2674 return st_pair_alloc_by_dsindex(info, cached_sentry, local_dsindex, num_elements, p_alloc_flags, status_flags, status_op); 2675 } 2676 2677 /* Map all the cached alloc sentries to the corresponding local to-be-alloc sentries (or NULL). */ 2678 head_dsentry = MAGIC_DSENTRY_FROM_SENTRY(cached_sentry); 2679 assert(cached_parent_name && cached_name); 2680 MAGIC_DSENTRY_ALIVE_NAME_ID_ITER(head_dsentry, prev_dsentry, dsentry, 2681 sentry, cached_parent_name, cached_name, cached_dsentry_site_id, 2682 r = st_pair_alloc_by_dsindex(info, sentry, local_dsindex, num_elements, p_alloc_flags, status_flags, status_op); 2683 if (r != OK) { 2684 return r; 2685 } 2686 ); 2687 2688 return OK; 2689 } 2690 2691 /* Metadata transfer and adjustment functions */ 2692 2693 PRIVATE int transfer_metadata_functions(st_init_info_t *info, 2694 struct _magic_vars_t *cached_magic_vars, 2695 struct _magic_vars_t *remote_magic_vars, 2696 st_counterparts_t *counterparts) 2697 { 2698 2699 int i; 2700 struct _magic_function *cached_function; 2701 2702 /* transfer magic_functions */ 2703 MD_TRANSFER(info, remote_magic_vars->functions, (void **)&cached_magic_vars->functions, remote_magic_vars->functions_num * sizeof(struct _magic_function)); 2704 2705 /* adjust magic_functions */ 2706 for (i = 0 ; i < cached_magic_vars->functions_num ; i++) { 2707 cached_function = &cached_magic_vars->functions[i]; 2708 MD_TRANSFER_STR(info, &cached_function->name); 2709 cached_function->type = &cached_magic_vars->types[cached_function->type - remote_magic_vars->types]; 2710 } 2711 2712 return OK; 2713 } 2714 2715 PRIVATE int transfer_metadata_dfunctions(st_init_info_t *info, 2716 struct _magic_vars_t *cached_magic_vars, 2717 struct _magic_vars_t *remote_magic_vars, 2718 st_counterparts_t *counterparts) 2719 { 2720 2721 struct _magic_dfunction **dfunction_ptr; 2722 struct _magic_dfunction *cached_dfunction, *prev_dfunction = NULL; 2723 struct _magic_function *cached_function; 2724 2725 /* Transfer dfunctions. */ 2726 cached_magic_vars->first_dfunction = remote_magic_vars->first_dfunction; 2727 dfunction_ptr = &cached_magic_vars->first_dfunction; 2728 while (*dfunction_ptr != NULL) { 2729 MD_TRANSFER(info, *dfunction_ptr, (void **)dfunction_ptr, sizeof(struct _magic_dfunction)); 2730 cached_dfunction = *dfunction_ptr; 2731 2732 /* Adjust dfunction parent_name and next/prev links. */ 2733 if (cached_dfunction->parent_name != NULL) { 2734 MD_TRANSFER_STR(info, &cached_dfunction->parent_name); 2735 if (strlen(cached_dfunction->parent_name) == 0) { 2736 printf("ERROR. strlen(dfunction->parent_name) == 0.\n"); 2737 return EGENERIC; 2738 } 2739 } else { 2740 printf("ERROR. dfunction->parent_name == NULL.\n"); 2741 return EGENERIC; 2742 } 2743 2744 /* Adjust function name and type. */ 2745 cached_function = &cached_dfunction->function; 2746 MD_TRANSFER_STR(info, &cached_function->name); 2747 cached_function->type = &cached_magic_vars->types[cached_function->type - remote_magic_vars->types]; 2748 2749 if (cached_dfunction->prev != NULL) 2750 cached_dfunction->prev = prev_dfunction; 2751 2752 dfunction_ptr = &cached_dfunction->next; 2753 prev_dfunction = cached_dfunction; 2754 } 2755 2756 cached_magic_vars->last_dfunction = prev_dfunction; 2757 2758 return OK; 2759 } 2760 2761 2762 PUBLIC int st_transfer_metadata_types(st_init_info_t *info, struct _magic_vars_t *cached_magic_vars 2763 , struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts) 2764 { 2765 2766 int i; 2767 2768 /* transfer types */ 2769 MD_TRANSFER(info, remote_magic_vars->types, (void **)&cached_magic_vars->types, remote_magic_vars->types_num * sizeof(struct _magic_type)); 2770 2771 /* type adjustments */ 2772 for (i = 0 ; i < cached_magic_vars->types_num ; i++) { 2773 if (transfer_metadata_type_members(info, &cached_magic_vars->types[i], cached_magic_vars, remote_magic_vars)) { 2774 printf("ERROR transferring type members metadata.\n"); 2775 return EGENERIC; 2776 } 2777 set_typename_key(&cached_magic_vars->types[i]); 2778 } 2779 2780 return OK; 2781 } 2782 2783 PRIVATE int transfer_metadata_type_value_set(st_init_info_t *info, struct _magic_type *type, struct _magic_vars_t *cached_magic_vars, struct _magic_vars_t *remote_magic_vars) 2784 { 2785 int num_elements; 2786 /* MD_TRANSFER cannot be used, because it will allocate space for num_elements */ 2787 if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) type->value_set, sizeof(int), (uint32_t) &num_elements)) { 2788 printf("ERROR transferring type value set metadata.\n"); 2789 return EGENERIC; 2790 } 2791 num_elements++; 2792 MD_TRANSFER(info, type->value_set, (void **)&type->value_set, num_elements *sizeof(int)); 2793 return OK; 2794 } 2795 2796 PRIVATE int transfer_metadata_type_members(st_init_info_t *info, struct _magic_type *type, struct _magic_vars_t *cached_magic_vars, struct _magic_vars_t *remote_magic_vars) 2797 { 2798 int r; 2799 int num_child = MAGIC_TYPE_NUM_CONTAINED_TYPES(type), i; 2800 2801 MD_TRANSFER_STR(info, &type->name); 2802 MD_TRANSFER_STR(info, &type->type_str); 2803 2804 if (type->names != NULL && type->num_names > 0) { 2805 /* transfer array of name pointers */ 2806 MD_TRANSFER(info, type->names, (void **)&type->names, type->num_names * sizeof(char *)); 2807 for (i = 0 ; (unsigned int)i < type->num_names ; i++) { 2808 /* transfer individual name */ 2809 MD_TRANSFER_STR(info, &type->names[i]); 2810 } 2811 } 2812 2813 2814 #define MD_TRANSFER_ADJUST_MEMBER_PTR(NUM_ELEMENTS, \ 2815 ELEMENT_SIZE,PTR_ARRAY,INDEX) \ 2816 if((NUM_ELEMENTS) > 0 && (PTR_ARRAY) != NULL) { \ 2817 MD_TRANSFER(info, PTR_ARRAY, (void **)&PTR_ARRAY, \ 2818 NUM_ELEMENTS * ELEMENT_SIZE); \ 2819 for(INDEX = 0 ; (INDEX) < (NUM_ELEMENTS) ; INDEX++) { \ 2820 PTR_ARRAY[INDEX] = ADJUST_POINTER(cached_magic_vars->types, \ 2821 remote_magic_vars->types, PTR_ARRAY[INDEX]); \ 2822 } \ 2823 } 2824 2825 MD_TRANSFER_ADJUST_MEMBER_PTR( 2826 (type->type_id == MAGIC_TYPE_FUNCTION ? num_child + 1 : num_child), 2827 sizeof(struct _magic_type *), type->contained_types, i 2828 ); 2829 2830 if (type->compatible_types) { 2831 struct _magic_type *comp_types_element; 2832 int comp_types_size=0; 2833 /* determine size of array */ 2834 do { 2835 if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) &type->compatible_types[comp_types_size] 2836 , sizeof(struct _magic_type *), (uint32_t) &comp_types_element)) 2837 { 2838 printf("ERROR transferring compatible types array metadata.\n"); 2839 return EGENERIC; 2840 } 2841 comp_types_size++; 2842 } while(comp_types_element != NULL); 2843 /* We know the size, now transfer the whole array */ 2844 MD_TRANSFER(info, type->compatible_types, (void **) &type->compatible_types, comp_types_size * sizeof(struct _magic_type *)); 2845 for (i = 0; i < comp_types_size; i++) { 2846 if (type->compatible_types[i] != NULL) { 2847 /* Adjust the pointer to point to the local counterpart */ 2848 type->compatible_types[i] = ADJUST_POINTER(cached_magic_vars->types, remote_magic_vars->types, type->compatible_types[i]); 2849 } 2850 } 2851 } 2852 2853 if (num_child>0 && type->member_names != NULL) { 2854 MD_TRANSFER(info, type->member_names, (void **)&type->member_names, num_child * sizeof(char *)); 2855 for (i = 0 ; i < num_child ; i++) { 2856 MD_TRANSFER_STR(info, &type->member_names[i]); 2857 } 2858 } 2859 2860 if (num_child>0 && type->member_offsets != NULL) { 2861 MD_TRANSFER(info, type->member_offsets, (void **)&type->member_offsets, num_child * sizeof(unsigned)); 2862 } 2863 2864 if (MAGIC_TYPE_HAS_VALUE_SET(type)) { 2865 r = transfer_metadata_type_value_set(info, type, cached_magic_vars, remote_magic_vars); 2866 if (r != OK) { 2867 return r; 2868 } 2869 } 2870 return OK; 2871 } 2872 2873 PRIVATE int transfer_metadata_sentries(st_init_info_t *info, struct _magic_vars_t *cached_magic_vars 2874 , struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts 2875 , size_t *max_buff_sz) 2876 { 2877 2878 int i; 2879 int skipped_sentries = 0; 2880 struct _magic_sentry *cached_sentry; 2881 2882 /* transfer sentries */ 2883 MD_TRANSFER(info, remote_magic_vars->sentries, (void **)&cached_magic_vars->sentries, remote_magic_vars->sentries_num * sizeof(struct _magic_sentry)); 2884 /* todo: try to use only remote_magic_vars or cached magic_vars */ 2885 /* todo: if transfer is complete, and argument 2 and 3 are always the same, remove 2nd argument */ 2886 2887 /* adjust sentries */ 2888 for (i = 0 ; i < cached_magic_vars->sentries_num ; i++) { 2889 cached_sentry = &cached_magic_vars->sentries[i]; 2890 2891 if ((st_policies & ST_TRANSFER_DIRTY_ONLY) && 2892 !MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DIRTY_PAGE) && 2893 !MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_IMMUTABLE)) { 2894 skipped_sentries++; 2895 continue; 2896 } 2897 if (skipped_sentries > 0) { 2898 cached_magic_vars->sentries[i - skipped_sentries] = 2899 cached_magic_vars->sentries[i]; 2900 cached_magic_vars->sentries[i - skipped_sentries].id -= 2901 skipped_sentries; 2902 cached_sentry = &cached_magic_vars->sentries[i - skipped_sentries]; 2903 } 2904 2905 2906 if (transfer_metadata_sentry_members(info, cached_sentry)) { 2907 printf("ERROR transferring sentry members metadata.\n"); 2908 return EGENERIC; 2909 } 2910 2911 /* 2912 * We have to change the type to its cached counterpart, 2913 * so that it may be compared to the local type of the local sentry counterpart. 2914 */ 2915 cached_sentry->type = &cached_magic_vars->types[cached_sentry->type - remote_magic_vars->types]; 2916 2917 if (cached_sentry->type->size > *max_buff_sz) { 2918 *max_buff_sz = cached_sentry->type->size; 2919 } 2920 } 2921 2922 if (skipped_sentries > 0) 2923 cached_magic_vars->sentries_num -= skipped_sentries; 2924 2925 return OK; 2926 } 2927 2928 PRIVATE int transfer_metadata_sentry_members(st_init_info_t *info, struct _magic_sentry *sentry) 2929 { 2930 if (sentry->name != NULL) { 2931 MD_TRANSFER_STR(info, &sentry->name); 2932 } else { 2933 printf("ERROR. sentry->name == NULL.\n"); 2934 return EGENERIC; 2935 } 2936 return OK; 2937 } 2938 2939 PUBLIC int st_transfer_metadata_dsentries(st_init_info_t *info, struct _magic_vars_t *cached_magic_vars 2940 , struct _magic_vars_t *remote_magic_vars, st_counterparts_t *counterparts, size_t *max_buff_sz, int *dsentries_num) 2941 { 2942 2943 struct _magic_dsentry **dsentry_ptr; 2944 #if MAGIC_DSENTRY_ALLOW_PREV 2945 struct _magic_dsentry *prev_dsentry = NULL; 2946 #endif 2947 int r; 2948 2949 *dsentries_num = 0; 2950 2951 cached_magic_vars->first_dsentry = remote_magic_vars->first_dsentry; 2952 dsentry_ptr = &cached_magic_vars->first_dsentry; 2953 while (*dsentry_ptr != NULL) { 2954 2955 struct _magic_dsentry *cached_dsentry, *remote_dsentry = *dsentry_ptr; 2956 struct _magic_sentry *sentry; 2957 2958 /* transfer dsentry */ 2959 MD_TRANSFER(info, *dsentry_ptr, (void **) dsentry_ptr, sizeof(struct _magic_dsentry)); 2960 cached_dsentry = *dsentry_ptr; 2961 2962 if ((st_policies & ST_TRANSFER_DIRTY_ONLY) && 2963 !MAGIC_STATE_FLAG((&cached_dsentry->sentry), MAGIC_STATE_DIRTY_PAGE) && 2964 !MAGIC_STATE_FLAG((&cached_dsentry->sentry), MAGIC_STATE_IMMUTABLE)) { 2965 *dsentry_ptr = cached_dsentry->next; 2966 continue; 2967 } 2968 2969 if (cached_magic_vars->first_stack_dsentry == remote_dsentry) { 2970 cached_magic_vars->first_stack_dsentry = cached_dsentry; 2971 } else if(cached_magic_vars->last_stack_dsentry == remote_dsentry) { 2972 cached_magic_vars->last_stack_dsentry = cached_dsentry; 2973 } 2974 2975 /* adjust dsentry */ 2976 if (cached_dsentry->parent_name != NULL) { 2977 MD_TRANSFER_STR(info, &cached_dsentry->parent_name); 2978 if (strlen(cached_dsentry->parent_name) == 0) { 2979 printf("ERROR. strlen(dsentry->parent_name) == 0.\n"); 2980 #if TODO_DSENTRY_PARENT_NAME_BUG 2981 if (cached_dsentry->next != NULL) 2982 #endif 2983 return EGENERIC; 2984 } 2985 } else { 2986 printf("ERROR. dsentry->parent_name == NULL.\n"); 2987 return EGENERIC; 2988 } 2989 2990 sentry = &cached_dsentry->sentry; 2991 if (transfer_metadata_sentry_members(info, sentry)) { 2992 printf("ERROR transferring sentry members metadata.\n"); 2993 return EGENERIC; 2994 } 2995 2996 /* Override original id to simplify pairing later. */ 2997 sentry->id = cached_magic_vars->sentries_num + *dsentries_num + 1; 2998 2999 /* 3000 * Report violations for all the pointers pointing to the initial stack area. 3001 * This is to make sure no assumption is incorrectly made about this area. 3002 */ 3003 if (!strcmp(sentry->name, MAGIC_ALLOC_INITIAL_STACK_NAME)) { 3004 sentry->flags |= MAGIC_STATE_ADDR_NOT_TAKEN; 3005 } 3006 3007 /* 3008 * Adjust the type, so that the local and remote type can be compared 3009 * during a server version update 3010 */ 3011 if (sentry->type == &remote_dsentry->type) { 3012 3013 /* 3014 * sentry->type is contained in dsentry.type. Therefore, this is an 3015 * array type. In order to allocate a new memory region, we only 3016 * need the size of the type, and the contained type as arguments 3017 * to the magic allocation function. Therefore, other members of 3018 * the type do need to be cached or adjusted. 3019 */ 3020 3021 /* Adjust pointer to cached location */ 3022 sentry->type = &cached_dsentry->type; 3023 3024 /* Adjust contained_types to type_array located in dsentry struct. */ 3025 sentry->type->contained_types = cached_dsentry->type_array; 3026 3027 /* 3028 * Adjust only pointer in type_array. It currently has the same 3029 * value as the remote copy, but it has to point to the cached 3030 * of the contained type. 3031 */ 3032 sentry->type->contained_types[0] = &cached_magic_vars->types[sentry->type->contained_types[0] - remote_magic_vars->types]; 3033 3034 /* Adjust empty strings. */ 3035 sentry->type->name = ""; 3036 sentry->type->type_str = ""; 3037 3038 /* Adjust value set if necessary. */ 3039 if (MAGIC_TYPE_HAS_VALUE_SET(sentry->type)) { 3040 r = transfer_metadata_type_value_set(info, sentry->type, cached_magic_vars, remote_magic_vars); 3041 if (r != OK) { 3042 return r; 3043 } 3044 } 3045 } else { 3046 3047 /* 3048 * sentry.type must be in the global type array. Adjust pointer accordingly. 3049 * The pointer is still pointing to the remote version. 3050 * We have to change it to the cached version. 3051 */ 3052 sentry->type = &cached_magic_vars->types[sentry->type - remote_magic_vars->types]; 3053 3054 } 3055 3056 /* see if the buffer needs to be bigger for the dsentry data region. */ 3057 if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND) && *max_buff_sz < sentry->type->size) { 3058 *max_buff_sz = sentry->type->size; 3059 } 3060 3061 dsentry_ptr = &cached_dsentry->next; 3062 #if MAGIC_DSENTRY_ALLOW_PREV 3063 if (cached_dsentry->prev != NULL) 3064 cached_dsentry->prev = prev_dsentry; 3065 prev_dsentry = cached_dsentry; 3066 #endif 3067 *dsentries_num = *dsentries_num + 1; 3068 } 3069 3070 return OK; 3071 } 3072 3073 PRIVATE int pair_metadata_types(st_init_info_t *info, 3074 struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts, int allow_unpaired_types) 3075 { 3076 int i, j, num_unpaired_struct_types = 0; 3077 int num_unpaired_types = 0; 3078 int num_total_types = 0; 3079 int num_struct_types = 0; 3080 int num_unpaired_types_left, num_unpaired_struct_types_left; 3081 3082 if (st_unpaired_types_ratio > 0 || st_unpaired_struct_types_ratio > 0) { 3083 for (i = 0 ; i < cached_magic_vars->types_num ; i++) { 3084 struct _magic_type *type = &cached_magic_vars->types[i]; 3085 if (ST_IS_UNPAIRABLE_STRUCT_TYPE(type)) { 3086 num_struct_types++; 3087 } 3088 if (ST_IS_UNPAIRABLE_TYPE(type)) { 3089 num_total_types++; 3090 } 3091 } 3092 num_unpaired_types = (int) (st_unpaired_types_ratio*num_total_types); 3093 num_unpaired_struct_types = (int) (st_unpaired_struct_types_ratio*num_struct_types); 3094 } 3095 num_unpaired_types_left = num_unpaired_types; 3096 num_unpaired_struct_types_left = num_unpaired_struct_types; 3097 3098 /* type pairing, remote->local */ 3099 for(i = 0 ; i < cached_magic_vars->types_num ; i++) { 3100 struct _magic_type *type = &cached_magic_vars->types[i]; 3101 counterparts->types[i].counterpart = NULL; 3102 3103 if (num_unpaired_types_left > 0 && ST_IS_UNPAIRABLE_TYPE(type)) { 3104 num_unpaired_types_left--; 3105 continue; 3106 } 3107 else if (num_unpaired_struct_types_left > 0 && ST_IS_UNPAIRABLE_STRUCT_TYPE(type)) { 3108 num_unpaired_struct_types_left--; 3109 continue; 3110 } 3111 3112 for (j = 0 ; j < _magic_types_num ; j++) { 3113 /* A remote type may be paired to multiple local types. 3114 * It is safe to index only the first type since counterparts 3115 * are only used to speed up type matching. 3116 */ 3117 if (magic_type_compatible(type, &_magic_types[j], MAGIC_TYPE_COMPARE_ALL)) { 3118 counterparts->types[i].counterpart = &_magic_types[j]; 3119 break; 3120 } 3121 } 3122 3123 if (!allow_unpaired_types && counterparts->types[i].counterpart == NULL) { 3124 printf("ERROR, remote type cannot be paired with a local type: "); 3125 MAGIC_TYPE_PRINT(type, MAGIC_EXPAND_TYPE_STR); 3126 printf("\n"); 3127 return EGENERIC; 3128 } 3129 } 3130 if (st_unpaired_types_ratio > 0 || st_unpaired_struct_types_ratio > 0) { 3131 assert(num_unpaired_types_left == 0 && (st_unpaired_types_ratio > 0 || num_unpaired_struct_types == 0)); 3132 _magic_printf("Unpaired types stats: unpaired types: %d, total types: %d, unpaired struct types: %d, struct types: %d\n", num_unpaired_types, num_total_types, num_unpaired_struct_types, num_struct_types); 3133 } 3134 3135 for (i = 0 ; i < cached_magic_vars->types_num ; i++) { 3136 struct _magic_type *type = &cached_magic_vars->types[i]; 3137 struct _magic_type *local_type = (struct _magic_type*) counterparts->types[i].counterpart; 3138 counterparts->ptr_types[i].counterpart = NULL; 3139 if (local_type && type->type_id == MAGIC_TYPE_POINTER) { 3140 if (MAGIC_TYPE_HAS_COMP_TYPES(type) != MAGIC_TYPE_HAS_COMP_TYPES(local_type)) { 3141 continue; 3142 } 3143 if (MAGIC_TYPE_HAS_COMP_TYPES(type)) { 3144 j = 0; 3145 while (MAGIC_TYPE_HAS_COMP_TYPE(type, j) && MAGIC_TYPE_HAS_COMP_TYPE(local_type, j)) { 3146 struct _magic_type *ctype = MAGIC_TYPE_COMP_TYPE(type, j); 3147 struct _magic_type *local_ctype = MAGIC_TYPE_COMP_TYPE(local_type, j); 3148 if (!ST_TYPE_IS_CACHED_COUNTERPART(ctype, local_ctype)) { 3149 break; 3150 } 3151 j++; 3152 } 3153 if (MAGIC_TYPE_HAS_COMP_TYPE(type, j) || MAGIC_TYPE_HAS_COMP_TYPE(local_type, j)) { 3154 continue; 3155 } 3156 } 3157 counterparts->ptr_types[i].counterpart = local_type; 3158 } 3159 } 3160 3161 return OK; 3162 } 3163 3164 PRIVATE int pair_metadata_functions(st_init_info_t *info, 3165 struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts) 3166 { 3167 int i; 3168 struct _magic_function *cached_function, *local_function; 3169 #if ST_DEBUG_LEVEL > 0 3170 int num_relocated = 0; 3171 #endif 3172 3173 /* map remote functions to local functions */ 3174 for(i = 0 ; i < cached_magic_vars->functions_num ; i++) { 3175 cached_function = &cached_magic_vars->functions[i]; 3176 local_function = NULL; 3177 st_map_functions(&cached_function, &local_function); 3178 ST_SET_CACHED_COUNTERPART(cached_function, functions, functions, local_function); 3179 3180 #if CHECK_SENTITY_PAIRS 3181 if (local_function) { 3182 /* debug: see if the function is paired more than once */ 3183 struct _magic_function *cfunction = NULL; 3184 st_map_functions(&cfunction, &local_function); 3185 if (cfunction != cached_function) { 3186 printf("function pairing failed for (1) local function linked to multiple remote functions (2), (3)\n"); 3187 printf("(1) "); MAGIC_FUNCTION_PRINT(local_function, 0); printf("\n"); 3188 printf("(2) "); MAGIC_FUNCTION_PRINT(cached_function, 0); printf("\n"); 3189 printf("(3) "); MAGIC_FUNCTION_PRINT(cfunction, 0); printf("\n"); 3190 return EGENERIC; 3191 } 3192 } 3193 #endif 3194 3195 #if ST_DEBUG_LEVEL > 0 3196 if (local_function && cached_function->address != local_function->address) { 3197 num_relocated++; 3198 if (ST_DEBUG_LEVEL > 1) { 3199 printf("- relocated function: '%s'\n", cached_magic_vars->functions[i].name); 3200 } 3201 } 3202 #endif 3203 } 3204 3205 #if ST_DEBUG_LEVEL > 0 3206 printf("total remote functions: %d. relocated: %d\n", cached_magic_vars->functions_num, num_relocated); 3207 #endif 3208 3209 return OK; 3210 } 3211 3212 PRIVATE int pair_metadata_sentries(st_init_info_t *info, 3213 struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts) 3214 { 3215 int i, r; 3216 struct _magic_sentry *cached_sentry, *local_sentry; 3217 #if ST_DEBUG_LEVEL > 0 3218 int num_relocated_str = 0, num_relocated_normal = 0; 3219 #endif 3220 3221 /* pair sentries remote->local */ 3222 for (i = 0 ; i < cached_magic_vars->sentries_num ; i++) { 3223 void *local_data_addr = NULL; 3224 cached_sentry = &cached_magic_vars->sentries[i]; 3225 3226 /* String data is transferred directly. */ 3227 if (MAGIC_SENTRY_IS_STRING(cached_sentry)) { 3228 char *string = st_buff_allocate(info, cached_sentry->type->size); 3229 if (!string) { 3230 printf("ERROR allocating string.\n"); 3231 return EGENERIC; 3232 } 3233 r = st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) cached_sentry->address, 3234 cached_sentry->type->size, (uint32_t) string); 3235 if(r != OK) { 3236 printf("ERROR transferring string.\n"); 3237 return EGENERIC; 3238 } 3239 local_data_addr = string; 3240 } 3241 ST_SET_CACHED_COUNTERPART(cached_sentry, sentries, sentries_data, local_data_addr); 3242 3243 local_sentry = NULL; 3244 st_map_sentries(&cached_sentry, &local_sentry); 3245 ST_SET_CACHED_COUNTERPART(cached_sentry, sentries, sentries, local_sentry); 3246 3247 #if CHECK_SENTITY_PAIRS 3248 if (local_sentry && !MAGIC_SENTRY_IS_STRING(cached_sentry)) { 3249 /* debug: see if the non-string sentry is paired more than once */ 3250 struct _magic_sentry *csentry = NULL; 3251 st_map_sentries(&csentry, &local_sentry); 3252 if (csentry != cached_sentry) { 3253 printf("sentry pairing failed for (1) local sentry linked to multiple remote sentries (2), (3)\n"); 3254 printf("(1) "); MAGIC_SENTRY_PRINT(local_sentry, 0); printf("\n"); 3255 printf("(2) "); MAGIC_SENTRY_PRINT(cached_sentry, 0); printf("\n"); 3256 printf("(3) "); MAGIC_SENTRY_PRINT(csentry, 0); printf("\n"); 3257 return EGENERIC; 3258 } 3259 } 3260 #endif 3261 3262 #if ST_DEBUG_LEVEL > 0 3263 if (local_sentry && cached_sentry->address != local_sentry->address) { 3264 if (MAGIC_SENTRY_IS_STRING(cached_sentry)) { 3265 num_relocated_str++; 3266 } 3267 else { 3268 num_relocated_normal++; 3269 if (ST_DEBUG_LEVEL > 1) { 3270 printf("- relocated non-string sentry: '%s'\n", cached_sentry->name); 3271 } 3272 } 3273 } 3274 #endif 3275 } 3276 3277 #if ST_DEBUG_LEVEL > 0 3278 printf("total remote sentries: %d. relocated normal: %d relocated string: %d\n", cached_magic_vars->sentries_num, num_relocated_normal, num_relocated_str); 3279 #endif 3280 3281 return OK; 3282 } 3283 3284 #if ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 3285 PRIVATE int allocate_pair_metadata_dsentries_from_raw_copy(st_init_info_t *info, 3286 struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts) 3287 { 3288 struct _magic_dsentry *dsentry; 3289 int remote_dsentries = 0, unpaired_dsentries = 0; 3290 3291 #if ST_DEBUG_LEVEL > 3 3292 EXEC_WITH_MAGIC_VARS( 3293 magic_print_dsentries(); 3294 , &st_cached_magic_vars 3295 ); 3296 magic_print_dsentries(); 3297 #endif 3298 3299 dsentry = cached_magic_vars->first_dsentry; 3300 while (dsentry != NULL) { 3301 struct _magic_sentry *local_sentry = NULL, *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 3302 3303 /* Initialize counterpart to NULL. */ 3304 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, NULL); 3305 3306 remote_dsentries++; 3307 3308 if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_STACK) && !MAGIC_STATE_FLAG(sentry, MAGIC_STATE_LIB)) { 3309 local_sentry = MAGIC_DSENTRY_TO_SENTRY((struct _magic_dsentry *)MAGIC_PTR_FROM_DATA(sentry->address)); 3310 } else { 3311 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX 3312 EXEC_WITH_MAGIC_VARS( 3313 local_sentry = magic_sentry_lookup_by_range(sentry->address, NULL); 3314 , &st_cached_magic_vars 3315 ); 3316 #else 3317 local_sentry = magic_sentry_lookup_by_addr(sentry->address, NULL); 3318 #endif 3319 } 3320 3321 if (!local_sentry) { 3322 unpaired_dsentries++; 3323 #if ST_DEBUG_LEVEL > 2 3324 printf("allocate_pair_metadata_dsentries_from_raw_copy: found unpaired "); MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR); _magic_printf("\n"); 3325 #endif 3326 } 3327 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry); 3328 dsentry = dsentry->next; 3329 } 3330 3331 #if ST_DEBUG_LEVEL > 0 3332 printf("total remote dsentries: %d (%d unpaired)\n", remote_dsentries, unpaired_dsentries); 3333 #endif 3334 3335 return OK; 3336 } 3337 3338 #else 3339 3340 PRIVATE int allocate_pair_metadata_dsentries(st_init_info_t *info, 3341 struct _magic_vars_t *cached_magic_vars, st_counterparts_t *counterparts) 3342 { 3343 struct _magic_dsentry *dsentry = cached_magic_vars->first_dsentry, *local_dsentry; 3344 int remote_dsentries = 0; 3345 #ifndef __MINIX 3346 int *local_sentry_paired_by_id = st_buff_allocate(info, (_magic_sentries_next_id + 1) * sizeof(int)); 3347 #endif 3348 3349 #if ST_DEBUG_LEVEL > 3 3350 EXEC_WITH_MAGIC_VARS( 3351 magic_print_dsentries(); 3352 , &st_cached_magic_vars 3353 ); 3354 magic_print_dsentries(); 3355 #endif 3356 3357 #ifdef __MINIX 3358 /* 3359 * Since on MINIX the mmaped regions are inherited in the new process, 3360 * we must first deallocate them. This is not the case on Linux. 3361 */ 3362 while (dsentry != NULL) { 3363 int res = 0; 3364 struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 3365 int size = sentry->type->size; 3366 /* For mmap first unmap the old region that is already mapped into this new instance */ 3367 if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND) 3368 && MAGIC_STATE_REGION(sentry) == MAGIC_STATE_MAP 3369 && !USE_PRE_ALLOCATED_BUFFER(info) 3370 ) 3371 { 3372 /* 3373 * The 'ext' field in the dsentry is used here to record 3374 * the padding for ASR. 3375 */ 3376 size_t padding = (size_t) dsentry->ext; 3377 /* 3378 * call munmap(). ptr and size have to be altered, 3379 * in order to free the preceding page, containing the dsentry struct, too. 3380 */ 3381 MAGIC_MEM_WRAPPER_BLOCK( 3382 res = munmap((char *)sentry->address - magic_get_sys_pagesize(), size + magic_get_sys_pagesize() + padding); 3383 ); 3384 if (res != 0) { 3385 printf("ERROR, munmap returned NULL.\n"); 3386 return EGENERIC; 3387 } 3388 } 3389 dsentry = dsentry->next; 3390 } 3391 #endif 3392 3393 /* Permute dsentries in case of ASR. */ 3394 if (info->flags & ST_LU_ASR) { 3395 magic_asr_permute_dsentries(&cached_magic_vars->first_dsentry); 3396 } 3397 3398 dsentry = cached_magic_vars->first_dsentry; 3399 while (dsentry != NULL) { 3400 struct _magic_sentry *local_sentry, *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 3401 int is_alloc_dsentry = MAGIC_SENTRY_IS_ALLOC(sentry); 3402 int res = 0; 3403 struct _magic_dsindex *local_dsindex; 3404 3405 remote_dsentries++; 3406 3407 #ifdef __MINIX 3408 /* Cannot deal with dead dsentries. */ 3409 assert(dsentry->magic_state == MAGIC_DSENTRY_MSTATE_ALIVE); 3410 #else 3411 /* 3412 * If there are dead dsentries, we simply skip them. 3413 */ 3414 if (dsentry->magic_state != MAGIC_DSENTRY_MSTATE_ALIVE) { 3415 dsentry = dsentry->next; 3416 continue; 3417 } 3418 #endif 3419 3420 /* Initialize counterpart to NULL. */ 3421 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, NULL); 3422 3423 /* Handle non-alloc dsentries first. */ 3424 if (!is_alloc_dsentry) { 3425 local_sentry = magic_sentry_lookup_by_name(dsentry->parent_name, 3426 sentry->name, dsentry->site_id, NULL); 3427 if (local_sentry) { 3428 assert(!MAGIC_SENTRY_IS_ALLOC(local_sentry)); 3429 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry); 3430 } 3431 3432 dsentry = dsentry->next; 3433 continue; 3434 } 3435 3436 /* Out-of-band alloc dsentries next. */ 3437 if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_OUT_OF_BAND)) { 3438 struct _magic_type *type; 3439 /* We can only handle obdsentries with the magic void type, transferred as-is. */ 3440 if (sentry->type != &dsentry->type) { 3441 /* Not an array type */ 3442 type = sentry->type; 3443 } else { 3444 /* This is an array type, use its contained type instead. */ 3445 type = sentry->type->contained_types[0]; 3446 } 3447 /* We now have the cached version of the type. Compare it to magic void type */ 3448 if (!magic_type_compatible(type, MAGIC_VOID_TYPE, MAGIC_TYPE_COMPARE_ALL)) { 3449 printf("Can't handle obdsentry with non-void type\n"); 3450 return EGENERIC; 3451 } 3452 #ifdef __MINIX 3453 /* On MINIX we need to recreate all the obdsentries. */ 3454 struct _magic_obdsentry *obdsentry; 3455 int size = sentry->type->size; 3456 obdsentry = magic_create_obdsentry(sentry->address, 3457 MAGIC_VOID_TYPE, size, MAGIC_STATE_REGION(sentry), sentry->name, dsentry->parent_name); 3458 if (obdsentry == NULL) { 3459 printf("ERROR, magic_create_obdsentry returned NULL.\n"); 3460 return EGENERIC; 3461 } 3462 local_dsentry = MAGIC_OBDSENTRY_TO_DSENTRY(obdsentry); 3463 #else 3464 /* On Linux we only need to pair them. */ 3465 local_sentry = magic_sentry_lookup_by_name( 3466 MAGIC_SENTRY_PARENT(sentry), sentry->name, 3467 MAGIC_SENTRY_SITE_ID(sentry), NULL); 3468 if (local_sentry == NULL) { 3469 printf("Unable to pair obdsentry.\n"); 3470 return EGENERIC; 3471 } 3472 local_dsentry = MAGIC_DSENTRY_FROM_SENTRY(local_sentry); 3473 #endif 3474 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, MAGIC_DSENTRY_TO_SENTRY(local_dsentry)); 3475 dsentry = dsentry->next; 3476 continue; 3477 } 3478 3479 /* Handle regular alloc dsentries last. */ 3480 #ifndef __MINIX 3481 /* 3482 * For Linux, first pair INIT time remote 3483 * dsentries with local dsentries. 3484 */ 3485 3486 if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_INIT)) { 3487 local_sentry = NULL; 3488 3489 if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_IMMUTABLE)) { 3490 /* 3491 * Immutable init time dsentries should have already been 3492 * preallocated, so just pair them by address. 3493 */ 3494 local_sentry = magic_sentry_lookup_by_addr(sentry->address, NULL); 3495 } else { 3496 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH 3497 struct _magic_sentry_list *local_sentry_list; 3498 local_sentry_list = magic_sentry_list_lookup_by_name_hash( 3499 dsentry->parent_name, sentry->name, dsentry->site_id, NULL); 3500 3501 while (local_sentry_list) { 3502 if (!local_sentry_paired_by_id[local_sentry_list->sentry->id]) { 3503 local_sentry = local_sentry_list->sentry; 3504 break; 3505 } 3506 local_sentry_list = local_sentry_list->next; 3507 } 3508 3509 #else 3510 do { 3511 struct _magic_dsentry *prev_dsentry, *tmp_dsentry; 3512 struct _magic_sentry *tmp_sentry; 3513 MAGIC_DSENTRY_LOCK(); 3514 MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, 3515 tmp_dsentry, tmp_sentry, 3516 if (!strcmp(tmp_sentry->name, sentry->name)) { 3517 if (!dsentry->parent_name || 3518 !strcmp(MAGIC_SENTRY_PARENT(tmp_sentry), dsentry->parent_name)) { 3519 if (dsentry->site_id == MAGIC_DSENTRY_SITE_ID_NULL || 3520 tmp_dsentry->site_id == dsentry->site_id) { 3521 if (!local_sentry_paired_by_id[tmp_sentry->id]) { 3522 local_sentry = tmp_sentry; 3523 break; 3524 } 3525 } 3526 } 3527 } 3528 ); 3529 MAGIC_DSENTRY_UNLOCK(); 3530 } while (0); 3531 #endif 3532 } 3533 if (local_sentry) { 3534 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry); 3535 local_sentry_paired_by_id[local_sentry->id] = 1; 3536 dsentry = dsentry->next; 3537 continue; 3538 } 3539 } 3540 #endif 3541 3542 /* 3543 * Just recreate all the other dsentries. Immutable objects will 3544 * have already been inherited and allocate_local_dsentry() will 3545 * not reallocate them, but instead it will just create a new 3546 * local dsentry in the right place. 3547 */ 3548 local_dsindex = magic_dsindex_lookup_by_name(dsentry->parent_name, sentry->name); 3549 if (local_dsindex || MAGIC_SENTRY_IS_LIB_ALLOC(sentry)) { 3550 3551 /* Allocate a new local dsentry and pair it with the remote. */ 3552 res = allocate_local_dsentry(info, local_dsindex, 0, 0, NULL, &local_dsentry, dsentry, NULL); 3553 if (res != ENOSYS) { 3554 if (res != OK) { 3555 return res; 3556 } 3557 assert(local_dsentry); 3558 ST_SET_CACHED_COUNTERPART(sentry, sentries, sentries, MAGIC_DSENTRY_TO_SENTRY(local_dsentry)); 3559 } 3560 } 3561 dsentry = dsentry->next; 3562 } 3563 3564 #if ST_DEBUG_LEVEL > 0 3565 printf("total remote dsentries: %d\n", remote_dsentries); 3566 #endif 3567 3568 return OK; 3569 } 3570 3571 PRIVATE int deallocate_nonxferred_dsentries(struct _magic_dsentry *first_dsentry, st_counterparts_t *counterparts) 3572 { 3573 struct _magic_dsentry *dsentry = first_dsentry; 3574 struct _magic_sentry *local_sentry; 3575 3576 while (dsentry != NULL) { 3577 struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 3578 int is_paired_dsentry = ST_HAS_CACHED_COUNTERPART(sentry, sentries); 3579 int is_alloc_dsentry = MAGIC_SENTRY_IS_ALLOC(sentry); 3580 ST_GET_CACHED_COUNTERPART(sentry, sentries, sentries, local_sentry); 3581 3582 if (MAGIC_STATE_EXTF_GET(sentry, ST_TRANSFER_DONE) || !is_alloc_dsentry) { 3583 dsentry = dsentry->next; 3584 continue; 3585 } 3586 3587 /* Report non-transferred alloc dsentries when requested. */ 3588 if (is_paired_dsentry && (st_policies & ST_REPORT_NONXFERRED_ALLOCS)) { 3589 printf("deallocate_nonxferred_dsentries: Non-transferred dsentry found: "); 3590 MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR); 3591 printf("\n"); 3592 } 3593 if (!is_paired_dsentry && (st_policies & ST_REPORT_NONXFERRED_UNPAIRED_ALLOCS)) { 3594 printf("deallocate_nonxferred_dsentries: Non-transferred unpaired dsentry found: "); 3595 MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR); 3596 printf("\n"); 3597 } 3598 3599 if (!is_paired_dsentry) { 3600 dsentry = dsentry->next; 3601 continue; 3602 } 3603 assert(local_sentry); 3604 if (MAGIC_SENTRY_IS_ALLOC(local_sentry)) { 3605 deallocate_local_dsentry(MAGIC_DSENTRY_FROM_SENTRY(local_sentry)); 3606 } 3607 dsentry = dsentry->next; 3608 } 3609 3610 return OK; 3611 } 3612 #endif 3613 3614 PRIVATE void deallocate_local_dsentry(struct _magic_dsentry *local_dsentry) 3615 { 3616 int r, dsentry_type; 3617 struct _magic_sentry *local_sentry = MAGIC_DSENTRY_TO_SENTRY(local_dsentry); 3618 3619 assert(MAGIC_SENTRY_IS_ALLOC(local_sentry)); 3620 dsentry_type = MAGIC_STATE_FLAG(local_sentry, MAGIC_STATE_OUT_OF_BAND) ? MAGIC_STATE_OUT_OF_BAND : MAGIC_STATE_REGION(local_sentry); 3621 /* A MAP_SHARED region will have both MAGIC_STATE_MAP and MAGIC_STATE_SHM. */ 3622 if (dsentry_type == (MAGIC_STATE_MAP | MAGIC_STATE_SHM)) 3623 dsentry_type = MAGIC_STATE_MAP; 3624 3625 MAGIC_MEM_WRAPPER_BEGIN(); 3626 switch (dsentry_type) { 3627 case MAGIC_STATE_HEAP: 3628 /* free */ 3629 magic_free(local_sentry->address); 3630 break; 3631 3632 case MAGIC_STATE_MAP: 3633 /* munmap */ 3634 r = magic_munmap(local_sentry->address, local_sentry->type->size); 3635 if (r != 0) { 3636 printf("Warning: magic_munmap failed for "); 3637 MAGIC_DSENTRY_PRINT(local_dsentry, 0); 3638 printf("\n"); 3639 } 3640 break; 3641 3642 #ifndef __MINIX 3643 case MAGIC_STATE_SHM: 3644 /* shmdt */ 3645 r = magic_shmdt(local_sentry->address); 3646 if (r != 0) { 3647 printf("Warning: magic_shmdt failed for "); 3648 MAGIC_DSENTRY_PRINT(local_dsentry, 0); 3649 printf("\n"); 3650 } 3651 break; 3652 #endif 3653 3654 case MAGIC_STATE_OUT_OF_BAND: 3655 /* out-of-band dsentry. */ 3656 r = magic_destroy_obdsentry_by_addr(local_sentry->address); 3657 if (r != 0) { 3658 printf("Warning: magic_destroy_obdsentry_by_addr failed for "); 3659 MAGIC_DSENTRY_PRINT(local_dsentry, 0); 3660 printf("\n"); 3661 } 3662 break; 3663 3664 default: 3665 st_cbs_os.panic("ERROR. UNSUPPORTED DSENTRY TYPE: %d\n", dsentry_type); 3666 } 3667 MAGIC_MEM_WRAPPER_END(); 3668 } 3669 3670 PRIVATE int allocate_local_dsentry(st_init_info_t *info, struct _magic_dsindex *local_dsindex, int num_elements, int is_type_mismatch, const union __alloc_flags *p_alloc_flags, struct _magic_dsentry** local_dsentry_ptr, struct _magic_dsentry *cached_dsentry, void *ptr) 3671 { 3672 struct _magic_dsentry *local_dsentry = NULL; 3673 struct _magic_sentry *cached_sentry = NULL; 3674 const char *name, *parent_name; 3675 struct _magic_type *type; 3676 int region; 3677 size_t size; 3678 union __alloc_flags alloc_flags; 3679 3680 /* Either a dsindex or a dsentry needs to be set. */ 3681 assert(local_dsindex || cached_dsentry); 3682 3683 if (cached_dsentry) 3684 cached_sentry = MAGIC_DSENTRY_TO_SENTRY(cached_dsentry); 3685 3686 /* name, parent_name: local_dsindex || cached_dsentry. */ 3687 if (local_dsindex) { 3688 assert(MAGIC_DSINDEX_IS_ALLOC(local_dsindex)); 3689 name = local_dsindex->name; 3690 parent_name = local_dsindex->parent_name; 3691 } else { 3692 assert(MAGIC_SENTRY_IS_ALLOC(cached_sentry)); 3693 /* 3694 * The external allocation parent_name needs to be readjusted. 3695 * The external allocation name is adjusted after the new dsentry 3696 * is created. 3697 */ 3698 name = cached_sentry->name; 3699 if (!strcmp(cached_dsentry->parent_name, MAGIC_ALLOC_EXT_PARENT_NAME)) { 3700 parent_name = MAGIC_ALLOC_EXT_PARENT_NAME; 3701 } else { 3702 int found_parent_name = 0; 3703 struct _magic_sodesc *sodesc; 3704 struct _magic_dsodesc *dsodesc; 3705 MAGIC_DSODESC_LOCK(); 3706 MAGIC_SODESC_ITER(_magic_first_sodesc, sodesc, 3707 if (!strcmp(cached_dsentry->parent_name, sodesc->lib.name)) { 3708 parent_name = (const char *)sodesc->lib.name; 3709 found_parent_name = 1; 3710 break; 3711 } 3712 ); 3713 if (!found_parent_name) { 3714 MAGIC_DSODESC_ITER(_magic_first_dsodesc, dsodesc, 3715 if (!strcmp(cached_dsentry->parent_name, dsodesc->lib.name)) { 3716 parent_name = (const char *)dsodesc->lib.name; 3717 found_parent_name = 1; 3718 break; 3719 } 3720 ); 3721 } 3722 MAGIC_DSODESC_UNLOCK(); 3723 assert(found_parent_name && "Invalid parent name for cached dsentry!"); 3724 } 3725 } 3726 3727 /* num_elements: args || cached_sentry. */ 3728 if (num_elements <= 0 && cached_sentry) { 3729 num_elements = cached_sentry->type->type_id == MAGIC_TYPE_ARRAY ? 3730 cached_sentry->type->num_child_types : 1; 3731 } 3732 assert(num_elements > 0); 3733 3734 /* alloc_flags: args || cached_dsentry. */ 3735 if (!p_alloc_flags) { 3736 if (cached_dsentry && MAGIC_SENTRY_IS_ALLOC(cached_sentry)) { 3737 alloc_flags = cached_dsentry->alloc_flags; 3738 } 3739 } else { 3740 alloc_flags = *p_alloc_flags; 3741 } 3742 3743 /* is_type_mismatch: args || cached_dsentry. */ 3744 if (!is_type_mismatch && cached_dsentry) 3745 is_type_mismatch = MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_TYPE_SIZE_MISMATCH); 3746 3747 /* 3748 * Use old address for immutable objects. 3749 */ 3750 /* ptr: args || cached_sentry. */ 3751 if (!ptr && cached_sentry && 3752 MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_IMMUTABLE)) 3753 ptr = cached_sentry->address; 3754 3755 /* region: local_dsindex || cached_sentry. */ 3756 if (local_dsindex) 3757 region = MAGIC_STATE_REGION(local_dsindex); 3758 else 3759 region = MAGIC_STATE_REGION(cached_sentry); 3760 3761 /* Check if the region is ambigous. This shouldn't happen. */ 3762 assert(!((region & (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) == 3763 (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) && 3764 "MAGIC_STATE_HEAP | MAGIC_STATE_MAP detected!"); 3765 #if 0 3766 if ((region & (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) == 3767 (MAGIC_STATE_HEAP | MAGIC_STATE_MAP)) { 3768 /* Check call flags to determine what to do in the ambiguous cases. */ 3769 region = (alloc_flags.mmap_flags && alloc_flags.mmap_prot) ? 3770 MAGIC_STATE_MAP : MAGIC_STATE_HEAP; 3771 } 3772 #endif 3773 3774 /* type: local_dsindex || cached_sentry. */ 3775 if (local_dsindex) { 3776 type = local_dsindex->type; 3777 3778 if (num_elements > 1 && MAGIC_TYPE_FLAG(local_dsindex->type, MAGIC_TYPE_VARSIZE)) { 3779 size = magic_type_alloc_get_varsized_array_size(local_dsindex->type, num_elements); 3780 assert(size > 0); 3781 } else { 3782 if (is_type_mismatch) { 3783 type = MAGIC_VOID_TYPE; 3784 printf("WARNING: Type size mismatch dsentry detected! Ignoring dsindex type and reverting to MAGIC_TYPE_VOID.\n"); 3785 printf("name=%s, parent_name=%s\n", local_dsindex->name, local_dsindex->parent_name); 3786 } 3787 size = num_elements * type->size; 3788 } 3789 } else { 3790 /* 3791 * The type will need adjusting later. 3792 */ 3793 type = cached_sentry->type; 3794 size = type->size; 3795 } 3796 3797 *local_dsentry_ptr = NULL; 3798 3799 if (region & MAGIC_STATE_HEAP) { 3800 /* malloc */ 3801 ptr = magic_malloc_positioned(type, name, parent_name, size, (ptr == NULL ? NULL : MAGIC_PTR_FROM_DATA(ptr))); 3802 if (ptr == NULL) { 3803 printf("ERROR, magic_malloc_positioned returned NULL.\n"); 3804 return ENOMEM; 3805 } 3806 memset(ptr, 0, size); 3807 local_dsentry = MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr)); 3808 } 3809 else if (region & MAGIC_STATE_MAP) { 3810 /* mmap */ 3811 if (!alloc_flags.mmap_flags || !alloc_flags.mmap_prot) { 3812 /* We need call_flags to perform mmap. */ 3813 return ENOSYS; 3814 } 3815 ptr = persistent_mmap(type, name, parent_name, info, NULL, size, 3816 alloc_flags.mmap_prot, alloc_flags.mmap_flags, -1, 0, ptr); 3817 if (ptr == NULL) { 3818 printf("ERROR, persistent_mmap returned NULL.\n"); 3819 return ENOMEM; 3820 } 3821 if (!(alloc_flags.mmap_flags & MAP_SHARED)) 3822 memset(ptr, 0, size); 3823 local_dsentry = MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr)); 3824 } 3825 #ifndef __MINIX 3826 else if (region & MAGIC_STATE_SHM) { 3827 /* shmat */ 3828 if (!alloc_flags.shmat_flags || !alloc_flags.shmat_shmid) { 3829 /* We need call_flags to perform shmat. */ 3830 return ENOSYS; 3831 } 3832 ptr = magic_shmat(type, name, parent_name, alloc_flags.shmat_shmid, 3833 ptr, alloc_flags.shmat_flags); 3834 if (ptr == NULL) { 3835 printf("ERROR, magic_shmat returned NULL.\n"); 3836 return ENOMEM; 3837 } 3838 local_dsentry = MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(ptr)); 3839 } 3840 #endif 3841 else { 3842 if (local_dsindex) { 3843 printf("ERROR. UNSUPPORTED DSINDEX TYPE: "); 3844 MAGIC_DSINDEX_PRINT(local_dsindex, MAGIC_EXPAND_TYPE_STR); 3845 } else { 3846 printf("ERROR. UNSUPPORTED DSENTRY: "); 3847 MAGIC_DSENTRY_PRINT(cached_dsentry, MAGIC_EXPAND_TYPE_STR); 3848 } 3849 printf("\n"); 3850 return EINVAL; 3851 } 3852 3853 if (!local_dsindex) { 3854 /* 3855 * This was an externally allocated type and, as such, needs adjusting. 3856 */ 3857 assert(cached_sentry->type == &cached_dsentry->type); 3858 local_dsentry->type = cached_dsentry->type; 3859 if (cached_dsentry->type_array[0]->type_id == MAGIC_TYPE_POINTER) { 3860 ST_GET_CACHED_COUNTERPART(cached_dsentry->type_array[0], types, ptr_types, local_dsentry->type_array[0]); 3861 } else { 3862 ST_GET_CACHED_COUNTERPART(cached_dsentry->type_array[0], types, types, local_dsentry->type_array[0]); 3863 } 3864 local_dsentry->sentry.type = &local_dsentry->type; 3865 local_dsentry->sentry.type->contained_types = local_dsentry->type_array; 3866 } 3867 3868 assert(local_dsentry); 3869 assert(local_dsentry->parent_name && strcmp(local_dsentry->parent_name, "")); 3870 assert(local_dsentry->sentry.name && strcmp(local_dsentry->sentry.name, "")); 3871 assert(magic_check_dsentry(local_dsentry, 0)); 3872 *local_dsentry_ptr = local_dsentry; 3873 3874 if (is_type_mismatch) 3875 local_dsentry->sentry.flags |= MAGIC_STATE_TYPE_SIZE_MISMATCH; 3876 3877 /* 3878 * Dsentries allocated by shared libraries have the names stored in dsentry 3879 * buffers (for now). 3880 * Readjust the local_sentry to do this as well, since after state transfer 3881 * cleanup the existing names will become invalid. 3882 */ 3883 if (!local_dsindex && MAGIC_SENTRY_IS_LIB_ALLOC(cached_sentry)) { 3884 strncpy(local_dsentry->name_ext_buff, local_dsentry->sentry.name, 3885 MAGIC_DSENTRY_EXT_NAME_BUFF_SIZE); 3886 local_dsentry->sentry.name = local_dsentry->name_ext_buff; 3887 } 3888 3889 return OK; 3890 } 3891 3892 PRIVATE int check_unpaired_sentry(st_init_info_t *info, 3893 struct _magic_sentry* cached_sentry) 3894 { 3895 int sentry_needs_transfer = MAGIC_STATE_EXTF_GET(cached_sentry, ST_NEEDS_TRANSFER | ST_TRANSFER_DONE) == ST_NEEDS_TRANSFER; 3896 int report; 3897 3898 if (!sentry_needs_transfer && !MAGIC_SENTRY_IS_STRING(cached_sentry)) { 3899 return OK; 3900 } 3901 3902 if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC)) { 3903 report = st_policies & ST_REPORT_UNPAIRED_DSENTRIES; 3904 } 3905 else if(MAGIC_SENTRY_IS_STRING(cached_sentry)) { 3906 report = st_policies & ST_REPORT_UNPAIRED_STRINGS; 3907 } 3908 else { 3909 report = st_policies & ST_REPORT_UNPAIRED_SENTRIES; 3910 } 3911 if (report) { 3912 printf("check_unpaired_sentry: Unpaired sentry found: "); 3913 ST_SENTRY_PRINT(cached_sentry,MAGIC_EXPAND_TYPE_STR); 3914 printf("\n"); 3915 } 3916 3917 return OK; 3918 } 3919 3920 PUBLIC struct _magic_sentry* st_cached_to_remote_sentry(st_init_info_t *info, struct _magic_sentry *cached_sentry) 3921 { 3922 struct _magic_sentry *remote_sentry; 3923 void *local_data_addr; 3924 ST_CHECK_INIT(); 3925 3926 /* Copy metadata into metadata buffer. */ 3927 if (MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_DYNAMIC)) { 3928 magic_copy_dsentry(MAGIC_DSENTRY_FROM_SENTRY(cached_sentry), st_dsentry_buff); 3929 remote_sentry = MAGIC_DSENTRY_TO_SENTRY(st_dsentry_buff); 3930 } 3931 else { 3932 memcpy(&st_dsentry_buff->sentry, cached_sentry, sizeof(struct _magic_sentry)); 3933 remote_sentry = &st_dsentry_buff->sentry; 3934 } 3935 3936 /* Have the remote sentry point to local data. */ 3937 local_data_addr = NULL; 3938 /* See if we have the data locally already first. */ 3939 ST_GET_CACHED_COUNTERPART(cached_sentry, sentries, sentries_data, local_data_addr); 3940 if (!local_data_addr) { 3941 /* Copy remote data into local data buffer. */ 3942 if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) remote_sentry->address 3943 , remote_sentry->type->size, (uint32_t) st_data_buff)) 3944 { 3945 printf("ERROR transferring sentry data to local buffer.\n"); 3946 return NULL; 3947 } 3948 local_data_addr = st_data_buff; 3949 } 3950 remote_sentry->address = local_data_addr; 3951 3952 return remote_sentry; 3953 } 3954 3955 PRIVATE int transfer_data_sentry(st_init_info_t *info, 3956 struct _magic_sentry* cached_sentry) 3957 { 3958 3959 int r; 3960 int st_cb_flags = ST_CB_DEFAULT_FLAGS; 3961 struct _magic_sentry *local_sentry, *remote_sentry; 3962 int flags = ST_SEL_ANALYZE_FLAGS; 3963 struct st_cb_info cb_info_buff; 3964 struct st_cb_info *cb_info = &cb_info_buff; 3965 static _magic_selement_t magic_local_selements[MAGIC_MAX_RECURSIVE_TYPES+1]; 3966 static int magic_flags_by_depth[MAGIC_MAX_RECURSIVE_TYPES+1]; 3967 3968 /* Skip extern weak symbols. */ 3969 if (!cached_sentry->address) { 3970 assert(MAGIC_STATE_FLAG(cached_sentry, MAGIC_STATE_EXTERNAL)); 3971 st_set_transfer_status(ST_TRANSFER_DONE, ST_OP_ADD, cached_sentry, NULL); 3972 return OK; 3973 } 3974 3975 /* Determine local and remote sentries from the cached version. */ 3976 local_sentry = NULL; 3977 st_lookup_sentry_pair(&cached_sentry, &local_sentry); 3978 assert(local_sentry && "Unexpected unpaired sentry!"); 3979 remote_sentry = st_cached_to_remote_sentry(info, cached_sentry); 3980 if (!remote_sentry) { 3981 printf("No remote sentry found for cached sentry: "); 3982 MAGIC_SENTRY_PRINT(cached_sentry, 0); 3983 printf("\n"); 3984 return EFAULT; 3985 } 3986 3987 cb_info->local_selements = magic_local_selements; 3988 cb_info->local_selement = magic_selement_from_sentry(local_sentry, &magic_local_selements[0]); 3989 cb_info->walk_flags = MAGIC_TYPE_WALK_DEFAULT_FLAGS; 3990 cb_info->st_cb_flags = st_cb_flags; 3991 cb_info->init_info = info; 3992 cb_info->st_cb_saved_flags = magic_flags_by_depth; 3993 magic_flags_by_depth[0] = st_cb_flags; 3994 3995 EXEC_WITH_MAGIC_VARS( 3996 r = magic_sentry_analyze(remote_sentry , flags, transfer_data_selement, cb_info, NULL); 3997 , &st_cached_magic_vars 3998 ); 3999 if (r < 0) { 4000 return r; 4001 } 4002 4003 st_set_transfer_status(ST_TRANSFER_DONE, ST_OP_ADD, cached_sentry, NULL); 4004 return OK; 4005 } 4006 4007 PRIVATE int transfer_data_selement(_magic_selement_t *selement, _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, void *cb_args) 4008 { 4009 4010 int r = ST_CB_NOT_PROCESSED; 4011 int depth, cb_flags; 4012 struct st_cb_info *cb_info = (struct st_cb_info *) cb_args; 4013 _magic_selement_t *local_selement, *local_parent_selement; 4014 st_cb_selement_transfer_t *cb; 4015 4016 register_typenames_and_callbacks(); 4017 4018 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) { 4019 depth = selement->depth; 4020 local_selement = &cb_info->local_selements[depth]; 4021 if (depth > 0) { 4022 local_parent_selement = &cb_info->local_selements[depth-1]; 4023 local_selement->sentry = local_parent_selement->sentry; 4024 local_selement->parent_type = local_parent_selement->type; 4025 local_selement->parent_address = local_parent_selement->address; 4026 cb_info->st_cb_flags = cb_info->st_cb_saved_flags[depth-1]; 4027 } 4028 /* Map the cached and the local selement. */ 4029 st_map_selement(selement, local_selement, cb_info, FALSE); 4030 if (local_selement->type == NULL) { 4031 /* Unpaired selement. */ 4032 if (st_policies & ST_REPORT_UNPAIRED_SELEMENTS) { 4033 printf("transfer_data_selement: Unpaired selement found: "); 4034 MAGIC_SELEMENT_PRINT(selement, MAGIC_EXPAND_TYPE_STR); 4035 printf("\n"); 4036 } 4037 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 4038 } 4039 cb_info->local_selement = local_selement; 4040 4041 /* See if identity transfer has been requested. */ 4042 if (cb_info->st_cb_flags & ST_CB_FORCE_IXFER) { 4043 r = transfer_identity_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 4044 assert(r != ST_CB_NOT_PROCESSED); 4045 cb_info->st_cb_saved_flags[depth] = cb_info->st_cb_flags; 4046 return r; 4047 } 4048 } 4049 4050 cb_flags = ST_CB_TYPE_SELEMENT; 4051 if (ST_TYPE_NAME_KEY(selement->type) != NULL) { 4052 cb_flags |= ST_CB_TYPE_TYPENAME; 4053 } 4054 if (selement->num == 1) { 4055 cb_flags |= ST_CB_TYPE_SENTRY; 4056 } 4057 4058 cb = st_cbs.st_cb_selement_transfer[cb_flags]; 4059 while (TRUE) { 4060 4061 if (*cb != NULL) { 4062 r = (*cb)(selement, sel_analyzed, sel_stats, cb_info); 4063 } else { 4064 r = default_transfer_selement_sel_cb(selement, sel_analyzed, sel_stats, cb_info); 4065 assert(r != ST_CB_NOT_PROCESSED 4066 && "Default selement callback should always process the selement."); 4067 } 4068 4069 if (r != ST_CB_NOT_PROCESSED) { 4070 assert((r<0 || MAGIC_SENTRY_ANALYZE_IS_VALID_RET(r)) && "Invalid callback return code!"); 4071 if (!ST_CB_FLAG(ST_CB_CHECK_ONLY)) { 4072 cb_info->st_cb_saved_flags[depth] = cb_info->st_cb_flags; 4073 } 4074 return r; 4075 } 4076 4077 cb++; 4078 } 4079 4080 /* Not reachable. */ 4081 return EINTR; 4082 } 4083 4084 PRIVATE int lookup_trg_info(_magic_selement_t *selement, 4085 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, struct st_cb_info *cb_info, 4086 _magic_selement_t *cached_trg_selement, _magic_selement_t *local_trg_selement) 4087 { 4088 _magic_selement_t *local_selement, *trg_selement; 4089 struct _magic_sentry *cached_trg_sentry, *local_trg_sentry = NULL; 4090 struct _magic_function *cached_trg_function, *local_trg_function = NULL; 4091 _magic_sel_analyzed_t local_sel_analyzed; 4092 _magic_sel_stats_t local_sel_stats; 4093 void *local_trg_root_address; 4094 struct _magic_type *cached_trg_root_type, *local_trg_root_type; 4095 int first_legal_trg_type, is_same_type, is_same_trg_type, local_trg_has_addr_not_taken; 4096 4097 local_selement = cb_info->local_selement; 4098 first_legal_trg_type = sel_analyzed->u.ptr.first_legal_trg_type; 4099 assert(first_legal_trg_type >= 0); 4100 trg_selement = &sel_analyzed->u.ptr.trg_selements[first_legal_trg_type]; 4101 local_trg_root_type = NULL; 4102 4103 /* Lookup cached and local targets. */ 4104 if (MAGIC_SEL_ANALYZED_PTR_HAS_TRG_SENTRY(sel_analyzed)) { 4105 cached_trg_sentry = trg_selement->sentry; 4106 local_trg_sentry = NULL; 4107 st_lookup_sentry_pair(&cached_trg_sentry, &local_trg_sentry); 4108 *cached_trg_selement = *trg_selement; 4109 cached_trg_root_type = cached_trg_sentry->type; 4110 local_trg_has_addr_not_taken = local_trg_sentry && MAGIC_STATE_FLAG(local_trg_sentry, MAGIC_STATE_ADDR_NOT_TAKEN); 4111 local_trg_selement->sentry = local_trg_sentry; 4112 if (local_trg_sentry) { 4113 local_trg_root_address = local_trg_sentry->address; 4114 local_trg_root_type = local_trg_sentry->type; 4115 } 4116 } 4117 else if(MAGIC_SEL_ANALYZED_PTR_HAS_TRG_FUNCTION(sel_analyzed)) { 4118 cached_trg_function = MAGIC_DFUNCTION_TO_FUNCTION(&sel_analyzed->u.ptr.trg.dfunction); 4119 local_trg_function = NULL; 4120 st_lookup_function_pair(&cached_trg_function, &local_trg_function); 4121 *cached_trg_selement = *trg_selement; 4122 cached_trg_root_type = cached_trg_function->type; 4123 local_trg_has_addr_not_taken = local_trg_function && MAGIC_STATE_FLAG(local_trg_function, MAGIC_STATE_ADDR_NOT_TAKEN); 4124 local_trg_selement->sentry = NULL; 4125 if (local_trg_function) { 4126 local_trg_root_address = local_trg_function->address; 4127 local_trg_root_type = local_trg_function->type; 4128 } 4129 } 4130 4131 /* Check unpaired targets. */ 4132 if (!local_trg_root_type) { 4133 local_trg_selement->type = NULL; 4134 return OK; 4135 } 4136 4137 /* Check address not taken violations. */ 4138 if (local_trg_has_addr_not_taken) { 4139 ST_CB_PRINT(ST_CB_ERR, "uncaught ptr with paired target whose address is not taken", selement, sel_analyzed, sel_stats, cb_info); 4140 return EFAULT; 4141 } 4142 4143 /* Check types and return immediately in case of perfect pointer match. */ 4144 is_same_type = selement->type == local_selement->type || ST_PTR_TYPE_IS_CACHED_COUNTERPART(selement->type, local_selement->type); 4145 is_same_trg_type = ST_TYPE_IS_CACHED_COUNTERPART(cached_trg_root_type, local_trg_root_type); 4146 if (is_same_type && is_same_trg_type) { 4147 local_trg_selement->type = cached_trg_selement->type; 4148 local_trg_selement->address = (char*) local_trg_root_address + sel_analyzed->u.ptr.trg_offset; 4149 return OK; 4150 } 4151 #if CHECK_ASR && !FORCE_SOME_UNPAIRED_TYPES 4152 if (cb_info->init_info->flags & ST_LU_ASR) { 4153 st_cbs_os.panic("ASR should never get here!"); 4154 } 4155 #endif 4156 4157 /* Map sel_analyzed to its local counterpart. */ 4158 if (is_same_trg_type) { 4159 local_sel_analyzed = *sel_analyzed; 4160 local_sel_analyzed.u.ptr.trg_selements[0].address = (char*) local_trg_root_address + sel_analyzed->u.ptr.trg_offset; 4161 } 4162 else { 4163 st_map_sel_analyzed_from_target(sel_analyzed, &local_sel_analyzed, local_trg_sentry, local_trg_function, cb_info); 4164 if (local_sel_analyzed.u.ptr.num_trg_types == 0) { 4165 /* Unpaired target selements. */ 4166 local_trg_selement->type = NULL; 4167 return OK; 4168 } 4169 } 4170 4171 /* Check violations on the local target. */ 4172 memset(&local_sel_stats, 0, sizeof(local_sel_stats)); 4173 magic_selement_analyze_ptr_type_invs(local_selement, &local_sel_analyzed, &local_sel_stats); 4174 if (MAGIC_SEL_STATS_HAS_VIOLATIONS(&local_sel_stats)) { 4175 /* Local pointer with violations found */ 4176 ST_CB_PRINT(ST_CB_ERR, "uncaught ptr with after-transfer violations", selement, sel_analyzed, sel_stats, cb_info); 4177 ST_CB_PRINT(ST_CB_ERR, "transferred ptr with violations", local_selement, &local_sel_analyzed, &local_sel_stats, cb_info); 4178 return EFAULT; 4179 } 4180 4181 /* All the targets mapped correctly. */ 4182 local_trg_selement->type = local_sel_analyzed.u.ptr.trg_selements[0].type; 4183 local_trg_selement->address = local_sel_analyzed.u.ptr.trg_selements[0].address; 4184 return OK; 4185 } 4186 4187 /* transfer helper functions */ 4188 4189 PRIVATE int md_transfer_str(st_init_info_t *info, char **str_pt) 4190 { 4191 char buff[ST_STR_BUFF_SIZE + 2]; 4192 4193 if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) *str_pt, ST_STR_BUFF_SIZE + 1, (uint32_t) buff)) { 4194 st_cbs_os.panic("md_transfer_str(): ERROR transferring string.\n"); 4195 return EGENERIC; 4196 } 4197 buff[ST_STR_BUFF_SIZE + 1] = '\0'; 4198 if (strlen(buff) > ST_STR_BUFF_SIZE) { 4199 st_cbs_os.panic("md_transfer_str(): transferred string has a wrong size: %d\n", strlen(buff)); 4200 return EGENERIC; 4201 } 4202 4203 *str_pt = st_buff_allocate(info, strlen(buff) + 1); 4204 if (!*str_pt) { 4205 st_cbs_os.panic("md_transfer_str(): string buffer could not be allocated.\n"); 4206 return EGENERIC; 4207 } 4208 strcpy(*str_pt, buff); 4209 return OK; 4210 } 4211 4212 PRIVATE int md_transfer(st_init_info_t *info, void *from, void **to, int len) 4213 { 4214 /* backup from value, in case &from == to */ 4215 void *from_backup = from; 4216 *to = st_buff_allocate(info, len); 4217 if (!*to) { 4218 st_cbs_os.panic("md_transfer(): buffer could not be allocated.\n"); 4219 return EGENERIC; 4220 } 4221 if (st_cbs_os.copy_state_region(info->info_opaque, (uint32_t) from_backup, len, (uint32_t) *to)) { 4222 st_cbs_os.panic("md_transfer(): ERROR transferring remote data to buffer.\n"); 4223 return EGENERIC; 4224 } 4225 return OK; 4226 } 4227 4228 4229 /* Buffer allocation */ 4230 4231 PRIVATE void *persistent_mmap(__MA_ARGS__ st_init_info_t *info, void *start, size_t length, int prot, int flags, int fd, off_t offset, struct _magic_dsentry *dsentry) { 4232 if (USE_PRE_ALLOCATED_BUFFER(info)) { 4233 size_t alloc_length = length + (length % magic_get_sys_pagesize() == 0 ? 0 : magic_get_sys_pagesize() - (length % magic_get_sys_pagesize())); 4234 char *ptr, *data_ptr; 4235 4236 assert(((char *)info->init_buff_cleanup_start) + alloc_length + magic_get_sys_pagesize() <= st_pre_allocated_page_pt && "mmap region hits temporary buffer."); 4237 assert(((char *)info->init_buff_cleanup_start) + alloc_length + magic_get_sys_pagesize() <= ((char *) info->init_buff_start) + info->init_buff_len && "mmap region hits end of pre-allocated buffer"); 4238 4239 ptr = ((char *)info->init_buff_cleanup_start) + magic_get_sys_pagesize() - MAGIC_SIZE_TO_REAL(0); 4240 data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, (int) MAGIC_STATE_MAP); 4241 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = flags; 4242 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = prot; 4243 info->init_buff_cleanup_start = &data_ptr[alloc_length]; 4244 return data_ptr; 4245 } else { 4246 /* no pre-allocated mmap buffer. Call magic_mmap to allocate region. */ 4247 return magic_mmap_positioned(type, name, parent_name 4248 , NULL, length, prot, flags, -1, 0, dsentry); 4249 } 4250 } 4251 4252 PUBLIC void *st_cb_pages_allocate(st_init_info_t *info, uint32_t *phys, int num_pages) 4253 { 4254 void *result; 4255 int len = num_pages * magic_get_sys_pagesize(); 4256 4257 if (USE_PRE_ALLOCATED_BUFFER(info)) { 4258 if (!st_pre_allocated_page_pt) { 4259 #if ST_DEBUG_LEVEL > 0 4260 printf("st_pages_allocate: initializing pre-allocated page buffer.\n"); 4261 #endif 4262 st_pre_allocated_page_pt = &((char *)info->init_buff_start)[info->init_buff_len]; 4263 } 4264 st_pre_allocated_page_pt -= len; 4265 assert(st_pre_allocated_page_pt >= (char *)info->init_buff_cleanup_start 4266 && "Temporary buffer ran into perminently pre-allocated mmapped pages."); 4267 return st_pre_allocated_page_pt; 4268 } 4269 4270 result = st_cbs_os.alloc_contig(len, 0, NULL); 4271 if (result == NULL) { 4272 printf("st_pages_allocate: alloc_contig(%d) failed.\n", len); 4273 return NULL; 4274 } 4275 4276 *phys = (uint32_t) NULL; /* we don't know or need the physical address in order to free */ 4277 4278 return result; 4279 } 4280 4281 PUBLIC void st_cb_pages_free(st_init_info_t *info, st_alloc_pages *current_page) 4282 { 4283 st_alloc_pages *to_be_freed; 4284 int result; 4285 4286 if (USE_PRE_ALLOCATED_BUFFER(info)) { 4287 /* nothing to do */ 4288 return; 4289 } 4290 4291 while (current_page != NULL) { 4292 to_be_freed = current_page; 4293 current_page = current_page->previous; 4294 4295 result = st_cbs_os.free_contig(to_be_freed->virt_addr, to_be_freed->num_pages * magic_get_sys_pagesize()); 4296 4297 if (result != OK) { 4298 printf("munmap result != ok, using free()\n"); 4299 /* 4300 * NOTE: in case this is moved out of a magic_* module it needs to be 4301 * manually annotated so it doesn't get instrumented. 4302 */ 4303 free(to_be_freed->virt_addr); 4304 } 4305 4306 } 4307 4308 } 4309 4310 PUBLIC void *st_buff_allocate(st_init_info_t *info, size_t size) 4311 { 4312 void *result; 4313 4314 if (size > st_alloc_buff_available) { 4315 4316 int pagesize = magic_get_sys_pagesize(); 4317 uint32_t phys; 4318 st_alloc_pages *buff_previous_page = st_alloc_pages_current; 4319 4320 /* calculate number of pages needed */ 4321 int pages_needed = (size + sizeof(st_alloc_pages)) / pagesize; 4322 if ((size + sizeof(st_alloc_pages)) % pagesize) 4323 pages_needed++; 4324 4325 /* allocate pages */ 4326 st_alloc_pages_current 4327 = st_cbs.st_cb_pages_allocate(info, &phys, pages_needed); 4328 4329 if (!st_alloc_pages_current) { 4330 printf("Could not allocate buffer.\n"); 4331 return NULL; 4332 } 4333 4334 /* set allocation struct */ 4335 st_alloc_pages_current->virt_addr = st_alloc_pages_current; 4336 st_alloc_pages_current->phys_addr = phys; 4337 st_alloc_pages_current->num_pages = pages_needed; 4338 st_alloc_pages_current->previous = buff_previous_page; 4339 4340 /* requested space is right after the struct */ 4341 st_alloc_buff_pt = (char *) st_alloc_pages_current; 4342 st_alloc_buff_pt += sizeof(st_alloc_pages); 4343 /* subtract the struct size from the available buffer */ 4344 st_alloc_buff_available = pages_needed * pagesize - sizeof(st_alloc_pages); 4345 4346 } 4347 4348 /* return current buffer pointer */ 4349 result = st_alloc_buff_pt; 4350 /* set buffer pointer after space that is requested, ready for next allocation */ 4351 st_alloc_buff_pt += size; 4352 /* adjust available space */ 4353 st_alloc_buff_available -= size; 4354 4355 return result; 4356 4357 } 4358 4359 PUBLIC void st_buff_cleanup(st_init_info_t *info) 4360 { 4361 st_cbs.st_cb_pages_free(info, st_alloc_pages_current); 4362 st_alloc_pages_current = NULL; 4363 st_alloc_buff_available = 0; 4364 st_alloc_buff_pt = NULL; 4365 } 4366 4367 PUBLIC void st_cleanup(st_init_info_t *info) 4368 { 4369 4370 #if MAGIC_LOOKUP_SENTRY_ALLOW_RANGE_INDEX 4371 st_cleanup_rl_index(info, &st_cached_magic_vars); 4372 st_cleanup_rl_index(info, _magic_vars); 4373 #endif 4374 4375 #if MAGIC_LOOKUP_SENTRY_ALLOW_NAME_HASH 4376 st_cleanup_sentry_hash(info, &st_cached_magic_vars); 4377 st_cleanup_sentry_hash(info, _magic_vars); 4378 #endif 4379 4380 #if MAGIC_LOOKUP_FUNCTION_ALLOW_ADDR_HASH 4381 st_cleanup_function_hash(info, &st_cached_magic_vars); 4382 st_cleanup_function_hash(info, _magic_vars); 4383 #endif 4384 4385 #if !ST_ASSUME_RAW_COPY_BEFORE_TRANSFER 4386 assert( 4387 deallocate_nonxferred_dsentries(st_cached_magic_vars.first_dsentry, 4388 &st_counterparts) == OK && 4389 "ERROR occurred during call to deallocate_nonxferred_dsentries()."); 4390 #endif 4391 4392 /* 4393 * Free all temporary allocated memory. 4394 */ 4395 st_buff_cleanup(info); 4396 4397 /* 4398 * Reset all values in case of successive state transfers. 4399 */ 4400 st_init_done = FALSE; 4401 st_pre_allocated_page_pt = NULL; 4402 st_dsentry_buff = NULL; 4403 st_data_buff = NULL; 4404 st_num_type_transformations = 0; 4405 st_local_magic_vars_ptr = &_magic_vars_buff; 4406 st_policies = ST_POLICIES_DEFAULT; 4407 st_unpaired_types_ratio = ST_UNPAIRED_TYPES_RATIO_DEFAULT; 4408 st_unpaired_struct_types_ratio = ST_UNPAIRED_STRUCT_TYPES_RATIO_DEFAULT; 4409 4410 /* Reallow mempool dsentries lookups. */ 4411 magic_lookup_nested_dsentries = 1; 4412 } 4413 4414 /* State cleanup/checking functions. */ 4415 4416 /*===========================================================================* 4417 * do_st_before_receive * 4418 *===========================================================================*/ 4419 PUBLIC void do_st_before_receive() 4420 { 4421 /* Handle State transfer before receive events. */ 4422 int num_violations; 4423 4424 assert(st_state_checking_before_receive_is_enabled()); 4425 4426 num_violations = st_do_state_checking(); 4427 if (__st_before_receive_sc_max_cycles < LONG_MAX) { 4428 __st_before_receive_sc_max_cycles--; 4429 } 4430 if (__st_before_receive_sc_max_violations < LONG_MAX) { 4431 __st_before_receive_sc_max_violations -= num_violations; 4432 } 4433 if (__st_before_receive_sc_max_cycles <= 0) { 4434 st_state_checking_before_receive_set_enabled(0, 0, 0); 4435 printf("Maximum number of cycles reached\n"); 4436 } 4437 if (__st_before_receive_sc_max_violations <= 0) { 4438 st_state_checking_before_receive_set_enabled(0, 0, 0); 4439 printf("Maximum number of violations reached\n"); 4440 } 4441 } 4442 4443 /*===========================================================================* 4444 * st_state_checking_before_receive_is_enabled * 4445 *===========================================================================*/ 4446 PUBLIC int st_state_checking_before_receive_is_enabled() 4447 { 4448 return __st_before_receive_enabled; 4449 } 4450 4451 /*===========================================================================* 4452 * st_state_checking_before_receive_set_enabled * 4453 *===========================================================================*/ 4454 PUBLIC int st_state_checking_before_receive_set_enabled(int enabled, 4455 int max_cycles, int max_violations) 4456 { 4457 int was_enabled = __st_before_receive_enabled; 4458 __st_before_receive_enabled = enabled; 4459 if (enabled) { 4460 if (max_cycles <= 0) { 4461 max_cycles = ST_STATE_CHECKING_DEFAULT_MAX_CYCLES; 4462 } 4463 if (max_violations <= 0) { 4464 max_violations = ST_STATE_CHECKING_DEFAULT_MAX_VIOLATIONS; 4465 } 4466 __st_before_receive_sc_max_cycles = max_cycles; 4467 __st_before_receive_sc_max_violations = max_violations; 4468 printf("Continuous state checking enabled, max cycles=%d, max violations=%d\n", 4469 max_cycles == LONG_MAX ? 0 : max_cycles, 4470 max_violations == LONG_MAX ? 0 : max_violations); 4471 } 4472 else { 4473 printf("Continuous state checking disabled\n"); 4474 } 4475 return was_enabled; 4476 } 4477 4478 /*===========================================================================* 4479 * st_cb_state_checking_wrapper * 4480 *===========================================================================*/ 4481 PRIVATE int st_cb_state_checking_wrapper(_magic_selement_t* selement, 4482 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 4483 void* cb_args) 4484 { 4485 struct st_cb_info cb_info_buff; 4486 struct st_cb_info *cb_info = &cb_info_buff; 4487 int *num_violations = (int*) cb_args; 4488 int ret; 4489 4490 cb_info->local_selements = NULL; 4491 cb_info->local_selement = NULL; 4492 cb_info->walk_flags = MAGIC_TYPE_WALK_DEFAULT_FLAGS; 4493 cb_info->st_cb_flags = ST_CB_CHECK_ONLY; 4494 cb_info->st_cb_saved_flags = NULL; 4495 cb_info->init_info = NULL; 4496 4497 ret = transfer_data_selement(selement, sel_analyzed, sel_stats, cb_info); 4498 if (ret < 0) { 4499 ret = st_cbs.st_cb_state_checking(selement, sel_analyzed, sel_stats, cb_args); 4500 (*num_violations)++; 4501 } 4502 return ret; 4503 } 4504 4505 /*===========================================================================* 4506 * st_do_state_checking * 4507 *===========================================================================*/ 4508 PUBLIC int st_do_state_checking() 4509 { 4510 int num_violations = 0; 4511 magic_sentries_analyze(ST_SEL_ANALYZE_FLAGS, 4512 st_cb_state_checking_wrapper, &num_violations, NULL); 4513 return num_violations; 4514 } 4515 4516 /*===========================================================================* 4517 * st_cb_state_checking_null * 4518 *===========================================================================*/ 4519 PUBLIC int st_cb_state_checking_null(_magic_selement_t* selement, 4520 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 4521 void* cb_args) 4522 { 4523 return EINTR; 4524 } 4525 4526 /*===========================================================================* 4527 * st_cb_state_checking_print * 4528 *===========================================================================*/ 4529 PUBLIC int st_cb_state_checking_print(_magic_selement_t* selement, 4530 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 4531 void* cb_args) 4532 { 4533 printf("%s. Found state violation:\n", st_cbs_os.debug_header()); 4534 magic_sentry_print_el_cb(selement, sel_analyzed, sel_stats, cb_args); 4535 return MAGIC_SENTRY_ANALYZE_SKIP_PATH; 4536 } 4537 4538 /*===========================================================================* 4539 * st_cb_state_checking_panic * 4540 *===========================================================================*/ 4541 PUBLIC int st_cb_state_checking_panic(_magic_selement_t* selement, 4542 _magic_sel_analyzed_t *sel_analyzed, _magic_sel_stats_t *sel_stats, 4543 void* cb_args) 4544 { 4545 st_cb_state_checking_print(selement, sel_analyzed, sel_stats, cb_args); 4546 st_cbs_os.panic("Time to panic..."); 4547 return MAGIC_SENTRY_ANALYZE_STOP; 4548 } 4549 4550 /*===========================================================================* 4551 * st_do_state_cleanup * 4552 *===========================================================================*/ 4553 PUBLIC int st_do_state_cleanup() 4554 { 4555 return st_cbs.st_cb_state_cleanup(); 4556 } 4557 4558 /*===========================================================================* 4559 * st_cb_state_cleanup_null * 4560 *===========================================================================*/ 4561 PUBLIC int st_cb_state_cleanup_null() { 4562 return OK; 4563 } 4564 4565 #ifndef __MINIX 4566 /*===========================================================================* 4567 * st_msync_all_shm_dsentries * 4568 *===========================================================================*/ 4569 PUBLIC void st_msync_all_shm_dsentries(void) { 4570 struct _magic_dsentry *prev_dsentry, *dsentry; 4571 struct _magic_sentry *sentry; 4572 MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, 4573 dsentry, sentry, 4574 4575 /* 4576 * TODO: 4577 * - Don't msync mmaps of /dev/zero 4578 */ 4579 if (MAGIC_STATE_FLAGS(sentry, MAGIC_STATE_SHM | MAGIC_STATE_MAP) && 4580 !(dsentry->alloc_mmap_flags & MAP_ANONYMOUS)) 4581 msync(MAGIC_PTR_TO_DATA(dsentry), sentry->type->size, 4582 MS_SYNC | MS_INVALIDATE); 4583 4584 ); 4585 } 4586 #endif 4587 4588