Can I protect areas of a MCU's flash from reprogramming/reading by arbitrary code executing in that MCU?
No, you cannot implement memory access control in Arduino microcontroller firmware. Maybe with a different platform, if you use a sufficiently secure system, but that's a major design consideration. You will have to take into consideration how important the thing you're trying to protect is.
The problem with inventing your own security system is that you have to get it right every single time, but an attacker only has to be right once. They only have to find a single weakness that you didn't think of. There is an industry group called Payment Card Industry Security Standards Council or PCI SSC which has been working on this problem for years... they are concerned about real criminals trying to break into financial terminals to steal real money, and all points of the supply chain are potentially vulnerable.
It's a very hard problem, and one that can't really be addressed very well without having a secure microcontroller to begin with. The company I work at makes security devices used in point-of-sale terminals (credit card readers); see appnote-4809 and deepcover embedded security solution guide (Full disclosure: I am an applications engineer at Maxim Integrated, which manufactures secure microcontrollers, among other things.)
In your case, you are only trying to control read/write access to some part of memory, but there's a conflict between the requirements of having &quot;access controlled memory&quot; and the requirements of allowing new firmware to run in a &quot;bare metal&quot; (eabi) environment, with no operating system and no supervisor. Anyone can load any code through your bootloader. There is no way for the Arduino chip to tell whether the code is &quot;good&quot; code or &quot;evil&quot; code. The Arduino bootloader is not designed for any kind of security at all, it is only designed for the convenience of being able to load new firmware in-circuit without the need for an external device programmer. The only Arduino security consideration is, don't let anyone &quot;evil&quot; near your hardware.
One idea to consider is to &quot;lock down&quot; your bootloader such that it will only accept firmware updates that have been signed with a suitable crypto key. You would then need to have some kind of system that reviews the candidate firmware, looking for any &quot;evil&quot; features like attempts to access certain memory addresses, before approving the firmware by signing it with your secret key. That's pretty far out of what you can do with an Arduino though, I don't know of any crypto libraries that work on an Arduino. You might consider upgrading to an Arm processor if you need that kind of security. See mbed.org for more details. However there are still more problems...
Consider also how the bootloader got into the chip in the first place. If your Arduino is the classic Atmel/Microchip ATmeta328 microcontroller, then the initial bootloader was programmed in using an external device programmer connected to a 6-pin header with SCK, MISO, MOSI, RESET, VCC, and GND. As long as that device programming header is available, then no matter what your bootloader does, an attacker could connect to those signals with an external device programmer, and load their own firmware directly. (This is not only an Arduino platform issue; most microcontrollers have an equivalent in-circuit debugging or programming interface. ARM core CPUs have CMSIS/DAPLINK which is used for firmware loading, and JTAG is also commonly used.)
There are frequently questions on this site where people ask how to reprogram various boards, whether garage door openers or washing machines or calculators or anything with any kind of microchip on it. So if your hardware is released in the wild, it's likely at some point someone will try to read or write your microcontroller's firmware. Most commercial products take the precaution of using microcontrollers that can lock against firmware being read out easily, by setting a one-time programmable &quot;fuse&quot; bit.
Even if you designed a custom PCB without that in-circuit programming header (and used ATmega328 chips that had firmware loaded prior to assembly, using a socketed external device programmer), all of the device pins are still exposed on the ATmega328 chip itself. A determined attacker with access to the hardware, could still contact those pins with a device programmer and gain control to execute arbitrary code on your board. It might be possible to shield against that type of physical attack by using epoxy potting compound to coat the chip with mechanically tough and electrically insulating material. This adds cost and also makes it impossible for you to update your own bootloader. And even that might not be enough to keep someone determined out.
That's just one small trace of the kind of nightmares a security researcher treads through. Every aspect of the system is potentially vulnerable to some kind of attack, if the attacker was lucky or determined enough. Add more armor against that particular type of attack, and now you have the cost and inconvenience of carrying that armor all the time. And even so, there are still vulnerabilities. So there is always consideration of cost versus benefit.
Ultimately, no matter how foolproof a system seems to be, someone always discovers some weird abnormal test case. See this recent question on stackoverflow meta: https://meta.stackoverflow.com/questions/404302/are-whitespace-only-display-names-allowed and its linked question which has a blank title consisting only of Unicode left-to-right and non-blanking-space characters, _____ and also discussed on meta here.