From 5945a5ab0f002078fc6eaaf7e20e2b7b66c67086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Clau=C3=9F?= Date: Fri, 25 Feb 2022 16:39:39 +0100 Subject: [PATCH] initial commit --- README.md | 66 ++ build/.ninja_deps | Bin 0 -> 40500 bytes build/.ninja_log | 87 +++ build/build.ninja | 324 ++++++++ examples/bind9/README.md | 83 ++ examples/cupsd/README.md | 79 ++ examples/exim/README.md | 286 +++++++ examples/nginx/README.md | 101 +++ examples/openssh/README.md | 109 +++ examples/openvpn/README.md | 59 ++ examples/redis/README.md | 67 ++ examples/vsftpd/README.md | 182 +++++ libdesock/include/arch/aarch64/syscall_arch.h | 78 ++ libdesock/include/arch/arm/syscall_arch.h | 103 +++ libdesock/include/arch/i386/syscall_arch.h | 89 +++ libdesock/include/arch/m68k/syscall_arch.h | 90 +++ .../include/arch/microblaze/syscall_arch.h | 99 +++ libdesock/include/arch/mips/syscall_arch.h | 153 ++++ libdesock/include/arch/mips64/syscall_arch.h | 128 ++++ libdesock/include/arch/mipsn32/syscall_arch.h | 130 ++++ libdesock/include/arch/or1k/syscall_arch.h | 115 +++ libdesock/include/arch/powerpc/syscall_arch.h | 94 +++ .../include/arch/powerpc64/syscall_arch.h | 90 +++ libdesock/include/arch/riscv64/syscall_arch.h | 78 ++ libdesock/include/arch/s390x/syscall_arch.h | 74 ++ libdesock/include/arch/sh/syscall_arch.h | 93 +++ libdesock/include/arch/x32/syscall_arch.h | 93 +++ libdesock/include/arch/x86_64/syscall_arch.h | 70 ++ libdesock/include/desock.h | 80 ++ libdesock/include/musl-features.h | 11 + libdesock/include/peekbuffer.h | 23 + libdesock/include/syscall.h | 399 ++++++++++ libdesock/src/accept.c | 53 ++ libdesock/src/bind.c | 26 + libdesock/src/close.c | 51 ++ libdesock/src/connect.c | 18 + libdesock/src/desock.c | 134 ++++ libdesock/src/dup.c | 95 +++ libdesock/src/epoll.c | 142 ++++ libdesock/src/getpeername.c | 18 + libdesock/src/getsockname.c | 17 + libdesock/src/listen.c | 16 + libdesock/src/peekbuffer.c | 109 +++ libdesock/src/poll.c | 70 ++ libdesock/src/read.c | 226 ++++++ libdesock/src/select.c | 117 +++ libdesock/src/sendfile.c | 18 + libdesock/src/shutdown.c | 16 + libdesock/src/socket.c | 37 + libdesock/src/sockopt.c | 17 + libdesock/src/syscall.c | 23 + libdesock/src/write.c | 118 +++ meson.build | 160 ++++ meson_options.txt | 6 + run-tests.sh | 39 + tests/coverage/.gitignore | 2 + tests/desock.py | 707 ++++++++++++++++++ tests/get-coverage.py | 31 + tests/helper.py | 183 +++++ tests/test_accept.py | 58 ++ tests/test_bind.py | 29 + tests/test_dup.py | 40 + tests/test_epoll.py | 145 ++++ tests/test_metadata.py | 39 + tests/test_peekbuffer.py | 206 +++++ tests/test_poll.py | 103 +++ tests/test_read.py | 227 ++++++ tests/test_select.py | 115 +++ tests/test_sendfile.py | 29 + tests/test_standard.py | 69 ++ tests/test_write.py | 62 ++ 71 files changed, 7104 insertions(+) create mode 100644 README.md create mode 100644 build/.ninja_deps create mode 100644 build/.ninja_log create mode 100644 build/build.ninja create mode 100644 examples/bind9/README.md create mode 100644 examples/cupsd/README.md create mode 100644 examples/exim/README.md create mode 100644 examples/nginx/README.md create mode 100644 examples/openssh/README.md create mode 100644 examples/openvpn/README.md create mode 100644 examples/redis/README.md create mode 100644 examples/vsftpd/README.md create mode 100644 libdesock/include/arch/aarch64/syscall_arch.h create mode 100644 libdesock/include/arch/arm/syscall_arch.h create mode 100644 libdesock/include/arch/i386/syscall_arch.h create mode 100644 libdesock/include/arch/m68k/syscall_arch.h create mode 100644 libdesock/include/arch/microblaze/syscall_arch.h create mode 100644 libdesock/include/arch/mips/syscall_arch.h create mode 100644 libdesock/include/arch/mips64/syscall_arch.h create mode 100644 libdesock/include/arch/mipsn32/syscall_arch.h create mode 100644 libdesock/include/arch/or1k/syscall_arch.h create mode 100644 libdesock/include/arch/powerpc/syscall_arch.h create mode 100644 libdesock/include/arch/powerpc64/syscall_arch.h create mode 100644 libdesock/include/arch/riscv64/syscall_arch.h create mode 100644 libdesock/include/arch/s390x/syscall_arch.h create mode 100644 libdesock/include/arch/sh/syscall_arch.h create mode 100644 libdesock/include/arch/x32/syscall_arch.h create mode 100644 libdesock/include/arch/x86_64/syscall_arch.h create mode 100644 libdesock/include/desock.h create mode 100644 libdesock/include/musl-features.h create mode 100644 libdesock/include/peekbuffer.h create mode 100644 libdesock/include/syscall.h create mode 100644 libdesock/src/accept.c create mode 100644 libdesock/src/bind.c create mode 100644 libdesock/src/close.c create mode 100644 libdesock/src/connect.c create mode 100644 libdesock/src/desock.c create mode 100644 libdesock/src/dup.c create mode 100644 libdesock/src/epoll.c create mode 100644 libdesock/src/getpeername.c create mode 100644 libdesock/src/getsockname.c create mode 100644 libdesock/src/listen.c create mode 100644 libdesock/src/peekbuffer.c create mode 100644 libdesock/src/poll.c create mode 100644 libdesock/src/read.c create mode 100644 libdesock/src/select.c create mode 100644 libdesock/src/sendfile.c create mode 100644 libdesock/src/shutdown.c create mode 100644 libdesock/src/socket.c create mode 100644 libdesock/src/sockopt.c create mode 100644 libdesock/src/syscall.c create mode 100644 libdesock/src/write.c create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100755 run-tests.sh create mode 100644 tests/coverage/.gitignore create mode 100644 tests/desock.py create mode 100755 tests/get-coverage.py create mode 100644 tests/helper.py create mode 100644 tests/test_accept.py create mode 100644 tests/test_bind.py create mode 100644 tests/test_dup.py create mode 100644 tests/test_epoll.py create mode 100644 tests/test_metadata.py create mode 100644 tests/test_peekbuffer.py create mode 100644 tests/test_poll.py create mode 100644 tests/test_read.py create mode 100644 tests/test_select.py create mode 100644 tests/test_sendfile.py create mode 100644 tests/test_standard.py create mode 100644 tests/test_write.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..131eca0 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# De-socketing for Fuzzing + +When fuzzing network applications the fuzzers provide their input via stdin +although the applications get their input over network connections. +This library redirects all network communication to stdin and stdout such that +network applications can be traditionally fuzzed with AFL++. + +For an in-depth explanation of de-socketing see our [blog post](https://lolcads.github.io/posts/2022/02/libdesock/). + +## Building +```sh +meson setup ./build +cd ./build +``` + +You can configure the build using +```sh +meson configure -D = +``` + +You can get an overview over all options with +```sh +meson configure +``` + +The following options are specific to libdesock: + +| Option | Description | Default | +|-----------------|--------------------------------------------------------------------------------------------|---------| +| `arch` | The CPU architecture for which you are compiling libdesock.so | x86_64 | +| `debug_desock` | If this is true, calls to functions in libdesock.so get logged to stderr. | false | +| `desock_client` | If this is true, calls to `connect()` get hooked. This enables the desocketing of clients. | false | +| `desock_server` | If this is true, calls to `bind()` get hooked. This enables the desocketing of servers. | true | +| `fd_table_size` | Only fds < `fd_table_size` can be desocked. | 128 | +| `interpreter` | Path to ld.so (will be determined dynamically if not set) | | + +If configuration is done compile with +```sh +meson compile +``` + +This creates a shared library `./build/libdesock.so` and a static library `./build/libdesock.a`. + +## Usage +Prepend +```sh +LD_PRELOAD=libdesock.so +``` +to the invocation of any network application or +set the environment variable +```sh +AFL_PRELOAD=libdesock.so +``` +when using AFL++. + +If you are using libdesock and AFL for fuzzing, the programs under test +usually require a special setup to work with AFL. Checkout our [examples](./examples) +directory for some examples on how to properly setup network applications for fuzzing. + +## Known Bugs +- TCP servers using [libuv](https://libuv.org/) cannot be de-socket-ed (yet). De-socketing of libuv currently only works with UDP servers. It only takes a small change to fix this though, if anyone needs this create an issue. +- `ioctl()` is not supported. Make sure your target does not rely on `ioctl` requests + +## System Call Emulation + +System call emulation is partly done using musl libc code (https://musl.libc.org/) - see `libdesock/include` diff --git a/build/.ninja_deps b/build/.ninja_deps new file mode 100644 index 0000000000000000000000000000000000000000..b764a284d727e3dc3d8e69ba266112fdc68d435a GIT binary patch literal 40500 zcmeI537lM2mBybVB1;U5gh&WU6G%X%yIn9QkU$f%fx!d`kc3F3y1Kf%NOx6RRh^9` zoyZoIeG3FIU_eA72|*D75fw#ooRL9soN*n;QO9j&Tt>(3|J{1G`t|F2uU@@WMd-ob z@B8Ia@1DB%-S3?5oO|D^_Nb<8CVN4$Bi&cnZ!gDjjsrcJ_KtKRms;6U$hGvfmj5$R z$fpviTsE6d6YoXYYYVOOY zJJOvk-H!7o`W)go1ALY9jj#OSowJ{N{?J#@{yR{0K0TR2F`dw zSvb!BVspIzJBQ7qJyR^SuFmB<3Ym3jWB0r0c0IXlS93?Mzr6?3-$t6Fx%Xm!dufip zsm-Q&>hUezzs6=pwEHTq?Mt)F#e9FNn8@T-rBmGD|6o7O+T(exU8z*-uyuL!o4mf{ zx{>qWk>+dGv`p@QMY54UnCTi0eig~aj8iuHB{mWHE@pbuWxjt=gPqnBKQZL}yoNb4 zo~UzvhD~|xZLAJk`@#EaP4y5X2@@m#8Ot`)A?u&kYO5704eR_Qj%~hV{9|k*a)M%I zvc+bQZR!3G?1t$8hY%x<@i}ep8-Jj9WbdPcci}L+QHl^6KM&FA*M^{TSU4?Yfko#S1 zYto@aqA+OfIN!m(&FWB;Sa5YruDL4NW7hcFyYU@`J|lL;S+i|^wbV$)FJK!r zu1%6p=!RRmzfqfAvZEt!=K6K)s>ge>(Ceuwp2y}`zkkuCxhtJb=QAl!SLdJTd$hl= zDOOtha)rzqGkwJ1Ir=qK?uUMrvgFt3Q+;hT*CAi+{3CYN{m^GeQKbd?2W(Zx4XL@j z_d0Ya=c|$DD81-Q=T+%2(BD@ZXJ~ilEA)@fTP7#HeHNRlyp_5-U#4%H|GvZWsT&13 zRVS`@eTnZFmTUU66ulkB_nzT;bv})*mR32}XY}}s*j4A#*rl_pGWlG#7yUP-h4Y2z zW3m(I%qDwFwd>Q-$LvZMnP|dH+1%&nqmSv@rgC|P{akdr(yAuXYqUV0#ZECdWN%~h z0I4mN>@gz$6#ZW3=Qy3uXLBvxpW#|{|0=C<$-;4-#HPvreWh4;ztwR*9qD@&i)9n% z32cUGh&Kk^u8-3%G*(T&=JsTv#OY)7kLX9G9F2X>t-n4M={`&yQC{#zBiZQQ2ZQ93 z*i?^^K^s@LoJS&!W%w(5#3!(kK2-FZ-u^;Q^Wetu+|G|p)VJdQS{bO8@SnDxzs=1pgDV=XF6q9)~!1hS@V|ZSjqC(Q34|wm#>O#QU zmG%y%j5hQAX!P;Q3wS>^!*s@7-H&i>Sj-Nai})xR+!uZPGJhY&W|%Hz)5Q#6FK+JZ z-bnK>>u4~qA*bnRvMuFFW(cl1Z zAUFsd3|=wc zP6MZdcYp=p4De2{5G(>`f_H(lz+!MVI0u{ymVl*T88{Ct2k!>wg9On1ln*p3oo}{h zvK{6$(Q!WLaymqxb-r2Ze5eE+yvhrCPini^r;DmD~H-uMWM;hipt8lC@d zfwLy=XIQ-2K3uzvKGMh`HIGjBsMl}hn)J(Di&^V)ej&StM|l-!d@bh5iKXH~ag zE1euNr(yZqA;GRk z520GRufa~56=B}4S31ts*z7=yI0(Jk!bjNQ=6F;wb|z04qTc=mlAj z1AX8|sP>4GoBGn}yv43yYC3A_ZwDs@a&T# zFhlGnI2+IWhw=;SHN3EJ@)qFzAkt9ACl9_-jtB0 zM!Jma5o@H?$xN}cC)s7r3@)wBP8DIl4Bv~L?sdp~D%X>pJ-MVFX*(OSDc8Q?^=rwd zIhE_}&6#tV4cN;6hm6O0C8sOq{s*FecWKp{+Y4#;taE+Mwq|-}+)J=MmU#_{OM7n~ z4pnblOy6zf)HSpxFTUEu=vvx}(RDx?78Iw7#|yzl;9_tIuzM=Soj-mX5r^v;X8>#f z%AGpv2-Ac(Iv%vot9RUn>B&a!tLmQ6oLZK0?nUrgQJYJBoC~?Gyg0;n^$;HqTF14B zapYP!&f3~+%){#JtWYwJ9C0lp+-soeO*Ua8^PxP_Nw&_(o zPIlL9W%RL`yRjtuly3Y2Y$N7YY?Ef=ujG)a$&S%@F+~rHx}(q4##_?9BiDs(bv-f9 zJIVug)-+E_fYK{4PPzuWLZV!9I33u<(GwQ8Jb0>xu`^wzx0b|7drfwzll!bbiQSLM z-S0&+?)&BgCU;*-Te;gl7YNGTOX#ELAx8m!o*u_%hl9(2a{T4s3NQ&MhpUdh5~!vg z3pN3p_uohR{on)OD$oS32G@XV!FAwza09pz+yrh0w}8#yR&X2G0&WMYLnnhN;23Z$ zxC7h?qU3VbAy3RKthW==IL;%NbAgiSm3{jWU<(^T2%IeI`^j|GUq? zRROHPH=3{?QUmI|-}d2Jf<6!6KOdz1i=%#T{AVj|`A;XPR{M3)$L~A1bHy{P9G~|A zonNW0^w*8zX;0LL)=$NQ_J{I;dhxuN?^*`V17REo@w)&!uRm5gUz7ibKKJS9@6#sk ze7Kdr59eRkiC3=cEbT7(JpRY6XX!c5-L%EM;%aa3YOoL37wiZ22ddYi?#<=z@*(e< z>mIf4jpExM(|fXZZ%9m+-h?nk{qi7A-9G1W{dqY35bL{Y=VHU@HrnFU>sMiM?T=@z zpY&6{U5PX02WhL#8Gemz;+pczB%oYVNzc#bbAR60ot$CwLl__OO|M^CEvS}LY+hZ0 zeZ6$Us~JJsP*wXWpUk^?c*-*Tpo#eni~VvR-W8zF3bxMo(C>);31=(*@1-qYvDy`+ z0d4d-1-qj-&HFyun)d_{G-tnGPo!@X zkZ-DX=3J_nr~jc&o*KtNE>8bH_5KwsaSmR`ZzB%=sjMX z<(xoYv3+&i)eR}@5bBQ$eQQC^ZdU2{+aTFL08pU7SJ;FNXq}cJF zxmulE&$R)t0Vq! z;fC|e&k+V+`Gn-zt{y+e{aTI-v`13@tW=vym!^T~-~@0Ym;q*j1;BE@koF>=^P?#H zwXl2~wm+*@@3@a0oKs!C9%nv(-g3oKY3<###aF$ww$ggpHEC2FM%@S0D;AfrUe)3- zjIU}sYX3Bpbaa->*%OSpq3K@3*%6Ib8D;wf%SSfBIz zMt$nk3N_E_e5UBWdwU9;jc4tL)jV#WHkZ>+(`V`a&n#0MK1sWtaTr!3c;lc^F&Wnv z;?ys3IgOC-yg$=(PIh_w3|u7+dDVI1P3KuJ=eu}kF>zzNntl%cbfG18lFQjs@HBIu zj^*O4-{nlcAEckv^itZYGt9%lIB+;n%pU<_7%k068dPpwbp+AEJv4dP261$t^ndj zx$sbMB^U$7f=$5QxBq!#6W6W=*MMumb>Mn%1Go{~1a1bmfX(1ma2wbHZU;w$$zTdN z254>W0C$2Y{vf}#zUTM3YWc1a{-OO&T)(Iq%Y%>3of-JX3bw0y zbiYB|iMI>EMc`s^39xIU*z{{pBWmsSj57c>0P!PEP6lnj@8@&)te$+;TSFAPL9w`z zYgOZM@HG`@I=t#Vt1n=eoOi(aipTqCi`NMth*Ljj6Y1Lojs(gLlYsJy%_IJt5H%mj zcWTWEi?Godf~|9<{fj{u-|`9Tlk$xy{L6Q(ua2dy+GadB0@zsgpAqg!U#RK_?jvT! z_cZ)K&tSjE+`s$TUzzxRkhc6la}M%@my#~;;68SOhrllIFbMOBFdvY=_%%K(E*H@M z3}F4j`e+o5ugYWj6_A$P+ui*73}e}N-cEZY@fgNS&^lW!kPi4`vJv%rHO@S*!a7r3 z4gL~y>sh+VXz(_dvxWR?eMR>W6o&_L?I3V4crB1$S>5yMl(bn|C0&(XS$(#;CC&G0 zxz+Kb`Ft{%0&ESgb&RX)l{EbhzVA*D7L$IRwlP)BC(hw}&jm}sp44FNRl=UF+ed$I z!v|DfeVP6{zIu03dH7MzIE#Al+s>QbFXwx~~)#GQed+S+G8D5{HT~A)a;^oE6c^r=7>Ns`U z0L$(iH|2f#s}6dh{Qpg%_aoZ*{GId0_3QH#ZE>S@3yQf>TvL3F28ttp?Ae;oYVF@L zt}4|j)wI%TsyFvUsZ+#fm@m%ddZqINaggVl<)A?OWe(!iio3%>(ZfN%%YpnmC=ROm zy<(&uz8}Y5!*s%{iE;DQQtoXTI1l)1lHK8872h{z^n9a5t7-44JfWCxR862gPc^Og zYR%u0J897?neTJYPBR?r<#I4m@4XM#DjRgmKWx{m93=KsU&M z3&2bH9pdue&~>#d$^DF^93D4rf@+?6$Bg~k3BUN!FHOu`>aM@t_Xg$gCG^votpng#?t)?{Xs@CiuDzS~ zZS|=8!fKk0jGVuOq>;6pw^rMeYaM5A zY5yjOl}Uizv@w;=>Fq2F8OUfP6sf?qBPA`Gwafg19G_nBPHf-F)(D@A;ef{t$C(nX<)vzKyo{_WDU! zocg(!9@#bau8I6W>mm-dHr5yH8p*%Beq(*661Q5%xIR?Lf2^<6;uAKutNDhl|CTW4 zJ;}Fn-vf;K>z_Sic->B0ylM_Xaje`dew3fZouAuA)FW~0fNJY*`SJU4P`+Hs{n|M4 z$A6gC&cQAy=2j4M_i+8OUB5LP+)G;=*zXJCp^ZNNdNgPZ@%$0`|LHfcTBEqWpY}-N zSzJheym>Va_fdGaytFZ%fBnOFw!g`J;j7yX2TANl5(i=H9kymcK5J`an-~2#TKU#unS#n?2iO$UCBlm49mP6RW+Oc0hAq%)QBoO0mq<~gm8 z);DY&qw1SkE^+19O&JpkMZ3d%lBO?9eR-VNQ!|S+|N$%5ZDDC24Q{?7BiJJ zts2jj@>vv3vwsg_)4-n$FKOmIl6dLlev}`yR}9)4X1SIFeL(xe-QmrfhZGOeD%A~f z`Sa`Cd3=}j>@)nkaNZl&DV9>SM-pe1{68#Sg7QTa{}0PgVL4rAe4k|9w{3aYaPX+h zLA`Q{SC1Q&KjP~AI__05%Jv_aSlP;F;=pS2-n3s0_5u5X{lNY}wU%_- zUxNkdxL3pFqkjKvR2;2mtN~#C-FxpgFME97K>OwVGI&nsUAt-;6vk0leh~*xcsST=gmDm-&*QFH zP#q9gx0K_bX5Fv3{2Ldl&RXkoVDn#?ZuzyxYJxP#uV;tw*%)BYKRgbXZKRK4<#GP~*4HLoB%bc3ExoE&j;~aY+BIoZPSM`p zuhW&ZrV(o$<|jcsh=Zq?^Ie-484mhg4zxZ&aZ)V~l>h4y3vqlqOf%}e=KgvquKwBI znOhDnbvdxl7=n0MLcb${p27J!8OLXbgUf*UxEx#oCIRV|H0w$r{Td540jqWXXE04% zyBb^rt_9bD>%k4+MsO3j8QcOkgImFEU< zXV&lK->RK$KB-r{tswP$j_*BX+LVixckZPv4lJiZJhaIM%mSx^*zBCp zf%oRk7~5!TjD=tkPz^6%4I0bOv2wOzK)FOd;OAWaaTu_1?~juvu1PB<0qI4hm^_=$ z{jtA0ac^ThEHC*vJ%c&OKdSkW*GK9dbT7ntkR<1RD2+(%oyOaM`JZX$h~fV4_Aiq$KtYjO2S z`dDji;?-%d{)Tbk*RwEg>{@&Ed@S>nj*kbbb1V35c2e|Fh=#oLp##jEZu zh}UUcn-2VWOgx+bP6RW+Oc1u7UTycTlYB#KrJT6Cc`t6Q6DN-R^{JOruQvMqNM{;f z=3ejF^0eXLQQGz7;KjVo>$q2~+lAmFa51<9*c`Q<_5j!bv~CFy=2LNai=uxU8TYUC Cm&m*T literal 0 HcmV?d00001 diff --git a/build/.ninja_log b/build/.ninja_log new file mode 100644 index 0000000..c47d5df --- /dev/null +++ b/build/.ninja_log @@ -0,0 +1,87 @@ +# ninja log v5 +1 27 1645170954721742038 libdesock.so.p/libdesock_src_connect.c.o d5e42f62cba16ece +2 77 1645170954769742101 libdesock.so.p/libdesock_src_listen.c.o 228d1bab9ab7c69d +0 79 1645170954769742101 libdesock.so.p/libdesock_src_bind.c.o 1eb012921b110996 +1 81 1645170954773742106 libdesock.so.p/libdesock_src_getsockname.c.o 2610b9438660f80a +0 85 1645170954776742110 libdesock.so.p/libdesock_src_accept.c.o 8229ec26e705745 +1 86 1645170954778742113 libdesock.so.p/libdesock_src_getpeername.c.o d67a0957691f5842 +27 92 1645170954771742104 libdesock.so.p/libdesock_src_sendfile.c.o a6146ff1fb4a840f +0 94 1645170954784742121 libdesock.so.p/libdesock_src_close.c.o b198d3035da54e83 +2 97 1645170954781742117 libdesock.so.p/libdesock_src_peekbuffer.c.o 1566dc6e99e56e84 +3 104 1645170954783742120 libdesock.so.p/libdesock_src_poll.c.o 5726a1e584097c1 +1 110 1645170954788742126 libdesock.so.p/libdesock_src_desock.c.o 89d8e00bf7327f98 +1 116 1645170954799742140 libdesock.so.p/libdesock_src_dup.c.o dbe4aca606967e29 +1 117 1645170954794742134 libdesock.so.p/libdesock_src_epoll.c.o bd742c74da43c54a +85 131 1645170954824742173 libdesock.so.p/libdesock_src_syscall.c.o 81ff60c09072bccc +3 140 1645170954820742168 libdesock.so.p/libdesock_src_select.c.o f8fb1977bbeeacdb +81 149 1645170954825742174 libdesock.so.p/libdesock_src_sockopt.c.o 8542fdefbf753939 +104 150 1645170954822742170 libdesock.a.p/libdesock_src_connect.c.o 383cbd8e656f3a4b +78 154 1645170954840742194 libdesock.so.p/libdesock_src_shutdown.c.o 4736227f347f34f6 +79 156 1645170954846742202 libdesock.so.p/libdesock_src_socket.c.o 94f67957ec5c1133 +92 165 1645170954856742215 libdesock.a.p/libdesock_src_accept.c.o 70f83521298d1bbb +94 173 1645170954856742215 libdesock.a.p/libdesock_src_bind.c.o b669431c11ad1a5e +97 191 1645170954866742228 libdesock.a.p/libdesock_src_close.c.o c601f827108f84fd +3 206 1645170954884742252 libdesock.so.p/libdesock_src_read.c.o ff71dff77a34e681 +113 210 1645170954885742253 libdesock.a.p/libdesock_src_desock.c.o 31d9fc300f5a0310 +131 215 1645170954885742253 libdesock.a.p/libdesock_src_getpeername.c.o 9c0137ae79f61cc8 +116 226 1645170954898742270 libdesock.a.p/libdesock_src_dup.c.o 8d2e7f622d42e149 +149 234 1645170954900742273 libdesock.a.p/libdesock_src_listen.c.o eaa405488b29b4e2 +86 234 1645170954919742297 libdesock.so.p/libdesock_src_write.c.o 27ef3d502a59271f +142 244 1645170954923742303 libdesock.a.p/libdesock_src_getsockname.c.o 4da5b7049bc05b9f +173 256 1645170954946742333 libdesock.a.p/libdesock_src_sendfile.c.o 3ef0b015d0fd562f +154 256 1645170954946742333 libdesock.a.p/libdesock_src_poll.c.o d2c5b0d8207b8c6c +215 263 1645170954955742345 libdesock.a.p/libdesock_src_syscall.c.o f5573d3625571ae4 +210 277 1645170954968742362 libdesock.a.p/libdesock_src_sockopt.c.o 3606b775e7a08fb1 +151 280 1645170954970742364 libdesock.a.p/libdesock_src_peekbuffer.c.o 6e44df44f02bed22 +167 280 1645170954974742369 libdesock.a.p/libdesock_src_select.c.o ab4ab2c00ffd0571 +207 280 1645170954972742367 libdesock.a.p/libdesock_src_socket.c.o c93eb537e69426e3 +191 282 1645170954974742369 libdesock.a.p/libdesock_src_shutdown.c.o 37514e307bb5bf24 +117 289 1645170954982742380 libdesock.a.p/libdesock_src_epoll.c.o b34671878ddbfb93 +234 296 1645170954990742390 libdesock.so 93ecbc8b06031ff2 +296 307 1645170955002742406 fake 7040f30ff78ddc2 +156 340 1645170955034742448 libdesock.a.p/libdesock_src_read.c.o 25fa2575dcce7a8c +226 342 1645170955036742451 libdesock.a.p/libdesock_src_write.c.o 4154854c4c63465b +342 346 1645170955041742457 libdesock.a 654baa5a2eb63a2d +16 34 1645803488036922924 libdesock.so.p/libdesock_src_connect.c.o d5e42f62cba16ece +18 77 1645803488079923022 libdesock.so.p/libdesock_src_getsockname.c.o 2610b9438660f80a +18 79 1645803488079923022 libdesock.so.p/libdesock_src_getpeername.c.o d67a0957691f5842 +35 80 1645803488079923022 libdesock.so.p/libdesock_src_sendfile.c.o a6146ff1fb4a840f +16 83 1645803488082923029 libdesock.so.p/libdesock_src_close.c.o b198d3035da54e83 +19 84 1645803488081923026 libdesock.so.p/libdesock_src_listen.c.o 228d1bab9ab7c69d +14 85 1645803488087923040 libdesock.so.p/libdesock_src_accept.c.o 8229ec26e705745 +15 92 1645803488082923029 libdesock.so.p/libdesock_src_bind.c.o 1eb012921b110996 +20 93 1645803488093923054 libdesock.so.p/libdesock_src_poll.c.o 5726a1e584097c1 +20 94 1645803488093923054 libdesock.so.p/libdesock_src_peekbuffer.c.o 1566dc6e99e56e84 +17 96 1645803488097923063 libdesock.so.p/libdesock_src_dup.c.o dbe4aca606967e29 +17 102 1645803488097923063 libdesock.so.p/libdesock_src_desock.c.o 89d8e00bf7327f98 +24 115 1645803488109923090 libdesock.so.p/libdesock_src_select.c.o f8fb1977bbeeacdb +94 118 1645803488115923104 libdesock.a.p/libdesock_src_connect.c.o 383cbd8e656f3a4b +18 122 1645803488121923118 libdesock.so.p/libdesock_src_epoll.c.o bd742c74da43c54a +77 124 1645803488124923124 libdesock.so.p/libdesock_src_shutdown.c.o 4736227f347f34f6 +83 125 1645803488127923131 libdesock.so.p/libdesock_src_syscall.c.o 81ff60c09072bccc +81 128 1645803488128923133 libdesock.so.p/libdesock_src_sockopt.c.o 8542fdefbf753939 +92 142 1645803488139923159 libdesock.a.p/libdesock_src_bind.c.o b669431c11ad1a5e +93 143 1645803488143923168 libdesock.a.p/libdesock_src_close.c.o c601f827108f84fd +79 157 1645803488145923172 libdesock.so.p/libdesock_src_socket.c.o 94f67957ec5c1133 +85 159 1645803488161923209 libdesock.a.p/libdesock_src_accept.c.o 70f83521298d1bbb +122 164 1645803488164923215 libdesock.a.p/libdesock_src_getsockname.c.o 4da5b7049bc05b9f +21 184 1645803488173923236 libdesock.so.p/libdesock_src_read.c.o ff71dff77a34e681 +84 185 1645803488173923236 libdesock.so.p/libdesock_src_write.c.o 27ef3d502a59271f +96 185 1645803488176923243 libdesock.a.p/libdesock_src_desock.c.o 31d9fc300f5a0310 +119 186 1645803488167923222 libdesock.a.p/libdesock_src_getpeername.c.o 9c0137ae79f61cc8 +125 186 1645803488167923222 libdesock.a.p/libdesock_src_listen.c.o eaa405488b29b4e2 +125 192 1645803488192923279 libdesock.a.p/libdesock_src_peekbuffer.c.o 6e44df44f02bed22 +103 197 1645803488197923290 libdesock.a.p/libdesock_src_dup.c.o 8d2e7f622d42e149 +157 200 1645803488200923297 libdesock.a.p/libdesock_src_sendfile.c.o 3ef0b015d0fd562f +128 201 1645803488200923297 libdesock.a.p/libdesock_src_poll.c.o d2c5b0d8207b8c6c +159 204 1645803488206923311 libdesock.a.p/libdesock_src_shutdown.c.o 37514e307bb5bf24 +185 212 1645803488214923329 libdesock.a.p/libdesock_src_syscall.c.o f5573d3625571ae4 +117 217 1645803488219923340 libdesock.a.p/libdesock_src_epoll.c.o b34671878ddbfb93 +184 224 1645803488226923356 libdesock.a.p/libdesock_src_sockopt.c.o 3606b775e7a08fb1 +185 225 1645803488227923359 libdesock.so 93ecbc8b06031ff2 +225 228 1645803488231923368 fake 7040f30ff78ddc2 +164 231 1645803488233923372 libdesock.a.p/libdesock_src_socket.c.o c93eb537e69426e3 +143 235 1645803488237923382 libdesock.a.p/libdesock_src_select.c.o ab4ab2c00ffd0571 +186 250 1645803488251923413 libdesock.a.p/libdesock_src_write.c.o 4154854c4c63465b +142 256 1645803488258923429 libdesock.a.p/libdesock_src_read.c.o 25fa2575dcce7a8c +256 261 1645803488263923441 libdesock.a 654baa5a2eb63a2d diff --git a/build/build.ninja b/build/build.ninja new file mode 100644 index 0000000..de977e1 --- /dev/null +++ b/build/build.ninja @@ -0,0 +1,324 @@ +# This is the build file for project "libdesock" +# It is autogenerated by the Meson build system. +# Do not edit by hand. + +ninja_required_version = 1.7.1 + +# Rules for compiling. + +rule c_COMPILER + command = cc $ARGS -MD -MQ $out -MF $DEPFILE -o $out -c $in + deps = gcc + depfile = $DEPFILE_UNQUOTED + description = Compiling C object $out + +# Rules for linking. + +rule STATIC_LINKER + command = rm -f $out && gcc-ar $LINK_ARGS $out $in + description = Linking static target $out + +rule c_LINKER + command = cc $ARGS -o $out $in $LINK_ARGS + description = Linking target $out + +rule SHSYM + command = /usr/bin/meson --internal symbolextractor /io/build $in $IMPLIB $out $CROSS + description = Generating symbol file $out + restat = 1 + +# Other rules + +rule CUSTOM_COMMAND + command = $COMMAND + description = $DESC + restat = 1 + +rule REGENERATE_BUILD + command = /usr/bin/meson --internal regenerate /io /io/build --backend ninja + description = Regenerating build files. + generator = 1 + +# Phony build target, always out of date + +build PHONY: phony + +# Build rules for targets + +build libdesock.so.p/libdesock_src_accept.c.o: c_COMPILER ../libdesock/src/accept.c + DEPFILE = libdesock.so.p/libdesock_src_accept.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_accept.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_bind.c.o: c_COMPILER ../libdesock/src/bind.c + DEPFILE = libdesock.so.p/libdesock_src_bind.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_bind.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_close.c.o: c_COMPILER ../libdesock/src/close.c + DEPFILE = libdesock.so.p/libdesock_src_close.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_close.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_connect.c.o: c_COMPILER ../libdesock/src/connect.c + DEPFILE = libdesock.so.p/libdesock_src_connect.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_connect.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_desock.c.o: c_COMPILER ../libdesock/src/desock.c + DEPFILE = libdesock.so.p/libdesock_src_desock.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_desock.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_dup.c.o: c_COMPILER ../libdesock/src/dup.c + DEPFILE = libdesock.so.p/libdesock_src_dup.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_dup.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_epoll.c.o: c_COMPILER ../libdesock/src/epoll.c + DEPFILE = libdesock.so.p/libdesock_src_epoll.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_epoll.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_getpeername.c.o: c_COMPILER ../libdesock/src/getpeername.c + DEPFILE = libdesock.so.p/libdesock_src_getpeername.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_getpeername.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_getsockname.c.o: c_COMPILER ../libdesock/src/getsockname.c + DEPFILE = libdesock.so.p/libdesock_src_getsockname.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_getsockname.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_listen.c.o: c_COMPILER ../libdesock/src/listen.c + DEPFILE = libdesock.so.p/libdesock_src_listen.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_listen.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_peekbuffer.c.o: c_COMPILER ../libdesock/src/peekbuffer.c + DEPFILE = libdesock.so.p/libdesock_src_peekbuffer.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_peekbuffer.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_poll.c.o: c_COMPILER ../libdesock/src/poll.c + DEPFILE = libdesock.so.p/libdesock_src_poll.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_poll.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_read.c.o: c_COMPILER ../libdesock/src/read.c + DEPFILE = libdesock.so.p/libdesock_src_read.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_read.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_select.c.o: c_COMPILER ../libdesock/src/select.c + DEPFILE = libdesock.so.p/libdesock_src_select.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_select.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_sendfile.c.o: c_COMPILER ../libdesock/src/sendfile.c + DEPFILE = libdesock.so.p/libdesock_src_sendfile.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_sendfile.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_shutdown.c.o: c_COMPILER ../libdesock/src/shutdown.c + DEPFILE = libdesock.so.p/libdesock_src_shutdown.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_shutdown.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_socket.c.o: c_COMPILER ../libdesock/src/socket.c + DEPFILE = libdesock.so.p/libdesock_src_socket.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_socket.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_sockopt.c.o: c_COMPILER ../libdesock/src/sockopt.c + DEPFILE = libdesock.so.p/libdesock_src_sockopt.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_sockopt.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_syscall.c.o: c_COMPILER ../libdesock/src/syscall.c + DEPFILE = libdesock.so.p/libdesock_src_syscall.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_syscall.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock_src_write.c.o: c_COMPILER ../libdesock/src/write.c + DEPFILE = libdesock.so.p/libdesock_src_write.c.o.d + DEPFILE_UNQUOTED = libdesock.so.p/libdesock_src_write.c.o.d + ARGS = -Ilibdesock.so.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.so.p/libdesock.so.symbols: SHSYM libdesock.so + IMPLIB = libdesock.so + +build libdesock.so: c_LINKER libdesock.so.p/libdesock_src_accept.c.o libdesock.so.p/libdesock_src_bind.c.o libdesock.so.p/libdesock_src_close.c.o libdesock.so.p/libdesock_src_connect.c.o libdesock.so.p/libdesock_src_desock.c.o libdesock.so.p/libdesock_src_dup.c.o libdesock.so.p/libdesock_src_epoll.c.o libdesock.so.p/libdesock_src_getpeername.c.o libdesock.so.p/libdesock_src_getsockname.c.o libdesock.so.p/libdesock_src_listen.c.o libdesock.so.p/libdesock_src_peekbuffer.c.o libdesock.so.p/libdesock_src_poll.c.o libdesock.so.p/libdesock_src_read.c.o libdesock.so.p/libdesock_src_select.c.o libdesock.so.p/libdesock_src_sendfile.c.o libdesock.so.p/libdesock_src_shutdown.c.o libdesock.so.p/libdesock_src_socket.c.o libdesock.so.p/libdesock_src_sockopt.c.o libdesock.so.p/libdesock_src_syscall.c.o libdesock.so.p/libdesock_src_write.c.o + LINK_ARGS = -Wl,--as-needed -Wl,--no-undefined -shared -fPIC -Wl,--start-group -Wl,-soname,libdesock.so -Wl,--end-group -Wl,-e,desock_main -pthread + +build libdesock.a.p/libdesock_src_accept.c.o: c_COMPILER ../libdesock/src/accept.c + DEPFILE = libdesock.a.p/libdesock_src_accept.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_accept.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_bind.c.o: c_COMPILER ../libdesock/src/bind.c + DEPFILE = libdesock.a.p/libdesock_src_bind.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_bind.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_close.c.o: c_COMPILER ../libdesock/src/close.c + DEPFILE = libdesock.a.p/libdesock_src_close.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_close.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_connect.c.o: c_COMPILER ../libdesock/src/connect.c + DEPFILE = libdesock.a.p/libdesock_src_connect.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_connect.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_desock.c.o: c_COMPILER ../libdesock/src/desock.c + DEPFILE = libdesock.a.p/libdesock_src_desock.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_desock.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_dup.c.o: c_COMPILER ../libdesock/src/dup.c + DEPFILE = libdesock.a.p/libdesock_src_dup.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_dup.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_epoll.c.o: c_COMPILER ../libdesock/src/epoll.c + DEPFILE = libdesock.a.p/libdesock_src_epoll.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_epoll.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_getpeername.c.o: c_COMPILER ../libdesock/src/getpeername.c + DEPFILE = libdesock.a.p/libdesock_src_getpeername.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_getpeername.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_getsockname.c.o: c_COMPILER ../libdesock/src/getsockname.c + DEPFILE = libdesock.a.p/libdesock_src_getsockname.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_getsockname.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_listen.c.o: c_COMPILER ../libdesock/src/listen.c + DEPFILE = libdesock.a.p/libdesock_src_listen.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_listen.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_peekbuffer.c.o: c_COMPILER ../libdesock/src/peekbuffer.c + DEPFILE = libdesock.a.p/libdesock_src_peekbuffer.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_peekbuffer.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_poll.c.o: c_COMPILER ../libdesock/src/poll.c + DEPFILE = libdesock.a.p/libdesock_src_poll.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_poll.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_read.c.o: c_COMPILER ../libdesock/src/read.c + DEPFILE = libdesock.a.p/libdesock_src_read.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_read.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_select.c.o: c_COMPILER ../libdesock/src/select.c + DEPFILE = libdesock.a.p/libdesock_src_select.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_select.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_sendfile.c.o: c_COMPILER ../libdesock/src/sendfile.c + DEPFILE = libdesock.a.p/libdesock_src_sendfile.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_sendfile.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_shutdown.c.o: c_COMPILER ../libdesock/src/shutdown.c + DEPFILE = libdesock.a.p/libdesock_src_shutdown.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_shutdown.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_socket.c.o: c_COMPILER ../libdesock/src/socket.c + DEPFILE = libdesock.a.p/libdesock_src_socket.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_socket.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_sockopt.c.o: c_COMPILER ../libdesock/src/sockopt.c + DEPFILE = libdesock.a.p/libdesock_src_sockopt.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_sockopt.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_syscall.c.o: c_COMPILER ../libdesock/src/syscall.c + DEPFILE = libdesock.a.p/libdesock_src_syscall.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_syscall.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a.p/libdesock_src_write.c.o: c_COMPILER ../libdesock/src/write.c + DEPFILE = libdesock.a.p/libdesock_src_write.c.o.d + DEPFILE_UNQUOTED = libdesock.a.p/libdesock_src_write.c.o.d + ARGS = -Ilibdesock.a.p -I. -I.. -I../libdesock/include -I../libdesock/include/arch/x86_64 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -g -fPIC -pthread -O2 -Wall -Wextra -Wpedantic -Wno-unused-parameter -Wno-sign-compare '-D$ DESOCKARCH="x86_64"' '-D$ MAX_CONNS=1' '-D$ FD_TABLE_SIZE=128' '-D$ INTERPRETER="/lib64/ld-linux-x86-64.so.2"' '-D$ DESOCK_BIND' + +build libdesock.a: STATIC_LINKER libdesock.a.p/libdesock_src_accept.c.o libdesock.a.p/libdesock_src_bind.c.o libdesock.a.p/libdesock_src_close.c.o libdesock.a.p/libdesock_src_connect.c.o libdesock.a.p/libdesock_src_desock.c.o libdesock.a.p/libdesock_src_dup.c.o libdesock.a.p/libdesock_src_epoll.c.o libdesock.a.p/libdesock_src_getpeername.c.o libdesock.a.p/libdesock_src_getsockname.c.o libdesock.a.p/libdesock_src_listen.c.o libdesock.a.p/libdesock_src_peekbuffer.c.o libdesock.a.p/libdesock_src_poll.c.o libdesock.a.p/libdesock_src_read.c.o libdesock.a.p/libdesock_src_select.c.o libdesock.a.p/libdesock_src_sendfile.c.o libdesock.a.p/libdesock_src_shutdown.c.o libdesock.a.p/libdesock_src_socket.c.o libdesock.a.p/libdesock_src_sockopt.c.o libdesock.a.p/libdesock_src_syscall.c.o libdesock.a.p/libdesock_src_write.c.o + LINK_ARGS = csrD + +build fake: CUSTOM_COMMAND libdesock.so | libdesock.so + COMMAND = strip --keep-symbol=accept --keep-symbol=accept4 --keep-symbol=bind --keep-symbol=connect --keep-symbol=close --keep-symbol=dup --keep-symbol=dup2 --keep-symbol=dup3 --keep-symbol=epoll_create --keep-symbol=epoll_create1 --keep-symbol=epoll_ctl --keep-symbol=epoll_pwait --keep-symbol=epoll_wait --keep-symbol=epoll_pwait2 --keep-symbol=getpeername --keep-symbol=getsockname --keep-symbol=listen --keep-symbol=poll --keep-symbol=ppoll --keep-symbol=read --keep-symbol=recvfrom --keep-symbol=recv --keep-symbol=recvmsg --keep-symbol=recvmmsg --keep-symbol=readv --keep-symbol=select --keep-symbol=pselect --keep-symbol=sendfile --keep-symbol=sendfile64 --keep-symbol=shutdown --keep-symbol=socket --keep-symbol=setsockopt --keep-symbol=write --keep-symbol=send --keep-symbol=sendto --keep-symbol=sendmsg --keep-symbol=sendmmsg --keep-symbol=writev libdesock.so + description = Generating$ target$ with$ a$ custom$ command + +# Test rules + +build meson-test: CUSTOM_COMMAND all PHONY + COMMAND = /usr/bin/meson test --no-rebuild --print-errorlogs + DESC = Running$ all$ tests. + pool = console + +build test: phony meson-test + +build meson-benchmark: CUSTOM_COMMAND all PHONY + COMMAND = /usr/bin/meson test --benchmark --logbase benchmarklog --num-processes=1 --no-rebuild + DESC = Running$ benchmark$ suite. + pool = console + +build benchmark: phony meson-benchmark + +# Install rules + +build meson-install: CUSTOM_COMMAND PHONY | all + DESC = Installing$ files. + COMMAND = /usr/bin/meson install --no-rebuild + pool = console + +build install: phony meson-install + +build meson-dist: CUSTOM_COMMAND PHONY + DESC = Creating$ source$ packages + COMMAND = /usr/bin/meson dist + pool = console + +build dist: phony meson-dist + +# Suffix + +build meson-uninstall: CUSTOM_COMMAND PHONY + COMMAND = /usr/bin/meson --internal uninstall + pool = console + +build uninstall: phony meson-uninstall + +build all: phony libdesock.so libdesock.a fake + +build clean: phony meson-clean + +build meson-clean-ctlist: CUSTOM_COMMAND PHONY + COMMAND = /usr/bin/meson --internal cleantrees /io/build/meson-private/cleantrees.dat + description = Cleaning$ custom$ target$ directories + +build clean-ctlist: phony meson-clean-ctlist + +build meson-clean: CUSTOM_COMMAND PHONY | clean-ctlist + COMMAND = /usr/bin/ninja -t clean + description = Cleaning + +build build.ninja: REGENERATE_BUILD ../meson.build ../meson_options.txt /bin/dash meson-private/coredata.dat + pool = console + +build reconfigure: REGENERATE_BUILD PHONY + pool = console + +build ../meson.build ../meson_options.txt /bin/dash meson-private/coredata.dat: phony + +default all + diff --git a/examples/bind9/README.md b/examples/bind9/README.md new file mode 100644 index 0000000..0bac552 --- /dev/null +++ b/examples/bind9/README.md @@ -0,0 +1,83 @@ +# Fuzzing bind9 with AFL + +This document explains how to setup [bind9 9.17.16](https://gitlab.isc.org/isc-projects/bind9.git) for fuzzing +with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +git clone https://gitlab.isc.org/isc-projects/bind9.git +cd bind9 +git checkout v9_17_16 +``` + +### Patching the source +In `lib/ns/client.c` add +```diff +@@ -11,6 +11,7 @@ + + #include + #include ++#include + + #include + #include +@@ -234,6 +235,7 @@ ns_client_endrequest(ns_client_t *client) { + client->sctx->fuzznotify(); + } + #endif /* ENABLE_AFL */ ++ _exit(0); + } +``` + +### Build configuration +```sh +autoreconf -i +mkdir -p build/install +cd build +CC="afl-clang-fast" CFLAGS="-fsanitize=address -g -Og" LDFLAGS="-fsanitize=address" ../configure --prefix=$PWD/install --disable-chroot --with-zlib=no --with-libxml2=no +make install +``` + +### Runtime configuration +Create `example.com.db`: +``` +$TTL 604800 +@ IN SOA ns.example.com. root.example.com. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 604800 ) ; Negative Cache TTL +@ IN NS ns.example.com. +ns IN A 127.0.0.1 +sub IN A 1.2.3.4 +``` + +Create `fuzz.conf`: +``` +options { + directory "/tmp"; + allow-query-cache { none; }; + allow-query { any; }; + recursion no; + listen-on port 5353 { 127.0.0.1; }; +}; + +controls { }; + +zone "example.com" { + type primary; + file "example.com.db"; +}; +``` + +### Fuzzing Setup +``` +cp example.com.db /tmp +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- ./install/sbin/named -c fuzz.conf -g -n 0 -4 +``` diff --git a/examples/cupsd/README.md b/examples/cupsd/README.md new file mode 100644 index 0000000..58c4cfe --- /dev/null +++ b/examples/cupsd/README.md @@ -0,0 +1,79 @@ +# Fuzzing cupsd with AFL + +This document explains how to setup [cupsd 2.3.3](https://github.com/OpenPrinting/cups) for fuzzing +with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +git clone https://github.com/OpenPrinting/cups +cd cups +git checkout v2.3.3op2 +``` + +### Patching the source +In `scheduler/main.c` add +```diff +@@ -718,6 +718,7 @@ main(int argc, /* I - Number of command-line args */ + report_time = 0; + senddoc_time = current_time; + ++ int __custom_events = 0; + while (!stop_scheduler) + { + /* +@@ -1147,6 +1148,8 @@ main(int argc, /* I - Number of command-line args */ + LastEvent = CUPSD_EVENT_NONE; + event_time = current_time; + } ++ ++ if (++__custom_events >= 2) exit(0); + } +``` + +### Build configuration +```sh +mkdir install +CC=afl-clang-fast CXX=afl-clang-fast++ CFLAGS="-fsanitize=address -g -Og" LDFLAGS="-fsanitize=address" \ +./configure --prefix=$PWD/install \ + --with-menudir=$PWD/install \ + --with-icondir=$PWD/install \ + --enable-debug \ + --without-pam-module \ + --with-cups-user=$USER \ + --with-cups-group=$USER \ + --without-xinetd \ + --disable-systemd \ + --disable-threads \ + --disable-dbus \ + --without-rcdir +``` + +In `Makedefs` set the linker to `afl-clang-fast++`: +``` +LD = afl-clang-fast++ +``` + +Then build the program +``` +make install +``` + +### Runtime Configuration +Create `fuzz.conf`: +``` +LogLevel error +Listen *:6666 +Timeout 10 +ErrorPolicy abort-job +HostNameLookups Off +``` + +### Fuzzing Setup +``` +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- ./sbin/cupsd -f -c fuzz.conf +``` diff --git a/examples/exim/README.md b/examples/exim/README.md new file mode 100644 index 0000000..ab63f4a --- /dev/null +++ b/examples/exim/README.md @@ -0,0 +1,286 @@ +# Fuzzing Exim with AFL + +This document explains how to setup [exim 4.95](https://github.com/exim/exim) +for fuzzing with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +git clone https://github.com/exim/exim +cd exim +git checkout exim-4.95 +``` + +### Patching the source +We need exim to exit after processing one request. We can do that by calling `exit()` +in the appropriate places. +In `src/src/daemon.c:918` insert +```diff +@@ -916,6 +916,7 @@ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) + smtp_accept_count, (smtp_accept_count == 1)? "" : "es"); + break; + } ++ if (!smtp_accept_count) _exit(0); + if (i < smtp_accept_max) continue; /* Found an accepting process */ + } +``` +In `src/src/deliver.c:2406` insert +```diff +@@ -2403,6 +2403,8 @@ if ((pid = exim_fork(US"delivery-local")) == 0) + file_format in appendfile. */ + + PASS_BACK: ++ search_tidyup(); ++ _exit(0); + +``` +In `src/src/smtp_in.c:5751` insert +```diff +@@ -5748,6 +5748,7 @@ while (done <= 0) + incomplete_transaction_log(US"connection lost"); + smtp_notquit_exit(US"connection-lost", US"421", + US"%s lost input connection", smtp_active_hostname); ++ _exit(0); + +``` + +Next we need to prohibit the creation of child processes. We do +that by simply returning `0` from `fork()`. +In `src/src/functions.h:1222` change +```diff +@@ -1219,7 +1219,7 @@ exim_fork(const unsigned char * purpose) + { + pid_t pid; + DEBUG(D_any) debug_printf("%s forking for %s\n", process_purpose, purpose); +-if ((pid = fork()) == 0) ++if ((pid = 0) == 0) + { + process_purpose = purpose; + DEBUG(D_any) debug_printf("postfork: %s\n", purpose); +``` + +Then we need to setup exim for correct processing of AFLs inputs. +Exim expects small delays between all SMTP messages. This of course +hinders fuzzing because AFLs input is a flat buffer where all messages +are already available. +In `src/src/globals.c:411` replace +```diff +@@ -408,7 +408,7 @@ BOOL sender_helo_dnssec = FALSE; + BOOL sender_host_dnssec = FALSE; + BOOL smtp_accept_keepalive = TRUE; + BOOL smtp_check_spool_space = TRUE; +-BOOL smtp_enforce_sync = TRUE; ++BOOL smtp_enforce_sync = FALSE; + BOOL smtp_etrn_serialize = TRUE; + BOOL smtp_input = FALSE; + BOOL smtp_return_error_details = FALSE; +``` +In `src/src/smtp_in.c:351` insert +```diff +@@ -348,7 +348,7 @@ wouldblock_reading(void) + int fd, rc; + fd_set fds; + struct timeval tzero = {.tv_sec = 0, .tv_usec = 0}; +- ++return TRUE; + #ifndef DISABLE_TLS + if (tls_in.active.sock >= 0) + return !tls_could_read(); +``` + +For performance reasons we add a deferred forkserver to exim +by inserting in `src/src/exim.c:4946` +```diff +@@ -4943,7 +4943,7 @@ if (f.daemon_listen || f.inetd_wait_mode || queue_interval > 0) + # endif + } + #endif +- ++ __AFL_INIT(); + daemon_go(); + } +``` + +Lastly we need to disable exims custom handling of segfaults by replacing in +`src/src/exim.c:1822` +```diff +@@ -1819,7 +1819,7 @@ descriptive text. */ + process_info = store_get(PROCESS_INFO_SIZE, TRUE); /* tainted */ + set_process_info("initializing"); + os_restarting_signal(SIGUSR1, usr1_handler); /* exiwhat */ +-signal(SIGSEGV, segv_handler); /* log faults */ ++//signal(SIGSEGV, segv_handler); /* log faults */ + + /* If running in a dockerized environment, the TERM signal is only + delegated to the PID 1 if we request it by setting an signal handler */ +``` + +### Build configuration +Exim keeps all build configuration in a single file called `src/Local/Makefile`. + +```sh +mkdir src/Local +``` + +Create the `Makefile` with the following contents: +```make +# The following lines have to be adjusted to your system +BIN_DIRECTORY=$(PWD)/src/build-Linux-x86_64 +CONFIGURE_FILE=$(PWD)/fuzz.conf +EXIM_USER=$(USER) +EXIM_GROUP=$(USER) +CONFIGURE_OWNER=$(USER) +CONFIGURE_GROUP=$(USER) +LOG_FILE_PATH=$(PWD)/log/%s +SYSTEM_ALIASES_FILE=$(PWD)/etc/aliases + +# The following can be used as is +CC=afl-clang-fast +LNCC=afl-clang-fast +LFLAGS=-fsanitize=address +CFLAGS=-fsanitize=address -g -Og +SPOOL_DIRECTORY=/tmp/exim-spool +DISABLE_TLS=yes +ROUTER_ACCEPT=yes +ROUTER_DNSLOOKUP=yes +ROUTER_IPLITERAL=yes +ROUTER_MANUALROUTE=yes +ROUTER_QUERYPROGRAM=yes +ROUTER_REDIRECT=yes +TRANSPORT_APPENDFILE=yes +TRANSPORT_AUTOREPLY=yes +TRANSPORT_PIPE=yes +TRANSPORT_SMTP=yes +SUPPORT_MAILDIR=yes +SUPPORT_MAILSTORE=yes +SUPPORT_MBX=yes +LOOKUP_PASSWD=yes +PCRE_CONFIG=yes +DISABLE_MAL_AVE=yes +DISABLE_MAL_KAV=yes +DISABLE_MAL_MKS=yes +DISABLE_DNSSEC=yes +DISABLE_EVENT=yes +DISABLE_PIPE_CONNECT=yes +FIXED_NEVER_USERS=root +ALLOW_INSECURE_TAINTED_DATA=yes +AUTH_PLAINTEXT=yes +HEADERS_CHARSET="ISO-8859-1" +EXICYCLOG_MAX=10 +COMPRESS_COMMAND=/usr/bin/gzip +COMPRESS_SUFFIX=gz +ZCAT_COMMAND=/usr/bin/zcat +NO_SYMLINK=yes +EXIM_TMPDIR="/tmp" +DELIVER_IN_BUFFER_SIZE=4096 +DELIVER_OUT_BUFFER_SIZE=4096 +NVALGRIND=1 +PID_FILE_PATH=/dev/null +``` + +You must replace `$(USER)` with your local username and `$(PWD)` with the +directory of the exim repo. + +Then build exim: +```sh +make -C src +``` + +If you get the message +``` +>>> exim binary built +``` +everything went well. + +### Runtime configuration +Exim looks for a configuration file `fuzz.conf` in the exim repo root. +Create it with the following contents: +``` +no_message_logs +log_selector = -all +primary_hostname = localhost +domainlist local_domains = @ +domainlist relay_to_domains = localhost +hostlist relay_from_hosts = localhost + +acl_smtp_rcpt = accept_everything +.ifdef _HAVE_PRDR +acl_smtp_data_prdr = accept_everything +.endif +acl_smtp_auth = accept_everything +acl_smtp_connect = accept_everything +acl_smtp_data = accept_everything +acl_smtp_etrn = accept_everything +acl_smtp_expn = accept_everything +acl_smtp_helo = accept_everything +acl_smtp_mail = accept_everything +acl_smtp_mailauth = accept_everything +acl_smtp_predata =accept_everything +acl_smtp_quit = accept_everything +acl_smtp_vrfy = accept_everything + +acl_not_smtp = deny_everything +acl_not_smtp_start = deny_everything + +daemon_smtp_ports = 2525 + +never_users = root + +dns_dnssec_ok = 0 + +ignore_bounce_errors_after = 2d + +timeout_frozen_after = 7d + +begin acl +accept_everything: + accept +deny_everything: + deny + +begin routers +localuser: + driver = accept + check_local_user + transport = local_delivery + cannot_route_message = Unknown user + +begin transports +local_delivery: + driver = appendfile + file = /tmp/mail/$local_part_data + delivery_date_add + envelope_to_add + return_path_add + group = $USER + +begin retry +# Address or Domain Error Retries +# ----------------- ----- ------- +* * F,2h,15m; G,16h,1h,1.5; F,4d,6h + +begin rewrite + +begin authenticators +PLAIN: +driver = plaintext +public_name = PLAIN +server_set_id = $auth2 +server_prompts = : + +# AUTH credentials are test:test (can be changed here) +server_condition = ${if and {{eq{$auth2}{test}}{eq{$auth3}{test}}}} +``` + +Change `group = $USER` to your local username. +This configures exim with only plaintext authentication, no DNSSEC, no TLS and no real ACLs. + +### Fuzzing Setup +Now it's time to start AFL: +```sh +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- ./src/build-Linux-x86_64/exim -bdf +``` diff --git a/examples/nginx/README.md b/examples/nginx/README.md new file mode 100644 index 0000000..872d30f --- /dev/null +++ b/examples/nginx/README.md @@ -0,0 +1,101 @@ +# Fuzzing nginx with AFL + +This document explains how to setup [nginx 1.21.4](https://github.com/nginx/nginx) for fuzzing +with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +git clone https://github.com/nginx/nginx +cd nginx +git checkout release-1.21.4 +``` + +### Patching the source +nginx runs in an endless loop but we want it to exit +after processing one request. We locate the event loop +in `src/os/unix/ngx_process_cycle.c:297` and replace +```diff +@@ -294,7 +294,7 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) + } + } + +- for ( ;; ) { ++ for (i = 0; i < 2; ++i) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); + + ngx_process_events_and_timers(cycle); +``` +The first iteration is for the `accept()`, the second iteration is for receiving +the request. + +Then we add a deferred forkserver to AFL by inserting in `src/os/unix/ngx_process_cycle.c:296` +```diff +@@ -293,7 +293,7 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) + } + } + } +- ++ __AFL_INIT(); + for (i = 0; i < 2; ++i) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); +``` + +### Build configuration +```sh +auto/configure \ + --prefix=$PWD \ + --conf-path=$PWD/fuzz.conf \ + --user=$USER --group=$USER \ + --with-debug \ + --with-cc=afl-clang-fast \ + --with-cc-opt="-fsanitize=address -g -Og -Wno-error=unused-but-set-variable" \ + --with-ld-opt="-fsanitize=address" \ + --pid-path=/dev/null \ + --with-poll_module +``` +and +```sh +make +``` + +### Runtime configuration +We have to tell nginx not to use any child processes / threads +and to not have any disk I/O. +We configure that in `fuzz.conf`. +``` +master_process off; +daemon off; +error_log /dev/null; +events { + worker_connections 1024; + use poll; + multi_accept off; +} + +http { + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + + server { + listen 20801; + server_name localhost; + access_log /dev/null; + + location / { + root html; + index index.html; + } + } +} +``` + +### Fuzzing Setup +``` +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- ./objs/nginx +``` diff --git a/examples/openssh/README.md b/examples/openssh/README.md new file mode 100644 index 0000000..e7e86df --- /dev/null +++ b/examples/openssh/README.md @@ -0,0 +1,109 @@ +# Fuzzing OpenSSH with AFL + +This document explains how to setup [openssh 8.8](https://www.openssh.com/) for fuzzing +with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +git clone https://github.com/openssh/openssh-portable +cd openssh-portable +git checkout V_8_8_P1 +``` + +### Patching the source +Disable privilege separation in `sshd.c:234`: +```diff +@@ -231,7 +231,7 @@ static int *startup_flags = NULL; /* Indicates child closed listener */ + static int startup_pipe = -1; /* in child */ + + /* variables used for privilege separation */ +-int use_privsep = -1; ++int use_privsep = PRIVSEP_OFF; + struct monitor *pmonitor = NULL; + int privsep_is_preauth = 1; + static int privsep_chroot = 1; +``` + +Disable PRNG in `openbsd-compat/arc4random.c:244` by inserting: +```diff +@@ -241,6 +241,7 @@ arc4random_addrandom(u_char *dat, int datlen) + u_int32_t + arc4random(void) + { ++ return 0; + u_int32_t val; + + _ARC4_LOCK(); +``` + +In `cipher.c` replace +```diff +@@ -75,7 +75,7 @@ struct sshcipher { + #define CFLAG_CHACHAPOLY (1<<1) + #define CFLAG_AESCTR (1<<2) + #define CFLAG_NONE (1<<3) +-#define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */ ++#define CFLAG_INTERNAL 0 /* Don't use "none" for packets */ + #ifdef WITH_OPENSSL + const EVP_CIPHER *(*evptype)(void); + #else +``` + +In `openbsd-compat/bsd-closefrom.c:139` insert: +```diff +@@ -136,7 +136,8 @@ closefrom(int lowfd) + while ((dent = readdir(dirp)) != NULL) { + fd = strtol(dent->d_name, &endp, 10); + if (dent->d_name != endp && *endp == '\0' && +- fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) ++ fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp) ++ && fd < 32) + (void) close((int) fd); + } + (void) closedir(dirp); +``` + +### Build configuration +```sh +autoreconf -i +CC=afl-clang-fast LIBS=-ldl CFLAGS="-fsanitize=address -g -Og" LDFLAGS="-fsanitize=address" ./configure \ + --disable-strip \ + --without-zlib \ + --without-pam \ + --without-selinux \ + --with-privsep-path=empty \ + --with-sandbox=no \ + --with-privsep-user=$USER +make sshd +``` + +### Runtime configuration +Generate a host key: +``` +ssh-keygen -f key -N "" +``` + +Save the following configuration in `fuzz.conf`: +``` +HostKey /key +AuthenticationMethods none +Banner none +Compression no +LogLevel QUIET +PermitRootLogin no +PermitTTY no +PermitUserRC no +PrintMotd no +UsePrivilegeSeparation no +Ciphers none +``` + +### Fuzzing Setup +``` +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- $(realpath ./sshd) -4 -E /dev/null -D -f fuzz.conf -p 12222 -r -d +``` diff --git a/examples/openvpn/README.md b/examples/openvpn/README.md new file mode 100644 index 0000000..43d5711 --- /dev/null +++ b/examples/openvpn/README.md @@ -0,0 +1,59 @@ +# Fuzzing OpenVPN with AFL + +This document explains how to setup [OpenVPN 2.5.5](https://github.com/OpenVPN/openvpn) for fuzzing +with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +git clone https://github.com/OpenVPN/openvpn +cd openvpn +git checkout v2.5.5 +``` + +### Patching the source +In `src/openvpn/mtcp.c:820` replace +```diff + /* per-packet event loop */ +- while (true) ++ for (int i = 0; i < 2; ++i) + { +``` + +### Build configuration +```sh +autoreconf -i +CC=afl-clang-fast CFLAGS="-fsanitize=address -g -Og" LDFLAGS="-fsanitize=address" ./configure --disable-lzo --disable-lz4 --enable-comp-stub --disable-unit-tests +make +``` + +### Runtime Configuration +Create `fuzz.conf`: +``` +local 127.0.0.1 +port 1194 +proto tcp +dev tun +server 10.8.0.0 255.255.255.0 +cipher AES-128-GCM +verb 0 + +ca ca.crt +cert server.crt +key server.key +dh dh2048.pem +``` + +Copy the necessary keys: +```sh +cp sample/sample-keys/{ca.crt,server.crt,server.key,dh2048.pem} . +``` + +### Fuzzing Setup +``` +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- src/openvpn/openvpn fuzz.conf +``` diff --git a/examples/redis/README.md b/examples/redis/README.md new file mode 100644 index 0000000..23092e0 --- /dev/null +++ b/examples/redis/README.md @@ -0,0 +1,67 @@ +# Fuzzing redis with AFL + +This document explains how to setup [redis 6.2.6](https://github.com/redis/redis/releases/tag/6.2.6) for fuzzing +with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +git clone https://github.com/redis/redis +cd redis +git checkout 6.2.6 +``` + +### Patching the source +In `src/networking.c` replace ... +```diff +@@ -1047,7 +1047,7 @@ void clientAcceptHandler(connection *conn) { + c); + } + +-#define MAX_ACCEPTS_PER_CALL 1000 ++#define MAX_ACCEPTS_PER_CALL 1 + static void acceptCommonHandler(connection *conn, int flags, char *ip) { + client *c; + char conninfo[100]; +``` +... and insert +```diff +@@ -2197,6 +2197,7 @@ void readQueryFromClient(connection *conn) { + } else if (nread == 0) { + serverLog(LL_VERBOSE, "Client closed connection"); + freeClientAsync(c); ++ exit(0); + return; + } else if (c->flags & CLIENT_MASTER) { + /* Append the query buffer to the pending (not applied) buffer +``` + +### Build configuration +```sh +mkdir install +make CC="afl-clang-fast" REDIS_CFLAGS="-fsanitize=address -g -Og" REDIS_LDFLAGS="-fsanitize=address" MALLOC="libc" +make PREFIX=$PWD/install install +``` + +### Runtime configuration +Create `fuzz.conf`: +``` +bind 127.0.0.1 +daemonize no +supervised no +loglevel warning +logfile /dev/null +always-show-logo no +io-threads 1 +timeout 0 +databases 1 +``` + +### Fuzzing Setup +``` +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- ./install/bin/redis-server fuzz.conf +``` diff --git a/examples/vsftpd/README.md b/examples/vsftpd/README.md new file mode 100644 index 0000000..f1c16e0 --- /dev/null +++ b/examples/vsftpd/README.md @@ -0,0 +1,182 @@ +# Fuzzing vsftpd with AFL + +This document explains how to setup [vsftpd 3.0.5](https://security.appspot.com/vsftpd.html) +for fuzzing with AFL and libdesock. + +__Disclaimer:__ This document only shows the modifications necessary to get the desocketing working. +Further modifications may be necessary for successful fuzzing. + +### Installing the source +```sh +wget https://security.appspot.com/downloads/vsftpd-3.0.5.tar.gz +tar -xf vsftpd-3.0.5.tar.gz +cd vsftpd-3.0.5 +``` + +### Patching the source +First we must prohibit the creation of any child processes. +To do that we insert in `standalone.c:156`: +```diff +@@ -153,6 +153,7 @@ vsf_standalone_main(void) + child_info.num_this_ip = 0; + p_raw_addr = vsf_sysutil_sockaddr_get_raw_addr(p_accept_addr); + child_info.num_this_ip = handle_ip_count(p_raw_addr); ++ /* + if (tunable_isolate) + { + if (tunable_http_enable && tunable_isolate_network) +@@ -168,6 +169,8 @@ vsf_standalone_main(void) + { + new_child = vsf_sysutil_fork_failok(); + } ++ */ ++ new_child = 0; + if (new_child != 0) + { + /* Parent context */ +``` + +vsftpd duplicates the FTP command socket to stdin, stdout and stderr. This +interferes with the desocketing library so we prohibit that too. +In `defs.h:6` replace +```diff +@@ -3,7 +3,7 @@ + + #define VSFTP_DEFAULT_CONFIG "/etc/vsftpd.conf" + +-#define VSFTP_COMMAND_FD 0 ++#define VSFTP_COMMAND_FD 29 + + #define VSFTP_PASSWORD_MAX 128 + #define VSFTP_USERNAME_MAX 128 +``` +and in `standalone.c:208` replace +```diff +@@ -205,9 +205,7 @@ static void + prepare_child(int new_client_sock) + { + /* We must satisfy the contract: command socket on fd 0, 1, 2 */ +- vsf_sysutil_dupfd2(new_client_sock, 0); +- vsf_sysutil_dupfd2(new_client_sock, 1); +- vsf_sysutil_dupfd2(new_client_sock, 2); ++ vsf_sysutil_dupfd2(new_client_sock, VSFTP_COMMAND_FD); + if (new_client_sock > 2) + { + vsf_sysutil_close(new_client_sock); +``` + +Next vsftpd enforces a custom memory limit. This interferes with ASAN +so we insert in `sysutil.c:2795` +```diff +@@ -2793,6 +2793,7 @@ void + vsf_sysutil_set_address_space_limit(unsigned long bytes) + { + /* Unfortunately, OpenBSD is missing RLIMIT_AS. */ ++ return; + #ifdef RLIMIT_AS + int ret; + struct rlimit rlim; +``` + +Then we add a deferred forkserver to vsftpd by inserting +in `prelogin.c:61` +```diff +@@ -59,6 +59,7 @@ init_connection(struct vsf_session* p_sess) + { + emit_greeting(p_sess); + } ++ __AFL_INIT(); + parse_username_password(p_sess); + } +``` + +We also want to prevent vsftpd from interfering with the forkserver +so we disable its SIGCHLD handler in `standalone.c:77` +```diff +@@ -74,7 +74,7 @@ vsf_standalone_main(void) + { + vsf_sysutil_setproctitle("LISTENER"); + } +- vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1); ++ //vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1); + vsf_sysutil_install_sighandler(kVSFSysUtilSigHUP, handle_sighup, 0, 1); + if (tunable_listen) + { +``` + +Lastly to prevent endless loops we disable the `bug()` function +in `utility.c:43` +```diff +@@ -40,6 +40,7 @@ die2(const char* p_text1, const char* p_text2) + void + bug(const char* p_text) + { ++ return; + /* Rats. Try and write the reason to the network for diagnostics */ + vsf_sysutil_activate_noblock(VSFTP_COMMAND_FD); + (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "500 OOPS: ", 10); +``` + +### Build configuration +In `Makefile` replace +```diff +@@ -1,16 +1,16 @@ + # Makefile for systems with GNU tools +-CC = gcc ++CC = afl-clang-fast + INSTALL = install + IFLAGS = -idirafter dummyinc + #CFLAGS = -g +-CFLAGS = -O2 -fPIE -fstack-protector --param=ssp-buffer-size=4 \ +- -Wall -W -Wshadow -Werror -Wformat-security \ ++CFLAGS = -fsanitize=address -g -Og -fPIE -fstack-protector \ ++ -Wall -W -Wshadow -Wformat-security \ + -D_FORTIFY_SOURCE=2 \ + #-pedantic -Wconversion + + LIBS = `./vsf_findlibs.sh` +-LINK = -Wl,-s +-LDFLAGS = -fPIE -pie -Wl,-z,relro -Wl,-z,now ++LINK = ++LDFLAGS = -fPIE -pie -Wl,-z,relro -Wl,-z,now -fsanitize=address + + OBJS = main.o utility.o prelogin.o ftpcmdio.o postlogin.o privsock.o \ + tunables.o ftpdataio.o secbuf.o ls.o \ +``` + +and execute +```sh +make +``` + +### Runtime configuration +Save the following configuration as `fuzz.conf`. +``` +listen=YES +seccomp_sandbox=NO +one_process_model=YES + +# User management +anonymous_enable=YES +no_anon_password=YES +nopriv_user=nobody + +# Permissions +connect_from_port_20=NO +run_as_launching_user=YES +listen_port=2121 +listen_address=127.0.0.1 +pasv_address=127.0.0.1 + +# Filesystem interactions +write_enable=NO +download_enable=NO +``` + +### Fuzzing Setup +Now it's time to start AFL: +``` +export AFL_PRELOAD=libdesock.so +export AFL_TMPDIR=/tmp +afl-fuzz -i corpus -o findings -m none -- ./vsftpd fuzz.conf +``` diff --git a/libdesock/include/arch/aarch64/syscall_arch.h b/libdesock/include/arch/aarch64/syscall_arch.h new file mode 100644 index 0000000..504983a --- /dev/null +++ b/libdesock/include/arch/aarch64/syscall_arch.h @@ -0,0 +1,78 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "svc 0" \ + : "=r"(x0) : __VA_ARGS__ : "memory", "cc"); \ + return x0; \ + } while (0) + +static inline long __syscall0(long n) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0"); + __asm_syscall("r"(x8)); +} + +static inline long __syscall1(long n, long a) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + __asm_syscall("r"(x8), "0"(x0)); +} + +static inline long __syscall2(long n, long a, long b) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + __asm_syscall("r"(x8), "0"(x0), "r"(x1)); +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2)); +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)); +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)); +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + register long x5 __asm__("x5") = f; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)); +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__kernel_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6.39" + +#define IPC_64 0 diff --git a/libdesock/include/arch/arm/syscall_arch.h b/libdesock/include/arch/arm/syscall_arch.h new file mode 100644 index 0000000..a877b2c --- /dev/null +++ b/libdesock/include/arch/arm/syscall_arch.h @@ -0,0 +1,103 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) + +#ifdef __thumb__ + +/* Avoid use of r7 in asm constraints when producing thumb code, + * since it's reserved as frame pointer and might not be supported. */ +#define __ASM____R7__ +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "mov %1,r7 ; mov r7,%2 ; svc 0 ; mov r7,%1" \ + : "=r"(r0), "=&r"((int){0}) : __VA_ARGS__ : "memory"); \ + return r0; \ + } while (0) + +#else + +#define __ASM____R7__ __asm__("r7") +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "svc 0" \ + : "=r"(r0) : __VA_ARGS__ : "memory"); \ + return r0; \ + } while (0) +#endif + +/* For thumb2, we can allow 8-bit immediate syscall numbers, saving a + * register in the above dance around r7. Does not work for thumb1 where + * only movs, not mov, supports immediates, and we can't use movs because + * it doesn't support high regs. */ +#ifdef __thumb2__ +#define R7_OPERAND "rI"(r7) +#else +#define R7_OPERAND "r"(r7) +#endif + +static inline long __syscall0(long n) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0"); + __asm_syscall(R7_OPERAND); +} + +static inline long __syscall1(long n, long a) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + __asm_syscall(R7_OPERAND, "0"(r0)); +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1)); +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2)); +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3)); +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4)); +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r7 __ASM____R7__ = n; + register long r0 __asm__("r0") = a; + register long r1 __asm__("r1") = b; + register long r2 __asm__("r2") = c; + register long r3 __asm__("r3") = d; + register long r4 __asm__("r4") = e; + register long r5 __asm__("r5") = f; + __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5)); +} + +#define SYSCALL_FADVISE_6_ARG + +#define SYSCALL_IPC_BROKEN_MODE diff --git a/libdesock/include/arch/i386/syscall_arch.h b/libdesock/include/arch/i386/syscall_arch.h new file mode 100644 index 0000000..f92b7aa --- /dev/null +++ b/libdesock/include/arch/i386/syscall_arch.h @@ -0,0 +1,89 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) + +#if SYSCALL_NO_TLS +#define SYSCALL_INSNS "int $128" +#else +#define SYSCALL_INSNS "call *%%gs:16" +#endif + +#define SYSCALL_INSNS_12 "xchg %%ebx,%%edx ; " SYSCALL_INSNS " ; xchg %%ebx,%%edx" +#define SYSCALL_INSNS_34 "xchg %%ebx,%%edi ; " SYSCALL_INSNS " ; xchg %%ebx,%%edi" + +static inline long __syscall0(long n) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n) : "memory"); + return __ret; +} + +static inline long __syscall1(long n, long a1) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1) : "memory"); + return __ret; +} + +static inline long __syscall2(long n, long a1, long a2) +{ + unsigned long __ret; + __asm__ __volatile__ (SYSCALL_INSNS_12 : "=a"(__ret) : "a"(n), "d"(a1), "c"(a2) : "memory"); + return __ret; +} + +static inline long __syscall3(long n, long a1, long a2, long a3) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3) : "memory"); +#else + __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3) : "memory"); +#endif + return __ret; +} + +static inline long __syscall4(long n, long a1, long a2, long a3, long a4) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); +#else + __asm__ __volatile__ (SYSCALL_INSNS_34 : "=a"(__ret) : "a"(n), "D"(a1), "c"(a2), "d"(a3), "S"(a4) : "memory"); +#endif + return __ret; +} + +static inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ (SYSCALL_INSNS + : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#else + __asm__ __volatile__ ("pushl %2 ; push %%ebx ; mov 4(%%esp),%%ebx ; " SYSCALL_INSNS " ; pop %%ebx ; add $4,%%esp" + : "=a"(__ret) : "a"(n), "g"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#endif + return __ret; +} + +static inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + unsigned long __ret; +#if !defined(__PIC__) || !defined(BROKEN_EBX_ASM) + __asm__ __volatile__ ("pushl %7 ; push %%ebp ; mov 4(%%esp),%%ebp ; " SYSCALL_INSNS " ; pop %%ebp ; add $4,%%esp" + : "=a"(__ret) : "a"(n), "b"(a1), "c"(a2), "d"(a3), "S"(a4), "D"(a5), "g"(a6) : "memory"); +#else + unsigned long a1a6[2] = { a1, a6 }; + __asm__ __volatile__ ("pushl %1 ; push %%ebx ; push %%ebp ; mov 8(%%esp),%%ebx ; mov 4(%%ebx),%%ebp ; mov (%%ebx),%%ebx ; " SYSCALL_INSNS " ; pop %%ebp ; pop %%ebx ; add $4,%%esp" + : "=a"(__ret) : "g"(&a1a6), "a"(n), "c"(a2), "d"(a3), "S"(a4), "D"(a5) : "memory"); +#endif + return __ret; +} + +#define VDSO_USEFUL +#define VDSO_CGT32_SYM "__vdso_clock_gettime" +#define VDSO_CGT32_VER "LINUX_2.6" +#define VDSO_CGT_SYM "__vdso_clock_gettime64" +#define VDSO_CGT_VER "LINUX_2.6" diff --git a/libdesock/include/arch/m68k/syscall_arch.h b/libdesock/include/arch/m68k/syscall_arch.h new file mode 100644 index 0000000..6a9d0ae --- /dev/null +++ b/libdesock/include/arch/m68k/syscall_arch.h @@ -0,0 +1,90 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) + +static __inline long __syscall0(long n) +{ + register unsigned long d0 __asm__("d0") = n; + __asm__ __volatile__ ("trap #0" : "+r"(d0) + : + : "memory"); + return d0; +} + +static inline long __syscall1(long n, long a) +{ + register unsigned long d0 __asm__("d0") = n; + register unsigned long d1 __asm__("d1") = a; + __asm__ __volatile__ ("trap #0" : "+r"(d0) + : "r"(d1) + : "memory"); + return d0; +} + +static inline long __syscall2(long n, long a, long b) +{ + register unsigned long d0 __asm__("d0") = n; + register unsigned long d1 __asm__("d1") = a; + register unsigned long d2 __asm__("d2") = b; + __asm__ __volatile__ ("trap #0" : "+r"(d0) + : "r"(d1), "r"(d2) + : "memory"); + return d0; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register unsigned long d0 __asm__("d0") = n; + register unsigned long d1 __asm__("d1") = a; + register unsigned long d2 __asm__("d2") = b; + register unsigned long d3 __asm__("d3") = c; + __asm__ __volatile__ ("trap #0" : "+r"(d0) + : "r"(d1), "r"(d2), "r"(d3) + : "memory"); + return d0; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register unsigned long d0 __asm__("d0") = n; + register unsigned long d1 __asm__("d1") = a; + register unsigned long d2 __asm__("d2") = b; + register unsigned long d3 __asm__("d3") = c; + register unsigned long d4 __asm__("d4") = d; + __asm__ __volatile__ ("trap #0" : "+r"(d0) + : "r"(d1), "r"(d2), "r"(d3), "r"(d4) + : "memory"); + return d0; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register unsigned long d0 __asm__("d0") = n; + register unsigned long d1 __asm__("d1") = a; + register unsigned long d2 __asm__("d2") = b; + register unsigned long d3 __asm__("d3") = c; + register unsigned long d4 __asm__("d4") = d; + register unsigned long d5 __asm__("d5") = e; + __asm__ __volatile__ ("trap #0" : "+r"(d0) + : "r"(d1), "r"(d2), "r"(d3), "r"(d4), "r"(d5) + : "memory"); + return d0; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register unsigned long d0 __asm__("d0") = n; + register unsigned long d1 __asm__("d1") = a; + register unsigned long d2 __asm__("d2") = b; + register unsigned long d3 __asm__("d3") = c; + register unsigned long d4 __asm__("d4") = d; + register unsigned long d5 __asm__("d5") = e; + register unsigned long a0 __asm__("a0") = f; + __asm__ __volatile__ ("trap #0" : "+r"(d0) + : "r"(d1), "r"(d2), "r"(d3), "r"(d4), "r"(d5), "r"(a0) + : "memory"); + return d0; +} + +#define SYSCALL_IPC_BROKEN_MODE diff --git a/libdesock/include/arch/microblaze/syscall_arch.h b/libdesock/include/arch/microblaze/syscall_arch.h new file mode 100644 index 0000000..61d8248 --- /dev/null +++ b/libdesock/include/arch/microblaze/syscall_arch.h @@ -0,0 +1,99 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) + +static __inline long __syscall0(long n) +{ + register unsigned long r12 __asm__("r12") = n; + register unsigned long r3 __asm__("r3"); + __asm__ __volatile__ ("brki r14, 0x8" : "=r"(r3) + : "r"(r12) + : "memory", "r4"); + return r3; +} + +static inline long __syscall1(long n, long a) +{ + register unsigned long r12 __asm__("r12") = n; + register unsigned long r3 __asm__("r3"); + register unsigned long r5 __asm__("r5") = a; + __asm__ __volatile__ ("brki r14, 0x8" : "=r"(r3) + : "r"(r12), "r"(r5) + : "memory", "r4"); + return r3; +} + +static inline long __syscall2(long n, long a, long b) +{ + register unsigned long r12 __asm__("r12") = n; + register unsigned long r3 __asm__("r3"); + register unsigned long r5 __asm__("r5") = a; + register unsigned long r6 __asm__("r6") = b; + __asm__ __volatile__ ("brki r14, 0x8" : "=r"(r3) + : "r"(r12), "r"(r5), "r"(r6) + : "memory", "r4"); + return r3; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register unsigned long r12 __asm__("r12") = n; + register unsigned long r3 __asm__("r3"); + register unsigned long r5 __asm__("r5") = a; + register unsigned long r6 __asm__("r6") = b; + register unsigned long r7 __asm__("r7") = c; + __asm__ __volatile__ ("brki r14, 0x8" : "=r"(r3) + : "r"(r12), "r"(r5), "r"(r6), "r"(r7) + : "memory", "r4"); + return r3; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register unsigned long r12 __asm__("r12") = n; + register unsigned long r3 __asm__("r3"); + register unsigned long r5 __asm__("r5") = a; + register unsigned long r6 __asm__("r6") = b; + register unsigned long r7 __asm__("r7") = c; + register unsigned long r8 __asm__("r8") = d; + __asm__ __volatile__ ("brki r14, 0x8" : "=r"(r3) + : "r"(r12), "r"(r5), "r"(r6), "r"(r7), "r"(r8) + : "memory", "r4"); + return r3; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register unsigned long r12 __asm__("r12") = n; + register unsigned long r3 __asm__("r3"); + register unsigned long r5 __asm__("r5") = a; + register unsigned long r6 __asm__("r6") = b; + register unsigned long r7 __asm__("r7") = c; + register unsigned long r8 __asm__("r8") = d; + register unsigned long r9 __asm__("r9") = e; + __asm__ __volatile__ ("brki r14, 0x8" : "=r"(r3) + : "r"(r12), "r"(r5), "r"(r6), "r"(r7), "r"(r8), "r"(r9) + : "memory", "r4"); + return r3; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register unsigned long r12 __asm__("r12") = n; + register unsigned long r3 __asm__("r3"); + register unsigned long r5 __asm__("r5") = a; + register unsigned long r6 __asm__("r6") = b; + register unsigned long r7 __asm__("r7") = c; + register unsigned long r8 __asm__("r8") = d; + register unsigned long r9 __asm__("r9") = e; + register unsigned long r10 __asm__("r10") = f; + __asm__ __volatile__ ("brki r14, 0x8" : "=r"(r3) + : "r"(r12), "r"(r5), "r"(r6), "r"(r7), "r"(r8), "r"(r9), "r"(r10) + : "memory", "r4"); + return r3; +} + +#define SYSCALL_IPC_BROKEN_MODE + +#undef SYS_socketcall diff --git a/libdesock/include/arch/mips/syscall_arch.h b/libdesock/include/arch/mips/syscall_arch.h new file mode 100644 index 0000000..5b7c38d --- /dev/null +++ b/libdesock/include/arch/mips/syscall_arch.h @@ -0,0 +1,153 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) + +#define SYSCALL_RLIM_INFINITY (-1UL/2) + +#if __mips_isa_rev >= 6 +#define SYSCALL_CLOBBERLIST \ + "$1", "$3", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" +#else +#define SYSCALL_CLOBBERLIST \ + "$1", "$3", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "hi", "lo", "memory" +#endif + +static inline long __syscall0(long n) +{ + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2) + : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall1(long n, long a) +{ + register long r4 __asm__("$4") = a; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4) + : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5) + : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "addu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST, "$8", "$9", "$10"); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r8 __asm__("$8") = e; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "subu $sp,$sp,32 ; sw $8,16($sp) ; " + "addu $2,$0,%3 ; syscall ;" + "addu $sp,$sp,32" + : "=&r"(r2), "+r"(r7), "+r"(r8) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST, "$9", "$10"); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r8 __asm__("$8") = e; + register long r9 __asm__("$9") = f; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; " + "addu $2,$0,%4 ; syscall ;" + "addu $sp,$sp,32" + : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST, "$10"); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall7(long n, long a, long b, long c, long d, long e, long f, long g) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r8 __asm__("$8") = e; + register long r9 __asm__("$9") = f; + register long r10 __asm__("$10") = g; + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "subu $sp,$sp,32 ; sw $8,16($sp) ; sw $9,20($sp) ; sw $10,24($sp) ; " + "addu $2,$0,%5 ; syscall ;" + "addu $sp,$sp,32" + : "=&r"(r2), "+r"(r7), "+r"(r8), "+r"(r9), "+r"(r10) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +#define VDSO_USEFUL +#define VDSO_CGT32_SYM "__vdso_clock_gettime" +#define VDSO_CGT32_VER "LINUX_2.6" +#define VDSO_CGT_SYM "__vdso_clock_gettime64" +#define VDSO_CGT_VER "LINUX_2.6" + +#define SO_SNDTIMEO_OLD 0x1005 +#define SO_RCVTIMEO_OLD 0x1006 + +#undef SYS_socketcall diff --git a/libdesock/include/arch/mips64/syscall_arch.h b/libdesock/include/arch/mips64/syscall_arch.h new file mode 100644 index 0000000..ae6532f --- /dev/null +++ b/libdesock/include/arch/mips64/syscall_arch.h @@ -0,0 +1,128 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define SYSCALL_RLIM_INFINITY (-1UL/2) + +#if __mips_isa_rev >= 6 +#define SYSCALL_CLOBBERLIST \ + "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" +#else +#define SYSCALL_CLOBBERLIST \ + "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "hi", "lo", "memory" +#endif + +static inline long __syscall0(long n) +{ + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall1(long n, long a) +{ + register long r4 __asm__("$4") = a; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r8 __asm__("$8") = e; + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r8 __asm__("$8") = e; + register long r9 __asm__("$9") = f; + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" + +#define SO_SNDTIMEO_OLD 0x1005 +#define SO_RCVTIMEO_OLD 0x1006 diff --git a/libdesock/include/arch/mipsn32/syscall_arch.h b/libdesock/include/arch/mipsn32/syscall_arch.h new file mode 100644 index 0000000..c681905 --- /dev/null +++ b/libdesock/include/arch/mipsn32/syscall_arch.h @@ -0,0 +1,130 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define SYSCALL_RLIM_INFINITY (-1UL/2) + +#if __mips_isa_rev >= 6 +#define SYSCALL_CLOBBERLIST \ + "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" +#else +#define SYSCALL_CLOBBERLIST \ + "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "hi", "lo", "memory" +#endif + +static inline long __syscall0(long n) +{ + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall1(long n, long a) +{ + register long r4 __asm__("$4") = a; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7"); + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "=r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r8 __asm__("$8") = e; + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r4 __asm__("$4") = a; + register long r5 __asm__("$5") = b; + register long r6 __asm__("$6") = c; + register long r7 __asm__("$7") = d; + register long r8 __asm__("$8") = e; + register long r9 __asm__("$9") = f; + register long r2 __asm__("$2"); + + __asm__ __volatile__ ( + "daddu $2,$0,%2 ; syscall" + : "=&r"(r2), "+r"(r7) + : "ir"(n), "0"(r2), "r"(r4), "r"(r5), "r"(r6), "r"(r8), "r"(r9) + : SYSCALL_CLOBBERLIST); + return r7 && r2>0 ? -r2 : r2; +} + +#define VDSO_USEFUL +#define VDSO_CGT32_SYM "__vdso_clock_gettime" +#define VDSO_CGT32_VER "LINUX_2.6" +#define VDSO_CGT_SYM "__vdso_clock_gettime64" +#define VDSO_CGT_VER "LINUX_2.6" + +#define SO_SNDTIMEO_OLD 0x1005 +#define SO_RCVTIMEO_OLD 0x1006 diff --git a/libdesock/include/arch/or1k/syscall_arch.h b/libdesock/include/arch/or1k/syscall_arch.h new file mode 100644 index 0000000..21738ce --- /dev/null +++ b/libdesock/include/arch/or1k/syscall_arch.h @@ -0,0 +1,115 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) + +#define SYSCALL_MMAP2_UNIT 8192ULL + +static __inline long __syscall0(long n) +{ + register unsigned long r11 __asm__("r11") = n; + __asm__ __volatile__ ("l.sys 1" + : "=r"(r11) + : "r"(r11) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", + "r12", "r13", "r15", "r17", "r19", "r21", + "r23", "r25", "r27", "r29", "r31"); + return r11; +} + +static inline long __syscall1(long n, long a) +{ + register unsigned long r11 __asm__("r11") = n; + register unsigned long r3 __asm__("r3") = a; + __asm__ __volatile__ ("l.sys 1" + : "=r"(r11) + : "r"(r11), "r"(r3) + : "memory", "r4", "r5", "r6", "r7", "r8", + "r12", "r13", "r15", "r17", "r19", "r21", + "r23", "r25", "r27", "r29", "r31"); + return r11; +} + +static inline long __syscall2(long n, long a, long b) +{ + register unsigned long r11 __asm__("r11") = n; + register unsigned long r3 __asm__("r3") = a; + register unsigned long r4 __asm__("r4") = b; + __asm__ __volatile__ ("l.sys 1" + : "=r"(r11) + : "r"(r11), "r"(r3), "r"(r4) + : "memory", "r5", "r6", "r7", "r8", + "r12", "r13", "r15", "r17", "r19", "r21", + "r23", "r25", "r27", "r29", "r31"); + return r11; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register unsigned long r11 __asm__("r11") = n; + register unsigned long r3 __asm__("r3") = a; + register unsigned long r4 __asm__("r4") = b; + register unsigned long r5 __asm__("r5") = c; + __asm__ __volatile__ ("l.sys 1" + : "=r"(r11) + : "r"(r11), "r"(r3), "r"(r4), "r"(r5) + : "memory", "r6", "r7", "r8", + "r12", "r13", "r15", "r17", "r19", "r21", + "r23", "r25", "r27", "r29", "r31"); + return r11; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register unsigned long r11 __asm__("r11") = n; + register unsigned long r3 __asm__("r3") = a; + register unsigned long r4 __asm__("r4") = b; + register unsigned long r5 __asm__("r5") = c; + register unsigned long r6 __asm__("r6") = d; + __asm__ __volatile__ ("l.sys 1" + : "=r"(r11) + : "r"(r11), "r"(r3), "r"(r4), "r"(r5), "r"(r6) + : "memory", "r7", "r8", + "r12", "r13", "r15", "r17", "r19", "r21", + "r23", "r25", "r27", "r29", "r31"); + return r11; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register unsigned long r11 __asm__("r11") = n; + register unsigned long r3 __asm__("r3") = a; + register unsigned long r4 __asm__("r4") = b; + register unsigned long r5 __asm__("r5") = c; + register unsigned long r6 __asm__("r6") = d; + register unsigned long r7 __asm__("r7") = e; + __asm__ __volatile__ ("l.sys 1" + : "=r"(r11) + : "r"(r11), "r"(r3), "r"(r4), "r"(r5), "r"(r6), + "r"(r7) + : "memory", "r8", + "r12", "r13", "r15", "r17", "r19", "r21", + "r23", "r25", "r27", "r29", "r31"); + return r11; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register unsigned long r11 __asm__("r11") = n; + register unsigned long r3 __asm__("r3") = a; + register unsigned long r4 __asm__("r4") = b; + register unsigned long r5 __asm__("r5") = c; + register unsigned long r6 __asm__("r6") = d; + register unsigned long r7 __asm__("r7") = e; + register unsigned long r8 __asm__("r8") = f; + __asm__ __volatile__ ("l.sys 1" + : "=r"(r11) + : "r"(r11), "r"(r3), "r"(r4), "r"(r5), "r"(r6), + "r"(r7), "r"(r8) + : "memory", + "r12", "r13", "r15", "r17", "r19", "r21", + "r23", "r25", "r27", "r29", "r31"); + return r11; +} + +#define IPC_64 0 diff --git a/libdesock/include/arch/powerpc/syscall_arch.h b/libdesock/include/arch/powerpc/syscall_arch.h new file mode 100644 index 0000000..ede97c1 --- /dev/null +++ b/libdesock/include/arch/powerpc/syscall_arch.h @@ -0,0 +1,94 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x)) + +static inline long __syscall0(long n) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3"); + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "=r"(r3) + :: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall1(long n, long a) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3) + :: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4) + :: "memory", "cr0", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5) + :: "memory", "cr0", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + register long r6 __asm__("r6") = d; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5), "+r"(r6) + :: "memory", "cr0", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + register long r6 __asm__("r6") = d; + register long r7 __asm__("r7") = e; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5), "+r"(r6), "+r"(r7) + :: "memory", "cr0", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + register long r6 __asm__("r6") = d; + register long r7 __asm__("r7") = e; + register long r8 __asm__("r8") = f; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5), "+r"(r6), "+r"(r7), "+r"(r8) + :: "memory", "cr0", "r9", "r10", "r11", "r12"); + return r3; +} + +#define SYSCALL_FADVISE_6_ARG + +#define SO_RCVTIMEO_OLD 18 +#define SO_SNDTIMEO_OLD 19 diff --git a/libdesock/include/arch/powerpc64/syscall_arch.h b/libdesock/include/arch/powerpc64/syscall_arch.h new file mode 100644 index 0000000..76b4e33 --- /dev/null +++ b/libdesock/include/arch/powerpc64/syscall_arch.h @@ -0,0 +1,90 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +static inline long __syscall0(long n) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3"); + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "=r"(r3) + :: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall1(long n, long a) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3) + :: "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4) + :: "memory", "cr0", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5) + :: "memory", "cr0", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + register long r6 __asm__("r6") = d; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5), "+r"(r6) + :: "memory", "cr0", "r7", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + register long r6 __asm__("r6") = d; + register long r7 __asm__("r7") = e; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5), "+r"(r6), "+r"(r7) + :: "memory", "cr0", "r8", "r9", "r10", "r11", "r12"); + return r3; +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r0 __asm__("r0") = n; + register long r3 __asm__("r3") = a; + register long r4 __asm__("r4") = b; + register long r5 __asm__("r5") = c; + register long r6 __asm__("r6") = d; + register long r7 __asm__("r7") = e; + register long r8 __asm__("r8") = f; + __asm__ __volatile__("sc ; bns+ 1f ; neg %1, %1 ; 1:" + : "+r"(r0), "+r"(r3), "+r"(r4), "+r"(r5), "+r"(r6), "+r"(r7), "+r"(r8) + :: "memory", "cr0", "r9", "r10", "r11", "r12"); + return r3; +} + +#define SO_RCVTIMEO_OLD 18 +#define SO_SNDTIMEO_OLD 19 diff --git a/libdesock/include/arch/riscv64/syscall_arch.h b/libdesock/include/arch/riscv64/syscall_arch.h new file mode 100644 index 0000000..7fd042c --- /dev/null +++ b/libdesock/include/arch/riscv64/syscall_arch.h @@ -0,0 +1,78 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __asm_syscall(...) \ + __asm__ __volatile__ ("ecall\n\t" \ + : "=r"(a0) : __VA_ARGS__ : "memory"); \ + return a0; \ + +static inline long __syscall0(long n) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0"); + __asm_syscall("r"(a7)) +} + +static inline long __syscall1(long n, long a) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + __asm_syscall("r"(a7), "0"(a0)) +} + +static inline long __syscall2(long n, long a, long b) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + __asm_syscall("r"(a7), "0"(a0), "r"(a1)) +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2)) +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3)) +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + register long a4 __asm__("a4") = e; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4)) +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long a7 __asm__("a7") = n; + register long a0 __asm__("a0") = a; + register long a1 __asm__("a1") = b; + register long a2 __asm__("a2") = c; + register long a3 __asm__("a3") = d; + register long a4 __asm__("a4") = e; + register long a5 __asm__("a5") = f; + __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)) +} + +#define VDSO_USEFUL +/* We don't have a clock_gettime function. +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" */ + +#define IPC_64 0 diff --git a/libdesock/include/arch/s390x/syscall_arch.h b/libdesock/include/arch/s390x/syscall_arch.h new file mode 100644 index 0000000..83cc9a2 --- /dev/null +++ b/libdesock/include/arch/s390x/syscall_arch.h @@ -0,0 +1,74 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __asm_syscall(ret, ...) do { \ + __asm__ __volatile__ ("svc 0\n" \ + : ret : __VA_ARGS__ : "memory"); \ + return r2; \ + } while (0) + +static inline long __syscall0(long n) +{ + register long r1 __asm__("r1") = n; + register long r2 __asm__("r2"); + __asm_syscall("=r"(r2), "r"(r1)); +} + +static inline long __syscall1(long n, long a) +{ + register long r1 __asm__("r1") = n; + register long r2 __asm__("r2") = a; + __asm_syscall("+r"(r2), "r"(r1)); +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r1 __asm__("r1") = n; + register long r2 __asm__("r2") = a; + register long r3 __asm__("r3") = b; + __asm_syscall("+r"(r2), "r"(r1), "r"(r3)); +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r1 __asm__("r1") = n; + register long r2 __asm__("r2") = a; + register long r3 __asm__("r3") = b; + register long r4 __asm__("r4") = c; + __asm_syscall("+r"(r2), "r"(r1), "r"(r3), "r"(r4)); +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r1 __asm__("r1") = n; + register long r2 __asm__("r2") = a; + register long r3 __asm__("r3") = b; + register long r4 __asm__("r4") = c; + register long r5 __asm__("r5") = d; + __asm_syscall("+r"(r2), "r"(r1), "r"(r3), "r"(r4), "r"(r5)); +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r1 __asm__("r1") = n; + register long r2 __asm__("r2") = a; + register long r3 __asm__("r3") = b; + register long r4 __asm__("r4") = c; + register long r5 __asm__("r5") = d; + register long r6 __asm__("r6") = e; + __asm_syscall("+r"(r2), "r"(r1), "r"(r3), "r"(r4), "r"(r5), "r"(r6)); +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + if (n == SYS_mmap) return __syscall1(n, (long)(long[]){a,b,c,d,e,f}); + + register long r1 __asm__("r1") = n; + register long r2 __asm__("r2") = a; + register long r3 __asm__("r3") = b; + register long r4 __asm__("r4") = c; + register long r5 __asm__("r5") = d; + register long r6 __asm__("r6") = e; + register long r7 __asm__("r7") = f; + __asm_syscall("+r"(r2), "r"(r1), "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)); +} diff --git a/libdesock/include/arch/sh/syscall_arch.h b/libdesock/include/arch/sh/syscall_arch.h new file mode 100644 index 0000000..628d8d3 --- /dev/null +++ b/libdesock/include/arch/sh/syscall_arch.h @@ -0,0 +1,93 @@ +#define __SYSCALL_LL_E(x) \ +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \ +((union { long long ll; long l[2]; }){ .ll = x }).l[1] +#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x)) +#define __SYSCALL_LL_PRW(x) 0, __SYSCALL_LL_E((x)) + +/* The extra OR instructions are to work around a hardware bug: + * http://documentation.renesas.com/doc/products/mpumcu/tu/tnsh7456ae.pdf + */ +#define __asm_syscall(trapno, ...) do { \ + __asm__ __volatile__ ( \ + "trapa #31\n" \ + "or r0, r0\n" \ + "or r0, r0\n" \ + "or r0, r0\n" \ + "or r0, r0\n" \ + "or r0, r0\n" \ + : "=r"(r0) : __VA_ARGS__ : "memory"); \ + return r0; \ + } while (0) + +static inline long __syscall0(long n) +{ + register long r3 __asm__("r3") = n; + register long r0 __asm__("r0"); + __asm_syscall(16, "r"(r3)); +} + +static inline long __syscall1(long n, long a) +{ + register long r3 __asm__("r3") = n; + register long r4 __asm__("r4") = a; + register long r0 __asm__("r0"); + __asm_syscall(17, "r"(r3), "r"(r4)); +} + +static inline long __syscall2(long n, long a, long b) +{ + register long r3 __asm__("r3") = n; + register long r4 __asm__("r4") = a; + register long r5 __asm__("r5") = b; + register long r0 __asm__("r0"); + __asm_syscall(18, "r"(r3), "r"(r4), "r"(r5)); +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long r3 __asm__("r3") = n; + register long r4 __asm__("r4") = a; + register long r5 __asm__("r5") = b; + register long r6 __asm__("r6") = c; + register long r0 __asm__("r0"); + __asm_syscall(19, "r"(r3), "r"(r4), "r"(r5), "r"(r6)); +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long r3 __asm__("r3") = n; + register long r4 __asm__("r4") = a; + register long r5 __asm__("r5") = b; + register long r6 __asm__("r6") = c; + register long r7 __asm__("r7") = d; + register long r0 __asm__("r0"); + __asm_syscall(20, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7)); +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long r3 __asm__("r3") = n; + register long r4 __asm__("r4") = a; + register long r5 __asm__("r5") = b; + register long r6 __asm__("r6") = c; + register long r7 __asm__("r7") = d; + register long r0 __asm__("r0") = e; + __asm_syscall(21, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0)); +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long r3 __asm__("r3") = n; + register long r4 __asm__("r4") = a; + register long r5 __asm__("r5") = b; + register long r6 __asm__("r6") = c; + register long r7 __asm__("r7") = d; + register long r0 __asm__("r0") = e; + register long r1 __asm__("r1") = f; + __asm_syscall(22, "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "0"(r0), "r"(r1)); +} + +#define SYSCALL_IPC_BROKEN_MODE + +#define SIOCGSTAMP_OLD (2U<<30 | 's'<<8 | 100 | 8<<16) +#define SIOCGSTAMPNS_OLD (2U<<30 | 's'<<8 | 101 | 8<<16) diff --git a/libdesock/include/arch/x32/syscall_arch.h b/libdesock/include/arch/x32/syscall_arch.h new file mode 100644 index 0000000..e0111cc --- /dev/null +++ b/libdesock/include/arch/x32/syscall_arch.h @@ -0,0 +1,93 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __scc(X) sizeof(1?(X):0ULL) < 8 ? (unsigned long) (X) : (long long) (X) +typedef long long syscall_arg_t; + +static __inline long __syscall0(long long n) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall1(long long n, long long a1) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall2(long long n, long long a1, long long a2) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) + : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall3(long long n, long long a1, long long a2, long long a3) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall4(long long n, long long a1, long long a2, long long a3, + long long a4_) +{ + unsigned long ret; + register long long a4 __asm__("r10") = a4_; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(a4): "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall5(long long n, long long a1, long long a2, long long a3, + long long a4_, long long a5_) +{ + unsigned long ret; + register long long a4 __asm__("r10") = a4_; + register long long a5 __asm__("r8") = a5_; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(a4), "r"(a5) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall6(long long n, long long a1, long long a2, long long a3, + long long a4_, long long a5_, long long a6_) +{ + unsigned long ret; + register long long a4 __asm__("r10") = a4_; + register long long a5 __asm__("r8") = a5_; + register long long a6 __asm__("r9") = a6_; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(a4), "r"(a5), "r"(a6) : "rcx", "r11", "memory"); + return ret; +} + +#undef SYS_futimesat + +#define SYS_clock_gettime64 SYS_clock_gettime +#define SYS_clock_settime64 SYS_clock_settime +#define SYS_clock_adjtime64 SYS_clock_adjtime +#define SYS_clock_nanosleep_time64 SYS_clock_nanosleep +#define SYS_timer_gettime64 SYS_timer_gettime +#define SYS_timer_settime64 SYS_timer_settime +#define SYS_timerfd_gettime64 SYS_timerfd_gettime +#define SYS_timerfd_settime64 SYS_timerfd_settime +#define SYS_utimensat_time64 SYS_utimensat +#define SYS_pselect6_time64 SYS_pselect6 +#define SYS_ppoll_time64 SYS_ppoll +#define SYS_recvmmsg_time64 SYS_recvmmsg +#define SYS_mq_timedsend_time64 SYS_mq_timedsend +#define SYS_mq_timedreceive_time64 SYS_mq_timedreceive +#define SYS_semtimedop_time64 SYS_semtimedop +#define SYS_rt_sigtimedwait_time64 SYS_rt_sigtimedwait +#define SYS_futex_time64 SYS_futex +#define SYS_sched_rr_get_interval_time64 SYS_sched_rr_get_interval +#define SYS_getrusage_time64 SYS_getrusage +#define SYS_wait4_time64 SYS_wait4 + +#define IPC_64 0 diff --git a/libdesock/include/arch/x86_64/syscall_arch.h b/libdesock/include/arch/x86_64/syscall_arch.h new file mode 100644 index 0000000..92d5c17 --- /dev/null +++ b/libdesock/include/arch/x86_64/syscall_arch.h @@ -0,0 +1,70 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +static __inline long __syscall0(long n) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall1(long n, long a1) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall2(long n, long a1, long a2) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) + : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall3(long n, long a1, long a2, long a3) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10): "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + register long r9 __asm__("r9") = a6; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); + return ret; +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" +#define VDSO_GETCPU_SYM "__vdso_getcpu" +#define VDSO_GETCPU_VER "LINUX_2.6" + +#define IPC_64 0 diff --git a/libdesock/include/desock.h b/libdesock/include/desock.h new file mode 100644 index 0000000..3273161 --- /dev/null +++ b/libdesock/include/desock.h @@ -0,0 +1,80 @@ +#ifndef DESOCK_H +#define DESOCK_H + +#include +#include +#include +#include +#include +#include +#include + +// Check that we are desocketing at least one of client or server +#ifndef DESOCK_BIND +#ifndef DESOCK_CONNECT +#error "At least one of DESOCK_CONNECT or DESOCK_BIND must be specified" +#endif +#endif + +/* +If conns >= MAX_CONNS accept() will block +*/ +#ifndef MAX_CONNS +#define MAX_CONNS 1 +#endif + +extern sem_t sem; + +#ifdef DEBUG +void _debug (char*, ...); +#define DEBUG_LOG(...) _debug(__VA_ARGS__); +#else +#define DEBUG_LOG(...) +#endif + +void fill_sockaddr (int, struct sockaddr*, socklen_t*); +void _error (char*, ...); + +struct fd_entry { + /* information passed to socket() */ + int domain; + + /* flag whether to desock this fd */ + int desock; + + /* flag whether this is the server socket */ + int listening; + + /* epoll stuff */ + int epfd; + struct epoll_event ep_event; +}; + +#ifndef FD_TABLE_SIZE +#define FD_TABLE_SIZE 1024 +#endif + +extern struct fd_entry fd_table[FD_TABLE_SIZE]; +extern int accept_block; +extern int max_fd; +extern const struct sockaddr_in stub_sockaddr_in; +extern const struct sockaddr_in6 stub_sockaddr_in6; +extern const struct sockaddr_un stub_sockaddr_un; + +#define VALID_FD(x) (0 <= (x) && (x) < FD_TABLE_SIZE) + +#define DESOCK_FD(x) (fd_table[(x)].domain == AF_INET || fd_table[(x)].domain == AF_INET6) + +#ifdef DEBUG +void clear_fd_table_entry(int); +#else +inline void clear_fd_table_entry (int idx) { + fd_table[idx].epfd = -1; + fd_table[idx].desock = 0; + fd_table[idx].listening = 0; +} +#endif + +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +#endif /* DESOCK_H */ diff --git a/libdesock/include/musl-features.h b/libdesock/include/musl-features.h new file mode 100644 index 0000000..f0b632c --- /dev/null +++ b/libdesock/include/musl-features.h @@ -0,0 +1,11 @@ +#ifndef FEATURES_H +#define FEATURES_H + +#define weak __attribute__((__weak__)) +#define hidden __attribute__((__visibility__("hidden"))) +#define weak_alias(old, new) \ + extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) +#define strong_alias(old, new) \ + extern __typeof(old) new __attribute__((__alias__(#old))) + +#endif diff --git a/libdesock/include/peekbuffer.h b/libdesock/include/peekbuffer.h new file mode 100644 index 0000000..e859398 --- /dev/null +++ b/libdesock/include/peekbuffer.h @@ -0,0 +1,23 @@ +#ifndef PEEKBUFFER_H +#define PEEKBUFFER_H + +#define STATIC_BUFFER_SIZE 8192 + +typedef struct { + char* buffer; + size_t start; + size_t size; + size_t capacity; +} peekbuffer_t; + +extern peekbuffer_t peekbuffer; + +int peekbuffer_read (size_t len); +size_t peekbuffer_cp (char* dest, size_t len, size_t offset); +size_t peekbuffer_mv (char* dest, size_t len); + +inline static size_t peekbuffer_size (void) { + return peekbuffer.size; +} + +#endif diff --git a/libdesock/include/syscall.h b/libdesock/include/syscall.h new file mode 100644 index 0000000..4547db8 --- /dev/null +++ b/libdesock/include/syscall.h @@ -0,0 +1,399 @@ +#ifndef _INTERNAL_SYSCALL_H +#define _INTERNAL_SYSCALL_H + +#include +#include + +#include +#include + +#ifndef SYSCALL_RLIM_INFINITY +#define SYSCALL_RLIM_INFINITY (~0ULL) +#endif + +#ifndef SYSCALL_MMAP2_UNIT +#define SYSCALL_MMAP2_UNIT 4096ULL +#endif + +#ifndef __SYSCALL_LL_PRW +#define __SYSCALL_LL_PRW(x) __SYSCALL_LL_O(x) +#endif + +#ifndef __scc +#define __scc(X) ((long) (X)) +typedef long syscall_arg_t; +#endif + +hidden long __syscall_ret(unsigned long), + __syscall_cp(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, + syscall_arg_t, syscall_arg_t, syscall_arg_t); + +#define __syscall1(n,a) __syscall1(n,__scc(a)) +#define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b)) +#define __syscall3(n,a,b,c) __syscall3(n,__scc(a),__scc(b),__scc(c)) +#define __syscall4(n,a,b,c,d) __syscall4(n,__scc(a),__scc(b),__scc(c),__scc(d)) +#define __syscall5(n,a,b,c,d,e) __syscall5(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) +#define __syscall6(n,a,b,c,d,e,f) __syscall6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) +#define __syscall7(n,a,b,c,d,e,f,g) __syscall7(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) + +#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n +#define __SYSCALL_NARGS(...) __SYSCALL_NARGS_X(__VA_ARGS__,7,6,5,4,3,2,1,0,) +#define __SYSCALL_CONCAT_X(a,b) a##b +#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) +#define __SYSCALL_DISP(b,...) __SYSCALL_CONCAT(b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) + +#define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__) +#define syscall(...) __syscall_ret(__syscall(__VA_ARGS__)) + +#define socketcall(nm,a,b,c,d,e,f) __syscall_ret(__socketcall(nm,a,b,c,d,e,f)) +#define socketcall_cp(nm,a,b,c,d,e,f) __syscall_ret(__socketcall_cp(nm,a,b,c,d,e,f)) + +#define __syscall_cp0(n) (__syscall_cp)(n,0,0,0,0,0,0) +#define __syscall_cp1(n,a) (__syscall_cp)(n,__scc(a),0,0,0,0,0) +#define __syscall_cp2(n,a,b) (__syscall_cp)(n,__scc(a),__scc(b),0,0,0,0) +#define __syscall_cp3(n,a,b,c) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),0,0,0) +#define __syscall_cp4(n,a,b,c,d) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),0,0) +#define __syscall_cp5(n,a,b,c,d,e) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),0) +#define __syscall_cp6(n,a,b,c,d,e,f) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) + +#define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) +#define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) + +static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, long c, long d, long e, long f) +{ + long r; + if (cp) r = __syscall_cp(sys, a, b, c, d, e, f); + else r = __syscall(sys, a, b, c, d, e, f); + if (r != -ENOSYS) return r; +#ifdef SYS_socketcall + if (cp) r = __syscall_cp(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); + else r = __syscall(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); +#endif + return r; +} +#define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \ + (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) +#define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \ + (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) + +/* fixup legacy 16-bit junk */ + +#ifdef SYS_getuid32 +#undef SYS_lchown +#undef SYS_getuid +#undef SYS_getgid +#undef SYS_geteuid +#undef SYS_getegid +#undef SYS_setreuid +#undef SYS_setregid +#undef SYS_getgroups +#undef SYS_setgroups +#undef SYS_fchown +#undef SYS_setresuid +#undef SYS_getresuid +#undef SYS_setresgid +#undef SYS_getresgid +#undef SYS_chown +#undef SYS_setuid +#undef SYS_setgid +#undef SYS_setfsuid +#undef SYS_setfsgid +#define SYS_lchown SYS_lchown32 +#define SYS_getuid SYS_getuid32 +#define SYS_getgid SYS_getgid32 +#define SYS_geteuid SYS_geteuid32 +#define SYS_getegid SYS_getegid32 +#define SYS_setreuid SYS_setreuid32 +#define SYS_setregid SYS_setregid32 +#define SYS_getgroups SYS_getgroups32 +#define SYS_setgroups SYS_setgroups32 +#define SYS_fchown SYS_fchown32 +#define SYS_setresuid SYS_setresuid32 +#define SYS_getresuid SYS_getresuid32 +#define SYS_setresgid SYS_setresgid32 +#define SYS_getresgid SYS_getresgid32 +#define SYS_chown SYS_chown32 +#define SYS_setuid SYS_setuid32 +#define SYS_setgid SYS_setgid32 +#define SYS_setfsuid SYS_setfsuid32 +#define SYS_setfsgid SYS_setfsgid32 +#endif + + +/* fixup legacy 32-bit-vs-lfs64 junk */ + +#ifdef SYS_fcntl64 +#undef SYS_fcntl +#define SYS_fcntl SYS_fcntl64 +#endif + +#ifdef SYS_getdents64 +#undef SYS_getdents +#define SYS_getdents SYS_getdents64 +#endif + +#ifdef SYS_ftruncate64 +#undef SYS_ftruncate +#undef SYS_truncate +#define SYS_ftruncate SYS_ftruncate64 +#define SYS_truncate SYS_truncate64 +#endif + +#ifdef SYS_stat64 +#undef SYS_stat +#define SYS_stat SYS_stat64 +#endif + +#ifdef SYS_fstat64 +#undef SYS_fstat +#define SYS_fstat SYS_fstat64 +#endif + +#ifdef SYS_lstat64 +#undef SYS_lstat +#define SYS_lstat SYS_lstat64 +#endif + +#ifdef SYS_statfs64 +#undef SYS_statfs +#define SYS_statfs SYS_statfs64 +#endif + +#ifdef SYS_fstatfs64 +#undef SYS_fstatfs +#define SYS_fstatfs SYS_fstatfs64 +#endif + +#if defined(SYS_newfstatat) +#undef SYS_fstatat +#define SYS_fstatat SYS_newfstatat +#elif defined(SYS_fstatat64) +#undef SYS_fstatat +#define SYS_fstatat SYS_fstatat64 +#endif + +#ifdef SYS_ugetrlimit +#undef SYS_getrlimit +#define SYS_getrlimit SYS_ugetrlimit +#endif + +#ifdef SYS__newselect +#undef SYS_select +#define SYS_select SYS__newselect +#endif + +#ifdef SYS_pread64 +#undef SYS_pread +#undef SYS_pwrite +#define SYS_pread SYS_pread64 +#define SYS_pwrite SYS_pwrite64 +#endif + +#ifdef SYS_fadvise64_64 +#undef SYS_fadvise +#define SYS_fadvise SYS_fadvise64_64 +#elif defined(SYS_fadvise64) +#undef SYS_fadvise +#define SYS_fadvise SYS_fadvise64 +#endif + +#ifdef SYS_sendfile64 +#undef SYS_sendfile +#define SYS_sendfile SYS_sendfile64 +#endif + +#ifndef SYS_timer_settime +#define SYS_timer_settime SYS_timer_settime32 +#endif + +#ifndef SYS_timer_gettime +#define SYS_timer_gettime SYS_timer_gettime32 +#endif + +#ifndef SYS_timerfd_settime +#define SYS_timerfd_settime SYS_timerfd_settime32 +#endif + +#ifndef SYS_timerfd_gettime +#define SYS_timerfd_gettime SYS_timerfd_gettime32 +#endif + +#ifndef SYS_clock_settime +#define SYS_clock_settime SYS_clock_settime32 +#endif + +#ifndef SYS_clock_gettime +#define SYS_clock_gettime SYS_clock_gettime32 +#endif + +#ifndef SYS_clock_getres +#define SYS_clock_getres SYS_clock_getres_time32 +#endif + +#ifndef SYS_clock_nanosleep +#define SYS_clock_nanosleep SYS_clock_nanosleep_time32 +#endif + +#ifndef SYS_gettimeofday +#define SYS_gettimeofday SYS_gettimeofday_time32 +#endif + +#ifndef SYS_settimeofday +#define SYS_settimeofday SYS_settimeofday_time32 +#endif + +/* Ensure that the plain syscall names are defined even for "time64-only" + * archs. These facilitate callers passing null time arguments, and make + * tests for establishing which to use/fallback-to more consistent when + * they do need to be called with time arguments. */ + +#ifndef SYS_clock_gettime +#define SYS_clock_gettime SYS_clock_gettime64 +#endif + +#ifndef SYS_clock_settime +#define SYS_clock_settime SYS_clock_settime64 +#endif + +#ifndef SYS_clock_adjtime +#define SYS_clock_adjtime SYS_clock_adjtime64 +#endif + +#ifndef SYS_clock_getres +#define SYS_clock_getres SYS_clock_getres_time64 +#endif + +#ifndef SYS_clock_nanosleep +#define SYS_clock_nanosleep SYS_clock_nanosleep_time64 +#endif + +#ifndef SYS_timer_gettime +#define SYS_timer_gettime SYS_timer_gettime64 +#endif + +#ifndef SYS_timer_settime +#define SYS_timer_settime SYS_timer_settime64 +#endif + +#ifndef SYS_timerfd_gettime +#define SYS_timerfd_gettime SYS_timerfd_gettime64 +#endif + +#ifndef SYS_timerfd_settime +#define SYS_timerfd_settime SYS_timerfd_settime64 +#endif + +#ifndef SYS_utimensat +#define SYS_utimensat SYS_utimensat_time64 +#endif + +#ifndef SYS_pselect6 +#define SYS_pselect6 SYS_pselect6_time64 +#endif + +#ifndef SYS_ppoll +#define SYS_ppoll SYS_ppoll_time64 +#endif + +#ifndef SYS_recvmmsg +#define SYS_recvmmsg SYS_recvmmsg_time64 +#endif + +#ifndef SYS_mq_timedsend +#define SYS_mq_timedsend SYS_mq_timedsend_time64 +#endif + +#ifndef SYS_mq_timedreceive +#define SYS_mq_timedreceive SYS_mq_timedreceive_time64 +#endif + +/* SYS_semtimedop omitted because SYS_ipc may provide it */ + +#ifndef SYS_rt_sigtimedwait +#define SYS_rt_sigtimedwait SYS_rt_sigtimedwait_time64 +#endif + +#ifndef SYS_futex +#define SYS_futex SYS_futex_time64 +#endif + +#ifndef SYS_sched_rr_get_interval +#define SYS_sched_rr_get_interval SYS_sched_rr_get_interval_time64 +#endif + + + + +/* socketcall calls */ + +#define __SC_socket 1 +#define __SC_bind 2 +#define __SC_connect 3 +#define __SC_listen 4 +#define __SC_accept 5 +#define __SC_getsockname 6 +#define __SC_getpeername 7 +#define __SC_socketpair 8 +#define __SC_send 9 +#define __SC_recv 10 +#define __SC_sendto 11 +#define __SC_recvfrom 12 +#define __SC_shutdown 13 +#define __SC_setsockopt 14 +#define __SC_getsockopt 15 +#define __SC_sendmsg 16 +#define __SC_recvmsg 17 +#define __SC_accept4 18 +#define __SC_recvmmsg 19 +#define __SC_sendmmsg 20 + +/* This is valid only because all socket syscalls are made via + * socketcall, which always fills unused argument slots with zeros. */ +#ifndef SYS_accept +#define SYS_accept SYS_accept4 +#endif + +#ifndef SO_RCVTIMEO_OLD +#define SO_RCVTIMEO_OLD 20 +#endif +#ifndef SO_SNDTIMEO_OLD +#define SO_SNDTIMEO_OLD 21 +#endif + +#define SO_TIMESTAMP_OLD 29 +#define SO_TIMESTAMPNS_OLD 35 +#define SO_TIMESTAMPING_OLD 37 +#define SCM_TIMESTAMP_OLD SO_TIMESTAMP_OLD +#define SCM_TIMESTAMPNS_OLD SO_TIMESTAMPNS_OLD +#define SCM_TIMESTAMPING_OLD SO_TIMESTAMPING_OLD + +#ifndef SIOCGSTAMP_OLD +#define SIOCGSTAMP_OLD 0x8906 +#endif +#ifndef SIOCGSTAMPNS_OLD +#define SIOCGSTAMPNS_OLD 0x8907 +#endif + +#ifdef SYS_open +#define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE) +#define __sys_open3(x,pn,fl,mo) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, mo) +#define __sys_open_cp2(x,pn,fl) __syscall_cp2(SYS_open, pn, (fl)|O_LARGEFILE) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp3(SYS_open, pn, (fl)|O_LARGEFILE, mo) +#else +#define __sys_open2(x,pn,fl) __syscall3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) +#define __sys_open3(x,pn,fl,mo) __syscall4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) +#define __sys_open_cp2(x,pn,fl) __syscall_cp3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) +#endif + +#define __sys_open(...) __SYSCALL_DISP(__sys_open,,__VA_ARGS__) +#define sys_open(...) __syscall_ret(__sys_open(__VA_ARGS__)) + +#define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) +#define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) + +hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned); + +hidden void *__vdsosym(const char *, const char *); + +#endif diff --git a/libdesock/src/accept.c b/libdesock/src/accept.c new file mode 100644 index 0000000..f648bfa --- /dev/null +++ b/libdesock/src/accept.c @@ -0,0 +1,53 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int internal_accept (int fd, struct sockaddr* restrict addr, socklen_t * restrict len, int flag) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::internal_accept(%d, %p, %p, %d)", gettid (), fd, addr, len, flag); + + if (accept_block) { + sem_wait (&sem); + } else { + accept_block = 1; + } + + int new_fd = syscall (SYS_dup, fd); + + if (new_fd == -1 || !VALID_FD (new_fd)) { + DEBUG_LOG (" = -1\n"); + return -1; + } + + clear_fd_table_entry (new_fd); + fd_table[new_fd].domain = fd_table[fd].domain; + fd_table[new_fd].desock = 1; + + fill_sockaddr (fd, addr, len); + + if (new_fd + 1 > max_fd) { + max_fd = new_fd + 1; + } + + DEBUG_LOG (" = %d\n", new_fd); + return new_fd; + } else { + return socketcall_cp (accept4, fd, addr, len, flag, 0, 0); + } +} + +int accept (int fd, struct sockaddr* restrict addr, socklen_t * restrict len) { + return internal_accept (fd, addr, len, 0); +} + +int accept4 (int fd, struct sockaddr* restrict addr, socklen_t * restrict len, int flg) { + return internal_accept (fd, addr, len, flg); +} diff --git a/libdesock/src/bind.c b/libdesock/src/bind.c new file mode 100644 index 0000000..1314962 --- /dev/null +++ b/libdesock/src/bind.c @@ -0,0 +1,26 @@ +#ifdef DESOCK_BIND +#include + +#define _GNU_SOURCE +#include + +#include +#include + +int bind (int fd, const struct sockaddr* addr, socklen_t len) { + if (VALID_FD (fd) && DESOCK_FD (fd)) { + DEBUG_LOG ("[%d] desock::bind(%d, %p, %d) = 0\n", gettid (), fd, addr, len); + fd_table[fd].desock = 1; + return 0; + } else { + return socketcall (bind, fd, addr, len, 0, 0, 0); + } +} + +#ifdef DEBUG +int _debug_real_bind (int fd, const struct sockaddr* addr, socklen_t len) { + return socketcall (bind, fd, addr, len, 0, 0, 0); +} +#endif + +#endif diff --git a/libdesock/src/close.c b/libdesock/src/close.c new file mode 100644 index 0000000..5a51eac --- /dev/null +++ b/libdesock/src/close.c @@ -0,0 +1,51 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include +#include + +int close (int fd) { + int r = 0; + + if (VALID_FD (fd)) { +#ifdef DEBUG + if (fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::close(%d)", gettid (), fd); + } +#endif + + if (fd_table[fd].desock && !fd_table[fd].listening) { + int sem_value = 0; + + if (sem_getvalue (&sem, &sem_value) == -1) { +#ifdef DEBUG + if (fd_table[fd].desock) { + DEBUG_LOG (" = -1\n"); + } +#endif + return -1; + } + + if (sem_value < MAX_CONNS) { + sem_post (&sem); + } + } +#ifdef DEBUG + if (fd_table[fd].desock) { + DEBUG_LOG (" = 0\n"); + } +#endif + + clear_fd_table_entry (fd); + } + + if (fd > 1) { + r = __syscall_cp (SYS_close, fd); + if (r == -EINTR) + r = 0; + } + + return __syscall_ret (r); +} diff --git a/libdesock/src/connect.c b/libdesock/src/connect.c new file mode 100644 index 0000000..9a64e70 --- /dev/null +++ b/libdesock/src/connect.c @@ -0,0 +1,18 @@ +#ifdef DESOCK_CONNECT +#define _GNU_SOURCE +#include +#include + +#include +#include + +int connect (int fd, const struct sockaddr* addr, socklen_t len) { + if (VALID_FD (fd) && DESOCK_FD (fd)) { + DEBUG_LOG ("[%d] desock::connect(%d, %p, %d)\n", gettid (), fd, addr, len); + fd_table[fd].desock = 1; + return 0; + } else { + return socketcall_cp (connect, fd, addr, len, 0, 0, 0); + } +} +#endif diff --git a/libdesock/src/desock.c b/libdesock/src/desock.c new file mode 100644 index 0000000..2fb35d4 --- /dev/null +++ b/libdesock/src/desock.c @@ -0,0 +1,134 @@ +#define __USE_GNU +#define GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +const struct sockaddr_in stub_sockaddr_in = { + .sin_family = AF_INET, + .sin_port = 53764, + .sin_addr.s_addr = 0x100007f +}; + +const struct sockaddr_in6 stub_sockaddr_in6 = { + .sin6_family = AF_INET6, + .sin6_port = 53764, + .sin6_flowinfo = 0, + .sin6_addr.s6_addr = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + .sin6_scope_id = 0 +}; + +void fill_sockaddr (int fd, struct sockaddr* addr, socklen_t * addr_len) { + if (addr && addr_len) { + switch (fd_table[fd].domain) { + case AF_INET:{ + struct sockaddr_in* ptr = (struct sockaddr_in *) addr; + ptr->sin_family = AF_INET; + if (*addr_len >= sizeof (struct sockaddr_in)) { + ptr->sin_port = stub_sockaddr_in.sin_port; + ptr->sin_addr = stub_sockaddr_in.sin_addr; + *addr_len = sizeof (struct sockaddr_in); + } + break; + } + + case AF_INET6:{ + *addr_len = MIN (*addr_len, sizeof (stub_sockaddr_in6)); + memcpy (addr, &stub_sockaddr_in6, *addr_len); + break; + } + + default:{ + _error ("desock::fill_sockaddr(): Invalid domain %d\n", fd_table[fd].domain); + } + } + } +} + +#ifdef DEBUG +void _debug (char* fmt_string, ...) { + va_list args; + va_start (args, fmt_string); + vfprintf (stderr, fmt_string, args); + va_end (args); + fflush (stderr); +} +#endif + +void _error (char* fmt_string, ...) { + va_list args; + va_start (args, fmt_string); + vfprintf (stderr, fmt_string, args); + va_end (args); + abort (); +} + +int max_fd = 0; +int accept_block = 1; +struct fd_entry fd_table[FD_TABLE_SIZE]; +sem_t sem; + +__attribute__ ((constructor)) +void desock_init (void) { + if (sem_init (&sem, 1, MAX_CONNS) == -1) { + _error ("desock::error: sem_init failed\n"); + } +} + +const char elf_interpreter[] __attribute__ ((section (".interp"))) = INTERPRETER; + +void desock_main (void) { + printf ("libdesock.so: A fast desocketing library built for fuzzing\n" "\n" "This library can desock\n" " servers = " +#ifdef DESOCK_BIND + "yes" +#else + "no" +#endif + "\n" " clients = " +#ifdef DESOCK_CONNECT + "yes" +#else + "no" +#endif + "\n\n" "Compilation options:\n" " - DEBUG = " +#ifdef DEBUG + "yes" +#else + "no" +#endif + "\n" " - MAX_CONNS = %d\n" " - FD_TABLE_SIZE = %d\n" " - ARCH = %s\n" "\n" "Use this with LD_PRELOAD=libdesock.so on a network application\n" "or with AFL_PRELOAD=libdesock.so when fuzzing with AFL.\n", MAX_CONNS, FD_TABLE_SIZE, DESOCKARCH); + + exit (0); +} + +#ifdef DEBUG +void clear_fd_table_entry (int idx) { + fd_table[idx].epfd = -1; + fd_table[idx].desock = 0; + fd_table[idx].listening = 0; +} + +int _debug_instant_fd (int listening) { + int fd = syscall (SYS_dup, 0); + + if (fd < 0 || !VALID_FD (fd)) { + return -1; + } + + fd_table[fd].desock = 1; + fd_table[fd].listening = (listening != 0); + return fd; +} + +void _debug_get_fd_table_entry (int idx, struct fd_entry* dst) { + memcpy (dst, &fd_table[idx], sizeof (struct fd_entry)); +} +#endif diff --git a/libdesock/src/dup.c b/libdesock/src/dup.c new file mode 100644 index 0000000..456a184 --- /dev/null +++ b/libdesock/src/dup.c @@ -0,0 +1,95 @@ +#define _GNU_SOURCE +#include +#include + +#include +#include + +int dup (int fd) { + int ret = syscall (SYS_dup, fd); + + if (ret > -1 && VALID_FD (ret) && VALID_FD (fd)) { + DEBUG_LOG ("[%d] desock::dup(%d)", gettid (), fd); + + fd_table[ret].domain = fd_table[fd].domain; + fd_table[ret].desock = fd_table[fd].desock; + fd_table[ret].listening = fd_table[fd].listening; + fd_table[ret].epfd = fd_table[fd].epfd; + fd_table[ret].ep_event.events = fd_table[fd].ep_event.events; + fd_table[ret].ep_event.data = fd_table[fd].ep_event.data; + + if (ret + 1 > max_fd) { + max_fd = ret + 1; + } + + DEBUG_LOG (" = %d\n", ret); + } + + return ret; +} + +int dup2 (int old, int new) { + int r = new; + + /* Don't allow overwriting of stdin/stdout */ + if (r > 1) { + while ((r = __syscall (SYS_dup2, old, new)) == -EBUSY) ; + } + + if (r > -1 && VALID_FD (r) && VALID_FD (old)) { + DEBUG_LOG ("[%d] desock::dup2(%d, %d)", gettid (), old, new); + + fd_table[r].domain = fd_table[old].domain; + fd_table[r].desock = fd_table[old].desock; + fd_table[r].listening = fd_table[old].listening; + fd_table[r].epfd = fd_table[old].epfd; + fd_table[r].ep_event.events = fd_table[old].ep_event.events; + fd_table[r].ep_event.data = fd_table[old].ep_event.data; + + if (r + 1 > max_fd) { + max_fd = r + 1; + } + + DEBUG_LOG (" = %d\n", r); + } + + return __syscall_ret (r); +} + +int dup3 (int old, int new, int flags) { + int r = new; + + /* Don't allow overwriting of stdin/stdout */ + if (r > 1) { + while ((r = __syscall (SYS_dup3, old, new, flags)) == -EBUSY) ; + } + + if (r > -1 && VALID_FD (r) && VALID_FD (old)) { + DEBUG_LOG ("[%d] desock::dup3(%d, %d, %d)", gettid (), old, new, flags); + + fd_table[r].domain = fd_table[old].domain; + fd_table[r].desock = fd_table[old].desock; + fd_table[r].listening = fd_table[old].listening; + fd_table[r].epfd = fd_table[old].epfd; + fd_table[r].ep_event.events = fd_table[old].ep_event.events; + fd_table[r].ep_event.data = fd_table[old].ep_event.data; + + if (r + 1 > max_fd) { + max_fd = r + 1; + } + + DEBUG_LOG (" = %d\n", r); + } + + return __syscall_ret (r); +} + +#ifdef DEBUG + +int _debug_real_dup2 (int old, int new) { + int r; + while ((r = __syscall (SYS_dup2, old, new)) == -EBUSY) ; + return __syscall_ret (r); +} + +#endif diff --git a/libdesock/src/epoll.c b/libdesock/src/epoll.c new file mode 100644 index 0000000..d268aee --- /dev/null +++ b/libdesock/src/epoll.c @@ -0,0 +1,142 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef DEBUG +int epoll_create (int size) { + int r = __syscall_ret (__syscall (SYS_epoll_create1, 0)); + DEBUG_LOG ("[%d] desock::epoll_create(%d) = %d\n", gettid (), size, r); + return r; +} + +int epoll_create1 (int flags) { + int r = __syscall_ret (__syscall (SYS_epoll_create1, flags)); + DEBUG_LOG ("[%d] desock::epoll_create1(%d) = %d\n", gettid (), flags, r); + return r; +} +#endif + +int epoll_ctl (int fd, int op, int fd2, struct epoll_event* ev) { + if (VALID_FD (fd2)) { + DEBUG_LOG ("[%d] desock::epoll_ctl(%d, %d, %d, %p)", gettid (), fd, op, fd2, ev); + + if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD) { + fd_table[fd2].epfd = fd; + fd_table[fd2].ep_event.events = ev->events; + fd_table[fd2].ep_event.data = ev->data; + } else if (op == EPOLL_CTL_DEL) { + fd_table[fd2].epfd = -1; + } + + if (fd_table[fd2].desock) { + DEBUG_LOG (" = 0\n"); + return 0; + } + } + + int r = syscall (SYS_epoll_ctl, fd, op, fd2, ev); +#ifdef DEBUG + if (VALID_FD (fd2)) { + DEBUG_LOG (" = %d\n", r); + } +#endif + return r; +} + +static int internal_epoll_wait (int fd, struct epoll_event* ev, int cnt) { + int j = 0; + int server_sock = -1; + + accept_block = 0; + + for (int i = 0; i < max_fd && j < cnt; ++i) { + if (fd_table[i].desock && fd_table[i].epfd == fd) { + if (fd_table[i].listening) { + server_sock = i; + } else { + ev[j].events = fd_table[i].ep_event.events; + ev[j].events &= (EPOLLIN | EPOLLOUT); + ev[j].data = fd_table[i].ep_event.data; + ++j; + + if (fd_table[i].ep_event.events & EPOLLONESHOT) { + fd_table[i].epfd = -1; + } + } + } + } + + if (server_sock > -1 && j < cnt) { + if (sem_trywait (&sem) == -1) { + if (errno != EAGAIN) { + _error ("desock::internal_epoll_wait(): sem_trywait failed\n"); + } + + if (j > 0) { + return j; + } + + sem_wait (&sem); + } + + ev[j].events = fd_table[server_sock].ep_event.events; + ev[j].events &= EPOLLIN; + ev[j].data = fd_table[server_sock].ep_event.data; + ++j; + + if (fd_table[server_sock].ep_event.events & EPOLLONESHOT) { + fd_table[server_sock].epfd = -1; + } + } + + return j; +} + +int epoll_pwait (int fd, struct epoll_event* ev, int cnt, int to, const sigset_t * sigs) { + DEBUG_LOG ("[%d] desock::epoll_pwait(%d, %p, %d, %d, %p)", gettid (), fd, ev, cnt, to, sigs); + + int ret = internal_epoll_wait (fd, ev, cnt); + if (ret) { + DEBUG_LOG (" = %d\n", ret); + return ret; + } else { + ret = __syscall_ret (__syscall (SYS_epoll_pwait, fd, ev, cnt, to, sigs)); + DEBUG_LOG (" = %d\n", ret); + return ret; + } +} + +int epoll_wait (int fd, struct epoll_event* ev, int cnt, int to) { + DEBUG_LOG ("[%d] desock::epoll_wait(%d, %p, %d, %d)", gettid (), fd, ev, cnt, to); + + int ret = internal_epoll_wait (fd, ev, cnt); + if (ret) { + DEBUG_LOG (" = %d\n", ret); + return ret; + } else { + ret = __syscall_ret (__syscall (SYS_epoll_pwait, fd, ev, cnt, to, 0)); + DEBUG_LOG (" = %d\n", ret); + return ret; + } +} + +int epoll_pwait2 (int epfd, struct epoll_event* events, int maxevents, struct timespec* timeout, const sigset_t * sigmask) { + DEBUG_LOG ("[%d] desock::epoll_pwait2(%d, %p, %d, %p, %p)", gettid (), epfd, events, maxevents, timeout, sigmask); + + int ret = internal_epoll_wait (epfd, events, maxevents); + if (ret) { + DEBUG_LOG (" = %d\n", ret); + return ret; + } else { + errno = ENOSYS; + DEBUG_LOG (" = -1\n"); + return -1; + } +} diff --git a/libdesock/src/getpeername.c b/libdesock/src/getpeername.c new file mode 100644 index 0000000..31391fc --- /dev/null +++ b/libdesock/src/getpeername.c @@ -0,0 +1,18 @@ +#define _GNU_SOURCE +#define __USE_GNU +#include +#include +#include + +#include +#include + +int getpeername (int fd, struct sockaddr* restrict addr, socklen_t * restrict len) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::getpeername(%d, %p, %p) = 0\n", gettid (), fd, addr, len); + fill_sockaddr (fd, addr, len); + return 0; + } else { + return socketcall (getpeername, fd, addr, len, 0, 0, 0); + } +} diff --git a/libdesock/src/getsockname.c b/libdesock/src/getsockname.c new file mode 100644 index 0000000..27b659e --- /dev/null +++ b/libdesock/src/getsockname.c @@ -0,0 +1,17 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include +#include + +int getsockname (int fd, struct sockaddr* restrict addr, socklen_t * restrict len) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::getsockname(%d, %p, %p) = 0\n", gettid (), fd, addr, len); + fill_sockaddr (fd, addr, len); + return 0; + } else { + return socketcall (getsockname, fd, addr, len, 0, 0, 0); + } +} diff --git a/libdesock/src/listen.c b/libdesock/src/listen.c new file mode 100644 index 0000000..11138b3 --- /dev/null +++ b/libdesock/src/listen.c @@ -0,0 +1,16 @@ +#define _GNU_SOURCE +#include +#include + +#include +#include + +int listen (int fd, int backlog) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::listen(%d, %d) = 0\n", gettid (), fd, backlog); + fd_table[fd].listening = 1; + return 0; + } else { + return socketcall (listen, fd, backlog, 0, 0, 0, 0); + } +} diff --git a/libdesock/src/peekbuffer.c b/libdesock/src/peekbuffer.c new file mode 100644 index 0000000..1193077 --- /dev/null +++ b/libdesock/src/peekbuffer.c @@ -0,0 +1,109 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +#include +#include +#include + +char static_buffer[STATIC_BUFFER_SIZE]; + +peekbuffer_t peekbuffer = { + .buffer = static_buffer, + .start = 0, + .size = 0, + .capacity = STATIC_BUFFER_SIZE +}; + +/* +Round `size` up to the next power of 2. +*/ +static size_t next_pow_2 (size_t size) { + size--; + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size |= size >> 8; + size |= size >> 16; + size |= size >> 32; + size++; + return size; +} + +static int peekbuffer_grow (size_t new_size) { + if (peekbuffer.start + new_size > peekbuffer.capacity) { + if (new_size <= peekbuffer.capacity) { + memmove (peekbuffer.buffer, peekbuffer.buffer + peekbuffer.start, peekbuffer.size); + peekbuffer.start = 0; + } else { + size_t capacity = next_pow_2 (new_size); + char* buffer = malloc (capacity); + + if (NULL == buffer) { + errno = ENOMEM; + return -1; + } + + memcpy (buffer, peekbuffer.buffer + peekbuffer.start, peekbuffer.size); + + if (peekbuffer.buffer != static_buffer) { + free (peekbuffer.buffer); + } + + peekbuffer.start = 0; + peekbuffer.buffer = buffer; + peekbuffer.capacity = capacity; + } + } + + return 0; +} + +int peekbuffer_read (size_t len) { + DEBUG_LOG ("[%d] desock::peekbuffer_read(%lu)", gettid (), len); + + if (peekbuffer_grow (peekbuffer.size + len) == -1) { + DEBUG_LOG (" = -1\n"); + return -1; + } + + int ret = syscall_cp (SYS_read, 0, peekbuffer.buffer + peekbuffer.start + peekbuffer.size, len); + + if (ret > 0) { + peekbuffer.size += ret; + } + + DEBUG_LOG (" = %d\n", ret); + return ret; +} + +size_t peekbuffer_cp (char* dest, size_t len, size_t offset) { + DEBUG_LOG ("[%d] desock::peekbuffer_cp(%p, %lu, %lu)", gettid (), dest, len, offset); + + if (offset >= peekbuffer.size) { + DEBUG_LOG (" = 0\n"); + return 0; + } + + len = MIN (len, peekbuffer.size - offset); + memcpy (dest, peekbuffer.buffer + peekbuffer.start + offset, len); + DEBUG_LOG (" = %lu\n", len); + return len; +} + +size_t peekbuffer_mv (char* dest, size_t len) { + DEBUG_LOG ("[%d] desock::peekbuffer_mv(%p, %lu) -> ", gettid (), dest, len); + + size_t ret = peekbuffer_cp (dest, len, 0); + peekbuffer.size -= ret; + + if (peekbuffer.size == 0) { + peekbuffer.start = 0; + } else { + peekbuffer.start += ret; + } + + return ret; +} diff --git a/libdesock/src/poll.c b/libdesock/src/poll.c new file mode 100644 index 0000000..bf13349 --- /dev/null +++ b/libdesock/src/poll.c @@ -0,0 +1,70 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +#include +#include + +static int internal_poll (struct pollfd* fds, nfds_t n) { + DEBUG_LOG ("[%d] desock::internal_poll(%p, %d)", gettid (), fds, n); + + int ret = 0; + int server_sock = -1; + + accept_block = 0; + + for (nfds_t i = 0; i < n; ++i) { + if (VALID_FD (fds[i].fd) && fd_table[fds[i].fd].desock) { + fds[i].revents = fds[i].events & (POLLIN | POLLOUT); + + if (fd_table[fds[i].fd].listening) { + server_sock = i; + fds[i].revents &= (~POLLOUT); + } + + ++ret; + } else { + fds[i].revents = 0; + } + } + + if (server_sock > -1) { + if (sem_trywait (&sem) == -1) { + if (errno != EAGAIN) { + _error ("desock::internal_poll(): sem_trywait failed\n"); + } + + if (ret == 1) { + sem_wait (&sem); + } else { + fds[server_sock].revents = 0; + --ret; + } + } + } + + DEBUG_LOG (" = %d\n", ret); + return ret; +} + +int poll (struct pollfd* fds, nfds_t n, int timeout) { + int r = internal_poll (fds, n); + + if (r == 0) { + return syscall_cp (SYS_poll, fds, n, timeout); + } else { + return r; + } +} + +int ppoll (struct pollfd* fds, nfds_t n, const struct timespec* to, const sigset_t * mask) { + int r = internal_poll (fds, n); + + if (r == 0) { + return syscall_cp (SYS_ppoll, fds, n, to, mask); + } else { + return r; + } +} diff --git a/libdesock/src/read.c b/libdesock/src/read.c new file mode 100644 index 0000000..b5602e7 --- /dev/null +++ b/libdesock/src/read.c @@ -0,0 +1,226 @@ +#define _GNU_SOURCE +#define __USE_GNU +#include +#include +#include +#include +#include + +#include +#include +#include + +static long internal_readv (struct iovec* iov, int len, int* full, int peek, int offset) { + int read_in = 0; + + if (full) { + *full = 1; + } + + for (int i = 0; i < len; ++i) { + int r = 0; + + if (peek) { + r = peekbuffer_cp (iov[i].iov_base, iov[i].iov_len, offset); + offset += r; + } else { + if (peekbuffer_size () > 0) { + r = peekbuffer_mv (iov[i].iov_base, iov[i].iov_len); + } + + if (r < iov[i].iov_len) { + errno = 0; + r += syscall_cp (SYS_read, 0, (char *) iov[i].iov_base + r, iov[i].iov_len - r); + + if (errno) { + return -1; + } + } + } + + read_in += r; + + if (r < iov[i].iov_len) { + if (full) { + *full = 0; + } + + break; + } + } + + return read_in; +} + +ssize_t read (int fd, void* buf, size_t count) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::read(%d, %p, %lu)", gettid (), fd, buf, count); + + int offset = 0; + + if (peekbuffer_size () > 0) { + offset = peekbuffer_mv (buf, count); + } + + if (offset < count) { + errno = 0; + offset += syscall_cp (SYS_read, 0, (char *) buf + offset, count - offset); + + if (errno) { + DEBUG_LOG (" = -1\n"); + return -1; + } + } + + DEBUG_LOG (" = %d\n", offset); + return offset; + } else { + return syscall_cp (SYS_read, fd, buf, count); + } +} + +static ssize_t internal_recv (int fd, char* buf, size_t len, int flags) { + size_t buflen = peekbuffer_size (); + int offset = 0; + + if (flags & MSG_PEEK) { + long delta = len - buflen; + + if (delta > 0 && peekbuffer_read (delta) == -1) { + return -1; + } + + return peekbuffer_cp (buf, len, 0); + } else if (buflen > 0) { + offset = peekbuffer_mv (buf, len); + } + + if (offset < len) { + errno = 0; + offset += (syscall_cp (SYS_read, 0, buf + offset, len - offset)); + + if (errno) { + return -1; + } + } + + return offset; +} + +ssize_t recvfrom (int fd, void* buf, size_t len, int flags, struct sockaddr* restrict addr, socklen_t * alen) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::recvfrom(%d, %p, %lu, %d, %p, %p)", gettid (), fd, buf, len, flags, addr, alen); + + fill_sockaddr (fd, addr, alen); + + int r = internal_recv (fd, buf, len, flags); + DEBUG_LOG (" = %d\n", r); + return r; + } else { + return socketcall_cp (recvfrom, fd, buf, len, flags, addr, alen); + } +} + +ssize_t recv (int fd, void* buf, size_t len, int flags) { + if (VALID_FD (fd) && fd_table[fd].desock) { + int r = internal_recv (fd, buf, len, flags); + DEBUG_LOG ("[%d] desock::recv(%d, %p, %lu, %d) = %d\n", gettid (), fd, buf, len, flags, r); + return r; + } else { + return socketcall_cp (recvfrom, fd, buf, len, flags, NULL, NULL); + } +} + +ssize_t recvmsg (int fd, struct msghdr* msg, int flags) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::recvmsg(%d, %p, %d)", gettid (), fd, msg, flags); + + if (flags & MSG_PEEK) { + size_t total_length = 0; + + for (int i = 0; i < msg->msg_iovlen; ++i) { + total_length += msg->msg_iov[i].iov_len; + } + + long delta = total_length - peekbuffer_size (); + + if (delta > 0 && peekbuffer_read (delta) == -1) { + DEBUG_LOG (" = -1\n"); + return -1; + } + } + + msg->msg_flags = 0; + + fill_sockaddr (fd, msg->msg_name, &msg->msg_namelen); + + int r = internal_readv (msg->msg_iov, msg->msg_iovlen, NULL, flags & MSG_PEEK, 0); + DEBUG_LOG (" = %d\n", r); + return r; + } else { + return socketcall_cp (recvmsg, fd, msg, flags, 0, 0, 0); + } +} + +int recvmmsg (int fd, struct mmsghdr* msgvec, unsigned int vlen, int flags, struct timespec* timeout) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::recvmmsg(%d, %p, %d, %d, %p)", gettid (), fd, msgvec, vlen, flags, timeout); + + int i; + int offset = 0; + + if (flags & MSG_PEEK) { + size_t total_length = 0; + + for (i = 0; i < vlen; ++i) { + for (int j = 0; j < msgvec[i].msg_hdr.msg_iovlen; ++j) { + total_length += msgvec[i].msg_hdr.msg_iov[j].iov_len; + } + } + + long delta = total_length - peekbuffer_size (); + + if (delta > 0 && peekbuffer_read (delta) == -1) { + DEBUG_LOG (" = -1\n"); + return -1; + } + } + + for (i = 0; i < vlen; ++i) { + int full = 0; + + msgvec[i].msg_hdr.msg_flags = 0; + + fill_sockaddr (fd, msgvec[i].msg_hdr.msg_name, &msgvec[i].msg_hdr.msg_namelen); + + msgvec[i].msg_len = internal_readv (msgvec[i].msg_hdr.msg_iov, msgvec[i].msg_hdr.msg_iovlen, &full, flags & MSG_PEEK, offset); + + if (msgvec[i].msg_len == -1) { + DEBUG_LOG (" = -1\n"); + return -1; + } + + offset += msgvec[i].msg_len; + + if (!full) { + break; + } + } + + int r = (i == vlen || i == 0) ? i : (i + 1); + DEBUG_LOG (" = %d\n", r); + return r; + } else { + return syscall_cp (SYS_recvmmsg, fd, msgvec, vlen, flags, timeout); + } +} + +ssize_t readv (int fd, struct iovec* iov, int count) { + if (VALID_FD (fd) && fd_table[fd].desock) { + int r = internal_readv (iov, count, NULL, 0, 0); + DEBUG_LOG ("[%d] desock::readv(%d, %p, %d) = %d\n", gettid (), fd, iov, count, r); + return r; + } else { + return syscall_cp (SYS_readv, fd, iov, count); + } +} diff --git a/libdesock/src/select.c b/libdesock/src/select.c new file mode 100644 index 0000000..1e69f4c --- /dev/null +++ b/libdesock/src/select.c @@ -0,0 +1,117 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include +#include + +static int internal_select (int n, fd_set * rfds, fd_set * wfds, fd_set * efds) { + DEBUG_LOG ("[%d] desock::internal_select(%d, %p, %p, %p)", gettid (), n, rfds, wfds, efds); + + int ret = 0; + int server_sock = -1; + + accept_block = 0; + + for (int i = 0; i < n; ++i) { + if (rfds && FD_ISSET (i, rfds)) { + if (VALID_FD (i) && fd_table[i].desock) { + if (fd_table[i].listening) { + server_sock = i; + } + + ++ret; + } else { + FD_CLR (i, rfds); + } + } + + if (wfds && FD_ISSET (i, wfds)) { + if (VALID_FD (i) && fd_table[i].desock && !fd_table[i].listening) { + ++ret; + } else { + FD_CLR (i, wfds); + } + } + } + + if (efds) { + explicit_bzero (efds, sizeof (fd_set)); + } + + if (server_sock > -1) { + if (sem_trywait (&sem) == -1) { + if (errno != EAGAIN) { + _error ("desock::internal_select(): sem_trywait failed\n"); + } + + if (ret == 1) { + sem_wait (&sem); + } else { + FD_CLR (server_sock, rfds); + --ret; + } + } + } + + DEBUG_LOG (" = %d\n", ret); + return ret; +} + +#define IS32BIT(x) !((x)+0x80000000ULL>>32) +#define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63)) + +static int musl_select (int n, fd_set * restrict rfds, fd_set * restrict wfds, fd_set * restrict efds, struct timeval* restrict tv) { + time_t s = tv ? tv->tv_sec : 0; + suseconds_t us = tv ? tv->tv_usec : 0; + long ns; + const time_t max_time = (1ULL << 8 * sizeof (time_t) - 1) - 1; + + if (s < 0 || us < 0) + return __syscall_ret (-EINVAL); + if (us / 1000000 > max_time - s) { + s = max_time; + us = 999999; + ns = 999999999; + } else { + s += us / 1000000; + us %= 1000000; + ns = us * 1000; + } + +#ifdef SYS_pselect6_time64 + int r = -ENOSYS; + if (SYS_pselect6 == SYS_pselect6_time64 || !IS32BIT (s)) + r = __syscall_cp (SYS_pselect6_time64, n, rfds, wfds, efds, tv ? ((long long[]) { s, ns } + ) : 0, + ((syscall_arg_t[]) { 0, _NSIG / 8 })); + if (SYS_pselect6 == SYS_pselect6_time64 || r != -ENOSYS) + return __syscall_ret (r); +#endif +#ifdef SYS_select + return syscall_cp (SYS_select, n, rfds, wfds, efds, tv ? ((long[]) { s, us }) : 0); +#else + return syscall_cp (SYS_pselect6, n, rfds, wfds, efds, tv ? ((long[]) { s, ns }) : 0, ((syscall_arg_t[]) { 0, _NSIG / 8 })); +#endif +} + +int select (int n, fd_set * restrict rfds, fd_set * restrict wfds, fd_set * restrict efds, struct timeval* restrict tv) { + if (!rfds && !wfds && !efds) { + return musl_select (n, rfds, wfds, efds, tv); + } else { + return internal_select (n, rfds, wfds, efds); + } + +} + +int pselect (int n, fd_set * restrict rfds, fd_set * restrict wfds, fd_set * restrict efds, const struct timespec* restrict ts, const sigset_t * restrict mask) { + if (!rfds && !wfds && !efds) { + return musl_select (n, rfds, wfds, efds, ts); + } else { + return internal_select (n, rfds, wfds, efds); + } +} diff --git a/libdesock/src/sendfile.c b/libdesock/src/sendfile.c new file mode 100644 index 0000000..2b88eae --- /dev/null +++ b/libdesock/src/sendfile.c @@ -0,0 +1,18 @@ +#define _GNU_SOURCE +#include +#include + +#include +#include +#include + +ssize_t sendfile (int out_fd, int in_fd, off_t * ofs, size_t count) { + if (VALID_FD (out_fd) && fd_table[out_fd].desock) { + DEBUG_LOG ("[%d] desock::sendfile(%d, %d, %p, %lu) = %lu\n", gettid (), out_fd, in_fd, ofs, count, count); + return count; + } else { + return syscall (SYS_sendfile, out_fd, in_fd, ofs, count); + } +} + +strong_alias (sendfile, sendfile64); diff --git a/libdesock/src/shutdown.c b/libdesock/src/shutdown.c new file mode 100644 index 0000000..05bcd7d --- /dev/null +++ b/libdesock/src/shutdown.c @@ -0,0 +1,16 @@ +#define _GNU_SOURCE +#define __USE_GNU +#include +#include + +#include +#include + +int shutdown (int fd, int how) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::shutdown(%d, %d) = 0\n", gettid (), fd, how); + return 0; + } else { + return socketcall (shutdown, fd, how, 0, 0, 0, 0); + } +} diff --git a/libdesock/src/socket.c b/libdesock/src/socket.c new file mode 100644 index 0000000..9c4530f --- /dev/null +++ b/libdesock/src/socket.c @@ -0,0 +1,37 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include +#include + +int socket (int domain, int type, int protocol) { + DEBUG_LOG ("[%d] desock::socket(%d, %d, %d)", gettid (), domain, type, protocol); + + int s = __socketcall (socket, domain, type, protocol, 0, 0, 0); + if ((s == -EINVAL || s == -EPROTONOSUPPORT) + && (type & (SOCK_CLOEXEC | SOCK_NONBLOCK))) { + s = __socketcall (socket, domain, type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK), protocol, 0, 0, 0); + if (s < 0) + return __syscall_ret (s); + if (type & SOCK_CLOEXEC) + __syscall (SYS_fcntl, s, F_SETFD, FD_CLOEXEC); + if (type & SOCK_NONBLOCK) + __syscall (SYS_fcntl, s, F_SETFL, O_NONBLOCK); + } + + if (s > -1 && VALID_FD (s)) { + clear_fd_table_entry (s); + fd_table[s].domain = domain; + if (s + 1 > max_fd) { + max_fd = s + 1; + } + } + + s = __syscall_ret (s); + DEBUG_LOG (" = %d\n", s); + return s; +} diff --git a/libdesock/src/sockopt.c b/libdesock/src/sockopt.c new file mode 100644 index 0000000..2479f8d --- /dev/null +++ b/libdesock/src/sockopt.c @@ -0,0 +1,17 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include +#include + +int setsockopt (int fd, int level, int optname, const void* optval, socklen_t optlen) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::setsockopt(%d, %d, %d, %p, %lu) = 0\n", gettid (), fd, level, optname, optval, optlen); + return 0; + } else { + int r = __socketcall (setsockopt, fd, level, optname, optval, optlen, 0); + return __syscall_ret (r); + } +} diff --git a/libdesock/src/syscall.c b/libdesock/src/syscall.c new file mode 100644 index 0000000..9b2fa33 --- /dev/null +++ b/libdesock/src/syscall.c @@ -0,0 +1,23 @@ + +#include + +hidden long __syscall_cp_c (); + +static long sccp (syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, syscall_arg_t x, syscall_arg_t y, syscall_arg_t z) { + return __syscall (nr, u, v, w, x, y, z); +} + +weak_alias (sccp, __syscall_cp_c); + +long (__syscall_cp) (syscall_arg_t nr, syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, syscall_arg_t x, syscall_arg_t y, syscall_arg_t z) { + return __syscall_cp_c (nr, u, v, w, x, y, z); +} + +long __syscall_ret (unsigned long r) { + if (r > -4096UL) { + errno = -r; + return -1; + } else { + return r; + } +} diff --git a/libdesock/src/write.c b/libdesock/src/write.c new file mode 100644 index 0000000..c81c261 --- /dev/null +++ b/libdesock/src/write.c @@ -0,0 +1,118 @@ +#define _GNU_SOURCE +#define __USE_GNU +#include +#include +#include + +#include +#include + +static long internal_writev (const struct iovec* iov, int len) { + int written = 0; + + for (int i = 0; i < len; ++i) { +#ifdef DEBUG + int offset = 0, r; + + do { + r = syscall_cp (SYS_write, 1, (char *) iov[i].iov_base + offset, iov[i].iov_len - offset); + + if (r == -1) { + return -1; + } + + written += r; + offset += r; + } while (offset < iov[i].iov_len && r > 0); +#else + written += iov[i].iov_len; +#endif + } + + return written; +} + +ssize_t write (int fd, const void* buf, size_t count) { + if (VALID_FD (fd) && fd_table[fd].desock) { +#ifdef DEBUG + int r = syscall_cp (SYS_write, 1, buf, count); + DEBUG_LOG ("[%d] desock::write(%d, %p, %lu) = %d\n", gettid (), fd, buf, count, r); + return r; +#else + return count; +#endif + } else { + return syscall_cp (SYS_write, fd, buf, count); + } +} + +ssize_t send (int fd, const void* buf, size_t len, int flags) { + if (VALID_FD (fd) && fd_table[fd].desock) { +#ifdef DEBUG + int r = syscall_cp (SYS_write, 1, buf, len); + DEBUG_LOG ("[%d] desock::send(%d, %p, %lu, %d) = %d\n", gettid (), fd, buf, len, flags, r); + return r; +#else + return len; +#endif + } else { + return sendto (fd, buf, len, flags, 0, 0); + } +} + +ssize_t sendto (int fd, const void* buf, size_t len, int flags, const struct sockaddr* addr, socklen_t alen) { + if (VALID_FD (fd) && fd_table[fd].desock) { +#ifdef DEBUG + int r = syscall_cp (SYS_write, 1, buf, len); + DEBUG_LOG ("[%d] desock::sendto(%d, %p, %lu, %d, %p, %lu) = %d\n", gettid (), fd, buf, len, flags, addr, alen, r); + return r; +#else + return len; +#endif + } else { + return socketcall_cp (sendto, fd, buf, len, flags, addr, alen); + } +} + +ssize_t sendmsg (int fd, const struct msghdr* msg, int flags) { + if (VALID_FD (fd) && fd_table[fd].desock) { + int r = internal_writev (msg->msg_iov, msg->msg_iovlen); + DEBUG_LOG ("[%d] desock::sendmsg(%d, %p, %d) = %d\n", gettid (), fd, msg, flags, r); + return r; + } else { + return socketcall_cp (sendmsg, fd, msg, flags, 0, 0, 0); + } +} + +int sendmmsg (int fd, struct mmsghdr* msgvec, unsigned int vlen, int flags) { + if (VALID_FD (fd) && fd_table[fd].desock) { + DEBUG_LOG ("[%d] desock::sendmmsg(%d, %p, %d, %d)", gettid (), fd, msgvec, vlen, flags); + + int i; + + for (i = 0; i < vlen; ++i) { + msgvec[i].msg_len = internal_writev (msgvec[i].msg_hdr.msg_iov, msgvec[i].msg_hdr.msg_iovlen); + + if (msgvec[i].msg_len == -1) { + DEBUG_LOG (" = -1\n"); + return -1; + } + } + + int r = (i == vlen || i == 0) ? i : (i + 1); + DEBUG_LOG (" = %d\n", r); + return r; + } else { + return syscall_cp (SYS_sendmmsg, fd, msgvec, vlen, flags); + } +} + +ssize_t writev (int fd, const struct iovec* iov, int count) { + if (VALID_FD (fd) && fd_table[fd].desock) { + int r = internal_writev (iov, count); + DEBUG_LOG ("[%d] desock::writev(%d, %p, %d) = %d\n", gettid (), fd, iov, count, r); + return r; + } else { + return syscall_cp (SYS_writev, fd, iov, count); + } +} diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..cc7e55d --- /dev/null +++ b/meson.build @@ -0,0 +1,160 @@ +project('libdesock', 'c') + +if get_option('interpreter') == '' + r = run_command('sh', '-c', 'readelf -l /bin/ls | grep "program interpreter" | cut -d: -f2 | sed -e "s/^.//" -e "s/.$//"') + interpreter = r.stdout().strip() +else + interpreter = get_option('interpreter') +endif + +args = [ + '-O2', + '-Wall', + '-Wextra', + '-Wpedantic', + '-Wno-unused-parameter', + '-Wno-sign-compare', + '-D DESOCKARCH="@0@"'.format(get_option('arch')), + '-D MAX_CONNS=1', + '-D FD_TABLE_SIZE=@0@'.format(get_option('fd_table_size')), + '-D INTERPRETER="@0@"'.format(interpreter) +] + +if get_option('debug_desock') + args += '-D DEBUG' +endif + +if get_option('desock_client') + args += '-D DESOCK_CONNECT' +endif + +if get_option('desock_server') + args += '-D DESOCK_BIND' +endif + +libdesock_shared = shared_library('desock', + sources : [ + 'libdesock/src/accept.c', + 'libdesock/src/bind.c', + 'libdesock/src/close.c', + 'libdesock/src/connect.c', + 'libdesock/src/desock.c', + 'libdesock/src/dup.c', + 'libdesock/src/epoll.c', + 'libdesock/src/getpeername.c', + 'libdesock/src/getsockname.c', + 'libdesock/src/listen.c', + 'libdesock/src/peekbuffer.c', + 'libdesock/src/poll.c', + 'libdesock/src/read.c', + 'libdesock/src/select.c', + 'libdesock/src/sendfile.c', + 'libdesock/src/shutdown.c', + 'libdesock/src/socket.c', + 'libdesock/src/sockopt.c', + 'libdesock/src/syscall.c', + 'libdesock/src/write.c', + ], + include_directories : [ + include_directories('libdesock/include'), + include_directories('libdesock/include/arch/' + get_option('arch')) + ], + c_args : args, + link_args : '-Wl,-e,desock_main', + install : false, + dependencies : [ + dependency('threads') + ] +) + +static_library('desock', + sources : [ + 'libdesock/src/accept.c', + 'libdesock/src/bind.c', + 'libdesock/src/close.c', + 'libdesock/src/connect.c', + 'libdesock/src/desock.c', + 'libdesock/src/dup.c', + 'libdesock/src/epoll.c', + 'libdesock/src/getpeername.c', + 'libdesock/src/getsockname.c', + 'libdesock/src/listen.c', + 'libdesock/src/peekbuffer.c', + 'libdesock/src/poll.c', + 'libdesock/src/read.c', + 'libdesock/src/select.c', + 'libdesock/src/sendfile.c', + 'libdesock/src/shutdown.c', + 'libdesock/src/socket.c', + 'libdesock/src/sockopt.c', + 'libdesock/src/syscall.c', + 'libdesock/src/write.c', + ], + include_directories : [ + include_directories('libdesock/include'), + include_directories('libdesock/include/arch/' + get_option('arch')) + ], + c_args : args, + link_args : '-Wl,-e,desock_main', + install : false, + dependencies : [ + dependency('threads') + ] +) + +exported_functions = [ + 'accept', + 'accept4', + 'bind', + 'connect', + 'close', + 'dup', + 'dup2', + 'dup3', + 'epoll_create', + 'epoll_create1', + 'epoll_ctl', + 'epoll_pwait', + 'epoll_wait', + 'epoll_pwait2', + 'getpeername', + 'getsockname', + 'listen', + 'poll', + 'ppoll', + 'read', + 'recvfrom', + 'recv', + 'recvmsg', + 'recvmmsg', + 'readv', + 'select', + 'pselect', + 'sendfile', + 'sendfile64', + 'shutdown', + 'socket', + 'setsockopt', + 'write', + 'send', + 'sendto', + 'sendmsg', + 'sendmmsg', + 'writev' +] + +strip_cmd = ['strip'] + +foreach fun : exported_functions + strip_cmd += '--keep-symbol=@0@'.format(fun) +endforeach + +strip_cmd += '@INPUT@' + +custom_target('target', + depends : libdesock_shared, + input : libdesock_shared, + output : 'fake', + command : strip_cmd, + build_by_default : true +) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..d1efb95 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,6 @@ +option('arch', type : 'combo', choices : ['aarch64', 'arm', 'i386', 'm68k', 'microblaze', 'mips', 'mips64', 'mipsn32', 'or1k', 'powerpc', 'powerpc64', 'riscv64', 's390x', 'sh', 'x32', 'x86_64'], value : 'x86_64') +option('fd_table_size', type : 'integer', min : 3, max : 1024, value : 128) +option('interpreter', type : 'string') +option('desock_client', type : 'boolean', value : false) +option('desock_server', type : 'boolean', value : true) +option('debug_desock', type : 'boolean', value : false) diff --git a/run-tests.sh b/run-tests.sh new file mode 100755 index 0000000..e7ca97e --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e; + +pytest="pytest -q -x -s" +dir=$(mktemp -d) + +meson setup "$dir" + +pushd "$dir" +meson configure -D b_coverage=true -D debug_desock=true -D desock_server=true -D desock_client=true -D fd_table_size=512 +meson compile +popd + +export LIBDESOCK=$(realpath "$dir/libdesock.so") + +$pytest tests/test_read.py tests/test_write.py tests/test_peekbuffer.py tests/test_sendfile.py +$pytest tests/test_accept.py +$pytest tests/test_bind.py +$pytest tests/test_dup.py +$pytest tests/test_standard.py +$pytest tests/test_select.py +$pytest tests/test_poll.py +$pytest tests/test_epoll.py +$pytest tests/test_metadata.py + +pushd "$dir" +find libdesock.so.p | grep -E '\.o$' | xargs gcov +popd + +mv "$dir/"*.gcov tests/coverage + +rm -rf "$dir" + +cd tests +echo +echo '########################' +./get-coverage.py +echo '########################' diff --git a/tests/coverage/.gitignore b/tests/coverage/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/coverage/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/desock.py b/tests/desock.py new file mode 100644 index 0000000..9a27697 --- /dev/null +++ b/tests/desock.py @@ -0,0 +1,707 @@ +import os +import socket +import ctypes +import faulthandler +faulthandler.enable() + +FD_TABLE_SIZE = 512 +STATIC_BUFFER_SIZE = 8192 + +class DesockError(RuntimeError): + pass + +class sockaddr(ctypes.Structure): + _fields_ = [ + ("sa_family", ctypes.c_ushort), + ("sa_data", ctypes.c_char * 14) + ] + +class sockaddr_in(ctypes.Structure): + _fields_ = [ + ("sin_family", ctypes.c_ushort), + ("sin_port", ctypes.c_ushort), + ("sin_addr", ctypes.c_uint), + ("sin_zero", ctypes.c_char * 8) + ] + +class sockaddr_in6(ctypes.Structure): + _fields_ = [ + ("sin6_family", ctypes.c_ushort), + ("sin6_port", ctypes.c_ushort), + ("sin6_flowinfo", ctypes.c_uint), + ("sin6_addr", ctypes.c_byte * 16), + ("sin6_scope_id", ctypes.c_uint) + ] + +class sockaddr_un(ctypes.Structure): + _fields_ = [ + ("sun_family", ctypes.c_ushort), + ("sun_path", ctypes.c_byte * 108) + ] + +class iovec(ctypes.Structure): + _fields_ = [ + ("iov_base", ctypes.POINTER(ctypes.c_char)), + ("iov_len", ctypes.c_size_t) + ] + +class msghdr(ctypes.Structure): + _fields_ = [ + ("msg_name", ctypes.POINTER(ctypes.c_char)), + ("msg_namelen", ctypes.c_uint), + ("msg_iov", ctypes.POINTER(iovec)), + ("msg_iovlen", ctypes.c_size_t), + ("msg_control", ctypes.POINTER(ctypes.c_char)), + ("msg_controllen", ctypes.c_size_t), + ("msg_flags", ctypes.c_int) + ] + +class mmsghdr(ctypes.Structure): + _fields_ = [ + ("msg_hdr", msghdr), + ("msg_len", ctypes.c_uint) + ] + +FD_SETSIZE = 1024 + +class fd_set(ctypes.Structure): + _fields_ = [ + ("fds_bits", ctypes.c_long * (FD_SETSIZE // 64)) + ] + +def FD_ZERO(s): + for i in range(len(s.fds_bits)): + s.fds_bits[i] = 0 + +def FD_SET(fd, s): + assert(0 <= fd < FD_SETSIZE) + s.fds_bits[fd // 64] |= (1 << (fd % 64)) + +def FD_CLR(fd, s): + assert(0 <= fd < FD_SETSIZE) + s.fds_bits[fd // 64] &= ~(1 << (fd % 64)) + +def FD_ISSET(fd, s): + assert(0 <= fd < FD_SETSIZE) + return (s.fds_bits[fd // 64] & (1 << (fd % 64))) != 0 + +def FD_COPY(dst, src): + for i in range(len(dst.fds_bits)): + dst.fds_bits[i] = src.fds_bits[i] + +class pollfd(ctypes.Structure): + _fields_ = [ + ("fd", ctypes.c_int), + ("events", ctypes.c_short), + ("revents", ctypes.c_short) + ] + +class epoll_data(ctypes.Union): + _fields_ = [ + ("ptr", ctypes.c_void_p), + ("fd", ctypes.c_int), + ("u32", ctypes.c_uint), + ("u64", ctypes.c_ulonglong) + ] + +class epoll_event(ctypes.Structure): + _fields_ = [ + ("events", ctypes.c_uint), + ("data", epoll_data) + ] + +class fd_entry(ctypes.Structure): + _fields_ = [ + ("domain", ctypes.c_int), + ("desock", ctypes.c_int), + ("listening", ctypes.c_int), + ("epfd", ctypes.c_int), + ("ep_event", epoll_event) + ] + +MSG_PEEK = socket.MSG_PEEK.value +AF_INET = socket.AF_INET.value +AF_INET6 = socket.AF_INET6.value +SOCK_STREAM = socket.SOCK_STREAM.value +SOCK_DGRAM = socket.SOCK_DGRAM.value +POLLIN = 1 +POLLOUT = 4 +POLLERR = 8 +POLLHUP = 16 +POLLNVAL = 32 +EPOLL_CTL_ADD = 1 +EPOLL_CTL_DEL = 2 +EPOLL_CTL_MOD = 3 +EPOLLIN = 1 +EPOLLOUT = 4 +EPOLLERR = 8 +EPOLLHUP = 16 +EPOLLONESHOT = 1 << 30 + +_libdesock = ctypes.cdll.LoadLibrary(os.getenv("LIBDESOCK")) + +pure_debug_functions = ["_debug_instant_fd", "_debug_real_bind", "_debug_real_dup2", "_debug_get_fd_table_entry"] +for debug_fn in pure_debug_functions: + if not hasattr(_libdesock, debug_fn): + print("It looks like you are not testing the debug-build of the library!") + exit(1) + +_libc = ctypes.CDLL("libc.so.6") + +_libc.__errno_location.restype = ctypes.POINTER(ctypes.c_int) +_libc.strerror.restype = ctypes.c_char_p +def _get_error(): + return _libc.strerror(_libc.__errno_location()[0]).decode() + +def _clear_error(): + _libc.__errno_location().contents = ctypes.c_int(0) + +_libdesock.socket.restype = ctypes.c_int +def socket(domain, type, protocol): + _clear_error() + r = _libdesock.socket( + ctypes.c_int(domain), + ctypes.c_int(type), + ctypes.c_int(protocol) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.close.restype = ctypes.c_int +def close(fd): + _clear_error() + r = _libdesock.close( + ctypes.c_int(fd) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.accept.restype = ctypes.c_int +def accept(fd, addr, len): + if addr is not None: + addr = ctypes.byref(addr) + if len is not None: + len = ctypes.byref(len) + + _clear_error() + r = _libdesock.accept( + ctypes.c_int(fd), + addr, + len + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.accept4.restype = ctypes.c_int +def accept4(fd, addr, len, flag=0): + if addr is not None: + addr = ctypes.byref(addr) + if len is not None: + len = ctypes.byref(len) + + _clear_error() + r = _libdesock.accept4( + ctypes.c_int(fd), + addr, + len, + ctypes.c_int(flag) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.bind.restype = ctypes.c_int +def bind(fd, addr, len): + if addr is not None: + addr = ctypes.byref(addr) + + _clear_error() + r = _libdesock.bind( + ctypes.c_int(fd), + addr, + ctypes.c_int(len) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.listen.restype = ctypes.c_int +def listen(fd, backlog): + _clear_error() + r = _libdesock.listen( + ctypes.c_int(fd), + ctypes.c_int(backlog) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.dup.restype = ctypes.c_int +def dup(fd): + _clear_error() + r = _libdesock.dup(ctypes.c_int(fd)) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.dup2.restype = ctypes.c_int +def dup2(old, new): + _clear_error() + r = _libdesock.dup2( + ctypes.c_int(old), + ctypes.c_int(new) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.dup3.restype = ctypes.c_int +def dup3(old, new, flags): + _clear_error() + r = _libdesock.dup3( + ctypes.c_int(old), + ctypes.c_int(new), + ctypes.c_int(flags) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.read.restype = ctypes.c_int +def read(fd, buf, count): + _clear_error() + r = _libdesock.read( + ctypes.c_int(fd), + ctypes.byref(buf), + ctypes.c_int(count) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.recv.restype = ctypes.c_int +def recv(fd, buf, len, flags): + _clear_error() + r = _libdesock.recv( + ctypes.c_int(fd), + ctypes.byref(buf), + ctypes.c_int(len), + ctypes.c_int(flags) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.recvfrom.restype = ctypes.c_int +def recvfrom(fd, buf, len, flags, addr, alen): + if addr is not None: + addr = ctypes.byref(addr) + if alen is not None: + alen = ctypes.byref(alen) + + _clear_error() + r = _libdesock.recvfrom( + ctypes.c_int(fd), + ctypes.byref(buf), + ctypes.c_int(len), + ctypes.c_int(flags), + addr, + alen + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.recvmsg.restype = ctypes.c_int +def recvmsg(fd, msg, flags): + _clear_error() + r = _libdesock.recvmsg( + ctypes.c_int(fd), + ctypes.byref(msg), + ctypes.c_int(flags) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.recvmmsg.restype = ctypes.c_int +def recvmmsg(fd, msgvec, vlen, flags, timeout): + if timeout is not None: + timeout = ctypes.byref(timeout) + + _clear_error() + r = _libdesock.recvmmsg( + ctypes.c_int(fd), + ctypes.byref(msgvec), + ctypes.c_int(vlen), + ctypes.c_int(flags), + timeout + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.readv.restype = ctypes.c_int +def readv(fd, iov, count): + _clear_error() + r = _libdesock.readv( + ctypes.c_int(fd), + ctypes.byref(iov), + ctypes.c_int(count) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock._debug_instant_fd.restype = ctypes.c_int +def _debug_instant_fd(listening): + _clear_error() + r = _libdesock._debug_instant_fd( + ctypes.c_int(listening) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock._debug_real_bind.restype = ctypes.c_int +def _debug_real_bind(fd, addr, len): + if addr is not None: + addr = ctypes.byref(addr) + + _clear_error() + r = _libdesock._debug_real_bind( + ctypes.c_int(fd), + addr, + ctypes.c_int(len) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.write.restype = ctypes.c_ssize_t +def write(fd, buf, count): + _clear_error() + r = _libdesock.write( + ctypes.c_int(fd), + ctypes.byref(buf), + ctypes.c_size_t(count) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.send.restype = ctypes.c_ssize_t +def send(fd, buf, len, flags): + _clear_error() + r = _libdesock.send( + ctypes.c_int(fd), + ctypes.byref(buf), + ctypes.c_int(len), + ctypes.c_int(flags) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.sendto.restype = ctypes.c_ssize_t +def sendto(fd, buf, len, flags, addr, alen): + if addr is not None: + addr = ctypes.byref(addr) + + _clear_error() + r = _libdesock.sendto( + ctypes.c_int(fd), + ctypes.byref(buf), + ctypes.c_int(len), + ctypes.c_int(flags), + addr, + ctypes.c_int(alen) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.sendmsg.restype = ctypes.c_ssize_t +def sendmsg(fd, msg, flags): + _clear_error() + r = _libdesock.sendmsg( + ctypes.c_int(fd), + ctypes.byref(msg), + ctypes.c_int(flags) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.sendmmsg.restype = ctypes.c_int +def sendmmsg(fd, msgvec, vlen, flags): + _clear_error() + r = _libdesock.sendmmsg( + ctypes.c_int(fd), + None if msgvec is None else ctypes.byref(msgvec), + ctypes.c_int(vlen), + ctypes.c_int(flags) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.writev.restype = ctypes.c_ssize_t +def writev(fd, iov, count): + _clear_error() + r = _libdesock.writev( + ctypes.c_int(fd), + ctypes.byref(iov), + ctypes.c_int(count) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.select.restype = ctypes.c_int +def select(nfds, rfds, wfds, efds, timeout): + if rfds is not None: + rfds = ctypes.byref(rfds) + if wfds is not None: + wfds = ctypes.byref(wfds) + if efds is not None: + efds = ctypes.byref(efds) + if timeout is not None: + timeout = ctypes.byref(timeout) + + _clear_error() + r = _libdesock.select( + ctypes.c_int(nfds), + rfds, + wfds, + efds, + timeout + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.pselect.restype = ctypes.c_int +def pselect(nfds, rfds, wfds, efds, timeout, sigmask): + if rfds is not None: + rfds = ctypes.byref(rfds) + if wfds is not None: + wfds = ctypes.byref(wfds) + if efds is not None: + efds = ctypes.byref(efds) + if timeout is not None: + timeout = ctypes.byref(timeout) + if sigmask is not None: + sigmask = ctypes.byref(sigmask) + + _clear_error() + r = _libdesock.pselect( + ctypes.c_int(nfds), + rfds, + wfds, + efds, + timeout, + sigmask + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.poll.restype = ctypes.c_int +def poll(fds, nfds, timeout): + if fds is not None: + fds = ctypes.byref(fds) + + _clear_error() + r = _libdesock.poll( + fds, + ctypes.c_int(nfds), + ctypes.c_int(timeout) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.ppoll.restype = ctypes.c_int +def ppoll(fds, nfds, timeout, mask): + if fds is not None: + fds = ctypes.byref(fds) + if timeout is not None: + timeout = ctypes.byref(timeout) + if mask is not None: + mask = ctypes.byref(mask) + + _clear_error() + r = _libdesock.ppoll( + fds, + ctypes.c_int(nfds), + timeout, + mask + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.epoll_create.restype = ctypes.c_int +def epoll_create(): + _clear_error() + r = _libdesock.epoll_create(0) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.epoll_ctl.restype = ctypes.c_int +def epoll_ctl(epfd, op, fd, event): + if event is not None: + event = ctypes.byref(event) + + _clear_error() + r = _libdesock.epoll_ctl( + ctypes.c_int(epfd), + ctypes.c_int(op), + ctypes.c_int(fd), + event + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.epoll_wait.restype = ctypes.c_int +def epoll_wait(epfd, events, maxevents, timeout): + _clear_error() + r = _libdesock.epoll_wait( + ctypes.c_int(epfd), + ctypes.byref(events), + ctypes.c_int(maxevents), + ctypes.c_int(timeout) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.epoll_pwait.restype = ctypes.c_int +def epoll_pwait(epfd, events, maxevents, timeout, sigmask): + if sigmask is not None: + sigmask = ctypes.byref(sigmask) + + _clear_error() + r = _libdesock.epoll_pwait( + ctypes.c_int(epfd), + ctypes.byref(events), + ctypes.c_int(maxevents), + ctypes.c_int(timeout), + sigmask + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.epoll_pwait2.restype = ctypes.c_int +def epoll_pwait2(epfd, events, maxevents, timeout, sigmask): + if timeout is not None: + timeout = ctypes.byref(timeout) + if sigmask is not None: + sigmask = ctypes.byref(sigmask) + + _clear_error() + r = _libdesock.epoll_pwait2( + ctypes.c_int(epfd), + ctypes.byref(events), + ctypes.c_int(maxevents), + timeout, + sigmask + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.getpeername.restype = ctypes.c_int +def getpeername(sockfd, addr, addrlen): + _clear_error() + r = _libdesock.getpeername( + ctypes.c_int(sockfd), + ctypes.byref(addr), + ctypes.byref(addrlen) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.getsockname.restype = ctypes.c_int +def getsockname(sockfd, addr, addrlen): + _clear_error() + r = _libdesock.getsockname( + ctypes.c_int(sockfd), + ctypes.byref(addr), + ctypes.byref(addrlen) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.sendfile.restype = ctypes.c_int +def sendfile(out_fd, in_fd, offset, count): + if offset is not None: + offset = ctypes.byref(offset) + + _clear_error() + r = _libdesock.sendfile( + ctypes.c_int(out_fd), + ctypes.c_int(in_fd), + offset, + ctypes.c_size_t(count) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.sendfile64.restype = ctypes.c_int +def sendfile64(out_fd, in_fd, offset, count): + if offset is not None: + offset = ctypes.byref(offset) + + _clear_error() + r = _libdesock.sendfile64( + ctypes.c_int(out_fd), + ctypes.c_int(in_fd), + offset, + ctypes.c_size_t(count) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock._debug_real_dup2.restype = ctypes.c_int +def _debug_real_dup2(old, new): + _clear_error() + r = _libdesock._debug_real_dup2( + ctypes.c_int(old), + ctypes.c_int(new) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +_libdesock.connect.restype = ctypes.c_int +def connect(fd, addr, addrlen): + if addr is not None: + addr = ctypes.byref(addr) + + _clear_error() + r = _libdesock.connect( + ctypes.c_int(fd), + addr, + ctypes.c_int(addrlen) + ) + if r < 0: + raise DesockError(_get_error()) + return r + +def _debug_get_fd_table_entry(idx, dst): + _libdesock._debug_get_fd_table_entry(idx, ctypes.byref(dst)) + +def clear_fd_table_entry(idx): + _libdesock.clear_fd_table_entry(idx) diff --git a/tests/get-coverage.py b/tests/get-coverage.py new file mode 100755 index 0000000..d1a4e27 --- /dev/null +++ b/tests/get-coverage.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import os + +def read_gcov_file(name): + r = 0 + t = 0 + with open(name) as f: + for line in f: + line = line.strip() + count = line.split(":", 1)[0] + + if count != "#####": + r += 1 + + t += 1 + return r, t + +def main(): + reached = 0 + total = 0 + + for c_file in os.listdir("../libdesock/src"): + r, t = read_gcov_file("coverage/" + c_file + ".gcov") + reached += r + total += t + + print(f"Statement coverage: {100 * reached // total}%") + +if __name__ == "__main__": + main() diff --git a/tests/helper.py b/tests/helper.py new file mode 100644 index 0000000..dcc45e0 --- /dev/null +++ b/tests/helper.py @@ -0,0 +1,183 @@ +import os +import ctypes +import socket +import threading +import random + +import desock + +all_domains = [ + desock.AF_INET, + desock.AF_INET6 +] +all_types = [ + desock.SOCK_STREAM, + desock.SOCK_DGRAM +] + +class StdinPipe: + def __init__(self): + self._r_fd = None + self._w_fd = None + self._stdin_backup = None + + def __enter__(self): + self._r_fd, self._w_fd = os.pipe() + self._stdin_backup = os.dup(0) + os.dup2(self._r_fd, 0) + return self + + def write(self, data): + return os.write(self._w_fd, bytes(data)) + + def close(self): + if self._w_fd is not None: + os.close(self._w_fd) + self._w_fd = None + + def __exit__(self, *args): + self.close() + os.dup2(self._stdin_backup, 0) + os.close(self._stdin_backup) + os.close(self._r_fd) + +class StdoutPipe: + def __init__(self): + self._r_fd = None + self._w_fd = None + self._stdout_backup = None + + def __enter__(self): + self._r_fd, self._w_fd = os.pipe() + self._stdout_backup = os.dup(1) + os.dup2(self._w_fd, 1) + return self + + def read(self, n): + return os.read(self._r_fd, n) + + def __exit__(self, *args): + os.close(self._r_fd) + os.close(self._w_fd) + os.dup2(self._stdout_backup, 1) + os.close(self._stdout_backup) + +def _init_data(size): + return bytes([0xff] * size) + +def create_iovec(number, size, datafunc=_init_data): + iovs = (desock.iovec * number)() + for i in range(number): + iovs[i].iov_len = size + + if size > 0: + iovs[i].iov_base = ctypes.create_string_buffer(datafunc(size)) + else: + iovs[i].iov_base = None + return iovs + +def create_msghdr(iov=None, namelen=0, controllen=0, flags=0, datafunc=_init_data): + msghdr = desock.msghdr() + msghdr.msg_namelen = namelen + msghdr.msg_controllen = controllen + msghdr.msg_flags = flags + + if namelen > 0: + msghdr.msg_name = ctypes.create_string_buffer(datafunc(namelen)) + else: + msghdr.msg_name = None + + if controllen > 0: + msghdr.msg_control = ctypes.create_string_buffer(datafunc(controllen)) + else: + msghdr.msg_control = None + + msghdr.msg_iov = iov + + if iov is not None: + msghdr.msg_iovlen = len(iov) + else: + msghdr.msg_iovlen = 0 + + return msghdr + +def create_mmsghdr(msghdr): + mmsghdr = desock.mmsghdr() + mmsghdr.msg_hdr = msghdr + mmsghdr.msg_len = 0 + return mmsghdr + +def _spawn_real_server(host="127.0.0.1", port=0): + address = desock.sockaddr_in(desock.AF_INET, socket.htons(port), int.from_bytes(socket.inet_aton(host), "little")) + s = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + desock._debug_real_bind(s, address, ctypes.sizeof(address)) + desock.listen(s, 10) + return s + +def interact_with_real_server(callback, data): + result = None + port = random.choice(range(1025, 65535)) + + def handle_client(s): + nonlocal callback, data, result + c = desock.accept(s, None, None) + try: + callback(c) + except BaseException as b: + result = b + desock.close(c) + + s = _spawn_real_server(port=port) + t = threading.Thread(target=handle_client, args=(s,)) + t.start() + + c = socket.create_connection(("127.0.0.1", port), timeout=3) + c.send(data) + c.close() + + t.join() + desock.close(s) + + if result is not None: + raise result + +def get_fake_connection(domain, type): + s = desock.socket(domain, type, 0) + desock.bind(s, None, 0) + desock.listen(s, 0) + c = desock.accept(s, None, None) + return s, c + +class ThreadPool: + def __init__(self): + self._pool = [] + + def spawn(self, method, args=[], kwargs={}): + t = threading.Thread(target=method, args=tuple(args), kwargs=kwargs) + t.start() + self._pool.append(t) + + def __enter__(self): + return self + + def __exit__(self, *args): + for t in self._pool: + t.join() + +class NoStdout: + def __init__(self): + self._dev_null = None + self._stdout_backup = None + + def __enter__(self): + self._stdout_backup = os.dup(1) + self._dev_null = os.open("/dev/null", os.O_WRONLY) + os.dup2(self._dev_null, 1) + return self + + def __exit__(self, *args): + os.close(self._dev_null) + os.dup2(self._stdout_backup, 1) + os.close(self._stdout_backup) + + diff --git a/tests/test_accept.py b/tests/test_accept.py new file mode 100644 index 0000000..2ceb8e0 --- /dev/null +++ b/tests/test_accept.py @@ -0,0 +1,58 @@ +""" +This file tests the accept() implementation. + +Target files: + - libdesock/src/accept.c +""" + +import ctypes + +import helper +import desock + +def test_sockaddr_in(): + for method in [desock.accept, desock.accept4]: + s = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + desock.bind(s, None, 0) + desock.listen(s, 0) + addr = desock.sockaddr_in() + len = ctypes.c_int(ctypes.sizeof(addr)) + c = method(s, addr, len) + desock.close(c) + desock.close(s) + assert(addr.sin_family == desock.AF_INET) + assert(addr.sin_port == 53764) + assert(addr.sin_addr == 0x100007f) + +def test_sockaddr_in6(): + for method in [desock.accept, desock.accept4]: + s = desock.socket(desock.AF_INET6, desock.SOCK_STREAM, 0) + desock.bind(s, None, 0) + desock.listen(s, 0) + addr = desock.sockaddr_in6() + len = ctypes.c_int(ctypes.sizeof(addr)) + c = method(s, addr, len) + desock.close(c) + desock.close(s) + assert(addr.sin6_family == desock.AF_INET6) + assert(addr.sin6_port == 53764) + assert(addr.sin6_flowinfo == 0) + for i in range(15): + assert(addr.sin6_addr[i] == 0) + assert(addr.sin6_addr[15] == 1) + assert(addr.sin6_scope_id == 0) + +def test_invalid(): + fd = desock._debug_instant_fd(1) + for _ in range(fd + 1, desock.FD_TABLE_SIZE): + desock.dup(0) + + try: + desock.accept(fd, None, None) + except desock.DesockError as e: + assert(str(e) == "Success") + else: + assert(False) + + for i in range(fd, desock.FD_TABLE_SIZE + 1): + desock.close(i) diff --git a/tests/test_bind.py b/tests/test_bind.py new file mode 100644 index 0000000..31758bc --- /dev/null +++ b/tests/test_bind.py @@ -0,0 +1,29 @@ +""" +This file tests the bind() implementation. + +Target files: + - libdesock/src/bind.c +""" + +import ctypes + +import desock +import helper + +def test_invalid(): + s1 = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + s = desock._debug_real_dup2(s1, desock.FD_TABLE_SIZE) + addr = desock.sockaddr_in() + addr.sin_family = desock.AF_INET + addr.sin_port = 53764 + addr.sin_addr = 0x100007f + desock.bind(s, addr, ctypes.sizeof(addr)) + sockname = desock.sockaddr_in() + sockname_len = ctypes.c_int(ctypes.sizeof(sockname)) + desock.getsockname(s, sockname, sockname_len) + assert(sockname_len.value == ctypes.sizeof(sockname)) + assert(sockname.sin_family == desock.AF_INET) + assert(sockname.sin_port == 53764) + assert(sockname.sin_addr == 0x100007f) + desock.close(s) + desock.close(s1) diff --git a/tests/test_dup.py b/tests/test_dup.py new file mode 100644 index 0000000..e8fe9d4 --- /dev/null +++ b/tests/test_dup.py @@ -0,0 +1,40 @@ +""" +This file tests the dup*() implementations. + +Target files: + - libdesock/src/dup.c +""" + +import ctypes + +import desock +import helper + +def dup23(method, *flags): + s = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + n = method(s, s + 1, *flags) + assert(n == s + 1) + entry1 = desock.fd_entry() + entry2 = desock.fd_entry() + desock._debug_get_fd_table_entry(s, entry1) + desock._debug_get_fd_table_entry(n, entry2) + assert(entry1.domain == entry2.domain) + assert(entry1.desock == entry2.desock) + assert(entry1.listening == entry2.listening) + assert(entry1.epfd == entry2.epfd) + assert(entry1.ep_event.events == entry2.ep_event.events) + assert(entry1.ep_event.data.u64 == entry2.ep_event.data.u64) + desock.close(n) + desock.close(s) + +def dup23_invalid_new(method, *flags): + s = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + n = desock.FD_TABLE_SIZE + assert(method(s, n, *flags) == n) + desock.close(n) + desock.close(s) + +def test_dup2_and_dup3(): + for method in [dup23_invalid_new, dup23]: + method(desock.dup2) + method(desock.dup3, 0) diff --git a/tests/test_epoll.py b/tests/test_epoll.py new file mode 100644 index 0000000..1481eee --- /dev/null +++ b/tests/test_epoll.py @@ -0,0 +1,145 @@ +""" +This file tests the epoll() implementation. + +Target files: + - libdesock/src/epoll.c +""" + +import os +import ctypes +import random + +import helper +import desock + +def _read(fd): + buf = ctypes.create_string_buffer(1024) + n = desock.recv(fd, buf, ctypes.sizeof(buf), 0) + return buf[:n] + +def do_syscall(method, *args): + s = desock.socket(desock.AF_INET, desock.SOCK_DGRAM, 0) + e = desock.epoll_create() + c = desock.dup2(s, desock.FD_TABLE_SIZE) + event = desock.epoll_event() + event.events = desock.EPOLLOUT + event.data.fd = c + desock.epoll_ctl(e, desock.EPOLL_CTL_ADD, c, event) + events = (desock.epoll_event * 1)() + assert(method(e, events, 1, *args) == 1) + assert(events[0].events & (~desock.EPOLLOUT) == 0) + assert(events[0].data.fd == c) + desock.close(c) + desock.close(e) + desock.close(s) + +def test_syscalls(): + do_syscall(desock.epoll_wait, -1) + do_syscall(desock.epoll_pwait, -1, None) + try: + do_syscall(desock.epoll_pwait2, None, None) + except desock.DesockError as e: + assert(str(e) == "Function not implemented") + else: + assert(False) + +def test_oneshot(): + s = desock.socket(desock.AF_INET, desock.SOCK_DGRAM, 0) + desock.bind(s, None, 0) + desock.listen(s, 0) + e = desock.epoll_create() + event = desock.epoll_event() + event.events = desock.EPOLLIN | desock.EPOLLONESHOT + event.data.u64 = 0 + desock.epoll_ctl(e, desock.EPOLL_CTL_ADD, s, event) + fd_entry = desock.fd_entry() + events = (desock.epoll_event * 1)() + assert(desock.epoll_wait(e, events, 1, -1) == 1) + assert(events[0].events & (~desock.EPOLLIN) == 0) + desock._debug_get_fd_table_entry(s, fd_entry) + assert(fd_entry.epfd == -1) + c = desock.accept(s, None, None) + desock.epoll_ctl(e, desock.EPOLL_CTL_ADD, c, event) + assert(desock.epoll_wait(e, events, 1, -1) == 1) + fd_entry = desock.fd_entry() + desock._debug_get_fd_table_entry(c, fd_entry) + assert(fd_entry.epfd == -1) + desock.close(c) + desock.close(s) + desock.close(e) + +def do_epoll(method, *args): + data = b"yeeha" + input = b"" + client = None + ready_list = (desock.epoll_event * 2)() + num_put_out = 0 + maxevents = 1 + run = True + + with helper.StdinPipe() as pipe: + pipe.write(data) + pipe.close() + s = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + desock.bind(s, None, 0) + desock.listen(s, 0) + epfd = desock.epoll_create() + + event = desock.epoll_event() + event.events = desock.EPOLLIN | desock.EPOLLOUT | desock.EPOLLERR | desock.EPOLLHUP + event.data.u32 = 0x1337 + desock.epoll_ctl(epfd, desock.EPOLL_CTL_ADD, s, event) + + event = desock.epoll_event() + event.events = desock.EPOLLIN | desock.EPOLLOUT | desock.EPOLLERR | desock.EPOLLHUP + event.data.fd = s + desock.epoll_ctl(epfd, desock.EPOLL_CTL_MOD, s, event) + + while run: + r = method(epfd, ready_list, maxevents, *args) + assert(0 < r <= 2) + + for i in range(r): + if ready_list[i].events & ~(desock.EPOLLIN | desock.EPOLLOUT): + assert(False) + + if ready_list[i].events & desock.EPOLLIN: + if ready_list[i].data.fd == s: + assert(client is None) + client = desock.accept(s, None, None) + event = desock.epoll_event() + event.events = desock.EPOLLIN | desock.EPOLLOUT | desock.EPOLLERR | desock.EPOLLHUP + event.data.fd = client + desock.epoll_ctl(epfd, desock.EPOLL_CTL_MOD, client, event) + maxevents += 1 + elif ready_list[i].data.fd == client: + b = _read(client) + if b: + input += b + else: + run = False + else: + print(f"data = {ready_list[i].data.u64}") + assert(False) + + if ready_list[i].events & desock.EPOLLOUT: + if ready_list[i].data.fd == client: + num_put_out += 1 + event = desock.epoll_event() + event.events = desock.EPOLLIN | desock.EPOLLERR | desock.EPOLLHUP + event.data.fd = client + desock.epoll_ctl(epfd, desock.EPOLL_CTL_MOD, client, event) + else: + assert(False) + + desock.epoll_ctl(epfd, desock.EPOLL_CTL_DEL, s, None) + desock.close(s) + desock.close(epfd) + desock.close(client) + assert(num_put_out == 1) + assert(input == data) + +def test_epoll(): + do_epoll(desock.epoll_wait, -1) + do_epoll(desock.epoll_pwait, -1, None) + do_epoll(desock.epoll_pwait2, None, None) diff --git a/tests/test_metadata.py b/tests/test_metadata.py new file mode 100644 index 0000000..bbba165 --- /dev/null +++ b/tests/test_metadata.py @@ -0,0 +1,39 @@ +""" +This file tests all functions that retrieve metadata about +a socket or connection. + +Target files: + - libdesock/src/getpeername.c + - libdesock/src/getsockname.c +""" + +import ctypes + +import helper +import desock + +def test_getpeername(): + for domain in helper.all_domains: + sockaddr = desock.sockaddr() + addr_len = ctypes.c_long(ctypes.sizeof(sockaddr)) + s = desock.socket(domain, desock.SOCK_STREAM, 0) + desock.bind(s, None, 0) + desock.listen(s, 0) + c = desock.accept(s, None, None) + r = desock.getpeername(c, sockaddr, addr_len) + assert(r == 0) + assert(sockaddr.sa_family == domain) + assert(addr_len.value == ctypes.sizeof(sockaddr)) + desock.close(s) + desock.close(c) + +def test_getsockname(): + for domain in helper.all_domains: + sockaddr = desock.sockaddr() + addr_len = ctypes.c_long(ctypes.sizeof(sockaddr)) + s = desock.socket(domain, desock.SOCK_STREAM, 0) + desock.bind(s, None, 0) + assert(desock.getsockname(s, sockaddr, addr_len) == 0) + assert(sockaddr.sa_family == domain) + assert(addr_len.value == ctypes.sizeof(sockaddr)) + desock.close(s) diff --git a/tests/test_peekbuffer.py b/tests/test_peekbuffer.py new file mode 100644 index 0000000..2ae2466 --- /dev/null +++ b/tests/test_peekbuffer.py @@ -0,0 +1,206 @@ +""" +This file tests recv*() calls with the MSG_PEEK flag set. + +Target files: + - libdesock/src/read.c +""" + +import ctypes + +import desock +import helper + +def test_recvmsg(): + fd = desock._debug_instant_fd(0) + + with helper.StdinPipe() as pipe: + data = bytes(range(128)) + pipe.write(data) + + msghdr = helper.create_msghdr(iov=helper.create_iovec(4, 16)) + + assert(desock.recvmsg(fd, msghdr, desock.MSG_PEEK) == 64) + + msghdr = helper.create_msghdr(iov=helper.create_iovec(4, 32)) + assert(desock.recvmsg(fd, msghdr, desock.MSG_PEEK) == 128) + for i in range(4): + assert(bytes(msghdr.msg_iov[i].iov_base[:msghdr.msg_iov[i].iov_len]) == data[i * 32 : (i + 1) * 32]) + + msghdr = helper.create_msghdr(iov=helper.create_iovec(4, 32)) + assert(desock.recvmsg(fd, msghdr, 0) == 128) + for i in range(4): + assert(bytes(msghdr.msg_iov[i].iov_base[:msghdr.msg_iov[i].iov_len]) == data[i * 32 : (i + 1) * 32]) + + pipe.close() + + assert(desock.recvmsg(fd, msghdr, 0) == 0) + +def test_with_recv_and_read(): + buf = ctypes.create_string_buffer(128) + fd = desock._debug_instant_fd(0) + + with helper.StdinPipe() as pipe: + data = bytes(range(128)) + pipe.write(data) + + assert(desock.recv(fd, buf, 64, desock.MSG_PEEK) == 64) + assert(desock.recv(fd, buf, 128, desock.MSG_PEEK) == 128) + assert(buf.raw == data) + + buf = ctypes.create_string_buffer(128) + assert(desock.recv(fd, buf, 128, 0) == 128) + assert(buf.raw == data) + + pipe.close() + + assert(desock.recv(fd, buf, 128, 0) == 0) + + with helper.StdinPipe() as pipe: + data = bytes(range(128, 256)) + pipe.write(data) + + assert(desock.recv(fd, buf, 128, desock.MSG_PEEK) == 128) + + for i in range(0, 64, 2): + assert(desock.recv(fd, buf, 2, desock.MSG_PEEK) == 2) + assert(buf[:2] == data[i:i+2]) + assert(desock.recv(fd, buf, 2, 0) == 2) + assert(buf[:2] == data[i:i+2]) + + buf = ctypes.create_string_buffer(128) + data = bytes([1] * 64) + pipe.write(data) + + assert(desock.recv(fd, buf, 128, desock.MSG_PEEK) == 128) + assert(buf.raw[:64] == bytes(range(128 + 64, 256))) + assert(buf.raw[64:] == data) + + assert(desock.read(fd, buf, 64) == 64) + assert(buf.raw[:64] == bytes(range(128 + 64, 256))) + assert(desock.read(fd, buf, 64) == 64) + assert(buf.raw[:64] == data) + pipe.close() + assert(desock.read(fd, buf, 64) == 0) + +def _collect_data(mmsghdrs): + ret = b"" + for i in range(len(mmsghdrs)): + tmp = b"" + for j in range(mmsghdrs[i].msg_hdr.msg_iovlen): + tmp += mmsghdrs[i].msg_hdr.msg_iov[j].iov_base[:mmsghdrs[i].msg_hdr.msg_iov[j].iov_len] + ret += tmp[:mmsghdrs[i].msg_len] + return ret + +def _collect_len(mmsghdrs): + ret = 0 + for i in range(len(mmsghdrs)): + ret += mmsghdrs[i].msg_len + return ret + +def _new_struct(n=4): + mmsghdrs = (desock.mmsghdr * n)() + for i in range(n): + mmsghdrs[i] = helper.create_mmsghdr(helper.create_msghdr(iov=helper.create_iovec(5, 5))) + return mmsghdrs + +def test_with_recvmmsg_and_readv(): + mmsghdrs = _new_struct() + fd = desock._debug_instant_fd(0) + + with helper.StdinPipe() as pipe: + data = bytes(range(100)) + pipe.write(data) + + assert(desock.recvmmsg(fd, mmsghdrs, 2, desock.MSG_PEEK, None) == 2) + assert(_collect_len(mmsghdrs) == 50) + assert(desock.recvmmsg(fd, mmsghdrs, 3, desock.MSG_PEEK, None) == 3) + assert(_collect_len(mmsghdrs) == 75) + assert(desock.recvmmsg(fd, mmsghdrs, 4, desock.MSG_PEEK, None) == 4) + assert(_collect_len(mmsghdrs) == 100) + assert(_collect_data(mmsghdrs) == data) + + mmsghdrs = _new_struct() + assert(desock.recvmmsg(fd, mmsghdrs, 4, 0, None) == 4) + assert(_collect_len(mmsghdrs)) + assert(_collect_data(mmsghdrs) == data) + + pipe.close() + + assert(desock.recvmmsg(fd, mmsghdrs, 4, 0, None) == 0) + + with helper.StdinPipe() as pipe: + mmsghdrs = _new_struct() + data = bytes(range(128, 228)) + pipe.write(data) + + assert(desock.recvmmsg(fd, mmsghdrs, 4, desock.MSG_PEEK, None) == 4) + assert(_collect_len(mmsghdrs) == 100) + + for i in range(2): + mmsghdrs = _new_struct() + assert(desock.recvmmsg(fd, mmsghdrs, 1, desock.MSG_PEEK, None) == 1) + assert(_collect_len(mmsghdrs) == 25) + assert(_collect_data(mmsghdrs) == data[i * 25 : (i + 1) * 25]) + + assert(desock.recvmmsg(fd, mmsghdrs, 1, 0, None) == 1) + assert(_collect_len(mmsghdrs) == 25) + assert(_collect_data(mmsghdrs) == data[i * 25 : (i + 1) * 25]) + + mmsghdrs = _new_struct(3) + data = bytes([1] * 25) + pipe.write(data) + + assert(desock.recvmmsg(fd, mmsghdrs, 3, desock.MSG_PEEK, None) == 3) + assert(_collect_len(mmsghdrs) == 75) + assert(_collect_data(mmsghdrs) == bytes(range(128, 228))[50:] + data) + + data = bytes(range(128, 228))[50:] + data + for i in range(3): + iov = helper.create_iovec(5, 5) + n = desock.readv(fd, iov, 5) + assert(n == 25) + + ret = b"" + for j in range(5): + ret += iov[j].iov_base[:iov[j].iov_len] + assert(ret == data[i * 25 : (i + 1) * 25]) + + pipe.close() + assert(desock.readv(fd, helper.create_iovec(5, 5), 5) == 0) + +def test_wrap_around(): + fd = desock._debug_instant_fd(0) + + with helper.StdinPipe() as pipe: + for c, _ in enumerate( range(0, desock.STATIC_BUFFER_SIZE, 1024) ): + buf = ctypes.create_string_buffer(1024 * (c + 1)) + pipe.write(bytes([0x40 + c] * 1024)) + assert(desock.recv(fd, buf, 1024 * (c + 1), desock.MSG_PEEK) == 1024 * (c + 1)) + assert(buf.raw[-1024:] == bytes([0x40 + c] * 1024)) + + buf_size = desock.STATIC_BUFFER_SIZE - 1 + buf = ctypes.create_string_buffer(buf_size) + + assert(desock.recv(fd, buf, buf_size, 0) == buf_size) + for i in range(desock.STATIC_BUFFER_SIZE // 1024): + assert(set(buf.raw[1024 * i:1024 * (i + 1)]) == set([0x40 + i])) + + pipe.write([0x0A] * 16) + assert(desock.recv(fd, buf, 17, desock.MSG_PEEK) == 17) + assert(buf[0][0] == 0x47) + assert(buf[1:17] == bytes([0x0A] * 16)) + + pipe.close() + desock.recv(fd, buf, 4096, 0) + +def test_move_to_heap(): + fd = desock._debug_instant_fd(0) + + with helper.StdinPipe() as pipe: + for c, _ in enumerate( range(0, desock.STATIC_BUFFER_SIZE * 2 + 1, 1024) ): + buf = ctypes.create_string_buffer(1024 * (c + 1)) + pipe.write(bytes([0x40 + c] * 1024)) + assert(desock.recv(fd, buf, 1024 * (c + 1), desock.MSG_PEEK) == 1024 * (c + 1)) + + for i in range(c + 1): + assert(buf.raw[1024 * i:1024 * (i + 1)] == bytes([0x40 + i] * 1024)) diff --git a/tests/test_poll.py b/tests/test_poll.py new file mode 100644 index 0000000..0cff0ee --- /dev/null +++ b/tests/test_poll.py @@ -0,0 +1,103 @@ +""" +This file tests the poll() functionality. + +Target files: + - libdesock/src/poll.c +""" + +import ctypes + +import helper +import desock + +def do_syscall(method, *args): + s = desock.socket(desock.AF_INET, desock.SOCK_DGRAM, 0) + s1 = desock.dup2(s, desock.FD_TABLE_SIZE) + pollfds = (desock.pollfd * 1)() + pollfds[0].fd = s1 + pollfds[0].events = desock.POLLOUT + pollfds[0].revents = 0 + assert(method(pollfds, 1, *args) == 1) + desock.close(s1) + desock.close(s) + +def test_syscall(): + do_syscall(desock.poll, -1) + do_syscall(desock.ppoll, None, None) + +def _read(fd): + buf = ctypes.create_string_buffer(1024) + n = desock.recv(fd, buf, ctypes.sizeof(buf), 0) + return buf[:n] + +def _check_ret_val(r, pollfds, nfds): + assert(r > 0) + s = 0 + for i in range(nfds): + if pollfds[i].revents != 0: + s += 1 + assert(s == r) + +def _simulate_server(s, method, *args): + input = b"" + client = None + nfds = 1 + pollfds = (desock.pollfd * 2)() + events = desock.POLLIN | desock.POLLERR | desock.POLLHUP | desock.POLLOUT + run = True + output = ctypes.create_string_buffer(b"fuck off") + + pollfds[0].fd = s + pollfds[0].events = events + pollfds[0].revents = 0 + + while run: + r = method(pollfds, nfds, *args) + _check_ret_val(r, pollfds, nfds) + + for i in range(nfds): + assert(pollfds[i].revents & (~events) == 0) + + if (pollfds[i].revents & desock.POLLERR) or (pollfds[i].revents & desock.POLLHUP): + assert(False) + + if pollfds[i].revents & desock.POLLIN: + if pollfds[i].fd == s: + client = desock.accept(s, None, None) + pollfds[1].fd = client + pollfds[1].events = events + pollfds[1].revents = 0 + nfds += 1 + elif pollfds[i].fd == client: + b = _read(client) + if b: + input += b + else: + run = False + else: + assert(False) + + if pollfds[i].revents & desock.POLLOUT: + if pollfds[i].fd == client: + desock.send(client, output, ctypes.sizeof(output) - 1, 0) + pollfds[i].events &= (~desock.POLLOUT) + else: + assert(False) + + desock.close(client) + return input + +def test_poll(): + data = b"test123456" + for method, args in [(desock.poll, [-1]), (desock.ppoll, [None, None])]: + for domain in helper.all_domains: + for type in helper.all_types: + with helper.StdinPipe() as in_pipe, helper.StdoutPipe() as out_pipe: + in_pipe.write(data) + in_pipe.close() + s = desock.socket(domain, type, 0) + desock.bind(s, None, 0) + desock.listen(s, 10) + assert(_simulate_server(s, method, *args) == data) + assert(out_pipe.read(8) == b"fuck off") + desock.close(s) diff --git a/tests/test_read.py b/tests/test_read.py new file mode 100644 index 0000000..ce11800 --- /dev/null +++ b/tests/test_read.py @@ -0,0 +1,227 @@ +""" +This file tests that recvmsg, recvmmsg and readv +work as expected without MSG_PEEK set. + +Target files: + - libdesock/src/read.c +""" + +import os +import random +import ctypes +import tempfile + +import desock +import helper + +def test_read_syscall(): + fd, _ = tempfile.mkstemp() + data = (ctypes.c_char * 5)() + len = ctypes.sizeof(data) + for i in range(len): + data[i] = i + assert(desock.write(fd, data, len) == len) + os.lseek(fd, 0, 0) + data = (ctypes.c_char * 5)() + len = ctypes.sizeof(data) + assert(desock.read(fd, data, len) == len) + for i in range(len): + assert(data[i][0] == i) + desock.close(fd) + +def test_recvfrom(): + # AF_INET + with helper.StdinPipe() as pipe: + pipe.write(b"12345") + pipe.close() + data = (ctypes.c_char * 128)() + sockaddr = desock.sockaddr_in() + sockaddr_len = ctypes.c_int(ctypes.sizeof(sockaddr)) + s = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + desock.connect(s, None, 0) + assert(desock.recvfrom(s, data, 128, 0, sockaddr, sockaddr_len) == 5) + desock.close(s) + assert(data.value == b"12345") + assert(sockaddr.sin_family == desock.AF_INET) + assert(sockaddr.sin_port == 53764) + assert(sockaddr.sin_addr == 0x100007f) + + # AF_INET6 + with helper.StdinPipe() as pipe: + pipe.write(b"12345") + pipe.close() + data = (ctypes.c_char * 128)() + sockaddr = desock.sockaddr_in6() + sockaddr_len = ctypes.c_int(ctypes.sizeof(sockaddr)) + s = desock.socket(desock.AF_INET6, desock.SOCK_STREAM, 0) + desock.connect(s, None, 0) + assert(desock.recvfrom(s, data, 128, 0, sockaddr, sockaddr_len) == 5) + desock.close(s) + assert(data.value == b"12345") + assert(sockaddr.sin6_family == desock.AF_INET6) + assert(sockaddr.sin6_port == 53764) + assert(sockaddr.sin6_flowinfo == 0) + assert(sockaddr.sin6_scope_id == 0) + assert(bytes(sockaddr.sin6_addr) == bytes([0] * 15 + [1])) + +def test_readv_with_data(): + n = None + bufs = 1 + buf_len = 1 + iov = helper.create_iovec(bufs, buf_len) + input = [b"Y"] + + with helper.StdinPipe() as pipe: + pipe.write(b"".join(input)) + fd = desock._debug_instant_fd(0) + n = desock.readv(fd, iov, bufs) + + assert(n == bufs * buf_len) + + for i in range(bufs): + assert(iov[i].iov_len == buf_len) + assert(iov[i].iov_base[:buf_len] == input[i]) + +def test_readv_without_data(): + iov = helper.create_iovec(1, 0) + fd = desock._debug_instant_fd(0) + n = desock.readv(fd, iov, 1) + assert(n == 0) + +def test_readv_without_desock(): + data = b"test123" + + def handle_connection(fd): + nonlocal data + iov = helper.create_iovec(1, len(data)) + n = desock.readv(fd, iov, 1) + assert(n == len(data)) + assert(iov[0].iov_base[:len(data)] == data) + + helper.interact_with_real_server(handle_connection, data) + +def test_recvmsg_with_data(): + n = None + bufs = 10 + buf_len = 10 + opt_buf_len = 50 + input = [] + + for i in range(bufs): + input.append(bytes([65 + i] * buf_len)) + + iovs = helper.create_iovec(bufs, buf_len) + msghdr = helper.create_msghdr(iov=iovs) + + with helper.StdinPipe() as pipe: + pipe.write(b"".join(input)) + fd = desock._debug_instant_fd(0) + n = desock.recvmsg(fd, msghdr, 0) + + assert(n == bufs * buf_len) + assert(msghdr.msg_iovlen == bufs) + assert(msghdr.msg_flags == 0) + + for i in range(bufs): + assert(msghdr.msg_iov[i].iov_len == buf_len) + assert(msghdr.msg_iov[i].iov_base[:buf_len] == input[i]) + +def test_recvmsg_without_data(): + msghdr = helper.create_msghdr() + fd = desock._debug_instant_fd(0) + n = desock.recvmsg(fd, msghdr, 0) + assert(n == 0) + +def test_recvmsg_without_desock(): + data = b"test123" + + def handle_connection(fd): + nonlocal data + iov = helper.create_iovec(1, len(data)) + msghdr = helper.create_msghdr(iov=iov) + n = desock.recvmsg(fd, msghdr, 0) + assert(n == len(data)) + assert(msghdr.msg_iov[0].iov_base[:len(data)] == data) + + helper.interact_with_real_server(handle_connection, data) + +def test_recvmmsg_with_data(): + entries = 5 + bufs = 10 + buf_len = 2 + opt_buf_len = 50 + n = None + input = [] + tmp = [] + + for i in range(entries * bufs): + input.append(bytes([65 + i] * buf_len)) + + for i in range(entries): + iov = helper.create_iovec(bufs, buf_len) + msghdr = helper.create_msghdr(iov=iov) + tmp.append(helper.create_mmsghdr(msghdr)) + + mmsghdrs = (desock.mmsghdr * entries)(*tmp) + + with helper.StdinPipe() as pipe: + pipe.write(b"".join(input)) + fd = desock._debug_instant_fd(0) + n = desock.recvmmsg(fd, mmsghdrs, entries, 0, None) + + assert(n == entries) + + for i in range(entries): + assert(mmsghdrs[i].msg_len == bufs * buf_len) + + assert(mmsghdrs[i].msg_hdr.msg_iovlen == bufs) + assert(mmsghdrs[i].msg_hdr.msg_flags == 0) + + for j in range(bufs): + assert(mmsghdrs[i].msg_hdr.msg_iov[j].iov_len == buf_len) + assert(mmsghdrs[i].msg_hdr.msg_iov[j].iov_base[:buf_len] == input.pop(0)) + + assert(len(input) == 0) + +def test_recvmmsg_without_data(): + mmsghdr = helper.create_mmsghdr(helper.create_msghdr()) + fd = desock._debug_instant_fd(0) + n = desock.recvmmsg(fd, mmsghdr, 0, 0, None) + assert(n == 0) + assert(mmsghdr.msg_len == 0) + +def test_recvmmsg_without_desock(): + data = b"test123" + + def handle_connection(fd): + nonlocal data + iov = helper.create_iovec(1, len(data)) + msghdr = helper.create_msghdr(iov=iov) + mmsghdr = helper.create_mmsghdr(msghdr) + n = desock.recvmmsg(fd, mmsghdr, 1, 0, None) + assert(n == 1) + assert(mmsghdr.msg_hdr.msg_iov[0].iov_base[:len(data)] == data) + + helper.interact_with_real_server(handle_connection, data) + +def test_recvmsg_name(): + iov = helper.create_iovec(1, 16) + namelen = ctypes.sizeof(desock.sockaddr_in()) + msg = helper.create_msghdr(iov=iov, namelen=namelen) + s, c = helper.get_fake_connection(desock.AF_INET, desock.SOCK_STREAM) + + with helper.StdinPipe() as pipe: + pipe.close() + assert(desock.recvmsg(c, msg, 0) == 0) + + assert(msg.msg_namelen == namelen) + name = bytes(msg.msg_name[:namelen]) + sin_family = int.from_bytes(name[:2], "little") + assert(sin_family == desock.AF_INET) + sin_port = int.from_bytes(name[2:4], "little") + assert(sin_port == 53764) + sin_addr = int.from_bytes(name[4:8], "little") + assert(sin_addr == 0x100007f) + + desock.close(s) + desock.close(c) diff --git a/tests/test_select.py b/tests/test_select.py new file mode 100644 index 0000000..733c02c --- /dev/null +++ b/tests/test_select.py @@ -0,0 +1,115 @@ +""" +This file tests the select() functionality. + +Target files: + - libdesock/src/select.c +""" + +import ctypes + +import helper +import desock + +def test_invalid(): + s = desock.socket(desock.AF_INET, desock.SOCK_DGRAM, 0) + s1 = desock.dup2(s, desock.FD_TABLE_SIZE) + rfds = desock.fd_set() + desock.FD_ZERO(rfds) + desock.FD_SET(s1, rfds) + wfds = desock.fd_set() + desock.FD_ZERO(wfds) + desock.FD_SET(s1, wfds) + assert(desock.select(s1 + 1, rfds, wfds, None, None) == 0) + desock.close(s1) + desock.close(s) + assert(not desock.FD_ISSET(s1, rfds)) + assert(not desock.FD_ISSET(s1, wfds)) + +def _check_return_val(n, r, w, e): + s = 0 + for i in range(desock.FD_SETSIZE): + s += int(desock.FD_ISSET(i, r)) + s += int(desock.FD_ISSET(i, w)) + s += int(desock.FD_ISSET(i, e)) + assert(s == n) + +def _read(fd): + buf = ctypes.create_string_buffer(1024) + n = desock.recv(fd, buf, ctypes.sizeof(buf), 0) + return buf[:n] + +def _simulate_server(s, method, *args): + input = b"" + output = ctypes.create_string_buffer(b"fuck off") + run = True + client = None + nfds = s + 1 + read_fds = desock.fd_set() + write_fds = desock.fd_set() + error_fds = desock.fd_set() + + desock.FD_ZERO(read_fds) + desock.FD_ZERO(write_fds) + desock.FD_ZERO(error_fds) + + desock.FD_SET(s, read_fds) + desock.FD_SET(s, error_fds) + + while run: + tmp_r_fds = desock.fd_set() + tmp_w_fds = desock.fd_set() + tmp_e_fds = desock.fd_set() + desock.FD_COPY(tmp_r_fds, read_fds) + desock.FD_COPY(tmp_w_fds, write_fds) + desock.FD_COPY(tmp_e_fds, error_fds) + + n = method(nfds, tmp_r_fds, tmp_w_fds, tmp_e_fds, *args) + _check_return_val(n, tmp_r_fds, tmp_w_fds, tmp_e_fds) + + for i in range(desock.FD_SETSIZE): + if desock.FD_ISSET(i, tmp_r_fds): + if i == s: + client = desock.accept(s, None, None) + desock.FD_SET(client, read_fds) + desock.FD_SET(client, write_fds) + desock.FD_SET(client, error_fds) + nfds = max(nfds - 1, client) + 1 + elif i == client: + b = _read(client) + if b: + input += b + else: + desock.FD_CLR(client, read_fds) + run = False + else: + assert(False) + + if desock.FD_ISSET(i, tmp_w_fds): + if i == s: + assert(False) + elif i == client: + desock.send(client, output, ctypes.sizeof(output) - 1, 0) + desock.FD_CLR(client, write_fds) + else: + assert(False) + + if desock.FD_ISSET(i, tmp_e_fds): + assert(False) + + desock.close(client) + return input + +def test_select(): + data = b"test123456" + for method, args in [(desock.select, [None]), (desock.pselect, [None, None])]: + for domain in helper.all_domains: + for type in helper.all_types: + with helper.StdinPipe() as in_pipe, helper.StdoutPipe() as out_pipe: + in_pipe.write(data) + in_pipe.close() + s = desock.socket(domain, type, 0) + desock.bind(s, None, 0) + desock.listen(s, 10) + assert(_simulate_server(s, method, *args) == data) + assert(out_pipe.read(8) == b"fuck off") + desock.close(s) diff --git a/tests/test_sendfile.py b/tests/test_sendfile.py new file mode 100644 index 0000000..2792443 --- /dev/null +++ b/tests/test_sendfile.py @@ -0,0 +1,29 @@ +""" +This file tests the sendfile() and sendfile64() functionality. + +Target files: + - libdesock/src/sendfile.c +""" + +import os +import ctypes +import tempfile + +import helper +import desock + +def test_sendfile(): + offset = ctypes.c_long(0) + data = b"hello motherfucker" + s, c = helper.get_fake_connection(desock.AF_INET, desock.SOCK_STREAM) + assert(desock.sendfile(c, -1, offset, len(data)) == len(data)) + desock.close(c) + desock.close(s) + +def test_sendfile64(): + offset = ctypes.c_long(0) + data = b"hello motherfucker" + s, c = helper.get_fake_connection(desock.AF_INET, desock.SOCK_STREAM) + assert(desock.sendfile64(c, -1, offset, len(data)) == len(data)) + desock.close(c) + desock.close(s) diff --git a/tests/test_standard.py b/tests/test_standard.py new file mode 100644 index 0000000..7ac5c85 --- /dev/null +++ b/tests/test_standard.py @@ -0,0 +1,69 @@ +""" +This file tests the standard way of creating a server: + 1. socket() + 2. bind() + 3. listen() + 4. accept() +in all possible combinations of socket domains and types. + +Target files: + - libdesock/src/socket.c + - libdesock/src/bind.c + - libdesock/src/listen.c + - libdesock/src/accept.c +""" + +import sys +import ctypes +import random +import os + +import helper +import desock + +def read_from_socket(fd): + buf = ctypes.create_string_buffer(256) + desock.read(fd, buf, 256) + return buf.value + +def test_standard(): + data = b"test123" + with helper.StdinPipe() as pipe: + for domain in helper.all_domains: + for type in helper.all_types: + s, c = helper.get_fake_connection(domain, type) + pipe.write(data) + + assert(read_from_socket(c) == data) + + desock.close(c) + desock.close(s) + +successful = 0 + +def _handle_connection(fd, data): + global successful + buf = ctypes.create_string_buffer(len(data)) + n = desock.read(fd, buf, len(data)) + m = desock.write(fd, buf, n) + desock.close(fd) + + assert(n == len(data)) + assert(m == len(data)) + assert(buf.raw == data) + + successful += 1 + +def test_multithreaded(): + with helper.StdinPipe() as pipe, helper.ThreadPool() as pool, helper.NoStdout(): + s = desock.socket(desock.AF_INET, desock.SOCK_STREAM, 0) + desock.bind(s, None, 0) + desock.listen(s, 0) + + for _ in range(10): + c = desock.accept(s, None, None) + data = os.urandom(random.randint(20, 50)) + pipe.write(data) + pool.spawn(_handle_connection, args=[c, data]) + + assert(successful == 10) diff --git a/tests/test_write.py b/tests/test_write.py new file mode 100644 index 0000000..65870cd --- /dev/null +++ b/tests/test_write.py @@ -0,0 +1,62 @@ +""" +This file tests that sendmmsg works correctly. + +Target files: + - libdesock/src/write.c +""" + +import ctypes + +import desock +import helper + +data = bytes(range(65, 115)) +cursor = 0 +def _get_data(size): + global cursor + ret = bytes(data[cursor: cursor + size]) + assert(len(ret) == size) + cursor += size + return ret + +def test_sendmmsg(): + fd = desock._debug_instant_fd(0) + + assert(desock.sendmmsg(fd, None, 0, 0) == 0) + + mmsghdrs = (desock.mmsghdr * 2)() + mmsghdrs[0] = helper.create_mmsghdr(helper.create_msghdr(iov=helper.create_iovec(5, 5, datafunc=_get_data))) + mmsghdrs[1] = helper.create_mmsghdr(helper.create_msghdr(iov=helper.create_iovec(5, 5, datafunc=_get_data))) + + with helper.StdoutPipe() as pipe: + assert(desock.sendmmsg(fd, mmsghdrs, 2, 0) == 2) + assert(pipe.read(50) == data) + +def test_sendto(): + data = ctypes.create_string_buffer(bytes(range(128))) + fd = desock._debug_instant_fd(0) + + with helper.StdoutPipe() as pipe: + assert(desock.sendto(fd, data, 128, 0, None, 0) == 128) + assert(pipe.read(128) == data[:128]) + +def test_sendmsg(): + global cursor + cursor = 0 + msghdr = helper.create_msghdr(iov=helper.create_iovec(5, 10, datafunc=_get_data)) + fd = desock._debug_instant_fd(0) + + with helper.StdoutPipe() as pipe: + assert(desock.sendmsg(fd, msghdr, 0) == 50) + assert(pipe.read(50) == data) + +def test_writev(): + global cursor + cursor = 0 + iov = helper.create_iovec(5, 10, datafunc=_get_data) + fd = desock._debug_instant_fd(0) + + with helper.StdoutPipe() as pipe: + assert(desock.writev(fd, iov, 5) == 50) + assert(pipe.read(50) == data) + \ No newline at end of file