diff options
Diffstat (limited to 'printutils')
-rw-r--r-- | printutils/lpd.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/printutils/lpd.c b/printutils/lpd.c index 45ad6d7e5..fe895939a 100644 --- a/printutils/lpd.c +++ b/printutils/lpd.c | |||
@@ -58,8 +58,6 @@ | |||
58 | */ | 58 | */ |
59 | #include "libbb.h" | 59 | #include "libbb.h" |
60 | 60 | ||
61 | // TODO: xmalloc_reads is vulnerable to remote OOM attack! | ||
62 | |||
63 | // strip argument of bad chars | 61 | // strip argument of bad chars |
64 | static char *sane(char *str) | 62 | static char *sane(char *str) |
65 | { | 63 | { |
@@ -75,6 +73,21 @@ static char *sane(char *str) | |||
75 | return str; | 73 | return str; |
76 | } | 74 | } |
77 | 75 | ||
76 | /* vfork() disables some optimizations. Moving its use | ||
77 | * to minimal, non-inlined function saves bytes */ | ||
78 | static NOINLINE void vfork_close_stdio_and_exec(char **argv) | ||
79 | { | ||
80 | if (vfork() == 0) { | ||
81 | // CHILD | ||
82 | // we are the helper. we wanna be silent. | ||
83 | // this call reopens stdio fds to "/dev/null" | ||
84 | // (no daemonization is done) | ||
85 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO | DAEMON_ONLY_SANITIZE, NULL); | ||
86 | BB_EXECVP(*argv, argv); | ||
87 | _exit(127); | ||
88 | } | ||
89 | } | ||
90 | |||
78 | static void exec_helper(const char *fname, char **argv) | 91 | static void exec_helper(const char *fname, char **argv) |
79 | { | 92 | { |
80 | char *p, *q, *file; | 93 | char *p, *q, *file; |
@@ -103,26 +116,24 @@ static void exec_helper(const char *fname, char **argv) | |||
103 | // next line, plz! | 116 | // next line, plz! |
104 | q = p; | 117 | q = p; |
105 | } | 118 | } |
119 | free(file); | ||
106 | 120 | ||
107 | if (vfork() == 0) { | 121 | vfork_close_stdio_and_exec(argv); |
108 | // CHILD | ||
109 | // we are the helper. we wanna be silent | ||
110 | // this call reopens stdio fds to "/dev/null" | ||
111 | // (no daemonization is done) | ||
112 | bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO | DAEMON_ONLY_SANITIZE, NULL); | ||
113 | BB_EXECVP(*argv, argv); | ||
114 | _exit(127); | ||
115 | } | ||
116 | 122 | ||
117 | // PARENT (or vfork error) | 123 | // PARENT (or vfork error) |
118 | // clean up... | 124 | // clean up... |
119 | free(file); | ||
120 | while (--env_idx >= 0) { | 125 | while (--env_idx >= 0) { |
121 | *strchrnul(our_env[env_idx], '=') = '\0'; | 126 | *strchrnul(our_env[env_idx], '=') = '\0'; |
122 | unsetenv(our_env[env_idx]); | 127 | unsetenv(our_env[env_idx]); |
123 | } | 128 | } |
124 | } | 129 | } |
125 | 130 | ||
131 | static char *xmalloc_read_stdin(void) | ||
132 | { | ||
133 | size_t max = 4 * 1024; /* more than enough for commands! */ | ||
134 | return xmalloc_reads(STDIN_FILENO, NULL, &max); | ||
135 | } | ||
136 | |||
126 | int lpd_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; | 137 | int lpd_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; |
127 | int lpd_main(int argc ATTRIBUTE_UNUSED, char *argv[]) | 138 | int lpd_main(int argc ATTRIBUTE_UNUSED, char *argv[]) |
128 | { | 139 | { |
@@ -130,7 +141,7 @@ int lpd_main(int argc ATTRIBUTE_UNUSED, char *argv[]) | |||
130 | char *s, *queue; | 141 | char *s, *queue; |
131 | 142 | ||
132 | // read command | 143 | // read command |
133 | s = xmalloc_reads(STDIN_FILENO, NULL); | 144 | s = xmalloc_read_stdin(); |
134 | 145 | ||
135 | // we understand only "receive job" command | 146 | // we understand only "receive job" command |
136 | if (2 != *s) { | 147 | if (2 != *s) { |
@@ -168,7 +179,7 @@ int lpd_main(int argc ATTRIBUTE_UNUSED, char *argv[]) | |||
168 | write(STDOUT_FILENO, "", 1); | 179 | write(STDOUT_FILENO, "", 1); |
169 | 180 | ||
170 | // get subcommand | 181 | // get subcommand |
171 | s = xmalloc_reads(STDIN_FILENO, NULL); | 182 | s = xmalloc_read_stdin(); |
172 | if (!s) | 183 | if (!s) |
173 | return EXIT_SUCCESS; // probably EOF | 184 | return EXIT_SUCCESS; // probably EOF |
174 | // we understand only "control file" or "data file" cmds | 185 | // we understand only "control file" or "data file" cmds |