VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Platform/Unix/Process.cpp
blob: 92a8f478883ec95d9ec7fc88b3ca1d60225fab51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 Derived from source code of TrueCrypt 7.1a, which is
 Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
 by the TrueCrypt License 3.0.

 Modifications and additions to the original source code (contained in this file)
 and all other portions of this file are Copyright (c) 2013-2016 IDRIX
 and are governed by the Apache License 2.0 the full text of which is
 contained in the file License.txt included in VeraCrypt binary and source
 code distribution packages.
*/

#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "Process.h"
#include "Platform/Exception.h"
#include "Platform/FileStream.h"
#include "Platform/ForEach.h"
#include "Platform/MemoryStream.h"
#include "Platform/SystemException.h"
#include "Platform/StringConverter.h"
#include "Platform/Unix/Pipe.h"
#include "Platform/Unix/Poller.h"

namespace VeraCrypt
{
	string Process::Execute (const string &processName, const list <string> &arguments, int timeOut, ProcessExecFunctor *execFunctor, const Buffer *inputData)
	{
		char *args[32];
		if (array_capacity (args) <= arguments.size())
			throw ParameterTooLarge (SRC_POS);

#if 0
		stringstream dbg;
		dbg << "exec " << processName;
		foreach (const string &at, arguments)
			dbg << " " << at;
		trace_msg (dbg.str());
#endif

		Pipe inPipe, outPipe, errPipe, exceptionPipe;

		int forkedPid = fork();
		throw_sys_if (forkedPid == -1);

		if (forkedPid == 0)
		{
			try
			{
				try
				{
					int argIndex = 0;
					/* Workaround for gcc 5.X issue related to the use of STL (string and list) with muliple fork calls.
					 *
					 * The char* pointers retrieved from the elements of parameter "arguments" are no longer valid after
					 * a second fork is called. "arguments" was created in the parent of the current child process.
					 *
					 * The only solution is to copy the elements of "arguments" parameter in a local string array on this
					 * child process and then use char* pointers retrieved from this local copies before calling fork.
					 *
					 * gcc 4.x doesn't suffer from this issue.
					 *
					 */
					string argsCopy[array_capacity (args)];
					if (!execFunctor)
					{
						argsCopy[argIndex++] = processName;
					}

					foreach (const string &arg, arguments)
					{
						argsCopy[argIndex++] = arg;
					}

					for (int i = 0; i < argIndex; i++)
					{
						args[i] = const_cast <char*> (argsCopy[i].c_str());
					}

					args[argIndex] = nullptr;

					if (inputData)
					{
						throw_sys_if (dup2 (inPipe.GetReadFD(), STDIN_FILENO) == -1);
					}
					else
					{
						inPipe.Close();
						int nullDev = open ("/dev/null", 0);
						throw_sys_sub_if (nullDev == -1, "/dev/null");
						throw_sys_if (dup2 (nullDev, STDIN_FILENO) == -1);
					}

					throw_sys_if (dup2 (outPipe.GetWriteFD(), STDOUT_FILENO) == -1);
					throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1);
					exceptionPipe.GetWriteFD();

					if (execFunctor)
					{
						(*execFunctor)(argIndex, args);
					}
					else
					{
						execvp (args[0], args);
						throw SystemException (SRC_POS, args[0]);
					}
				}
				catch (Exception &)
				{
					throw;
				}
				catch (exception &e)
				{
					throw ExternalException (SRC_POS, StringConverter::ToExceptionString (e));
				}
				catch (...)
				{
					throw UnknownException (SRC_POS);
				}
			}
			catch (Exception &e)
			{
				try
				{
					shared_ptr <Stream> outputStream (new FileStream (exceptionPipe.GetWriteFD()));
					e.Serialize (outputStream);
				}
				catch (...) { }
			}

			_exit (1);
		}

