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);
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);
143 size = safe_read(fd, buf, sizeof(buf)-1);
145 bb_perror_msg_and_die("read %s/%s",
146 directory_name, d->d_name);
152 tail = memchr(buf, '\n', sizeof(buf));
153 /* skip trailing whitespace */;
155 if (tail[0] == ' ') tail[0] = '\0';
156 if (tail[0] == '\t') tail[0] = '\0';
157 if (tail[0] == '\n') tail[0] = '\0';
158 if (tail == buf) break;
161 xsetenv(d->d_name, buf);
165 if (fchdir(wdir) == -1)
166 bb_perror_msg_and_die("fchdir");
170 static void limit(int what, long l)
174 /* Never fails under Linux (except if you pass it bad arguments) */
176 if ((l < 0) || (l > r.rlim_max))
177 r.rlim_cur = r.rlim_max;
180 if (setrlimit(what, &r) == -1)
181 bb_perror_msg_and_die("setrlimit");
184 static void slimit(void)
188 limit(RLIMIT_DATA, limitd);
191 bb_error_msg("system does not support RLIMIT_%s",
197 limit(RLIMIT_STACK, limits);
200 bb_error_msg("system does not support RLIMIT_%s",
205 #ifdef RLIMIT_MEMLOCK
206 limit(RLIMIT_MEMLOCK, limitl);
209 bb_error_msg("system does not support RLIMIT_%s",
215 limit(RLIMIT_VMEM, limita);
218 limit(RLIMIT_AS, limita);
221 bb_error_msg("system does not support RLIMIT_%s",
228 limit(RLIMIT_NOFILE, limito);
231 limit(RLIMIT_OFILE, limito);
234 bb_error_msg("system does not support RLIMIT_%s",
241 limit(RLIMIT_NPROC, limitp);
244 bb_error_msg("system does not support RLIMIT_%s",
250 limit(RLIMIT_FSIZE, limitf);
253 bb_error_msg("system does not support RLIMIT_%s",
259 limit(RLIMIT_CORE, limitc);
262 bb_error_msg("system does not support RLIMIT_%s",
268 limit(RLIMIT_RSS, limitr);
271 bb_error_msg("system does not support RLIMIT_%s",
277 limit(RLIMIT_CPU, limitt);
280 bb_error_msg("system does not support RLIMIT_%s",
287 static void setuidgid(int, char **) ATTRIBUTE_NORETURN;
288 static void envuidgid(int, char **) ATTRIBUTE_NORETURN;
289 static void envdir(int, char **) ATTRIBUTE_NORETURN;
290 static void softlimit(int, char **) ATTRIBUTE_NORETURN;
292 int chpst_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
293 int chpst_main(int argc ATTRIBUTE_UNUSED, char **argv)
297 if (applet_name[3] == 'd') envdir(argc, argv);
298 if (applet_name[1] == 'o') softlimit(argc, argv);
299 if (applet_name[0] == 's') setuidgid(argc, argv);
300 if (applet_name[0] == 'e') envuidgid(argc, argv);
301 // otherwise we are chpst
304 char *m,*d,*o,*p,*f,*c,*r,*t,*n;
305 getopt32(argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
306 &set_user,&env_user,&env_dir,
307 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
308 // if (option_mask32 & 0x1) // -u
309 // if (option_mask32 & 0x2) // -U
310 // if (option_mask32 & 0x4) // -e
311 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
312 if (option_mask32 & 0x10) limitd = xatoul(d); // -d
313 if (option_mask32 & 0x20) limito = xatoul(o); // -o
314 if (option_mask32 & 0x40) limitp = xatoul(p); // -p
315 if (option_mask32 & 0x80) limitf = xatoul(f); // -f
316 if (option_mask32 & 0x100) limitc = xatoul(c); // -c
317 if (option_mask32 & 0x200) limitr = xatoul(r); // -r
318 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
319 // if (option_mask32 & 0x800) // -/
320 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
321 // The below consts should match #defines at top!
322 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
323 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
324 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
325 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
326 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
329 if (!argv || !*argv) bb_show_usage();
331 if (OPT_pgrp) setsid();
332 if (env_dir) edir(env_dir);
340 if (nice(nicelvl) == -1)
341 bb_perror_msg_and_die("nice");
343 if (env_user) euidgid(env_user);
344 if (set_user) suidgid(set_user);
345 if (OPT_nostdin) close(0);
346 if (OPT_nostdout) close(1);
347 if (OPT_nostderr) close(2);
348 BB_EXECVP(argv[0], argv);
349 bb_perror_msg_and_die("exec %s", argv[0]);
352 static void setuidgid(int argc ATTRIBUTE_UNUSED, char **argv)
357 if (!account) bb_show_usage();
358 if (!*++argv) bb_show_usage();
359 suidgid((char*)account);
360 BB_EXECVP(argv[0], argv);
361 bb_perror_msg_and_die("exec %s", argv[0]);
364 static void envuidgid(int argc ATTRIBUTE_UNUSED, char **argv)
369 if (!account) bb_show_usage();
370 if (!*++argv) bb_show_usage();
371 euidgid((char*)account);
372 BB_EXECVP(argv[0], argv);
373 bb_perror_msg_and_die("exec %s", argv[0]);
376 static void envdir(int argc ATTRIBUTE_UNUSED, char **argv)
381 if (!dir) bb_show_usage();
382 if (!*++argv) bb_show_usage();
384 BB_EXECVP(argv[0], argv);
385 bb_perror_msg_and_die("exec %s", argv[0]);
388 static void softlimit(int argc ATTRIBUTE_UNUSED, char **argv)
390 char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
391 getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:",
392 &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
393 if (option_mask32 & 0x001) limita = xatoul(a); // -a
394 if (option_mask32 & 0x002) limitc = xatoul(c); // -c
395 if (option_mask32 & 0x004) limitd = xatoul(d); // -d
396 if (option_mask32 & 0x008) limitf = xatoul(f); // -f
397 if (option_mask32 & 0x010) limitl = xatoul(l); // -l
398 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
399 if (option_mask32 & 0x040) limito = xatoul(o); // -o
400 if (option_mask32 & 0x080) limitp = xatoul(p); // -p
401 if (option_mask32 & 0x100) limitr = xatoul(r); // -r
402 if (option_mask32 & 0x200) limits = xatoul(s); // -s
403 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
405 if (!argv[0]) bb_show_usage();
407 BB_EXECVP(argv[0], argv);
408 bb_perror_msg_and_die("exec %s", argv[0]);