...

суббота, 3 ноября 2018 г.

«Самоуничтожающаяся» бета Fallout 76

image
«Игроки PC #Fallout76 B.E.T.A.: Мы в курсе проблемы с клиентом и разбираемся с ней. Пожалуйста, не нажимайте пока никаких кнопок в клиенте-лаунчере.»
— Поддержка Bethesda (@BethesdaSupport) Октябрь 30, 2018
Поучительная история, наделавшая немало шуму, приключилась на этой неделе с компанией Bethesda. Игры Bethesda всегда славились большим количеством багов; сегодня компания по-прежнему продолжает следовать заветам Buggerfall (TES II Daggerfall) и, кажется, на этот раз смогла выйти на новый уровень.

Речь идет о старте бета-теста PC-версии Fallout 76 — многопользовательском спин-оффе известной ролевой серии, больше напоминающему по своему духу Rust – который состоялся на этой неделе, 30 октября. По факту, бета представляла собой стресс-тест из четырех коротких сессий длительностью 4-5 часов — и стресс-тестом (для CDN и пользователей) ее можно назвать не только в прямом, но и в переносном смысле.

Разработчики умудрились просмотреть в лаунчере игры баг, из-за которого ее клиент самовольно удалял все файлы игры с компьютера пользователя при запуске лаунчера и/или клику по любой кнопке в нем. В результате, когда долгожданная бета (ради которой игроки и оформляли предзаказ) наконец стартовала, десятки тысяч пользователей, загрузивших игру заранее, были вынуждены снова целиком скачивать установочные файлы игры (почти 50 гБ), причем скорость скачивания упала до минимальных значений (около 1Mb/s). Когда 4 часа спустя бета закончилась, большинство из них в итоге так и не смогло попасть в Fallout 76.

Если учесть, что всего неделю назад компания разослала игрокам-подписчикам письмо, в котором предупреждала, что в бете им предстоит столкнуться с невиданными доселе багами, то можно сказать, что Bethesda не подвела.

Суть проблемы


Когда компания Bethesda анонсировала свою новую игру Fallout 76 на выставке E3, то сразу объявила, что на этот раз для распространения игры Steam использоваться не будет — вместо него компания решила использовать собственный лаунчер Bethesda.net.

Причина такого решения очевидна — при таком подходе Bethesda не нужно платить отчисления Valve — для крупных компаний, издающих в Steam AAA-игры, это около 20-25% (все зависит от контракта с конкретной компании — но меньше, чем для большинства разработчиков). Впрочем, директор компании Пит Хайнс заявил, что это решение было принято с целью «упрощения коммуникации с сообществом игроков» — поскольку теперь игроки должны были обращаются с фидбеком напрямую на форумы Bethesda, минуя форумы (и обзоры) Steam.

Общественность некоторое время сильно возмущалась тем, что теперь игрокам придется держать у себя на компьютере еще один лаунчер, и за счет этого пророчила игре провал в продажах. Забегая вперед, можно сказать, что самые пессимистические прогнозы не оправдались — судя по весьма оживленному форуму, игра уже успела вызвать некоторый ажиотаж; к тому же в самой Fallout 76 активно используются ассеты и игровые механики Fallout 4, что значительно снижает стоимость производства подобного эксперимента. Последнее неудивительно, ведь бытует мнение, что этим проектом Bethesda прощупывает почву для использования модели «игра-как-сервис» в своих последующих проектах — ведь сложно придумать, куда еще можно было бы портировать Skyrim после Amazon Alexa.

Казалось бы, лаунчер и инфраструктуру можно было обкатать год назад — во время бета-тестирования Quake Champions, участники которого жаловались на различные проблемы еще тогда — но, судя по всему, их было решено полностью проигнорировать.

И вот назначенный день X для PC-игроков наконец-то настал. Тех, кто следил за таймером обратного отсчета в лаунчере игры, первое разочарование ждало уже тогда, когда выяснилось, что таймер отработал на два часа раньше положенного — кнопка «Играть» разблокировалась, однако, запустить игру не удавалось.

По проблеме таймера Bethesda отреагировала достаточно быстро и дала разъяснение: дескать, программист, отвечавший за таймер обратного отсчета, живет по Mountain Standard Time (MST), горному времени (это время, соответствующее часовому поясу Горных штатов, одному из семи часовых поясов США; оно на два часа позже Восточного поясного времени) — добавив, что этого программиста уже сбросили до «заводских настроек», и подобное не должно повториться.

Однако, начиная с этого момента, лаунчеры игроков стали массово стирать уже установленную игру и загружать установочные файлы снова. Столкнувшись с тысячами недовольных игроков, компания отреагировала тем самым твитом, который процитирован в начале поста. «Пожалуйста, не нажимайте никаких кнопок в лаунчере». Он, увы, теперь удален — но быстро разлетелся по сети, и его оригинал можно увидеть, например, в статье Kotaku.

Впрочем, по свидетельствам игроков, нажимать было ничего и не надо — достаточно было просто запустить лаунчер, как файлы игры исчезали или затирались. Те, кто узнал о проблеме раньше и успел сделать резервную копию файлов, пытались подсунуть их лаунчеру, но их тоже ждало разочарование — потратив полчаса на проверку этих файлов, лаунчер все равно начинал скачивать файлы установки с нуля.

Здесь расстроенных игроков ждал очередной подвох. Скорость скачивания внезапно упала до 0.5-1 MB/s — и ни у кого из них не осталось практически ни единого шанса скачать клиент за отведенные на бету 4 часа.

image

Спустя пару часов техподдержка компании опубликовала твит, в котором утверждалось, что проблема устранена — однако раздраженные игроки продолжали жаловаться на трудности с загрузкой игры, и его быстро удалили.

И даже на этом мучения отдельных пользователей не закончились. По окончанию скачивания файлов лаунчер мог выдать ошибку «Недостаточно прав для установки игры в выбранную директорию», после чего… думаю, вы уже и так догадались. В конечном итоге, отдельные «счастливчики» были вынуждены выкачать клиент полностью 3 раза.

Закончилось все тем, что Bethesda расширила период следующего дня бета-теста расширили на четыре часа.

Возможные причины и стоимость ошибки


К сожалению, никакой официальной информации о причине ошибки от компании так и не поступило, однако есть некоторые предположения.

На самом деле, она может быть вполне тривиальной — скорее всего, неправильно отработал механизм обновления игры. Допустим, в обновлении требовалось заменить поддиректорию, и для этого требовалось ее рекурсивно удалить, распаковав сюда же новую папку. И способов «накосячить» здесь было более, чем достаточно: перенос файлов мог отработать с ошибкой; где-то мог быть неправильно прописан относительный путь к папке; неправильно была задана переменная окружения или указан путь; для беты могли быть установлены специальные временные флаги в коде, которые забыли сбросить…

Попробуем примерно подсчитать, сколько эта ошибка могла стоить Bethesda. В качестве CDN Bethesda использует AWS CloudFront. Можно предположить, что такое сильное падение скорости скачивания было связано с throttling и некорректно настроенными параметрами конфигурации. Допустим, компания платит 0.10$/Gb; каждый человек, который загружает игру, стоит им примерно 50 центов. Если, допустим, загружать игру заново пришлось миллиону человек, то это ошибка обошлась компании в 500 000 $. Вопрос здесь в том, какое число пользователей это затронуло — и ответить на него трудно. Для сравнения, Fallout 4 за первые 24 часа после релиза на Steam продался тиражом в 1.2 миллиона копий, пиковое число пользователей составило 470 000 человек.

И это даже не считая отмененных раздраженными покупателями предзаказов цифровых и физических копий игры, которые ради возможности поиграть в бету брали отгул с работы.

Постскриптум


Справедливости ради, стоит отметить, что Bethesda вовсе не первопроходцы в данном «жанре» — истории известны и более серьезные ошибки.

Старожилы Хабра могли слышать о проблеме обновления EVE Online, которое удаляло у игроков файл C:\boot.ini. За нее разработчики из CCP извинились, заодно подробно рассказав о причине ошибки.

В свое время, первый Half-Life (в релизной версии 1.0, которая была записана на диске) включал в себя Sierra Utilities, которые при деинсталляции игры удаляли не только папку, в которую была установлена сама игра, но еще и ее родительскую директорию. Нетрудно представить, какая «радость» поджидала тех, у кого была установлена в c:\games\HL, c:\program files\hl или c:\hl

Let's block ads! (Why?)

Настройка окружения в Docker для yii-framework приложения

Для того чтобы быстро поднять рабочее окружение существует много способов. Один из них — поднять все необходимые сервисы в Docker-контейнерах. Чтобы ускорить создание новых проектов на Yii-framework я написал такую небольшую инструкцию, которую используют разработчики в нашей команде.

На старте у вас должны стоять docker, docker-compose, php и php-composer.
Создаем папку с проектом и в ней папку docker.

mkdir project-dir 
cd project-dir && mkdir docker

В папке docker создаем файл конфигурации нашего контейнера Dockerfile.

# Базовый образ с nginx и php
FROM richarvey/nginx-php-fpm

# ДОбавляем наше веб приложение
ADD app /var/www/app

