static void peek_buffer (pid_t pid, const void * ptr, char * buffer, int numwords) { int i; for (i = 0; i < numwords*sizeof(long); i += sizeof(long)) { *(unsigned long *)(buffer+i) = peek_long(pid, ptr+i); } }
static int bw2match(device_t parent, cfdata_t cf, void *args) { struct confargs *ca = args; int mid, p4id, peekval; void *p4reg; /* No default address support. */ if (ca->ca_paddr == -1) return 0; /* * Slight hack here: The low four bits of the * config flags, if set, restrict the match to * that machine "implementation" only. */ mid = cf->cf_flags & IDM_IMPL_MASK; if (mid != 0 && (mid != (cpu_machine_id & IDM_IMPL_MASK))) return 0; /* * Make sure something is there, and if so, * see if it looks like a P4 register. */ p4reg = bus_tmapin(ca->ca_bustype, ca->ca_paddr); peekval = peek_long(p4reg); p4id = (peekval == -1) ? P4_NOTFOUND : fb_pfour_id(p4reg); bus_tmapout(p4reg); if (peekval == -1) return 0; /* * The config flag 0x40 if set means we should match * only on a CG? overlay plane. We can use only the * CG4 and CG8, which both have a P4 register. */ if (cf->cf_flags & 0x40) { switch (p4id) { case P4_ID_COLOR8P1: case P4_ID_COLOR24: return 1; case P4_NOTFOUND: default: return 0; } } /* * OK, we are expecting a plain old BW2, and * there may or may not be a P4 register. */ switch (p4id) { case P4_ID_BW: case P4_NOTFOUND: return 1; default: #ifdef DEBUG aprint_debug("bwtwo at 0x%lx match p4id=0x%x fails\n", ca->ca_paddr, p4id & 0xFF); #endif break; } return 0; }
static int handle_syscall(struct trace_context *ctx, pid_t pid, int syscall) { int i; int ret; unsigned long arg; char *path; unsigned int flags; unsigned int oflags; const char *name; char at_path[PATH_MAX]; int at_nofollow; int fd; char *fdpath; for (i = 0; system_calls[i].name; i++) { if (system_calls[i].no == syscall) goto found; } return 0; found: flags = system_calls[i].flags; name = system_calls[i].name; if (flags & CHECK_PATH) { arg = ptrace(PTRACE_PEEKUSER, pid, REG_ARG1, 0); path = get_str(pid, arg); if (flags & OPEN_MODE) { oflags = ptrace(PTRACE_PEEKUSER, pid, REG_ARG2, 0); if (!(oflags & O_WRONLY || oflags & O_RDWR)) return 0; } ret = path_arg_writable(ctx, pid, path, name, flags & DONT_FOLLOW); if (ret) return ret; } if (flags & CHECK_PATH2) { arg = ptrace(PTRACE_PEEKUSER, pid, REG_ARG2, 0); path = get_str(pid, arg); ret = path_arg_writable(ctx, pid, path, name, flags & DONT_FOLLOW); if (ret) return ret; } if (flags & AT_FAMILY_12) { arg = ptrace(PTRACE_PEEKUSER, pid, REG_ARG2, 0); path = get_str(pid, arg); if(flags & AT_FLW_ARG5) //for linkat() call at_nofollow = (ptrace(PTRACE_PEEKUSER, pid, REG_ARG5, 0) & AT_SYMLINK_FOLLOW) ? 0 : 1; else if (flags & AT_FLW_ARG5) //for fchownat() and fchmodat() calls at_nofollow = (ptrace(PTRACE_PEEKUSER, pid, REG_ARG5, 0) & AT_SYMLINK_NOFOLLOW) ? 1 : 0; else if(flags & AT_NOFLW_ARG4) //for utimensat() call at_nofollow = (ptrace(PTRACE_PEEKUSER, pid, REG_ARG4, 0) & AT_SYMLINK_NOFOLLOW) ? 1 : 0; else at_nofollow = flags & DONT_FOLLOW; if (flags & OPEN_MODE) { oflags = ptrace(PTRACE_PEEKUSER, pid, REG_ARG3, 0); if (!(oflags & O_WRONLY || oflags & O_RDWR)) return 0; } if(path[0] != '/' && *path != 0) { fd = ptrace(PTRACE_PEEKUSER, pid, REG_ARG1, 0); fdpath = get_pid_fd_path(pid, fd); sprintf(at_path, "%s/%s", fdpath, path); ret = path_arg_writable(ctx, pid, at_path, name, at_nofollow); } else if (path[0] != '/' && *path == 0) { fd = ptrace(PTRACE_PEEKUSER, pid, REG_ARG1, 0); fdpath = get_pid_fd_path(pid, fd); ret = path_arg_writable(ctx, pid, fdpath, name, at_nofollow); } else ret = path_arg_writable(ctx, pid, path, name, at_nofollow); if (ret) return ret; } if (flags & AT_FAMILY_23) { arg = ptrace(PTRACE_PEEKUSER, pid, REG_ARG3, 0); path = get_str(pid, arg); if(path[0] != '/' && *path != 0) { fd = ptrace(PTRACE_PEEKUSER, pid, REG_ARG2, 0); fdpath = get_pid_fd_path(pid, fd); sprintf(at_path, "%s/%s", fdpath, path); ret = path_arg_writable(ctx, pid, at_path, name, flags & DONT_FOLLOW); } else if (path[0] != '/' && *path == 0) { fd = ptrace(PTRACE_PEEKUSER, pid, REG_ARG2, 0); fdpath = get_pid_fd_path(pid, fd); ret = path_arg_writable(ctx, pid, fdpath, name, flags & DONT_FOLLOW); } else ret = path_arg_writable(ctx, pid, path, name, flags & DONT_FOLLOW); if (ret) return ret; } else if (flags & AT_FAMILY_34) { arg = ptrace(PTRACE_PEEKUSER, pid, REG_ARG4, 0); path = get_str(pid, arg); if(path[0] != '/' && *path != 0) { fd = ptrace(PTRACE_PEEKUSER, pid, REG_ARG3, 0); fdpath = get_pid_fd_path(pid, fd); sprintf(at_path, "%s/%s", fdpath, path); ret = path_arg_writable(ctx, pid, at_path, name, flags & DONT_FOLLOW); } else if (path[0] != '/' && *path == 0) { fd = ptrace(PTRACE_PEEKUSER, pid, REG_ARG3, 0); fdpath = get_pid_fd_path(pid, fd); ret = path_arg_writable(ctx, pid, fdpath, name, flags & DONT_FOLLOW); } else ret = path_arg_writable(ctx, pid, path, name, flags & DONT_FOLLOW); if (ret) return ret; } if (flags & CONNECT_CALL && !ctx->network_allowed) { const struct sockaddr_in * connect_to = (const struct sockaddr_in *) ptrace(PTRACE_PEEKUSER, pid, REG_ARG2, 0); unsigned short * family_pos = (void*)&(connect_to->sin_family); unsigned short family = ptrace(PTRACE_PEEKDATA, pid, family_pos, 0) & 0xFFFF; if (family == AF_INET) { unsigned long host = peek_long(pid, &connect_to->sin_addr); unsigned short port = htons(peek_short(pid, &connect_to->sin_port)); char buffer[15 + 1 + 5 + 1]; // ip + : + 65535 + \0 snprintf(buffer, sizeof(buffer), "%s:%hu", inet_ntoa(*(struct in_addr *)&host), port); catbox_retval_add_violation(ctx, name, "", buffer); } else if (family == AF_LOCAL) { const struct sockaddr_un * local_struct = (const struct sockaddr_un *) connect_to; const char socket_name[UNIX_PATH_MAX]; peek_buffer(pid, &local_struct->sun_path, socket_name, UNIX_PATH_MAX / sizeof(long)); catbox_retval_add_violation(ctx, name, "", socket_name); } else if (family == AF_INET6) { const struct sockaddr_in6 * v6_struct = (const struct sockaddr_in6 *) connect_to; unsigned short port = htons(peek_short(pid, &v6_struct->sin6_port)); unsigned char v6_addr[16]; peek_buffer(pid, &v6_struct->sin6_addr, v6_addr, 16 / sizeof(long)); char ip_buffer[INET6_ADDRSTRLEN + 1 + 5 + 1] = {0}; // v6_addr + : + 65535 + \0 inet_ntop(AF_INET6, v6_addr, ip_buffer, sizeof(ip_buffer)); snprintf(ip_buffer + strlen(ip_buffer), 1+5+1, ":%hu", port); // : + 65535 + \0 catbox_retval_add_violation(ctx, name, "", ip_buffer); } else if (family == AF_UNSPEC) { // ignore this. it's a noop mostly } else { catbox_retval_add_violation(ctx, name, "", "unknown"); } return -EACCES; } if (flags & NET_CALL && !ctx->network_allowed) { catbox_retval_add_violation(ctx, name, "", ""); return -EACCES; } return 0; //below we only trap changes to owner/mode within the fishbowl. // The rest are taken care of in the above blocks if(0 & LOG_OWNER) { struct user_regs_struct regs; ptrace(PTRACE_GETREGS, pid, 0, ®s); // const char* path = get_str(pid, regs.ebx); // uid_t uid = (uid_t)regs.ecx; // gid_t gid = (gid_t)regs.edx; // PyObject* dict = PyObject_GetAttrString( ctx->ret_object, "ownerships" ); // PyDict_SetItem( dict, PyString_FromString(path), PyTuple_Pack( 2, PyInt_FromLong(uid), PyInt_FromLong(gid)) ); return 1; } if(0 & LOG_MODE) { struct user_regs_struct regs; ptrace(PTRACE_GETREGS, pid, 0, ®s); // const char* path = get_str(pid, regs.ebx); // mode_t mode = (mode_t)regs.ecx; // PyObject* dict = PyObject_GetAttrString( ctx->ret_object, "modes" ); // PyDict_SetItem( dict, PyString_FromString(path), PyInt_FromLong(mode) ); return 1; } if(0 & FAKE_ID) { return 2; } return 0; }