Root c что это
Перейти к содержимому

Root c что это

Анализ кода ROOT — фреймворка для анализа данных научных исследований

Picture 3

Пока в Стокгольме проходила 118-я Нобелевская неделя, в офисе разработки статического анализатора кода PVS-Studio готовился обзор кода проекта ROOT, используемого в научных исследованиях для обработки больших данных. Премию за такой код, конечно, не дашь, а вот подробный обзор интересных дефектов кода и лицензию для полной проверки проекта разработчики получат.

Введение

Picture 1

ROOT — набор утилит для работы с данными научных исследований. Он обеспечивает все функциональные возможности, необходимые для обработки больших данных, статистического анализа, визуализации и хранения. В основном написан на языке C++. Разработка началась в CERN (Европейская организация по ядерным исследованиям) для исследований по физике высоких энергий. Каждый день тысячи физиков используют ROOT-приложения для анализа своих данных или для моделирования.

PVS-Studio — это инструмент для выявления ошибок и потенциальных уязвимостей в исходном коде программ, написанных на языках С, C++, C# и Java. Работает в 64-битных системах на Windows, Linux и macOS и может анализировать код, предназначенный для 32-битных, 64-битных и встраиваемых ARM платформ.

Дебют новой диагностики

V1046 Unsafe usage of the bool’ and ‘int’ types together in the operation ‘&=’. GSLMultiRootFinder.h 175

Бета-версия анализатора, которая использовалась при проверке, нашла вот такую потрясающую ошибку.

Ожидание. Функция SetFunctionList обходит список итераторов. Если хоть один из них будет невалидным, то возвращаемое значение будет false, иначе true.

Реальность. Функция SetFunctionList может возвращать значение false даже для валидных итераторов. Разберёмся в ситуации.Функция AddFunction возвращает количество валидных итераторов в списке fFunctions. Т.е. при добавлении ненулевых итераторов, размер этого списка будет последовательно увеличиваться: 1, 2, 3, 4 и т.д. Вот тут и начнёт проявлять себя ошибка в коде:

Т.к. функция возвращает результат типа int, а не bool, то операция ‘&=’ с чётными числами будет давать значение false. Ведь младший бит чётных чисел всегда будет равен нулю. Следовательно, такая неочевидная ошибка будет портить результат функции SetFunctionsList даже для валидных аргументов.

Picture 2

Ошибки в условных выражениях

V501 There are identical sub-expressions to the left and to the right of the ‘&&’ operator: module && module rootcling_impl.cxx 3650

Начнём с самого безобидного примера. Указатель module проверяется два раза. Скорее всего, одна проверка лишняя. Но код лучше исправить, чтобы не возникало лишних вопросов.

V501 There are identical sub-expressions ‘strchr(fHostAuth->GetHost(), ‘*’)’ to the left and to the right of the ‘||’ operator. TAuthenticate.cxx 300

Тут в строке fHostAuth->GetHost() ищется один и тот же символ — ‘*’. Возможно, одним из них должен быть символ ‘?’. Обычно их используют для задания разных масок.

V517 The use of ‘if (A) <. >else if (A) <. >‘ pattern was detected. There is a probability of logical error presence. Check lines: 163, 165. TProofMonSenderML.cxx 163

Переменная fSummaryVrs дважды сравнивается с нулём. Это приводит к тому, что код в ветви else-if никогда не выполняется. А кода там написано немало…

V523 The ‘then’ statement is equivalent to the ‘else’ statement. TKDTree.cxx 805

Один и тот же copy-paste-код выполняется при любом условии. Возможно, есть опечатка в словах left и right.

Подобного подозрительного кода в проекте немало:

  • V523 The ‘then’ statement is equivalent to the ‘else’ statement. TContainerConverters.cxx 51
  • V523 The ‘then’ statement is equivalent to the ‘else’ statement. TWebFile.cxx 1310
  • V523 The ‘then’ statement is equivalent to the ‘else’ statement. MethodMLP.cxx 423
  • V523 The ‘then’ statement is equivalent to the ‘else’ statement. RooAbsCategory.cxx 394

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