# Удаляем конфиги сайтов которые там есть
RUN rm -Rf /etc/nginx/sites-enabled/*

# Добавляем наш конфиг
ADD docker/conf/nginx/site.conf /etc/nginx/sites-available/site.conf
# Включаем его
RUN ln -s /etc/nginx/sites-available/site.conf /etc/nginx/sites-enabled/site.conf

В этой же папке docker создаем docker-compose.yml для поднятия окружения разработки.

# Последняя версия docker-compose
version: '3'

# Создаем общую сеть deafult для всех контейнеров
networks:
  default:
    driver: bridge

# Создаем отдельные контейнеры
services:
  # Контерйнер с веб-приложением
  app:
    # Собираем из Dockerfile 
    build: 
      # Корнем указываем корень основного проекта
      context: ../
      dockerfile: ./docker/Dockerfile
    # Показываем наружу 80 порт
    ports: 
      - "80:80"
    # Подключаем к общей сети с другими контейнерами
    networks: 
      - default
    # Запускаем только после db
    depends_on: 
      - db    
    # Линкуем внешнюю папку с исходниками внутрь
    volumes:
      - "../app:/var/www/app"
      # Так же линкуем конфиг для nginx
      - "./conf/nginx:/etc/nginx/sites-available"      
  # Контейнер с базой данных
  db:
    image: mysql:latest
    # Подключаем к общей сети с другими контейнерами
    networks: 
      - default
    # Показываем наружу порт
    ports:
      - "3336:3306"
    # Задачем параметры для инициализации БД
    environment:
      # Пароль к БД
      MYSQL_ROOT_PASSWORD: root
      # Создаваемая по умолчанию бд
      MYSQL_DATABASE: yii-template-db
    # Линкуем внешнюю папку для хранения БД
    volumes:
      - "./database:/var/lib/mysql"

Для nginx создаем папку docker/conf/nginx и файл site.conf в ней. Файлик может изменяться, в зависимости от того, как вы хотите настроить nginx на своем проекте. Его можно менять локально, т.к. он подключается через volume. Но надо не забывать внутри контейнера перезагружать nginx: nginx -s reload

server {
    charset utf-8;
    client_max_body_size 128M;

    listen 80; ## listen for ipv4

    root        /var/www/app/frontend/web/;
    index       index.php;

    access_log  /var/www/app/log/frontend-access.log;
    error_log   /var/www/app/log/frontend-error.log;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # uncomment to avoid processing of calls to non-existing static files by Yii
    #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
    #    try_files $uri =404;
    #}
    #error_page 404 /404.html;

    # deny accessing php files for the /assets directory
    location ~ ^/assets/.*\.php$ {
        deny all;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        try_files $uri =404;
    }

    location ~* /\. {
        deny all;
    }
}

Все команды выполняются из корневой папки.


  • Выполняем команду создания проекта composer create-project --prefer-dist yiisoft/yii2-app-advanced app.
  • Запускаем окружение docker-compose -f docker/docker-compose.yml up -d
  • Инициализируем проект app/init --env=Development --overwrite=All
  • Открываем в редакторе файл app/common/config/main-local.php и заполняем его даными для подключения к БД. В примере у нас пароль root — root, хост БД — db, имя БД — yii-template-db.
  • Подключаемся к контейнеру docker exec -it docker_app_1 bash
  • Выполняем команду миграции БД php /var/www/app/yii migrate
  • Создаем папку для логов mkdir /var/www/app/log
  • И выходим exit
  • Тормозим сервис docker-compose -f docker/docker-compose.yml down
  • Запускаем его заново docker-compose -f docker/docker-compose.yml up -d
  • Открываем localhost в браузере и смотрим на новый сайт.

Let's block ads! (Why?)

Building client routing / semantic search at Profi.ru


TLDR

This is a very short executive summary (or a teaser) about what we managed to do in approximately 2 months in the Profi.ru DS department (I was there for a bit longer, but onboarding myself and my team was a separate thing to be done at first).


Projected goals


  1. Understand client input / intent and route clients accordingly (we opted for input quality agnostic classifier in the end, though we considered type-ahead char level models and language models as well. Simplicity rules);
  2. Find totally new services and synonyms for the existing services;
  3. As a sub-goal of (2) — learn to build proper clusters on arbitrary external corpuses;

Achieved goals

Obviously some of these results were achieved not only by our team, but by several teams (i.e. we obviously did not do the scraping part for domain corpuses and the manual annotation, though I believe scraping can be also solved by our team — you just need enough proxies + probably some experience with selenium).

Business goals:


  1. ~88+% (vs ~60% with elastic search) accuracy on client routing / intent classification (~5k classes);
  2. Search is agnostic to input quality (misprints / partial input);
  3. Classifier generalizes, morphologic structure of the language is exploited;
  4. Classifier severely beats elastic search on various benchmarks (see below);
  5. To be on the safe side — at least 1,000 new services were found + at least 15,000 synonyms (vs. the current state of 5,000 + ~30,000). I expect this figure to double of even triple;

The last bullet is a ballpark estimate, but a conservative one.
Also AB tests will follow. But I am confident in these results.

"Scientific" goals:


  1. We thoroughly compared many modern sentence embedding techniques using a downstream classification task + KNN with a database of service synonyms;
  2. We managed to beat weakly supervised (essentially their classifier is a bag-of-ngrams) elastic search on this benchmark (see details below) using UNSUPERVISED methods;
  3. We developed a novel way of building applied NLP models (a plain vanilla bi-LSTM + bag of embeddings, essentially fast-text meets RNN) — this takes the morphology of the Russian language into consideration and generalizes well;
  4. We demonstrated that our final embedding technique (a bottle-neck layer from the best classifier) combined with state-of-the-art unsupervised algorithms (UMAP + HDBSCAN) can produce stellar clusters;
  5. We demonstrated in practice the possibility, feasibility and usability of:
    • Knowledge distillation;
    • Augmentations for text data (sic!);
  6. Training text-based classifiers with dynamic augmentations reduced convergence time drastically (10x) compared to generating larger static datasets (i.e. the CNN learns to generalize the mistake being shown drastically less augmented sentences);

Overall project structure

This does not include the final classifier.
Also in the end we abandoned fake RNN and triplet loss models in favour of the classifier bottleneck.


What works in NLP now?

A birds' eye view:

Also you may know that NLP may be experiencing the Imagenet moment now.


Large scale UMAP hack

When building clusters, we stumbled upon a way / hack to essentially apply UMAP to 100m+ point (or maybe even 1bn) sized datasets. Essentially build a KNN graph with FAISS and then just rewrite the main UMAP loop into PyTorch using your GPU. We did not need that and abandoned the concept (we had only 10-15m points after all), but please follow this thread for details.


What works best


  • For supervised classification fast-text meets the RNN (bi-LSTM) + carefully chosen set of n-grams;
  • Implementation — plain python for n-grams + PyTorch Embedding bag layer;
  • For clustering — the bottleneck layer of this model + UMAP + HDBSCAN;

Best classifier benchmarks

Manually annotated dev set

Left to right:
(Top1 accuracy)


  • Current algorithm (elastic search);
  • First RNN;
  • New annotation;
  • Tuning;
  • Fast-text embedding bag layer;
  • Adding typos and partial input;
  • Dynamic generation of errors and partial input (training time reduced 10x);
  • Final score;

Manually annotated dev set + 1-3 errors per query

Left to right:
(Top1 accuracy)


  • Current algorithm (elastic search);
  • Fast-text embedding bag layer;
  • Adding typos and partial input;
  • Dynamic generation of errors and partial input;
  • Final score;

Manually annotated dev set + partial input

Left to right:
(Top1 accuracy)


  • Current algorithm (elastic search);
  • Fast-text embedding bag layer;
  • Adding typos and partial input;
  • Dynamic generation of errors and partial input;
  • Final score;

Large scale corpuses / n-gram selection


  • We collected the largest corpuses for the Russian language:
    • Areneum — a processed version is available here — dataset authors did not reply;
    • Taiga;
    • Common crawl and wiki — please follow these articles;
  • We collected a 100m word dictionary using 1TB crawl;
  • Also use this hack to download such files faster (overnight);
  • We selected an optimal set of 1m n-grams for our classifier to generalize best (500k most popular n-grams from fast-text trained on Russian Wikipedia + 500k most popular n-grams on our domain data);

Stress test of our 1M n-grams on 100M vocabulary:
image


Text augmentations

In a nutshell:


  • Take a large dictionary with errors (e.g. 10-100m unique words);
  • Generate an error (drop a letter, swap a letter using calculated probabilities, insert a random letter, maybe use keyboard layout, etc);
  • Check that new word is in dictionary;

We brute forced a lot of queries to services like this one (in attempt to essentially reverse engineer their dataset), and they have a very small dictionary inside (also this service is powered by a tree classifier with n-gram features). It was kind of funny to see that they covered only 30-50% of words we had on some corpuses.

Our approach is far superior, if you have access to a large domain vocabulary.


Best unsupervised / semi-supervised results

KNN used as a benchmark to compare different embedding methods.

(vector size) List of models tested:


  • (512) Large scale fake sentence detector trained on 200 GB of common crawl data;
  • (300) Fake sentence detector trained to tell a random sentence from Wikipedia from a service;
  • (300) Fast-text obtained from here, pre-trained on araneum corpus;
  • (200) Fast-text trained on our domain data;
  • (300) Fast-text trained on 200GB of Common Crawl data;
  • (300) A Siamese network with triplet loss trained with services / synonyms / random sentences from Wikipedia;
  • (200) First iteration of embedding bag RNN's embedding layer, a sentence is encoded as a whole bag of embeddings;
  • (200) Same, but first the sentence is split into words, then each word is embedded, then average is taken;
  • (300) The same as above but for the final model;
  • (300) The same as above but for the final model;
  • (250) Bottleneck layer of the final model (250 neurons);
  • Weakly supervised elastic search baseline;

default

To avoid leaks, all the random sentences were randomly sampled. Their length in words was the same as the length of services / synonyms they were compared with. Also measures were taken to make sure that models did not just learn by separating vocabularies (embeddings were frozen, Wikipedia was undersampled to make sure that there was at least one domain word in each Wikipedia sentence).


Cluster visualization

3D

2D


Cluster exploration "interface"

Green — new word / synonym.
Gray background — likely new word.
Gray text — existing synonym.


Ablation tests and what works, what we tried and what we did not


  1. See the above charts;
  2. Plain average / tf-idf average of fast-text embeddings — a VERY formidable baseline;
  3. Fast-text > Word2Vec for Russian;
  4. Sentence embedding by fake sentence detection kind of works, but pales in comparison with other methods;
  5. BPE (sentencepiece) showed no improvement on our domain;
  6. Char level models struggled to generalize, despite the recant paper from google;
  7. We tried multi-head transformer (with classifier and language modelling heads), but on the annotation available at hand it performed roughly the same as plain vanilla LSTM-based models. When we migrated to embedding bad approaches we abandoned this line of research due to transformer's lower practicality and impracticality of having a LM head along with embedding bag layer;
  8. BERT — seems to be overkill, also some people claim that transformers train literally for weeks;
  9. ELMO — using a library like AllenNLP seems counter productive in my opinion both in research / production and education environments for reasons I will not provide here;

Deploy

Done using:


  • Docker container with a simple web-service;
  • CPU-only for inference is enough;
  • ~2.5 ms per query on CPU, batching not really necessary;
  • ~1GB RAM memory footprint;
  • Almost no dependencies, apart from PyTorch, numpy and pandas (and web server ofc).
  • Mimic fast-text n-gram generation like this;
  • Embedding bag layer + indexes as just stored in a dictionary;

Let's block ads! (Why?)

Blizzard анонсировала выход переиздания WarCraft III в 2019 году. Открыт предзаказ

Вчера вечером на игровой выставке BlizzCon компания Blizzard анонсировала выход ремастера своей легендарной RTS WarCraft III. В новую версию игры под названием WarCraft III: Reforged войдут оригинальные кампании двух предыдущих версий игры — Reign of Chaos и Frozen Throne.

Кроме этого в игру «завезут» полностью переработанные модели персонажей, новую анимацию, фиксы кампаний, обновленный редактор карт и поддержку 4K. Еще разработчики обещают внести изменения в баланс игры, так что, вполне возможно, старые тактики и стратегии, которые нарабатывались игроками годами, работать уже не будут. Выход обновленного WarCraft III состоится в 2019 году. Стоит это счастье от 1299 до 3499 RUB по предзаказу.
WarCraft III ожидаемо повторил судьбу StarCraft, о переиздании которого я сообщал полтора года назад. Blizzard активно перерабатывает свои легендарные проекты. Первым пробным камнем стал StarCraft, после нам анонсировали выпуск ваниллы World Of WarCraft (согласно информации с BlizzCon выход состоится летом 2019 года), а теперь — WarCraft III.

Вступительный ролик

Трейлер кампании

Предварительный трейлер геймплея

Качественное переиздание любимых игр — это всегда приятно, но знающие люди обратили внимание на два факта: новый баланс и новый редактор карт.

Объективно, Blizzard который год пытается полноценно вступить в мир киберспорта, но ее постоянно преследуют неудачи. StarCraft из-за своей чудовищной популярности среди корейцев стал их локальной дисциплиной, не получив широкого распространения на западе, Hearthstone — ККИ по вселенной WarCraft давала надежды на доминацию в этом сегменте, но множественные невоздержанные обновления и слишком частые изменения баланса привели к упадку дисциплины. На это указывает минимум то, что большинство киберспортивных организаций отказались от «подписания» профессиональных игроков в HS. «Убийца доты» Heroes of the Storm так и не смог перебороть Dota 2 и LoL, находясь по популярности на твиче где-то рядом со StarCraft с показателем в 3-5 тысяч зрителей.

Новый WarCraft III с обновленным балансом может стать «золотым билетом» Blizzard на рынок киберспорта. Эта игра была популярна по всему миру, в прошлом профессиональные игроки все еще проводят стримы по игре для самых ярых фанатов и записывают видео геймплея для YouTube.

Кроме этого, WarCraft проще для восприятия, нежели StarCraft, хотя бы из-за меньшего количества юнитов. Киберспортивные партии в WarCraft редко переходят в режим «глубокого лейта», то есть количество юнитов на карте заметно ограничено по сравнению с тем же StarCraft. Плюс у игры есть огромная фанатская база в лице игроков в WoW и HS.

Новый же редактор карт дает надежду на возрождение культуры кастомных карт, которые так полюбились пользователям. Если опустить DotA, то можно вспомнить многочисленные TD (YOU TD, Maffa TD, Element TD, Legion TD), карты-арены (Angel Arena, Life in Arena, Footman Frenzy) и даже карты, которые задумывались изначально как шутка (Петросянщина). Все это — сюжетные приключения, созданные пользователями, масса контента, которая была похоронена под старым движком, не самым удобным редактором карт и особенностями сетевого режима. Часть этого контента сообщество попыталось возродить в кастомных картах Dota 2, но широкой популярности они не получили из-за давления со стороны «титульного» режима. Переиздание WarCraft может вернуть весь этот контент, чего минимум автор статьи очень бы хотел.

Ну и конечно же, мы все еще ждем WarCraft 4.


Так как о покойниках либо хорошо, либо ничего, о Diablo: Immortal на мобильных устройствах, которая была анонсирована там же, на BlizzCon, почитайте сами.

Let's block ads! (Why?)

[Перевод] Закон об авторских правах только что стал немного лучше с точки зрения истории видеоигр

В нескольких актах подряд Библиотека Конгресса США обозначила решения, которые помогут движению архивации и сохранения видеоигр


Новые постановления Библиотеки Конгресса принесли хорошие новости для дела сохранения старых видеоигр. В 85-страничном акте, покрывающем всё, от пультов управления электронными летательными аппаратами до ПО для диагностики сельскохозяйственного оборудования, Библиотека Конгресса описала разрешения на "добросовестное использование" видеоигр и ПО, попадающих под Закон об авторском праве в цифровую эпоху (Digital Millennium Copyright Act, DMCA). Эти разрешения облегчат жизнь архивариусам, сохраняющим исторические видеоигры, и музеям, выставляющим культурное наследие на всеобщее обозрение.

«Реестр поддерживает расширение прав на владение ПО в достаточно специфических случаях, когда организация, занимающаяся сохранением интеллектуального наследия, легально владеет копией серверного кода видеоигры и локальным кодом игры», — указано в заявлении Библиотеки. «При таких условиях действия, направленные на сохранение наследия, вероятно, считаются добросовестным использованием».
Эти правила стали хорошей новостью для однопользовательских игр. «Крупное изменение, Касающееся однопользовательских игр, произошло во время последнего пересмотра правил DMCA в 2015 году, когда Министерство интеллектуальной собственности определило, что музеи и архивы имеют право взламывать процедуру онлайн-авторизации однопользовательских игр, которые пытались связаться с сервером исключительно в целях предотвращения нелегального копирования», — рассказал журналу Фил Сальвадор, библиотекарь и архивариус из Вашингтона, О.К., владелец сайта The Obscuritory, занимающегося обсуждением и сохранением малоизвестных старых игр. Этот пересмотр должен был закончить своё действие в этом году, но, благодаря давлению со стороны активистов, он был заново восстановлен.

«Эти постановления – большая победа», — сказала журналу Кендра Альберт, инструктор в Клинике киберюриспруденции при Гарвардской юридической школе. Альберт представляет сеть сохранения программного обеспечения (Software Preservation Network), одну из организаций, ратовавших за изменения в законах перед Министерством интеллектуальной собственности. «Постановления от 2015 года открыли путь для многих вещей, но выданные в данном случае разрешения оказались гораздо шире».

Эти новости должны понравиться архивариусам и музеям, давно пытавшимся найти наилучший способ сохранения таких видеоигр, как Everquest или World of Warcraft. Для подобных многопользовательских игр требуется как ПО, локально запускаемое игроками на их компьютерах, так и ПО, работающее на сервере компании. Последнее ПО архивариусам гораздо сложнее найти и запустить у себя. А когда им удаётся запустить независимый сервер, игровые компании, например, Blizzard, начинают юридическую атаку на людей, поддерживающих неавторизованные сервера.

Новые правила разочаруют среднего пользователя, надеявшегося, что в забытые игры снова можно будет поиграть, просто для развлечения. Альберт рассказала журналу, что Музей искусства и цифровых развлечений требовал включить в эти разрешения и «сотрудничающих архивариусов», что позволило бы частным лицам участвовать в деле сохранения ПО. «Министерство интеллектуальной собственности ответило на этот запрос отказом, — сказали они. – Думаю, что одна из причин их беспокойства связана с тем, что количество занимающихся этим людей должно оставаться относительно небольшим».

Однако для организаций, занимающихся такой работой, есть подвох: архивариусы и защитники интеллектуального наследия должны получить серверный код легальным методом, а это трудная задача.

Правила дают разрешение на использование только «полного комплекта» игр, что означает, что архивариус должен приобрести как код оригинальной игры, так и код оригинального сервера. И любая «библиотека, архив или музей», заставившая таким способом работать онлайн-игру, не сможет предоставлять к ней публичный доступ «вне своей физической площади». Это означает, что если музей запустит старую ММО, он не сможет выставить её для всемирной аудитории фанатов – в неё можно будет поиграть только посетителям или исследователям. Это ограничение частично перечёркивает смысл сохранения старых ММО, поскольку часть имиджа игр типа World of Warcraft заключается в том, что в неё одновременно играют тысячи людей – а это не получится сделать, если играть в неё можно будет только в музее.

Эмуляция, или воссоздание кода сервера для запуска многопользовательской игры также не попадает под список разрешённых DMCA действий – и это проблема. «Маловероятно, что кто-то сохранит серверный код, — сказал журналу Джон Харди, директор Национального музея видеоигр в Фриско, Техас. – Во всей нашей архивной практике ещё ни одна компания не сказала нам: „вот вам, пожалуйста, наш серверный код“. В девяти случаях из десяти серверный код не архивировался и не сохранялся. Его просто форматируют, или что-то типа того, или выбрасывают вместе с сервером».

Для таких игр, как World of Warcraft или исчезнувших MMO вроде City of Heroes, существуют частные сервера. Но они обычно работают не на легально полученном коде. Многие из них кропотливо восстанавливали работу серверного ПО, перехватывая пакеты и изучая другие данные. Такая эмуляция не попадает под действие новых постановлений о добросовестном использовании.

Особенным ударом решение о том, что эмуляция сервера не является допустимым исключением из DMCA, стало для Музея искусств и цифровых развлечений (Museum of Art and Digital Entertainment, MADE), помогавшего подавать эту петицию в совет по политике DMCA. MADE сейчас работает над восстановлением Habitat, онлайн-игры 1986 года от LucasArts, одного из самых ранних примеров виртуального мира в онлайне. Создатели игры присоединились к MADE для её восстановления с использованием оригинального кода и эмуляции компьютеров Commodore 64 и Quantum Link. Такая эмуляция серверного кода, если судить по нашему прочтению этих правил, не станет допустимым исключением из DMCA.

«В деле сохранения видеоигр есть ещё множество юридических проблем, но принятые правила устраняют некоторые из них, и это облегчит работу организаций по сохранению видеоигр, что очень важно, — сказала Альберт. – Также произошло то, чему традиционно препятствовала Ассоциация развлекательного программного обеспечения [Entertainment Software Association, ESA] (группа лоббистов, выступающая от лица производителей видеоигр). Эта победа – результат работы активистов из Сети сохранения программ и MADE. Важно отметить, что ESA не всегда была права в своих заявлениях».

Конечно стоит отметить, что, хотя новые правила можно считать победой, учитывая текущее состояние закона об интеллектуальной собственности, она заставляет задуматься, почему у нас идут такие жаркие споры по поводу права историков сохранять важные исторические артефакты, особенно учитывая, что игровые компании чаще всего не выполняют тяжёлую работу по их сохранению.

Как писала в журнала Сара Джеон в 2015:

Раздел DMCA 1201 превратился в очень странную кустарщину с нулевой суммой. НКО платят юристам за то, чтобы они швыряли своё время и энергию в чёрную дыру. В результате музеи видеоигр получают возможность сохранять видеоигры после тяжёлых и продолжительных боёв (с протестами ESA). Это нельзя назвать огромной победой, и мы должны задаться вопросом, зачем вообще нам пришлось сражаться за эту победу? Почему это вообще было изначально нелегально?

Let's block ads! (Why?)

[Перевод] Загрузка ядра Linux. Часть 1

От загрузчика к ядру

Если вы читали предыдущие статьи, то знаете о моём новом увлечении низкоуровневым программированием. Я написал несколько статей о программировании на ассемблере для x86_64 Linux и в то же время начал погружаться в исходный код ядра Linux.

Мне очень интересно разобраться, как работают низкоуровневые штуки: как программы запускаются на моём компьютере, как они расположены в памяти, как ядро управляет процессами и памятью, как работает сетевой стек на низком уровне и многое другое. Итак, я решил написать еще одну серию статей о ядре Linux для архитектуры x86_64.

Обратите внимание, что я не профессиональный разработчик ядра и не пишу код ядра на работе. Это всего лишь хобби. Мне просто нравятся низкоуровневые вещи и интересно в них копаться. Поэтому если заметите какую-то путаницу или появилятся вопросы/замечания, свяжитесь со мной в твиттере, по почте или просто создайте тикет. Буду благодарен.
Все статьи публикуются в репозитории GitHub, и если что-то не так с моим английским или содержанием статьи, не стесняйтесь отправить пулл-реквест.

Обратите внимание, что это не официальная документация, а просто обучение и обмен знаниями.

Необходимые знания

  • Понимание кода на C
  • Понимание кода ассемблера (синтаксис AT&T)

Во всяком случае, если вы только начинаете изучать такие инструменты, я постараюсь что-то объяснить в этой и следующих статьях. Окей, с вступлением закончили, пора погрузиться в ядро Linux и низкоуровневые вещи.

Я начал писать эту книгу во времена ядра Linux 3.18, и многое могло измениться с тех пор. Если есть изменения, я буду соответственно обновлять статьи.


Хотя это статьи о ядре Linux, мы пока не дошли до него — по крайней мере, в этом параграфе. Как только вы нажмете волшебную кнопку питания на своём ноутбуке или настольном компьютере, он начинает работать. Материнская плата посылает сигнал к блоку питания. После получения сигнала он обеспечивает компьютеру необходимое количество электроэнергии. Как только материнская плата получает сигнал «Питание в норме», то пытается запустить CPU. Тот сбрасывает все оставшиеся данные в своих регистрах и устанавливает предопределённые значения для каждого из них.

У процессоров 80386 и более поздних версий после перезагрузки должны быть такие значения в регистрах CPU:

IP          0xfff0
CS selector 0xf000
CS base     0xffff0000

Процессор начинает работать в реальном режиме. Давайте немного вернемся назад и попытаемся понять сегментацию памяти в этом режиме. Реальный режим поддерживается на всех x86-совместимых процессорах: от 8086 до современных 64-разрядных процессоров Intel. В процессоре 8086 используется 20-битная шина адресов, то есть он может работать с адресным пространством 0-0xFFFFF или 1 мегабайт. Но у него есть только 16-битные регистры с максимальным адресом 2^16-1 или 0xffff (64 килобайта).

Сегментация памяти нужна для использования всего доступного адресного пространства. Вся память делится на небольшие сегменты фиксированного размера по 65536 байт (64 КБ). Поскольку с 16-битными регистрами мы не можем обратиться к памяти выше 64 КБ, был разработан альтернативный метод.

Адрес состоит из двух частей: 1) селектор сегмента с базовым адресом; 2) смещение от базового адреса. В реальном режиме базовым адресом селектора сегмента является селектор сегмента * 16. Таким образом, чтобы получить физический адрес в памяти, нужно умножить часть селектора сегмента на 16 и добавить к нему смещение:

Физический адрес = Селектор сегмента * 16 + Смещение

Например, если у регистра CS:IP значение 0x2000:0x0010, то соответствующий физический адрес будет таким:
>>> hex((0x2000 << 4) + 0x0010)
'0x20010'

Но если взять селектор наибольшего сегмента и смещение 0xffff:0xffff, то получается адрес:
>>> hex((0xffff << 4) + 0xffff)
'0x10ffef'

то есть 65520 байт после первого мегабайта. Поскольку в реальном режиме доступен только один мегабайт, 0x10ffef становится 0x00ffef с отключенной линией A20.

Хорошо, теперь мы немного знаем о реальном режиме и адресации памяти в этом режиме. Вернемся к обсуждению значений регистров после сброса.

Регистр CS состоит из двух частей: видимого селектора сегментов и скрытого базового адреса. Хотя базовый адрес обычно формируется путём умножения значения селектора сегмента на 16, но во время аппаратного сброса селектор сегмента в регистре CS получает значение 0xf000, а базовый адрес — 0xffff0000. Процессор использует этот специальный базовый адрес, пока не изменится CS.

Начальный адрес формируется добавлением базового адреса к значению в регистре EIP:

>>> 0xffff0000 + 0xfff0
'0xfffffff0'

Мы получаем 0xfffffff0, что на 16 байт ниже 4 ГБ. Эта точка называется вектором сброса. Это расположение в памяти, где CPU ждёт первую инструкцию для выполнения после сброса: операцию перехода (jmp), которая обычно указывает на точку входа BIOS. Например, если посмотреть исходный код coreboot (src/cpu/x86/16bit/reset16.inc), мы увидим:
    .section ".reset", "ax", %progbits
    .code16
.globl  _start
_start:
    .byte  0xe9
    .int   _start16bit - ( . + 2 )
    ...

Здесь мы видим код операции (опкод) jmp, а именно 0xe9, и адрес назначения _start16bit - ( . + 2).

Мы также видим, что раздел reset составляет 16 байт, и он компилируется для запуска с адреса 0xfffff0 (src/cpu/x86/16bit/reset16.ld):

SECTIONS {
    /* Trigger an error if I have an unuseable start address */
    _bogus = ASSERT(_start16bit >= 0xffff0000, "_start16bit too low. Please report.");
    _ROMTOP = 0xfffffff0;
    . = _ROMTOP;
    .reset . : {
        *(.reset);
        . = 15;
        BYTE(0x00);
    }
}

