Чӣ тавр муҳофизат кардани равандҳо ва васеъшавии ядро ​​​​дар macOS

Салом, Хабр! Имрӯз ман мехоҳам дар бораи он сӯҳбат кунам, ки чӣ гуна шумо метавонед равандҳоро аз ҳамлаҳои ҳамлагарон дар macOS муҳофизат кунед. Масалан, ин барои антивирус ё системаи эҳтиётӣ муфид аст, хусусан азбаски дар macOS якчанд роҳҳои "куштани" раванд мавҷуданд. Дар бораи ин ва усулҳои муҳофизат дар зери набуред.

Чӣ тавр муҳофизат кардани равандҳо ва васеъшавии ядро ​​​​дар macOS

Роҳи классикии "куштани" раванд

Роҳи маъруфи "куштани" раванд ин фиристодани сигнали SIGKILL ба раванд мебошад. Тавассути bash шумо метавонед стандарти "kill -SIGKILL PID" ё "pkill -9 NAME" -ро барои куштан даъват кунед. Фармони "куштан" аз рӯзҳои UNIX маълум аст ва на танҳо дар macOS, балки дар дигар системаҳои ба UNIX монанд дастрас аст.

Мисли системаҳои ба UNIX монанд, macOS ба шумо имкон медиҳад, ки ҳама гуна сигналҳоро ба раванд, ба истиснои ду - SIGKILL ва SIGSTOP боздоред. Ин мақола пеш аз ҳама ба сигнали SIGKILL ҳамчун сигнале, ки боиси кушта шудани раванд мегардад, тамаркуз хоҳад кард.

мушаххасоти macOS

Дар macOS, занги системаи куштор дар ядрои XNU функсияи psignal(SIGKILL,...) -ро даъват мекунад. Биёед кӯшиш кунем, ки чӣ гуна амалҳои дигари корбарро дар фазои корбарон бо функсияи psignal номидан мумкин аст. Биёед зангҳоро ба функсияи псигналӣ дар механизмҳои дохилии ядро ​​хориҷ кунем (гарчанде ки онҳо ночиз бошанд ҳам, мо онҳоро барои мақолаи дигар мегузорем 🙂 - тафтиши имзо, хатогиҳои хотира, коркарди баромад/қатъ, вайронкунии ҳифзи файл ва ғайра .

Биёед баррасиро бо функсия ва занги системаи мувофиқ оғоз кунем қатъ_бо_бор. Дидан мумкин аст, ки ба ғайр аз занги куштори классикӣ, як равиши алтернативӣ мавҷуд аст, ки ба системаи амалиётии macOS хос аст ва дар BSD пайдо намешавад. Принсипҳои кори ҳарду зангҳои система низ монанданд. Онҳо зангҳои мустақим ба вазифаи ядрои psignal мебошанд. Инчунин қайд кунед, ки пеш аз куштани раванд санҷиши "кансигнал" анҷом дода мешавад - оё ин раванд метавонад ба раванди дигар сигнал фиристад; система ба ягон барнома иҷозат намедиҳад, ки равандҳои системаро кушояд, масалан.

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 мебошанд, мисолҳои рамзӣ барои мақсадҳои тасвирӣ оварда шудаанд. Launctl муосир сигналҳои оғозшударо тавассути 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, сарфи назар аз номи худ, метавонад на танҳо бо SIGTERM, балки SIGKILL низ ирсол кунад.

Қатли ғайримустақим - Маҳдудияти захираҳо

Як ҳолати ҷолибтарро дар занги дигари система дидан мумкин аст раванд_сиёсат. Истифодаи маъмули ин занги система маҳдуд кардани захираҳои барномаҳо мебошад, ба монанди индексатор барои маҳдуд кардани вақти CPU ва квотаҳои хотира, то система тавассути фаъолияти кэшкунии файлҳо ба таври назаррас суст нашавад. Агар барнома ба маҳдудияти манбаи худ расида бошад, тавре ки аз функсияи proc_apply_resource_actions дида мешавад, сигнали SIGKILL ба раванд фиристода мешавад.

Гарчанде ки ин занги система метавонад равандро кушад, система ҳуқуқҳои равандеро, ки занги системаро даъват мекунад, ба таври кофӣ тафтиш накардааст. Дар асл тафтиш вуҷуд дошт, аммо барои гузаштан аз ин шарт истифода бурдани парчами алтернативии PROC_POLICY_ACTION_SET кифоя аст.

Аз ин рӯ, агар шумо квотаи истифодаи CPU-и барномаро "маҳдуд кунед" (масалан, танҳо 1 нс кор кунад), шумо метавонед ҳама гуна равандро дар система кушед. Ҳамин тариқ, нармафзори зараровар метавонад ҳама гуна равандро дар система, аз ҷумла раванди антивирусро кушад. Инчунин ҷолиб он аст, ки эффекте, ки ҳангоми куштани раванд бо pid 1 (launchctl) ба амал меояд - ваҳми ядро ​​ҳангоми кӯшиши коркарди сигнали SIGKILL :)

