Merge branch 'maint'
authorAndre Noll <maan@tuebingen.mpg.de>
Fri, 28 Jul 2017 08:03:34 +0000 (10:03 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Fri, 28 Jul 2017 08:03:34 +0000 (10:03 +0200)
A fix for an old bug which should be propagated to master and next.

* maint:
  vss: Avoid use after free in vss_send().

1  2 
vss.c

diff --combined vss.c
--- 1/vss.c
--- 2/vss.c
+++ b/vss.c
@@@ -19,9 -19,7 +19,9 @@@
  #include <arpa/inet.h>
  #include <sys/un.h>
  #include <netdb.h>
 +#include <lopsub.h>
  
 +#include "server.lsg.h"
  #include "para.h"
  #include "error.h"
  #include "portable_io.h"
@@@ -31,6 -29,7 +31,6 @@@
  #include "afs.h"
  #include "server.h"
  #include "net.h"
 -#include "server.cmdline.h"
  #include "list.h"
  #include "send.h"
  #include "sched.h"
@@@ -89,8 -88,6 +89,8 @@@ struct vss_task 
        enum afs_socket_status afsss;
        /** The memory mapped audio file. */
        char *map;
 +      /** The size of the memory mapping. */
 +      size_t mapsize;
        /** Used by the scheduler. */
        struct task *task;
        /** Pointer to the header of the mapped audio file. */
@@@ -99,8 -96,6 +99,8 @@@
        size_t header_len;
        /** Time between audio file headers are sent. */
        struct timeval header_interval;
 +      /* Only used if afh supports dynamic chunks. */
 +      void *afh_context;
  };
  
  /**
@@@ -352,8 -347,6 +352,8 @@@ static int initialize_fec_client(struc
  static void vss_get_chunk(int chunk_num, struct vss_task *vsst,
                char **buf, size_t *sz)
  {
 +      int ret;
 +
        /*
         * Chunk zero is special for header streams: It is the first portion of
         * the audio file which consists of the audio file header. It may be
         * rather than the unmodified header (chunk zero).
         */
        if (chunk_num == 0 && vsst->header_len > 0) {
 +              assert(vsst->header_buf);
                *buf = vsst->header_buf; /* stripped header */
                *sz = vsst->header_len;
                return;
        }
 -      afh_get_chunk(chunk_num, &mmd->afd.afhi, vsst->map, (const char **)buf,
 -              sz);
 +      ret = afh_get_chunk(chunk_num, &mmd->afd.afhi,
 +              mmd->afd.audio_format_id, vsst->map, vsst->mapsize,
 +              (const char **)buf, sz, &vsst->afh_context);
 +      if (ret < 0) {
 +              PARA_WARNING_LOG("could not get chunk %d: %s\n",
 +                      chunk_num, para_strerror(-ret));
 +              *buf = NULL;
 +              *sz = 0;
 +      }
  }
  
  static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
@@@ -861,7 -846,7 +861,7 @@@ static void vss_eof(struct vss_task *vs
        set_eof_barrier(vsst);
        afh_free_header(vsst->header_buf, mmd->afd.audio_format_id);
        vsst->header_buf = NULL;
 -      para_munmap(vsst->map, mmd->size);
 +      para_munmap(vsst->map, vsst->mapsize);
        vsst->map = NULL;
        mmd->chunks_sent = 0;
        //mmd->offset = 0;
        mmd->afd.afhi.chunk_tv.tv_usec = 0;
        free(mmd->afd.afhi.chunk_table);
        mmd->afd.afhi.chunk_table = NULL;
 -      mmd->size = 0;
 +      vsst->mapsize = 0;
 +      afh_close(vsst->afh_context, mmd->afd.audio_format_id);
 +      vsst->afh_context = NULL;
        mmd->events++;
  }
  
@@@ -990,11 -973,11 +990,11 @@@ static void recv_afs_result(struct vss_
                ret = -ERRNO_TO_PARA_ERROR(errno);
                goto err;
        }
 -      mmd->size = statbuf.st_size;
 -      ret = para_mmap(mmd->size, PROT_READ, MAP_PRIVATE | MAP_POPULATE,
 +      ret = para_mmap(statbuf.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE,
                passed_fd, 0, &vsst->map);
        if (ret < 0)
                goto err;
 +      vsst->mapsize = statbuf.st_size;
        close(passed_fd);
        mmd->chunks_sent = 0;
        mmd->current_chunk = 0;
        mmd->num_played++;
        mmd->new_vss_status_flags &= (~VSS_NEXT);
        afh_get_header(&mmd->afd.afhi, mmd->afd.audio_format_id,
 -              vsst->map, mmd->size, &vsst->header_buf, &vsst->header_len);
 +              vsst->map, vsst->mapsize, &vsst->header_buf, &vsst->header_len);
        return;
  err:
        free(mmd->afd.afhi.chunk_table);
@@@ -1046,9 -1029,9 +1046,9 @@@ static void vss_send(struct vss_task *v
                        continue;
                PARA_DEBUG_LOG("sending %u:%u (%u bytes)\n", fc->group.num,
                        fc->current_slice_num, fc->group.slice_bytes);
+               fc->current_slice_num++;
                fc->fcp->send_fec(fc->sc, (char *)fc->enc_buf,
                        fc->group.slice_bytes + FEC_HEADER_SIZE);
-               fc->current_slice_num++;
                fec_active = 1;
        }
        if (mmd->current_chunk >= mmd->afd.afhi.chunks_total) { /* eof */
                 */
                if (mmd->current_chunk > 0) { /* chunk 0 might be on the heap */
                        buf += len;
 -                      for (i = 0; i < 5 && buf < vsst->map + mmd->size; i++) {
 +                      for (i = 0; i < 5 && buf < vsst->map + vsst->mapsize; i++) {
                                __a_unused volatile char x = *buf;
                                buf += 4096;
                        }
@@@ -1130,7 -1113,7 +1130,7 @@@ static int vss_post_select(struct sche
                set_eof_barrier(vsst);
                mmd->chunks_sent = 0;
                mmd->current_chunk = afh_get_start_chunk(mmd->repos_request,
 -                      &mmd->afd.afhi);
 +                      &mmd->afd.afhi, mmd->afd.audio_format_id);
                mmd->new_vss_status_flags &= ~VSS_REPOS;
                set_mmd_offset();
        }
@@@ -1183,8 -1166,10 +1183,8 @@@ void init_vss_task(int afs_socket, stru
        static struct vss_task vss_task_struct, *vsst = &vss_task_struct;
        int i;
        char *hn = para_hostname(), *home = para_homedir();
 -      long unsigned announce_time = conf.announce_time_arg > 0?
 -                      conf.announce_time_arg : 300,
 -              autoplay_delay = conf.autoplay_delay_arg > 0?
 -                      conf.autoplay_delay_arg : 0;
 +      long unsigned announce_time = OPT_UINT32_VAL(ANNOUNCE_TIME),
 +              autoplay_delay = OPT_UINT32_VAL(AUTOPLAY_DELAY);
        vsst->header_interval.tv_sec = 5; /* should this be configurable? */
        vsst->afs_socket = afs_socket;
        ms2tv(announce_time, &vsst->announce_tv);
        free(hn);
        free(home);
        mmd->sender_cmd_data.cmd_num = -1;
 -      if (conf.autoplay_given) {
 +      if (OPT_GIVEN(AUTOPLAY)) {
                struct timeval tmp;
                mmd->vss_status_flags |= VSS_PLAYING;
                mmd->new_vss_status_flags |= VSS_PLAYING;