diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-05-22 20:29:00 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-05-22 20:29:00 +0000 |
commit | aeb44c4da620cd4ec1c4f1e4f15fb227ec4dc8dc (patch) | |
tree | 34880ad3a23ca05ec02f5a53d00067d6270f703a | |
parent | 816867858b90485df6c304673cbd01d9664007b4 (diff) | |
download | busybox-w32-aeb44c4da620cd4ec1c4f1e4f15fb227ec4dc8dc.tar.gz busybox-w32-aeb44c4da620cd4ec1c4f1e4f15fb227ec4dc8dc.tar.bz2 busybox-w32-aeb44c4da620cd4ec1c4f1e4f15fb227ec4dc8dc.zip |
Fix a race. Sometimes by the time we got to checkjobs(), the
pipe struct had already been freed. Return immediately if the
pipe is NULL.
-rw-r--r-- | hush.c | 39 | ||||
-rw-r--r-- | shell/hush.c | 39 |
2 files changed, 54 insertions, 24 deletions
@@ -1243,6 +1243,9 @@ static void checkjobs() | |||
1243 | break; | 1243 | break; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | if(pi==NULL) | ||
1247 | return; | ||
1248 | |||
1246 | if (WIFEXITED(status) || WIFSIGNALED(status)) { | 1249 | if (WIFEXITED(status) || WIFSIGNALED(status)) { |
1247 | /* child exited */ | 1250 | /* child exited */ |
1248 | pi->running_progs--; | 1251 | pi->running_progs--; |
@@ -1253,8 +1256,6 @@ static void checkjobs() | |||
1253 | remove_bg_job(pi); | 1256 | remove_bg_job(pi); |
1254 | } | 1257 | } |
1255 | } else { | 1258 | } else { |
1256 | if(pi==NULL) | ||
1257 | break; | ||
1258 | /* child stopped */ | 1259 | /* child stopped */ |
1259 | pi->stopped_progs++; | 1260 | pi->stopped_progs++; |
1260 | pi->progs[prognum].is_stopped = 1; | 1261 | pi->progs[prognum].is_stopped = 1; |
@@ -1727,31 +1728,33 @@ static int set_local_var(const char *s, int flg_export) | |||
1727 | cur->flg_export=flg_export; | 1728 | cur->flg_export=flg_export; |
1728 | else | 1729 | else |
1729 | result++; | 1730 | result++; |
1731 | free(newval); | ||
1730 | } else { | 1732 | } else { |
1731 | if(cur->flg_read_only) { | 1733 | if(cur->flg_read_only) { |
1732 | result = -1; | ||
1733 | error_msg("%s: readonly variable", name); | 1734 | error_msg("%s: readonly variable", name); |
1735 | free(newval); | ||
1736 | result = -1; | ||
1734 | } else { | 1737 | } else { |
1735 | if(flg_export>0 || cur->flg_export>1) | 1738 | if(flg_export>0 || cur->flg_export>1) |
1736 | cur->flg_export=1; | 1739 | cur->flg_export=1; |
1737 | free(cur->value); | 1740 | free(cur->value); |
1738 | cur->value = newval; | 1741 | cur->value = newval; |
1739 | newval = 0; /* protect free */ | ||
1740 | } | 1742 | } |
1741 | } | 1743 | } |
1742 | } else { | 1744 | } else { |
1743 | cur = malloc(sizeof(struct variables)); | 1745 | cur = malloc(sizeof(struct variables)); |
1744 | if(cur==0) { | 1746 | if(cur==0) { |
1747 | free(newval); | ||
1745 | result = -1; | 1748 | result = -1; |
1746 | } else { | 1749 | } else { |
1747 | cur->name = strdup(name); | 1750 | cur->name = strdup(name); |
1748 | if(cur->name == 0) { | 1751 | if(cur->name == 0) { |
1749 | free(cur); | 1752 | free(cur); |
1753 | free(newval); | ||
1750 | result = -1; | 1754 | result = -1; |
1751 | } else { | 1755 | } else { |
1752 | struct variables *bottom = top_vars; | 1756 | struct variables *bottom = top_vars; |
1753 | cur->value = newval; | 1757 | cur->value = newval; |
1754 | newval = 0; /* protect free */ | ||
1755 | cur->next = 0; | 1758 | cur->next = 0; |
1756 | cur->flg_export = flg_export; | 1759 | cur->flg_export = flg_export; |
1757 | cur->flg_read_only = 0; | 1760 | cur->flg_read_only = 0; |
@@ -1770,7 +1773,6 @@ static int set_local_var(const char *s, int flg_export) | |||
1770 | if(result>0) /* equivalent to previous set */ | 1773 | if(result>0) /* equivalent to previous set */ |
1771 | result = 0; | 1774 | result = 0; |
1772 | } | 1775 | } |
1773 | free(newval); | ||
1774 | return result; | 1776 | return result; |
1775 | } | 1777 | } |
1776 | 1778 | ||
@@ -2473,10 +2475,10 @@ void update_ifs_map(void) | |||
2473 | * The map[] array only really needs two bits each, and on most machines | 2475 | * The map[] array only really needs two bits each, and on most machines |
2474 | * that would be faster because of the reduced L1 cache footprint. | 2476 | * that would be faster because of the reduced L1 cache footprint. |
2475 | */ | 2477 | */ |
2476 | memset(map,0,sizeof(map)); /* most characters flow through always */ | 2478 | memset(map,0,sizeof(map)); /* most characters flow through always */ |
2477 | mapset("\\$'\"`", 3); /* never flow through */ | 2479 | mapset("\\$'\"`", 3); /* never flow through */ |
2478 | mapset("<>;&|(){}#", 1); /* flow through if quoted */ | 2480 | mapset("<>;&|(){}#", 1); /* flow through if quoted */ |
2479 | mapset(ifs, 2); /* also flow through if quoted */ | 2481 | mapset(ifs, 2); /* also flow through if quoted */ |
2480 | } | 2482 | } |
2481 | 2483 | ||
2482 | /* most recursion does not come through here, the exeception is | 2484 | /* most recursion does not come through here, the exeception is |
@@ -2549,7 +2551,7 @@ int shell_main(int argc, char **argv) | |||
2549 | * shell_main(), therefore we cannot rely on the BSS to zero out this | 2551 | * shell_main(), therefore we cannot rely on the BSS to zero out this |
2550 | * stuff. Reset these to 0 every time. */ | 2552 | * stuff. Reset these to 0 every time. */ |
2551 | ifs = NULL; | 2553 | ifs = NULL; |
2552 | memset(map,0,sizeof(map)); | 2554 | /* map[] is taken care of with call to update_ifs_map() */ |
2553 | fake_mode = 0; | 2555 | fake_mode = 0; |
2554 | interactive = 0; | 2556 | interactive = 0; |
2555 | close_me_head = NULL; | 2557 | close_me_head = NULL; |
@@ -2650,7 +2652,20 @@ int shell_main(int argc, char **argv) | |||
2650 | opt = parse_file_outer(input); | 2652 | opt = parse_file_outer(input); |
2651 | 2653 | ||
2652 | #ifdef BB_FEATURE_CLEAN_UP | 2654 | #ifdef BB_FEATURE_CLEAN_UP |
2653 | fclose(input.file); | 2655 | fclose(input); |
2656 | if (cwd && cwd != unknown) | ||
2657 | free((char*)cwd); | ||
2658 | { | ||
2659 | struct variables *cur, *tmp; | ||
2660 | for(cur = top_vars; cur; cur = tmp) { | ||
2661 | tmp = cur->next; | ||
2662 | if (!cur->flg_read_only) { | ||
2663 | free(cur->name); | ||
2664 | free(cur->value); | ||
2665 | free(cur); | ||
2666 | } | ||
2667 | } | ||
2668 | } | ||
2654 | #endif | 2669 | #endif |
2655 | 2670 | ||
2656 | final_return: | 2671 | final_return: |
diff --git a/shell/hush.c b/shell/hush.c index 46f1a77bd..a26e2f6e3 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1243,6 +1243,9 @@ static void checkjobs() | |||
1243 | break; | 1243 | break; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | if(pi==NULL) | ||
1247 | return; | ||
1248 | |||
1246 | if (WIFEXITED(status) || WIFSIGNALED(status)) { | 1249 | if (WIFEXITED(status) || WIFSIGNALED(status)) { |
1247 | /* child exited */ | 1250 | /* child exited */ |
1248 | pi->running_progs--; | 1251 | pi->running_progs--; |
@@ -1253,8 +1256,6 @@ static void checkjobs() | |||
1253 | remove_bg_job(pi); | 1256 | remove_bg_job(pi); |
1254 | } | 1257 | } |
1255 | } else { | 1258 | } else { |
1256 | if(pi==NULL) | ||
1257 | break; | ||
1258 | /* child stopped */ | 1259 | /* child stopped */ |
1259 | pi->stopped_progs++; | 1260 | pi->stopped_progs++; |
1260 | pi->progs[prognum].is_stopped = 1; | 1261 | pi->progs[prognum].is_stopped = 1; |
@@ -1727,31 +1728,33 @@ static int set_local_var(const char *s, int flg_export) | |||
1727 | cur->flg_export=flg_export; | 1728 | cur->flg_export=flg_export; |
1728 | else | 1729 | else |
1729 | result++; | 1730 | result++; |
1731 | free(newval); | ||
1730 | } else { | 1732 | } else { |
1731 | if(cur->flg_read_only) { | 1733 | if(cur->flg_read_only) { |
1732 | result = -1; | ||
1733 | error_msg("%s: readonly variable", name); | 1734 | error_msg("%s: readonly variable", name); |
1735 | free(newval); | ||
1736 | result = -1; | ||
1734 | } else { | 1737 | } else { |
1735 | if(flg_export>0 || cur->flg_export>1) | 1738 | if(flg_export>0 || cur->flg_export>1) |
1736 | cur->flg_export=1; | 1739 | cur->flg_export=1; |
1737 | free(cur->value); | 1740 | free(cur->value); |
1738 | cur->value = newval; | 1741 | cur->value = newval; |
1739 | newval = 0; /* protect free */ | ||
1740 | } | 1742 | } |
1741 | } | 1743 | } |
1742 | } else { | 1744 | } else { |
1743 | cur = malloc(sizeof(struct variables)); | 1745 | cur = malloc(sizeof(struct variables)); |
1744 | if(cur==0) { | 1746 | if(cur==0) { |
1747 | free(newval); | ||
1745 | result = -1; | 1748 | result = -1; |
1746 | } else { | 1749 | } else { |
1747 | cur->name = strdup(name); | 1750 | cur->name = strdup(name); |
1748 | if(cur->name == 0) { | 1751 | if(cur->name == 0) { |
1749 | free(cur); | 1752 | free(cur); |
1753 | free(newval); | ||
1750 | result = -1; | 1754 | result = -1; |
1751 | } else { | 1755 | } else { |
1752 | struct variables *bottom = top_vars; | 1756 | struct variables *bottom = top_vars; |
1753 | cur->value = newval; | 1757 | cur->value = newval; |
1754 | newval = 0; /* protect free */ | ||
1755 | cur->next = 0; | 1758 | cur->next = 0; |
1756 | cur->flg_export = flg_export; | 1759 | cur->flg_export = flg_export; |
1757 | cur->flg_read_only = 0; | 1760 | cur->flg_read_only = 0; |
@@ -1770,7 +1773,6 @@ static int set_local_var(const char *s, int flg_export) | |||
1770 | if(result>0) /* equivalent to previous set */ | 1773 | if(result>0) /* equivalent to previous set */ |
1771 | result = 0; | 1774 | result = 0; |
1772 | } | 1775 | } |
1773 | free(newval); | ||
1774 | return result; | 1776 | return result; |
1775 | } | 1777 | } |
1776 | 1778 | ||
@@ -2473,10 +2475,10 @@ void update_ifs_map(void) | |||
2473 | * The map[] array only really needs two bits each, and on most machines | 2475 | * The map[] array only really needs two bits each, and on most machines |
2474 | * that would be faster because of the reduced L1 cache footprint. | 2476 | * that would be faster because of the reduced L1 cache footprint. |
2475 | */ | 2477 | */ |
2476 | memset(map,0,sizeof(map)); /* most characters flow through always */ | 2478 | memset(map,0,sizeof(map)); /* most characters flow through always */ |
2477 | mapset("\\$'\"`", 3); /* never flow through */ | 2479 | mapset("\\$'\"`", 3); /* never flow through */ |
2478 | mapset("<>;&|(){}#", 1); /* flow through if quoted */ | 2480 | mapset("<>;&|(){}#", 1); /* flow through if quoted */ |
2479 | mapset(ifs, 2); /* also flow through if quoted */ | 2481 | mapset(ifs, 2); /* also flow through if quoted */ |
2480 | } | 2482 | } |
2481 | 2483 | ||
2482 | /* most recursion does not come through here, the exeception is | 2484 | /* most recursion does not come through here, the exeception is |
@@ -2549,7 +2551,7 @@ int shell_main(int argc, char **argv) | |||
2549 | * shell_main(), therefore we cannot rely on the BSS to zero out this | 2551 | * shell_main(), therefore we cannot rely on the BSS to zero out this |
2550 | * stuff. Reset these to 0 every time. */ | 2552 | * stuff. Reset these to 0 every time. */ |
2551 | ifs = NULL; | 2553 | ifs = NULL; |
2552 | memset(map,0,sizeof(map)); | 2554 | /* map[] is taken care of with call to update_ifs_map() */ |
2553 | fake_mode = 0; | 2555 | fake_mode = 0; |
2554 | interactive = 0; | 2556 | interactive = 0; |
2555 | close_me_head = NULL; | 2557 | close_me_head = NULL; |
@@ -2650,7 +2652,20 @@ int shell_main(int argc, char **argv) | |||
2650 | opt = parse_file_outer(input); | 2652 | opt = parse_file_outer(input); |
2651 | 2653 | ||
2652 | #ifdef BB_FEATURE_CLEAN_UP | 2654 | #ifdef BB_FEATURE_CLEAN_UP |
2653 | fclose(input.file); | 2655 | fclose(input); |
2656 | if (cwd && cwd != unknown) | ||
2657 | free((char*)cwd); | ||
2658 | { | ||
2659 | struct variables *cur, *tmp; | ||
2660 | for(cur = top_vars; cur; cur = tmp) { | ||
2661 | tmp = cur->next; | ||
2662 | if (!cur->flg_read_only) { | ||
2663 | free(cur->name); | ||
2664 | free(cur->value); | ||
2665 | free(cur); | ||
2666 | } | ||
2667 | } | ||
2668 | } | ||
2654 | #endif | 2669 | #endif |
2655 | 2670 | ||
2656 | final_return: | 2671 | final_return: |