void uv_inject(page_desc_t *pd, page_desc_t *pdbegin, page_desc_t *pdend, unsigned long pages, unsigned long addr, unsigned long addrend, unsigned int pagesize, unsigned long mattr, unsigned long nodeid, unsigned long paddr, char *pte_str, unsigned long nodeid_start, unsigned long mattr_start, unsigned long addr_start, int mce_opt) { int count = 0; eid.cpu = sched_getcpu(); for (pd=pdbegin, pdend=pd+pages; pd<pdend && addr < addrend; pd++, addr += pagesize) { if (pd->flags & PD_HOLE) { pagesize = pd->pte; mattr = 0; nodeid = -1; } else { nodeid = get_pnodeid(*pd); paddr = get_paddr(*pd); if (nodeid == INVALID_NODE) nodeid = 0; mattr = get_memory_attr(*pd); pagesize = get_pagesize(*pd); if (mattr && paddr) { if ((pd_total / 2) == count){ sprintf(pte_str, " 0x%016lx ", pd->pte); printf("\t[%012lx] -> 0x%012lx on %s %3s %s%s\n", addr, paddr, idstr(), nodestr(nodeid), pte_str, get_memory_attr_str(nodeid, mattr)); /* Setting value at memory location for recovery * before injecting. */ memset((void *)addr, 'A', pagesize); injecteddata = (char *)addr; printf("Data:%x\n",*injecteddata); eid.addr = paddr; eid.cpu = nodeid; break;//only allow once for now } } } count++; } if (delay){ printf("Enter char to inject.."); getchar(); } if(!manual){ inject_uc(eid.addr, 0 /*int notrigger*/); } }
void* rwxalloc(size_t bytes){ if (!bytes) return 0; static const size_t pagesize = get_pagesize(); size_t numpages = (bytes+pagesize-1)/pagesize; void* block = VirtualAlloc(NULL, numpages*pagesize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); return block; }
/* Params are passed directly, offset is in pages */ int sys_mmap_pgoff(struct tcb *tcp) { /* Try test/mmap_offset_decode.c */ unsigned long long offset; offset = (unsigned long) tcp->u_arg[5]; offset *= get_pagesize(); return print_mmap(tcp, tcp->u_arg, offset); }
int cm_get_proc_stat (T_CM_PROC_STAT * stat, int pid) { long vmem_pages; long rmem_pages; char fname[PATH_MAX]; FILE *cpufp, *memfp; if (stat == NULL || pid == 0) { return 0; } stat->pid = pid; snprintf (fname, PATH_MAX - 1, "/proc/%d/stat", (int) pid); cpufp = fopen (fname, "r"); if (!cpufp) { return 0; } snprintf (fname, PATH_MAX - 1, "/proc/%d/statm", (int) pid); memfp = fopen (fname, "r"); if (memfp == NULL) { fclose (cpufp); return 0; } fscanf (cpufp, "%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%*s%llu%llu", &stat->cpu_user, &stat->cpu_kernel); fscanf (memfp, "%lu%lu", &vmem_pages, &rmem_pages); /* 'size' and 'resident' in stat file */ stat->mem_virtual = vmem_pages * get_pagesize (); stat->mem_physical = rmem_pages * get_pagesize (); fclose (cpufp); fclose (memfp); return 1; }
/* Params are pointed to by u_arg[0], offset is in pages */ int sys_old_mmap_pgoff(struct tcb *tcp) { long u_arg[5]; int i; unsigned narrow_arg[6]; unsigned long long offset; if (umoven(tcp, tcp->u_arg[0], sizeof(narrow_arg), (char *) narrow_arg) == -1) return 0; for (i = 0; i < 5; i++) u_arg[i] = (unsigned long) narrow_arg[i]; offset = narrow_arg[5]; offset *= get_pagesize(); return print_mmap(tcp, u_arg, offset); }
int main(int argc, char **argv) { vps_param *param, *gparam; struct stat st; char *infile = NULL; int opt, recover = 0, ask = 0; int ret = 1; int vswap = -1; init_log(NULL, 0, 1, 0, 0, progname); while ((opt = getopt(argc, argv, "rihv:")) > 0) { switch(opt) { case 'r' : recover = 1; break; case 'i' : ask = 1; break; case 'h' : usage(0); case 'v': switch (yesno2id(optarg)) { case YES: vswap = 1; break; case NO: vswap = 0; break; default: logger(-1, 0, "Invalid argument " "for -v: %s", optarg); usage(1); } break; default : usage(1); } } if (optind >= argc) usage(1); if ((page_size = get_pagesize()) < 0) return 1; /* Read global config */ gparam = init_vps_param(); if (vps_parse_config(0, GLOBAL_CFG, gparam, NULL)) { logger(-1, 0, "WARNING: Global configuration file %s " "not found", GLOBAL_CFG); } /* Read container config */ infile = strdup(argv[optind]); if (!infile) { logger(-1, 0, "No free memory"); goto err; } if (stat(infile, &st)) { logger(-1, 0, "Container configuration file %s not found", infile); goto err; } param = init_vps_param(); if (vps_parse_config(0, infile, param, NULL)) goto err; /* Merge configs (needed for DISK_QUOTA value, maybe others) */ merge_vps_param(gparam, param); if (vswap == -1) vswap = is_vswap_config(¶m->res.ub); if (!(ret = validate(¶m->res, recover, ask, vswap))) { if (recover || ask) if (vps_save_config(0, infile, param, NULL, NULL)) goto err; logger(-1, 0, "Validation completed: success"); ret = 0; } else ret = 2; err: free(infile); exit(ret); }
int calculate(int veid, ub_param *ub, int verbose) { ub_param ub_cur; char tmp[STR_SIZE]; int ret = 0; double kmem_net_cur, lm_cur, tr_cur, ms_cur, al_cur, np_cur; double kmem_net_max, lm_max, lm_prm, ms_prm, al_prm, al_max, np_max; double cur, prm, max; unsigned long long lowmem; unsigned long long ram, swap = 1; int run, thrmax; int page; if (check_param(ub)) return 1; if (get_mem(&ram)) return 1; if (get_thrmax(&thrmax)) return 1; get_swap(&swap); if (get_lowmem(&lowmem)) return 1; page = get_pagesize(); lm_cur = tr_cur = ms_cur = al_cur = np_cur = 0; lowmem *= 0.4; memset(&ub_cur, 0, sizeof(ub_cur)); if (!(run = vps_read_ubc(veid, &ub_cur))) { if (check_param(&ub_cur)) return 1; kmem_net_cur = (double)ub_cur.kmemsize[0] + (double)ub_cur.tcprcvbuf[0] + (double)ub_cur.tcpsndbuf[0] + (double)ub_cur.dgramrcvbuf[0] + (double)ub_cur.othersockbuf[0]; /* Low memory */ lm_cur = kmem_net_cur / lowmem; /* Total RAM */ tr_cur = ((double)ub_cur.physpages[0] * page + kmem_net_cur) / ram; /* Mem + Swap */ ms_cur = ((double)ub_cur.oomguarpages[0] * page + kmem_net_cur) / (ram + swap); /* Allocated */ al_cur = ((double)ub_cur.privvmpages[0] * page + kmem_net_cur) / (ram + swap); /* Numproc */ np_cur = (double)ub_cur.numproc[0] / thrmax; } kmem_net_max = (double)ub->kmemsize[1] + (double)ub->tcprcvbuf[1] + (double)ub->tcpsndbuf[1] + (double)ub->dgramrcvbuf[1] + (double)ub->othersockbuf[1]; /* Low memory */ lm_max = kmem_net_max / lowmem; lm_prm = lm_max; /* Mem + Swap */ ms_prm = ((double)ub->oomguarpages[0] * page + kmem_net_max) / (ram + swap); /* Allocated */ al_prm = ((double)ub->vmguarpages[0] * page + kmem_net_max) / (ram + swap); al_max = ((double)ub->privvmpages[1] * page + kmem_net_max) / (ram + swap); /* Numproc */ np_max = (double)ub->numproc[0] / thrmax; /* Calculate maximum for current */ cur = lm_cur; if (tr_cur > cur) cur = tr_cur; if (ms_cur > cur) cur = ms_cur; if (al_cur > cur) cur = al_cur; if (np_cur > cur) cur = np_cur; /* Calculate maximum for promised */ prm = lm_prm; if (ms_prm > prm) prm = ms_prm; if (al_prm > prm) prm = al_prm; /* Calculate maximum for Max */ max = lm_max; if (al_max > max) max = al_max; if (np_max > max) max = np_max; sprintf(tmp, "n/a"); printf("Resource Current(%%) Promised(%%) Max(%%)\n"); if (verbose) { if (!run) sprintf(tmp, "%10.2f", lm_cur * 100); printf("Low Mem %10s %10.2f %10.2f\n", tmp, lm_prm * 100, lm_max * 100); if (!run) sprintf(tmp, "%10.2f", tr_cur * 100); printf("Total RAM %10s n/a n/a \n", tmp); if (!run) sprintf(tmp, "%10.2f", ms_cur * 100); printf("Mem + Swap %10s %10.2f n/a\n", tmp, ms_prm * 100); if (!run) sprintf(tmp, "%10.2f", al_cur * 100); printf("Alloc. Mem %10s %10.2f %10.2f\n", tmp , al_prm * 100, al_max * 100); if (!run) sprintf(tmp, "%10.2f", np_cur * 100); printf("Num. Proc %10s n/a %10.2f\n", tmp, np_max * 100); printf("--------------------------------------------\n"); } if (!run) sprintf(tmp, "%10.2f", cur * 100); printf("Memory %10s %10.2f %10.2f\n", tmp, prm * 100, max * 100); free_ub_param(&ub_cur); return ret; }
static ssize_t vm_read_mem(const pid_t pid, void *const laddr, const kernel_ulong_t raddr, const size_t len) { const unsigned long truncated_raddr = raddr; #if SIZEOF_LONG < SIZEOF_KERNEL_LONG_T if (raddr != (kernel_ulong_t) truncated_raddr) { errno = EIO; return -1; } #endif const struct iovec local = { .iov_base = laddr, .iov_len = len }; const struct iovec remote = { .iov_base = (void *) truncated_raddr, .iov_len = len }; const ssize_t rc = process_vm_readv(pid, &local, 1, &remote, 1, 0); if (rc < 0 && errno == ENOSYS) process_vm_readv_not_supported = true; return rc; } static bool tracee_addr_is_invalid(kernel_ulong_t addr) { return #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG current_wordsize < sizeof(addr) && addr & ~(kernel_ulong_t) -1U; #else false; #endif } /* legacy method of copying from tracee */ static int umoven_peekdata(const int pid, kernel_ulong_t addr, unsigned int len, void *laddr) { unsigned int nread = 0; unsigned int residue = addr & (sizeof(long) - 1); while (len) { addr &= -sizeof(long); /* aligned address */ errno = 0; union { long val; char x[sizeof(long)]; } u = { .val = ptrace(PTRACE_PEEKDATA, pid, addr, 0) }; switch (errno) { case 0: break; case ESRCH: case EINVAL: /* these could be seen if the process is gone */ return -1; case EFAULT: case EIO: case EPERM: /* address space is inaccessible */ if (nread) { perror_msg("umoven: short read (%u < %u) @0x%" PRI_klx, nread, nread + len, addr - nread); } return -1; default: /* all the rest is strange and should be reported */ perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx, pid, addr); return -1; } unsigned int m = MIN(sizeof(long) - residue, len); memcpy(laddr, &u.x[residue], m); residue = 0; addr += sizeof(long); laddr += m; nread += m; len -= m; } return 0; } /* * Copy `len' bytes of data from process `pid' * at address `addr' to our space at `our_addr'. */ int umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, void *const our_addr) { if (tracee_addr_is_invalid(addr)) return -1; const int pid = tcp->pid; if (process_vm_readv_not_supported) return umoven_peekdata(pid, addr, len, our_addr); int r = vm_read_mem(pid, our_addr, addr, len); if ((unsigned int) r == len) return 0; if (r >= 0) { error_msg("umoven: short read (%u < %u) @0x%" PRI_klx, (unsigned int) r, len, addr); return -1; } switch (errno) { case ENOSYS: case EPERM: /* try PTRACE_PEEKDATA */ return umoven_peekdata(pid, addr, len, our_addr); case ESRCH: /* the process is gone */ return -1; case EFAULT: case EIO: /* address space is inaccessible */ return -1; default: /* all the rest is strange and should be reported */ perror_msg("process_vm_readv: pid:%d @0x%" PRI_klx, pid, addr); return -1; } } /* * Like umoven_peekdata but make the additional effort of looking * for a terminating zero byte. */ static int umovestr_peekdata(const int pid, kernel_ulong_t addr, unsigned int len, void *laddr) { unsigned int nread = 0; unsigned int residue = addr & (sizeof(long) - 1); void *const orig_addr = laddr; while (len) { addr &= -sizeof(long); /* aligned address */ errno = 0; union { unsigned long val; char x[sizeof(long)]; } u = { .val = ptrace(PTRACE_PEEKDATA, pid, addr, 0) }; switch (errno) { case 0: break; case ESRCH: case EINVAL: /* these could be seen if the process is gone */ return -1; case EFAULT: case EIO: case EPERM: /* address space is inaccessible */ if (nread) { perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx, nread, nread + len, addr - nread); } return -1; default: /* all the rest is strange and should be reported */ perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx, pid, addr); return -1; } unsigned int m = MIN(sizeof(long) - residue, len); memcpy(laddr, &u.x[residue], m); while (residue < sizeof(long)) if (u.x[residue++] == '\0') return (laddr - orig_addr) + residue; residue = 0; addr += sizeof(long); laddr += m; nread += m; len -= m; } return 0; } /* * Like `umove' but make the additional effort of looking * for a terminating zero byte. * * Returns < 0 on error, strlen + 1 if NUL was seen, * else 0 if len bytes were read but no NUL byte seen. * * Note: there is no guarantee we won't overwrite some bytes * in laddr[] _after_ terminating NUL (but, of course, * we never write past laddr[len-1]). */ int umovestr(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len, char *laddr) { if (tracee_addr_is_invalid(addr)) return -1; const int pid = tcp->pid; if (process_vm_readv_not_supported) return umovestr_peekdata(pid, addr, len, laddr); const size_t page_size = get_pagesize(); const size_t page_mask = page_size - 1; unsigned int nread = 0; while (len) { /* * Don't cross pages, otherwise we can get EFAULT * and fail to notice that terminating NUL lies * in the existing (first) page. */ unsigned int chunk_len = len > page_size ? page_size : len; unsigned int end_in_page = (addr + chunk_len) & page_mask; if (chunk_len > end_in_page) /* crosses to the next page */ chunk_len -= end_in_page; int r = vm_read_mem(pid, laddr, addr, chunk_len); if (r > 0) { char *nul_addr = memchr(laddr, '\0', r); if (nul_addr) return (nul_addr - laddr) + 1; addr += r; laddr += r; nread += r; len -= r; continue; } switch (errno) { case ENOSYS: case EPERM: /* try PTRACE_PEEKDATA */ if (!nread) return umovestr_peekdata(pid, addr, len, laddr); ATTRIBUTE_FALLTHROUGH; case EFAULT: case EIO: /* address space is inaccessible */ if (nread) perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx, nread, nread + len, addr - nread); return -1; case ESRCH: /* the process is gone */ return -1; default: /* all the rest is strange and should be reported */ perror_msg("process_vm_readv: pid:%d @0x%" PRI_klx, pid, addr); return -1; } } return 0; }