		throw_sys_if (fcntl (outPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
		throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
		throw_sys_if (fcntl (exceptionPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);

		vector <char> buffer (4096), stdOutput (4096), errOutput (4096), exOutput (4096);
		buffer.clear ();
		stdOutput.clear ();
		errOutput.clear ();
		exOutput.clear ();

		Poller poller (outPipe.GetReadFD(), errPipe.GetReadFD(), exceptionPipe.GetReadFD());
		int status, waitRes;

		if (inputData)
			throw_sys_if (write (inPipe.GetWriteFD(), inputData->Ptr(), inputData->Size()) == -1 && errno != EPIPE);

		inPipe.Close();

		int timeTaken = 0;
		do
		{
			const int pollTimeout = 200;
			try
			{
				ssize_t bytesRead = 0;
				foreach (int fd, poller.WaitForData (pollTimeout))
				{
					bytesRead = read (fd, &buffer[0], buffer.capacity());
					if (bytesRead > 0)
					{
						if (fd == outPipe.GetReadFD())
							stdOutput.insert (stdOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
						else if (fd == errPipe.GetReadFD())
							errOutput.insert (errOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
						else if (fd == exceptionPipe.GetReadFD())
							exOutput.insert (exOutput.end(), buffer.begin(), buffer.begin() + bytesRead);
					}
				}

				if (bytesRead == 0)
				{
					waitRes = waitpid (forkedPid, &status, 0);
					break;
				}
			}
			catch (TimeOut&)
			{
				timeTaken += pollTimeout;
				if (timeOut >= 0 && timeTaken >= timeOut)
					throw;
			}
		} while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0);
		throw_sys_if (waitRes == -1);

		if (!exOutput.empty())
		{
			auto_ptr <Serializable> deserializedObject;
			Exception *deserializedException = nullptr;

			try
			{
				shared_ptr <Stream> stream (new MemoryStream (ConstBufferPtr ((byte *) &exOutput[0], exOutput.size())));
				deserializedObject.reset (Serializable::DeserializeNew (stream));
				deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
			}
			catch (...)	{ }

			if (deserializedException)
				deserializedException->Throw();
		}

		int exitCode = (WIFEXITED (status) ? WEXITSTATUS (status) : 1);
		if (exitCode != 0)
		{
			string strErrOutput;

			if (!errOutput.empty())
				strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end());

			throw ExecutedProcessFailed (SRC_POS, processName, exitCode, strErrOutput);
		}

		string strOutput;

		if (!stdOutput.empty())
			strOutput.insert (strOutput.begin(), stdOutput.begin(), stdOutput.end());

		return strOutput;
	}
}
м, убедитесь, что выключено <em style="text-align:left">быстрое форматирование</em>. </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> В среде Windows убедитесь, что вы не удаляли никаких файлов в томе, внутри которого собираетесь создать скрытый том (при сканировании карты кластеров удалённые файлы не определяются). </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> В среде Linux или Mac OS X (macOS), если вы собираетесь создать скрытый том внутри тома VeraCrypt на основе файла, убедитесь, что этот том – не на основе разрежённого (sparse) файла (Windows-версия VeraCrypt это проверяет самостоятельно, не позволяя создавать скрытые тома внутри разрежённых файлов). </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Когда скрытый том смонтирован, операционная система и сторонние приложения могут выполнять запись в нескрытые тома (обычно в незашифрованный системный том) незашифрованной информации о данных, хранящихся в скрытом томе (например имена и расположение файлов, к которым недавно было обращение, базы данных, созданные утилитами индексирования файлов, и др.), самих данных в незашифрованном виде (временные файлы и т. п.), незашифрованной информации о файловой системе в скрытом томе (что может быть использовано, например, для идентификации файловой системы и определения, является ли файловая система той, что во внешнем томе), пароля/ключа для скрытого тома или других конфиденциальных данных. Поэтому необходимо соблюдать следующие требования и предостережения: <br style="text-align:left"> <ul style="text-align:left; margin-top:18px; margin-bottom:19px; padding-top:0px; padding-bottom:0px"> <li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <em style="text-align:left">Windows</em>: Создайте скрытую операционную систему (о том, как это сделать, см. раздел <a href="Hidden%20Operating%20System.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> Скрытая операционная система</a>) и монтируйте скрытые тома только тогда, когда запущена скрытая операционная система. <span style="text-align:left; font-size:10px; line-height:12px">Примечание. Когда работает скрытая операционная система, VeraCrypt гарантирует, что все локальные незашифрованные файловые системы и нескрытые тома VeraCrypt доступны только для чтения (то есть никакие файлы не могут быть записаны в такие файловые системы или тома VeraCrypt).<a href="#hidden_os_exception">*</a> Запись данных в файловые системы разрешена внутри <a href="Hidden%20Volume.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> скрытых томов VeraCrypt</a>.</span> В качестве альтернативного варианта, если применение скрытой операционной системы невозможно, используйте "live-CD" с системой Windows PE (целиком хранящейся на CD/DVD и оттуда же загружающейся), гарантирующей, что все данные, записываемые в системный том, записываются в RAM-диск (диск в ОЗУ). Монтируйте скрытые тома только тогда, когда работает система с такого "live-CD" (если нельзя использовать скрытую операционную систему). Кроме того, в течение такого "live-CD"-сеанса в режиме чтения-записи можно монтировать только файловые системы, расположенные в скрытых томах VeraCrypt (внешние или незашифрованные тома/файловые системы необходимо монтировать в режиме только для чтения, либо они не должны монтироваться/быть доступными вовсе). В противном случае вы должны удостовериться, что во время "live-CD"-сеанса приложения и операционная система не выполняют запись никаких конфиденциальных данных (см. выше) в нескрытые тома/файловые системы. </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <em style="text-align:left">Linux</em>: Загрузите или создайте версию "live-CD" вашей операционной системы (т. е. "live"-систему Linux, целиком хранящуюся на CD/DVD и оттуда же загружающуюся), это гарантирует, что любые записанные в системный том данные записаны в RAM-диск (диск в ОЗУ). Монтируйте скрытые тома только тогда, когда запущена такая "live-CD"-система. В течение сеанса только файловые системы внутри скрытых томов VeraCrypt могут быть смонтированы в режиме чтения-записи (внешние или незашифрованные тома/файловые системы должны монтироваться как только для чтения или оставаться вовсе несмонтированными/недоступными). Если вы не можете соблюсти это требование и не в состоянии гарантировать, что приложения и операционная система не выполняют запись никаких конфиденциальных данных (см. выше) в нескрытые тома/файловые системы, вы не должны монтировать или создавать скрытые тома VeraCrypt в среде Linux. </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <em style="text-align:left">Mac OS X</em>: Если вы не гарантируете, что приложения и операционная система не выполняют запись никаких конфиденциальных данных данных перечисленных выше критических типов в нескрытые тома (или файловые системы), монтировать или создавать скрытые тома VeraCrypt в среде Mac OS X нельзя. </li></ul> </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Когда смонтирован внешний том с включённой <a href="Protection%20of%20Hidden%20Volumes.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> защитой скрытого тома от повреждения</a> (см. раздел <a href="Protection%20of%20Hidden%20Volumes.html"> Защита скрытых томов от повреждения</a>), необходимо следовать тем же требованиям и предостережениям, что и при монтировании скрытого тома (см. выше). Причина этого в том, что из операционной системы может "утечь" пароль/ключ для скрытого тома в нескрытый или незашифрованный том.</li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Если вы используете <strong style="text-align:left">операционную систему, находящуюся внутри скрытого тома</strong> (см. раздел <a href="Hidden%20Operating%20System.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> Скрытая операционная система</a>), то в дополнение к вышесказанному необходимо соблюдать следующие требования безопасности и предостережения: <br style="text-align:left"> <ul style="text-align:left; margin-top:18px; margin-bottom:19px; padding-top:0px; padding-bottom:0px"> <li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Следует использовать обманную операционную систему так часто, как вы пользуетесь своим компьютером. В идеале её следует использовать всегда, когда не требуется задействовать засекреченные данные. В противном случае может пострадать правдоподобность отрицания наличия скрытой операционной системы (если вы сообщили неприятелю пароль от обманной операционной системы, он сможет выяснить, что эта система использовалась не слишком часто, что может навести на мысль о существовании в компьютере скрытой операционной системы). Обратите внимание, что вы можете сохранять данные в разделе с обманной системой в любой момент и без какого-либо риска повредить скрытый том (так как обманная система <i>не</i> установлена во внешнем томе). </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Если операционную систему требуется активировать, это нужно сделать до того, как она будет клонирована (клонирование это часть процесса создания скрытой ОС &mdash; см. раздел <a href="Hidden%20Operating%20System.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> Скрытая операционная система</a>), а скрытая операционная система (т. е. клон) никогда не должна быть активирована повторно. Причина в том, что скрытая операционная система создана путём копирования содержимого системного раздела в скрытый том (поэтому если операционная система не активирована, скрытая операционная система также будет неактивированной). В случае активации или повторной активации скрытой операционной системы, дата и время активации (и другая информация) могут быть зафиксированы на сервере Microsoft (и в скрытой операционной системе), но не в <a href="Hidden%20Operating%20System.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> обманной операционной системе</a>. Поэтому если неприятель получит доступ к сохранённым на сервере данным или перехватит ваш запрос серверу (и если вы сообщили ему пароль от обманной операционной системы), он сможет выяснить, что обманная операционная система была активирована (или повторно активирована) в другое время, а это способно навести на мысль о существовании в компьютере скрытой операционной системы. <br style="text-align:left"> По аналогичным причинам любое ПО, требующее активации, должно быть установлено и активировано до того, как вы приступите к созданию скрытой операционной системы. </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Когда вам нужно завершить работу скрытой операционной системы и запустить обманную систему, <i>не</i> перезагружайте компьютер. Вместо этого завершите работу системы или переведите её в состояние гибернации (сна), после чего оставьте компьютер выключенным в течение хотя бы нескольких минут (чем дольше, тем лучше), и только после этого включите его и загрузите обманную систему. Это требуется, чтобы очистить память, в которой могут содержаться конфиденциальные данные. Подробности см. в разделе <a href="Unencrypted%20Data%20in%20RAM.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> Незашифрованные данные в ОЗУ</a>, глава <a href="Security%20Requirements%20and%20Precautions.html" style="text-align:left; color:#0080c0; text-decoration:none.html"> Требования безопасности и меры предосторожности</a>. </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Компьютер может быть подключён к сети (в том числе к Интернету), только когда запущена обманная операционная система. Когда выполняется скрытая ОС, компьютер не следует подключать ни к какой сети, включая Интернет (один из самых надёжных способов гарантировать это – отключить от ПК кабель сетевого адаптера, если таковой имеется). Обратите внимание, что при загрузке данных с/на удалённый сервер, на сервере обычно фиксируются дата и время соединения и другая информация. Разного сорта данные также протоколируются и в операционной системе (например, данные автоматического обновления Windows, отчёты приложений, протоколы ошибок и т. п.). Таким образом, если неприятель получил доступ к хранящимся на сервере данным или перехватил ваш запрос серверу (и если вы сообщили ему пароль от обманной операционной системы), он сможет узнать, что соединение было выполнено не из обманной ОС, и это способно навести его на мысль о существовании в вашем компьютере скрытой операционной системы. <br style="text-align:left"> <br style="text-align:left"> Также имейте в виду, что аналогичные проблемы возможны, если у вас в среде скрытой операционной системы есть какие-либо файловые системы с общим доступом через сеть (вне зависимости от того, удалённая файловая система или локальная). Поэтому во время работы скрытой операционной системы никаких файловых систем с общим доступом по сети (в любом направлении) быть не должно.<br><br> </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Любые действия, которые могут быть обнаружены неприятелем (или любые действия, модифицирующие какие-либо данные вне смонтированных скрытых томов), должны выполняться, только когда работает обманная операционная система (если только у вас нет альтернативного правдоподобного объяснения, например, использование системы на "live-CD" для выполнения таких действий). Скажем, параметр <i>Автоматический переход на летнее время и обратно</i> можно включать только в обманной операционной системе. </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> Если BIOS, EFI или любой другой компонент журналирует выключения питания или любые другие события, которые могут свидетельствовать об использовании скрытого тома/системы (например, путём сравнения таких событий с событиями в протоколе Windows), вы обязаны либо отключить подобное журналирование, либо обеспечить надёжное удаление журнала после каждого сеанса (или иначе избежать подобной проблемы соответствующим образом). </li></ul> </li></ul> <div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px"> <br style="text-align:left"> В дополнение к вышесказанному необходимо соблюдать требования безопасности и меры предосторожности, перечисленные в следующих главах:</div> <ul style="text-align:left; margin-top:18px; margin-bottom:19px; padding-top:0px; padding-bottom:0px"> <li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <a href="Security%20Requirements%20and%20Precautions.html" style="text-align:left; color:#0080c0; text-decoration:none; font-weight:bold.html">Требования безопасности и меры предосторожности</a> </li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px"> <strong style="text-align:left"><a href="How%20to%20Back%20Up%20Securely.html" style="text-align:left; color:#0080c0; text-decoration:none.html">О безопасном резервном копировании</a></strong> </li></ul> <p><a href="VeraCrypt%20Hidden%20Operating%20System.html" style="text-align:left; color:#0080c0; text-decoration:none; font-weight:bold.html">Следующий раздел &gt;&gt;</a></p> <hr align="left" size="1" width="189" style="text-align:left; height:0px; border-width:0px 1px 1px; border-style:solid; border-color:#000000"> <p id="hidden_os_exception"><span style="text-align:left; font-size:10px; line-height:12px">* Это не относится к файловым системам на CD/DVD-подобных носителях, а также к пользовательским, нетипичным или нестандартным устройствам/носителям.</span></p> </div><div class="ClearBoth"></div></body></html>