Теперь запускается BIOS; после инициализации и проверки оборудования BIOS необходимо найти загрузочное устройство. Порядок загрузки сохраняется в конфигурации BIOS. При попытке загрузки с жёсткого диска BIOS пытается найти загрузочный сектор. На дисках с разметкой разделов MBR загрузочный сектор хранится в первых 446 байтах первого сектора, где каждый сектор равен 512 байтам. Последние два байта первого сектора — 0x55 и 0xaa. Они показывают BIOS, что это загрузочное устройство.

Например:

;
; Примечание: этот пример написан в синтаксисе ассемблера Intel x86
;
[BITS 16]

boot:
    mov al, '!'
    mov ah, 0x0e
    mov bh, 0x00
    mov bl, 0x07

    int 0x10
    jmp $

times 510-($-$$) db 0

db 0x55
db 0xaa

Собираем и запускаем:

nasm -f bin boot.nasm && qemu-system-x86_64 boot

QEMU получает команду использовать двоичный файл boot, который мы только что создали как образ диска. Так как двоичный файл, сгенерированный выше, удовлетворяет требованиям загрузочного сектора (начало в 0x7c00 и завершение магической последовательностью), то QEMU будет рассматривать двоичный файл как главную загрузочную запись (MBR) образа диска.

Вы увидите:

