diff options
author | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
---|---|---|
committer | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
commit | 5fd83771641d15c418f747bd343ba6738d3875f7 (patch) | |
tree | 5abf0f78f680d9837dbd93d4d4c3933bb7509599 /system_cmds/proc_uuid_policy.tproj | |
download | apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip |
Import macOS userland
adv_cmds-176
basic_cmds-55
bootstrap_cmds-116.100.1
developer_cmds-66
diskdev_cmds-667.40.1
doc_cmds-53.60.1
file_cmds-321.40.3
mail_cmds-35
misc_cmds-34
network_cmds-606.40.1
patch_cmds-17
remote_cmds-63
shell_cmds-216.60.1
system_cmds-880.60.2
text_cmds-106
Diffstat (limited to 'system_cmds/proc_uuid_policy.tproj')
-rw-r--r-- | system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.1 | 54 | ||||
-rw-r--r-- | system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.c | 470 |
2 files changed, 524 insertions, 0 deletions
diff --git a/system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.1 b/system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.1 new file mode 100644 index 0000000..f7398dd --- /dev/null +++ b/system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.1 @@ -0,0 +1,54 @@ +.\" Copyright (c) 2016, Apple Inc. All rights reserved. +.\" +.Dd March 14, 2016 +.Dt PROC_UUID_POLICY 1 +.Os "Mac OS X" +.Sh NAME +.Nm proc_uuid_policy +.Nd Set UUID policy with the kernel +.Sh SYNOPSIS +.Nm +.Ar verb +.Ar policy +.Ar uuid | path +.Sh DESCRIPTION +.Nm +sets policy for a specific UUID or mach-o file with the kernel +.Pp +The uuid may be a uuid of the form 1A213FB4-B430-333F-AC63-891678070AFE +or a path to a valid mach-o executable. +.Nm +will extract the LC_UUID load commands from the executable. +.Pp +.Sh VERBS +The verbs are as follows: +.Bl -tag -width indent +.\" ========== +.It clear +Clear the policy for the given UUID with PROC_UUID_POLICY_OPERATION_CLEAR. +.\" ========== +.It add +Add the policy for the given UUID with PROC_UUID_POLICY_OPERATION_ADD. +.\" ========== +.It remove +Add the policy for the given UUID with PROC_UUID_POLICY_OPERATION_REMOVE. +.\" ========== +.Sh POLICIES +The policies are as follows: +.Bl -tag -width indent +.\" ========== +.It none +PROC_UUID_POLICY_FLAGS_NONE +.\" ========== +.It no_cellular +PROC_UUID_NO_CELLULAR +.\" ========== +.It necp +PROC_UUID_NO_CELLULAR +.\" ========== +.It alt-dyld +PROC_UUID_ALT_DYLD_POLICY +.\" ========== +.El +.Sh SEE ALSO +.Xr otool 1 diff --git a/system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.c b/system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.c new file mode 100644 index 0000000..0078cb9 --- /dev/null +++ b/system_cmds/proc_uuid_policy.tproj/proc_uuid_policy.c @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2016 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* Header Declarations */ +#include <errno.h> +#include <fcntl.h> +#include <libkern/OSByteOrder.h> +#include <libproc.h> +#include <mach-o/fat.h> +#include <mach-o/loader.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> +#include <uuid/uuid.h> +#include <System/sys/proc_uuid_policy.h> + +/* Constant Declarations */ +#define SUCCESS 0 +#define FAILURE -1 +#define MAX_CHUNK_SIZE 1024 * 1024 * 16 + +#ifndef PROC_UUID_ALT_DYLD_POLICY +#define PROC_UUID_ALT_DYLD_POLICY 0x00000004 +#endif + +/* UUID bucket */ +struct uuid_bucket +{ + unsigned int num_uuids; + uuid_t *binary_uuids; +}; + +/* Static Function Definitions */ +static +void +usage(); + +static +int +parse_macho_uuids( + const char *path, + struct uuid_bucket *uuid_bucket); + +static +int +parse_macho_slice( + const void *mapped, + const unsigned int offset, + const unsigned int slice_index, + struct uuid_bucket *uuid_bucket); + +/* Function Definitions */ +int +main( + int argc, + char **argv) +{ + int exit_status = EXIT_FAILURE; + const char *verb_string; + const char *policy_string; + const char *uuid_path_string; + int operation = 0; + const char *operation_string = NULL; + int policy = 0; + uuid_t uuid; + struct stat sb; + struct uuid_bucket uuid_bucket = {0, NULL}; + unsigned int i; + uuid_string_t uuid_string = ""; + + /* + * Parse the arguments. + */ + + if (argc != 4) { + + usage(); + goto BAIL; + } + + verb_string = argv[1]; + policy_string = argv[2]; + uuid_path_string = argv[3]; + + if (strcmp(verb_string, "clear") == 0) { + + operation = PROC_UUID_POLICY_OPERATION_CLEAR; + operation_string = "Clearing"; + } else if (strcmp(verb_string, "add") == 0) { + + operation = PROC_UUID_POLICY_OPERATION_ADD; + operation_string = "Adding"; + } else if (strcmp(verb_string, "remove") == 0) { + + operation = PROC_UUID_POLICY_OPERATION_REMOVE; + operation_string = "Removing"; + } else { + + fprintf(stderr, "Unknown verb: %s\n", verb_string); + usage(); + goto BAIL; + } + + if (strcmp(policy_string, "none") == 0) { + + policy = PROC_UUID_POLICY_FLAGS_NONE; + } else if (strcmp(policy_string, "no_cellular") == 0) { + + policy = PROC_UUID_NO_CELLULAR; + } else if (strcmp(policy_string, "necp") == 0) { + + policy = PROC_UUID_NECP_APP_POLICY; + } else if (strcmp(policy_string, "alt-dyld") == 0) { + + policy = PROC_UUID_ALT_DYLD_POLICY; + } else { + + fprintf(stderr, "Unknown policy: %s\n", policy_string); + usage(); + goto BAIL; + } + + if (uuid_parse(uuid_path_string, uuid) == -1) { + + /* Is this a path to a macho file? */ + if (stat(uuid_path_string, &sb) == -1) { + + fprintf(stderr, "%s is not a UUID nor path: %s\n", uuid_path_string, strerror(errno)); + goto BAIL; + } else { + + /* Parse the UUID from the macho file. */ + if (parse_macho_uuids(uuid_path_string, &uuid_bucket)) { + + fprintf(stderr, "Could not parse %s for its UUID\n", uuid_path_string); + goto BAIL; + } + } + } else { + + uuid_bucket.num_uuids = 1; + uuid_bucket.binary_uuids = calloc(1, sizeof(uuid_t)); + if (uuid_bucket.binary_uuids == NULL) { + + fprintf(stderr, "Could not allocate single UUID bucket\n"); + goto BAIL; + } + + memcpy(uuid_bucket.binary_uuids[0], uuid, sizeof(uuid_t)); + } + + for (i = 0; i < uuid_bucket.num_uuids; i++) { + + uuid_unparse(uuid_bucket.binary_uuids[i], uuid_string); + printf("%s the %s policy for %s\n", operation_string, policy_string, uuid_string); + + if (proc_uuid_policy(operation, uuid_bucket.binary_uuids[i], sizeof(uuid_t), policy) == -1) { + + fprintf(stderr, "Could not enable the UUID policy: %s\n", strerror(errno)); + goto BAIL; + } + } + + /* Set the exit status to success. */ + exit_status = EXIT_SUCCESS; + +BAIL: + + /* + * Clean up. + */ + + if (uuid_bucket.binary_uuids != NULL) { + + free(uuid_bucket.binary_uuids); + } + + return exit_status; +} + +/* Static Function Definitions */ +static +void +usage(void) +{ + fprintf(stderr, "usage: %s <verb> <policy> <uuid | path>\n", getprogname()); + fprintf(stderr, "Verbs:\n"); + fprintf(stderr, "\tclear\tClear all policies for a given UUID\n"); + fprintf(stderr, "\tadd\tAdd a specific policy\n"); + fprintf(stderr, "\tremove\tRemove a specific policy\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Policies:\n"); + fprintf(stderr, "\tnone\t\tPROC_UUID_POLICY_FLAGS_NONE\n"); + fprintf(stderr, "\tno_cellular\tPROC_UUID_NO_CELLULAR\n"); + fprintf(stderr, "\tnecp\t\tPROC_UUID_NECP_APP_POLICY\n"); + fprintf(stderr, "\talt-dyld\tPROC_UUID_ALT_DYLD_POLICY\n"); +} + +static +int +parse_macho_uuids( + const char *path, + struct uuid_bucket *uuid_bucket) +{ + int result = FAILURE; + int fd = -1; + struct stat sb; + void *mapped = MAP_FAILED; + + struct fat_header *fat_header_pointer; + struct fat_arch *fat_arch_pointer; + bool swapped = false; + + uint32_t nfat_arch = 0; + unsigned int i; + uint32_t arch_offset; + uint32_t arch_size; + + /* Open the file and determine its size. */ + fd = open(path, O_RDONLY); + if (fd == -1) { + + fprintf(stderr, "Could not open %s: %s\n", path, strerror(errno)); + goto BAIL; + } + + if (fstat(fd, &sb) == -1) { + + fprintf(stderr, "Could not fstat %s: %s\n", path, strerror(errno)); + goto BAIL; + } + + /* Memory map the file. */ + mapped = mmap (0, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == MAP_FAILED) { + + fprintf(stderr, "Could not memory map %s: %s\n", path, strerror(errno)); + goto BAIL; + } + + /* + * Determine the file type. + */ + + fat_header_pointer = (struct fat_header *) mapped; + + switch (fat_header_pointer->magic) { + + case FAT_MAGIC: { + + nfat_arch = fat_header_pointer->nfat_arch; + }break; + + case FAT_CIGAM: { + + swapped = true; + nfat_arch = OSSwapInt32(fat_header_pointer->nfat_arch); + }break; + + case MH_MAGIC: + case MH_CIGAM: + case MH_MAGIC_64: + case MH_CIGAM_64: { + + uuid_bucket->num_uuids = 1; + + uuid_bucket->binary_uuids = calloc(1, sizeof(uuid_t)); + if (uuid_bucket->binary_uuids == NULL) { + + fprintf(stderr, "Could not allocate a UUID\n"); + goto BAIL; + } + + if (parse_macho_slice(mapped, 0, 0, uuid_bucket)) { + + fprintf(stderr, "Could not parse slice\n"); + goto BAIL; + } + }break; + + default: { + + fprintf(stderr, "Unknown magic: %d\n", fat_header_pointer->magic); + goto BAIL; + } + } + + if (nfat_arch > 0) { + + uuid_bucket->num_uuids = nfat_arch; + + uuid_bucket->binary_uuids = calloc(nfat_arch, sizeof(uuid_t)); + if (uuid_bucket->binary_uuids == NULL) { + + fprintf(stderr, "Could not allocate %d UUIDs\n", nfat_arch); + goto BAIL; + } + + for (i = 0; i < nfat_arch; i++) { + + fat_arch_pointer = (struct fat_arch *)(mapped + sizeof(struct fat_header) + (sizeof(struct fat_arch) * i)); + + if (swapped) { + + arch_offset = OSSwapInt32(fat_arch_pointer->offset); + arch_size = OSSwapInt32(fat_arch_pointer->size); + } else { + + arch_offset = fat_arch_pointer->offset; + arch_size = fat_arch_pointer->size; + } + + if (parse_macho_slice(mapped, arch_offset, i, uuid_bucket)) { + + fprintf(stderr, "Could not parse slice %d of %d\n", i, nfat_arch); + goto BAIL; + } + } + } + + /* Set the result to success. */ + result = SUCCESS; + +BAIL: + + /* + * Clean up. + */ + + if (mapped != MAP_FAILED) { + + (void) munmap(mapped, (size_t)sb.st_size); + mapped = MAP_FAILED; + } + + if (fd != -1) { + + (void) close(fd); + fd = -1; + } + + return result; +} + +static +int +parse_macho_slice( + const void *mapped, + const unsigned int offset, + const unsigned int slice_index, + struct uuid_bucket *uuid_bucket) +{ + int result = FAILURE; + + struct mach_header *mach_header_pointer; + struct mach_header_64 *mach_header_64_pointer; + struct load_command *load_command_pointer; + + bool swapped = false; + + unsigned int number_load_commands = 0; + unsigned int i; + + bool found_uuid_load_command = false; + struct uuid_command *uuid_load_command_pointer = NULL; + + mach_header_pointer = (struct mach_header *)(mapped + offset); + + switch (mach_header_pointer->magic) { + + case FAT_MAGIC: { + + fprintf(stderr, "FAT_MAGIC\n"); + goto BAIL; + }break; + + case FAT_CIGAM: { + + fprintf(stderr, "FAT_CIGAM\n"); + goto BAIL; + }break; + + case MH_MAGIC: { + + number_load_commands = mach_header_pointer->ncmds; + load_command_pointer = (struct load_command *)(void *)(mach_header_pointer + 1); + }break; + + case MH_CIGAM: { + + swapped = true; + + number_load_commands = OSSwapInt32(mach_header_pointer->ncmds); + load_command_pointer = (struct load_command *)(void *)(mach_header_pointer + 1); + }break; + + case MH_MAGIC_64: { + + mach_header_64_pointer = (struct mach_header_64 *)(mapped + offset); + number_load_commands = mach_header_64_pointer->ncmds; + + load_command_pointer = (struct load_command *)(void *)(mach_header_64_pointer + 1); + }break; + + case MH_CIGAM_64: { + + swapped = true; + + mach_header_64_pointer = (struct mach_header_64 *)(mapped + offset); + number_load_commands = OSSwapInt32(mach_header_64_pointer->ncmds); + + load_command_pointer = (struct load_command *)(void *)(mach_header_64_pointer + 1); + }break; + + default: { + + fprintf(stderr, "Unknown magic: %d\n", mach_header_pointer->magic); + goto BAIL; + } + } + + /* Walk the load commands looking for LC_UUID. */ + for (i = 0; i < number_load_commands; i++) { + + if (load_command_pointer->cmd == LC_UUID) { + + found_uuid_load_command = true; + uuid_load_command_pointer = (struct uuid_command *)load_command_pointer; + memcpy(uuid_bucket->binary_uuids[slice_index], uuid_load_command_pointer->uuid, sizeof(uuid_t)); + } + + load_command_pointer = (struct load_command *)((uintptr_t)load_command_pointer + load_command_pointer->cmdsize); + } + + if (found_uuid_load_command == false) { + + fprintf(stderr, "Could not find LC_UUID\n"); + goto BAIL; + } + + /* Set the result to success. */ + result = SUCCESS; + +BAIL: + + return result; +} |