Linux не позволяет изменить файл запущенной программы потому, что он не всегда загружается в оперативную память полностью, а может быть считан с диска в разные моменты выполнения программы.
Прямым ответом на ваш вопрос:
при fork-e копируется основная программа и не высвобождается handler исполняемого файла, что необходимо достичь
Будет копирование всех заmap'ленных сегментов в оперативную память, правильная настройка памяти, и munmap() оригинальных маппингов.
Самый простой вариант «выполнения execve не через файл» — использование вызова memfd_create для создания «файла» полностью в оперативной памяти (Linux 3.17+).
Вот здесь этот подход описан подробно.
Альтернативные универсальные варианты — написание собственного загрузчика ELF/PE, вместо использования execve.
Либо просто сожмите файл upx'ом, его загрузчик сам загрузит файл в оперативную память целиком, без файловых mmap'ов.
Непонятно, какую задачу вы хотите решить изначально. Вы можете просто удалить файл rm'ом, затем создать на его месте новый, с таким же названием, и в него уже писать новое содержимое.
Если задача в редактировании кода или данных программы на лету, то это можно сделать непосредственно в памяти, путем записи в /proc/PID/mem.