V590 Consider inspecting the ‘!file1 || c <= 0 || c == ‘*’ || c != ‘(» expression. The expression is excessive or contains a misprint. TTabCom.cxx 840

Рассмотрим сокращённую часть условного выражения, на которое указал анализатор:

Условие не зависит от того, равен символ «звёздочке» или нет. Эта часть условного выражения всегда будет истинна для любого символа, отличного от ‘(‘. В этом легко убедиться, если построить таблицу истинности.

Ещё два места со странной логикой в условных выражениях:

  • V590 Consider inspecting this expression. The expression is excessive or contains a misprint. TFile.cxx 3963
  • V590 Consider inspecting this expression. The expression is excessive or contains a misprint. TStreamerInfoActions.cxx 3084

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

Есть ещё одно место с похожим дефектом:

  • V593 Consider reviewing the expression of the ‘A = B < C’ kind. The expression is calculated as following: ‘A = (B < C)’. TProofServ.cxx 3897

Хм… Зачем делать отрицание константного значения kCostComplexityPruning? Скорее всего, символ отрицания случайно добавился и теперь приводит к неправильной логике выполнения кода.

Некорректный код с указателями

V522 Dereferencing of the null pointer ‘pre’ might take place. TSynapse.cxx 61

Я попытался разобраться в этом странном коде. Вроде задумка в том, чтобы не выставлять новое значение полю fpre. Тогда тут допустили ошибку, перепутав указатель, который следует проверить в условии. В текущей реализации, если передать значение nullptr в функцию SetPre, то произойдёт разыменование нулевого указателя.

Скорее всего, правильно так:

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

Вот ещё одно место, которое скопировано отсюда с небольшими изменениями:

  • V522 Dereferencing of the null pointer ‘post’ might take place. TSynapse.cxx 74

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

Традиционно, это диагностическое правило выдаёт много полезных предупреждений. Вот некоторые из них:

  • V595 The ‘file’ pointer was utilized before it was verified against nullptr. Check lines: 141, 153. TFileCacheRead.cxx 141
  • V595 The ‘fFree’ pointer was utilized before it was verified against nullptr. Check lines: 2029, 2038. TFile.cxx 2029
  • V595 The ‘tbuf’ pointer was utilized before it was verified against nullptr. Check lines: 586, 591. TGText.cxx 586
  • V595 The ‘fPlayer’ pointer was utilized before it was verified against nullptr. Check lines: 3425, 3430. TProof.cxx 3425
  • V595 The ‘gProofServ’ pointer was utilized before it was verified against nullptr. Check lines: 1192, 1194. TProofPlayer.cxx 1192
  • V595 The ‘projDataTmp’ pointer was utilized before it was verified against nullptr. Check lines: 791, 804. RooSimultaneous.cxx 791

V571 Recurring check. The ‘if (fCanvasImp)’ condition was already verified in line 799. TCanvas.cxx 800

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

Ошибки при работе с массивами

V519 The ‘Line[Cursor]’ variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 352, 353. Editor.cpp 353

Новое значение элемента Line[Cursor] сразу же перезаписывается. Что-то здесь не так…

V557 Array overrun is possible. The ‘ivar’ index is pointing beyond array bound. BasicMinimizer.cxx 130

Так ошибаться в проверке индекса массива — просто массовая проблема в последнее время. Чуть ли не в каждом третьем проекте встречается. Если при индексации массива в цикле всё просто — почти всегда используется оператор ‘<‘ для сравнения индекса с размером массива, то при такой проверке, как здесь, надо использовать оператор ‘>=’, а не ‘>’. Иначе возможен выход за границу массива на один элемент.

Эту ошибку расплодили по файлу несколько раз:

  • V557 Array overrun is possible. The ‘ivar’ index is pointing beyond array bound. BasicMinimizer.cxx 186
  • V557 Array overrun is possible. The ‘ivar’ index is pointing beyond array bound. BasicMinimizer.cxx 194
  • V557 Array overrun is possible. The ‘ivar’ index is pointing beyond array bound. BasicMinimizer.cxx 209
  • V557 Array overrun is possible. The ‘ivar’ index is pointing beyond array bound. BasicMinimizer.cxx 215
  • V557 Array overrun is possible. The ‘ivar’ index is pointing beyond array bound. BasicMinimizer.cxx 230

Скорее всего, в цикле for хотели сравнивать переменную dim с dm->fArrayDim, а не fArrayDim. Значение используемой переменной — отрицательное, благодаря условию в начале функции. Такой цикл никогда не выполняется.

V767 Suspicious access to element of ‘current’ array by a constant index inside a loop. TClingUtils.cxx 3082

Этот фрагмент кода парсит некую строку и проверяет её корректность. После того, как нулевой символ строки current определяется как число, выполняется обход всех остальных символов, чтобы убедиться, что до конца строки все символы — числа. Ну как выполняется… счётчик цикла i не используется в цикле. Надо было написать current[i], а не current[0] в условии.

Picture 4

Утечка памяти

V773 The function was exited without releasing the ‘optionlist’ pointer. A memory leak is possible. TDataMember.cxx 355

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

Снова про функцию memset

V597 The compiler could delete the ‘memset’ function call, which is used to flush ‘x’ buffer. The memset_s() function should be used to erase the private data. TMD5.cxx 366

Многие подумают, что когда код скомпилируется, в бинарный файл не попадёт этот комментарий, и будут правы :D. А вот что функция memset тоже будет удалена компилятором, догадываются не все. А это произойдёт. Если очищаемый буфер больше не будет использоваться в коде, то компилятор оптимизирует код и удалит вызов функции. Технически он прав, но если в буфере были секретные данные, то они там и останутся. Это классический дефект безопасности CWE-14.

Разные предупреждения

V591 Non-void function should return a value. LogLikelihoodFCN.h 108

В перегруженном операторе отсутствует возвращаемое значение. Тоже очень распространённая проблема в последнее время.

V596 The object was created but it is not being used. The ‘throw’ keyword could be missing: throw runtime_error(FOO); RTensor.hxx 363

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

Всего нашлось два таких места. Второе:

  • V596 The object was created but it is not being used. The ‘throw’ keyword could be missing: throw runtime_error(FOO); Forest.hxx 137

Случай, похожий на те, что были описаны ранее про массивы. Здесь переменная n ограничивается диапазоном значений от 0 до 100. В таком случае существует ветвь кода, в которой произойдет деление на переменную n со значением 0. Скорее всего, ограничение значения n следует переписать таким образом:

V646 Consider inspecting the application’s logic. It’s possible that ‘else’ keyword is missing. TProofServ.cxx 729

Анализатор обнаружил странное форматирование. В одном месте отсутствует ключевое слово else. По коду можно предположить, что код действительно стоит исправить.

И ещё пару мест исправить заодно:

  • V646 Consider inspecting the application’s logic. It’s possible that ‘else’ keyword is missing. TFormula_v5.cxx 3702
  • V646 Consider inspecting the application’s logic. It’s possible that ‘else’ keyword is missing. RooAbsCategory.cxx 604

При работе с классом std::istream недостаточно вызова функции eof() для завершения цикла. В случае возникновения сбоя при чтении данных, вызов функции eof() будет всегда возвращать значение false, а других точек выхода из цикла в этом коде нет. Для завершения цикла в этом случае необходима дополнительная проверка значения, возвращаемого функцией fail():

Или просто написать:

V678 An object is used as an argument to its own method. Consider checking the first actual argument of the ‘Copy’ function. TFormLeafInfo.cxx 2414

Напоследок вот такая опечаточка. Вместо fSizes надо было передать orig.fSizes в функцию Copy.

Заключение

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

Кстати, на днях вышла macOS 10.15 Catalina, в которой отказались от поддержки 32-х битных приложений. И в PVS-Studio есть большой набор правил для выявления проблем при портировании программ на 64-х битные системы. Подробнее об этом в посте блога анализатора.

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Svyatoslav Razmyslov. Analyzing the Code of ROOT, Scientific Data Analysis Framework.

Root c что это

Основным средством анализа данных на LHC является пакет ROOT. Пакет ROOT является объектно-ориентированным аналогом библиотеки программ CERNLIB, который широко применялся в физике высоких энергий и далеко за ее пределами в 80-х и 90-х годах. Качество этого продукта предопределено тем, что основным автором его является Рене Бран, который написал основные подпакеты CERNLIB: HBOOK, ZEBRA, PAW, PAW++, GEANT3.

Для удаленной работы ROOT можно инсталлировать на Linux или Windows.

Linux — среда родная для ROOT.

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

Поэтому нам нужно только найти его месторасположение — оно определяется переменной окружения ROOTSYS:

Чтобы правильно настроить ROOT лучше всего использовать готовый скрипт:

Ш source bin/thisrot.sh (только для bash)

Ш source bin/thisrot.csh (только для tcsh, csh)

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

Конечно, перед этим необходимо иметь X-сервер на Вашей машине (то есть запустить Xming). Через 5 секунд получаем стартовый экран-загрузки с информацией (заставка). Запуск ROOT без этого стартового окна:

Чтобы запуск прошел быстрее, нужно указать опцию (b — batch, пакетный режим, работа без графики):

Интерпретатор ROOT-команд готов к работе.

ROOT можно использовать как в режиме интерпретатора команд (или макросов), или в режиме обычной so-библиотеки (so — “shared object”, совместно используемая библиотека).

“ROOT” и “Visual C++ 2010” в OC Windows

На cайте ROOT в разделе загрузки

root.cern.ch Download Pro, version 5.28/00

находим информацию о запуске ROOT в Windows: поддерживаются ОС Windows 7/Vista/XP/NT/2000. Предлагается обычный инсталляционный пакет для Windows — MSI. Этот пакет также устанавливает переменные окружения. Деинсталлировать можно с помощью «Control Panel»/»Add or Remove Programs».

Для инсталляции ROOT в Windows просто загрузите и стартуйте пакет (двойной клик мышкой на пакете). Однако, до этого необходимо иметь установленным пакет Visual C++:

MS VC++ 7.1 для ROOT-дистрибутива “VC++ 7.1”;

MS VC++ ? 8 для ROOT-дистрибутива “VC++ 9”;

MS VC++ 10 для ROOT-дистрибутива “VC++ 10”.

Бесплатную версию можно скачать с сайта Visual Studio.

Нам предлагается дистрибутив ROOT в бинарном виде — то есть уже откомпилированные библиотеки: root_v5.28.00c.win32.vc10.msi . Этот файл инсталлируется стандартно для Windows. Но прежде нужно установить Visual C++, например 2010.

Оказывается, что можно не устанавливать полный пакет VC++. Нам предлагается пакет “Microsoft Visual C++ 2010 Redistributable Package (x86)”. Его краткое описание такое: “Microsoft Visual C++ 2010 Redistributable Package устанавливает компоненты среды выполнения Visual C++, необходимых для запуска приложений, разработанных с Visual C++ на компьютере, который не имеет установленного Visual C++ 2010”.

Для интерактивной работы с ROOT нам этого должно быть достаточно. Скачиваем пакет “Microsoft Visual C++ 2010 Redistributable Package” (4.5 Мб) и устанавливаем его. После этого кликнем мышкой на root_v5.28.00c.win32.vc10.msi (54.5 Мб). После установки пакет занимает 340 Мб. На панели мы получаем значек

Кликнем на значке и получаем приглашение интерактивного ROOT:

C таким пакетом VC++ мы не сможем писать batch-программу с применением ROOT, но интерактивные скрипты работают в полном объеме. Например, Вы увидите ниже, что ROOT способен загрузить геометрию детектора ATLAS/LHC и отобразить ее на Вашем компьютере в ROOT-браузере.

Для того, чтобы писать полноценные batch-программы, нужно установить Visual Studio, который включает VC++.

Что такое root-доступ и как его получить на Android

Многие из нас слышали выражения, подобные этим: “root”, “рутануть”, “получить рут”. В основном, этими словами оперируют бывалые пользователи Android-смартфонов на специализированных форумах, а простого юзера фраза “это приложение работает только под рутом” порой вводит в ступор и недоумение. Попытки погуглить и узнать, что такое рут, приведут вас на специализированные форумы, где вменяемого ответа вам не дадут, а лишь отправят читать ветку из 600 постов. Что ж, я попытаюсь помочь в этом вопросе.

Root — это фактически права супер-пользователя

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

Что такое root

Рут снимает все ограничения на взаимодействие с ОС

Root — это особая учетная запись в любой UNIX-подобной системе c супер-правами. Благодаря ей пользователь получает права на выполнение абсолютно любых манипуляций с ОС.

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

Если не вдаваться в нудные технические подробности, то запущенные от имени root-пользователя приложения имеют неограниченные права на доступ к любым данным в системе. В основном, конечно, рут-права нужны разработчикам. Благодаря им они создают прекрасные приложения, которые помогают простому пользователю и делают работу с системой удобнее и проще. За примерами далеко ходить не будем, сервис Titanium Backup, который может сделать бэкап всех данных на смартфоне, работает только с root-правами.

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

Зачем нужен root

Многие защищённые приложения вроде Сбербанк Онлайна могут перестать работать на рутированном устройстве

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

  • Увеличить максимальную громкость динамиков или наушников;
  • Откалибровать датчики освещенности;
  • Изменить интенсивность вибрации смартфона;
  • Увеличить или уменьшить максимальный и минимальный уровни яркости дисплея;
  • Отключить сжатие фото в JPEG и увеличить качество фото с камеры;
  • Удалить всю рекламу из системы и приложений, включая YouTube;
  • Удалить неудаляемые системные приложения и трекеры;
  • Оптимизировать работу аккумулятора и увеличить автономность смартфона.

Как сделать root-права

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

Практически — потому что существуют обходные способы разблокировки загрузчика с помощью специальных кодов, которые продают сотрудники компаний, выпускающих аппараты. Но, во-первых, стоят они довольно много (около 60-80 долларов), а, во-вторых, велик риск наткнуться на мошенника, у которого никакого кода, к сожалению, не имеется. Поэтому лучше оставить эту затею.

Впрочем, если ваш смартфон позволяет разблокировать загрузчик, вот вам беглая инструкция на примере OnePlus 9 Pro. С более подробными положениями рекомендую ознакомиться в разделе вашего устройства на 4PDA.

  • Сохраните резервную копию на случай утери данных;
  • Перейдите в «Настройки» — «Для разработчика»;
  • Включите «Заводская разблокировка» и «Отладка по USB»;
  • Скачайте Fastboot/ADB на ПК и подключите смартфон к нему;
  • Запустите ADB, напишите в адресной строке cmd и нажмите Enter;

Если скачиваете непропатченный файл boot.img, его потребуется пропатчить

  • Затем пропишите в консоли adb devices, чтобы убедиться, что она видит ваш смартфон;
  • Согласитесь с отладкой и пропишите в консоли adb reboot bootloader;
  • Если вас перебросило в меню, то выберите english — advanced — reboot to fastboot;
  • Пропишите в консоли fastboot oem unlock, а на смартфоне кнопками громкости выберите unlock the bootloader и нажмите кнопку power;
  • Скачайте и установите Team Win Recovery Project (для каждого устройства свой);
  • Установите приложение Magisk, а затем, следуя инструкции на 4PDA, завершите процедуру получения рут-прав.

Я специально не даю ссылок, потому что для каждого устройства все файлы и конфигурации, которые нужно скачивать, отличаются. Все необходимые ссылки и инструкции вы найдёте на 4PDA, в разделе, посвящённом вашей модели смартфона. Но учитывайте, что OnePlus 9 и OnePlus 9 Pro — это разные аппараты. Если случайно установить несовместимый файл на несовместимое устройство, получится кирпич.

Стоит ли делать рут

Делать рут довольно опасно, да и рядовому пользователю абсолютно незачем

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

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

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

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *