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;
}