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 if (!get_uidgid(&ugid, user, 1)) {
85 bb_error_msg_and_die("unknown user/group: %s", user);
87 if (setgroups(1, &ugid.gid) == -1)
88 bb_perror_msg_and_die("setgroups");
93 static void euidgid(char *user)
95 struct bb_uidgid_t ugid;
97 if (!get_uidgid(&ugid, user, 1)) {
98 bb_error_msg_and_die("unknown user/group: %s", user);
100 xsetenv("GID", utoa(ugid.gid));
101 xsetenv("UID", utoa(ugid.uid));
104 static void edir(const char *directory_name)
111 wdir = xopen(".", O_RDONLY | O_NDELAY);
112 xchdir(directory_name);
115 bb_perror_msg_and_die("opendir %s", directory_name);
125 bb_perror_msg_and_die("readdir %s",
129 if (d->d_name[0] == '.')
131 fd = open(d->d_name, O_RDONLY | O_NDELAY);
133 if ((errno == EISDIR) && env_dir) {
135 bb_perror_msg("warning: %s/%s is a directory",
136 directory_name, d->d_name);
139 bb_perror_msg_and_die("open %s/%s",
140 directory_name, d->d_name);
142 size = full_read(fd, buf, sizeof(buf)-1);
145 bb_perror_msg_and_die("read %s/%s",
146 directory_name, d->d_name);
152 tail = strchr(buf, '\n');
153 /* skip trailing whitespace */
157 if (tail < buf || !isspace(*tail))
160 xsetenv(d->d_name, buf);
163 if (fchdir(wdir) == -1)
164 bb_perror_msg_and_die("fchdir");
168 static void limit(int what, long l)
172 /* Never fails under Linux (except if you pass it bad arguments) */
174 if ((l < 0) || (l > r.rlim_max))
175 r.rlim_cur = r.rlim_max;
178 if (setrlimit(what, &r) == -1)
179 bb_perror_msg_and_die("setrlimit");
182 static void slimit(void)
186 limit(RLIMIT_DATA, limitd);
189 bb_error_msg("system does not support RLIMIT_%s",
195 limit(RLIMIT_STACK, limits);
198 bb_error_msg("system does not support RLIMIT_%s",
203 #ifdef RLIMIT_MEMLOCK
204 limit(RLIMIT_MEMLOCK, limitl);
207 bb_error_msg("system does not support RLIMIT_%s",
213 limit(RLIMIT_VMEM, limita);
216 limit(RLIMIT_AS, limita);
219 bb_error_msg("system does not support RLIMIT_%s",
226 limit(RLIMIT_NOFILE, limito);
229 limit(RLIMIT_OFILE, limito);
232 bb_error_msg("system does not support RLIMIT_%s",
239 limit(RLIMIT_NPROC, limitp);
242 bb_error_msg("system does not support RLIMIT_%s",
248 limit(RLIMIT_FSIZE, limitf);
251 bb_error_msg("system does not support RLIMIT_%s",
257 limit(RLIMIT_CORE, limitc);
260 bb_error_msg("system does not support RLIMIT_%s",
266 limit(RLIMIT_RSS, limitr);
269 bb_error_msg("system does not support RLIMIT_%s",
275 limit(RLIMIT_CPU, limitt);
278 bb_error_msg("system does not support RLIMIT_%s",
285 static void setuidgid(int, char **) ATTRIBUTE_NORETURN;
286 static void envuidgid(int, char **) ATTRIBUTE_NORETURN;
287 static void envdir(int, char **) ATTRIBUTE_NORETURN;
288 static void softlimit(int, char **) ATTRIBUTE_NORETURN;
290 int chpst_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
291 int chpst_main(int argc ATTRIBUTE_UNUSED, char **argv)
295 if (applet_name[3] == 'd') envdir(argc, argv);
296 if (applet_name[1] == 'o') softlimit(argc, argv);
297 if (applet_name[0] == 's') setuidgid(argc, argv);
298 if (applet_name[0] == 'e') envuidgid(argc, argv);
299 // otherwise we are chpst
302 char *m,*d,*o,*p,*f,*c,*r,*t,*n;
303 getopt32(argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
304 &set_user,&env_user,&env_dir,
305 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
306 // if (option_mask32 & 0x1) // -u
307 // if (option_mask32 & 0x2) // -U
308 // if (option_mask32 & 0x4) // -e
309 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
310 if (option_mask32 & 0x10) limitd = xatoul(d); // -d
311 if (option_mask32 & 0x20) limito = xatoul(o); // -o
312 if (option_mask32 & 0x40) limitp = xatoul(p); // -p
313 if (option_mask32 & 0x80) limitf = xatoul(f); // -f
314 if (option_mask32 & 0x100) limitc = xatoul(c); // -c
315 if (option_mask32 & 0x200) limitr = xatoul(r); // -r
316 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
317 // if (option_mask32 & 0x800) // -/
318 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
319 // The below consts should match #defines at top!
320 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
321 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
322 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
323 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
324 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
327 if (!argv || !*argv) bb_show_usage();
329 if (OPT_pgrp) setsid();
330 if (env_dir) edir(env_dir);
338 if (nice(nicelvl) == -1)
339 bb_perror_msg_and_die("nice");
341 if (env_user) euidgid(env_user);
342 if (set_user) suidgid(set_user);
343 if (OPT_nostdin) close(0);
344 if (OPT_nostdout) close(1);
345 if (OPT_nostderr) close(2);
346 BB_EXECVP(argv[0], argv);
347 bb_perror_msg_and_die("exec %s", argv[0]);
350 static void setuidgid(int argc ATTRIBUTE_UNUSED, char **argv)
355 if (!account) bb_show_usage();
356 if (!*++argv) bb_show_usage();
357 suidgid((char*)account);
358 BB_EXECVP(argv[0], argv);
359 bb_perror_msg_and_die("exec %s", argv[0]);
362 static void envuidgid(int argc ATTRIBUTE_UNUSED, char **argv)
367 if (!account) bb_show_usage();
368 if (!*++argv) bb_show_usage();
369 euidgid((char*)account);
370 BB_EXECVP(argv[0], argv);
371 bb_perror_msg_and_die("exec %s", argv[0]);
374 static void envdir(int argc ATTRIBUTE_UNUSED, char **argv)
379 if (!dir) bb_show_usage();
380 if (!*++argv) bb_show_usage();
382 BB_EXECVP(argv[0], argv);
383 bb_perror_msg_and_die("exec %s", argv[0]);
386 static void softlimit(int argc ATTRIBUTE_UNUSED, char **argv)
388 char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
389 getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:",
390 &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
391 if (option_mask32 & 0x001) limita = xatoul(a); // -a
392 if (option_mask32 & 0x002) limitc = xatoul(c); // -c
393 if (option_mask32 & 0x004) limitd = xatoul(d); // -d
394 if (option_mask32 & 0x008) limitf = xatoul(f); // -f
395 if (option_mask32 & 0x010) limitl = xatoul(l); // -l
396 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
397 if (option_mask32 & 0x040) limito = xatoul(o); // -o
398 if (option_mask32 & 0x080) limitp = xatoul(p); // -p
399 if (option_mask32 & 0x100) limitr = xatoul(r); // -r
400 if (option_mask32 & 0x200) limits = xatoul(s); // -s
401 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
403 if (!argv[0]) bb_show_usage();
405 BB_EXECVP(argv[0], argv);
406 bb_perror_msg_and_die("exec %s", argv[0]);