1*d4514f0bSApple OSS Distributionsimport sys 2*d4514f0bSApple OSS Distributions 3*d4514f0bSApple OSS Distributions# This script's return values 4*d4514f0bSApple OSS DistributionsERROR = 1 5*d4514f0bSApple OSS DistributionsSUCCESS = 0 6*d4514f0bSApple OSS Distributions 7*d4514f0bSApple OSS Distributionserror_help_message = """Safe types were used in MIG in violation of VM API sanitization enforcement. 8*d4514f0bSApple OSS Distributions\t- If you created a new MIG file that is not related to Virtual Memory, you will want to add it to the list of \ 9*d4514f0bSApple OSS Distributionsexceptions in this Python script. 10*d4514f0bSApple OSS Distributions\t- If your work is related to Virtual Memory, you need to use unsafe types for userspace inputs. Make sure you \ 11*d4514f0bSApple OSS Distributionsdefine VM_KERNEL_SERVER in the MIG file, and that the safe type is associated to an unsafe type via VM_UNSAFE_TYPE/VM_TYPE_SAFE_UNSAFE. Learn more by reading doc/vm/sanitize.md.""" 12*d4514f0bSApple OSS Distributions 13*d4514f0bSApple OSS Distributions# List of safe types that should not be used to represent userspace inputs. 14*d4514f0bSApple OSS Distributions# Note that is may be counter-intuitive that we want to prevent the use of 15*d4514f0bSApple OSS Distributions# safe types: they are safe after all, so wouldn't it be better to use them? 16*d4514f0bSApple OSS Distributions# The source of the confusion is that the safety of the type really describes 17*d4514f0bSApple OSS Distributions# the safety of the data. Since the data will be coming from userspace, it is 18*d4514f0bSApple OSS Distributions# considered unsafe/untrusted, and we want to make sure we represent it with 19*d4514f0bSApple OSS Distributions# unsafe types to force the programmer to sanitize it before it can be 20*d4514f0bSApple OSS Distributions# represented with the (directly usable) safe type. 21*d4514f0bSApple OSS Distributions# This is a list of all the safe types which have corresponding unsafe types 22*d4514f0bSApple OSS Distributions# in vm_types_unsafe.h. 23*d4514f0bSApple OSS Distributionssafe_type_list = [ 24*d4514f0bSApple OSS Distributions "mach_vm_address_t", 25*d4514f0bSApple OSS Distributions "mach_vm_offset_t", 26*d4514f0bSApple OSS Distributions "mach_vm_size_t", 27*d4514f0bSApple OSS Distributions "vm_address_t", 28*d4514f0bSApple OSS Distributions "vm_offset_t", 29*d4514f0bSApple OSS Distributions "vm_size_t", 30*d4514f0bSApple OSS Distributions "vm_map_address_t", 31*d4514f0bSApple OSS Distributions "vm_map_offset_t", 32*d4514f0bSApple OSS Distributions "vm_map_size_t", 33*d4514f0bSApple OSS Distributions "memory_object_offset_t", 34*d4514f0bSApple OSS Distributions "memory_object_size_t", 35*d4514f0bSApple OSS Distributions "vm_object_offset_t", 36*d4514f0bSApple OSS Distributions "vm_object_size_t", 37*d4514f0bSApple OSS Distributions "pointer_t", 38*d4514f0bSApple OSS Distributions "vm32_address_t", 39*d4514f0bSApple OSS Distributions "vm32_offset_t", 40*d4514f0bSApple OSS Distributions "vm32_size_t", 41*d4514f0bSApple OSS Distributions "vm_prot_t", 42*d4514f0bSApple OSS Distributions "vm_inherit_t", 43*d4514f0bSApple OSS Distributions "vm_behavior_t", 44*d4514f0bSApple OSS Distributions "caddr_t", 45*d4514f0bSApple OSS Distributions "user_addr_t", 46*d4514f0bSApple OSS Distributions "size_t", 47*d4514f0bSApple OSS Distributions "user_size_t", 48*d4514f0bSApple OSS Distributions "struct mach_vm_range", 49*d4514f0bSApple OSS Distributions "mach_vm_range_recipe_v1_t", 50*d4514f0bSApple OSS Distributions] 51*d4514f0bSApple OSS Distributions 52*d4514f0bSApple OSS Distributions# Files that are considered outside the VM boundary and are thus not subject to enforcement. 53*d4514f0bSApple OSS Distributionsfile_ignorelist = [ 54*d4514f0bSApple OSS Distributions "arcade_register_server.c", 55*d4514f0bSApple OSS Distributions "clock_server.c", 56*d4514f0bSApple OSS Distributions "exc_server.c", 57*d4514f0bSApple OSS Distributions "mach_eventlink_server.c", 58*d4514f0bSApple OSS Distributions "mach_exc_server.c", 59*d4514f0bSApple OSS Distributions "mach_notify_server.c", 60*d4514f0bSApple OSS Distributions "mach_port_server.c", 61*d4514f0bSApple OSS Distributions "mach_voucher_server.c", 62*d4514f0bSApple OSS Distributions "memory_entry_server.c", 63*d4514f0bSApple OSS Distributions "processor_server.c", 64*d4514f0bSApple OSS Distributions "processor_set_server.c", 65*d4514f0bSApple OSS Distributions "restartable_server.c", 66*d4514f0bSApple OSS Distributions "task_server.c", 67*d4514f0bSApple OSS Distributions "thread_act_server.c", 68*d4514f0bSApple OSS Distributions "upl_server.c", 69*d4514f0bSApple OSS Distributions] 70*d4514f0bSApple OSS Distributions 71*d4514f0bSApple OSS Distributionsdef print_error(*args, **kwargs): 72*d4514f0bSApple OSS Distributions print("error:", *args, file=sys.stderr, **kwargs) 73*d4514f0bSApple OSS Distributions 74*d4514f0bSApple OSS Distributionsdef is_type_used_in_line(safe_type, line): 75*d4514f0bSApple OSS Distributions # This is used by an autogenerated struct in MIG that isn't an argument to a MIG call 76*d4514f0bSApple OSS Distributions if "vm_address_t reserved; /* Reserved */" in line: 77*d4514f0bSApple OSS Distributions return False 78*d4514f0bSApple OSS Distributions 79*d4514f0bSApple OSS Distributions # arguments to MIG functions are typically the first thing on the line in the generated header, 80*d4514f0bSApple OSS Distributions # but we search for the type elsewhere to be on the safe side. We still need to be careful not 81*d4514f0bSApple OSS Distributions # to trigger false positives by doing a naive search 82*d4514f0bSApple OSS Distributions # e.g. size_t is in "__Request__host_page_size_t __attribute__((unused));" 83*d4514f0bSApple OSS Distributions if safe_type in line.replace(':', ' ').replace(';', ' ').replace(',', ' ').split(): 84*d4514f0bSApple OSS Distributions return True 85*d4514f0bSApple OSS Distributions 86*d4514f0bSApple OSS Distributions return False 87*d4514f0bSApple OSS Distributions 88*d4514f0bSApple OSS Distributionsdef are_safe_types_used_in_file(filepath): 89*d4514f0bSApple OSS Distributions are_safe_types_used = False 90*d4514f0bSApple OSS Distributions lineno = 1 91*d4514f0bSApple OSS Distributions with open(filepath, "r") as file: 92*d4514f0bSApple OSS Distributions for line in file: 93*d4514f0bSApple OSS Distributions for safe_type in safe_type_list: 94*d4514f0bSApple OSS Distributions if is_type_used_in_line(safe_type, line): 95*d4514f0bSApple OSS Distributions print_error("Found safe type \"" + safe_type + "\" in " +filepath + ":" + str(lineno) + ". Line is \"" + line.strip() + "\"") 96*d4514f0bSApple OSS Distributions are_safe_types_used = True 97*d4514f0bSApple OSS Distributions lineno += 1 98*d4514f0bSApple OSS Distributions return are_safe_types_used 99*d4514f0bSApple OSS Distributions 100*d4514f0bSApple OSS Distributionsdef main(): 101*d4514f0bSApple OSS Distributions if len(sys.argv) < 2: 102*d4514f0bSApple OSS Distributions print_error("usage: python vm_api_enforcement.py filename [extra_filename...]") 103*d4514f0bSApple OSS Distributions return ERROR 104*d4514f0bSApple OSS Distributions 105*d4514f0bSApple OSS Distributions are_safe_types_used = False 106*d4514f0bSApple OSS Distributions for filename in sys.argv[1:]: 107*d4514f0bSApple OSS Distributions if filename in file_ignorelist: 108*d4514f0bSApple OSS Distributions continue 109*d4514f0bSApple OSS Distributions 110*d4514f0bSApple OSS Distributions if not (filename.endswith(".c") or filename.endswith(".h")): 111*d4514f0bSApple OSS Distributions print_error("File should be a .c or .h file:", filename) 112*d4514f0bSApple OSS Distributions return ERROR 113*d4514f0bSApple OSS Distributions header = filename[:-1] + "h" 114*d4514f0bSApple OSS Distributions 115*d4514f0bSApple OSS Distributions are_safe_types_used = are_safe_types_used_in_file(header) 116*d4514f0bSApple OSS Distributions 117*d4514f0bSApple OSS Distributions if are_safe_types_used: 118*d4514f0bSApple OSS Distributions print_error("{}: {}".format(sys.argv[0], error_help_message)) 119*d4514f0bSApple OSS Distributions return ERROR 120*d4514f0bSApple OSS Distributions return SUCCESS 121*d4514f0bSApple OSS Distributions 122*d4514f0bSApple OSS Distributionssys.exit(main()) 123