В этом примере мы видим, что код выполняется в 16-битном реальном режиме и начинается с адреса 0x7c00 в памяти. После запуска он вызывает прерывание 0x10, которое просто печатает символ !; заполняет оставшиеся 510 байт нулями и заканчивается двумя волшебными байтами 0xaa и 0x55.

Двоичный дамп можно посмотреть утилитой objdump:

nasm -f bin boot.nasm
objdump -D -b binary -mi386 -Maddr16,data16,intel boot

Конечно, в реальном загрузочном секторе — код для продолжения процесса загрузки и таблица разделов вместо кучи нулей и восклицательного знака :). С этого момента BIOS передаёт управление загрузчику.

Примечание: как объясняется выше, CPU находится в реальном режиме; где вычисление физического адреса в памяти происходит следующим образом:

Физический адрес = Селектор сегмента * 16 + Смещение

У нас только 16-битные регистры общего назначения, а максимальное значение 16-битного регистра 0xffff, поэтому на самых больших значениях результат будет:
>>> hex((0xffff * 16) + 0xffff)
'0x10ffef'

где 0x10ffef равно 1 МБ + 64 КБ - 16 байт. В процессоре 8086 (первый процессор с реальным режимом) 20-битная адресная линия. Поскольку 2^20 = 1048576, то фактически доступная память составляет 1 МБ.

В целом адресация памяти реального режима выглядит следующим образом:

0x00000000 - 0x000003FF – таблица векторов прерываний реального режима
0x00000400 - 0x000004FF - область данных BIOS
0x00000500 - 0x00007BFF - не используется
0x00007C00 - 0x00007DFF - наш загрузчик
0x00007E00 - 0x0009FFFF - не используется
0x000A0000 - 0x000BFFFF - память Video RAM (VRAM) 
0x000B0000 - 0x000B7777 - видеопамять монохромного режима
0x000B8000 - 0x000BFFFF - видеопамять цветного режима
0x000C0000 - 0x000C7FFF - Video ROM BIOS
0x000C8000 - 0x000EFFFF - теневая область (BIOS Shadow)
0x000F0000 - 0x000FFFFF - системный BIOS

