TL; DR: SSH ãã¯ã©ãã·ã¥ããå Žåã§ããICMP ãã€ããŒãããã³ãã³ããèªã¿åãããµãŒããŒäžã§å®è¡ããã«ãŒãã« ã¢ãžã¥ãŒã«ãäœæããŠããŸãã æããã£ãã¡ãªäººã®ããã«ããã¹ãŠã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
泚æïŒ çµéšè±å¯ãª C ããã°ã©ããŒã¯è¡ã®æ¶ãæµãå±éºããããŸãã çšèªãééã£ãŠããå¯èœæ§ããããŸããããæ¹å€ã¯å€§æè¿ã§ãã ãã®æçš¿ã¯ãC ããã°ã©ãã³ã°ã«ã€ããŠå€§ãŸããªã¢ã€ãã¢ãæã£ãŠããŠãLinux ã®å éšã調ã¹ãã人ã察象ãšããŠããŸãã
ç§ã®æåã®ã³ã¡ã³ãã§
ã¯ãã2020 幎ã«ãICMP ãã±ããã«ä»»æã®ãã€ããŒããæ¿å
¥ã§ããããšãç¥ããŸããã ããããé
ããªã£ãŠãäœãããªãããã¯ãã·ã§ãã ãããŠãããã«ã€ããŠäœãã§ããã®ã§ããã°ããããè¡ãå¿
èŠããããŸãã ç§ã¯æ¥åžžç掻㧠SSH çµç±ãªã©ã³ãã³ã ã©ã€ã³ã䜿çšããããšãå€ããããICMP ã·ã§ã«ã®ã¢ã€ãã¢ãæåã«é ã«æµ®ãã³ãŸããã ãããŠãå®å
šãªãã«ã·ãŒã«ã ãã³ãŽãçµã¿ç«ãŠãããã«ã倧ãŸããªã¢ã€ãã¢ããç¥ããªãèšèªã§ããã Linux ã¢ãžã¥ãŒã«ãšããŠæžãããšã«ããŸããã ãã®ãããªã·ã§ã«ã¯ããã»ã¹ã®ãªã¹ãã«ã¯è¡šç€ºããããã«ãŒãã«ã«ããŒãã§ããŸããããã¡ã€ã« ã·ã¹ãã äžã«ã¯ååšããããªã¹ãã³ã° ããŒãã®ãªã¹ãã«ã¯çããããã®ã¯è¡šç€ºãããŸããã æ©èœã®ç¹ã§ã¯ãããã¯æ¬æ Œçãªã«ãŒããããã§ããããããæ¹åããŠãè² è·å¹³åãé«ãã㊠SSH çµç±ã§ãã°ã€ã³ããŠå°ãªããšãå®è¡ã§ããªãå Žåã®æåŸã®æ段ã®ã·ã§ã«ãšããŠäœ¿çšããããšèããŠããŸãã echo i > /proc/sysrq-trigger
åèµ·åããã«ã¢ã¯ã»ã¹ã埩å
ããŸãã
ããã¹ã ãšãã£ã¿ãŒãPython ãš CãGoogle ã®åºæ¬çãªããã°ã©ãã³ã° ã¹ãã«ãå¿
èŠã§ãã
ã¯ã©ã€ã¢ã³ãéšå
ã¯ã©ã€ã¢ã³ãéšåã¯80è¡ãããã®ã¹ã¯ãªãããæžããªããã°ãããªããšæã£ãŠããŸãããã芪åãªæ¹ã代ããã«æžããŠãããŸããã
import sys
from scapy.all import sr1, IP, ICMP
if len(sys.argv) < 3:
print('Usage: {} IP "command"'.format(sys.argv[0]))
exit(0)
p = sr1(IP(dst=sys.argv[1])/ICMP()/"run:{}".format(sys.argv[2]))
if p:
p.show()
ã¹ã¯ãªããã¯ãã¢ãã¬ã¹ãšãã€ããŒããšãã XNUMX ã€ã®åŒæ°ãåããŸãã éä¿¡åã«ããã€ããŒãã®åã«ããŒãä»ããããŸã run:
ãã©ã³ãã ãªãã€ããŒããæã€ããã±ãŒãžãé€å€ããããã«å¿
èŠã«ãªããŸãã
ã«ãŒãã«ã«ã¯ããã±ãŒãžãäœæããæš©éãå¿
èŠãªã®ã§ãã¹ã¯ãªããã¯ã¹ãŒããŒãŠãŒã¶ãŒãšããŠå®è¡ããå¿
èŠããããŸãã å®è¡æš©éãä»äžããscapyèªäœãã€ã³ã¹ããŒã«ããããšãå¿ããªãã§ãã ããã Debian ã«ã¯æ¬¡ã®ãããªããã±ãŒãžããããŸãã python3-scapy
ã ããã§ããã¹ãŠãã©ã®ããã«æ©èœãããã確èªã§ããŸãã
ã³ãã³ãã®å®è¡ãšåºå
morq@laptop:~/icmpshell$ sudo ./send.py 45.11.26.232 "Hello, world!"
Begin emission:
.Finished sending 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 45
id = 17218
flags =
frag = 0
ttl = 58
proto = icmp
chksum = 0x3403
src = 45.11.26.232
dst = 192.168.0.240
options
###[ ICMP ]###
type = echo-reply
code = 0
chksum = 0xde03
id = 0x0
seq = 0x0
###[ Raw ]###
load = 'run:Hello, world!
ã¹ãããã¡ãŒã§ã¯ãããªæãã§ã
morq@laptop:~/icmpshell$ sudo tshark -i wlp1s0 -O icmp -f "icmp and host 45.11.26.232"
Running as user "root" and group "root". This could be dangerous.
Capturing on 'wlp1s0'
Frame 1: 59 bytes on wire (472 bits), 59 bytes captured (472 bits) on interface wlp1s0, id 0
Internet Protocol Version 4, Src: 192.168.0.240, Dst: 45.11.26.232
Internet Control Message Protocol
Type: 8 (Echo (ping) request)
Code: 0
Checksum: 0xd603 [correct]
[Checksum Status: Good]
Identifier (BE): 0 (0x0000)
Identifier (LE): 0 (0x0000)
Sequence number (BE): 0 (0x0000)
Sequence number (LE): 0 (0x0000)
Data (17 bytes)
0000 72 75 6e 3a 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 run:Hello, world
0010 21 !
Data: 72756e3a48656c6c6f2c20776f726c6421
[Length: 17]
Frame 2: 59 bytes on wire (472 bits), 59 bytes captured (472 bits) on interface wlp1s0, id 0
Internet Protocol Version 4, Src: 45.11.26.232, Dst: 192.168.0.240
Internet Control Message Protocol
Type: 0 (Echo (ping) reply)
Code: 0
Checksum: 0xde03 [correct]
[Checksum Status: Good]
Identifier (BE): 0 (0x0000)
Identifier (LE): 0 (0x0000)
Sequence number (BE): 0 (0x0000)
Sequence number (LE): 0 (0x0000)
[Request frame: 1]
[Response time: 19.094 ms]
Data (17 bytes)
0000 72 75 6e 3a 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 run:Hello, world
0010 21 !
Data: 72756e3a48656c6c6f2c20776f726c6421
[Length: 17]
^C2 packets captured
å¿çããã±ãŒãžå ã®ãã€ããŒãã¯å€æŽãããŸããã
ã«ãŒãã«ã¢ãžã¥ãŒã«
Debian ä»®æ³ãã·ã³ããã«ãããã«ã¯ãå°ãªããšã次ã®ãã®ãå¿
èŠã§ãã make
О linux-headers-amd64
ãæ®ãã¯äŸåé¢ä¿ã®åœ¢ã§æäŸãããŸãã ãã®èšäºã§ã¯ã³ãŒãå
šäœã玹ä»ããŸããããGithub ã§ã¯ããŒã³ãäœæã§ããŸãã
ããã¯ã®ã»ããã¢ãã
ãŸããã¢ãžã¥ãŒã«ãããŒããã¢ã³ããŒãããã«ã¯ XNUMX ã€ã®é¢æ°ãå¿
èŠã§ãã ã¢ã³ããŒãããæ©èœã¯å¿
èŠãããŸãããã rmmod
ããã¯æ©èœããŸãããã¢ãžã¥ãŒã«ã¯é»æºããªãã«ãªã£ãå Žåã«ã®ã¿ã¢ã³ããŒããããŸãã
#include <linux/module.h>
#include <linux/netfilter_ipv4.h>
static struct nf_hook_ops nfho;
static int __init startup(void)
{
nfho.hook = icmp_cmd_executor;
nfho.hooknum = NF_INET_PRE_ROUTING;
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST;
nf_register_net_hook(&init_net, &nfho);
return 0;
}
static void __exit cleanup(void)
{
nf_unregister_net_hook(&init_net, &nfho);
}
MODULE_LICENSE("GPL");
module_init(startup);
module_exit(cleanup);
äœãèµ·ããŠãïŒ
- ã¢ãžã¥ãŒã«èªäœãšããããã£ã«ã¿ãŒãæäœããããã« XNUMX ã€ã®ããã㌠ãã¡ã€ã«ãåã蟌ãŸããŸãã
- ãã¹ãŠã®æäœã¯ããããã£ã«ã¿ãŒãééããããããã£ã«ã¿ãŒã«ããã¯ãèšå®ã§ããŸãã ãããè¡ãã«ã¯ãããã¯ãæ§æãããæ§é ã宣èšããå¿
èŠããããŸãã æãéèŠãªããšã¯ãããã¯ãšããŠå®è¡ãããé¢æ°ãæå®ããããšã§ãã
nfho.hook = icmp_cmd_executor;
é¢æ°èªäœã«ã€ããŠã¯åŸã»ã©èª¬æããŸãã
次ã«ãããã±ãŒãžã®åŠçæéãèšå®ããŸããNF_INET_PRE_ROUTING
ããã±ãŒãžãã«ãŒãã«ã«æåã«çŸãããšãã«ããã±ãŒãžãåŠçããããã«æå®ããŸãã ã«äœ¿ããNF_INET_POST_ROUTING
ãã±ãããã«ãŒãã«ããåºããšãã«åŠçããŸãã
ãã£ã«ã¿ãŒã IPv4 ã«èšå®ããŸãããnfho.pf = PF_INET;
.
ç§ã¯ããã¯ãæåªå ã«ããŸããnfho.priority = NF_IP_PRI_FIRST;
ãããŠãããŒã¿æ§é ãå®éã®ããã¯ãšããŠç»é²ããŸããnf_register_net_hook(&init_net, &nfho);
- æåŸã®é¢æ°ã¯ããã¯ãåé€ããŸãã
- ã³ã³ãã€ã©ãæå¥ãèšããªãããã«ã©ã€ã»ã³ã¹ãæ瀺ããŠããŸãã
- æ©èœ
module_init()
Оmodule_exit()
ã¢ãžã¥ãŒã«ã®åæåãšçµäºãè¡ãä»ã®é¢æ°ãèšå®ããŸãã
ãã€ããŒãã®ååŸ
次ã«ãã€ããŒããæœåºããå¿ èŠããããŸããããããæãé£ããäœæ¥ã§ããããšãå€æããŸããã ã«ãŒãã«ã«ã¯ãã€ããŒããæäœããããã®çµã¿èŸŒã¿é¢æ°ããããŸããã解æã§ããã®ã¯äžäœã¬ãã«ã®ãããã³ã«ã®ããããŒã®ã¿ã§ãã
#include <linux/ip.h>
#include <linux/icmp.h>
#define MAX_CMD_LEN 1976
char cmd_string[MAX_CMD_LEN];
struct work_struct my_work;
DECLARE_WORK(my_work, work_handler);
static unsigned int icmp_cmd_executor(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
struct iphdr *iph;
struct icmphdr *icmph;
unsigned char *user_data;
unsigned char *tail;
unsigned char *i;
int j = 0;
iph = ip_hdr(skb);
icmph = icmp_hdr(skb);
if (iph->protocol != IPPROTO_ICMP) {
return NF_ACCEPT;
}
if (icmph->type != ICMP_ECHO) {
return NF_ACCEPT;
}
user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
tail = skb_tail_pointer(skb);
j = 0;
for (i = user_data; i != tail; ++i) {
char c = *(char *)i;
cmd_string[j] = c;
j++;
if (c == '')
break;
if (j == MAX_CMD_LEN) {
cmd_string[j] = '';
break;
}
}
if (strncmp(cmd_string, "run:", 4) != 0) {
return NF_ACCEPT;
} else {
for (j = 0; j <= sizeof(cmd_string)/sizeof(cmd_string[0])-4; j++) {
cmd_string[j] = cmd_string[j+4];
if (cmd_string[j] == '')
break;
}
}
schedule_work(&my_work);
return NF_ACCEPT;
}
äœãèµ·ãããŸãïŒ
- ä»å㯠IP ããããŒãš ICMP ããããŒãæäœããããã«ãè¿œå ã®ããã㌠ãã¡ã€ã«ãå«ããå¿ èŠããããŸããã
- è¡ã®æ倧é·ãèšå®ããŸãã
#define MAX_CMD_LEN 1976
ã ãŸãã«ãªããããªã®ã§ããããïŒ ã³ã³ãã€ã©ãããã«ã€ããŠæå¥ãèšãããã§ãã 圌ãã¯ãã§ã«ãã¹ã¿ãã¯ãšããŒããç解ããå¿ èŠããããšç§ã«ææ¡ããŸããããã€ãå¿ ããããå®è¡ããå Žåã«ãã£ãŠã¯ã³ãŒããä¿®æ£ããã€ããã§ãã ããã«ã³ãã³ããå«ãè¡ãèšå®ããŸããchar cmd_string[MAX_CMD_LEN];
ã ããã¯ãã¹ãŠã®é¢æ°ã§è¡šç€ºãããå¿ èŠããããŸããããã«ã€ããŠã¯æ®µèœ 9 ã§è©³ãã説æããŸãã - 次ã«ãåæåããå¿
èŠããããŸã(
struct work_struct my_work;
) æ§é äœãäœæãããããå¥ã®é¢æ° (DECLARE_WORK(my_work, work_handler);
ïŒã ãªããããå¿ èŠãªã®ãã«ã€ããŠã¯ãXNUMX çªç®ã®æ®µèœã§èª¬æããŸãã - ããã§ãããã¯ãšãªãé¢æ°ã宣èšããŸãã åãšåãå
¥ããããåŒæ°ã¯ããããã£ã«ã¿ãŒã«ãã£ãŠæ±ºãŸããŸããç§ãã¡ãé¢å¿ãããã®ã¯ã
skb
ã ããã¯ãœã±ãã ãããã¡ã§ããããã±ããã«é¢ãããã¹ãŠã®å©çšå¯èœãªæ å ±ãå«ãŸããåºæ¬çãªããŒã¿æ§é ã§ãã - ãã®é¢æ°ãæ©èœããã«ã¯ãXNUMX ã€ã®æ§é äœãšãXNUMX ã€ã®ã€ãã¬ãŒã¿ãå«ãããã€ãã®å€æ°ãå¿
èŠã§ãã
struct iphdr *iph; struct icmphdr *icmph; unsigned char *user_data; unsigned char *tail; unsigned char *i; int j = 0;
- è«çããå§ããããšãã§ããŸãã ã¢ãžã¥ãŒã«ãåäœããã«ã¯ãICMP Echo 以å€ã®ãã±ããã¯å¿
èŠãªããããçµã¿èŸŒã¿é¢æ°ã䜿çšããŠãããã¡ã解æããé ICMP ããã³é Echo ãã±ããããã¹ãŠã¹ããŒããŸãã æ»ã
NF_ACCEPT
ã¯è·ç©ã®åãå ¥ããæå³ããŸãããè¿éããããšã§è·ç©ãããããããããšãã§ããŸãNF_DROP
.iph = ip_hdr(skb); icmph = icmp_hdr(skb); if (iph->protocol != IPPROTO_ICMP) { return NF_ACCEPT; } if (icmph->type != ICMP_ECHO) { return NF_ACCEPT; }
IP ããããŒããã§ãã¯ããªããšäœãèµ·ãããã¯ãã¹ãããŠããŸããã ç§ã® C ã«é¢ããæäœéã®ç¥èãããããšãè¿œå ã®ãã§ãã¯ããªããã°ãäœãæãããããšãèµ·ããã«éããããŸããã ãããæããšã©ãŸãããŠããããšå¬ããã§ãïŒ
- ããã±ãŒãžãå¿
èŠãªã¿ã€ãã«ãªã£ãã®ã§ãããŒã¿ãæœåºã§ããŸãã çµã¿èŸŒã¿é¢æ°ããªãå Žåã¯ããŸããã€ããŒãã®å
é ãžã®ãã€ã³ã¿ãŒãååŸããå¿
èŠããããŸãã ãã㯠XNUMX ãæã§è¡ãããŸããICMP ããããŒã®å
é ãžã®ãã€ã³ã¿ãŒãååŸããããããã®ããããŒã®ãµã€ãºã«ç§»åããå¿
èŠããããŸãã ãã¹ãŠã¯æ§é ã䜿çšããŸã
icmph
:user_data = (unsigned char *)((unsigned char *)icmph + (sizeof(icmph)));
ããããŒã®æ«å°Ÿã¯ãã€ããŒãã®æ«å°ŸãšäžèŽããå¿ èŠããããŸããskb
ãããã£ãŠã察å¿ããæ§é ããæ žæ段ã䜿çšããŠãããååŸããŸããtail = skb_tail_pointer(skb);
.
åçãçãŸããŸããæ ã« ãœã±ãã ãããã¡ãŒã®è©³çŽ°ã«ã€ããŠã¯ããã¡ããã芧ãã ããã - å
é ãšæ«å°Ÿãžã®ãã€ã³ã¿ãŒãååŸããããããŒã¿ãæååã«ã³ããŒã§ããŸãã
cmd_string
ããã¬ãã£ãã¯ã¹ã®ååšã確èªããŠãã ããrun:
ãããŠãããã±ãŒãžãèŠã€ãããªãå Žåã¯ç Žæ£ãããããã®ãã¬ãã£ãã¯ã¹ãåé€ããŠè¡ãå床æžãçŽããŸãã - ããã§ãå¥ã®ãã³ãã©ãŒãåŒã³åºãããšãã§ããŸãã
schedule_work(&my_work);
ã ãã®ãããªåŒã³åºãã«ãã©ã¡ãŒã¿ãæž¡ãããšã¯ã§ããªããããã³ãã³ããå«ãè¡ã¯ã°ããŒãã«ã§ããå¿ èŠããããŸããschedule_work()
æž¡ãããæ§é äœã«é¢é£ä»ããããé¢æ°ãã¿ã¹ã¯ ã¹ã±ãžã¥ãŒã©ã®äžè¬ãã¥ãŒã«é 眮ãããŠå®äºãããããã³ãã³ããå®äºããã®ãåŸ ã€å¿ èŠããªããªããŸãã ããã¯ã¯éåžžã«é«éã§ãªããã°ãªããªãããããããå¿ èŠã§ãã ããããªããšãäœãéå§ãããªãããã«ãŒãã« ãããã¯ãçºçããããéžæã§ããŸãã é ãã¯æ»ã®ãããªãã®ã ïŒ - ããã§ã察å¿ããè¿åã䌎ãããã±ãŒãžãåãå ¥ããããšãã§ããŸãã
ãŠãŒã¶ãŒç©ºéã§ããã°ã©ã ãåŒã³åºã
ãã®æ©èœãäžçªããããããã§ããã ãã®ååãä»ããããã®ã¯ã DECLARE_WORK()
ãåãšåãå
¥ããããåŒæ°ã¯èå³æ·±ããã®ã§ã¯ãããŸããã ã³ãã³ããå«ãè¡ãååŸãããããå®å
šã«ã·ã§ã«ã«æž¡ããŸãã 解æããã€ããªã®æ€çŽ¢ããã®ä»ãã¹ãŠã圌ã«ä»»ããŠãã ããã
static void work_handler(struct work_struct * work)
{
static char *argv[] = {"/bin/sh", "-c", cmd_string, NULL};
static char *envp[] = {"PATH=/bin:/sbin", NULL};
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
}
- åŒæ°ãæååã®é
åã«èšå®ããŸã
argv[]
ã ããã°ã©ã ã¯å®éã«ã¯ã¹ããŒã¹ãå«ãé£ç¶è¡ãšããŠã§ã¯ãªãããã®æ¹æ³ã§å®è¡ãããããšã¯èª°ããç¥ã£ãŠãããšä»®å®ããŸãã - ç°å¢å€æ°ãèšå®ããŸãã ãã¹ãŠãæ¢ã«çµåãããŠããããšãé¡ããæå°éã®ãã¹ã®ã»ãããæ〠PATH ã®ã¿ãæ¿å
¥ããŸããã
/bin
Ñ/usr/bin
О/sbin
Ñ/usr/sbin
ã ä»ã®ãã¹ãå®éã«ã¯åé¡ã«ãªãããšã¯ã»ãšãã©ãããŸããã - ãã£ãããã£ãŠã¿ããïŒ ã«ãŒãã«é¢æ°
call_usermodehelper()
ãšã³ããªãŒãåãä»ããŸãã ãã€ããªãžã®ãã¹ãåŒæ°ã®é åãç°å¢å€æ°ã®é åã ããã§ã¯ãå®è¡å¯èœãã¡ã€ã«ãžã®ãã¹ãå¥ã®åŒæ°ãšããŠæž¡ãæå³ã誰ããç解ããŠãããšä»®å®ããŸãããå°ããããšãã§ããŸãã æåŸã®åŒæ°ã¯ãããã»ã¹ãå®äºãããŸã§åŸ ã€ãã©ãããæå®ããŸã (UMH_WAIT_PROC
)ãããã»ã¹éå§(UMH_WAIT_EXEC
) ãŸãã¯ãŸã£ããåŸ ããªã (UMH_NO_WAIT
ïŒã ä»ã«ããããŸããUMH_KILLABLE
, 調ã¹ãŠãŸããã§ããã
çµç«
ã«ãŒãã« ã¢ãžã¥ãŒã«ã®ã¢ã»ã³ããªã¯ãã«ãŒãã« make-framework ãéããŠå®è¡ãããŸãã åŒã°ãã make
ã«ãŒãã«ã®ããŒãžã§ã³ã«é¢é£ä»ããããç¹å¥ãªãã£ã¬ã¯ããªå
(ããã§å®çŸ©ãããŠããŸã: KERNELDIR:=/lib/modules/$(shell uname -r)/build
)ãã¢ãžã¥ãŒã«ã®å Žæãå€æ°ã«æž¡ãããŸãã M
è°è«ã®äžã§ã icmpshell.ko ãš clean ã¿ãŒã²ããã¯å®å
šã«ãã®ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŸãã 㧠obj-m
ã¢ãžã¥ãŒã«ã«å€æããããªããžã§ã¯ããã¡ã€ã«ã瀺ããŸãã ãªã¡ã€ã¯ããæ§æ main.o
в icmpshell.o
(icmpshell-objs = main.o
ïŒç§ã«ã¯ããŸãè«ççãšã¯æããŸããããããã¯ããã§ããã§ãããã
KERNELDIR:=/lib/modules/$(shell uname -r)/build
obj-m = icmpshell.o
icmpshell-objs = main.o
all: icmpshell.ko
icmpshell.ko: main.c
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
ç§ãã¡ã¯ä»¥äžãåéããŸã: make
ã èªã¿èŸŒã¿äž: insmod icmpshell.ko
ã å®äºãããšã次ã®ããšã確èªã§ããŸãã sudo ./send.py 45.11.26.232 "date > /tmp/test"
ã ãã·ã³äžã«ãã¡ã€ã«ãããå Žå /tmp/test
ããã«ã¯ãªã¯ãšã¹ããéä¿¡ãããæ¥ä»ãå«ãŸããŠããŸããã€ãŸããããªãã¯ãã¹ãŠæ£ããè¡ããç§ããã¹ãŠæ£ããè¡ã£ãããšãæå³ããŸãã
ãŸãšã
ç§ã®åããŠã®æ žéçºäœéšã¯ãäºæ³ããŠããããããã£ãšç°¡åã§ããã C ã§ã®éçºçµéšããªããŠããã³ã³ãã€ã©ã®ãã³ããš Google ã®çµæã«çŠç¹ãåœãŠãŠãæ©èœããã¢ãžã¥ãŒã«ãäœæããŠãã«ãŒãã« ããã«ãŒã§ãããšåæã«ã¹ã¯ãªããå°å§ã®ãããªæ°åãå³ããããšãã§ããŸããã ããã«ãKernel Newbies ãã£ã³ãã«ã«ã¢ã¯ã»ã¹ãããšã次ã®ã³ãã³ãã䜿çšããããã«èšãããŸããã schedule_work()
é»è©±ãã代ããã« call_usermodehelper()
ããã¯èªäœã®äžã«ããŠãè©æ¬ºãçã£ãŠåœŒãæ¥ããããŸããã XNUMX è¡ã®ã³ãŒããäœæããã«ã¯ãèªç±æéã䜿ã£ãŠçŽ XNUMX é±éã®éçºè²»çšãããããŸããã ã·ã¹ãã éçºã®å§åçãªè€éãã«ã€ããŠã®ç§ã®å人çãªé説ãæã¡ç Žã£ãæåäœéšã
誰ãã Github ã§ã³ãŒãã¬ãã¥ãŒãè¡ãããšã«åæããŠãããããæè¬ããŸãã ç¹ã«æååãæ±ããšãã«ãæããªééããããããç¯ãããšç¢ºä¿¡ããŠããŸãã
åºæïŒ habr.com