Чӣ тавр муҳофизат кардани равандҳо ва васеъшавии ядро ​​​​дар macOS

Мушкилотро чӣ тавр бояд ҳал кард?

Роҳи осонтарини пешгирии нобудшавии раванд ин иваз кардани нишоннамои функсия дар ҷадвали зангҳои система мебошад. Мутаассифона, ин усул барои бисёр сабабҳо ғайриоддӣ аст.

Аввалан, рамзе, ки макони хотираи sysent-ро назорат мекунад, на танҳо барои рамзи ядрои XNU хусусӣ аст, балки онро дар рамзҳои ядро ​​​​пайдо кардан мумкин нест. Шумо бояд усулҳои ҷустуҷӯи эвристикиро истифода баред, ба монанди динамикӣ тақсим кардани функсия ва ҷустуҷӯи нишона дар он.

Дуюм, сохтори сабтҳо дар ҷадвал аз парчамҳое, ки ядро ​​бо онҳо тартиб дода шудааст, вобаста аст. Агар парчами CONFIG_REQUIRES_U32_MUNGING эълон карда шавад, андозаи сохтор тағир дода мешавад - майдони иловагӣ илова карда мешавад sy_arg_munge32. Барои муайян кардани он, ки ядро ​​бо кадом парчам тартиб дода шудааст ё ба таври дигар, нишондиҳандаҳои функсионалӣ нисбат ба аломатҳои маълум тафтиши иловагӣ гузаронидан лозим аст.

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-и навро барои кор бо равандҳо таъмин мекунад. API Endpoint Security ба мизоҷон имкон медиҳад, ки дархостҳои зиёдеро ба равандҳои дигар иҷозат диҳанд. Ҳамин тариқ, шумо метавонед ҳама гуна сигналҳоро ба равандҳо, аз ҷумла сигнали 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-ро дар ядро ​​сабт кардан мумкин аст, ки усули муҳофизати сигналро таъмин мекунад (policy proc_check_signal), аммо API расман дастгирӣ намешавад.

Муҳофизати васеъшавии ядро ​​​​

Илова ба ҳифзи равандҳо дар система, муҳофизати худи васеъшавии ядро ​​​​(kext) низ зарур аст. macOS барои таҳиягарон чаҳорчӯба фароҳам меорад, то драйверҳои дастгоҳи IOKit-ро ба осонӣ таҳия кунанд. Илова ба пешниҳоди асбобҳо барои кор бо дастгоҳҳо, IOKit усулҳои stacking драйверҳоро бо истифода аз мисолҳои синфҳои C++ пешниҳод мекунад. Замима дар фазои корбарон қодир аст, ки як мисоли ба қайд гирифташудаи синфро барои барқарор кардани робитаи ядро ​​ва фазои корбар "ёбад".

Барои муайян кардани шумораи мисолҳои синфӣ дар система, утилитаи ioclasscount мавҷуд аст.

my_kext_ioservice = 1
my_kext_iouserclient = 1

Ҳар як васеъшавии ядро, ки мехоҳад бо стек драйвер сабти ном шавад, бояд синферо эълон кунад, ки аз IOService мерос мегирад, масалан my_kext_ioservice дар ин ҳолат Пайваст кардани замимаҳои корбар боиси эҷоди як мисоли нави синфе мегардад, ки аз IOUserClient мерос мегирад, дар мисоли my_kext_iouserclient.

Ҳангоми кӯшиши бор кардани драйвер аз система (фармони kextunload), функсияи виртуалии "bool terminate(IOOptionBits options)" даъват карда мешавад. Барои қатъ кардани занг ҳангоми кӯшиши борфарорӣ барои хомӯш кардани 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 flag, io_name_t description);" бор кардан мумкин аст. Шумо метавонед ҳангоми занг задан ба фармони "қатъ кардан" хатогиро баргардонед, то он даме, ки замимаи фазои корбарон "мемирад", яъне функсияи "clientDied" даъват карда нашавад.

Муҳофизати файл

Барои ҳифзи файлҳо, истифодаи Kauth API кифоя аст, ки ба шумо имкон медиҳад дастрасӣ ба файлҳоро маҳдуд кунед. Apple ба таҳиягарон дар бораи рӯйдодҳои гуногун дар доираи огоҳиҳо медиҳад; барои мо амалиётҳои KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ва KAUTH_VNODE_DELETE_CHILD муҳиманд. Роҳи осонтарини маҳдуд кардани дастрасӣ ба файлҳо тавассути роҳ аст - мо API-и "vn_getpath" -ро барои дарёфти роҳ ба файл ва муқоисаи префикси роҳ истифода мебарем. Дар хотир доред, ки барои оптимизатсияи тағир додани номи роҳҳои ҷузвдони файл, система дастрасӣ ба ҳар як файлро иҷозат намедиҳад, балки танҳо ба худи ҷузвдоне, ки номаш тағир дода шудааст. Роҳи волидайнро муқоиса кардан ва барои он KAUTH_VNODE_DELETE -ро маҳдуд кардан лозим аст.

