chpst.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. Copyright (c) 2001-2006, Gerrit Pape
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions are met:
  6. 1. Redistributions of source code must retain the above copyright notice,
  7. this list of conditions and the following disclaimer.
  8. 2. Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in the
  10. documentation and/or other materials provided with the distribution.
  11. 3. The name of the author may not be used to endorse or promote products
  12. derived from this software without specific prior written permission.
  13. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  14. WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  15. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  16. EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  17. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  18. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  19. OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  20. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  21. OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  22. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
  25. /* Dependencies on runit_lib.c removed */
  26. #include "busybox.h"
  27. #include <dirent.h>
  28. // Must match constants in chpst_main!
  29. #define OPT_verbose (option_mask32 & 0x2000)
  30. #define OPT_pgrp (option_mask32 & 0x4000)
  31. #define OPT_nostdin (option_mask32 & 0x8000)
  32. #define OPT_nostdout (option_mask32 & 0x10000)
  33. #define OPT_nostderr (option_mask32 & 0x20000)
  34. static char *set_user;
  35. static char *env_user;
  36. static const char *env_dir;
  37. static long limitd = -2;
  38. static long limits = -2;
  39. static long limitl = -2;
  40. static long limita = -2;
  41. static long limito = -2;
  42. static long limitp = -2;
  43. static long limitf = -2;
  44. static long limitc = -2;
  45. static long limitr = -2;
  46. static long limitt = -2;
  47. static int nicelvl;
  48. static const char *root;
  49. static void suidgid(char *user)
  50. {
  51. struct bb_uidgid_t ugid;
  52. if (!uidgid_get(&ugid, user)) {
  53. bb_error_msg_and_die("unknown user/group: %s", user);
  54. }
  55. if (setgroups(1, &ugid.gid) == -1)
  56. bb_perror_msg_and_die("setgroups");
  57. xsetgid(ugid.gid);
  58. xsetuid(ugid.uid);
  59. }
  60. static void euidgid(char *user)
  61. {
  62. struct bb_uidgid_t ugid;
  63. if (!uidgid_get(&ugid, user)) {
  64. bb_error_msg_and_die("unknown user/group: %s", user);
  65. }
  66. xsetenv("GID", utoa(ugid.gid));
  67. xsetenv("UID", utoa(ugid.uid));
  68. }
  69. static void edir(const char *directory_name)
  70. {
  71. int wdir;
  72. DIR *dir;
  73. struct dirent *d;
  74. int fd;
  75. wdir = xopen(".", O_RDONLY | O_NDELAY);
  76. xchdir(directory_name);
  77. dir = opendir(".");
  78. if (!dir)
  79. bb_perror_msg_and_die("opendir %s", directory_name);
  80. for (;;) {
  81. errno = 0;
  82. d = readdir(dir);
  83. if (!d) {
  84. if (errno)
  85. bb_perror_msg_and_die("readdir %s",
  86. directory_name);
  87. break;
  88. }
  89. if (d->d_name[0] == '.') continue;
  90. fd = open(d->d_name, O_RDONLY | O_NDELAY);
  91. if (fd < 0) {
  92. if ((errno == EISDIR) && env_dir) {
  93. if (OPT_verbose)
  94. bb_perror_msg("warning: %s/%s is a directory",
  95. directory_name, d->d_name);
  96. continue;
  97. } else
  98. bb_perror_msg_and_die("open %s/%s",
  99. directory_name, d->d_name);
  100. }
  101. if (fd >= 0) {
  102. char buf[256];
  103. char *tail;
  104. int size;
  105. size = safe_read(fd, buf, sizeof(buf)-1);
  106. if (size < 0)
  107. bb_perror_msg_and_die("read %s/%s",
  108. directory_name, d->d_name);
  109. if (size == 0) {
  110. unsetenv(d->d_name);
  111. continue;
  112. }
  113. buf[size] = '\n';
  114. tail = memchr(buf, '\n', sizeof(buf));
  115. /* skip trailing whitespace */;
  116. while (1) {
  117. if (tail[0]==' ') tail[0] = '\0';
  118. if (tail[0]=='\t') tail[0] = '\0';
  119. if (tail[0]=='\n') tail[0] = '\0';
  120. if (tail == buf) break;
  121. tail--;
  122. }
  123. xsetenv(d->d_name, buf);
  124. }
  125. }
  126. closedir(dir);
  127. if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir");
  128. close(wdir);
  129. }
  130. static void limit(int what, long l)
  131. {
  132. struct rlimit r;
  133. if (getrlimit(what, &r) == -1) bb_perror_msg_and_die("getrlimit");
  134. if ((l < 0) || (l > r.rlim_max))
  135. r.rlim_cur = r.rlim_max;
  136. else
  137. r.rlim_cur = l;
  138. if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit");
  139. }
  140. static void slimit(void)
  141. {
  142. if (limitd >= -1) {
  143. #ifdef RLIMIT_DATA
  144. limit(RLIMIT_DATA, limitd);
  145. #else
  146. if (OPT_verbose) bb_error_msg("system does not support %s",
  147. "RLIMIT_DATA");
  148. #endif
  149. }
  150. if (limits >= -1) {
  151. #ifdef RLIMIT_STACK
  152. limit(RLIMIT_STACK, limits);
  153. #else
  154. if (OPT_verbose) bb_error_msg("system does not support %s",
  155. "RLIMIT_STACK");
  156. #endif
  157. }
  158. if (limitl >= -1) {
  159. #ifdef RLIMIT_MEMLOCK
  160. limit(RLIMIT_MEMLOCK, limitl);
  161. #else
  162. if (OPT_verbose) bb_error_msg("system does not support %s",
  163. "RLIMIT_MEMLOCK");
  164. #endif
  165. }
  166. if (limita >= -1) {
  167. #ifdef RLIMIT_VMEM
  168. limit(RLIMIT_VMEM, limita);
  169. #else
  170. #ifdef RLIMIT_AS
  171. limit(RLIMIT_AS, limita);
  172. #else
  173. if (OPT_verbose)
  174. bb_error_msg("system does not support %s",
  175. "RLIMIT_VMEM");
  176. #endif
  177. #endif
  178. }
  179. if (limito >= -1) {
  180. #ifdef RLIMIT_NOFILE
  181. limit(RLIMIT_NOFILE, limito);
  182. #else
  183. #ifdef RLIMIT_OFILE
  184. limit(RLIMIT_OFILE, limito);
  185. #else
  186. if (OPT_verbose)
  187. bb_error_msg("system does not support %s",
  188. "RLIMIT_NOFILE");
  189. #endif
  190. #endif
  191. }
  192. if (limitp >= -1) {
  193. #ifdef RLIMIT_NPROC
  194. limit(RLIMIT_NPROC, limitp);
  195. #else
  196. if (OPT_verbose) bb_error_msg("system does not support %s",
  197. "RLIMIT_NPROC");
  198. #endif
  199. }
  200. if (limitf >= -1) {
  201. #ifdef RLIMIT_FSIZE
  202. limit(RLIMIT_FSIZE, limitf);
  203. #else
  204. if (OPT_verbose) bb_error_msg("system does not support %s",
  205. "RLIMIT_FSIZE");
  206. #endif
  207. }
  208. if (limitc >= -1) {
  209. #ifdef RLIMIT_CORE
  210. limit(RLIMIT_CORE, limitc);
  211. #else
  212. if (OPT_verbose) bb_error_msg("system does not support %s",
  213. "RLIMIT_CORE");
  214. #endif
  215. }
  216. if (limitr >= -1) {
  217. #ifdef RLIMIT_RSS
  218. limit(RLIMIT_RSS, limitr);
  219. #else
  220. if (OPT_verbose) bb_error_msg("system does not support %s",
  221. "RLIMIT_RSS");
  222. #endif
  223. }
  224. if (limitt >= -1) {
  225. #ifdef RLIMIT_CPU
  226. limit(RLIMIT_CPU, limitt);
  227. #else
  228. if (OPT_verbose) bb_error_msg("system does not support %s",
  229. "RLIMIT_CPU");
  230. #endif
  231. }
  232. }
  233. /* argv[0] */
  234. static void setuidgid(int, char **);
  235. static void envuidgid(int, char **);
  236. static void envdir(int, char **);
  237. static void softlimit(int, char **);
  238. int chpst_main(int argc, char **argv)
  239. {
  240. if (applet_name[3] == 'd') envdir(argc, argv);
  241. if (applet_name[1] == 'o') softlimit(argc, argv);
  242. if (applet_name[0] == 's') setuidgid(argc, argv);
  243. if (applet_name[0] == 'e') envuidgid(argc, argv);
  244. // otherwise we are chpst
  245. {
  246. char *m,*d,*o,*p,*f,*c,*r,*t,*n;
  247. getopt32(argc, argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
  248. &set_user,&env_user,&env_dir,
  249. &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
  250. // if (option_mask32 & 0x1) // -u
  251. // if (option_mask32 & 0x2) // -U
  252. // if (option_mask32 & 0x4) // -e
  253. if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
  254. if (option_mask32 & 0x10) limitd = xatoul(d); // -d
  255. if (option_mask32 & 0x20) limito = xatoul(o); // -o
  256. if (option_mask32 & 0x40) limitp = xatoul(p); // -p
  257. if (option_mask32 & 0x80) limitf = xatoul(f); // -f
  258. if (option_mask32 & 0x100) limitc = xatoul(c); // -c
  259. if (option_mask32 & 0x200) limitr = xatoul(r); // -r
  260. if (option_mask32 & 0x400) limitt = xatoul(t); // -t
  261. // if (option_mask32 & 0x800) // -/
  262. if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
  263. // The below consts should match #defines at top!
  264. //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
  265. //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
  266. //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
  267. //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
  268. //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
  269. }
  270. argv += optind;
  271. if (!argv || !*argv) bb_show_usage();
  272. if (OPT_pgrp) setsid();
  273. if (env_dir) edir(env_dir);
  274. if (root) {
  275. xchdir(root);
  276. if (chroot(".") == -1)
  277. bb_perror_msg_and_die("chroot");
  278. }
  279. slimit();
  280. if (nicelvl) {
  281. errno = 0;
  282. if (nice(nicelvl) == -1)
  283. bb_perror_msg_and_die("nice");
  284. }
  285. if (env_user) euidgid(env_user);
  286. if (set_user) suidgid(set_user);
  287. if (OPT_nostdin) close(0);
  288. if (OPT_nostdout) close(1);
  289. if (OPT_nostderr) close(2);
  290. execvp(argv[0], argv);
  291. bb_perror_msg_and_die("exec %s", argv[0]);
  292. }
  293. static void setuidgid(int argc, char **argv)
  294. {
  295. const char *account;
  296. account = *++argv;
  297. if (!account) bb_show_usage();
  298. if (!*++argv) bb_show_usage();
  299. suidgid((char*)account);
  300. execvp(argv[0], argv);
  301. bb_perror_msg_and_die("exec %s", argv[0]);
  302. }
  303. static void envuidgid(int argc, char **argv)
  304. {
  305. const char *account;
  306. account = *++argv;
  307. if (!account) bb_show_usage();
  308. if (!*++argv) bb_show_usage();
  309. euidgid((char*)account);
  310. execvp(argv[0], argv);
  311. bb_perror_msg_and_die("exec %s", argv[0]);
  312. }
  313. static void envdir(int argc, char **argv)
  314. {
  315. const char *dir;
  316. dir = *++argv;
  317. if (!dir) bb_show_usage();
  318. if (!*++argv) bb_show_usage();
  319. edir(dir);
  320. execvp(argv[0], argv);
  321. bb_perror_msg_and_die("exec %s", argv[0]);
  322. }
  323. static void softlimit(int argc, char **argv)
  324. {
  325. char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
  326. getopt32(argc, argv, "+a:c:d:f:l:m:o:p:r:s:t:",
  327. &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
  328. if (option_mask32 & 0x001) limita = xatoul(a); // -a
  329. if (option_mask32 & 0x002) limitc = xatoul(c); // -c
  330. if (option_mask32 & 0x004) limitd = xatoul(d); // -d
  331. if (option_mask32 & 0x008) limitf = xatoul(f); // -f
  332. if (option_mask32 & 0x010) limitl = xatoul(l); // -l
  333. if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
  334. if (option_mask32 & 0x040) limito = xatoul(o); // -o
  335. if (option_mask32 & 0x080) limitp = xatoul(p); // -p
  336. if (option_mask32 & 0x100) limitr = xatoul(r); // -r
  337. if (option_mask32 & 0x200) limits = xatoul(s); // -s
  338. if (option_mask32 & 0x400) limitt = xatoul(t); // -t
  339. argv += optind;
  340. if (!argv[0]) bb_show_usage();
  341. slimit();
  342. execvp(argv[0], argv);
  343. bb_perror_msg_and_die("exec %s", argv[0]);
  344. }