static ssize_t dev_write()

in pwnables/kpets/src/kpets.c [158:228]


static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
#ifdef DEBUG
    printk("kpets: received pet...\n");
#endif
    struct pet new_pet;
    struct pet* user_pet = (struct pet *)buffer;
    
    unsigned int pet_name_len;
    copy_from_user(&pet_name_len, &user_pet->name_len, sizeof(unsigned int));
    // Validate name len
    if(pet_name_len > sizeof(new_pet.name)) {
        printk("kpets: invalid pet name len: 0x%02x\n", pet_name_len);
        return len;
    }
#ifdef DEBUG
    printk("kpets: first len: %u\n", pet_name_len);
#endif
    unsigned int pet_desc_len;
    copy_from_user(&pet_desc_len, &user_pet->description_len, sizeof(unsigned int));
    // Validate description length
    if(pet_desc_len > sizeof(new_pet.description)) {
        printk("kpets: invalid pet description len: 0x%02x\n", pet_desc_len);
        return len;
    } 

    // Find next free slot
    int i;
    struct pet* p;
    for(i = max_pets - 1, p=first_slot; i > -1 && p->type; i--,p--) {}
    if(i == -1) {
#ifdef DEBUG
        printk("kpets: pet store is full! Time to clear out!\n");
#endif
        clear_pets();
        p = first_slot;
        i = max_pets - 1;
    }
#ifdef DEBUG
    printk("kpets: adding at slot %d\n", i);
#endif

    // Give time for someone to pwn us
    printk("kpets: your new pet owner is %s!", choose_owner());

    char type;
    copy_from_user(&type, &user_pet->type, sizeof(char));
    if(type != '\xc0' && type != '\xc1' && type != '\xc2') {
        printk("kpets: invalid pet type: 0x%02hhx\n", type);
        return len;
    }

    // This is the vulnerability
    unsigned int vuln_name_len;
    copy_from_user(&vuln_name_len, &user_pet->name_len, sizeof(unsigned int));
     
    p->type = type;
    copy_from_user(&p->name, &user_pet->name, vuln_name_len);
    copy_from_user(&p->description, &user_pet->description, pet_desc_len);

#ifdef DEBUG
    printk("New pet type: 0x%02hhx\n", type);
    printk("New pet name: %s\n", &p->name);
    printk("New pet description: %s\n", &p->description);
    if (pet_name_len != vuln_name_len) {
        printk("PWNEDPWNEDPWNED\n");
    }
    printk("Second len: %u\n", vuln_name_len);
#endif
    
    return len;
}