ΠΠ΄ΡΠ°Π²ΠΎ, Π₯Π°Π±Ρ! ΠΠ΅Π½Π΅Ρ Π±ΠΈ ΡΠ°ΠΊΠ°Π» Π΄Π° Π·Π±ΠΎΡΡΠ²Π°ΠΌ Π·Π° ΡΠΎΠ° ΠΊΠ°ΠΊΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΈ Π·Π°ΡΡΠΈΡΠΈΡΠ΅ ΠΏΡΠΎΡΠ΅ΡΠΈΡΠ΅ ΠΎΠ΄ Π½Π°ΠΏΠ°Π΄ΠΈ ΠΎΠ΄ Π½Π°ΠΏΠ°ΡΠ°ΡΠΈ Π²ΠΎ macOS. ΠΠ° ΠΏΡΠΈΠΌΠ΅Ρ, ΠΎΠ²Π° Π΅ ΠΊΠΎΡΠΈΡΠ½ΠΎ Π·Π° Π°Π½ΡΠΈΠ²ΠΈΡΡΡ ΠΈΠ»ΠΈ ΡΠ΅Π·Π΅ΡΠ²Π΅Π½ ΡΠΈΡΡΠ΅ΠΌ, ΠΎΡΠΎΠ±Π΅Π½ΠΎ Π·Π°ΡΠΎΠ° ΡΡΠΎ ΠΏΠΎΠ΄ macOS ΠΏΠΎΡΡΠΎΡΠ°Ρ Π½Π΅ΠΊΠΎΠ»ΠΊΡ Π½Π°ΡΠΈΠ½ΠΈ Π΄Π° ΡΠ΅ βΡΠ±ΠΈΠ΅β ΠΏΡΠΎΡΠ΅Ρ. ΠΡΠΎΡΠΈΡΠ°ΡΡΠ΅ Π·Π° ΠΎΠ²Π° ΠΈ Π·Π° Π·Π°ΡΡΠΈΡΠ½ΠΈΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄ΠΈ ΠΏΠΎΠ΄ ΡΠ΅ΡΠ΅ΡΠ΅ΡΠΎ.
ΠΠ»Π°ΡΠΈΡΠ΅Π½ Π½Π°ΡΠΈΠ½ Π΄Π° ΡΠ΅ βΡΠ±ΠΈΠ΅β ΠΏΡΠΎΡΠ΅Ρ
ΠΠΎΠ±ΡΠΎ ΠΏΠΎΠ·Π½Π°Ρ Π½Π°ΡΠΈΠ½ Π΄Π° ΡΠ΅ βΡΠ±ΠΈΠ΅β ΠΏΡΠΎΡΠ΅Ρ Π΅ Π΄Π° ΡΠ΅ ΠΈΡΠΏΡΠ°ΡΠΈ ΡΠΈΠ³Π½Π°Π» SIGKILL Π΄ΠΎ ΠΏΡΠΎΡΠ΅ΡΠΎΡ. ΠΡΠ΅ΠΊΡ Π±Π°Ρ, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΈ ΠΏΠΎΠ²ΠΈΠΊΠ°ΡΠ΅ ΡΡΠ°Π½Π΄Π°ΡΠ΄Π½ΠΈΡΠ΅ βkill -SIGKILL PIDβ ΠΈΠ»ΠΈ βpkill -9 NAMEβ Π·Π° ΡΠ±ΠΈΡΡΠ²ΠΎ. ΠΠΎΠΌΠ°Π½Π΄Π°ΡΠ° βΡΠ±ΠΈΡβ Π΅ ΠΏΠΎΠ·Π½Π°ΡΠ° ΡΡΡΠ΅ ΠΎΠ΄ Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π½Π° UNIX ΠΈ Π΅ Π΄ΠΎΡΡΠ°ΠΏΠ½Π° Π½Π΅ ΡΠ°ΠΌΠΎ Π½Π° macOS, ΡΡΠΊΡ ΠΈ Π½Π° Π΄ΡΡΠ³ΠΈ ΡΠΈΡΡΠ΅ΠΌΠΈ ΡΠ»ΠΈΡΠ½ΠΈ Π½Π° UNIX.
ΠΡΡΠΎ ΠΊΠ°ΠΊΠΎ ΠΈ Π²ΠΎ ΡΠΈΡΡΠ΅ΠΌΠΈΡΠ΅ ΡΠ»ΠΈΡΠ½ΠΈ Π½Π° UNIX, macOS Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° ΠΏΡΠ΅ΡΡΠ΅ΡΠ½Π΅ΡΠ΅ ΠΊΠ°ΠΊΠ²ΠΈ Π±ΠΈΠ»ΠΎ ΡΠΈΠ³Π½Π°Π»ΠΈ Π΄ΠΎ ΠΏΡΠΎΡΠ΅Ρ ΠΎΡΠ²Π΅Π½ Π΄Π²Π° - SIGKILL ΠΈ SIGSTOP. ΠΠ²Π°Π° ΡΡΠ°ΡΠΈΡΠ° ΠΏΡΠ²Π΅Π½ΡΡΠ²Π΅Π½ΠΎ ΡΠ΅ ΡΠ΅ ΡΠΎΠΊΡΡΠΈΡΠ° Π½Π° ΡΠΈΠ³Π½Π°Π»ΠΎΡ SIGKILL ΠΊΠ°ΠΊΠΎ ΡΠΈΠ³Π½Π°Π» ΡΡΠΎ ΠΏΡΠ΅Π΄ΠΈΠ·Π²ΠΈΠΊΡΠ²Π° ΡΠ½ΠΈΡΡΡΠ²Π°ΡΠ΅ Π½Π° ΠΏΡΠΎΡΠ΅Ρ.
ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠΈ Π½Π° macOS
ΠΠ° macOS, ΠΏΠΎΠ²ΠΈΠΊΠΎΡ Π½Π° ΡΠΈΡΡΠ΅ΠΌΠΎΡ Π·Π° ΡΠ±ΠΈΠ²Π°ΡΠ΅ Π²ΠΎ ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ XNU ΡΠ° ΠΏΠΎΠ²ΠΈΠΊΡΠ²Π° ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° psignal(SIGKILL,...). ΠΡΠ΄Π΅ Π΄Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄Π΅ΠΌΠ΅ Π΄Π° Π²ΠΈΠ΄ΠΈΠΌΠ΅ ΠΊΠΎΠΈ Π΄ΡΡΠ³ΠΈ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈ Π΄Π΅ΡΡΡΠ²Π° Π²ΠΎ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈΠΎΡ ΠΏΡΠΎΡΡΠΎΡ ΠΌΠΎΠΆΠ°Ρ Π΄Π° ΡΠ΅ Π½Π°ΡΠ΅ΡΠ°Ρ ΡΠΎ ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° psignal. ΠΡΠ΄Π΅ Π΄Π° Π³ΠΈ ΠΎΡΡΡΡΠ°Π½ΠΈΠΌΠ΅ ΠΏΠΎΠ²ΠΈΡΠΈΡΠ΅ Π΄ΠΎ ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° psignal Π²ΠΎ Π²Π½Π°ΡΡΠ΅ΡΠ½ΠΈΡΠ΅ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΠΈ Π½Π° ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ (ΠΈΠ°ΠΊΠΎ ΠΌΠΎΠΆΠ΅Π±ΠΈ ΡΠ΅ Π½Π΅ΡΡΠΈΠ²ΠΈΡΠ°Π»Π½ΠΈ, ΡΠ΅ Π³ΠΈ ΠΎΡΡΠ°Π²ΠΈΠΌΠ΅ Π·Π° Π΄ΡΡΠ³Π° ΡΡΠ°ΡΠΈΡΠ° π - ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΠΏΠΎΡΠΏΠΈΡ, Π³ΡΠ΅ΡΠΊΠΈ Π²ΠΎ ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ°ΡΠ°, ΡΠ°ΠΊΡΠ²Π°ΡΠ΅ ΡΠΎ ΠΈΠ·Π»Π΅Π·/ΠΊΡΠ°Ρ, ΠΏΡΠ΅ΠΊΡΡΡΠ²Π°ΡΠ΅ Π½Π° Π·Π°ΡΡΠΈΡΠ°ΡΠ° Π½Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈ ΠΈΡΠ½. .
ΠΠ° Π³ΠΎ Π·Π°ΠΏΠΎΡΠ½Π΅ΠΌΠ΅ ΠΏΡΠ΅Π³Π»Π΅Π΄ΠΎΡ ΡΠΎ ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° ΠΈ ΡΠΎΠΎΠ΄Π²Π΅ΡΠ½ΠΈΠΎΡ ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈ ΠΏΠΎΠ²ΠΈΠΊ . Π‘Π΅ Π³Π»Π΅Π΄Π° Π΄Π΅ΠΊΠ° ΠΏΠΎΠΊΡΠ°Ρ ΠΊΠ»Π°ΡΠΈΡΠ½ΠΈΠΎΡ ΠΏΠΎΠ²ΠΈΠΊ Π·Π° ΡΠ±ΠΈΠ²Π°ΡΠ΅, ΠΏΠΎΡΡΠΎΠΈ ΠΈ Π°Π»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π΅Π½ ΠΏΡΠΈΡΡΠ°ΠΏ ΠΊΠΎΡ Π΅ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅Π½ Π·Π° ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΈΠΎΡ ΡΠΈΡΡΠ΅ΠΌ macOS ΠΈ Π³ΠΎ Π½Π΅ΠΌΠ° Π²ΠΎ BSD. ΠΡΠΈΠ½ΡΠΈΠΏΠΈΡΠ΅ Π½Π° ΡΠ°Π±ΠΎΡΠ° Π½Π° Π΄Π²Π°ΡΠ° ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈ ΠΏΠΎΠ²ΠΈΡΠΈ ΡΠ΅ ΠΈΡΡΠΎ ΡΠ°ΠΊΠ° ΡΠ»ΠΈΡΠ½ΠΈ. Π’ΠΈΠ΅ ΡΠ΅ Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΈ ΠΏΠΎΠ²ΠΈΡΠΈ Π΄ΠΎ ΠΏΡΠΈΠ³Π½Π°Π»ΠΎΡ Π½Π° ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° Π½Π° ΡΠ°Π΄ΡΠΎΡΠΎ. ΠΡΡΠΎ ΡΠ°ΠΊΠ°, Π·Π°Π±Π΅Π»Π΅ΠΆΠ΅ΡΠ΅ Π΄Π΅ΠΊΠ° ΠΏΡΠ΅Π΄ Π΄Π° ΡΠ΅ ΡΠ±ΠΈΠ΅ ΠΏΡΠΎΡΠ΅Ρ, ΡΠ΅ Π²ΡΡΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° βΠΊΠ°Π½ΡΠΈΠ³Π½Π°Π»β - Π΄Π°Π»ΠΈ ΠΏΡΠΎΡΠ΅ΡΠΎΡ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΡΠΏΡΠ°ΡΠΈ ΡΠΈΠ³Π½Π°Π» Π΄ΠΎ Π΄ΡΡΠ³ ΠΏΡΠΎΡΠ΅Ρ; ΡΠΈΡΡΠ΅ΠΌΠΎΡ Π½Π΅ Π΄ΠΎΠ·Π²ΠΎΠ»ΡΠ²Π° Π½ΠΈΡΡ Π΅Π΄Π½Π° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° Π΄Π° Π³ΠΈ ΡΠ±ΠΈΠ΅ ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈΡΠ΅ ΠΏΡΠΎΡΠ΅ΡΠΈ, Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ.
static int
terminate_with_payload_internal(struct proc *cur_proc, int target_pid, uint32_t reason_namespace,
uint64_t reason_code, user_addr_t payload, uint32_t payload_size,
user_addr_t reason_string, uint64_t reason_flags)
{
...
target_proc = proc_find(target_pid);
...
if (!cansignal(cur_proc, cur_cred, target_proc, SIGKILL)) {
proc_rele(target_proc);
return EPERM;
}
...
if (target_pid == cur_proc->p_pid) {
/*
* psignal_thread_with_reason() will pend a SIGKILL on the specified thread or
* return if the thread and/or task are already terminating. Either way, the
* current thread won't return to userspace.
*/
psignal_thread_with_reason(target_proc, current_thread(), SIGKILL, signal_reason);
} else {
psignal_with_reason(target_proc, SIGKILL, signal_reason);
}
...
}
Π»Π°Π½ΡΠΈΡΠ°Π½
ΠΠΎΠ²Π΅Π΄Π΅Π½ Π΅ ΡΡΠ°Π½Π΄Π°ΡΠ΄Π½ΠΈΠΎΡ Π½Π°ΡΠΈΠ½ Π·Π° ΡΠΎΠ·Π΄Π°Π²Π°ΡΠ΅ Π΄Π΅ΠΌΠΎΠ½ΠΈ ΠΏΡΠΈ ΡΡΠ°ΡΡΡΠ²Π°ΡΠ΅ Π½Π° ΡΠΈΡΡΠ΅ΠΌΠΎΡ ΠΈ ΠΊΠΎΠ½ΡΡΠΎΠ»Π° Π½Π° Π½ΠΈΠ²Π½ΠΈΠΎΡ ΠΆΠΈΠ²ΠΎΡΠ΅Π½ Π²Π΅ΠΊ. ΠΠΌΠ°ΡΡΠ΅ ΠΏΡΠ΅Π΄Π²ΠΈΠ΄ Π΄Π΅ΠΊΠ° ΠΈΠ·Π²ΠΎΡΠΈΡΠ΅ ΡΠ΅ Π·Π° ΡΡΠ°ΡΠ°ΡΠ° Π²Π΅ΡΠ·ΠΈΡΠ° Π½Π° launchctl Π΄ΠΎ macOS 10.10, ΠΏΡΠΈΠΌΠ΅ΡΠΈ Π½Π° ΠΊΠΎΠ΄ ΡΠ΅ Π΄Π°Π΄Π΅Π½ΠΈ Π·Π° ΠΈΠ»ΡΡΡΡΠ°ΡΠΈΠ²Π½ΠΈ ΡΠ΅Π»ΠΈ. Π‘ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½ΠΈΠΎΡ launchctl ΠΈΡΠΏΡΠ°ΡΠ° Π»Π°Π½ΡΠΈΡΠ°Π½ΠΈ ΡΠΈΠ³Π½Π°Π»ΠΈ ΠΏΡΠ΅ΠΊΡ XPC, Π»ΠΎΠ³ΠΈΠΊΠ°ΡΠ° launchctl Π΅ ΠΏΡΠ΅ΠΌΠ΅ΡΡΠ΅Π½Π° Π²ΠΎ Π½Π΅Π³ΠΎ.
ΠΡΠ΄Π΅ Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌΠ΅ ΠΊΠ°ΠΊΠΎ ΡΠΎΡΠ½ΠΎ ΡΠ΅ ΡΡΠΎΠΏΠΈΡΠ°Π°Ρ Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈΡΠ΅. ΠΡΠ΅Π΄ Π΄Π° ΡΠ΅ ΠΈΡΠΏΡΠ°ΡΠΈ ΡΠΈΠ³Π½Π°Π»ΠΎΡ SIGTERM, Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° ΡΠ΅ ΠΎΠ±ΠΈΠ΄ΡΠ²Π° Π΄Π° ΡΠ΅ ΠΏΡΠ΅ΠΊΠΈΠ½Π΅ ΡΠΎ ΠΏΠΎΠΌΠΎΡ Π½Π° ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈΠΎΡ ΠΏΠΎΠ²ΠΈΠΊ βproc_terminateβ.
<launchctl src/core.c>
...
error = proc_terminate(j->p, &sig);
if (error) {
job_log(j, LOG_ERR | LOG_CONSOLE, "Could not terminate job: %d: %s", error, strerror(error));
job_log(j, LOG_NOTICE | LOG_CONSOLE, "Using fallback option to terminate job...");
error = kill2(j->p, SIGTERM);
if (error) {
job_log(j, LOG_ERR, "Could not signal job: %d: %s", error, strerror(error));
}
...
<>
ΠΠΎΠ΄ Ρ Π°ΡΠ±Π°ΡΠ°, proc_terminate, ΠΈ ΠΏΠΎΠΊΡΠ°Ρ Π½Π΅Π³ΠΎΠ²ΠΎΡΠΎ ΠΈΠΌΠ΅, ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΡΠΏΡΠ°ΡΠΈ Π½Π΅ ΡΠ°ΠΌΠΎ psignal ΡΠΎ SIGTERM, ΡΡΠΊΡ ΠΈ SIGKILL.
ΠΠ½Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ ΡΠ±ΠΈΡΡΠ²ΠΎ - ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΡΠ΅ Π½Π° ΡΠ΅ΡΡΡΡΠΈΡΠ΅
ΠΠΎΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ ΡΠ»ΡΡΠ°Ρ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π²ΠΈΠ΄ΠΈ Π²ΠΎ Π΄ΡΡΠ³ ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈ ΠΏΠΎΠ²ΠΈΠΊ . ΠΠΎΠΎΠ±ΠΈΡΠ°Π΅Π½Π° ΡΠΏΠΎΡΡΠ΅Π±Π° Π½Π° ΠΎΠ²ΠΎΡ ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈ ΠΏΠΎΠ²ΠΈΠΊ Π΅ Π΄Π° ΡΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ°Ρ ΡΠ΅ΡΡΡΡΠΈΡΠ΅ Π½Π° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ°, ΠΊΠ°ΠΊΠΎ ΡΡΠΎ Π΅ ΠΈΠ½Π΄Π΅ΠΊΡΠ°ΡΠΎΡΠΎΡ Π΄Π° Π³ΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈ Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π½Π° ΠΏΡΠΎΡΠ΅ΡΠΎΡΠΎΡ ΠΈ ΠΊΠ²ΠΎΡΠΈΡΠ΅ Π½Π° ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ°ΡΠ°, ΡΠ°ΠΊΠ° ΡΡΠΎ ΡΠΈΡΡΠ΅ΠΌΠΎΡ Π½Π΅ Π΅ Π·Π½Π°ΡΠΈΡΠ΅Π»Π½ΠΎ Π·Π°Π±Π°Π²Π΅Π½ ΠΎΠ΄ Π°ΠΊΡΠΈΠ²Π½ΠΎΡΡΠΈΡΠ΅ Π·Π° ΠΊΠ΅ΡΠΈΡΠ°ΡΠ΅ Π½Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈ. ΠΠΊΠΎ Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π³ΠΎ Π΄ΠΎΡΡΠΈΠ³Π½Π°Π»Π° ΡΠ²ΠΎΡΠΎΡ Π»ΠΈΠΌΠΈΡ Π½Π° ΡΠ΅ΡΡΡΡΠΈ, ΠΊΠ°ΠΊΠΎ ΡΡΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π²ΠΈΠ΄ΠΈ ΠΎΠ΄ ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° proc_apply_resource_actions, ΡΠΈΠ³Π½Π°Π»ΠΎΡ SIGKILL ΡΠ΅ ΠΈΡΠΏΡΠ°ΡΠ° Π΄ΠΎ ΠΏΡΠΎΡΠ΅ΡΠΎΡ.
ΠΠ°ΠΊΠΎ ΠΎΠ²ΠΎΡ ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈ ΠΏΠΎΠ²ΠΈΠΊ ΠΏΠΎΡΠ΅Π½ΡΠΈΡΠ°Π»Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ±ΠΈΠ΅ ΠΏΡΠΎΡΠ΅Ρ, ΡΠΈΡΡΠ΅ΠΌΠΎΡ Π½Π΅ Π³ΠΈ ΠΏΡΠΎΠ²Π΅ΡΠΈ ΡΠΎΠΎΠ΄Π²Π΅ΡΠ½ΠΎ ΠΏΡΠ°Π²Π°ΡΠ° Π½Π° ΠΏΡΠΎΡΠ΅ΡΠΎΡ ΡΡΠΎ Π³ΠΎ ΠΏΠΎΠ²ΠΈΠΊΡΠ²Π° ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈΠΎΡ ΠΏΠΎΠ²ΠΈΠΊ. ΠΡΡΡΠ½ΠΎΡΡ ΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΡΠ²Π° , Π½ΠΎ Π΄ΠΎΠ²ΠΎΠ»Π½ΠΎ Π΅ Π΄Π° ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ Π°Π»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΠΎΡΠΎ Π·Π½Π°ΠΌΠ΅Π½ΡΠ΅ PROC_POLICY_ACTION_SET Π·Π° Π΄Π° ΡΠ΅ Π·Π°ΠΎΠ±ΠΈΠΊΠΎΠ»ΠΈ ΠΎΠ²Π°Π° ΡΠΎΡΡΠΎΡΠ±Π°.
ΠΡΡΡΠΊΠ°, Π°ΠΊΠΎ ΡΠ° βΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡΠ΅β ΠΊΠ²ΠΎΡΠ°ΡΠ° Π·Π° ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π½Π° ΠΏΡΠΎΡΠ΅ΡΠΎΡΠΎΡ Π½Π° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° (Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ, Π΄ΠΎΠ·Π²ΠΎΠ»ΡΠ²Π°ΡΡΠΈ ΡΠ°ΠΌΠΎ 1 ns Π΄Π° ΡΠ°Π±ΠΎΡΠΈ), ΡΠΎΠ³Π°Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΎ ΡΠ±ΠΈΠ΅ΡΠ΅ ΡΠ΅ΠΊΠΎΡ ΠΏΡΠΎΡΠ΅Ρ Π²ΠΎ ΡΠΈΡΡΠ΅ΠΌΠΎΡ. Π’Π°ΠΊΠ°, ΠΌΠ°Π»ΠΈΡΠΈΠΎΠ·Π½ΠΈΠΎΡ ΡΠΎΡΡΠ²Π΅Ρ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ±ΠΈΠ΅ ΠΊΠΎΡ Π±ΠΈΠ»ΠΎ ΠΏΡΠΎΡΠ΅Ρ Π½Π° ΡΠΈΡΡΠ΅ΠΌΠΎΡ, Π²ΠΊΠ»ΡΡΡΠ²Π°ΡΡΠΈ Π³ΠΎ ΠΈ Π°Π½ΡΠΈΠ²ΠΈΡΡΡΠ½ΠΈΠΎΡ ΠΏΡΠΎΡΠ΅Ρ. ΠΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ Π΅ ΠΈ Π΅ΡΠ΅ΠΊΡΠΎΡ ΡΡΠΎ ΡΠ΅ ΡΠ°Π²ΡΠ²Π° ΠΏΡΠΈ ΡΠ±ΠΈΠ²Π°ΡΠ΅ Π½Π° ΠΏΡΠΎΡΠ΅Ρ ΡΠΎ pid 1 (launchctl) - ΠΏΠ°Π½ΠΈΠΊΠ° Π½Π° ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ ΠΊΠΎΠ³Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄ΡΠ²Π°ΡΠ΅ Π΄Π° Π³ΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΈΡΠ΅ ΡΠΈΠ³Π½Π°Π»ΠΎΡ SIGKILL :)

ΠΠ°ΠΊΠΎ Π΄Π° ΡΠ΅ ΡΠ΅ΡΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΡ?
ΠΠ°ΡΠ΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΈΠΎΡ Π½Π°ΡΠΈΠ½ Π΄Π° ΡΠ΅ ΡΠΏΡΠ΅ΡΠΈ ΡΠ½ΠΈΡΡΡΠ²Π°ΡΠ΅ Π½Π° ΠΏΡΠΎΡΠ΅Ρ Π΅ Π΄Π° ΡΠ΅ Π·Π°ΠΌΠ΅Π½ΠΈ ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π°ΡΠΎΡ Π½Π° ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° Π²ΠΎ ΡΠ°Π±Π΅Π»Π°ΡΠ° Π·Π° ΡΠΈΡΡΠ΅ΠΌΡΠΊΠΈ ΠΏΠΎΠ²ΠΈΡΠΈ. ΠΠ° ΠΆΠ°Π», ΠΎΠ²ΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ Π΅ Π½Π΅ΡΡΠΈΠ²ΠΈΡΠ°Π»Π΅Π½ ΠΏΠΎΡΠ°Π΄ΠΈ ΠΌΠ½ΠΎΠ³Ρ ΠΏΡΠΈΡΠΈΠ½ΠΈ.
ΠΡΠ²ΠΎ, ΡΠΈΠΌΠ±ΠΎΠ»ΠΎΡ ΡΡΠΎ ΡΠ° ΠΊΠΎΠ½ΡΡΠΎΠ»ΠΈΡΠ° ΠΌΠ΅ΠΌΠΎΡΠΈΡΠΊΠ°ΡΠ° Π»ΠΎΠΊΠ°ΡΠΈΡΠ° Π½Π° sysent Π½Π΅ Π΅ ΡΠ°ΠΌΠΎ ΠΏΡΠΈΠ²Π°ΡΠ΅Π½ Π·Π° ΡΠΈΠΌΠ±ΠΎΠ»ΠΎΡ Π½Π° ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ XNU, ΡΡΠΊΡ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π½Π°ΡΠ΄Π΅ Π²ΠΎ ΡΠΈΠΌΠ±ΠΎΠ»ΠΈΡΠ΅ Π½Π° ΡΠ°Π΄ΡΠΎΡΠΎ. ΠΠ΅ ΠΌΠΎΡΠ° Π΄Π° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ Ρ Π΅ΡΡΠΈΡΡΠΈΡΠΊΠΈ ΠΌΠ΅ΡΠΎΠ΄ΠΈ Π·Π° ΠΏΡΠ΅Π±Π°ΡΡΠ²Π°ΡΠ΅, ΠΊΠ°ΠΊΠΎ ΡΡΠΎ Π΅ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠΊΠΎ ΡΠ°ΡΠΊΠ»ΠΎΠΏΡΠ²Π°ΡΠ΅ Π½Π° ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° ΠΈ ΠΏΡΠ΅Π±Π°ΡΡΠ²Π°ΡΠ΅ Π½Π° ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π°Ρ Π²ΠΎ Π½Π΅Π°.
ΠΡΠΎΡΠΎ, ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° Π½Π° Π·Π°ΠΏΠΈΡΠΈΡΠ΅ Π²ΠΎ ΡΠ°Π±Π΅Π»Π°ΡΠ° Π·Π°Π²ΠΈΡΠΈ ΠΎΠ΄ Π·Π½Π°ΠΌΠ΅Π½ΡΠ°ΡΠ° ΡΠΎ ΠΊΠΎΠΈ Π΅ ΡΠΎΡΡΠ°Π²Π΅Π½ΠΎ ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ. ΠΠΊΠΎ ΡΠ΅ Π΄Π΅ΠΊΠ»Π°ΡΠΈΡΠ° Π·Π½Π°ΠΌΠ΅ΡΠΎ CONFIG_REQUIRES_U32_MUNGING, Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°ΡΠ° Π½Π° ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° ΡΠ΅ ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ - ΡΠ΅ ΡΠ΅ Π΄ΠΎΠ΄Π°Π΄Π΅ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»Π½ΠΎ ΠΏΠΎΠ»Π΅ . ΠΠ΅ΠΎΠΏΡ ΠΎΠ΄Π½ΠΎ Π΅ Π΄Π° ΡΠ΅ ΠΈΠ·Π²ΡΡΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»Π½Π° ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π·Π° Π΄Π° ΡΠ΅ ΡΡΠ²ΡΠ΄ΠΈ ΡΠΎ ΠΊΠΎΠ΅ Π·Π½Π°ΠΌΠ΅Π½ΡΠ΅ Π΅ ΡΠΎΡΡΠ°Π²Π΅Π½ΠΎ ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ, ΠΈΠ»ΠΈ Π°Π»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΠΎ, Π΄Π° ΡΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠ°Ρ ΡΡΠ½ΠΊΡΠΈΡΠΊΠΈΡΠ΅ ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π°ΡΠΈ ΠΏΡΠΎΡΠΈΠ² ΠΏΠΎΠ·Π½Π°ΡΠΈΡΠ΅.
struct sysent { /* system call table */
sy_call_t *sy_call; /* implementing function */
#if CONFIG_REQUIRES_U32_MUNGING || (__arm__ && (__BIGGEST_ALIGNMENT__ > 4))
sy_munge_t *sy_arg_munge32; /* system call arguments munger for 32-bit process */
#endif
int32_t sy_return_type; /* system call return types */
int16_t sy_narg; /* number of args */
uint16_t sy_arg_bytes; /* Total size of arguments in bytes for
* 32-bit system calls
*/
};
ΠΠ° ΡΡΠ΅ΡΠ°, Π²ΠΎ ΠΌΠΎΠ΄Π΅ΡΠ½ΠΈΡΠ΅ Π²Π΅ΡΠ·ΠΈΠΈ Π½Π° macOS, Apple ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡΠ²Π° Π½ΠΎΠ²ΠΎ API Π·Π° ΡΠ°Π±ΠΎΡΠ° ΡΠΎ ΠΏΡΠΎΡΠ΅ΡΠΈ. Endpoint Security API ΠΈΠΌ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π½Π° ΠΊΠ»ΠΈΠ΅Π½ΡΠΈΡΠ΅ Π΄Π° ΠΎΠ²Π»Π°ΡΡΠ°Ρ ΠΌΠ½ΠΎΠ³Ρ Π±Π°ΡΠ°ΡΠ° Π·Π° Π΄ΡΡΠ³ΠΈ ΠΏΡΠΎΡΠ΅ΡΠΈ. Π’Π°ΠΊΠ°, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π±Π»ΠΎΠΊΠΈΡΠ°ΡΠ΅ ΠΊΠ°ΠΊΠ²ΠΈ Π±ΠΈΠ»ΠΎ ΡΠΈΠ³Π½Π°Π»ΠΈ Π΄ΠΎ ΠΏΡΠΎΡΠ΅ΡΠΈΡΠ΅, Π²ΠΊΠ»ΡΡΡΠ²Π°ΡΡΠΈ Π³ΠΎ ΠΈ ΡΠΈΠ³Π½Π°Π»ΠΎΡ SIGKILL, ΠΊΠΎΡΠΈΡΡΠ΅ΡΡΠΈ Π³ΠΎ Π³ΠΎΡΠ΅ΡΠΏΠΎΠΌΠ΅Π½Π°ΡΠΈΠΎΡ API.
#include <bsm/libbsm.h>
#include <EndpointSecurity/EndpointSecurity.h>
#include <unistd.h>
int main(int argc, const char * argv[]) {
es_client_t* cli = nullptr;
{
auto res = es_new_client(&cli, ^(es_client_t * client, const es_message_t * message) {
switch (message->event_type) {
case ES_EVENT_TYPE_AUTH_SIGNAL:
{
auto& msg = message->event.signal;
auto target = msg.target;
auto& token = target->audit_token;
auto pid = audit_token_to_pid(token);
printf("signal '%d' sent to pid '%d'n", msg.sig, pid);
es_respond_auth_result(client, message, pid == getpid() ? ES_AUTH_RESULT_DENY : ES_AUTH_RESULT_ALLOW, false);
}
break;
default:
break;
}
});
}
{
es_event_type_t evs[] = { ES_EVENT_TYPE_AUTH_SIGNAL };
es_subscribe(cli, evs, sizeof(evs) / sizeof(*evs));
}
printf("%dn", getpid());
sleep(60); // could be replaced with other waiting primitive
es_unsubscribe_all(cli);
es_delete_client(cli);
return 0;
}
Π‘Π»ΠΈΡΠ½ΠΎ, Π²ΠΎ ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠ° ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ° Π½Π° MAC, ΠΊΠΎΡΠ° ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡΠ²Π° ΠΌΠ΅ΡΠΎΠ΄ Π·Π° Π·Π°ΡΡΠΈΡΠ° Π½Π° ΡΠΈΠ³Π½Π°Π»ΠΎΡ (ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ° proc_check_signal), Π½ΠΎ API-ΡΠΎ Π½Π΅ Π΅ ΠΎΡΠΈΡΠΈΡΠ°Π»Π½ΠΎ ΠΏΠΎΠ΄Π΄ΡΠΆΠ°Π½ΠΎ.
ΠΠ°ΡΡΠΈΡΠ° Π·Π° ΠΏΡΠΎΡΠΈΡΡΠ²Π°ΡΠ΅ Π½Π° ΡΠ°Π΄ΡΠΎΡΠΎ
ΠΠΎΠΊΡΠ°Ρ Π·Π°ΡΡΠΈΡΠ°ΡΠ° Π½Π° ΠΏΡΠΎΡΠ΅ΡΠΈΡΠ΅ Π²ΠΎ ΡΠΈΡΡΠ΅ΠΌΠΎΡ, Π½Π΅ΠΎΠΏΡ ΠΎΠ΄Π½Π° Π΅ ΠΈ Π·Π°ΡΡΠΈΡΠ° Π½Π° ΡΠ°ΠΌΠ°ΡΠ° Π΅ΠΊΡΡΠ΅Π½Π·ΠΈΡΠ° Π½Π° ΡΠ°Π΄ΡΠΎΡΠΎ (kext). macOS ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡΠ²Π° ΡΠ°ΠΌΠΊΠ° Π·Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠΈΡΠ΅ Π»Π΅ΡΠ½ΠΎ Π΄Π° Π³ΠΈ ΡΠ°Π·Π²ΠΈΠ²Π°Π°Ρ Π΄ΡΠ°ΡΠ²Π΅ΡΠΈΡΠ΅ Π·Π° ΡΡΠ΅Π΄ΠΈΡΠ΅ IOKit. ΠΠΎΠΊΡΠ°Ρ ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡΠ²Π°ΡΠ΅ΡΠΎ Π°Π»Π°ΡΠΊΠΈ Π·Π° ΡΠ°Π±ΠΎΡΠ° ΡΠΎ ΡΡΠ΅Π΄ΠΈ, IOKit ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡΠ²Π° ΠΌΠ΅ΡΠΎΠ΄ΠΈ Π·Π° Π½Π°ΡΡΡΠΏΡΠ²Π°ΡΠ΅ Π½Π° Π΄ΡΠ°ΡΠ²Π΅ΡΠΈ ΠΊΠΎΡΠΈΡΡΠ΅ΡΡΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠΎΡΠΈ ΠΎΠ΄ ΠΊΠ»Π°ΡΠΈΡΠ΅ C++. ΠΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π²ΠΎ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈΠΎΡ ΠΏΡΠΎΡΡΠΎΡ ΡΠ΅ ΠΌΠΎΠΆΠ΅ Π΄Π° βΠΏΡΠΎΠ½Π°ΡΠ΄Π΅β ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠ°Π½ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠΊ ΠΎΠ΄ ΠΊΠ»Π°ΡΠ°ΡΠ° Π·Π° Π΄Π° Π²ΠΎΡΠΏΠΎΡΡΠ°Π²ΠΈ Π²ΡΡΠΊΠ° ΠΊΠ΅ΡΠ½Π΅Π»-ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈ ΠΏΡΠΎΡΡΠΎΡ.
ΠΠ° Π΄Π° ΡΠ΅ ΠΎΡΠΊΡΠΈΠ΅ Π±ΡΠΎΡΠΎΡ Π½Π° ΠΏΡΠΈΠΌΠ΅ΡΠΎΡΠΈ Π½Π° ΠΊΠ»Π°ΡΠΈ Π²ΠΎ ΡΠΈΡΡΠ΅ΠΌΠΎΡ, ΠΏΠΎΡΡΠΎΠΈ Π°Π»Π°ΡΠΊΠ°ΡΠ° ioclasscount.
my_kext_ioservice = 1
my_kext_iouserclient = 1
Π‘Π΅ΠΊΠΎΡΠ° Π΅ΠΊΡΡΠ΅Π½Π·ΠΈΡΠ° Π½Π° ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ ΡΡΠΎ ΡΠ°ΠΊΠ° Π΄Π° ΡΠ΅ ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠ° ΡΠΎ ΡΡΠ΅ΠΊΠΎΡ Π½Π° Π΄ΡΠ°ΡΠ²Π΅ΡΠΈ ΠΌΠΎΡΠ° Π΄Π° Π΄Π΅ΠΊΠ»Π°ΡΠΈΡΠ° ΠΊΠ»Π°ΡΠ° ΡΡΠΎ Π½Π°ΡΠ»Π΅Π΄ΡΠ²Π° ΠΎΠ΄ IOService, Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ my_kext_ioservice Π²ΠΎ ΠΎΠ²ΠΎΡ ΡΠ»ΡΡΠ°Ρ. ΠΠΎΠ²ΡΠ·ΡΠ²Π°ΡΠ΅ΡΠΎ Π½Π° ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈΡΠ΅ Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈ ΠΏΡΠ΅Π΄ΠΈΠ·Π²ΠΈΠΊΡΠ²Π° ΡΠΎΠ·Π΄Π°Π²Π°ΡΠ΅ Π½Π° Π½ΠΎΠ² ΠΏΡΠΈΠΌΠ΅ΡΠΎΠΊ ΠΎΠ΄ ΠΊΠ»Π°ΡΠ°ΡΠ° ΡΡΠΎ Π½Π°ΡΠ»Π΅Π΄ΡΠ²Π° ΠΎΠ΄ IOUserClient, Π²ΠΎ ΠΏΡΠΈΠΌΠ΅ΡΠΎΡ my_kext_iouserclient.
ΠΠΎΠ³Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄ΡΠ²Π°ΡΠ΅ Π΄Π° ΡΠ°ΡΡΠΎΠ²Π°ΡΠ°ΡΠ΅ Π΄ΡΠ°ΡΠ²Π΅Ρ ΠΎΠ΄ ΡΠΈΡΡΠ΅ΠΌΠΎΡ (ΠΊΠΎΠΌΠ°Π½Π΄Π° kextunload), ΡΠ΅ ΠΏΠΎΠ²ΠΈΠΊΡΠ²Π° Π²ΠΈΡΡΡΠ΅Π»Π½Π°ΡΠ° ΡΡΠ½ΠΊΡΠΈΡΠ° βbool terminate(IOOptionBits options)β. ΠΠΎΠ²ΠΎΠ»Π½ΠΎ Π΅ Π΄Π° ΡΠ΅ Π²ΡΠ°ΡΠΈ false Π½Π° ΠΏΠΎΠ²ΠΈΠΊΠΎΡ Π·Π° Π΄Π° ΡΠ΅ ΠΏΡΠ΅ΠΊΠΈΠ½Π΅ ΠΊΠΎΠ³Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄ΡΠ²Π°ΡΠ΅ Π΄Π° ΡΠ΅ ΠΈΡΡΠΎΠ²Π°ΡΠΈΡΠ΅ Π·Π° Π΄Π° ΡΠ΅ ΠΎΠ½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠΈ kextunload.
bool Kext::terminate(IOOptionBits options)
{
if (!IsUnloadAllowed)
{
// Unload is not allowed, returning false
return false;
}
return super::terminate(options);
}
ΠΠ½Π°ΠΌΠ΅ΡΠΎ IsUnloadAllowed ΠΌΠΎΠΆΠ΅ Π΄Π° Π³ΠΎ ΠΏΠΎΡΡΠ°Π²ΠΈ IOUserClient ΠΏΡΠΈ Π²ΡΠΈΡΡΠ²Π°ΡΠ΅. ΠΠΎΠ³Π° ΠΈΠΌΠ° ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΡΠ΅ Π·Π° ΠΏΡΠ΅Π·Π΅ΠΌΠ°ΡΠ΅, ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ° kextunload ΡΠ΅ Π³ΠΎ Π²ΡΠ°ΡΠΈ ΡΠ»Π΅Π΄Π½ΠΈΠΎΠ² ΠΈΠ·Π»Π΅Π·:
admin@admins-Mac drivermanager % sudo kextunload ./test.kext
Password:
(kernel) Can't remove kext my.kext.test; services failed to terminate - 0xe00002c7.
Failed to unload my.kext.test - (iokit/common) unsupported function.
Π‘Π»ΠΈΡΠ½Π° Π·Π°ΡΡΠΈΡΠ° ΠΌΠΎΡΠ° Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ Π·Π° IOUserClient. ΠΡΠΈΠΌΠ΅ΡΠΎΡΠΈΡΠ΅ Π½Π° ΠΊΠ»Π°ΡΠΈΡΠ΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΡΠ°ΡΡΠΎΠ²Π°ΡΠ°Ρ ΡΠΎ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π½Π° ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈ ΠΏΡΠΎΡΡΠΎΡ Π½Π° IOKitLib βIOCatalogueTerminate(mach_port_t, uint32_t Π·Π½Π°ΠΌΠ΅Π½ΡΠ΅, io_name_t ΠΎΠΏΠΈΡ); ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²ΡΠ°ΡΠΈΡΠ΅ Π½Π΅ΡΠΎΡΠ½ΠΎ ΠΊΠΎΠ³Π° ΡΠ° ΠΏΠΎΠ²ΠΈΠΊΡΠ²Π°ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Π°ΡΠ° βterminateβ Π΄ΠΎΠ΄Π΅ΠΊΠ° Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π·Π° ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΊΠΈ ΠΏΡΠΎΡΡΠΎΡ Π½Π΅ βΡΠΌΡΠ΅β, ΠΎΠ΄Π½ΠΎΡΠ½ΠΎ Π½Π΅ ΡΠ΅ ΠΏΠΎΠ²ΠΈΠΊΠ° ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ° βclientDiedβ.
ΠΠ°ΡΡΠΈΡΠ° Π½Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈ
ΠΠ° Π΄Π° Π³ΠΈ Π·Π°ΡΡΠΈΡΠΈΡΠ΅ Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈΡΠ΅, Π΄ΠΎΠ²ΠΎΠ»Π½ΠΎ Π΅ Π΄Π° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ Kauth API, ΠΊΠΎΡ Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° Π³ΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΡΠ΅ ΠΏΡΠΈΡΡΠ°ΠΏΠΎΡ Π΄ΠΎ Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈΡΠ΅. Apple ΠΈΠΌ Π΄Π°Π²Π° Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ΅ΡΠΈΡΠ΅ ΠΈΠ·Π²Π΅ΡΡΡΠ²Π°ΡΠ° Π·Π° ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ Π½Π°ΡΡΠ°Π½ΠΈ Π²ΠΎ ΠΎΠΏΡΠ΅Π³ΠΎΡ; Π·Π° Π½Π°Ρ, ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈΡΠ΅ KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ΠΈ KAUTH_VNODE_DELETE_CHILD ΡΠ΅ Π²Π°ΠΆΠ½ΠΈ. ΠΠ°ΡΠ»Π΅ΡΠ΅Π½ Π½Π°ΡΠΈΠ½ Π΄Π° ΡΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈ ΠΏΡΠΈΡΡΠ°ΠΏΠΎΡ Π΄ΠΎ Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈΡΠ΅ Π΅ ΠΏΠΎ ΠΏΠ°ΡΠ΅ΠΊΠ° - Π³ΠΎ ΠΊΠΎΡΠΈΡΡΠΈΠΌΠ΅ API βvn_getpathβ Π·Π° Π΄Π° ΡΠ° Π΄ΠΎΠ±ΠΈΠ΅ΠΌΠ΅ ΠΏΠ°ΡΠ΅ΠΊΠ°ΡΠ° Π΄ΠΎ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ°ΡΠ° ΠΈ Π΄Π° Π³ΠΎ ΡΠΏΠΎΡΠ΅Π΄ΠΈΠΌΠ΅ ΠΏΡΠ΅ΡΠΈΠΊΡΠΎΡ Π½Π° ΠΏΠ°ΡΠ΅ΠΊΠ°ΡΠ°. ΠΠ°Π±Π΅Π»Π΅ΠΆΠ΅ΡΠ΅ Π΄Π΅ΠΊΠ° Π·Π° Π΄Π° ΡΠ΅ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠ° ΠΏΡΠ΅ΠΈΠΌΠ΅Π½ΡΠ²Π°ΡΠ΅ΡΠΎ Π½Π° ΠΏΠ°ΡΠ΅ΠΊΠΈΡΠ΅ Π½Π° ΠΏΠ°ΠΏΠΊΠ°ΡΠ° ΡΠΎ Π΄Π°ΡΠΎΡΠ΅ΠΊΠΈ, ΡΠΈΡΡΠ΅ΠΌΠΎΡ Π½Π΅ Π΄ΠΎΠ·Π²ΠΎΠ»ΡΠ²Π° ΠΏΡΠΈΡΡΠ°ΠΏ Π΄ΠΎ ΡΠ΅ΠΊΠΎΡΠ° Π΄Π°ΡΠΎΡΠ΅ΠΊΠ°, ΡΡΠΊΡ ΡΠ°ΠΌΠΎ Π΄ΠΎ ΡΠ°ΠΌΠ°ΡΠ° ΠΏΠ°ΠΏΠΊΠ° ΡΡΠΎ Π΅ ΠΏΡΠ΅ΠΈΠΌΠ΅Π½ΡΠ²Π°Π½Π°. ΠΠ΅ΠΎΠΏΡ ΠΎΠ΄Π½ΠΎ Π΅ Π΄Π° ΡΠ΅ ΡΠΏΠΎΡΠ΅Π΄ΠΈ ΠΌΠ°ΡΠΈΡΠ½Π°ΡΠ° ΠΏΠ°ΡΠ΅ΠΊΠ° ΠΈ Π΄Π° ΡΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈ KAUTH_VNODE_DELETE Π·Π° Π½Π΅Π°.

ΠΠ΅Π΄ΠΎΡΡΠ°ΡΠΎΠΊ Π½Π° ΠΎΠ²ΠΎΡ ΠΏΡΠΈΡΡΠ°ΠΏ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π½ΠΈΡΠΊΠΈΡΠ΅ ΠΏΠ΅ΡΡΠΎΡΠΌΠ°Π½ΡΠΈ Π±ΠΈΠ΄Π΅ΡΡΠΈ Π±ΡΠΎΡΠΎΡ Π½Π° ΠΏΡΠ΅ΡΠΈΠΊΡΠΈ ΡΠ΅ Π·Π³ΠΎΠ»Π΅ΠΌΡΠ²Π°. ΠΠ° Π΄Π° ΡΠ΅ ΠΎΡΠΈΠ³ΡΡΠ°ΡΠ΅ Π΄Π΅ΠΊΠ° ΡΠΏΠΎΡΠ΅Π΄Π±Π°ΡΠ° Π½Π΅ Π΅ Π΅Π΄Π½Π°ΠΊΠ²Π° Π½Π° O (ΠΏΡΠ΅ΡΠΈΠΊΡ*Π΄ΠΎΠ»ΠΆΠΈΠ½Π°), ΠΊΠ°Π΄Π΅ ΡΡΠΎ ΠΏΡΠ΅ΡΠΈΠΊΡΠΎΡ Π΅ Π±ΡΠΎΡΠΎΡ Π½Π° ΠΏΡΠ΅ΡΠΈΠΊΡΠΈ, Π΄ΠΎΠ»ΠΆΠΈΠ½Π°ΡΠ° Π΅ Π΄ΠΎΠ»ΠΆΠΈΠ½Π°ΡΠ° Π½Π° Π½ΠΈΠ·Π°ΡΠ°, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ Π΄Π΅ΡΠ΅ΡΠΌΠΈΠ½ΠΈΡΡΠΈΡΠΊΠΈ ΠΊΠΎΠ½Π΅ΡΠ΅Π½ Π°Π²ΡΠΎΠΌΠ°Ρ (DFA) ΠΈΠ·Π³ΡΠ°Π΄Π΅Π½ ΡΠΎ ΠΏΡΠ΅ΡΠΈΠΊΡΠΈ.
ΠΡΠ΄Π΅ Π΄Π° ΡΠ°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΌΠ΅ΡΠΎΠ΄ Π·Π° ΠΊΠΎΠ½ΡΡΡΡΠΈΡΠ°ΡΠ΅ Π½Π° DFA Π·Π° Π΄Π°Π΄Π΅Π½ ΡΠ΅Ρ Π½Π° ΠΏΡΠ΅ΡΠΈΠΊΡΠΈ. ΠΠΈΠ΅ Π³ΠΈ ΠΈΠ½ΠΈΡΠΈΡΠ°Π»ΠΈΠ·ΠΈΡΠ°ΠΌΠ΅ ΠΊΡΡΡΠΎΡΠΈΡΠ΅ Π½Π° ΠΏΠΎΡΠ΅ΡΠΎΠΊΠΎΡ Π½Π° ΡΠ΅ΠΊΠΎΡ ΠΏΡΠ΅ΡΠΈΠΊΡ. ΠΠΊΠΎ ΡΠΈΡΠ΅ ΠΊΡΡΡΠΎΡΠΈ ΡΠΊΠ°ΠΆΡΠ²Π°Π°Ρ Π½Π° ΠΈΡΡΠΈΠΎΡ Π·Π½Π°ΠΊ, ΡΠΎΠ³Π°Ρ Π·Π³ΠΎΠ»Π΅ΠΌΠ΅ΡΠ΅ Π³ΠΎ ΡΠ΅ΠΊΠΎΡ ΠΊΡΡΡΠΎΡ Π·Π° Π΅Π΄Π΅Π½ Π·Π½Π°ΠΊ ΠΈ Π·Π°ΠΏΠΎΠΌΠ½Π΅ΡΠ΅ Π΄Π΅ΠΊΠ° Π΄ΠΎΠ»ΠΆΠΈΠ½Π°ΡΠ° Π½Π° ΠΈΡΡΠ°ΡΠ° Π»ΠΈΠ½ΠΈΡΠ° Π΅ ΠΏΠΎΠ³ΠΎΠ»Π΅ΠΌΠ° Π·Π° Π΅Π΄Π΅Π½. ΠΠΊΠΎ ΠΈΠΌΠ° Π΄Π²Π° ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π°ΡΠΈ ΡΠΎ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΡΠΈΠΌΠ±ΠΎΠ»ΠΈ, ΠΏΠΎΠ΄Π΅Π»Π΅ΡΠ΅ Π³ΠΈ ΠΊΡΡΡΠΎΡΠΈΡΠ΅ Π²ΠΎ Π³ΡΡΠΏΠΈ ΡΠΏΠΎΡΠ΅Π΄ ΡΠΈΠΌΠ±ΠΎΠ»ΠΎΡ ΠΊΠΎΠ½ ΠΊΠΎΡ ΡΠΊΠ°ΠΆΡΠ²Π°Π°Ρ ΠΈ ΠΏΠΎΠ²ΡΠΎΡΠ΅ΡΠ΅ Π³ΠΎ Π°Π»Π³ΠΎΡΠΈΡΠΌΠΎΡ Π·Π° ΡΠ΅ΠΊΠΎΡΠ° Π³ΡΡΠΏΠ°.
ΠΠΎ ΠΏΡΠ²ΠΈΠΎΡ ΡΠ»ΡΡΠ°Ρ (ΡΠΈΡΠ΅ Π·Π½Π°ΡΠΈ ΠΏΠΎΠ΄ ΠΊΡΡΡΠΎΡΠΈΡΠ΅ ΡΠ΅ ΠΈΡΡΠΈ), Π΄ΠΎΠ±ΠΈΠ²Π°ΠΌΠ΅ ΡΠΎΡΡΠΎΡΠ±Π° Π½Π° DFA ΠΊΠΎΡΠ° ΠΈΠΌΠ° ΡΠ°ΠΌΠΎ Π΅Π΄Π½Π° ΡΡΠ°Π½Π·ΠΈΡΠΈΡΠ° ΠΏΠΎ ΠΈΡΡΠ°ΡΠ° Π»ΠΈΠ½ΠΈΡΠ°. ΠΠΎ Π²ΡΠΎΡΠΈΠΎΡ ΡΠ»ΡΡΠ°Ρ, Π΄ΠΎΠ±ΠΈΠ²Π°ΠΌΠ΅ ΡΠ°Π±Π΅Π»Π° ΡΠΎ ΡΡΠ°Π½Π·ΠΈΡΠΈΠΈ ΡΠΎ Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π° 256 (Π±ΡΠΎΡ Π½Π° Π·Π½Π°ΡΠΈ ΠΈ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»Π΅Π½ Π±ΡΠΎΡ Π½Π° Π³ΡΡΠΏΠΈ) Π΄ΠΎ ΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ ΡΠΎΡΡΠΎΡΠ±ΠΈ Π΄ΠΎΠ±ΠΈΠ΅Π½ΠΈ ΡΠΎ ΡΠ΅ΠΊΡΡΠ·ΠΈΠ²Π½ΠΎ ΠΏΠΎΠ²ΠΈΠΊΡΠ²Π°ΡΠ΅ Π½Π° ΡΡΠ½ΠΊΡΠΈΡΠ°ΡΠ°.
ΠΡΠ΄Π΅ Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌΠ΅ Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ. ΠΠ° Π·Π±ΠΈΡ Π½Π° ΠΏΡΠ΅ΡΠΈΠΊΡΠΈ (β/foo/bar/tmp/β, β/var/db/foo/β, β/foo/bar/aba/β, βfoo/bar/aac/β) ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π³ΠΎ Π΄ΠΎΠ±ΠΈΠ΅ΡΠ΅ ΡΠ»Π΅Π΄Π½ΠΎΠ²ΠΎ DFA. Π‘Π»ΠΈΠΊΠ°ΡΠ° ΠΏΠΎΠΊΠ°ΠΆΡΠ²Π° ΡΠ°ΠΌΠΎ ΡΡΠ°Π½Π·ΠΈΡΠΈΠΈ ΠΊΠΎΠΈ Π²ΠΎΠ΄Π°Ρ ΠΊΠΎΠ½ Π΄ΡΡΠ³ΠΈ ΡΠΎΡΡΠΎΡΠ±ΠΈ; Π΄ΡΡΠ³ΠΈΡΠ΅ ΡΡΠ°Π½Π·ΠΈΡΠΈΠΈ Π½Π΅ΠΌΠ° Π΄Π° Π±ΠΈΠ΄Π°Ρ ΠΊΠΎΠ½Π΅ΡΠ½ΠΈ.

ΠΠΎΠ³Π° ΠΏΠΎΠΌΠΈΠ½ΡΠ²Π°ΡΠ΅ Π½ΠΈΠ· Π΄ΡΠΆΠ°Π²ΠΈΡΠ΅ DKA, ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° 3 ΡΠ»ΡΡΠ°ΠΈ.
- ΠΠΎΠ½Π΅ΡΠ½Π°ΡΠ° ΡΠΎΡΡΠΎΡΠ±Π° Π΅ ΠΏΠΎΡΡΠΈΠ³Π½Π°ΡΠ° - ΠΏΠ°ΡΠ΅ΠΊΠ°ΡΠ° Π΅ Π·Π°ΡΡΠΈΡΠ΅Π½Π°, Π³ΠΈ ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΠΌΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈΡΠ΅ KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ΠΈ KAUTH_VNODE_DELETE_CHILD
- ΠΠΎΠ½Π΅ΡΠ½Π°ΡΠ° ΡΠΎΡΡΠΎΡΠ±Π° Π½Π΅ Π±Π΅ΡΠ΅ ΠΏΠΎΡΡΠΈΠ³Π½Π°ΡΠ°, Π½ΠΎ ΠΏΠ°ΡΠ΅ΠΊΠ°ΡΠ° βΠ·Π°Π²ΡΡΠΈβ (Π΄ΠΎΡΡΠΈΠ³Π½Π°Ρ Π΅ Π½ΡΠ»Π° ΡΠ΅ΡΠΌΠΈΠ½Π°ΡΠΎΡ) - ΠΏΠ°ΡΠ΅ΠΊΠ°ΡΠ° Π΅ ΡΠΎΠ΄ΠΈΡΠ΅Π», Π½Π΅ΠΎΠΏΡ ΠΎΠ΄Π½ΠΎ Π΅ Π΄Π° ΡΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈ KAUTH_VNODE_DELETE. ΠΠ°Π±Π΅Π»Π΅ΠΆΠ΅ΡΠ΅ Π΄Π΅ΠΊΠ° Π°ΠΊΠΎ vnode Π΅ ΠΏΠ°ΠΏΠΊΠ°, ΡΡΠ΅Π±Π° Π΄Π° Π΄ΠΎΠ΄Π°Π΄Π΅ΡΠ΅ '/' Π½Π° ΠΊΡΠ°ΡΠΎΡ, Π²ΠΎ ΡΠΏΡΠΎΡΠΈΠ²Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ° ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈ Π½Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠ°ΡΠ° β/foor/bar/tβ, ΡΡΠΎ Π΅ Π½Π΅ΡΠΎΡΠ½ΠΎ.
- ΠΠΎΠ½Π΅ΡΠ½Π°ΡΠ° ΡΠΎΡΡΠΎΡΠ±Π° Π½Π΅ Π±Π΅ΡΠ΅ ΠΏΠΎΡΡΠΈΠ³Π½Π°ΡΠ°, ΠΏΠ°ΡΠΎΡ Π½Π΅ Π·Π°Π²ΡΡΠΈ. ΠΠΈΡΡ Π΅Π΄Π΅Π½ ΠΎΠ΄ ΠΏΡΠ΅ΡΠΈΠΊΡΠΈΡΠ΅ Π½Π΅ ΡΠ΅ ΡΠΎΠ²ΠΏΠ°ΡΠ° ΡΠΎ ΠΎΠ²ΠΎΡ, Π½Π΅ Π²ΠΎΠ²Π΅Π΄ΡΠ²Π°ΠΌΠ΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΡΠ°.
ΠΠ°ΠΊΠ»ΡΡΠΎΠΊ
Π¦Π΅Π»ΡΠ° Π½Π° Π±Π΅Π·Π±Π΅Π΄Π½ΠΎΡΠ½ΠΈΡΠ΅ ΡΠ΅ΡΠ΅Π½ΠΈΡΠ° ΡΡΠΎ ΡΠ΅ ΡΠ°Π·Π²ΠΈΠ²Π°Π°Ρ Π΅ Π΄Π° ΡΠ΅ Π·Π³ΠΎΠ»Π΅ΠΌΠΈ Π½ΠΈΠ²ΠΎΡΠΎ Π½Π° Π±Π΅Π·Π±Π΅Π΄Π½ΠΎΡΡ Π½Π° ΠΊΠΎΡΠΈΡΠ½ΠΈΠΊΠΎΡ ΠΈ Π½Π΅Π³ΠΎΠ²ΠΈΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ. ΠΠ΄ Π΅Π΄Π½Π° ΡΡΡΠ°Π½Π°, ΠΎΠ²Π°Π° ΡΠ΅Π» ΡΠ΅ ΠΏΠΎΡΡΠΈΠ³Π½ΡΠ²Π° ΡΠΎ ΡΠ°Π·Π²ΠΎΡΠΎΡ Π½Π° ΡΠΎΡΡΠ²Π΅ΡΡΠΊΠΈΠΎΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ Acronis, ΠΊΠΎΡ Π³ΠΈ Π·Π°ΡΠ²ΠΎΡΠ° ΠΎΠ½ΠΈΠ΅ ΠΏΡΠΎΠΏΡΡΡΠΈ ΠΊΠ°Π΄Π΅ ΡΡΠΎ ΡΠ°ΠΌΠΈΠΎΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π΅Π½ ΡΠΈΡΡΠ΅ΠΌ Π΅ βΡΠ»Π°Π±β. ΠΠ΄ Π΄ΡΡΠ³Π° ΡΡΡΠ°Π½Π°, Π½Π΅ ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΎ Π·Π°Π½Π΅ΠΌΠ°ΡΠΈΠΌΠ΅ Π·Π°ΡΠ°ΠΊΠ½ΡΠ²Π°ΡΠ΅ΡΠΎ Π½Π° ΠΎΠ½ΠΈΠ΅ Π±Π΅Π·Π±Π΅Π΄Π½ΠΎΡΠ½ΠΈ Π°ΡΠΏΠ΅ΠΊΡΠΈ ΡΡΠΎ ΠΌΠΎΠΆΠ°Ρ Π΄Π° ΡΠ΅ ΠΏΠΎΠ΄ΠΎΠ±ΡΠ°Ρ Π½Π° ΡΡΡΠ°Π½Π°ΡΠ° Π½Π° ΠΠ‘, ΠΎΡΠΎΠ±Π΅Π½ΠΎ Π·Π°ΡΠΎΠ° ΡΡΠΎ Π·Π°ΡΠ²ΠΎΡΠ°ΡΠ΅ΡΠΎ Π½Π° ΡΠ°ΠΊΠ²ΠΈΡΠ΅ ΠΏΡΠΎΠΏΡΡΡΠΈ ΡΠ° Π·Π³ΠΎΠ»Π΅ΠΌΡΠ²Π° Π½Π°ΡΠ°ΡΠ° ΡΠΎΠΏΡΡΠ²Π΅Π½Π° ΡΡΠ°Π±ΠΈΠ»Π½ΠΎΡΡ ΠΊΠ°ΠΊΠΎ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄. Π Π°Π½Π»ΠΈΠ²ΠΎΡΡΠ° Π±Π΅ΡΠ΅ ΠΏΡΠΈΡΠ°Π²Π΅Π½Π° Π΄ΠΎ ΡΠΈΠΌΠΎΡ Π·Π° Π±Π΅Π·Π±Π΅Π΄Π½ΠΎΡΡ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈ Π½Π° Apple ΠΈ Π΅ ΠΏΠΎΠΏΡΠ°Π²Π΅Π½Π° Π²ΠΎ macOS 10.14.5 (https://support.apple.com/en-gb/HT210119).

Π‘Π΅ΡΠΎ ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ ΡΠ°ΠΌΠΎ Π°ΠΊΠΎ Π²Π°ΡΠ°ΡΠ° Π°Π»Π°ΡΠΊΠ° Π΅ ΠΎΡΠΈΡΠΈΡΠ°Π»Π½ΠΎ ΠΈΠ½ΡΡΠ°Π»ΠΈΡΠ°Π½Π° Π²ΠΎ ΠΊΠ΅ΡΠ½Π΅Π»ΠΎΡ. ΠΠ΄Π½ΠΎΡΠ½ΠΎ, Π½Π΅ΠΌΠ° ΡΠ°ΠΊΠ²ΠΈ Π΄ΡΠΏΠΊΠΈ Π·Π° Π½Π°Π΄Π²ΠΎΡΠ΅ΡΠ΅Π½ ΠΈ Π½Π΅ΡΠ°ΠΊΠ°Π½ ΡΠΎΡΡΠ²Π΅Ρ. Π‘Π΅ΠΏΠ°ΠΊ, ΠΊΠ°ΠΊΠΎ ΡΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡΠ΅, Π΄ΡΡΠΈ ΠΈ Π·Π°ΡΡΠΈΡΠ°ΡΠ° Π½Π° Π»Π΅Π³ΠΈΡΠΈΠΌΠ½ΠΈΡΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈ ΠΊΠ°ΠΊΠΎ ΡΡΠΎ ΡΠ΅ Π°Π½ΡΠΈΠ²ΠΈΡΡΡΠ½ΠΈ ΠΈ ΡΠ΅Π·Π΅ΡΠ²Π½ΠΈ ΡΠΈΡΡΠ΅ΠΌΠΈ Π±Π°ΡΠ° ΡΠ°Π±ΠΎΡΠ°. ΠΠΎ, ΡΠ΅Π³Π° Π½ΠΎΠ²ΠΈΡΠ΅ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈ Π½Π° Acronis Π·Π° macOS ΡΠ΅ ΠΈΠΌΠ°Π°Ρ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»Π½Π° Π·Π°ΡΡΠΈΡΠ° ΠΎΠ΄ ΠΈΡΡΠΎΠ²Π°Ρ ΠΎΠ΄ ΡΠΈΡΡΠ΅ΠΌΠΎΡ.
ΠΠ·Π²ΠΎΡ: www.habr.com