В начале статьи написано, что первая инструкция для процессора находится по адресу 0xFFFFFFF0, что намного больше 0xFFFFF (1 МБ). Как CPU получить доступ к этому адресу в реальном режиме? Ответ в документации coreboot:

0xFFFE_0000 - 0xFFFF_FFFF: 128 килобайт ROM транслируются в адресное пространство

В начале выполнения BIOS находится не в RAM, а в ROM.


Ядро Linux можно загружать разными загрузчиками, такими как GRUB 2 и syslinux. В ядре есть протокол загрузки, который определяет требования к загрузчику для реализации поддержки Linux. В данном примере мы работаем с GRUB 2.

Продолжая процесс загрузки, BIOS выбрал загрузочное устройство и передал управление загрузочному сектору, выполнение начинается с boot.img. Из-за ограниченного объёма это очень простой код. Он содержит указатель для перехода к основному образу GRUB 2. Тот начинается с diskboot.img и обычно хранится сразу после первого сектора в неиспользуемом пространстве перед первым разделом. Приведённый выше код загружает в память остальную часть образа, который содержит ядро GRUB 2 и драйверы для обработки файловых систем. После этого выполняется функция grub_main.

Функция grub_main инициализирует консоль, возвращает базовый адрес для модулей, устанавливает корневое устройство, загружает/парсит конфигурационный файл grub, загружает модули и т.д. В конце выполнения она переводит grub в нормальный режим. Функция grub_normal_execute (из исходного файла grub-core/normal/main.c) завершает последние приготовления и показывает меню для выбора операционной системы. Когда мы выбираем один из пунктов меню grub, запускается функция grub_menu_execute_entry, которая выполняет команду grub boot и загружает выбранную ОС.

Как указано в протоколе загрузки ядра, загрузчик должен прочитать и заполнить некоторые поля заголовка установки ядра, который начинается со смещения 0x01f1 от кода установки ядра. Это смещение указано в скрипте линкера. Заголовок ядра arch/x86/boot/header.S начинается с:

    .globl hdr
hdr:
    setup_sects: .byte 0
    root_flags:  .word ROOT_RDONLY
    syssize:     .long 0
    ram_size:    .word 0
    vid_mode:    .word SVGA_MODE
    root_dev:    .word 0
    boot_flag:   .word 0xAA55

Загрузчик должен заполнить этот и остальные заголовки (которые помечены только как тип write в протоколе загрузки Linux, как в данном примере) значениями, которые получил из командной строки или рассчитал во время загрузки. Сейчас мы не будем подробно останавливаться на описаниях и пояснениях для всех полей заголовка. Позже обсудим, как ядро их использует. Описание всех полей см. в протоколе загрузки.

Как видим в протоколе загрузки ядра, память будет отображаться следующим образом:

         | Защищённый режим ядра  |
100000   +------------------------+
         | Отображение I/O        |
0A0000   +------------------------+
         | Зарезерв. для BIOS     | Как можно больше оставить свободным
         ~                        ~
         | Командная строка       | (также может находиться за отметкой X+10000)
X+10000  +------------------------+
         | Стек/куча              | Для использования кодом реального режима ядра
X+08000  +------------------------+
         | Установка ядра         | Код реального режима ядра
         | Загрузочный сектор ядра| Легаси-загрузочный сектор ядра
       X +------------------------+
         | Загрузчик              | <- Точка входа 0x7C00 загрузочного сектора
001000   +------------------------+
         | Зарезерв. для MBR/BIOS |
000800   +------------------------+
         | Обычно использ. MBR    |
000600   +------------------------+
         | Использ. только BIOS   |
000000   +------------------------+

Итак, когда загрузчик передаёт управление ядру, оно начинается с адреса:
X + sizeof (KernelBootSector) + 1

где X — адрес загрузочного сектора ядра. В нашем случае X равен 0x10000, как видно в дампе памяти:

Загрузчик перенёс ядро Linux в память, заполнил поля заголовка, а затем перешёл на соответствующий адрес памяти. Теперь мы можем перейти непосредственно к коду установки ядра.


Наконец-то мы в ядре! Хотя технически оно ещё не запущено. Сначала часть установки ядра должна кое-что настроить, в том числе декомпрессор и некоторые вещи с управлением памятью. После всего этого она распакует настоящее ядро и перейдёт к нему. Выполнение установки начинается в arch/x86/boot/header.S с символа _start.

На первый взгляд это может показаться немного странным, так как перед ним есть несколько инструкций. Но давным-давно у ядра Linux был собственный загрузчик. Теперь же если запустить, например,

qemu-system-x86_64 vmlinuz-3.18-generic

вы увидите:

Собственно, файл header.S начинается с магического числа MZ (см. скриншот дампа выше), текста сообщения об ошибке и заголовка PE:

#ifdef CONFIG_EFI_STUB
# "MZ", MS-DOS header
.byte 0x4d
.byte 0x5a
#endif
...
...
...
pe_header:
    .ascii "PE"
    .word 0

Он нужен для загрузки операционной системы с поддержкой UEFI. Его устройство рассмотрим в следующих главах.

Фактическая точка входа для установки ядра:

// header.S line 292
.globl _start
_start:

Загрузчик (grub2 и другие) знает об этой точке (смещение 0x200 от MZ) и переходит прямо к ней, хотя header.S начинается с раздела .bstext, где находится текст сообщения об ошибке:
//
// arch/x86/boot/setup.ld
//
. = 0;                    // current position
.bstext : { *(.bstext) }  // put .bstext section to position 0
.bsdata : { *(.bsdata) }

Точка входа установки ядра:
    .globl _start
_start:
    .byte  0xeb
    .byte  start_of_setup-1f
1:
    //
    // rest of the header
    //

Здесь мы видим код операции jmp (0xeb), который переходит к точке start_of_setup-1f. В нотации Nf, например, 2f ссылается на локальную метку 2:. В нашем случае это метка 1, которая присутствует сразу после перехода, и она содержит остальную часть заголовка setup. Сразу после заголовка установки мы видим раздел .entrytext, который начинается с метки start_of_setup.

Это первый фактически выполняемый код (кроме предыдущих инструкций перехода, конечно). После того, как часть установки ядра получает управление от загрузчика, первая инструкция jmp находится по смещению 0x200 от начала реального режима ядра, то есть после первых 512 байт. Это можно увидеть как в протоколе загрузки ядра Linux, так и в исходном коде grub2:

segment = grub_linux_real_target >> 4;
state.gs = state.fs = state.es = state.ds = state.ss = segment;
state.cs = segment + 0x20;

В нашем случае ядро загружается по адресу 0x10000. Это означает, что после запуска установки ядра регистры сегментов будут иметь следующие значения:

gs = fs = es = ds = ss = 0x10000
cs = 0x10200

После перехода к start_of_setup ядро должно сделать следующее:

  • Убедиться, что все значения регистров сегментов одинаковы
  • При необходимости настроить правильный стек
  • Настроить bss
  • Перейти к коду C в arch/x86/boot/main.с

Посмотрим, как это реализовано.
Прежде всего ядро проверяет, что регистры сегментов ds и es указывают на один и тот же адрес. Затем очищает флаг направления с помощью инструкции cld:
    movw    %ds, %ax
    movw    %ax, %es
    cld

Как я писал ранее, grub2 по умолчанию загружает код установки ядра по адресу 0x10000, а cs по адресу 0x10200, потому что выполнение начинается не с начала файла, а с перехода сюда:
_start:
    .byte 0xeb
    .byte start_of_setup-1f

Это смещение на 512 байт от 4d 5a. Также необходимо выровнять cs с 0x10200 до 0x10000, как и все остальные регистры сегментов. После этого устанавливаем стек:
    pushw   %ds
    pushw   $6f
    lretw

Эта инструкция помещает на стек значение ds, за ним следуют адрес метки 6 и инструкция lretw, которая загружает адрес метки 6 в регистр счётчика команд и загружает cs со значением ds. После этого у ds и cs будут одинаковые значения.
Почти весь этот код — часть процесса подготовки окружения для языка C в реальном режиме. Следующий шаг — проверить значение регистра ss и создать корректный стек, если значение ss неверное:
    movw    %ss, %dx
    cmpw    %ax, %dx
    movw    %sp, %dx
    je      2f

Это может инициировать три разных сценария:
  • у ss допустимое значение 0x1000 (как у всех остальных регистров, кроме cs)
  • у ss недопустимое значение, и флаг CAN_USE_HEAP установлен (см. ниже)
  • у ss недопустимое значение, и флаг CAN_USE_HEAP не установлен (см. ниже)

Рассмотрим все сценарии по порядку:
  • У ss допустимое значение (0x1000). В этом случае мы переходим к метке 2:
2:  andw    $~3, %dx
    jnz     3f
    movw    $0xfffc, %dx
3:  movw    %ax, %ss
    movzwl  %dx, %esp
    sti

Здесь мы устанавливаем выравнивание регистра dx (который содержит значение sp, указанное загрузчиком) по 4 байтам и проверяем на нуль. Если он равен нулю, то помещаем в dx значение 0xfffc (выровненный по 4 байтам адрес перед максимальным размером сегмента 64 КБ). Если он не равен нулю, то продолжаем использовать значение sp, заданное загрузчиком (0xf7f4 в нашем случае). Затем помещаем значение ax в ss, что сохраняет правильный адрес сегмента 0x1000 и устанавливает правильный sp. Теперь у нас есть правильный стек:

  • Во втором сценарии ss != ds. Сначала помещаем значение _end (адрес конца кода установки) в dx и проверяем поле заголовка loadflags, используя инструкцию testb, чтобы проверить, можно ли использовать кучу. loadflags — это заголовок битовой маски, который определяется следующим образом:
#define LOADED_HIGH     (1<<0)
#define QUIET_FLAG      (1<<5)
#define KEEP_SEGMENTS   (1<<6)
#define CAN_USE_HEAP    (1<<7)

