PTRACE_TRACEME CVE-2019-13272 本地提权漏洞解析

来源:岁月联盟 编辑:猪蛋儿 时间:2020-01-29
 886 {
 887         bool seized = child->ptrace & PT_SEIZED;
 888         int ret = -EIO;
 889         siginfo_t siginfo, *si;
 890         void __user *datavp = (void __user *) data;
 891         unsigned long __user *datalp = datavp;
 892         unsigned long flags;
 893
 894         switch (request) {
 895         case PTRACE_PEEKTEXT:
 896         case PTRACE_PEEKDATA:
 897                 return generic_ptrace_peekdata(child, addr, data);
 898         case PTRACE_POKETEXT:
 899         case PTRACE_POKEDATA:
 900                 return generic_ptrace_pokedata(child, addr, data);
 901
 =================== skip ================
 1105 }
 1156 int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
 1157                             unsigned long data)
 1158 {
 1159         unsigned long tmp;
 1160         int copied;
 1161
 1162         copied = ptrace_access_vm(tsk, addr, &tmp, sizeof(tmp), FOLL_FORCE); //
 1163         if (copied != sizeof(tmp))
 1164                 return -EIO;
 1165         return put_user(tmp, (unsigned long __user *)data);
 1166 }
 1167
 1168 int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
 1169                             unsigned long data)
 1170 {
 1171         int copied;
 1172
 1173         copied = ptrace_access_vm(tsk, addr, &data, sizeof(data), //
 1174                         FOLL_FORCE | FOLL_WRITE);
 1175         return (copied == sizeof(data)) ? 0 : -EIO;
 1176 }
如上,当 tracer 想要控制 tracee 执行新的代码逻辑时,需要发送 request 读写 tracee 的代码区和内存区, 对应的 request 是 PTRACE_PEEKTEXT / PTRACE_PEEKDATA / PTRACE_POKETEXT / PTRACE_POKEDATA
这几种读写操作最终都是通过函数 ptrace_access_vm 实现的
    kernel/ptrace.c
    38 int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
    39                      void *buf, int len, unsigned int gup_flags)
    40 {
    41         struct mm_struct *mm;
    42         int ret;
    43
    44         mm = get_task_mm(tsk);
    45         if (!mm)
    46                 return 0;
    47
    48         if (!tsk->ptrace ||
    49             (current != tsk->parent) ||
    50             ((get_dumpable(mm) != SUID_DUMP_USER) &&
    51              !ptracer_capable(tsk, mm->user_ns))) { //
    52                 mmput(mm);

上一页  [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]  下一页