]> The Tcpdump Group git mirrors - tcpdump/blobdiff - tcpdump.c
Have a common routine for converting dates and times to strings.
[tcpdump] / tcpdump.c
index c01a3753b68f23f02e4d8fc9fb80f564b0c66ea8..0b6541589f018fd61121bcb66a9fd6262d44346d 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -843,6 +843,8 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
         char *filename = malloc(PATH_MAX + 1);
         if (filename == NULL)
             error("%s: malloc", __func__);
+        if (strlen(orig_name) == 0)
+            error("an empty string is not a valid file name");
 
         /* Process with strftime if Gflag is set. */
         if (Gflag != 0) {
@@ -854,9 +856,25 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
           }
 
           /* There's no good way to detect an error in strftime since a return
-           * value of 0 isn't necessarily failure.
+           * value of 0 isn't necessarily failure; if orig_name is an empty
+           * string, the formatted string will be empty.
+           *
+           * However, the C90 standard says that, if there *is* a
+           * buffer overflow, the content of the buffer is undefined,
+           * so we must check for a buffer overflow.
+           *
+           * So we check above for an empty orig_name, and only call
+           * strftime() if it's non-empty, in which case the return
+           * value will only be 0 if the formatted date doesn't fit
+           * in the buffer.
+           *
+           * (We check above because, even if we don't use -G, we
+           * want a better error message than "tcpdump: : No such
+           * file or directory" for this case.)
            */
-          strftime(filename, PATH_MAX, orig_name, local_tm);
+          if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) {
+            error("%s: strftime", __func__);
+          }
         } else {
           strncpy(filename, orig_name, PATH_MAX);
         }
@@ -2382,17 +2400,44 @@ DIAG_ON_ASSIGN_ENUM
 #endif
                if (Cflag != 0 || Gflag != 0) {
 #ifdef HAVE_CAPSICUM
-                       dumpinfo.WFileName = strdup(basename(WFileName));
+                       /*
+                        * basename() and dirname() may modify their input buffer
+                        * and they do since FreeBSD 12.0, but they didn't before.
+                        * Hence use the return value only, but always assume the
+                        * input buffer has been modified and would need to be
+                        * reset before the next use.
+                        */
+                       char *WFileName_copy;
+
+                       if ((WFileName_copy = strdup(WFileName)) == NULL) {
+                               error("Unable to allocate memory for file %s",
+                                   WFileName);
+                       }
+                       DIAG_OFF_C11_EXTENSIONS
+                       dumpinfo.WFileName = strdup(basename(WFileName_copy));
+                       DIAG_ON_C11_EXTENSIONS
                        if (dumpinfo.WFileName == NULL) {
                                error("Unable to allocate memory for file %s",
                                    WFileName);
                        }
-                       dumpinfo.dirfd = open(dirname(WFileName),
+                       free(WFileName_copy);
+
+                       if ((WFileName_copy = strdup(WFileName)) == NULL) {
+                               error("Unable to allocate memory for file %s",
+                                   WFileName);
+                       }
+                       DIAG_OFF_C11_EXTENSIONS
+                       char *WFileName_dirname = dirname(WFileName_copy);
+                       DIAG_ON_C11_EXTENSIONS
+                       dumpinfo.dirfd = open(WFileName_dirname,
                            O_DIRECTORY | O_RDONLY);
                        if (dumpinfo.dirfd < 0) {
                                error("unable to open directory %s",
-                                   dirname(WFileName));
+                                   WFileName_dirname);
                        }
+                       free(WFileName_dirname);
+                       free(WFileName_copy);
+
                        cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL,
                            CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE);
                        if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 &&
@@ -2641,7 +2686,7 @@ DIAG_ON_ASSIGN_ENUM
 
        free(cmdbuf);
        pcap_freecode(&fcode);
-       exit_tcpdump(status == -1 ? 1 : 0);
+       exit_tcpdump(status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS);
 }
 
 /*
@@ -2657,7 +2702,14 @@ static void
 
        memset(&new, 0, sizeof(new));
        new.sa_handler = func;
-       if (sig == SIGCHLD)
+       if ((sig == SIGCHLD)
+# ifdef SIGNAL_REQ_INFO
+               || (sig == SIGNAL_REQ_INFO)
+# endif
+# ifdef SIGNAL_FLUSH_PCAP
+               || (sig == SIGNAL_FLUSH_PCAP)
+# endif
+               )
                new.sa_flags = SA_RESTART;
        if (sigaction(sig, &new, &old) < 0)
                return (SIG_ERR);