и, как указано в протоколе загрузки:

Имя поля: loadflags

Это поле является битовой маской.

Бит 7 (запись): CAN_USE_HEAP
Установите этот бит равным 1, чтобы указать, что значение
heap_end_ptr допустимо. Если это поле пусто, будет отключена
часть функциональности установки.

Если установлен бит CAN_USE_HEAP, то в dx ставим значение heap_end_ptr (которое указывает на _end) и добавляем к нему STACK_SIZE (минимальный размер стека 1024 байта). После этого переходим к метке 2 (как в предыдущем случае) и делаем правильный стек.

  • Если CAN_USE_HEAP не установлен, просто используем минимальный стек от _end до _end + STACK_SIZE:


Нужны ещё два шага, прежде чем перейти к основному коду C: это настройка области BSS и проверка «волшебной» подписи. Сначала проверка подписи:
    cmpl    $0x5a5aaa55, setup_sig
    jne     setup_bad

Инструкция просто сравнивает setup_sig с магическим числом 0x5a5aaa55. Если они не равны, сообщается о неустранимой ошибке.

Если магическое число совпадает и у нас есть набор правильных регистров сегментов и стек, то осталось лишь настроить раздел BSS перед переходом к коду C.

Раздел BSS используется для хранения статически выделенных неинициализированных данных. Linux тщательно проверяет, что эта область памяти обнулилась:

    movw    $__bss_start, %di
    movw    $_end+3, %cx
    xorl    %eax, %eax
    subw    %di, %cx
    shrw    $2, %cx
    rep; stosl

Первым делом начальный адрес __bss_start перемещается в di. Затем адрес _end + 3 (+3 для выравнивания по 4 байтам) перемещается в cx. Регистр eax очищается (с помощью инструкции xor), вычисляется размер раздела bss (cx-di) и он помещается в cx. Затем cx делится на четыре (размер «слова») и многократно используется инструкция stosl, сохраняя значение еах (нуль) в адрес, указывающий на di, автоматически увеличивая di на четыре и повторяя это до тех пор, пока сх не достигнет нуля). Чистый эффект этого кода заключается в том, что нули записываются во все слова в памяти от __bss_start до _end:


Вот и всё: у нас есть стек и BSS, так что можно перейти к функции main() C:
    calll main

Функция main() находится в arch/x86/boot/main.c. О ней поговорим в следующей части.
Это конец первой части об устройстве ядра Linux. Если у вас есть вопросы или предложения, свяжитесь со мной в твиттере, по почте или просто создайте тикет. В следующей части мы увидим первый код на C, который выполняется при установке ядра Linux, реализацию подпрограмм памяти, таких как memset, memcpy, earlyprintk, раннюю реализацию и инициализацию консоли и многое другое.

Let's block ads! (Why?)

[Перевод] Курс MIT «Безопасность компьютерных систем». Лекция 15: «Медицинское программное обеспечение», часть 1

Массачусетский Технологический институт. Курс лекций #6.858. «Безопасность компьютерных систем». Николай Зельдович, Джеймс Микенс. 2014 год


Computer Systems Security — это курс о разработке и внедрении защищенных компьютерных систем. Лекции охватывают модели угроз, атаки, которые ставят под угрозу безопасность, и методы обеспечения безопасности на основе последних научных работ. Темы включают в себя безопасность операционной системы (ОС), возможности, управление потоками информации, языковую безопасность, сетевые протоколы, аппаратную защиту и безопасность в веб-приложениях.

Лекция 1: «Вступление: модели угроз» Часть 1 / Часть 2 / Часть 3
Лекция 2: «Контроль хакерских атак» Часть 1 / Часть 2 / Часть 3
Лекция 3: «Переполнение буфера: эксплойты и защита» Часть 1 / Часть 2 / Часть 3
Лекция 4: «Разделение привилегий» Часть 1 / Часть 2 / Часть 3
Лекция 5: «Откуда берутся ошибки систем безопасности» Часть 1 / Часть 2
Лекция 6: «Возможности» Часть 1 / Часть 2 / Часть 3
Лекция 7: «Песочница Native Client» Часть 1 / Часть 2 / Часть 3
Лекция 8: «Модель сетевой безопасности» Часть 1 / Часть 2 / Часть 3
Лекция 9: «Безопасность Web-приложений» Часть 1 / Часть 2 / Часть 3
Лекция 10: «Символьное выполнение» Часть 1 / Часть 2 / Часть 3
Лекция 11: «Язык программирования Ur/Web» Часть 1 / Часть 2 / Часть 3
Лекция 12: «Сетевая безопасность» Часть 1 / Часть 2 / Часть 3
Лекция 13: «Сетевые протоколы» Часть 1 / Часть 2 / Часть 3
Лекция 14: «SSL и HTTPS» Часть 1 / Часть 2 / Часть 3
Лекция 15: «Медицинское программное обеспечение» Часть 1 / Часть 2 / Часть 3

Приветствую всех, я тоже учился в MIT в 90-х годах и рад снова сюда вернуться. Сегодня мы поговорим о несколько другом виде безопасности, оставим техническую часть в стороне и обсудим, к каким далеко идущим последствиям приводит эта безопасность. Чтобы вы знали, я сам из района Midnight Сoffeehouse club, а наш Университет Массачусетс Амхерст, который вы видите на экране, расположен в Мичигане, но мы не настолько велики, как ваш кампус.

Сегодня мы поговорим о некоторых наших исследованиях и обсудим всё: от взрывающихся дефибрилляторов до вопросов конфиденциальности в медицинских изделиях. В основном это будет связано только с одним направлением исследований моего бывшего аспиранта, который на представленном здесь фото дезинфицирует имплантируемые дефибрилляторы.Сегодня мы в основном поговорим о безопасности медицинских устройств.

На следующем слайде показан список множества людей, принимавших участие в этих исследованиях, и я попытаюсь просуммировать некоторые современные положения о безопасности медицинского устройства с различных точек зрения. Я также обязан включить в свою лекцию этот шаблонный слайд о возможном конфликте интересов, так что теперь вы можете узнать о любых потенциальных предубеждениях в моем мышлении. Но мне бы хотелось думать, что я менее предвзят, чем обычный человек.

Примерно год назад произошло интересное событие. FDA, Управление по санитарному надзору за качеством пищевых продуктов и медикаментов, выпустило проект документа, в котором было сказано, что теперь они будут проверять производителей на предмет соблюдения кибербезопасности, или, как мы это называем, безопасности и конфиденциальности, не только в отношении реализации программного обеспечения медицинского устройства, но также и в отношении разработки этого программного обеспечения ещё до того, как будет написана первая строчка программы.

Поэтому мы поговорим о том, как это повлияло на мышление сообщества производителей медицинских устройств. Последнее руководство по разработке дизайна медицинского программного обеспечения появилось всего пару недель назад, и мы недавно участвовали в видеоконференции, организованной FDA по этому поводу. Всего к этому совещанию присоединились более 650 человек. Там было много интересного для производителей медицинского оборудования относительно того, как применить некоторые концепции, которые вы изучаете здесь в своем классе.

Однако это действительно трудно. Я заметил, что один из вопросов на сайте был о том, как изменить культуру медицинского сообщества так, чтобы оно понимало, насколько важна безопасность. Данный слайд иллюстрирует это.

На слайде изображён один из основоположников асептики, доктор Игнац Земмельвайс, говорящий, что доктор обязан мыть руки. Ему возражает американский акушер Чарльз Мейгс, произносящий слова: «Поскольку доктора – джентльмены, у них всегда чистые руки!»

Кто сегодня утром мыл руки? Отлично, я не узнаю Массачусетский институт! Итак, 165 лет назад жил известный врач-акушер Игнац Земмельвайс, который исследовал болезнь под названием «послеродовой сепсис». И он обнаружил, что если его студенты-медики, работавшие утром в морге, затем шли к пациентам, то эти пациенты, как правило, умирали чаще. Он пришёл к выводу, что если врачи будут мыть руки после того, как работали с трупами, то смертность после родов, во время которых они ассистировали, будет намного меньше. Так что он рекомендовал врачам мыть руки. Однако реакция сообщества врачей на это предложение в основном выражалась мнением акушера Чарльза Мейгса, утверждавшего, что все врачи – джентльмены, поэтому у них всегда чистые руки.

В какой-то мере мы видим подобное отношение к безопасности и сегодня, так что это не слишком удивительно. На протяжении нашего разговора я попробую провести с этим некоторые параллели.
У меня имеется слишком много материала по теме, так что я буду перескакивать через некоторые вещи. Но первым делом я хочу поинтересоваться — кто-нибудь из вас собирается стать врачом? Нет? Хорошо, хорошо, в таком случае вам будет о чём поговорить за коктейлем с друзьями-врачами.

Мы немного поговорим об имплантируемых медицинских устройствах. Я дам вам подержать в руках эту штуку, она безопасна, только не надо её облизывать. Это имплантируемый дефибриллятор бывшего пациента. На самом деле, этим устройствам уже около 50 лет, именно тогда начали появляться первые кардиовентеры-дефибрилляторы. В то время они были внешними, и пациентам приходилось толкать перед собой тележку с этим устройством и иметь рядом с собой сильную медсестру.

Прошли десятилетия, и дефибрилляторы стали достаточно маленькими, чтобы быть полностью имплантированными в организм. На слайде вы видите изображение того, что называется «жезлом», который использует индуктивную связь. Технически он беспроводной, здесь нет никаких проводов. Прибор программируется так, чтобы обеспечивать сердечный ритм 60 ударов в минуту.

Меня как исследователя безопасности заинтересовало появление примерно в 2003 году дефибрилляторов, таких как тот, что я передал вам, использующих беспроводные технологии и сети. Мы привыкли, что сети больше служат для глобальных вычислений, поэтому я задумался, что здесь может пойти не так?

К счастью, есть много инженеров, которые также озабочены этим вопросом в медицинских компаниях, однако здесь безопасность требует совсем другого мышления. И я собираюсь рассказать вам о том, как менялось это мышление.