Чӣ тавр муҳофизат кардани равандҳо ва васеъшавии ядро ​​​​дар macOS

Камбудии ин равиш метавонад иҷрои паст бошад, зеро шумораи префиксҳо зиёд мешаванд. Барои боварӣ ҳосил кардан, ки муқоиса ба O (префикс* дарозӣ) баробар нест, ки дар он префикс шумораи префиксҳо, дарозӣ дарозии сатр аст, шумо метавонед автомати муайянкунандаи ниҳоӣ (DFA) -ро истифода баред, ки бо префикс сохта шудааст.

Биёед усули сохтани DFA-ро барои маҷмӯи префиксҳои додашуда баррасӣ кунем. Мо курсорҳоро дар аввали ҳар як префикс оғоз мекунем. Агар ҳамаи курсорҳо ба як аломат ишора кунанд, он гоҳ ҳар як курсорро як аломат зиёд кунед ва дар хотир доред, ки дарозии як сатр якто калонтар аст. Агар ду курсор бо аломатҳои гуногун мавҷуд бошад, курсорҳоро мувофиқи аломате, ки ба онҳо нишон медиҳанд, ба гурӯҳҳо тақсим кунед ва алгоритми ҳар як гурӯҳро такрор кунед.

Дар ҳолати аввал (ҳамаи аломатҳои зери курсорҳо якхелаанд), мо ҳолати DFA мегирем, ки танҳо як гузаришро дар як сатр дорад. Дар ҳолати дуюм, мо ҷадвали гузаришҳои андозаи 256 (шумораи аломатҳо ва шумораи максималии гурӯҳҳо) ба ҳолати минбаъда, ки тавассути рекурсивӣ даъват кардани функсия ба даст оварда шудаанд, мегирем.

Биёед як мисолро дида бароем. Барои маҷмӯи префиксҳо (“/foo/bar/tmp/”, “/var/db/foo/”, “/foo/bar/aba/”, “foo/bar/aac/”) шумо метавонед инҳоро гиред DFA. Дар расм танҳо гузариши ба дигар давлатҳо овардашуда нишон дода шудааст; дигар гузаришҳо ниҳоӣ нестанд.

Чӣ тавр муҳофизат кардани равандҳо ва васеъшавии ядро ​​​​дар macOS

Ҳангоми гузаштан аз давлатҳои DKA, метавонад 3 ҳолат бошад.

  1. Ҳолати ниҳоӣ расид - роҳ ҳифз карда шудааст, мо амалҳои KAUTH_VNODE_DELETE, KAUTH_VNODE_WRITE_DATA ва KAUTH_VNODE_DELETE_CHILD-ро маҳдуд мекунем
  2. Ҳолати ниҳоӣ ба даст нарасид, аммо роҳ "анҷом ёфт" (терминатори нул расид) - роҳ волидайн аст, KAUTH_VNODE_DELETE-ро маҳдуд кардан лозим аст. Дар хотир доред, ки агар vnode ҷузвдон бошад, шумо бояд дар охири '/' илова кунед, вагарна он метавонад онро бо файли "/foor/bar/t" маҳдуд кунад, ки нодуруст аст.
  3. Ба холати нихой нарасид, рох тамом нашуд. Ҳеҷ яке аз префиксҳо ба ин мувофиқат намекунанд, мо маҳдудият ҷорӣ намекунем.

хулоса

Ҳадафи қарорҳои амниятӣ, ки таҳия мешаванд, баланд бардоштани сатҳи амнияти корбар ва маълумоти ӯ мебошад. Аз як тараф, ин ҳадаф тавассути таҳияи маҳсулоти нармафзори Acronis ба даст меояд, ки он осебпазириро, ки худи системаи амалиётӣ "заиф" аст, маҳкам мекунад. Аз тарафи дигар, мо набояд аз таҳкими он ҷанбаҳои амниятӣ, ки метавонанд дар тарафи OS такмил дода шаванд, беэътиноӣ кунем, бахусус азбаски пӯшидани чунин осебпазирӣ суботи худи моро ҳамчун маҳсулот афзоиш медиҳад. Дар бораи осебпазирӣ ба Гурӯҳи Амнияти Маҳсулоти Apple гузориш дода шуд ва он дар macOS 10.14.5 (https://support.apple.com/en-gb/HT210119) ислоҳ шудааст.

Чӣ тавр муҳофизат кардани равандҳо ва васеъшавии ядро ​​​​дар macOS

Ҳамаи инро танҳо дар сурате иҷро кардан мумкин аст, ки агар утилитаи шумо расман дар ядро ​​насб карда шуда бошад. Яъне, барои нармафзори беруна ва номатлуб чунин холӣ вуҷуд надорад. Аммо, тавре ки шумо мебинед, ҳатто ҳифзи барномаҳои қонунӣ ба монанди антивирус ва системаҳои эҳтиётӣ кор талаб мекунад. Аммо ҳоло маҳсулоти нави Acronis барои macOS муҳофизати иловагӣ аз борфарорӣ аз система хоҳанд дошт.

Манбаъ: will.com

Илова Эзоҳ