Changeset 1598 in kBuild
- Timestamp:
- May 1, 2008 9:52:59 PM (17 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/Makefile.am
r1526 r1598 75 75 kmkbuiltin/strlcpy.c \ 76 76 kmkbuiltin/osdep.c \ 77 kmkbuiltin/kbuild_protection.c \ 77 78 kmkbuiltin/kbuild_version.c 78 79 -
trunk/src/kmk/Makefile.kmk
r1526 r1598 82 82 kmkbuiltin/strmode.c \ 83 83 kmkbuiltin/kbuild_version.c \ 84 kmkbuiltin/kbuild_protection.c \ 84 85 getopt.c \ 85 86 getopt1.c \ -
trunk/src/kmk/kmkbuiltin/rm.c
r1578 r1598 67 67 # include <direct.h> 68 68 # include <limits.h> 69 #endif 69 #endif 70 70 #include "kmkbuiltin.h" 71 #include "kbuild_protection.h" 71 72 72 73 #if defined(__EMX__) || defined(_MSC_VER) … … 94 95 #endif 95 96 96 static int protectionflag, fullprotectionflag, protectiondepth;97 97 static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok; 98 98 static uid_t uid; 99 99 100 100 static char *argv0; 101 static KBUILDPROTECTION g_ProtData; 101 102 102 103 static struct option long_options[] = … … 115 116 static int check(char *, char *, struct stat *); 116 117 static void checkdot(char **); 117 static voidrm_file(char **);118 static int rm_file(char **); 118 119 static int rm_overwrite(char *, struct stat *); 119 static voidrm_tree(char **);120 static int rm_tree(char **); 120 121 static int count_path_components(const char *); 121 122 static int set_protection_depth(const char *); … … 140 141 argv0 = argv[0]; 141 142 dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0; 142 fullprotectionflag = 0;143 protectionflag = 1;144 protectiondepth = DEFAULT_PROTECTION_DEPTH;145 143 uid = 0; 144 kBuildProtectionInit(&g_ProtData); 146 145 147 146 /* kmk: reset getopt and set program name. */ … … 184 183 #endif 185 184 case 261: 185 kBuildProtectionTerm(&g_ProtData); 186 186 usage(stdout); 187 187 return 0; 188 188 case 262: 189 kBuildProtectionTerm(&g_ProtData); 189 190 return kbuild_version(argv[0]); 190 191 case 263: 191 protectionflag = 0;192 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); 192 193 break; 193 194 case 264: 194 protectionflag = 1;195 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); 195 196 break; 196 197 case 265: 197 fullprotectionflag = 1;198 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL); 198 199 break; 199 200 case 266: 200 fullprotectionflag = 0;201 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL); 201 202 break; 202 203 case 267: 203 set_protection_depth(optarg); 204 if (kBuildProtectionSetDepth(&g_ProtData, optarg)) { 205 kBuildProtectionTerm(&g_ProtData); 206 return 1; 207 } 204 208 break; 205 209 case '?': 206 210 default: 211 kBuildProtectionTerm(&g_ProtData); 207 212 return usage(stderr); 208 213 } … … 211 216 212 217 if (argc < 1) { 218 kBuildProtectionTerm(&g_ProtData); 213 219 if (fflag) 214 220 return (0); … … 216 222 } 217 223 218 /* Search the environment for option overrides (protection). */ 219 for (i = 0; envp[i]; i++) { 220 if (!strncmp(envp[i], "KMK_RM_", sizeof("KMK_RM_") - 1)) { 221 if (!strncmp(envp[i], "KMK_RM_PROTECTION_DEPTH=", sizeof("KMK_RM_PROTECTION_DEPTH=") - 1)) { 222 const char *val = envp[i] + sizeof("KMK_RM_PROTECTION_DEPTH=") - 1; 223 if (set_protection_depth(val)) 224 return eval; 225 } else if (!strncmp(envp[i], "KMK_RM_DISABLE_PROTECTION=", sizeof("KMK_RM_DISABLE_PROTECTION=") - 1)) { 226 if (protectionflag >= 0) 227 protectionflag = 0; 228 } else if (!strncmp(envp[i], "KMK_RM_ENABLE_PROTECTION=", sizeof("KMK_RM_ENABLE_PROTECTION=") - 1)) { 229 protectionflag = -1; 230 } else if (!strncmp(envp[i], "KMK_RM_DISABLE_FULL_PROTECTION=", sizeof("KMK_RM_DISABLE_FULL_PROTECTION=") - 1)) { 231 if (fullprotectionflag >= 0) 232 fullprotectionflag = 0; 233 } else if (!strncmp(envp[i], "KMK_RM_ENABLE_FULL_PROTECTION=", sizeof("KMK_RM_ENABLE_FULL_PROTECTION=") - 1)) { 234 fullprotectionflag = protectionflag = -1; 235 } 236 } 237 } 238 if (fullprotectionflag) 239 protectionflag = 1; 240 241 checkdot(argv); 242 uid = geteuid(); 243 244 if (*argv) { 245 stdin_ok = isatty(STDIN_FILENO); 246 if (rflag) 247 rm_tree(argv); 248 else 249 rm_file(argv); 250 } 251 224 if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_RM_")) { 225 checkdot(argv); 226 uid = geteuid(); 227 228 if (*argv) { 229 stdin_ok = isatty(STDIN_FILENO); 230 if (rflag) 231 eval |= rm_tree(argv); 232 else 233 eval |= rm_file(argv); 234 } 235 } else { 236 eval = 1; 237 } 238 239 kBuildProtectionTerm(&g_ProtData); 252 240 return eval; 253 241 } 254 242 255 /**256 * Sets protectiondepth according to the option argument.257 *258 * @returns eval, that is 0 on success and non-zero on failure259 *260 * @param val The value.261 */262 243 static int 263 set_protection_depth(const char *val)264 {265 /* skip leading blanks, they don't count either way. */266 while (isspace(*val))267 val++;268 269 /* number or path? */270 if (!isdigit(*val) || strpbrk(val, ":/\\")) {271 protectiondepth = count_path_components(val);272 } else {273 char *more = 0;274 protectiondepth = strtol(val, &more, 0);275 if (protectiondepth != 0 && more) {276 /* trailing space is harmless. */277 while (isspace(*more))278 more++;279 }280 if (!protectiondepth || val == more || *more)281 return eval = errx(1, "bogus protection depth: %s", val);282 }283 284 if (protectiondepth < 1)285 return eval = errx(1, "bogus protection depth: %s", val);286 return eval;287 }288 289 /**290 * Counts the components in the specified sub path.291 * This is a helper for count_path_components.292 *293 * etc = 1294 * etc/ = 1295 * etc/x11 = 2296 * and so and and so forth.297 */298 static int299 count_sub_path_components(const char *path, int depth)300 {301 for (;;) {302 const char *end;303 size_t len;304 305 /* skip slashes. */306 while (IS_SLASH(*path))307 path++;308 if (!*path)309 break;310 311 /* find end of component. */312 end = path;313 while (!IS_SLASH(*end) && *end)314 end++;315 316 /* count it, checking for '..' and '.'. */317 len = end - path;318 if (len == 2 && path[0] == '.' && path[1] == '.') {319 if (depth > 0)320 depth--;321 } else if (len != 1 || path[0] != '.') {322 depth++;323 }324 325 /* advance */326 if (!*end)327 break;328 path = end + 1;329 }330 return depth;331 }332 333 /**334 * Parses the specified path counting the number of components335 * relative to root.336 *337 * We don't check symbolic links and such, just some simple and cheap338 * path parsing.339 *340 * @param path The path to process.341 *342 * @returns 0 or higher on success.343 * On failure an error is printed, eval is set and -1 is returned.344 */345 static int346 count_path_components(const char *path)347 {348 int components = 0;349 350 /*351 * Deal with root, UNC, drive letter.352 */353 #if defined(_MSC_VER) || defined(__OS2__)354 if (IS_SLASH(path[0]) && IS_SLASH(path[1]) && !IS_SLASH(path[2])) {355 /* skip the root - UNC */356 path += 3;357 while (!IS_SLASH(*path) && *path) /* server name */358 path++;359 while (IS_SLASH(*path))360 path++;361 while (!IS_SLASH(*path) && *path) /* share name */362 path++;363 while (IS_SLASH(*path))364 path++;365 } else {366 unsigned drive_letter = (unsigned)toupper(path[0]) - (unsigned)'A';367 if (drive_letter <= (unsigned)('Z' - 'A') && path[1] == ':') {368 drive_letter++; /* A == 1 */369 } else {370 drive_letter = 0; /* 0 == default */371 }372 373 if (!IS_SLASH(path[drive_letter ? 2 : 0])) {374 /*375 * Relative path, must count cwd depth first.376 */377 #ifdef __OS2__ /** @todo remove when ticket 194 has been fixed */378 char *cwd = _getdcwd(drive_letter, NULL, PATH_MAX);379 #else380 char *cwd = _getdcwd(drive_letter, NULL, 0);381 #endif382 char *tmp = cwd;383 if (!tmp) {384 eval = err(1, "_getdcwd");385 return -1;386 }387 388 if (IS_SLASH(tmp[0]) && IS_SLASH(tmp[1])) {389 /* skip the root - UNC */390 tmp += 2;391 while (!IS_SLASH(*tmp) && *tmp) /* server name */392 tmp++;393 while (IS_SLASH(*tmp))394 tmp++;395 while (!IS_SLASH(*tmp) && *tmp) /* share name */396 tmp++;397 } else {398 /* skip the drive letter and while we're at it, the root slash too. */399 tmp += 1 + (tmp[1] == ':');400 }401 components = count_sub_path_components(tmp, 0);402 free(cwd);403 } else {404 /* skip the drive letter and while we're at it, the root slash too. */405 path += drive_letter ? 3 : 1;406 }407 }408 #else409 if (!IS_SLASH(path[0])) {410 /*411 * Relative path, must count cwd depth first.412 */413 char cwd[4096];414 if (!getcwd(cwd, sizeof(cwd))) {415 eval = err(1, "getcwd");416 return -1;417 }418 components = count_sub_path_components(cwd, 0);419 }420 #endif421 422 /*423 * We're now past any UNC or drive letter crap, possibly positioned424 * at the root slash or at the start of a path component at the425 * given depth. Count the remainder.426 */427 return count_sub_path_components(path, components);428 }429 430 431 /**432 * Protect the upper layers of the file system against accidental433 * or malicious deletetion attempt from within a makefile.434 *435 * @param path The path to check.436 * @param required_depth The minimum number of components in the437 * path counting from the root.438 *439 * @returns 0 on success.440 * On failure an error is printed, eval is set and -1 is returned.441 */442 static int443 enforce_protection(const char *path, int required_depth)444 {445 int components;446 447 /*448 * Count the path and compare it with the required depth.449 */450 components = count_path_components(path);451 if (components < 0)452 return -1;453 if (components < required_depth) {454 eval = errx(1, "%s: protected", path);455 return -1;456 }457 return 0;458 }459 460 static void461 244 rm_tree(char **argv) 462 245 { … … 471 254 * everything, but we'll check the individual items later. 472 255 */ 473 if (protectionflag) { 474 int i; 475 for (i = 0; argv[i]; i++) { 476 if (enforce_protection(argv[i], protectiondepth + 1)) 477 return; 256 int i; 257 for (i = 0; argv[i]; i++) { 258 if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) { 259 return 1; 478 260 } 479 261 } … … 499 281 #endif 500 282 if (!(fts = fts_open(argv, flags, NULL))) { 501 eval = err(1, "fts_open"); 502 return; 283 return err(1, "fts_open"); 503 284 } 504 285 while ((p = fts_read(fts)) != NULL) { … … 512 293 continue; 513 294 case FTS_ERR: 514 eval = errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));515 295 fts_close(fts); 516 return ;296 return errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno)); 517 297 case FTS_NS: 518 298 /* … … 558 338 * Protect against deleting root files and directories. 559 339 */ 560 if ( protectionflag && enforce_protection(p->fts_accpath, protectiondepth + 1)) {340 if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) { 561 341 fts_close(fts); 562 return ;342 return 1; 563 343 } 564 344 … … 640 420 } 641 421 fts_close(fts); 422 return eval; 642 423 } 643 424 644 static void425 static int 645 426 rm_file(char **argv) 646 427 { … … 652 433 * Check up front before anything is deleted. 653 434 */ 654 if (fullprotectionflag) { 655 int i; 656 for (i = 0; argv[i]; i++) { 657 if (enforce_protection(argv[i], protectiondepth + 1)) 658 return; 659 } 435 int i; 436 for (i = 0; argv[i]; i++) { 437 if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i])) 438 return 1; 660 439 } 661 440 … … 714 493 #ifdef _MSC_VER 715 494 if (rval != 0) { 716 495 chmod(f, 0777); 717 496 rval = unlink(f); 718 497 } … … 727 506 (void)printf("%s\n", f); 728 507 } 508 return eval; 729 509 } 730 510 … … 836 616 if ((flagsp = fflagstostr(sp->st_flags)) == NULL) 837 617 exit(err(1, "fflagstostr")); 838 839 840 841 842 843 618 (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ", 619 modep + 1, modep[9] == ' ' ? "" : " ", 620 user_from_uid(sp->st_uid, 0), 621 group_from_gid(sp->st_gid, 0), 622 *flagsp ? flagsp : "", *flagsp ? " " : "", 623 path); 844 624 free(flagsp); 845 625 #else 846 847 848 849 626 (void)flagsp; 627 (void)fprintf(stderr, "override %s%s %d/%d for %s? ", 628 modep + 1, modep[9] == ' ' ? "" : " ", 629 sp->st_uid, sp->st_gid, path); 850 630 #endif 851 631 } … … 951 731 , 952 732 g_progname, g_progname, g_progname, 953 DEFAULT_PROTECTION_DEPTH, DEFAULT_PROTECTION_DEPTH);733 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth()); 954 734 return EX_USAGE; 955 735 }
Note:
See TracChangeset
for help on using the changeset viewer.