Если вы разберёте одно из таких устройств, то найдете в нем огромное количество вещей, ограничивающих эксплуатацию. Так что если вам нужна сложная инженерная проблема, просто разберите одно из таких устройств. Больше половины объёма дефибриллятора занимает аккумулятор очень большой ёмкости, который стоит 40000 долларов. Здесь также используется серебристый металл — оксид ванадия.

В верхней части стимулятора расположены микроконтроллеры, и обычно в нём есть антенны для связи с устройством контроля дефибриллятора. Все это герметично запечатано и имплантировано в ваше тело.

Мы говорим об одном из самых суровых условий эксплуатации электронного устройства. Если вы захотите перезарядить батарею в своем теле, вам можно только пожелать удачи. Знаете ли вы, что при зарядке аккумуляторы выделяют тепло и газ? Поэтому при конструировании таких устройств существуют серьёзные ограничения, и добавить туда безопасность достаточно сложно.

Однако существует очень веская причина для беспроводного управления медицинским устройством. Есть веские причины, но есть и серьезные риски. Чтобы проиллюстрировать это, я хочу, чтобы вы посмотрели, как выглядели первые имплантируемые дефибрилляторы.

Это дефибриллятор из музея Medtronic в Миннеаполисе. Может ли кто-нибудь догадаться, что это за маленький металлический цилиндр с правой стороны? Какова его функция? Антенна? Контроль? Управление — очень близкая догадка! Есть еще предположения?

Этот «выступ» использовался ещё до появления беспроводной связи для управления дефибриллятором. Раньше для изменения настроек устройства врач говорил: «пациент, пожалуйста, поднимите руку. Я собираюсь вставить вам иглу через подмышку и покрутить диск изменения сердечного ритма».

Таким образом, одно из главных преимуществ беспроводной связи заключается в том, что она фактически снижает количество инородных предметов, попадающих в организм, потому что чем больше инородных предметов попадает в организм, тем больше вероятность заражения. Это серьезный риск. На самом деле, 1% имплантатов дают серьезные осложнения, и из них около 1% являются фатальными. Так что контроль инфекции — одна из самых важных вещей, которую вы должны обеспечить при имплантации и замене устройства.

Конечно, если вы впадёте в другую крайность и просто скажете, что хотите повсюду установить беспроводную связь, вы получите другие виды рисков. Я назвал это теорией «бекона для беспроводной связи». Моя мама со среднего Запада говорила, что бекон делает всё вокруг лучше.
Я заметил, что есть некоторые производители устройств, которые, похоже, используют беспроводную связь везде, при этом не продумывая опасность такого решения. Оно имеет свои преимущества, но нужно поразмыслить стратегически, прежде чем добавлять такую возможность в достаточно небезопасное устройство. Например, подумать, о том, какие риски могут возникнуть со временем.

Я не собираюсь говорить много об интернет-сетях, но думаю, эта цитата заслуживает упоминания. Кто-нибудь помнит корабль «Коста Конкордия» у берегов Италии? Его капитан говорил: «В наши дни все намного безопаснее благодаря современным инструментам и интернету». Это кадр из космоса, на котором видно его перевернувшийся корабль.

Так что когда вы добавляете интернет и беспроводную связь в ваше медицинское устройство, то идете на новый риск. Но вам не стоит этого бояться, нужно просто предусмотреть контроль возможных негативных последствий.

Я хочу показать вам в картинках, как проходит типичная эксплуатации медицинского устройства, как оно используется в клинической помощи, как это может изменить ваше мышление, если исходить с точки зрения безопасности, и что вы должны думать о риске. Сначала поговорим о мире, в котором нет реальных угроз, а присутствуют только небезопасные методы, опасные случайности и некоторая небрежность без всякого сознательного саботажа.

FDA поддерживает базу данных промахов, неисправностей, повреждений и смертельных случаев. Это открытая информация, вы можете сами посмотреть. Эта выборка называется MAUDE – «Опыт использования устройств производителями и потребителями».

На этом слайде описывается случай применения устройства под названием «объемный инфузионный насос», это прибор, который механически вводит лекарственные препараты в ваше тело через вену. В данном случае пациент умер, и если вы посмотрите на этот текст внимательно, то увидите, что одной из причин трагедии было переполнение буфера. Я думаю, вы знаете всё о переполнении буфера из вашей первой лекции. Так что подобное случается в реальной жизни в каждой области, использующей компьютерную технику.

В этом конкретном случае переполнение буфера было обнаружено во время проверки ошибок программного обеспечения, но реакцией на такую ошибку было выключение насоса, то есть перевод его в безопасный режим. Но создатели ПО не учли того, что для некоторых пациентов отключение насоса — это смертный приговор. Так что этот пациент умер после увеличения внутричерепного давления, сопровождаемого смертью мозга, и всё это случилось из-за переполнения буфера.

Так что здесь нет ничего сложного, верно? Вы все знаете, что не хотите получить переполнение буфера в программном обеспечении, и в данном случае нет никакого внешнего воздействия. Это просто иллюстрирует состояние программного обеспечения, по крайней мере, для этого конкретного устройства. Это очень сложная задача.

Другая сложность обеспечения безопасности состоит в необходимости учитывать человеческий фактор. Есть несколько университетов, которые фокусируются на этой стороне вопроса, но, по моему мнению, недостаточно. Поэтому я опираюсь на собственный жизненный опыт.

Моя жена просила сохранить анонимность, так что я не раскрою ее имя. На слайде вы видите меня, мою жену, сзади расположен инфузионный насос, а наш ребёнок находится пока что внутри жены. К нашему счастью, насос работал просто отлично. Вообще насосы отлично подходят для оказания медицинской помощи, но они всё же вызвали более 500 смертей и из-за различных видов неисправностей.

Поэтому я расскажу вам еще об одной неисправности. На следующем слайде показан имплантируемый вид насоса. У него есть полупроницаемая мембрана, через которую вы можете пополнить запасы лекарств, и пользовательский интерфейс, который медсестра или врач использует для изменения дозировки.

Кто-нибудь видит, где вы набираете количество медицинского препарата? Вы должны прищуриться, верно? Вам нужно очень хорошо приглядеться к этой цифре.
.

Здесь под номером шесть написано, что мы собираемся дозировать болюс. Болюс — это время постепенного введения ежедневной дозы лекарства, более 20 минут и 12 секунд, и всё это имплантировано, так что пациент не чувствует процесса введения лекарства.

Этот пользовательский интерфейс вступил в силу после того, как FDA отозвало предыдущую версию интерфейса и потребовало доработки. До отзыва в пункте 6 интерфейса управления этим насосом отсутствовало восемь ключевых элементов: HH: MM: SS, это часы, минуты и секунды.

Как вы думаете, что могло бы произойти, когда это обозначение отсутствовало? В таком случае очень легко ошибиться в единицах измерения и сделать ошибку в порядке величины.

К несчастью для данного пациента, его насос был неправильно запрограммирован, так что лекарство вводилось за 24 минуты вместо 24 часов. Ошибка была вызвана отсутствием обозначения вводимых цифр: часы, минуты, секунды. Это было обнаружено только после смерти пациента – покинув лечебное учреждение, он попал в тяжёлую автомобильную аварию и позже умер из-за того, что его семья согласилась отключить медицинскую систему жизнеобеспечения.

Если вы посмотрите на это с технической точки зрения, проблема довольно проста, не так ли? Просто в интерфейсе не было «этикетки». Но здесь человеческий фактор очень легко проследить, хотя он не всегда на виду, в центре внимания инженерных процессов. Но это очень важный элемент повышения надежности устройств, которые полагаются на программное обеспечение. Поэтому я призываю вас обязательно учитывать человеческий фактор при разработке своего программного обеспечения, даже если он не оказывает критического влияния.

Еще я хочу поговорить о захватывающем мире программного менеджмента. Я собрал на этом слайде все эти маленькие диалоговые окна, появляющиеся всякий раз, как мой компьютер получает обновление программного обеспечения, но все это происходит в фоновом режиме. Как и мой iPhone, который постоянно получает обновления и становится «всё сильнее». Медицинские устройства также получают обновления программного обеспечения, принципиально они не отличаются от традиционных вычислительных устройств. Они просто контролируют жизненно важные функции вашего организма.

Имеется один интересный случай, который произошёл около 4-х лет назад. Есть компании, выпускающие антивирусное ПО, которое используется больницами, в частности, McAfee. Так вот, этот антивирус при очередном критическом обновлении Windows посчитал его вредоносным, поместил на карантин, а потом решил изолировать систему. Это вызвало аварийную перезагрузку компьютеров и появление BSOD на экранах.

В результате данная больница прекратила приём пациентов, за исключением тяжелых случаев, таких как огнестрельные ранения, потому что их системы регистратуры не работали должным образом.

Итак, клиническая помощь сильно зависит от функций программного обеспечения, и мы иногда забываем о роли безопасности.

Microsoft имеет огромное влияние на множество пользователей как крупнейший разработчик операционных систем. Верите вы или нет, но до сих пор существует множество медицинских устройств под управлением Windows XP, поддержка которой прекратилась полгода назад. Таким образом, вы не должны использовать эту ОС, потому что больше для неё не выпускается обновлений безопасности и обновления функций. Это устаревшее программное обеспечение. Но до сих в медицинские учреждения продолжает поставляться новое компьютерное оборудование с предустановленной ОС Windows XP.

В данной ситуации жизненные циклы программного обеспечения немного смещены. Хорошо, если вы привыкли ежедневно загружать обновления для общедоступного программного обеспечения, но подумайте о медицинских устройствах. Вы не сможете отказаться от него через год, оно может использоваться в течение 20 лет. Поэтому очень трудно найти программное обеспечение, подходящее для 20-тилетней эксплуатации, это практически как полет в космос.

Месяц назад FDA выпустило руководство о том, что они ожидают увидеть от производителей. Думайте о нем, как о проекте для разработчиков ПО.

Когда вы излагаете все требования для своего медицинского устройства, они спрашивают производителей, как они продумали проблемы безопасности, все риски и как они собираются их смягчить. Каковы остаточные риски, то есть каковы проблемы, которые они не могут решить? В идеале они ожидают, что производитель или разработчик предусмотрит все возможные риски и способы их уменьшения.

