diff options
-rw-r--r-- | src/firejail/bandwidth.c | 97 | ||||
-rw-r--r-- | src/firejail/firejail.h | 9 | ||||
-rw-r--r-- | src/firejail/main.c | 45 | ||||
-rw-r--r-- | src/firejail/shutdown.c | 2 | ||||
-rw-r--r-- | src/firemon/netstats.c | 10 |
5 files changed, 79 insertions, 84 deletions
diff --git a/src/firejail/bandwidth.c b/src/firejail/bandwidth.c index b7bfb43e6..34c5ca509 100644 --- a/src/firejail/bandwidth.c +++ b/src/firejail/bandwidth.c | |||
@@ -112,28 +112,11 @@ int fibw_count(void) { | |||
112 | 112 | ||
113 | 113 | ||
114 | //*********************************** | 114 | //*********************************** |
115 | // shm file handling | 115 | // run file handling |
116 | //*********************************** | 116 | //*********************************** |
117 | void shm_create_firejail_dir(void) { | 117 | static void bandwidth_create_run_file(pid_t pid) { |
118 | struct stat s; | ||
119 | if (stat("/dev/shm/firejail", &s) == -1) { | ||
120 | /* coverity[toctou] */ | ||
121 | if (mkdir("/dev/shm/firejail", 0644) == -1) | ||
122 | errExit("mkdir"); | ||
123 | if (chown("/dev/shm/firejail", 0, 0) == -1) | ||
124 | errExit("chown"); | ||
125 | } | ||
126 | else { // check /dev/shm/firejail directory belongs to root end exit if doesn't! | ||
127 | if (s.st_uid != 0 || s.st_gid != 0) { | ||
128 | fprintf(stderr, "Error: non-root %s directory, exiting...\n", "/dev/shm/firejail"); | ||
129 | exit(1); | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void shm_create_bandwidth_file(pid_t pid) { | ||
135 | char *fname; | 118 | char *fname; |
136 | if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1) | 119 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) |
137 | errExit("asprintf"); | 120 | errExit("asprintf"); |
138 | 121 | ||
139 | // if the file already exists, do nothing | 122 | // if the file already exists, do nothing |
@@ -157,33 +140,33 @@ static void shm_create_bandwidth_file(pid_t pid) { | |||
157 | errExit("chown"); | 140 | errExit("chown"); |
158 | } | 141 | } |
159 | else { | 142 | else { |
160 | fprintf(stderr, "Error: cannot create bandwidth file in /dev/shm/firejail directory\n"); | 143 | fprintf(stderr, "Error: cannot create bandwidth file\n"); |
161 | exit(1); | 144 | exit(1); |
162 | } | 145 | } |
163 | 146 | ||
164 | free(fname); | 147 | free(fname); |
165 | } | 148 | } |
166 | 149 | ||
167 | // delete shm bandwidth file | 150 | // delete bandwidth file |
168 | void bandwidth_shm_del_file(pid_t pid) { | 151 | void bandwidth_del_run_file(pid_t pid) { |
169 | char *fname; | 152 | char *fname; |
170 | if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1) | 153 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) |
171 | errExit("asprintf"); | 154 | errExit("asprintf"); |
172 | unlink(fname); | 155 | unlink(fname); |
173 | free(fname); | 156 | free(fname); |
174 | } | 157 | } |
175 | 158 | ||
176 | void network_shm_del_file(pid_t pid) { | 159 | void network_del_run_file(pid_t pid) { |
177 | char *fname; | 160 | char *fname; |
178 | if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1) | 161 | if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) |
179 | errExit("asprintf"); | 162 | errExit("asprintf"); |
180 | unlink(fname); | 163 | unlink(fname); |
181 | free(fname); | 164 | free(fname); |
182 | } | 165 | } |
183 | 166 | ||
184 | void network_shm_set_file(pid_t pid) { | 167 | void network_set_run_file(pid_t pid) { |
185 | char *fname; | 168 | char *fname; |
186 | if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1) | 169 | if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) |
187 | errExit("asprintf"); | 170 | errExit("asprintf"); |
188 | 171 | ||
189 | // create an empty file and set mod and ownership | 172 | // create an empty file and set mod and ownership |
@@ -205,7 +188,7 @@ void network_shm_set_file(pid_t pid) { | |||
205 | errExit("chown"); | 188 | errExit("chown"); |
206 | } | 189 | } |
207 | else { | 190 | else { |
208 | fprintf(stderr, "Error: cannot create network map file in /dev/shm/firejail directory\n"); | 191 | fprintf(stderr, "Error: cannot create network map file\n"); |
209 | exit(1); | 192 | exit(1); |
210 | } | 193 | } |
211 | 194 | ||
@@ -213,11 +196,11 @@ void network_shm_set_file(pid_t pid) { | |||
213 | } | 196 | } |
214 | 197 | ||
215 | 198 | ||
216 | void shm_read_bandwidth_file(pid_t pid) { | 199 | static void read_bandwidth_file(pid_t pid) { |
217 | assert(ifbw == NULL); | 200 | assert(ifbw == NULL); |
218 | 201 | ||
219 | char *fname; | 202 | char *fname; |
220 | if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1) | 203 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) |
221 | errExit("asprintf"); | 204 | errExit("asprintf"); |
222 | 205 | ||
223 | FILE *fp = fopen(fname, "r"); | 206 | FILE *fp = fopen(fname, "r"); |
@@ -248,12 +231,12 @@ void shm_read_bandwidth_file(pid_t pid) { | |||
248 | } | 231 | } |
249 | } | 232 | } |
250 | 233 | ||
251 | void shm_write_bandwidth_file(pid_t pid) { | 234 | static void write_bandwidth_file(pid_t pid) { |
252 | if (ifbw == NULL) | 235 | if (ifbw == NULL) |
253 | return; // nothing to do | 236 | return; // nothing to do |
254 | 237 | ||
255 | char *fname; | 238 | char *fname; |
256 | if (asprintf(&fname, "/dev/shm/firejail/%d-bandwidth", (int) pid) == -1) | 239 | if (asprintf(&fname, "%s/%d-bandwidth", RUN_FIREJAIL_BANDWIDTH_DIR, (int) pid) == -1) |
257 | errExit("asprintf"); | 240 | errExit("asprintf"); |
258 | 241 | ||
259 | FILE *fp = fopen(fname, "w"); | 242 | FILE *fp = fopen(fname, "w"); |
@@ -279,33 +262,30 @@ errout: | |||
279 | // add or remove interfaces | 262 | // add or remove interfaces |
280 | //*********************************** | 263 | //*********************************** |
281 | 264 | ||
282 | // remove interface from shm file | 265 | // remove interface from run file |
283 | void bandwidth_shm_remove(pid_t pid, const char *dev) { | 266 | void bandwidth_remove(pid_t pid, const char *dev) { |
284 | // create bandwidth directory & file in case they are not in the filesystem yet | 267 | bandwidth_create_run_file(pid); |
285 | shm_create_firejail_dir(); | ||
286 | shm_create_bandwidth_file(pid); | ||
287 | 268 | ||
288 | // read bandwidth file | 269 | // read bandwidth file |
289 | shm_read_bandwidth_file(pid); | 270 | read_bandwidth_file(pid); |
290 | 271 | ||
291 | // find the element and remove it | 272 | // find the element and remove it |
292 | IFBW *elem = ifbw_find(dev); | 273 | IFBW *elem = ifbw_find(dev); |
293 | if (elem) { | 274 | if (elem) { |
294 | ifbw_remove(elem); | 275 | ifbw_remove(elem); |
295 | shm_write_bandwidth_file(pid) ; | 276 | write_bandwidth_file(pid) ; |
296 | } | 277 | } |
297 | 278 | ||
298 | // remove the file if there are no entries in the list | 279 | // remove the file if there are no entries in the list |
299 | if (ifbw == NULL) { | 280 | if (ifbw == NULL) { |
300 | bandwidth_shm_del_file(pid); | 281 | bandwidth_del_run_file(pid); |
301 | } | 282 | } |
302 | } | 283 | } |
303 | 284 | ||
304 | // add interface to shm file | 285 | // add interface to run file |
305 | void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up) { | 286 | void bandwidth_set(pid_t pid, const char *dev, int down, int up) { |
306 | // create bandwidth directory & file in case they are not in the filesystem yet | 287 | // create bandwidth directory & file in case they are not in the filesystem yet |
307 | shm_create_firejail_dir(); | 288 | bandwidth_create_run_file(pid); |
308 | shm_create_bandwidth_file(pid); | ||
309 | 289 | ||
310 | // create the new text entry | 290 | // create the new text entry |
311 | char *txt; | 291 | char *txt; |
@@ -313,7 +293,7 @@ void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up) { | |||
313 | errExit("asprintf"); | 293 | errExit("asprintf"); |
314 | 294 | ||
315 | // read bandwidth file | 295 | // read bandwidth file |
316 | shm_read_bandwidth_file(pid); | 296 | read_bandwidth_file(pid); |
317 | 297 | ||
318 | // look for an existing entry and replace the text | 298 | // look for an existing entry and replace the text |
319 | IFBW *ptr = ifbw_find(dev); | 299 | IFBW *ptr = ifbw_find(dev); |
@@ -333,7 +313,7 @@ void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up) { | |||
333 | // add it to the linked list | 313 | // add it to the linked list |
334 | ifbw_add(ifbw_new); | 314 | ifbw_add(ifbw_new); |
335 | } | 315 | } |
336 | shm_write_bandwidth_file(pid) ; | 316 | write_bandwidth_file(pid) ; |
337 | } | 317 | } |
338 | 318 | ||
339 | 319 | ||
@@ -376,15 +356,14 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in | |||
376 | free(comm); | 356 | free(comm); |
377 | 357 | ||
378 | // check network namespace | 358 | // check network namespace |
379 | EUID_ROOT(); | 359 | char *name; |
380 | char *cmd = pid_proc_cmdline(pid); | 360 | if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1) |
381 | EUID_USER(); | 361 | errExit("asprintf"); |
382 | if (!cmd || strstr(cmd, "--net") == NULL) { | 362 | struct stat s; |
363 | if (stat(name, &s) == -1) { | ||
383 | fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n"); | 364 | fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n"); |
384 | exit(1); | 365 | exit(1); |
385 | } | 366 | } |
386 | free(cmd); | ||
387 | |||
388 | 367 | ||
389 | //************************ | 368 | //************************ |
390 | // join the network namespace | 369 | // join the network namespace |
@@ -401,20 +380,20 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in | |||
401 | exit(1); | 380 | exit(1); |
402 | } | 381 | } |
403 | 382 | ||
404 | // set shm file | 383 | // set run file |
405 | if (strcmp(command, "set") == 0) | 384 | if (strcmp(command, "set") == 0) |
406 | bandwidth_shm_set(pid, dev, down, up); | 385 | bandwidth_set(pid, dev, down, up); |
407 | else if (strcmp(command, "clear") == 0) | 386 | else if (strcmp(command, "clear") == 0) |
408 | bandwidth_shm_remove(pid, dev); | 387 | bandwidth_remove(pid, dev); |
409 | 388 | ||
410 | //************************ | 389 | //************************ |
411 | // build command | 390 | // build command |
412 | //************************ | 391 | //************************ |
413 | char *devname = NULL; | 392 | char *devname = NULL; |
414 | if (dev) { | 393 | if (dev) { |
415 | // read shm network map file | 394 | // read network map file |
416 | char *fname; | 395 | char *fname; |
417 | if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1) | 396 | if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) |
418 | errExit("asprintf"); | 397 | errExit("asprintf"); |
419 | FILE *fp = fopen(fname, "r"); | 398 | FILE *fp = fopen(fname, "r"); |
420 | if (!fp) { | 399 | if (!fp) { |
@@ -449,7 +428,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in | |||
449 | } | 428 | } |
450 | 429 | ||
451 | // build fshaper.sh command | 430 | // build fshaper.sh command |
452 | cmd = NULL; | 431 | char *cmd = NULL; |
453 | if (devname) { | 432 | if (devname) { |
454 | if (strcmp(command, "set") == 0) { | 433 | if (strcmp(command, "set") == 0) { |
455 | if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s %d %d", | 434 | if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s %d %d", |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 92fd151c1..24ea53476 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -208,6 +208,7 @@ static inline int any_interface_configured(void) { | |||
208 | else | 208 | else |
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | void clear_run_files(pid_t pid); | ||
211 | 212 | ||
212 | extern int arg_private; // mount private /home | 213 | extern int arg_private; // mount private /home |
213 | extern int arg_debug; // print debug messages | 214 | extern int arg_debug; // print debug messages |
@@ -468,13 +469,11 @@ void netfilter(const char *fname); | |||
468 | void netfilter6(const char *fname); | 469 | void netfilter6(const char *fname); |
469 | 470 | ||
470 | // bandwidth.c | 471 | // bandwidth.c |
471 | void shm_create_firejail_dir(void); | 472 | void bandwidth_del_run_file(pid_t pid); |
472 | void bandwidth_shm_del_file(pid_t pid); | ||
473 | void bandwidth_shm_set(pid_t pid, const char *dev, int down, int up); | ||
474 | void bandwidth_name(const char *name, const char *command, const char *dev, int down, int up); | 473 | void bandwidth_name(const char *name, const char *command, const char *dev, int down, int up); |
475 | void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up); | 474 | void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up); |
476 | void network_shm_del_file(pid_t pid); | 475 | void network_del_run_file(pid_t pid); |
477 | void network_shm_set_file(pid_t pid); | 476 | void network_set_run_file(pid_t pid); |
478 | 477 | ||
479 | // fs_etc.c | 478 | // fs_etc.c |
480 | void fs_check_etc_list(void); | 479 | void fs_check_etc_list(void); |
diff --git a/src/firejail/main.c b/src/firejail/main.c index b029ef21e..d33a8740d 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -105,27 +105,33 @@ int fullargc = 0; | |||
105 | static pid_t child = 0; | 105 | static pid_t child = 0; |
106 | pid_t sandbox_pid; | 106 | pid_t sandbox_pid; |
107 | 107 | ||
108 | static void set_name_file(uid_t pid); | 108 | static void set_name_file(pid_t pid); |
109 | static void delete_name_file(uid_t pid); | 109 | static void delete_name_file(pid_t pid); |
110 | static void set_x11_file(uid_t pid, int display); | 110 | static void set_x11_file(pid_t pid, int display); |
111 | static void delete_x11_file(uid_t pid); | 111 | static void delete_x11_file(pid_t pid); |
112 | |||
113 | void clear_run_files(pid_t pid) { | ||
114 | bandwidth_del_run_file(pid); // bandwidth file | ||
115 | network_del_run_file(pid); // network map file | ||
116 | delete_name_file(pid); | ||
117 | delete_x11_file(pid); | ||
118 | } | ||
112 | 119 | ||
113 | static void myexit(int rv) { | 120 | static void myexit(int rv) { |
114 | logmsg("exiting..."); | 121 | logmsg("exiting..."); |
115 | if (!arg_command && !arg_quiet) | 122 | if (!arg_command && !arg_quiet) |
116 | printf("\nparent is shutting down, bye...\n"); | 123 | printf("\nparent is shutting down, bye...\n"); |
117 | 124 | ||
125 | |||
118 | // delete sandbox files in shared memory | 126 | // delete sandbox files in shared memory |
119 | bandwidth_shm_del_file(sandbox_pid); // bandwidth file | 127 | EUID_ROOT(); |
120 | network_shm_del_file(sandbox_pid); // network map file | 128 | clear_run_files(sandbox_pid); |
121 | delete_name_file(sandbox_pid); | ||
122 | delete_x11_file(sandbox_pid); | ||
123 | 129 | ||
124 | exit(rv); | 130 | exit(rv); |
125 | } | 131 | } |
126 | 132 | ||
127 | static void my_handler(int s){ | 133 | static void my_handler(int s){ |
128 | EUID_ROOT(); | 134 | EUID_ROOT(); |
129 | if (!arg_quiet) | 135 | if (!arg_quiet) |
130 | printf("\nSignal %d caught, shutting down the child process\n", s); | 136 | printf("\nSignal %d caught, shutting down the child process\n", s); |
131 | logsignal(s); | 137 | logsignal(s); |
@@ -615,7 +621,7 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
615 | 621 | ||
616 | } | 622 | } |
617 | 623 | ||
618 | static void set_name_file(uid_t pid) { | 624 | static void set_name_file(pid_t pid) { |
619 | char *fname; | 625 | char *fname; |
620 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_NAME_DIR, pid) == -1) | 626 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_NAME_DIR, pid) == -1) |
621 | errExit("asprintf"); | 627 | errExit("asprintf"); |
@@ -637,7 +643,7 @@ static void set_name_file(uid_t pid) { | |||
637 | 643 | ||
638 | } | 644 | } |
639 | 645 | ||
640 | static void delete_name_file(uid_t pid) { | 646 | static void delete_name_file(pid_t pid) { |
641 | char *fname; | 647 | char *fname; |
642 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_NAME_DIR, pid) == -1) | 648 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_NAME_DIR, pid) == -1) |
643 | errExit("asprintf"); | 649 | errExit("asprintf"); |
@@ -645,7 +651,7 @@ static void delete_name_file(uid_t pid) { | |||
645 | (void) rv; | 651 | (void) rv; |
646 | } | 652 | } |
647 | 653 | ||
648 | static void set_x11_file(uid_t pid, int display) { | 654 | static void set_x11_file(pid_t pid, int display) { |
649 | char *fname; | 655 | char *fname; |
650 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_X11_DIR, pid) == -1) | 656 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_X11_DIR, pid) == -1) |
651 | errExit("asprintf"); | 657 | errExit("asprintf"); |
@@ -667,7 +673,7 @@ static void set_x11_file(uid_t pid, int display) { | |||
667 | 673 | ||
668 | } | 674 | } |
669 | 675 | ||
670 | static void delete_x11_file(uid_t pid) { | 676 | static void delete_x11_file(pid_t pid) { |
671 | char *fname; | 677 | char *fname; |
672 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_X11_DIR, pid) == -1) | 678 | if (asprintf(&fname, "%s/%d", RUN_FIREJAIL_X11_DIR, pid) == -1) |
673 | errExit("asprintf"); | 679 | errExit("asprintf"); |
@@ -772,9 +778,11 @@ int main(int argc, char **argv) { | |||
772 | // check firejail directories | 778 | // check firejail directories |
773 | EUID_ROOT(); | 779 | EUID_ROOT(); |
774 | fs_build_firejail_dir(); | 780 | fs_build_firejail_dir(); |
775 | // todo: deprecate shm functions | 781 | bandwidth_del_run_file(sandbox_pid); |
776 | shm_create_firejail_dir(); | 782 | network_del_run_file(sandbox_pid); |
777 | bandwidth_shm_del_file(sandbox_pid); | 783 | delete_name_file(sandbox_pid); |
784 | delete_x11_file(sandbox_pid); | ||
785 | |||
778 | EUID_USER(); | 786 | EUID_USER(); |
779 | 787 | ||
780 | //check if the parent is sshd daemon | 788 | //check if the parent is sshd daemon |
@@ -1926,7 +1934,7 @@ int main(int argc, char **argv) { | |||
1926 | check_network(&cfg.bridge3); | 1934 | check_network(&cfg.bridge3); |
1927 | 1935 | ||
1928 | // save network mapping in shared memory | 1936 | // save network mapping in shared memory |
1929 | network_shm_set_file(sandbox_pid); | 1937 | network_set_run_file(sandbox_pid); |
1930 | EUID_USER(); | 1938 | EUID_USER(); |
1931 | } | 1939 | } |
1932 | 1940 | ||
@@ -2089,6 +2097,7 @@ int main(int argc, char **argv) { | |||
2089 | EUID_USER(); | 2097 | EUID_USER(); |
2090 | int status = 0; | 2098 | int status = 0; |
2091 | waitpid(child, &status, 0); | 2099 | waitpid(child, &status, 0); |
2100 | printf("after wait\n"); | ||
2092 | 2101 | ||
2093 | // free globals | 2102 | // free globals |
2094 | #ifdef HAVE_SECCOMP | 2103 | #ifdef HAVE_SECCOMP |
diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c index b7ef48c8d..94ca0a816 100644 --- a/src/firejail/shutdown.c +++ b/src/firejail/shutdown.c | |||
@@ -98,4 +98,6 @@ void shut(pid_t pid) { | |||
98 | printf("Sending SIGKILL to %u\n", parent); | 98 | printf("Sending SIGKILL to %u\n", parent); |
99 | kill(parent, SIGKILL); | 99 | kill(parent, SIGKILL); |
100 | } | 100 | } |
101 | |||
102 | clear_run_files(parent); | ||
101 | } | 103 | } |
diff --git a/src/firemon/netstats.c b/src/firemon/netstats.c index 3b6c128ae..89e4202bd 100644 --- a/src/firemon/netstats.c +++ b/src/firemon/netstats.c | |||
@@ -117,8 +117,14 @@ static void print_proc(int index, int itv, int col) { | |||
117 | } | 117 | } |
118 | else | 118 | else |
119 | ptrcmd = cmd; | 119 | ptrcmd = cmd; |
120 | // if the command doesn't have a --net= option, don't print | 120 | |
121 | if (strstr(ptrcmd, "--net=") == NULL) { | 121 | // check network namespace |
122 | char *name; | ||
123 | if (asprintf(&name, "/run/firejail/network/%d-netmap", index) == -1) | ||
124 | errExit("asprintf"); | ||
125 | struct stat s; | ||
126 | if (stat(name, &s) == -1) { | ||
127 | // the sandbox doesn't have a --net= option, don't print | ||
122 | if (cmd) | 128 | if (cmd) |
123 | free(cmd); | 129 | free(cmd); |
124 | return; | 130 | return; |