Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/runit/chpst.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/runit/chpst.c
r1765 r2725 26 26 */ 27 27 28 /* Busyboxed by Den is Vlasenko <vda.linux@googlemail.com> */28 /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 29 29 /* Dependencies on runit_lib.c removed */ 30 30 31 31 #include "libbb.h" 32 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 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; 55 static int nicelvl; 56 static const char *root; 57 58 static 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 71 static 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 82 static void edir(const char *directory_name) 33 /* 34 Five applets here: chpst, envdir, envuidgid, setuidgid, softlimit. 35 36 Only softlimit and chpst are taking options: 37 38 # common 39 -o N Limit number of open files per process 40 -p N Limit number of processes per uid 41 -m BYTES Same as -d BYTES -s BYTES -l BYTES [-a BYTES] 42 -d BYTES Limit data segment 43 -f BYTES Limit output file sizes 44 -c BYTES Limit core file size 45 # softlimit 46 -a BYTES Limit total size of all segments 47 -s BYTES Limit stack segment 48 -l BYTES Limit locked memory size 49 -r BYTES Limit resident set size 50 -t N Limit CPU time 51 # chpst 52 -u USER[:GRP] Set uid and gid 53 -U USER[:GRP] Set $UID and $GID in environment 54 -e DIR Set environment variables as specified by files in DIR 55 -/ DIR Chroot to DIR 56 -n NICE Add NICE to nice value 57 -v Verbose 58 -P Create new process group 59 -0 -1 -2 Close fd 0,1,2 60 61 Even though we accept all these options for both softlimit and chpst, 62 they are not to be advertised on their help texts. 63 We have enough problems with feature creep in other people's 64 software, don't want to add our own. 65 66 envdir, envuidgid, setuidgid take no options, but they reuse code which 67 handles -e, -U and -u. 68 */ 69 70 enum { 71 OPT_a = (1 << 0) * ENABLE_SOFTLIMIT, 72 OPT_c = (1 << 1) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 73 OPT_d = (1 << 2) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 74 OPT_f = (1 << 3) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 75 OPT_l = (1 << 4) * ENABLE_SOFTLIMIT, 76 OPT_m = (1 << 5) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 77 OPT_o = (1 << 6) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 78 OPT_p = (1 << 7) * (ENABLE_SOFTLIMIT || ENABLE_CHPST), 79 OPT_r = (1 << 8) * ENABLE_SOFTLIMIT, 80 OPT_s = (1 << 9) * ENABLE_SOFTLIMIT, 81 OPT_t = (1 << 10) * ENABLE_SOFTLIMIT, 82 OPT_u = (1 << 11) * (ENABLE_CHPST || ENABLE_SETUIDGID), 83 OPT_U = (1 << 12) * (ENABLE_CHPST || ENABLE_ENVUIDGID), 84 OPT_e = (1 << 13) * (ENABLE_CHPST || ENABLE_ENVDIR), 85 OPT_root = (1 << 14) * ENABLE_CHPST, 86 OPT_n = (1 << 15) * ENABLE_CHPST, 87 OPT_v = (1 << 16) * ENABLE_CHPST, 88 OPT_P = (1 << 17) * ENABLE_CHPST, 89 OPT_0 = (1 << 18) * ENABLE_CHPST, 90 OPT_1 = (1 << 19) * ENABLE_CHPST, 91 OPT_2 = (1 << 20) * ENABLE_CHPST, 92 }; 93 94 /* TODO: use recursive_action? */ 95 static NOINLINE void edir(const char *directory_name) 83 96 { 84 97 int wdir; … … 89 102 wdir = xopen(".", O_RDONLY | O_NDELAY); 90 103 xchdir(directory_name); 91 dir = opendir("."); 92 if (!dir) 93 bb_perror_msg_and_die("opendir %s", directory_name); 104 dir = xopendir("."); 94 105 for (;;) { 106 char buf[256]; 107 char *tail; 108 int size; 109 95 110 errno = 0; 96 111 d = readdir(dir); … … 101 116 break; 102 117 } 103 if (d->d_name[0] == '.') continue; 118 if (d->d_name[0] == '.') 119 continue; 104 120 fd = open(d->d_name, O_RDONLY | O_NDELAY); 105 121 if (fd < 0) { 106 if ((errno == EISDIR) && env_dir) {107 if ( OPT_verbose)122 if ((errno == EISDIR) && directory_name) { 123 if (option_mask32 & OPT_v) 108 124 bb_perror_msg("warning: %s/%s is a directory", 109 directory_name, d->d_name);110 continue;111 } else112 bb_perror_msg_and_die("open %s/%s",113 125 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 126 continue; 127 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 } 128 bb_perror_msg_and_die("open %s/%s", 129 directory_name, d->d_name); 130 } 131 size = full_read(fd, buf, sizeof(buf)-1); 132 close(fd); 133 if (size < 0) 134 bb_perror_msg_and_die("read %s/%s", 135 directory_name, d->d_name); 136 if (size == 0) { 137 unsetenv(d->d_name); 138 continue; 139 } 140 buf[size] = '\n'; 141 tail = strchr(buf, '\n'); 142 /* skip trailing whitespace */ 143 while (1) { 144 *tail = '\0'; 145 tail--; 146 if (tail < buf || !isspace(*tail)) 147 break; 148 } 149 xsetenv(d->d_name, buf); 140 150 } 141 151 closedir(dir); 142 if (fchdir(wdir) == -1) bb_perror_msg_and_die("fchdir"); 152 if (fchdir(wdir) == -1) 153 bb_perror_msg_and_die("fchdir"); 143 154 close(wdir); 144 155 } … … 148 159 struct rlimit r; 149 160 150 if (getrlimit(what, &r) == -1) bb_perror_msg_and_die("getrlimit"); 161 /* Never fails under Linux (except if you pass it bad arguments) */ 162 getrlimit(what, &r); 151 163 if ((l < 0) || (l > r.rlim_max)) 152 164 r.rlim_cur = r.rlim_max; 153 165 else 154 166 r.rlim_cur = l; 155 if (setrlimit(what, &r) == -1) bb_perror_msg_and_die("setrlimit"); 167 if (setrlimit(what, &r) == -1) 168 bb_perror_msg_and_die("setrlimit"); 156 169 } 157 170 158 static void slimit(void) 171 int chpst_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 172 int chpst_main(int argc UNUSED_PARAM, char **argv) 159 173 { 160 if (limitd >= -1) { 174 struct bb_uidgid_t ugid; 175 char *set_user = set_user; /* for compiler */ 176 char *env_user = env_user; 177 char *env_dir = env_dir; 178 char *root; 179 char *nicestr; 180 unsigned limita; 181 unsigned limitc; 182 unsigned limitd; 183 unsigned limitf; 184 unsigned limitl; 185 unsigned limitm; 186 unsigned limito; 187 unsigned limitp; 188 unsigned limitr; 189 unsigned limits; 190 unsigned limitt; 191 unsigned opt; 192 193 if ((ENABLE_CHPST && applet_name[0] == 'c') 194 || (ENABLE_SOFTLIMIT && applet_name[1] == 'o') 195 ) { 196 // FIXME: can we live with int-sized limits? 197 // can we live with 40000 days? 198 // if yes -> getopt converts strings to numbers for us 199 opt_complementary = "-1:a+:c+:d+:f+:l+:m+:o+:p+:r+:s+:t+"; 200 opt = getopt32(argv, "+a:c:d:f:l:m:o:p:r:s:t:u:U:e:" 201 IF_CHPST("/:n:vP012"), 202 &limita, &limitc, &limitd, &limitf, &limitl, 203 &limitm, &limito, &limitp, &limitr, &limits, &limitt, 204 &set_user, &env_user, &env_dir 205 IF_CHPST(, &root, &nicestr)); 206 argv += optind; 207 if (opt & OPT_m) { // -m means -asld 208 limita = limits = limitl = limitd = limitm; 209 opt |= (OPT_s | OPT_l | OPT_a | OPT_d); 210 } 211 } else { 212 option_mask32 = opt = 0; 213 argv++; 214 if (!*argv) 215 bb_show_usage(); 216 } 217 218 // envdir? 219 if (ENABLE_ENVDIR && applet_name[3] == 'd') { 220 env_dir = *argv++; 221 opt |= OPT_e; 222 } 223 224 // setuidgid? 225 if (ENABLE_SETUIDGID && applet_name[1] == 'e') { 226 set_user = *argv++; 227 opt |= OPT_u; 228 } 229 230 // envuidgid? 231 if (ENABLE_ENVUIDGID && applet_name[0] == 'e' && applet_name[3] == 'u') { 232 env_user = *argv++; 233 opt |= OPT_U; 234 } 235 236 // we must have PROG [ARGS] 237 if (!*argv) 238 bb_show_usage(); 239 240 // set limits 241 if (opt & OPT_d) { 161 242 #ifdef RLIMIT_DATA 162 243 limit(RLIMIT_DATA, limitd); 163 244 #else 164 if (OPT_verbose) bb_error_msg("system does not support %s", 165 "RLIMIT_DATA"); 166 #endif 167 } 168 if (limits >= -1) { 245 if (opt & OPT_v) 246 bb_error_msg("system does not support RLIMIT_%s", 247 "DATA"); 248 #endif 249 } 250 if (opt & OPT_s) { 169 251 #ifdef RLIMIT_STACK 170 252 limit(RLIMIT_STACK, limits); 171 253 #else 172 if (OPT_verbose) bb_error_msg("system does not support %s", 173 "RLIMIT_STACK"); 174 #endif 175 } 176 if (limitl >= -1) { 254 if (opt & OPT_v) 255 bb_error_msg("system does not support RLIMIT_%s", 256 "STACK"); 257 #endif 258 } 259 if (opt & OPT_l) { 177 260 #ifdef RLIMIT_MEMLOCK 178 261 limit(RLIMIT_MEMLOCK, limitl); 179 262 #else 180 if (OPT_verbose) bb_error_msg("system does not support %s", 181 "RLIMIT_MEMLOCK"); 182 #endif 183 } 184 if (limita >= -1) { 263 if (opt & OPT_v) 264 bb_error_msg("system does not support RLIMIT_%s", 265 "MEMLOCK"); 266 #endif 267 } 268 if (opt & OPT_a) { 185 269 #ifdef RLIMIT_VMEM 186 270 limit(RLIMIT_VMEM, limita); … … 189 273 limit(RLIMIT_AS, limita); 190 274 #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) {275 if (opt & OPT_v) 276 bb_error_msg("system does not support RLIMIT_%s", 277 "VMEM"); 278 #endif 279 #endif 280 } 281 if (opt & OPT_o) { 198 282 #ifdef RLIMIT_NOFILE 199 283 limit(RLIMIT_NOFILE, limito); … … 202 286 limit(RLIMIT_OFILE, limito); 203 287 #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) {288 if (opt & OPT_v) 289 bb_error_msg("system does not support RLIMIT_%s", 290 "NOFILE"); 291 #endif 292 #endif 293 } 294 if (opt & OPT_p) { 211 295 #ifdef RLIMIT_NPROC 212 296 limit(RLIMIT_NPROC, limitp); 213 297 #else 214 if (OPT_verbose) bb_error_msg("system does not support %s", 215 "RLIMIT_NPROC"); 216 #endif 217 } 218 if (limitf >= -1) { 298 if (opt & OPT_v) 299 bb_error_msg("system does not support RLIMIT_%s", 300 "NPROC"); 301 #endif 302 } 303 if (opt & OPT_f) { 219 304 #ifdef RLIMIT_FSIZE 220 305 limit(RLIMIT_FSIZE, limitf); 221 306 #else 222 if (OPT_verbose) bb_error_msg("system does not support %s", 223 "RLIMIT_FSIZE"); 224 #endif 225 } 226 if (limitc >= -1) { 307 if (opt & OPT_v) 308 bb_error_msg("system does not support RLIMIT_%s", 309 "FSIZE"); 310 #endif 311 } 312 if (opt & OPT_c) { 227 313 #ifdef RLIMIT_CORE 228 314 limit(RLIMIT_CORE, limitc); 229 315 #else 230 if (OPT_verbose) bb_error_msg("system does not support %s", 231 "RLIMIT_CORE"); 232 #endif 233 } 234 if (limitr >= -1) { 316 if (opt & OPT_v) 317 bb_error_msg("system does not support RLIMIT_%s", 318 "CORE"); 319 #endif 320 } 321 if (opt & OPT_r) { 235 322 #ifdef RLIMIT_RSS 236 323 limit(RLIMIT_RSS, limitr); 237 324 #else 238 if (OPT_verbose) bb_error_msg("system does not support %s", 239 "RLIMIT_RSS"); 240 #endif 241 } 242 if (limitt >= -1) { 325 if (opt & OPT_v) 326 bb_error_msg("system does not support RLIMIT_%s", 327 "RSS"); 328 #endif 329 } 330 if (opt & OPT_t) { 243 331 #ifdef RLIMIT_CPU 244 332 limit(RLIMIT_CPU, limitt); 245 333 #else 246 if (OPT_verbose) bb_error_msg("system does not support %s", 247 "RLIMIT_CPU"); 248 #endif 249 } 334 if (opt & OPT_v) 335 bb_error_msg("system does not support RLIMIT_%s", 336 "CPU"); 337 #endif 338 } 339 340 if (opt & OPT_P) 341 setsid(); 342 343 if (opt & OPT_e) 344 edir(env_dir); 345 346 // FIXME: chrooted jail must have /etc/passwd if we move this after chroot! 347 // OTOH chroot fails for non-roots! 348 // SOLUTION: cache uid/gid before chroot, apply uid/gid after 349 if (opt & OPT_U) { 350 xget_uidgid(&ugid, env_user); 351 xsetenv("GID", utoa(ugid.gid)); 352 xsetenv("UID", utoa(ugid.uid)); 353 } 354 355 if (opt & OPT_u) { 356 xget_uidgid(&ugid, set_user); 357 } 358 359 if (opt & OPT_root) { 360 xchdir(root); 361 xchroot("."); 362 } 363 364 if (opt & OPT_u) { 365 if (setgroups(1, &ugid.gid) == -1) 366 bb_perror_msg_and_die("setgroups"); 367 xsetgid(ugid.gid); 368 xsetuid(ugid.uid); 369 } 370 371 if (opt & OPT_n) { 372 errno = 0; 373 if (nice(xatoi(nicestr)) == -1) 374 bb_perror_msg_and_die("nice"); 375 } 376 377 if (opt & OPT_0) 378 close(STDIN_FILENO); 379 if (opt & OPT_1) 380 close(STDOUT_FILENO); 381 if (opt & OPT_2) 382 close(STDERR_FILENO); 383 384 BB_EXECVP_or_die(argv); 250 385 } 251 252 /* argv[0] */253 static void setuidgid(int, char **);254 static void envuidgid(int, char **);255 static void envdir(int, char **);256 static void softlimit(int, char **);257 258 int chpst_main(int argc, char **argv);259 int 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 chpst266 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) // -u273 // if (option_mask32 & 0x2) // -U274 // if (option_mask32 & 0x4) // -e275 if (option_mask32 & 0x8) limits = limitl = limita = limitd = xatoul(m); // -m276 if (option_mask32 & 0x10) limitd = xatoul(d); // -d277 if (option_mask32 & 0x20) limito = xatoul(o); // -o278 if (option_mask32 & 0x40) limitp = xatoul(p); // -p279 if (option_mask32 & 0x80) limitf = xatoul(f); // -f280 if (option_mask32 & 0x100) limitc = xatoul(c); // -c281 if (option_mask32 & 0x200) limitr = xatoul(r); // -r282 if (option_mask32 & 0x400) limitt = xatoul(t); // -t283 // if (option_mask32 & 0x800) // -/284 if (option_mask32 & 0x1000) nicelvl = xatoi(n); // -n285 // The below consts should match #defines at top!286 //if (option_mask32 & 0x2000) OPT_verbose = 1; // -v287 //if (option_mask32 & 0x4000) OPT_pgrp = 1; // -P288 //if (option_mask32 & 0x8000) OPT_nostdin = 1; // -0289 //if (option_mask32 & 0x10000) OPT_nostdout = 1; // -1290 //if (option_mask32 & 0x20000) OPT_nostderr = 1; // -2291 }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 317 static 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 329 static 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 341 static 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 353 static 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); // -a359 if (option_mask32 & 0x002) limitc = xatoul(c); // -c360 if (option_mask32 & 0x004) limitd = xatoul(d); // -d361 if (option_mask32 & 0x008) limitf = xatoul(f); // -f362 if (option_mask32 & 0x010) limitl = xatoul(l); // -l363 if (option_mask32 & 0x020) limits = limitl = limita = limitd = xatoul(m); // -m364 if (option_mask32 & 0x040) limito = xatoul(o); // -o365 if (option_mask32 & 0x080) limitp = xatoul(p); // -p366 if (option_mask32 & 0x100) limitr = xatoul(r); // -r367 if (option_mask32 & 0x200) limits = xatoul(s); // -s368 if (option_mask32 & 0x400) limitt = xatoul(t); // -t369 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 TracChangeset
for help on using the changeset viewer.