source: branches/2.2.5/mindi-busybox/runit/chpst.c @ 1765

Last change on this file since 1765 was 1765, checked in by Bruno Cornec, 13 years ago

Update to busybox 1.7.2

  • Property svn:eol-style set to native
File size: 9.8 KB
Line 
1/*
2Copyright (c) 2001-2006, Gerrit Pape
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
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.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28/* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
29/* Dependencies on runit_lib.c removed */
30
31#include "libbb.h"
32
33#include <dirent.h>
34
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)
41
42static char *set_user;
43static char *env_user;
44static const char *env_dir;
45static long limitd = -2;
46static long limits = -2;
47static long limitl = -2;
48static long limita = -2;
49static long limito = -2;
50static long limitp = -2;
51static long limitf = -2;
52static long limitc = -2;
53static long limitr = -2;
54static long limitt = -2;
55static int nicelvl;
56static const char *root;
57
58static void suidgid(char *user)
59{
60    struct bb_uidgid_t ugid;
61
62    if (!get_uidgid(&ugid, user, 1)) {
63        bb_error_msg_and_die("unknown user/group: %s", user);
64    }
65    if (setgroups(1, &ugid.gid) == -1)
66        bb_perror_msg_and_die("setgroups");
67    xsetgid(ugid.gid);
68    xsetuid(ugid.uid);
69}
70
71static void euidgid(char *user)
72{
73    struct bb_uidgid_t ugid;
74
75    if (!get_uidgid(&ugid, user, 1)) {
76        bb_error_msg_and_die("unknown user/group: %s", user);
77    }
78    xsetenv("GID", utoa(ugid.gid));
79    xsetenv("UID", utoa(ugid.uid));
80}
81
82static void edir(const char *directory_name)
83{
84    int wdir;
85    DIR *dir;
86    struct dirent *d;
87    int fd;
88
89    wdir = xopen(".", O_RDONLY | O_NDELAY);
90    xchdir(directory_name);
91    dir = opendir(".");
92    if (!dir)
93        bb_perror_msg_and_die("opendir %s", directory_name);
94    for (;;) {
95        errno = 0;
96        d = readdir(dir);
97        if (!d) {
98            if (errno)
99                bb_perror_msg_and_die("readdir %s",
100                        directory_name);
101            break;
102        }
103        if (d->d_name[0] == '.') continue;
104        fd = open(d->d_name, O_RDONLY | O_NDELAY);
105        if (fd < 0) {
106            if ((errno == EISDIR) && env_dir) {
107                if (OPT_verbose)
108                    bb_perror_msg("warning: %s/%s is a directory",
109                        directory_name, d->d_name);
110                continue;
111            } else
112                bb_perror_msg_and_die("open %s/%s",
113                        directory_name, d->d_name);
114        }
115        if (fd >= 0) {
116            char buf[256];
117            char *tail;
118            int size;
119
120            size = safe_read(fd, buf, sizeof(buf)-1);
121            if (size < 0)
122                bb_perror_msg_and_die("read %s/%s",
123                        directory_name, d->d_name);
124            if (size == 0) {
125                unsetenv(d->d_name);
126                continue;
127            }
128            buf[size] = '\n';
129            tail = memchr(buf, '\n', sizeof(buf));
130            /* skip trailing whitespace */;
131            while (1) {
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;
136                tail--;
137            }
138            xsetenv(d->d_name, buf);
139        }
140    }
141    closedir(dir);
142    if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir");
143    close(wdir);
144}
145
146static void limit(int what, long l)
147{
148    struct rlimit r;
149
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;
153    else
154        r.rlim_cur = l;
155    if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit");
156}
157
158static void slimit(void)
159{
160    if (limitd >= -1) {
161#ifdef RLIMIT_DATA
162        limit(RLIMIT_DATA, limitd);
163#else
164        if (OPT_verbose) bb_error_msg("system does not support %s",
165                "RLIMIT_DATA");
166#endif
167    }
168    if (limits >= -1) {
169#ifdef RLIMIT_STACK
170        limit(RLIMIT_STACK, limits);
171#else
172        if (OPT_verbose) bb_error_msg("system does not support %s",
173                "RLIMIT_STACK");
174#endif
175    }
176    if (limitl >= -1) {
177#ifdef RLIMIT_MEMLOCK
178        limit(RLIMIT_MEMLOCK, limitl);
179#else
180        if (OPT_verbose) bb_error_msg("system does not support %s",
181                "RLIMIT_MEMLOCK");
182#endif
183    }
184    if (limita >= -1) {
185#ifdef RLIMIT_VMEM
186        limit(RLIMIT_VMEM, limita);
187#else
188#ifdef RLIMIT_AS
189        limit(RLIMIT_AS, limita);
190#else
191        if (OPT_verbose)
192            bb_error_msg("system does not support %s",
193                "RLIMIT_VMEM");
194#endif
195#endif
196    }
197    if (limito >= -1) {
198#ifdef RLIMIT_NOFILE
199        limit(RLIMIT_NOFILE, limito);
200#else
201#ifdef RLIMIT_OFILE
202        limit(RLIMIT_OFILE, limito);
203#else
204        if (OPT_verbose)
205            bb_error_msg("system does not support %s",
206                "RLIMIT_NOFILE");
207#endif
208#endif
209    }
210    if (limitp >= -1) {
211#ifdef RLIMIT_NPROC
212        limit(RLIMIT_NPROC, limitp);
213#else
214        if (OPT_verbose) bb_error_msg("system does not support %s",
215                "RLIMIT_NPROC");
216#endif
217    }
218    if (limitf >= -1) {
219#ifdef RLIMIT_FSIZE
220        limit(RLIMIT_FSIZE, limitf);
221#else
222        if (OPT_verbose) bb_error_msg("system does not support %s",
223                "RLIMIT_FSIZE");
224#endif
225    }
226    if (limitc >= -1) {
227#ifdef RLIMIT_CORE
228        limit(RLIMIT_CORE, limitc);
229#else
230        if (OPT_verbose) bb_error_msg("system does not support %s",
231                "RLIMIT_CORE");
232#endif
233    }
234    if (limitr >= -1) {
235#ifdef RLIMIT_RSS
236        limit(RLIMIT_RSS, limitr);
237#else
238        if (OPT_verbose) bb_error_msg("system does not support %s",
239                "RLIMIT_RSS");
240#endif
241    }
242    if (limitt >= -1) {
243#ifdef RLIMIT_CPU
244        limit(RLIMIT_CPU, limitt);
245#else
246        if (OPT_verbose) bb_error_msg("system does not support %s",
247                "RLIMIT_CPU");
248#endif
249    }
250}
251
252/* argv[0] */
253static void setuidgid(int, char **);
254static void envuidgid(int, char **);
255static void envdir(int, char **);
256static void softlimit(int, char **);
257
258int chpst_main(int argc, char **argv);
259int chpst_main(int argc, char **argv)
260{
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
266
267    {
268        char *m,*d,*o,*p,*f,*c,*r,*t,*n;
269        getopt32(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
291    }
292    argv += optind;
293    if (!argv || !*argv) bb_show_usage();
294
295    if (OPT_pgrp) setsid();
296    if (env_dir) edir(env_dir);
297    if (root) {
298        xchdir(root);
299        if (chroot(".") == -1)
300            bb_perror_msg_and_die("chroot");
301    }
302    slimit();
303    if (nicelvl) {
304        errno = 0;
305        if (nice(nicelvl) == -1)
306            bb_perror_msg_and_die("nice");
307    }
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]);
315}
316
317static void setuidgid(int argc, char **argv)
318{
319    const char *account;
320
321    account = *++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]);
327}
328
329static void envuidgid(int argc, char **argv)
330{
331    const char *account;
332
333    account = *++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]);
339}
340
341static void envdir(int argc, char **argv)
342{
343    const char *dir;
344
345    dir = *++argv;
346    if (!dir) bb_show_usage();
347    if (!*++argv) bb_show_usage();
348    edir(dir);
349    BB_EXECVP(argv[0], argv);
350    bb_perror_msg_and_die("exec %s", argv[0]);
351}
352
353static void softlimit(int argc, char **argv)
354{
355    char *a,*c,*d,*f,*l,*m,*o,*p,*r,*s,*t;
356    getopt32(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
369    argv += optind;
370    if (!argv[0]) bb_show_usage();
371    slimit();
372    BB_EXECVP(argv[0], argv);
373    bb_perror_msg_and_die("exec %s", argv[0]);
374}
Note: See TracBrowser for help on using the repository browser.