static int check_prctl(void) { unsigned long user_auxv = 0; unsigned int *tid_addr; int ret; ret = sys_prctl(PR_GET_TID_ADDRESS, (unsigned long)&tid_addr, 0, 0, 0); if (ret) { pr_msg("prctl: PR_GET_TID_ADDRESS is not supported\n"); return -1; } ret = sys_prctl(PR_SET_MM, PR_SET_MM_BRK, sys_brk(0), 0, 0); if (ret) { if (ret == -EPERM) pr_msg("prctl: One needs CAP_SYS_RESOURCE capability to perform testing\n"); else pr_msg("prctl: PR_SET_MM is not supported\n"); return -1; } ret = sys_prctl(PR_SET_MM, PR_SET_MM_EXE_FILE, -1, 0, 0); if (ret != -EBADF) { pr_msg("prctl: PR_SET_MM_EXE_FILE is not supported (%d)\n", ret); return -1; } ret = sys_prctl(PR_SET_MM, PR_SET_MM_AUXV, (long)&user_auxv, sizeof(user_auxv), 0); if (ret) { pr_msg("prctl: PR_SET_MM_AUXV is not supported\n"); return -1; } return 0; }
int log_init(const char *output) { int new_logfd, sfd, dfd; dfd = get_service_fd(LOG_DIR_FD_OFF); if (dfd < 0) { pr_msg("Can't obtain logfd"); goto err; } if (logdir < 0) { int tmp; tmp = open(".", O_RDONLY); if (tmp == -1) { pr_perror("Can't open a current directory"); return -1; } if (reopen_fd_as(dfd, tmp) < 0) return -1; logdir = dfd; } sfd = get_service_fd(LOG_FD_OFF); if (sfd < 0) { pr_msg("Can't obtain logfd"); goto err; } if (output) { new_logfd = openat(logdir, output, O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0600); if (new_logfd < 0) { pr_perror("Can't create log file %s", output); return -1; } if (sfd == current_logfd) close(sfd); if (reopen_fd_as(sfd, new_logfd) < 0) goto err; } else { new_logfd = dup2(DEFAULT_LOGFD, sfd); if (new_logfd < 0) { pr_perror("Dup %d -> %d failed", DEFAULT_LOGFD, sfd); goto err; } } current_logfd = sfd; return 0; err: pr_perror("Log engine failure, can't duplicate descriptor"); return -1; }
static int pb_msg_int64x_r(pb_pr_field_t *field) { long val = *(long *)field->data; if (val) pr_msg("%#016lx", val); else pr_msg("0"); return 0; }
void show_tcp_stream(int fd, void *obj) { TcpStreamEntry *e = obj; if (opts.show_pages_content) { pr_msg("In-queue:"); print_image_data(fd, e->inq_len, 1); pr_msg("Out-queue:"); print_image_data(fd, e->outq_len, 1); } }
static int show_bool(pb_pr_field_t *field) { protobuf_c_boolean val = *(protobuf_c_boolean *)field->data; if (val) pr_msg("True"); else pr_msg("False"); return 0; }
static int check_sock_diag(void) { int ret; ret = collect_sockets(0); if (!ret) return 0; pr_msg("The sock diag infrastructure is incomplete.\n"); pr_msg("Make sure you have:\n"); pr_msg(" 1. *_DIAG kernel config options turned on;\n"); pr_msg(" 2. *_diag.ko modules loaded (if compiled as modules).\n"); return -1; }
static int od_match(const char *map, const char *key, char **od_line, int *od_len) { int ret; char *pattern; struct match_cbdata cbdata; if (trace > 1) { trace_prt(1, "od_match called\n"); trace_prt(1, "od_match: key =[ %s ] map = %s\n", key, map); } /* Construct the string value to search for. */ if (asprintf(&pattern, "%s,automountMapName=%s", key, map) == -1) { pr_msg("od_match: malloc failed"); ret = __NSW_UNAVAIL; goto done; } if (trace > 1) trace_prt(1, " od_match: Searching for %s\n", pattern); cbdata.map = map; cbdata.key = key; cbdata.od_line = od_line; cbdata.od_len = od_len; ret = od_search(kODAttributeTypeRecordName, pattern, match_callback, (void *) &cbdata); free(pattern); if (trace > 1) { if (ret == __NSW_NOTFOUND) trace_prt(1, " od_match: no entries found\n"); else if (ret != __NSW_UNAVAIL) trace_prt(1, " od_match: od_search FAILED: %d\n", ret); else trace_prt(1, " od_match: od_search OK\n"); } if (verbose) { if (ret == __NSW_NOTFOUND) pr_msg("od_search for %s in %s failed", key, map); } done: return (ret); }
void do_pb_show_plain(int fd, int type, int single_entry, void (*payload_hadler)(int fd, void *obj), const char *pretty_fmt) { pb_pr_ctl_t ctl = {NULL, single_entry, pretty_fmt}; void (*handle_payload)(int fd, void *obj); if (!cr_pb_descs[type].pb_desc) { pr_err("Wrong object requested %d\n", type); return; } handle_payload = (payload_hadler) ? : pb_no_payload; while (1) { void *obj; if (pb_read_one_eof(fd, &obj, type) <= 0) break; ctl.arg = (void *)cr_pb_descs[type].pb_desc; pb_show_msg(obj, &ctl); handle_payload(fd, obj); cr_pb_descs[type].free(obj, NULL); if (single_entry) break; pr_msg("\n"); } }
static int parse_ns_string(const char *ptr) { const char *end = ptr + strlen(ptr); do { if (ptr[3] != ',' && ptr[3] != '\0') goto bad_ns; if (!strncmp(ptr, "uts", 3)) opts.rst_namespaces_flags |= CLONE_NEWUTS; else if (!strncmp(ptr, "ipc", 3)) opts.rst_namespaces_flags |= CLONE_NEWIPC; else if (!strncmp(ptr, "mnt", 3)) opts.rst_namespaces_flags |= CLONE_NEWNS; else if (!strncmp(ptr, "pid", 3)) opts.rst_namespaces_flags |= CLONE_NEWPID; else if (!strncmp(ptr, "net", 3)) opts.rst_namespaces_flags |= CLONE_NEWNET; else goto bad_ns; ptr += 4; } while (ptr < end); return 0; bad_ns: pr_msg("Error: unknown namespace: %s\n", ptr); return -1; }
int main(int argc, char **argv) { int ret; char *pattern; if (argc < 2 || argc > 3) { fprintf(stderr, "Usage: dumammap <map name> [ <key> ]\n"); return 1; } if (argc == 2) { /* * Dump the entire map. */ ret = od_search(kODAttributeTypeMetaAutomountMap, argv[1]); } else { /* * Dump an entry in the map. * First, construct the string value to search for. */ if (asprintf(&pattern, "%s,automountMapName=%s", argv[2], argv[1]) == -1) { pr_msg("malloc failed"); return 2; } /* * Now search for that entry. */ ret = od_search(kODAttributeTypeRecordName, pattern); free(pattern); } return ret ? 0 : 2; }
static void pb_show_field(const ProtobufCFieldDescriptor *fd, int nr_fields, pb_pr_ctl_t *ctl) { pb_pr_show_t show; print_tabs(ctl); pr_msg("%s: ", fd->name); show = get_show_function(fd, ctl); pb_show_repeated(ctl, nr_fields, show, pb_show_prepare_field_context(fd, ctl)); if (ctl->single_entry) pr_msg("\n"); else pr_msg(" "); }
/* * Fetch all the map records in Open Directory that have a certain attribute * that matches a certain value and pass those records to a callback function. */ static int od_search(CFStringRef attr_to_match, char *value_to_match, callback_fn callback, void *udata) { int ret; CFErrorRef error; char *errstring; ODNodeRef node_ref; CFArrayRef attrs; CFStringRef value_to_match_cfstr; ODQueryRef query_ref; CFArrayRef results; CFIndex num_results; CFIndex i; ODRecordRef record; callback_ret_t callback_ret; /* * Create the search node. */ error = NULL; node_ref = ODNodeCreateWithNodeType(kCFAllocatorDefault, kODSessionDefault, kODNodeTypeAuthentication, &error); if (node_ref == NULL) { errstring = od_get_error_string(error); pr_msg("od_search: can't create search node for /Search: %s", errstring); free(errstring); return (__NSW_UNAVAIL); } /* * Create the query. */ value_to_match_cfstr = CFStringCreateWithCString(kCFAllocatorDefault, value_to_match, kCFStringEncodingUTF8); if (value_to_match_cfstr == NULL) { CFRelease(node_ref); pr_msg("od_search: can't make CFString from %s", value_to_match); return (__NSW_UNAVAIL); } attrs = CFArrayCreate(kCFAllocatorDefault, (const void *[2]){kODAttributeTypeRecordName, kODAttributeTypeAutomountInformation}, 2,
static int check_tty(void) { int master = -1, slave = -1; const int lock = 1; struct termios t; char *slavename; int ret = -1; if (ARRAY_SIZE(t.c_cc) < TERMIOS_NCC) { pr_msg("struct termios has %d @c_cc while " "at least %d expected.\n", (int)ARRAY_SIZE(t.c_cc), TERMIOS_NCC); goto out; } master = open("/dev/ptmx", O_RDWR); if (master < 0) { pr_msg("Can't open master pty.\n"); goto out; } if (ioctl(master, TIOCSPTLCK, &lock)) { pr_msg("Unable to lock pty device.\n"); goto out; } slavename = ptsname(master); slave = open(slavename, O_RDWR); if (slave < 0) { if (errno != EIO) { pr_msg("Unexpected error code on locked pty.\n"); goto out; } } else { pr_msg("Managed to open locked pty.\n"); goto out; } ret = 0; out: close_safe(&master); close_safe(&slave); return ret; }
static int show_bytes(pb_pr_field_t *field) { ProtobufCBinaryData *bytes = (ProtobufCBinaryData *)field->data; int i = 0; while (i < bytes->len) pr_msg("%02x ", bytes->data[i++]); return 0; }
void ipc_msg_handler(struct cr_img *img, void *obj) { IpcMsgEntry *e = obj; int msg_nr = 0; pr_msg("\n"); while (msg_nr++ < e->qnum) pb_show_plain_payload(img, PB_IPCNS_MSG, ipc_msg_data_handler); }
static inline void print_tabs(pb_pr_ctl_t *ctl) { int counter = ctl->cur.depth; if (!ctl->single_entry) return; while (counter--) pr_msg("\t"); }
static int check_kcmp(void) { int ret = sys_kcmp(getpid(), -1, -1, -1, -1); if (ret != -ENOSYS) return 0; pr_msg("System call kcmp is not supported\n"); return -1; }
static void show_inventory(int fd, struct cr_options *o) { InventoryEntry *he; if (pb_read_one(fd, &he, PB_INVENTORY) < 0) return; pr_msg("Version: %u\n", he->img_version); inventory_entry__free_unpacked(he, NULL); }
static int check_posix_timers(void) { int ret; ret = access("/proc/self/timers", R_OK); if (!ret) return 0; pr_msg("/proc/<pid>/timers file is missing.\n"); return -1; }
static int show_enum(pb_pr_field_t *field) { pb_pr_ctl_t *ctl = container_of(field, pb_pr_ctl_t, cur); ProtobufCEnumDescriptor *d = ctl->arg; const char *val_name = NULL; int val, i; val = *(int *)field->data; for (i = 0; i < d->n_values; i++) if (d->values[i].value == val) { val_name = d->values[i].name; break; } if (val_name != NULL) pr_msg("%s", val_name); else pr_msg("%d", val); return 0; }
static int check_ns_last_pid(void) { int ret; ret = access(LAST_PID_PATH, W_OK); if (!ret) return 0; pr_msg("%s sysctl is missing.\n", LAST_PID_PATH); return -1; }
static int check_map_files(void) { int ret; ret = access("/proc/self/map_files", R_OK); if (!ret) return 0; pr_msg("/proc/<pid>/map_files directory is missing.\n"); return -1; }
static int check_ipc(void) { int ret; ret = access("/proc/sys/kernel/sem_next_id", R_OK | W_OK); if (!ret) return 0; pr_msg("/proc/sys/kernel/sem_next_id sysctl is missing.\n"); return -1; }
static int check_proc_stat(void) { struct proc_pid_stat stat; int ret; ret = parse_pid_stat(getpid(), &stat); if (ret) { pr_msg("procfs: stat extension is not supported\n"); return -1; } return 0; }
static int check_sock_diag(void) { int ret; struct ns_id ns; ns.pid = 0; ns.net.nlsk = socket(PF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG); if (ns.net.nlsk < 0) { pr_perror("Can't make diag socket for check"); return -1; } ret = collect_sockets(&ns); if (!ret) return 0; pr_msg("The sock diag infrastructure is incomplete.\n"); pr_msg("Make sure you have:\n"); pr_msg(" 1. *_DIAG kernel config options turned on;\n"); pr_msg(" 2. *_diag.ko modules loaded (if compiled as modules).\n"); return -1; }
static int pb_show_pretty(pb_pr_field_t *field) { switch (field->fmt[0]) { case '%': pr_msg(field->fmt, *(long *)field->data); break; case 'S': { ProtobufCBinaryData *name = (ProtobufCBinaryData *)field->data; int i; for (i = 0; i < name->len; i++) { char c = (char)name->data[i]; if (isprint(c)) pr_msg("%c", c); else if (c != 0) pr_msg("."); } break; } case 'A': { char addr[INET_ADDR_LEN] = "<unknown>"; int family = (field->count == 1) ? AF_INET : AF_INET6; if (inet_ntop(family, (void *)field->data, addr, INET_ADDR_LEN) == NULL) pr_msg("failed to translate"); else pr_msg("%s", addr); } return 1; } return 0; }
static void pb_show_repeated(pb_pr_ctl_t *ctl, int nr_fields, pb_pr_show_t show, size_t fsize) { pb_pr_field_t *field = &ctl->cur; unsigned long counter; int done; if (nr_fields == 0) { pr_msg("<empty>"); return; } field->count = nr_fields; done = show(field); if (done) return; field->data += fsize; for (counter = 0; counter < nr_fields - 1; counter++, field->data += fsize) { pr_msg(":"); show(field); } }
void ipc_sem_handler(int fd, void *obj) { IpcSemEntry *e = obj; u16 *values; int size; pr_msg("\n"); size = round_up(sizeof(u16) * e->nsems, sizeof(u64)); values = xmalloc(size); if (values == NULL) return; if (read_img_buf(fd, values, size) <= 0) { xfree(values); return; } pr_msg_ipc_sem_array(e->nsems, values); }
static int check_prctl(void) { unsigned long user_auxv = 0; unsigned int *tid_addr; unsigned int size = 0; int ret; ret = prctl(PR_GET_TID_ADDRESS, (unsigned long)&tid_addr, 0, 0, 0); if (ret) { pr_msg("prctl: PR_GET_TID_ADDRESS is not supported"); return -1; } /* * Either new or old interface must be supported in the kernel. */ ret = prctl(PR_SET_MM, PR_SET_MM_MAP_SIZE, (unsigned long)&size, 0, 0); if (ret) { if (!opts.check_ms_kernel) { pr_msg("prctl: PR_SET_MM_MAP is not supported, which " "is required for restoring user namespaces\n"); return -1; } else pr_warn("Skipping unssuported PR_SET_MM_MAP\n"); ret = prctl(PR_SET_MM, PR_SET_MM_BRK, brk(0), 0, 0); if (ret) { if (ret == -EPERM) pr_msg("prctl: One needs CAP_SYS_RESOURCE capability to perform testing\n"); else pr_msg("prctl: PR_SET_MM is not supported\n"); return -1; } ret = prctl(PR_SET_MM, PR_SET_MM_EXE_FILE, -1, 0, 0); if (ret != -EBADF) { pr_msg("prctl: PR_SET_MM_EXE_FILE is not supported (%d)\n", ret); return -1; } ret = prctl(PR_SET_MM, PR_SET_MM_AUXV, (long)&user_auxv, sizeof(user_auxv), 0); if (ret) { pr_msg("prctl: PR_SET_MM_AUXV is not supported\n"); return -1; } } return 0; }
static int check_sock_peek_off(void) { int sk; int ret, off, sz; sk = socket(PF_UNIX, SOCK_DGRAM, 0); if (sk < 0) { pr_perror("Can't create unix socket for check"); return -1; } sz = sizeof(off); ret = getsockopt(sk, SOL_SOCKET, SO_PEEK_OFF, &off, (socklen_t *)&sz); close(sk); if ((ret == 0) && (off == -1) && (sz == sizeof(int))) return 0; pr_msg("SO_PEEK_OFF sockoption doesn't work.\n"); return -1; }