2 Copyright (c) 2001-2006, Gerrit Pape
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29 /* Dependencies on runit_lib.c removed */
35 // Must match constants in chpst_main!
36 #define OPT_verbose (option_mask32 & 0x2000)
37 #define OPT_pgrp (option_mask32 & 0x4000)
38 #define OPT_nostdin (option_mask32 & 0x8000)
39 #define OPT_nostdout (option_mask32 & 0x10000)
40 #define OPT_nostderr (option_mask32 & 0x20000)
47 long limitd; /* limitX are initialized to -2 */
59 #define G (*(struct globals*)&bb_common_bufsiz1)
60 #define set_user (G.set_user)
61 #define env_user (G.env_user)
62 #define env_dir (G.env_dir )
63 #define root (G.root )
64 #define limitd (G.limitd )
65 #define limits (G.limits )
66 #define limitl (G.limitl )
67 #define limita (G.limita )
68 #define limito (G.limito )
69 #define limitp (G.limitp )
70 #define limitf (G.limitf )
71 #define limitc (G.limitc )
72 #define limitr (G.limitr )
73 #define limitt (G.limitt )
74 #define nicelvl (G.nicelvl )
75 #define INIT_G() do { \
77 do *p++ = -2; while (p <= &limitt); \
80 static void suidgid(char *user)
82 struct bb_uidgid_t ugid;
84 xget_uidgid(&ugid, user);
85 if (setgroups(1, &ugid.gid) == -1)
86 bb_perror_msg_and_die("setgroups");
91 static void euidgid(char *user)
93 struct bb_uidgid_t ugid;
95 xget_uidgid(&ugid, user);
96 xsetenv("GID", utoa(ugid.gid));
97 xsetenv("UID", utoa(ugid.uid));
100 static void edir(const char *directory_name)
107 wdir = xopen(".", O_RDONLY | O_NDELAY);
108 xchdir(directory_name);
111 bb_perror_msg_and_die("opendir %s", directory_name);
121 bb_perror_msg_and_die("readdir %s",
125 if (d->d_name[0] == '.')
127 fd = open(d->d_name, O_RDONLY | O_NDELAY);
129 if ((errno == EISDIR) && env_dir) {
131 bb_perror_msg("warning: %s/%s is a directory",
132 directory_name, d->d_name);
135 bb_perror_msg_and_die("open %s/%s",
136 directory_name, d->d_name);
138 size = full_read(fd, buf, sizeof(buf)-1);
141 bb_perror_msg_and_die("read %s/%s",
142 directory_name, d->d_name);
148 tail = strchr(buf, '\n');
149 /* skip trailing whitespace */
153 if (tail < buf || !isspace(*tail))
156 xsetenv(d->d_name, buf);
159 if (fchdir(wdir) == -1)
160 bb_perror_msg_and_die("fchdir");
164 static void limit(int what, long l)
168 /* Never fails under Linux (except if you pass it bad arguments) */
170 if ((l < 0) || (l > r.rlim_max))
171 r.rlim_cur = r.rlim_max;
174 if (setrlimit(what, &r) == -1)
175 bb_perror_msg_and_die("setrlimit");
178 static void slimit(void)
182 limit(RLIMIT_DATA, limitd);
185 bb_error_msg("system does not support RLIMIT_%s",
191 limit(RLIMIT_STACK, limits);
194 bb_error_msg("system does not support RLIMIT_%s",
199 #ifdef RLIMIT_MEMLOCK
200 limit(RLIMIT_MEMLOCK, limitl);
203 bb_error_msg("system does not support RLIMIT_%s",
209 limit(RLIMIT_VMEM, limita);
212 limit(RLIMIT_AS, limita);
215 bb_error_msg("system does not support RLIMIT_%s",
222 limit(RLIMIT_NOFILE, limito);
225 limit(RLIMIT_OFILE, limito);
228 bb_error_msg("system does not support RLIMIT_%s",
235 limit(RLIMIT_NPROC, limitp);
238 bb_error_msg("system does not support RLIMIT_%s",
244 limit(RLIMIT_FSIZE, limitf);
247 bb_error_msg("system does not support RLIMIT_%s",
253 limit(RLIMIT_CORE, limitc);
256 bb_error_msg("system does not support RLIMIT_%s",
262 limit(RLIMIT_RSS, limitr);
265 bb_error_msg("system does not support RLIMIT_%s",
271 limit(RLIMIT_CPU, limitt);
274 bb_error_msg("system does not support RLIMIT_%s",
281 static void setuidgid(int, char **) NORETURN;
282 static void envuidgid(int, char **) NORETURN;
283 static void envdir(int, char **) NORETURN;
284 static void softlimit(int, char **) NORETURN;
286 int chpst_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
287 int chpst_main(int argc UNUSED_PARAM, char **argv)
291 if (applet_name[3] == 'd') envdir(argc, argv);
292 if (applet_name[1] == 'o') softlimit(argc, argv);
293 if (applet_name[0] == 's') setuidgid(argc, argv);
294 if (applet_name[0] == 'e') envuidgid(argc, argv);
295 // otherwise we are chpst
298 char *m,*d,*o,*p,*f,*c,*r,*t,*n;
299 getopt32(argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
300 &set_user,&env_user,&env_dir,
301 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
302 // if (option_mask32 & 0x1) // -u
303 // if (option_mask32 & 0x2) // -U
304 // if (option_mask32 & 0x4) // -e
305 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
306 if (option_mask32 & 0x10) limitd = xatoul(d); // -d
307 if (option_mask32 & 0x20) limito = xatoul(o); // -o
308 if (option_mask32 & 0x40) limitp = xatoul(p); // -p
309 if (option_mask32 & 0x80) limitf = xatoul(f); // -f
310 if (option_mask32 & 0x100) limitc = xatoul(c); // -c
311 if (option_mask32 & 0x200) limitr = xatoul(r); // -r
312 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
313 // if (option_mask32 & 0x800) // -/
314 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
315 // The below consts should match #defines at top!
316 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
317 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
318 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
319 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
320 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
323 if (!argv || !*argv) bb_show_usage();
325 if (OPT_pgrp) setsid();
326 if (env_dir) edir(env_dir);
334 if (nice(nicelvl) == -1)
335 bb_perror_msg_and_die("nice");
337 if (env_user) euidgid(env_user);
338 if (set_user) suidgid(set_user);
339 if (OPT_nostdin) close(0);
340 if (OPT_nostdout) close(1);
341 if (OPT_nostderr) close(2);
342 BB_EXECVP(argv[0], argv);
343 bb_perror_msg_and_die("exec %s", argv[0]);
346 static void setuidgid(int argc UNUSED_PARAM, char **argv)
351 if (!account) bb_show_usage();
352 if (!*++argv) bb_show_usage();
353 suidgid((char*)account);
354 BB_EXECVP(argv[0], argv);
355 bb_perror_msg_and_die("exec %s", argv[0]);
358 static void envuidgid(int argc UNUSED_PARAM, char **argv)
363 if (!account) bb_show_usage();
364 if (!*++argv) bb_show_usage();
365 euidgid((char*)account);
366 BB_EXECVP(argv[0], argv);
367 bb_perror_msg_and_die("exec %s", argv[0]);
370 static void envdir(int argc UNUSED_PARAM, char **argv)
375 if (!dir) bb_show_usage();
376 if (!*++argv) bb_show_usage();
378 BB_EXECVP(argv[0], argv);
379 bb_perror_msg_and_die("exec %s", argv[0]);
382 static void softlimit(int argc UNUSED_PARAM, char **argv)
384 char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
385 getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:",
386 &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
387 if (option_mask32 & 0x001) limita = xatoul(a); // -a
388 if (option_mask32 & 0x002) limitc = xatoul(c); // -c
389 if (option_mask32 & 0x004) limitd = xatoul(d); // -d
390 if (option_mask32 & 0x008) limitf = xatoul(f); // -f
391 if (option_mask32 & 0x010) limitl = xatoul(l); // -l
392 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
393 if (option_mask32 & 0x040) limito = xatoul(o); // -o
394 if (option_mask32 & 0x080) limitp = xatoul(p); // -p
395 if (option_mask32 & 0x100) limitr = xatoul(r); // -r
396 if (option_mask32 & 0x200) limits = xatoul(s); // -s
397 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
399 if (!argv[0]) bb_show_usage();
401 BB_EXECVP(argv[0], argv);
402 bb_perror_msg_and_die("exec %s", argv[0]);