I am interested in the fork() use case.
1) After fork, the kernel creates a new PCB for the child process. It changes the permission of all page table entries in the parent to be read-only. It then copies the page directories and table of the parent in the new child PCB. Is this correct? Or do the parent and child process share them?
2) How does the kernel know the actual permission of the pages if it changes all them to be read only after copying them?
I think the opinions in the 1) is correct, during fork(), kernel will create a new task_struct for the child process, and copy the mm_struct and page table, it shares resources with parent process which depends on the clone_flags. And it will invalidate the MMU entries which is_cow_mapping() and marks the related page table entries to read only.
The answer to 2): The kernel only change page table entries which is_cow_mapping() to read only, when child or parent want to access these address ranges, kernel will duplicate and marked to read/write.
If exec() is called after fork(), a totally new virtual space will be setup, the older one which is copied from parent is discarded.