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> */
34 // Must match constants in chpst_main!
35 #define OPT_verbose (option_mask32 & 0x2000)
36 #define OPT_pgrp (option_mask32 & 0x4000)
37 #define OPT_nostdin (option_mask32 & 0x8000)
38 #define OPT_nostdout (option_mask32 & 0x10000)
39 #define OPT_nostderr (option_mask32 & 0x20000)
41 static char *set_user;
42 static char *env_user;
43 static const char *env_dir;
44 static long limitd = -2;
45 static long limits = -2;
46 static long limitl = -2;
47 static long limita = -2;
48 static long limito = -2;
49 static long limitp = -2;
50 static long limitf = -2;
51 static long limitc = -2;
52 static long limitr = -2;
53 static long limitt = -2;
55 static const char *root;
57 static void suidgid(char *user)
59 struct bb_uidgid_t ugid;
61 if (!uidgid_get(&ugid, user)) {
62 bb_error_msg_and_die("unknown user/group: %s", user);
64 if (setgroups(1, &ugid.gid) == -1)
65 bb_perror_msg_and_die("setgroups");
70 static void euidgid(char *user)
72 struct bb_uidgid_t ugid;
74 if (!uidgid_get(&ugid, user)) {
75 bb_error_msg_and_die("unknown user/group: %s", user);
77 xsetenv("GID", utoa(ugid.gid));
78 xsetenv("UID", utoa(ugid.uid));
81 static void edir(const char *directory_name)
88 wdir = xopen(".", O_RDONLY | O_NDELAY);
89 xchdir(directory_name);
92 bb_perror_msg_and_die("opendir %s", directory_name);
97 if (errno) bb_perror_msg_and_die("readdir %s", directory_name);
100 if (d->d_name[0] == '.') continue;
101 fd = open(d->d_name, O_RDONLY | O_NDELAY);
103 if ((errno == EISDIR) && env_dir) {
105 bb_perror_msg("warning: %s/%s is a directory", directory_name,
109 bb_perror_msg_and_die("open %s/%s", directory_name, /* was exiting 111 */
117 size = safe_read(fd, buf, sizeof(buf)-1);
119 bb_perror_msg_and_die("read %s/%s", directory_name, /* was exiting 111 */
126 tail = memchr(buf, '\n', sizeof(buf));
127 /* skip trailing whitespace */;
129 if (tail[0]==' ') tail[0] = '\0';
130 if (tail[0]=='\t') tail[0] = '\0';
131 if (tail[0]=='\n') tail[0] = '\0';
132 if (tail == buf) break;
135 xsetenv(d->d_name, buf);
139 if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir");
143 static void limit(int what, long l)
147 if (getrlimit(what, &r) == -1) bb_perror_msg_and_die("getrlimit");
148 if ((l < 0) || (l > r.rlim_max))
149 r.rlim_cur = r.rlim_max;
152 if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit");
155 static void slimit(void)
159 limit(RLIMIT_DATA, limitd);
161 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_DATA");
166 limit(RLIMIT_STACK, limits);
168 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_STACK");
172 #ifdef RLIMIT_MEMLOCK
173 limit(RLIMIT_MEMLOCK, limitl);
175 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_MEMLOCK");
180 limit(RLIMIT_VMEM, limita);
183 limit(RLIMIT_AS, limita);
186 bb_error_msg("system does not support %s", "RLIMIT_VMEM");
192 limit(RLIMIT_NOFILE, limito);
195 limit(RLIMIT_OFILE, limito);
198 bb_error_msg("system does not support %s", "RLIMIT_NOFILE");
204 limit(RLIMIT_NPROC, limitp);
206 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_NPROC");
211 limit(RLIMIT_FSIZE, limitf);
213 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_FSIZE");
218 limit(RLIMIT_CORE, limitc);
220 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_CORE");
225 limit(RLIMIT_RSS, limitr);
227 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_RSS");
232 limit(RLIMIT_CPU, limitt);
234 if (OPT_verbose) bb_error_msg("system does not support %s", "RLIMIT_CPU");
240 static void setuidgid(int, char **);
241 static void envuidgid(int, char **);
242 static void envdir(int, char **);
243 static void softlimit(int, char **);
245 int chpst_main(int argc, char **argv)
247 if (applet_name[3] == 'd') envdir(argc, argv);
248 if (applet_name[1] == 'o') softlimit(argc, argv);
249 if (applet_name[0] == 's') setuidgid(argc, argv);
250 if (applet_name[0] == 'e') envuidgid(argc, argv);
251 // otherwise we are.......... chpst
254 char *m,*d,*o,*p,*f,*c,*r,*t,*n;
255 getopt32(argc, argv, "+u:U:e:m:d:o:p:f:c:r:t:/:n:vP012",
256 &set_user,&env_user,&env_dir,
257 &m,&d,&o,&p,&f,&c,&r,&t,&root,&n);
258 // if (option_mask32 & 0x1) // -u
259 // if (option_mask32 & 0x2) // -U
260 // if (option_mask32 & 0x4) // -e
261 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m
262 if (option_mask32 & 0x10) limitd = xatoul(d); // -d
263 if (option_mask32 & 0x20) limito = xatoul(o); // -o
264 if (option_mask32 & 0x40) limitp = xatoul(p); // -p
265 if (option_mask32 & 0x80) limitf = xatoul(f); // -f
266 if (option_mask32 & 0x100) limitc = xatoul(c); // -c
267 if (option_mask32 & 0x200) limitr = xatoul(r); // -r
268 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
269 // if (option_mask32 & 0x800) // -/
270 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n
271 // The below consts should match #defines at top!
272 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v
273 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P
274 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0
275 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1
276 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2
279 if (!argv || !*argv) bb_show_usage();
281 if (OPT_pgrp) setsid();
282 if (env_dir) edir(env_dir);
285 if (chroot(".") == -1)
286 bb_perror_msg_and_die("chroot");
291 if (nice(nicelvl) == -1)
292 bb_perror_msg_and_die("nice");
294 if (env_user) euidgid(env_user);
295 if (set_user) suidgid(set_user);
296 if (OPT_nostdin) close(0);
297 if (OPT_nostdout) close(1);
298 if (OPT_nostderr) close(2);
299 execvp(argv[0], argv);
300 bb_perror_msg_and_die("exec %s", argv[0]);
303 static void setuidgid(int argc, char **argv)
308 if (!account) bb_show_usage();
309 if (!*++argv) bb_show_usage();
310 suidgid((char*)account);
311 execvp(argv[0], argv);
312 bb_perror_msg_and_die("exec %s", argv[0]);
315 static void envuidgid(int argc, char **argv)
320 if (!account) bb_show_usage();
321 if (!*++argv) bb_show_usage();
322 euidgid((char*)account);
323 execvp(argv[0], argv);
324 bb_perror_msg_and_die("exec %s", argv[0]);
327 static void envdir(int argc, char **argv)
332 if (!dir) bb_show_usage();
333 if (!*++argv) bb_show_usage();
335 execvp(argv[0], argv);
336 bb_perror_msg_and_die("exec %s", argv[0]);
339 static void softlimit(int argc, char **argv)
341 char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
342 getopt32(argc, argv, "+a:c:d:f:l:m:o:p:r:s:t:",
343 &a,&c,&d,&f,&l,&m,&o,&p,&r,&s,&t);
344 if (option_mask32 & 0x001) limita = xatoul(a); // -a
345 if (option_mask32 & 0x002) limitc = xatoul(c); // -c
346 if (option_mask32 & 0x004) limitd = xatoul(d); // -d
347 if (option_mask32 & 0x008) limitf = xatoul(f); // -f
348 if (option_mask32 & 0x010) limitl = xatoul(l); // -l
349 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m
350 if (option_mask32 & 0x040) limito = xatoul(o); // -o
351 if (option_mask32 & 0x080) limitp = xatoul(p); // -p
352 if (option_mask32 & 0x100) limitr = xatoul(r); // -r
353 if (option_mask32 & 0x200) limits = xatoul(s); // -s
354 if (option_mask32 & 0x400) limitt = xatoul(t); // -t
356 if (!argv[0]) bb_show_usage();
358 execvp(argv[0], argv);
359 bb_perror_msg_and_die("exec %s", argv[0]);