Pull to refresh

Comments 15

Как я понял, проблема в том, что драйвер (или ОС) выводит содержимое выделенной области памяти на экран пользователя, отображая старое содержимое этой области. Если же отображение начиналось по команде приложения, когда загрузка данных в эту область уже произведена, то проблемы бы не возникло. Правильно я понял?
UFO just landed and posted this here
можно вообще на сайте где-нить в iframe крутить яваскрипт, который, используя webgl, будет слизывать содержимое VRAM пользователя и отсылать картинки на сервер.
Где-то уже можно посмотреть пример реализации?
В первоначальной статье была ссылка на баг. Там есть в аттачменте к исходному сообщению «chrome_vram_leak.zip». Написано на Go. Думаю, для тех, кто знает javascript, проблем переложить в браузерную версию не будет.
Многие приложения используют двойную буферизацию. Пока одна поверхность готовится/рендерится в не отображаемой области видеопамяти, на экран выводится другая. При этом, если приложение отдельно не озаботится очисткой дефолтной поверхности ее содержимое в начальный момент времени может содержать результаты работы предшественника. Поскольку первоначальная подготовка кадра может быть достаточно длительной, не очищенная поверхность может быть заметна глазу до переключения.

Драйвер и ОС в данном случае не брали на себя дополнительной ответственности за гарантирование очищения чужих кадров. Как оказалось, пользователям хром также этого не гарантировал, хотя это исключительно в его компетенции. Все остальные вариации решения проблемы не могут претендовать на универсальность и кросс-платформенность. Также это замечание справедливо для зануления оперативной памяти операционной системой.
Наблюдал схожую проблему в рамках одного приложения хрома — в tweetdeck. После разворачивания иллюстрации на фулскрин и отмены этого… все оставалось на месте. Приходилось водить курсором по всем тайлам экрана, чтобы они обновились
ОС должна следить за необходимостью того или иного приложения прибрать за собой (это либо некое маркирование защищаемых поверхностей, либо избыточное зануление любых поверхностей как в ОЗУ, так и в видеопамяти);

Именно так. Страницы памяти при передаче их другому приложению зануляет именно ОС, потому что приложение не имеет возможности их занулить. Почему для памяти в GPU должно быть иначе?
Потому что в данном случае приложение имеет возможность занулить. Более того, для фреймбуфера это делается одной командой.
Это как набросать мусора на лестнице, в надежде, что дворник уберет, вместо того, чтобы просто выбросить в мусоропровод.
Приложение имеет возможность прибрать за собой как в случае видеопамяти, так и в случае оперативной. Для первого варианта как справедливо отметил iSage, достаточно одной команды, с оперативной памятью чуть сложнее и несколько более затратно, но тем не менее осуществимо.

Вообще, мне не ясна природу утверждения о необходимости ОС передавать зануленные страницы. Есть возможность запрашивать при выделении памяти зануление (тривиальная функция calloc()/mmap() ), для обратных операций подобного требования к ОС и системной библиотеке нет — хотите занулить, зануляйте сами. Оно появляется только в процессе сертификации по определенному классу защищенности и в этом смысле идет речь о спец. средствах и спец. ОС. Работает оно обычно по принципу — сдох процесс, прикопаем с трупом его пожитки.
В современных операционных системах принято занулять память перед тем как отдать её приложению. Это это очень хорошо, так как при выполнении malloc «мусор» в буфере окажется мусором освобождённой памяти текущего приложения, а не какого-то другого. Зануление при освобождении, как правило, не происходит (в угоду производительности) и используется на параноидальных сборках ядра Linux с патчами PAX/Grsecurity.

Я на скорую руку переписал тест автора бага на Си: github.com/scriptum/vmem_test (go активно отказывался компилироваться). Проверил на двух драйверах под Linux: nouveau и nvidia 358.16. В драйвере nouveau эффект присутствует (да какой — данные сохраняются даже после перезагрузки), в случае же с последним актуальным проприетарным драйвером nvidia 358.16 — возвращается чёрный экран.

Достаточно обратиться к /dev/mem по известному из вывода утилиты «lspci» офсету.

Это очень плохая «фича». Я очень рад, что моя система запрещает обращаться к /dev/mem не только кому попало, но и руту. Так, на всякий случай.

Проблема в том, что непривилегированный процесс, используя штатные механизмы (в данном случае — запрос видеобуфера из памяти через OpenGL), может получить данные, которые ему не принадлежат.
В оригинальном коде на Go ещё затекстуренный полигон рисуется перед чтением vram. В комментах указано, что драйвера для оптимизации выкидывают вызовы если этого не делать. Видимо это ваш случай с проприетарными дровами.
Если я правильно понял, то эта оптимизация имеет отношение к блоку clearMemory, но не readpixels, к тому же автор оставил блок clearMemory опциональным. Мне же было интересно сохранить весь дамп VRAM для последующего изучения. Есть вероятность что драйвер «оптимизировал» также и чтение из только что аллоцированного пустого блока. Наверное, стоит попробовать рисовать небольшой прямоугольник поверх этого буфера, чтобы драйвер пометил его как «грязный». Попробую ещё потестить с разными драйверами.
Проверил на разных машинах. В драйвере 358 пофикшено, в 352 ещё не пофикшено (с помощью этой программы можно получить остаточные буферы памяти). В драйверах Intel и VESA проблемы нет.
Если интересно, там в баге хрома смогли воспроизвести и на интеле.
Sign up to leave a comment.

Articles