Или нет? Например, сейчас вовсю набирают популярность языки, где возможность "обратиться не туда" исключается самим языком: достаточно отказаться от указателей внутри языка (вместо них ввести какие-нибудь высокоуровневые "ссылки"), ввести принудительную проверку индексов массивов и приравненных к ним сущностей, а чтобы не делать лишние проверки где не надо - максимально "обернуть" типовые действия над множествами объектов разнообразными "итераторами" и прочими примочками. И, собственно, всё - если язык by design не позволяет совершать такого типа ошибки, а компилятор исправен и не допускает их сам - полученный машинный код можно запускать "без защиты", ошибки в нём могут быть, но только внутренние, не мешающие остальным. Проблема получается только в том, что не весь код создаётся именно этим, "правильным", компилятором, на "правильном" языке (а возвращаясь к "вредоносным программам" - кто-то может создать "неправильный" код непосредственно в коде, минуя компилятор), а значит совсем отказаться от аппаратной защиты как бы опять же... или таки нет?
А что если попробовать возродить что-то вроде UCSD P-System, но на новом уровне? Для начала - разрабатываем "относительно низкоуровневый" псевдокод (вроде того же UCSD P-code или Java bytecode), в который можно оттранслировать программу на любом интересующем нас языке, но при этом обладающий тем свойством, что в рамках этого псевдокода нельзя обратиться к не принадлежащему тебе объекту - просто потому что нет метода это сделать, как, например, нет метода обратиться к произвольной ячейке памяти в языках без указателей. Помнится, Великий и Ужасный dz когда-то упоминал (жаль, без подробностей) архитектуру Intel 432, где в самом машинном коде просто не было способа создать указатель из числа - только получить его извне, а значит и обратиться "не туда" программа не могла, ввиду отсутствия метода это сделать. (Как я понимаю, "метод создать указатель" там всё-таки был, но он был доступен только на определенном уровне привилегий - грубо говоря, "только ОС и доверенный код" - раз уж указатели предусмотрены архитектурой, кто-то же их должен порождать). А значит, "тьюринг-полный" псевдокод, застрахованный от ошибок вида "обратился к чужому", придумать можно.
А дальше - очень просто. Программы распространяются не в "бинарниках" с машинным кодом, а в псевдокоде. Принесённый извне (скопированный) бинарник с машинным кодом ОС игнорируется - "это не моё, запускать не буду", при первом запуске программы в псевдокоде - из него генерируется бинарник в машинном коде (заведомо не содержащий ошибок вида "обратиться к чужому", в силу устройства псевдокода), и именно он уже запускается. Сгенерированный бинарник с машинным кодом на уровне ОС доступен пользователю только на просмотр и удаление, изменение разрешено только самой ОС - а значит хотя в машинном коде и могли бы содержаться ошибки вида "обращение к чужому", взяться им там неоткуда: ОС генерирует код без ошибок, а подменить машинный код на ошибочный так просто не получится - ОС защищает файл.
При "добропорядочном" использовании системы этого уже достаточно: принесённые извне бинарники с машинным кодом не запускаются (а по потребности - пересоздаются из псевдокода), лежащие на локальных несменных дисках бинарники с машинным кодом защищены от изменения средствами самой ОС. На втором уровне паранойи ("а мы теперь такие загрузимся с дискетки и таки подменим бинарник с маш. кодом") можно предусмотреть, например, "подписывание" бинарников этой копией ОС, и даже их перегенерацию из псевдокода при запуске после перезагрузки системы, но это уже подробности - если не заглубляться в рассуждения, как ещё можно обмануть ОС, если поставить себе цель, то достаточную безопасность обеспечить можно, а если заглубиться - так имея физический доступ к диску всегда можно обойти любую защиту, вопрос только в сложности.
В результате мы получаем операционную систему, с возможностью разработки приложений на большинстве языков (на всех тех, что допускают компиляцию в наш псевдокод), способную обеспечить защиту памяти не хуже других ОС, при этом работающую даже на процессорах, не имеющих аппаратных средств защиты (хоть, простигосподи, 8086 какой-нибудь), и работающую быстро - используется не интерпретация псевдокода, а выполнение машинного кода на реальном процессоре. Сейчас, когда с одной стороны довольно мощные системы вовсю "лезут в карман" (используются в портативных применениях), а с другой стороны - активно идёт разработка новых платформ (пусть даже наворачиванием очередного слоя обёртки на уже существующие, главное что разработчики уже спокойно относятся к частой смене платформ), возможность без проблем выкинуть из процессора сколько-то "лишних" транзисторов и "лишних" проверок при выполнении - может оказаться востребованной.
...А теперь скажите мне, какой велосипед я на этот раз изобрёл? Не верю, что с момента изобретения p-code никто не пытался сформулировать эту идею именно так :-)