I'm learning about buffer overflows, and I get the idea of fat pointer, but what I don't quite get is how are they a good protection? If you were able to modify the pointer so it points to another address, wouldn't you be able to modify the obj base and obj end section of the fat pointer so that the pointer still seems valid?
Buffer overflows aren't about setting the pointer to point to another arbitrary address.
A buffer overflow happens when an input causes your program to performs a seemingly-correct operation (e.g. "
increment(): move the pointer forward 256 bytes") too many times, so that the pointer moves out of the intended data structure / array, and into another object.
A "fat pointer" contains information about the data structure / array size.
increment() can have safety checks in its code, to make sure the pointer is within the appropriate bounds. You still need safety checks somewhere in your code, but this lets you centralise it.
It seems like you think of the type of bufferoverflow which usually happens on the heap. There typically the allocated memory chunks are stored as elements, with metadata, which include pointers to the next and previous element, in doubly linked lists. In theory by overflowing the buffer you'd be able to overwrite the metadata of the next memory chunk and if that one is freed you could be able to overwrite a function pointer, leading to arbitrary code execution. For more information on exploitation see this website
Fat pointers could protect you from this: By simply checking for each operation on the array like reading from or writing to the location, internally a bounds check, wether the given offset/index is valid, will be done and if and only if the bounds check is passed the operation will be executed. (Like @cloudfeet already said.) This means you will not be able to write after the bounds of your memory and therefore are unable to overwrite things like the metadata of the next memory chunk or a pointer on the stack.