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 Denis 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)
42 static char *set_user;
43 static char *env_user;
44 static const char *env_dir;
45 static long limitd = -2;
46 static long limits = -2;
47 static long limitl = -2;
48 static long limita = -2;
49 static long limito = -2;
50 static long limitp = -2;
51 static long limitf = -2;
52 static long limitc = -2;
53 static long limitr = -2;
54 static long limitt = -2;
56 static const char *root;
58 static void suidgid(char *user)
60 struct bb_uidgid_t ugid;
62 if (!get_uidgid(&ugid, user, 1)) {
63 bb_error_msg_and_die("unknown user/group: %s", user);
65 if (setgroups(1, &ugid.gid) == -1)
66 bb_perror_msg_and_die("setgroups");
71 static void euidgid(char *user)
73 struct bb_uidgid_t ugid;
75 if (!get_uidgid(&ugid, user, 1)) {
76 bb_error_msg_and_die("unknown user/group: %s", user);
78 xsetenv("GID", utoa(ugid.gid));
79 xsetenv("UID", utoa(ugid.uid));
82 static void edir(const char *directory_name)
89 wdir = xopen(".", O_RDONLY | O_NDELAY);
90 xchdir(directory_name);
93 bb_perror_msg_and_die("opendir %s", directory_name);
99 bb_perror_msg_and_die("readdir %s",
103 if (d->d_name[0] == '.') continue;
104 fd = open(d->d_name, O_RDONLY | O_NDELAY);
106 if ((errno == EISDIR) && env_dir) {
108 bb_perror_msg("warning: %s/%s is a directory",
109 directory_name, d->d_name);
112 bb_perror_msg_and_die("open %s/%s",
113 directory_name, d->d_name);
120 size = safe_read(fd, buf, sizeof(buf)-1);
122 bb_perror_msg_and_die("read %s/%s",
123 directory_name, d->d_name);
129 tail = memchr(buf, '\n', sizeof(buf));
130 /* skip trailing whitespace */;
132 if (tail[0]==' ') tail[0] = '\0';
133 if (tail[0]=='\t') tail[0] = '\0';
134 if (tail[0]=='\n') tail[0] = '\0';
135 if (tail == buf) break;
138 xsetenv(d->d_name, buf);
142 if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir");
146 static void limit(int what, long l)
150 if (getrlimit(what, &r) == -1) bb_perror_msg_and_die("getrlimit");
151 if ((l < 0) || (l > r.rlim_max))
152 r.rlim_cur = r.rlim_max;
155 if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit");
158 static void slimit(void)
162 limit(RLIMIT_DATA, limitd);
164 if (OPT_verbose) bb_error_msg("system does not support %s",
170 limit(RLIMIT_STACK, limits);
172 if (OPT_verbose) bb_error_msg("system does not support %s",
177 #ifdef RLIMIT_MEMLOCK
178 limit(RLIMIT_MEMLOCK, limitl);
180 if (OPT_verbose) bb_error_msg("system does not support %s",
186 limit(RLIMIT_VMEM, limita);
189 limit(RLIMIT_AS, limita);
192 bb_error_msg("system does not support %s",
199 limit(RLIMIT_NOFILE, limito);
202 limit(RLIMIT_OFILE, limito);
205 bb_error_msg("system does not support %s",
212 limit(RLIMIT_NPROC, limitp);
214 if (OPT_verbose) bb_error_msg("system does not support %s",
220 limit(RLIMIT_FSIZE, limitf);
222 if (OPT_verbose) bb_error_msg("system does not support %s",
228 limit(RLIMIT_CORE, limitc);
230 if (OPT_verbose) bb_error_msg("system does not support %s",
236 limit(RLIMIT_RSS, limitr);
238 if (OPT_verbose) bb_error_msg("system does not support %s",
244 limit(RLIMIT_CPU, limitt);
246 if (OPT_verbose) bb_error_msg("system does not support %s",
253 static void setuidgid(int, char **);
254 static void envuidgid(int, char **);
255 static void envdir(int, char **);
256 static void softlimit(int, char **);
258 int chpst_main(int argc, char **argv);
259 int chpst_main(int argc, char **argv)
261 if (applet_name[3] == 'd') envdir(argc, argv);
262 if (applet_name[1] == 'o') softlimit(argc, argv);
263 if (applet_name[0] == 's') setuidgid(argc, argv);
264 if (applet_name[0] == 'e') envuidgid(argc, argv);
265 // otherwise we are chpst
268 char *m,*d,*o,*p,*f,*c,*r,*t,*n;
269 getopt32(argc, argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
270 &set_user,&env_user,&env_dir,
271 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
272 // if (option_mask32 & 0x1) // -u
273 // if (option_mask32 & 0x2) // -U
274 // if (option_mask32 & 0x4) // -e
275 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
276 if (option_mask32 & 0x10) limitd = xatoul(d); // -d
277 if (option_mask32 & 0x20) limito = xatoul(o); // -o
278 if (option_mask32 & 0x40) limitp = xatoul(p); // -p
279 if (option_mask32 & 0x80) limitf = xatoul(f); // -f
280 if (option_mask32 & 0x100) limitc = xatoul(c); // -c
281 if (option_mask32 & 0x200) limitr = xatoul(r); // -r
282 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
283 // if (option_mask32 & 0x800) // -/
284 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
285 // The below consts should match #defines at top!
286 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
287 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
288 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
289 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
290 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
293 if (!argv || !*argv) bb_show_usage();
295 if (OPT_pgrp) setsid();
296 if (env_dir) edir(env_dir);
299 if (chroot(".") == -1)
300 bb_perror_msg_and_die("chroot");
305 if (nice(nicelvl) == -1)
306 bb_perror_msg_and_die("nice");
308 if (env_user) euidgid(env_user);
309 if (set_user) suidgid(set_user);
310 if (OPT_nostdin) close(0);
311 if (OPT_nostdout) close(1);
312 if (OPT_nostderr) close(2);
313 BB_EXECVP(argv[0], argv);
314 bb_perror_msg_and_die("exec %s", argv[0]);
317 static void setuidgid(int argc, char **argv)
322 if (!account) bb_show_usage();
323 if (!*++argv) bb_show_usage();
324 suidgid((char*)account);
325 BB_EXECVP(argv[0], argv);
326 bb_perror_msg_and_die("exec %s", argv[0]);
329 static void envuidgid(int argc, char **argv)
334 if (!account) bb_show_usage();
335 if (!*++argv) bb_show_usage();
336 euidgid((char*)account);
337 BB_EXECVP(argv[0], argv);
338 bb_perror_msg_and_die("exec %s", argv[0]);
341 static void envdir(int argc, char **argv)
346 if (!dir) bb_show_usage();
347 if (!*++argv) bb_show_usage();
349 BB_EXECVP(argv[0], argv);
350 bb_perror_msg_and_die("exec %s", argv[0]);
353 static void softlimit(int argc, char **argv)
355 char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
356 getopt32(argc, argv, "+a:c:d:f:l:m:o:p:r:s:t:",
357 &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
358 if (option_mask32 & 0x001) limita = xatoul(a); // -a
359 if (option_mask32 & 0x002) limitc = xatoul(c); // -c
360 if (option_mask32 & 0x004) limitd = xatoul(d); // -d
361 if (option_mask32 & 0x008) limitf = xatoul(f); // -f
362 if (option_mask32 & 0x010) limitl = xatoul(l); // -l
363 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
364 if (option_mask32 & 0x040) limito = xatoul(o); // -o
365 if (option_mask32 & 0x080) limitp = xatoul(p); // -p
366 if (option_mask32 & 0x100) limitr = xatoul(r); // -r
367 if (option_mask32 & 0x200) limits = xatoul(s); // -s
368 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
370 if (!argv[0]) bb_show_usage();
372 BB_EXECVP(argv[0], argv);
373 bb_perror_msg_and_die("exec %s", argv[0]);