С точки зрения управления программным обеспечением, никто из медицинского персонала не является ответственным, авторизированным пользователем, поэтому может случиться всякое. Но теперь появились рекомендации, которые призваны помочь производителям лучше интегрировать безопасность в свои продукты. Так что я думаю, что мы проводим время с пользой, обсуждая подобные вопросы.

Теперь мы сможем перейти к обсуждению проблем безопасности, оставив вне контекста лекции вещи, к ней не относящиеся. Так что давайте наденем свои серые и чёрные шляпы (намёк на этику хакеров: хакер в серой шляпе тестирует уязвимость компьютеров, но может применить свои знания в корыстных целях, хакеры в чёрных шляпах больше взломщики, чем исследователи).

Прежде чем я начну, хочу сказать, что это очень сложная область исследования, потому что в ней присутствуют пациенты. И если бы сегодня мне дали медицинское устройство, у которого имеются проблемы безопасности, я бы всё равно взял его, потому что пациенту будет намного лучше с этим прибором, чем без него. Но, конечно, я бы предпочел иметь более безопасные медицинские устройства. Сейчас появляется все больше и больше безопасных устройств, но если вы должны выбрать между прибором и его отсутствием, я бы настойчиво рекомендовал вам всё равно использовать прибор, чтобы быть в гораздо лучшем положении.

Но, тем не менее, давайте рассмотрим случай саботажа, в котором у нас имеется противник, желающий создать проблемы при использовании медицинского устройства. У кого сейчас дефибриллятор? Отлично, он здесь. Я хотел бы рассказать вам немного о том, как эти дефибрилляторы имплантируются. Это очень специфичное устройство, потому что, во-первых, оно имплантировано внутрь живого организма, поэтому риск очень высок. Оно поддерживает вашу жизнь. Если оно бьется в вашем сердце и вдруг отказывает, результаты могут быть катастрофическими. Так что это очень интересно с инженерной точки зрения, потому что дефибриллятор должен работать круглосуточно, семь дней в неделю в течение многих лет.

Итак, это программер, не человек, а устройство. В основном это износоустойчивый компьютер, к которому прикреплен небольшой девайс под названием Wand, или жезл. Это не компьютерная мышь, а передатчик и приемник, использующий собственную беспроводную связь в специально выделенном частотном диапазоне, это не обычная связь стандарта 802.11.

Операция длится примерно 90 минут. Пациент бодрствует, он сохраняет спокойствие, но операция выполняется под местной анестезией. Спереди под ключицей делается небольшой разрез, а затем бригада из шести человек будет проводить электрод через кровеносный сосуд, заканчивающийся внутри сердца. У меня здесь есть такой зонд — электрод, который ранее не использовался.

Вы видите маленькие насечки на его конце, в некоторых таких устройствах есть два датчика, так что он может чувствовать ваш сердечный ритм и оказывать на него влияние. Вы можете создавать маленькие или большие сердечные сокращения, в такт сердечному ритму или чтобы перезагрузить сердце, если ритм хаотичный. Это очень продвинутое устройство. Скошенный кончик на конце зонда-электрода – это металл стероидного типа, он не цепляется к тканям, поэтому электрод свободно проходит через сосуд. В принципе, это обычный USB-кабель, верно?

После того, как эта штука имплантирована в сердце, пациента зашивают и проводят испытания работоспособности стимулятора. Обычно после этого пациент получает то, что выглядит как маленькая базовая станция, как маленькая точка доступа и называется «домашний монитор». Это очень ограничивает свободу.

По радиоканалу, работающему на выделенной частоте, можно собрать всю телеметрию и отправить её в «облако», обычно это конфиденциальное облачное хранилище для приватного использования, чтобы медицинские работники могли следить за своим пациентом. Например, если вы заметили, что устройство пациента Мэри передаёт необычные показания, вы можете позвонить ей и сказать: «вам нужно записаться на прием и прийти ко мне, потому что я хотел бы разобраться, что происходит с вашим дефибриллятором».

Таким образом, одно из полезных свойств беспроводной связи – это возможность осуществлять непрерывное наблюдение за работой дефибриллятора пациента, а не проделывать это всего лишь раз в год.

У нас была команда студентов, которую мы собрали из нескольких университетов, я дал им дефибриллятор и осциллограф, и они «удалились в пещеру» примерно на девять месяцев. Вернувшись оттуда, они сказали: «посмотрите, что мы нашли»!

На следующем слайде показан скриншот сеанса связи между устройством и программером. Всё, что вы видите, совершенно понятно, никакой криптографии, по крайней мере, никакого шифрования, которое можно было бы заметить.

Здесь вы найдете имя врача, поставившего имплантат, диагноз, название больницы, состояние устройства, имя пациента, дата рождения, модель и производителя дефибриллятора, серийный номер устройства. В целом это полная электронная медицинская карта. Это довольно старое устройство, использовавшееся около 10 лет назад, но в то время оно воспринималось как произведение искусства. Оно не использовало шифрование, по крайней мере, для обеспечения конфиденциальности медицинской информации.

Поэтому, когда мы увидели это, то подумали, что нам определенно нужно обратить внимание на безопасность управления данным устройством. Как оно обеспечивают подлинность контроля? Неприкосновенность информации? Мы решили провести следующий эксперимент и начали учиться использовать то, что называется «программным радио». Возможно, некоторые из вас играли с этим, сейчас их целая куча. Около 10 лет назад популярным было программное обеспечение для радио USRP и GNU. Нашей целью было заставить дефибриллятор думать, что сердце пациента продуцирует фатальный сердечный ритм.

Мы взяли ненужную антенну от кардиостимулятора, создали маленькую антенну и записали радиочастотный сигнал, вызывающий фатальный сердечный ритм. А затем мы направили его обратно дефибриллятору по беспроводной связи. После этого устройство излучило сигнал, соответствующий шоку от удара током 500В. То есть провело электрическую дефибрилляцию останавливающую сердце несуществующего пациента. Это порядка 32 джоулей в миллисекунду, нечто подобное можно испытать при ударе в грудь лошадиным копытом.

Интересно было то, как мы это обнаружили. Итак, я был в операционной, и если помните, я говорил, что после имплантации хирургическая бригада проверяет, правильно ли работает дефибриллятор. Как можно узнать, нормально ли работает дефибриллятор, если сердце пациента бьется нормально? Поэтому в дефибриллятор встроена команда, вызывающая смертельный сердечный ритм, для восстановления которого и предназначается дефибриллятор. Это называется «командный шок». Поэтому, когда я спросил врачей об этом, выяснилось, что они не понимают, в чём заключается концепция аутентификации для подобных устройств. После этого мы решили, что нам действительно нужно более глубоко изучить, как можно решить эти проблемы.

В данном конкретном случае мы смогли отправить команду на устройство, но не смогли проверить подлинность этой команды, так что мы искусственно можем вызвать шок. Хорошая новость состоит в том, что эти устройства могли решить данную проблему путем обновления программного обеспечения.

Вот что касается самого имплантата. К ним применяется огромное количество инновационных решений, это больше не научная фантастика, за этим стоят реальные люди и пациенты.

Большинство людей глубоко озабочены предоставлением качественной медицинской помощи. Но иногда они просто не понимают, как вписать безопасность в процесс проектирования, так что в культурном плане это некий вызов.

Еще одной заинтересованной стороной являются те люди, которые оказывают медицинскую помощь в первую очередь – это персонал больниц или небольших клиник. Если вы хотите найти вредоносное ПО, обратитесь в больницу, там вы найдёте много интересных вирусных программ, и вот почему.

На следующем слайде представлен скриншот от моего коллеги, который работал в бостонском медицинском центре Beth Israel Deaconess. Он сделал скриншот своей сетевой архитектуры. В ней нет ничего потрясающего. Интересно, что он перечислил операционные системы, установленные на том, что считалось медицинскими устройствами.

Мне нравится складывать цифры и всё проверять, поэтому я пересчитал его данные и сказал:

«Хорошо, у вас есть пакет обновления Windows XP SP1, SP2 и SP3, но 0+15+1 не равняется 600, оно равно 16, у тебя неправильно сложение»! Он посмотрел на меня и сказал: „Нет, Кевин, всё правильно, у нас в больнице есть ещё 600 компьютеров с нулевым пакетом обновления Windows XP“.

Таким образом, это те медицинские устройства, для которых они не смогли обновить программное обеспечение производителя и установить патчи безопасности. Это означает, что у них в больнице используется старое программное обеспечение, уязвимое для всех старых вредоносных программ, которые поражают Windows XP на протяжении 15 лет.

В условиях клиники очень трудно обеспечивать защиту оборудования, потому что сроки службы оборудования и программного обеспечения не синхронизированы. В здравоохранении мыслят, оперируя понятиями десятилетий, но в быстром мире хоккейной клюшки из Силиконовой долины, мы думаем о днях, неделях или месяцах по отношению к новинкам программного обеспечения.
Внизу слайда вы видите информацию о том, что среднее время заражения медицинского оборудования вирусами составляет 12 дней, в течение которых у них нет никакой защиты от вредоносных программ. При наличии антивирусных программ время безопасной работы устройств без угрозы заражения вирусами увеличивается почти до 1 года, но и этого недостаточно.

25:00 мин

Курс MIT «Безопасность компьютерных систем». Лекция 15: «Медицинское программное обеспечение», часть 2


Полная версия курса доступна здесь.

Спасибо, что остаётесь с нами. Вам нравятся наши статьи? Хотите видеть больше интересных материалов? Поддержите нас оформив заказ или порекомендовав знакомым, 30% скидка для пользователей Хабра на уникальный аналог entry-level серверов, который был придуман нами для Вас: Вся правда о VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps от $20 или как правильно делить сервер? (доступны варианты с RAID1 и RAID10, до 24 ядер и до 40GB DDR4).

VPS (KVM) E5-2650 v4 (6 Cores) 10GB DDR4 240GB SSD 1Gbps до декабря бесплатно при оплате на срок от полугода, заказать можно тут.

Dell R730xd в 2 раза дешевле? Только у нас 2 х Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 ТВ от $249 в Нидерландах и США! Читайте о том Как построить инфраструктуру корп. класса c применением серверов Dell R730xd Е5-2650 v4 стоимостью 9000 евро за копейки?

Let's block ads! (Why?)