One of the sticky bits with the /* ADD CLEANUP */ part is that it is followed by exiting. A good little programmer should detect a failure at some point to allocate memory. But then all the previously allocated memory should be freed if the program is going to exit, if you are trying to be kind to the OS. This can make things a little ugly, so I left it out of the first pass. What do I mean by ugly? Something like this, perhaps.
Code:
int main()
{
   char buf[BUFSIZ], id_file[256];
   char **id_file_array;
   char **id_array;
   struct CAN_line *linenr;
   int i;

   id_file_array = malloc(LINE_COUNT * sizeof *id_file_array);
   if ( id_file_array == NULL )
   {
      return 0;
   }
   
   for ( i = 0; i < LINE_COUNT; ++i )
   {
      id_file_array[i] = malloc(30 * sizeof *id_file_array[i]);
      if ( id_file_array[i] == NULL )
      {
         while ( --i >= 0 )
         {
            free(id_file_array[i]);
         }
         free(id_file_array);
         return 0;
      }
   }

   id_array = malloc(LINE_COUNT * sizeof *id_array);
   if ( id_array == NULL )
   {
      for ( i = 0; i < LINE_COUNT; ++i )
      {
         free(id_file_array[i]);
      }
      free(id_file_array);
      return 0;
   }

   for ( i = 0; i < LINE_COUNT; ++i )
   {
      id_array[i] = malloc(30 * sizeof *id_array[i]);
      if ( id_array[i] == NULL )
      {
         while ( --i >= 0 )
         {
            free(id_array[i]);
         }
         free(id_array);
         for ( i = 0; i < LINE_COUNT; ++i )
         {
            free(id_file_array[i]);
         }
         free(id_file_array);
         return 0;
      }
   }

   linenr = malloc(LINE_COUNT * sizeof *linenr);
   if ( linenr == NULL )
   {
      for ( i = 0; i < LINE_COUNT; ++i )
      {
         free(id_file_array[i]);
         free(id_array[i]);
      }
      free(id_file_array);
      free(id_array);
      free(linenr);
      return 0;
   }

   /* ... */

   for ( i = 0; i < LINE_COUNT; ++i )
   {
      free(id_file_array[i]);
      free(id_array[i]);
   }
   free(id_file_array);
   free(id_array);
   free(linenr);
   return 0;
}
So it's not quite just adding a free or two.