From 9f23f04c3792ce4c64fec9f1b8116e0586f50ce0 Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Mon, 3 Apr 2017 09:05:29 -0500 Subject: [PATCH] Rewrite of Ruby script into C. To my eye, it's much cleaner. :-) There are still a few things that need to be added, like status of monitored processes, and reading/parsing of inittab to make it a true drop in replacement for SysV init, but this is pretty close as it is. --- Makefile | 5 + README | 5 + init-ng | Bin 0 -> 19640 bytes init-ng.c | 387 +++++++++++++++++++++++++++++++++++++++++++++ init => init-ng.rb | 0 5 files changed, 397 insertions(+) create mode 100644 Makefile create mode 100755 init-ng create mode 100644 init-ng.c rename init => init-ng.rb (100%) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..561f3c3 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +# Doesn't need to be more complex than this + +init-ng: init-ng.c + gcc -std=c99 -g init-ng.c -o init-ng + diff --git a/README b/README index be745eb..7f5e224 100644 --- a/README +++ b/README @@ -32,6 +32,11 @@ HOW TO INSTALL/USE IT Once you have rebooted successfully and logged in as root, typing 'init' on the command line will display the commands that init-ng understands. +It is also possible to leave the existing init in place without renaming it; in +this case you would rename the new init to something else, such as init-ng. +Then, on your kernel boot command line, you would add "init=/sbin/init-ng" +(without the quotes) to have the kernel use it instead of your current init. + CREDITS ------- diff --git a/init-ng b/init-ng new file mode 100755 index 0000000000000000000000000000000000000000..dcd7ff3fc95c0f6d5e4a6770b6d06136e6399d75 GIT binary patch literal 19640 zcmeHveSB2ang6*nndDC1Ap`eIl&dcP^ zkoooV`Tenf^@O?4d0x+R&Uwzc_ndn!f97soZ__lUl8xQW2x}{Lagw+)wrU+mC2bYc znTyr38kP@=13wq%5EMBDPe{`W>Qc@Qm`8b=B-mUcBVo0`n1aeff>hpAa>=ZKZ_XE} zf{YoQKzih>L;*VqOGBL;LK@gEpb{kaNUzEe^eU;R;At|9q@b!F)s24DvVPSz7cjzI z1g6~Jm~0E=+s?=Rq}M)IFxuz3ct*kd1eqzw+Yq!*L66r@^8XkpmjVr;;Et8oHH7@j zLcwri_p;rqRxVq4U41N4zk>Tua#Y0)w{PJZsyz&jF*XCR20z(+>`LTI@N?oo+$9P}^eps&n9-=Bm2Vh;L0=b$ghLI0N=^r0N|S8~uBa?lUw zpi_TO*KW7xpzq8f`A3*Fj}Pgv-5UsLHR3!Uz1 zDm`PN)BR4R=PY!(FRFCHLRa@G;=N*_t9vNXPh03T=c;tZLRa@W;+?b5t@qrNg>Jnc zPFU!4Z&%4PctQ6JJN|Z#!8}7J;*M0a#+YaDW&I^3A>icok3eK{(O=+NR^vjB@E&50 zots2j^jX58%*IZ0{6WHLD2$!p_+G+k2#h_$@hIUG`eRRU{4<18$d4W3_zuD;)W-%m z{%OJ~#K-zLzKL)O?Xgad-%2=z^jI6m*Ah;lJm%u~YQiam#~L}lf^Z7mF@xhv2&a%8 zE9ZDE;S{Q4jN|hNrw|>R_!xvmGYO~A96QJHLc%E|$4+zHMmUAy*a?pRel~Cl!LesJ z{vP2JdSg#;{B6Q1(bnEFdg8=v7xRq1 z(8v)NxsHoBZP-EmbA$WReZPE;!lUCQ(#2>hPwv0O)jY#_ zKOVS_T4OZz+NH_KDPp@I{y-5&MFC`H*f9*VgDLGs_oYPHuw%c#l8!hsr&Jk@@X?b@ zobx2NoKe2cvHCiAaWY{WFB6VZ!;quD5)xZ3Bxmsod4}C*$hp`5FgfW-z9{@l&Js=! zyJ3Aa^=vk;y^{?)-m2sl$-%S84xZ4Gj-MeT9em(IBgTa%`TUu8V0ri;2M32HfE}B} z2=XLfBikQ-G&y{va^V3-9L z5AHw9;swXvf)C@4V<~cF*bT9hBjd>P*hzgA?t{vk$$_p*eG_FS-IoUUUt)>?=NaCZqN*fc zgRu#84UnmtSc2jh&BMp3q9YVlslS3P<(h4LH;SB0%u8+kJuI-ni-m|4|HvoFuOSGI zZyt6mtKbb`8{dE;P}slox?LRHe{nL7j<`r&P|PDmB4}EK1}|53@7FLnfC=T_KzS?( zKhnOIkGQC`0yuDtygY6K9qA*QA8K$F#R?9wVdHFCbXQvRhUrEBJ}o+w7A>7#^dX3* zoib?TI~rzU&On)>^heVc{t3+uzYb+P)(jIgSl=3X5?Z3`-uaNKej)k7F=os#jz9gY zUw=IE%{2FQaAlznTsQ`2s2-g6PNa zCFy>DaR2+0iQj2hZ@cM1krL-~jc>!(aeK?mNh(t7PCN zn0)@if0EX-=KxZ-fQ|AIJzCj;3s4^9Y_06`{|E#{kre#JlL$LL0Vk-~uR;l9u_KH9 zp=9q9?3=ULT9we=F4#3$?0m^y!`X?dOg0ru@i*R-Nk3j9)$)Z}@yOYa7c{3{Mo5g$ z9+?Sd>ZaczUpTUu@{PzpM_oAfGM;}@I>a!?5n=q(!-)o;lHU)8Ki4qkO%4n&F+#%vHHG<)l z^8Yrqw;o*du+zXJ+rec7H@9AMe)%tHHIe$}f1x%n{J|cdi|4G?pXi?K5t*=59g0!CLP6pHMkhLj?))rK;= z)R1S=(->6*_t2Mf!kzVNy51G3+^U4{0 zA+Imc6AAeP(GF79=G$-F4Oog_@w=0gF9TkBZ*uZ40N+E9)19myL!=l}`y+r$0k6eS zY6bjPz!2a!Fj0ICa5Dz|w*gat{{+~9IsF1)BW}ROxJwk{Cb1MS1Q-XTxr~ywcN5cg zmuvHj3-m);K{?TB(bfq+mXLr<)5|lq5PXt%O-xQspgdMuzP_~T*0Q2q`T)CS-i=GH zU06#dNCwL!_A%_8*tc$)t= zp#K~A-^$?sZJPfw=s~pOs~P+sr}=M!UV(P~b_V|&X?`B+cLe+|W$+KB`3u3Hh5krn z@cYvIb>IiV|5*nAwKU%kel_~hpGY zsc|sRUAp*l4o_+0L;0T4Rf7dBrLLaRRZXRhO{I(1mKtkIt02F&ROkIp@i75A0Dnq< zYJoqsz@J*+kG6nO;u10nN)0uKC|E4%s|tm@+M|DYw!qVS(%3Ger1qTY9zbcH08E#B zn)fLwex5*?%jV)a^$uggA#nBXLbnT?HfSk*BmjS}OW7)kS4yY=O}&&R7IbomTP07Y zWk%fx)w_^6lHXI{;yFccleqF*mFJZ53dh55gh-829xGsutMb&}A4r&AEX$YhDhXFgxL(5S`fq4%UTrL1p9sez5#zf08|trJ7QOZw zkz-3CE#gGydh6w2ndi(lBk<3GE&^KD{sScK6@(u>bxo&e)AX~53Y)DUgfeV-1qK1V zU_JpY|5u#ns0Fa+Iq=dGJVyuY<^7BV_TLDzd0|{^LwC_tFZdKu@ME?=r?=Yqc>o)ej=8>yBGj0CPS=q*f}MIq7lDu`z&a z9@EPmpE5~c7Fpd)R+;lL5@@GE%F}Sk-?9v5^7U(REx#F;8QfN>UQkT|Uh*8Q71Y#H)=Sw1 zyOCw(Q6)Kp=XmSn>*P_sPI@!_kb113>W9cXZ^EUZj*K(sf1}KTPy7T~-T58L*Hd{9 zI~z%6`Hyft#47T2(!&_r%0a&v(ajmB&Su*fu^mp2zh(u+o)q+nP<=WhrdMAF>dc=)pxpVD_24*nBJcbf*=9~Zj5r@B zvW*qesJ#jh3$NHmO233)VU1AwC6#6nSt<=HrJZc{Lttu4sG@4};mb7O z+T;HMxjA&&LtFAV2)4u9t2WB1tsXd~xk08aC2iZ`5bokT;evLM4n0zAlTY=H2p~Fw}!SqzOR#={KYj1sNsn@lz;OsJ@Z*@V`j**Eh{@ahU|alB^xi zLvwt+h@4+b4~6DiY0X`v`MbZDntW-@OQBcsLi2Z`H&XXkzeJo5Db($UC+?q%e*C?# z8mgf)J(@$4-q*xdFfCtVerDW9inBOQFP16sMK+-JcpNwD1+;xGCG3aKb}ZOPkv2;s zp8fFYjv5{&v$eefkJMhGc247F4ezlzny6M!?J`nduL)Pr-BZgwSNKFn4P4)#(Y$Os z>=(XolHPXK9jS1Efvp05#St8oS%W}aB_%?vYH_8DGnd0_N;Pq&`8nHu_yVk>_5o>r zdkq>UCRMl6+(*sH=Zs+(7SUTE2www%Pa?&v`Y2U!{xhIB?Puh}`$E#FE`+{TO)c%T z57c!65|N_t3PC(j*GV*1-HnTO<^8baw4bQ!1P0=_$#9L3+`3Q@3#r}cDM`3vXVvRL z&6>`O7R@cUOFXTG9{0VwK*0`W#H(_f$~c2 z>bYcRh68qR*Qm&_Qc=mS#D`oMFwzFv!YkNQ6N{u!~)OlgboAh%}qJi`$oIiAVGbEEsHCaMAK_ z&HwJU>z~$d({FqK=jX52mrLd+6!X0PwEmr^&#%-M>Zfi?=w}-BZvFfF^a^`%z20zy zOLdVoEHLu&w&v@f{^5b(Hr;ikzenG;y<2ZxV|Ui;EA(J@L(dNzkE}S-_^Q36%eJKA z=(g(zpMb5KQ>XMHz5hq*-%(Pf`q{SIY={KY#F10qP7`lEdJ=JZA+#>C3vY++ zXui!{w_#J$MrKlXqU#%aBE5lzSdX_i5o?G=5>a1(-kH<89@ZC)_yVyQUK616_Xens zSgSV?_Vuusmkh{bsiuiL2+A_OQLw}**dQHGrS~mnq7MgWnYlBFldiF#8R^FBW(jVHo^HQj-5AR6=mC70HS1OLXdZetn3d5!Oe8_+J1XdLg2aMo7T60ew;hnKy% zWka*4bsdh`q9k8W$e(UZ`8o}+kMNeuB!8l86a4HC2v7KnDjw2Q8xys}$>Gi3ew_VP zXMIr-Uj(Z%FmTrgwu9b30n$wv07Zr)EWj%Uq$?N*`EeB3Yj$~igP}cW^^ zgBMA>88@xl$Tp*+c_(|L-9F*FY)XoPpxNbTp$Oh*@k`nUH2|GQ=3T>`-T`;Wi$1&o zW3UyY3l2l`Mi-{|F=q0~?~Qw9OJ-O!`@AqhRxo2ghda61{i(L5=G)xuu!a6J>G{qy zsVAv+AumcY={U5A1e}t_OFZt0cwJ~x98md*uxtw!_VR$>QxS2zIDsA8Nd@y`*L+fu z4b*fOwLx6AF^?qfl=8@H(mOr8DJ7raw}|X?Fsk>2Q!PjhM^oTb*RYM=oq?ukccK@) z*NS4#>zR8VIIyEnof*2yGe;?_g zKD@(1u^lRgZ>I*q)7}c+ZWOuFOktM~5-Ls3BVXFW{UqsSN?Z?_^i zK3^XVguJ96bA5OxTTc~a_3^-NT)TjP7vWJ=ALuc=qNtDAgLxs12@Om%QSTn1q4J;c zK@8S0OnfLB4M~@JUW%}|BNk)z)RX8Rhz52fx}oe1cLzWhDDP3l+OZ=V=vN$k8xT-= zGz{G*|DVZDw@;hvG8sE=rPb5Y?dg4CtCF2Ij_lLfaWJ)SoGG8rrrU3|vx4+KZKk}= z)P8R!-H8*$)0JDu)c$y;d=cv`oKC(t{heK=dY4OXc3M8NXVS~?z1Vd2%h~B^ z={UJ#bXraDyd7VpsQq~>(~d70=ooBvvg57ebo zzKXf(rlY6dHdxKzkx9K}$RLA0Ka(IaEJt$CugF2a@-jLi8BzG|WHtj2{fP2Xrj}TE zAm@n=W^33{9H{H$IF?sD)!|BXwZ>BPPe}TSx=!SwbD}ZYb9N+t+4IJ z(?&&?t0`s(`c_4k3o1qTE4o@kVRfX^boC8#=8VhYXD{g5G;uO0<+J1PQ7(UZoY3aT zOzd`^knyi^ea3#o=@PL3diI}b!BzGgrx#zg8TKxxE2$}1hJvQEQNQE`RwvLnj2M^XIi3^m94r z@8_WFSS?LwpWb#%M{meMcjutf1}fDzdp^0B%NMikt*pH{?0h~4{jWhcGFnm~-vxb! z4I2w}of+H_qGKLV^R^nNv`tU(oV}I$3rX*kao!=Vz0K(vraAI4=;bt@+}D}GwA+RK z>MTPkYj>}}{La>zfMgZ?V$)W6y7^9JbC`9qsk)3rk$0)YI<-byaw z^vjwJZx|mOowd6_JT& z_+VT-d7AW{r@3z1?M)k7nz4AWaIgZ#+bDBG>m6>FpDwuixx$H`|-mwz^FS@()LS zv4qK=d&v`*%lauNeS?}wxoka={Y7b}xcHzolP14T%_N#F?Hf%T>_oQRFdB@XA(2FL0V{u zCcb^n6fr4*VD*~kT)Z?$R^GWdO8DIIY)}iYE z5lKk~l|jBMee87ebPKMyMWprBdUb*nkUkP1ea)`_25{(1kt$!UYcJp>9;KTFNc*qk z6l@2d&L}Bdol|P0Mny9CRkV@Se@SLOWT-8azFH@@NqtpM)n3{4@0I#%r9rix=3nZ9 zrp{%NKDBeU{w~nSFInC6x_cG9#X`zn2`WDXm$4`^R(-WT@09xd%(D^(l*_0z+@Gbd zo~PQ1h0?v!jxwS26+W1yuh#o7(*hC6DM0#~?SB#+@?W*TdcHg@^&e0SX+gE0GI%&k zU+o{L|99p-B`9Hb`A4$!)jq>%xip{kN6P;u^zrVEj{#nU(a8Zb1jzO`8-EsJW%$t; zqNMgMbc3VmcoEoC{3!edWT^d=zS`d?H-toXdD-|$h*9h*eYFo#CH3j72PHY2)BdP9 z_-F8}<*WUY)B>)SmKWHR|H_a5lclfDHBKmfS$-~kI>}`%U#*ue)(Q>fXSTk={~a0f zMb+O`*9i=?Iu4j?n}F)-QW*(TfK+~C7G3FQ@4%?)C`jvdmA9H$B+JjXdzmZx&EtL_WbywjDRq8lU9tvUP`T*m$f DaNKg^ literal 0 HcmV?d00001 diff --git a/init-ng.c b/init-ng.c new file mode 100644 index 0000000..3b969be --- /dev/null +++ b/init-ng.c @@ -0,0 +1,387 @@ +// +// Init-NG +// +// A minimal, drop-in replacement for SysV init. +// This leverages OpenRC to do most of the heavy lifting, and does the minimum +// amount that it should--unlike other so-called inits, that have world + +// kitchen sink thrown in, seemingly to enlarge the attack surface. ;-) +// +// by James Hammons +// (C) 2017 Underground Software +// + +#define _GNU_SOURCE // Without this, functions in unistd.h go missing +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char socketPath[] = "/run/initctl"; +static int shuttingDown = 0; +static int verbose = 0; // N.B.: There is no mechanism to set this ATM +static struct sigaction action; +static int freeProcessSlot = 0; +static pid_t processPID[1024]; +static char * processCmd[1024]; +static char * processName[1024]; +static char * args[256]; // 256 arguments ought to be enough for anybody ;-) + + +// +// Find a process in the monitored process list (MPL) by PID. Returns the index +// of the entry in the MPL. +// +int FindMonitoredPID(pid_t pid) +{ + for(int i=0; i 1) + { + if ((strcmp(argv[1], "poweroff") == 0) + || (strcmp(argv[1], "restart") == 0) + || (strcmp(argv[1], "halt") == 0) + || (strcmp(argv[1], "status") == 0)) + { + DoCmd(argv[1]); + } + else if (strcmp(argv[1], "test") == 0) + { + ShutDown(LINUX_REBOOT_CMD_POWER_OFF); + } + else + printf("Invalid command\n"); + } + else + printf("Usage: poweroff, restart, halt, status, test\n"); + + return 1; + } + + // We are PID EINS, so start the system using OpenRC... + Init(); + + // Launch TTYs... + // N.B.: To be a drop in replacement for SysV init, we really should read + // and parse the entries in /etc/inittab; at least the c entries... + for(int i=1; i<=6; i++) + { + sprintf(buf, "agetty%i", i); + sprintf(buf2, "/sbin/agetty tty%i --noclear", i); + Launch(buf, buf2, 1); + } + + // Install SIGCHLD signal handler to do process monitoring + memset(&action, 0, sizeof(action)); + action.sa_sigaction = HandleSIGCHLD; + action.sa_flags = SA_SIGINFO; + sigaction(SIGCHLD, &action, NULL); + + // Create socket to listen on for commands... + struct sockaddr_un local, remote; + unsigned int s = socket(AF_UNIX, SOCK_STREAM, 0); + + if (s == -1) + { + perror("socket"); + printf("init-ng: socket() failed!\n"); + } + + local.sun_family = AF_UNIX; + strcpy(local.sun_path, socketPath); + unlink(local.sun_path); + int len = strlen(local.sun_path) + sizeof(local.sun_family); + + if (bind(s, (struct sockaddr *)&local, len) == -1) + { + perror("bind"); + printf("init-ng: bind() failed!\n"); + } + + // Queue size of 20 ought to be enough for anybody ;-) + if (listen(s, 20) == -1) + { + perror("listen"); + printf("init-ng: listen() failed!\n"); + } + + // Main loop for PID 1. All commands are received and acted upon from here. + while (1) + { + int t = sizeof(remote); + unsigned int s2 = accept(s, (struct sockaddr *)&remote, &t); + + if (s2 == -1) + { + // Check to see if the signal handler blew things up on us + if (errno == EINTR) + continue; + + // An unanticipated error occurred, handle it + perror("accept"); + printf("init-ng: accept() failed!\n"); + } + + // Get the message from the socket + int n = recv(s2, buf, 2048, 0); + buf[n] = 0; + + if (verbose) + printf("PID1: Received \"%s\" from socket...\n", buf); + + // Now do something with it... + if (strcmp(buf, "poweroff") == 0) + { + ShutDown(LINUX_REBOOT_CMD_POWER_OFF); + } + else if (strcmp(buf, "restart") == 0) + { + ShutDown(LINUX_REBOOT_CMD_RESTART); + } + else if (strcmp(buf, "halt") == 0) + { + ShutDown(LINUX_REBOOT_CMD_HALT); + } + else if (strcmp(buf, "status") == 0) + { + printf("[Status placeholder]\n"); + } + + close(s2); + } + + // We should never get here... + return 0; +} + diff --git a/init b/init-ng.rb similarity index 100% rename from init rename to init-ng.rb -- 2.37.2