RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  j...@rpm5.org
  Module: rpm                              Date:   04-Apr-2016 06:21:40
  Branch: rpm-5_4                          Handle: 2016040404214000

  Modified files:           (Branch: rpm-5_4)
    rpm/rpmdb               pkgio.c

  Log:
    - pkgio: fix: can't retrofit a trailer tag fix with PROT_READ in place.
    - pkgio: improved santy checks for {il,dl} based on file size.

  Summary:
    Revision    Changes     Path
    1.121.2.18  +82 -22     rpm/rpmdb/pkgio.c
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/rpmdb/pkgio.c
  ============================================================================
  $ cvs diff -u -r1.121.2.17 -r1.121.2.18 pkgio.c
  --- rpm/rpmdb/pkgio.c 2 Apr 2016 23:01:12 -0000       1.121.2.17
  +++ rpm/rpmdb/pkgio.c 4 Apr 2016 04:21:40 -0000       1.121.2.18
  @@ -706,16 +706,20 @@
    * @param siglen             signature header size
    * @param pad                        signature padding
    * @param datalen            length of header+payload
  + * @retval *st                       stat(2) of input file
    * @return                   rpmRC return code
    */
  -static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, size_t 
datalen)
  +static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad,
  +             size_t datalen, struct stat *st)
        /*@globals fileSystem, internalState @*/
        /*@modifies fileSystem, internalState @*/
   {
  -    struct stat sb, * st = &sb;
       size_t expected;
       size_t nl = rpmpkgSizeof("Lead", NULL);
   
  +    if (st == NULL)
  +     st = memset(alloca(sizeof(*st)), 0, sizeof(*st));
  +
   #ifndef      DYING   /* XXX Fstat(2) contentLength not gud enuf yet. */
       int fdno = Fileno(fd);
       /* HACK: workaround for davRead wiring. */
  @@ -775,6 +779,7 @@
       rpmRC rc = RPMRC_FAIL;           /* assume failure */
       int xx;
       rpmuint32_t i;
  +    struct stat sb, *st = &sb;
       static int map = 1;
   
   if (_pkgio_debug)
  @@ -794,6 +799,13 @@
            goto exit;
        }
       }
  +
  +    if (Fstat(fd, st) < 0) {
  +     (void) snprintf(buf, sizeof(buf),
  +             _("sigh stat: BAD, Fstat(2) failed"));
  +     goto exit;
  +    }
  +
       startoff = fd->stats->ops[FDSTAT_READ].bytes;
       if ((xx = (int) timedRead(fd, (char *)block, sizeof(block))) != (int) 
sizeof(block)) {
        (void) snprintf(buf, sizeof(buf),
  @@ -814,22 +826,28 @@
            goto exit;
        }
       }
  +    /* XXX arbitrary limit check doesn't help much */
       il = (rpmuint32_t) ntohl(block[2]);
  -    if (il > 32) {
  +    if (il > (st->st_size - startoff - sizeof(block)) || il > 32) {
        (void) snprintf(buf, sizeof(buf),
                _("sigh tags: BAD, no. of tags(%u) out of range"), (unsigned) 
il);
        goto exit;
       }
  +    /* XXX arbitrary limit check doesn't help much */
       dl = (rpmuint32_t) ntohl(block[3]);
  -    if (dl > 8192) {
  +    if (dl > (st->st_size - startoff - sizeof(block)) || dl > 8192) {
        (void) snprintf(buf, sizeof(buf),
                _("sigh data: BAD, no. of bytes(%u) out of range"), (unsigned) 
dl);
        goto exit;
       }
   
  -/*@-sizeoftype@*/
       nb = (il * sizeof(struct entryInfo_s)) + dl;
  -/*@=sizeoftype@*/
  +    if (nb > (st->st_size - startoff - sizeof(block))) {
  +     (void) snprintf(buf, sizeof(buf),
  +             _("hdr blob: BAD, header size (%u) larger than file size"),
  +             (unsigned) nb);
  +       goto exit;
  +    }
       if (map) {
        size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
           static const int prot = PROT_READ | PROT_WRITE;
  @@ -844,7 +862,8 @@
                   "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n",
                   NULL, (unsigned)pvlen, prot, flags, fdno, (unsigned)off,
                   errno, strerror(errno));
  -    } else {
  +    } else
  +    {
        size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
        ei = (rpmuint32_t *) xmalloc(pvlen);
       }
  @@ -915,7 +934,9 @@
        if (info->tag == (rpmuint32_t) htonl(RPMTAG_HEADERIMAGE)) {
            rpmuint32_t stag = (rpmuint32_t) htonl(RPMTAG_HEADERSIGNATURES);
            info->tag = (rpmTag) stag;
  +#ifdef       DYING   /* XXX can't retrofit with PROT_READ */
            memcpy(dataEnd, &stag, sizeof(stag));
  +#endif
        }
        dataEnd += REGION_TAG_COUNT;
   
  @@ -986,7 +1007,7 @@
        xx = headerGet(sigh, he, HEADERGET_SIGHEADER);
        if (xx) {
            size_t datasize = he->p.ui32p[0];
  -         rc = printSize(fd, sigSize, pad, datasize);
  +         rc = printSize(fd, sigSize, pad, datasize, st);
            if (rc != RPMRC_OK)
                (void) snprintf(buf, sizeof(buf),
                        _("sigh sigSize(%u): BAD, Fstat(2) failed"), (unsigned) 
sigSize);
  @@ -1255,7 +1276,7 @@
        buf[sizeof(buf)-1] = '\0';
        if (msg) *msg = xstrdup(buf);
   if (_pkgio_debug)
  -fprintf(stderr, "<-- headerCheck #1: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
  +fprintf(stderr, "<-- headerCheck#1: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
        return rc;
       }
   
  @@ -1275,7 +1296,7 @@
        buf[sizeof(buf)-1] = '\0';
        if (msg) *msg = xstrdup(buf);
   if (_pkgio_debug)
  -fprintf(stderr, "<-- headerCheck #2: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
  +fprintf(stderr, "<-- headerCheck#2: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
        return rc;
       }
   
  @@ -1298,9 +1319,15 @@
        /* Parse the parameters from the OpenPGP packets that will be needed. */
        pleft = info->count;
        xx = pgpPktLen((const rpmuint8_t *)sig, pleft, pp);
  +     if (xx < 0) {
  +         rpmlog(RPMLOG_ERR,
  +             _("skipping header with malformed RSA signature packet\n"));
  +         rc = RPMRC_FAIL;
  +         goto exit;
  +     }
        xx = rpmhkpLoadSignature(NULL, dig, pp);
  -     if (dig->signature.version != (rpmuint8_t)3
  -      && dig->signature.version != (rpmuint8_t)4)
  +     if (xx < 0
  +      || (dig->signature.version != 3 && dig->signature.version != 4))
        {
            rpmlog(RPMLOG_ERR,
                _("skipping header with unverifiable V%u signature\n"),
  @@ -1317,9 +1344,15 @@
        /* Parse the parameters from the OpenPGP packets that will be needed. */
        pleft = info->count;
        xx = pgpPktLen((const rpmuint8_t *)sig, pleft, pp);
  +     if (xx < 0) {
  +         rpmlog(RPMLOG_ERR,
  +             _("skipping header with malformed DSA signature packet\n"));
  +         rc = RPMRC_FAIL;
  +         goto exit;
  +     }
        xx = rpmhkpLoadSignature(NULL, dig, pp);
  -     if (dig->signature.version != (rpmuint8_t)3
  -      && dig->signature.version != (rpmuint8_t)4)
  +     if (xx < 0
  +      || (dig->signature.version != 3 && dig->signature.version != 4))
        {
            rpmlog(RPMLOG_ERR,
                _("skipping header with unverifiable V%u signature\n"),
  @@ -1336,9 +1369,15 @@
        /* Parse the parameters from the OpenPGP packets that will be needed. */
        pleft = info->count;
        xx = pgpPktLen((const rpmuint8_t *)sig, pleft, pp);
  +     if (xx < 0) {
  +         rpmlog(RPMLOG_ERR,
  +             _("skipping header with malformed ECDSA signature packet\n"));
  +         rc = RPMRC_FAIL;
  +         goto exit;
  +     }
        xx = rpmhkpLoadSignature(NULL, dig, pp);
  -     if (dig->signature.version != (rpmuint8_t)3
  -      && dig->signature.version != (rpmuint8_t)4)
  +     if (xx < 0
  +      || (dig->signature.version != 3 && dig->signature.version != 4))
        {
            rpmlog(RPMLOG_ERR,
                _("skipping header with unverifiable V%u signature\n"),
  @@ -1442,6 +1481,7 @@
       rpmRC rc = RPMRC_FAIL;           /* assume failure */
       int xx;
       static int map = 1;
  +    struct stat sb, *st = &sb;
   
   if (_pkgio_debug)
   fprintf(stderr, "--> rpmReadHeader(%p, %p, %p)\n", fd, hdrp, msg);
  @@ -1468,6 +1508,12 @@
        }
       }
   
  +    if (Fstat(fd, st) < 0) {
  +     (void) snprintf(buf, sizeof(buf),
  +             _("hdr stat: BAD, Fstat(2) failed"));
  +     goto exit;
  +    }
  +
       startoff = fd->stats->ops[FDSTAT_READ].bytes;
       if ((xx = (int) timedRead(fd, (char *)block, sizeof(block))) != 
(int)sizeof(block)) {
        /* XXX Handle EOF's as RPMRC_NOTFOUND, not RPMRC_FAIL, returns. */
  @@ -1475,7 +1521,8 @@
            rc = RPMRC_NOTFOUND;
        else
            (void) snprintf(buf, sizeof(buf),
  -             _("hdr size(%u): BAD, read returned %d"), 
(unsigned)sizeof(block), xx);
  +             _("hdr size(%u): BAD, read returned %d"),
  +             (unsigned)sizeof(block), xx);
        goto exit;
       }
   
  @@ -1491,21 +1538,33 @@
       }
   
       il = (rpmuint32_t)ntohl(block[2]);
  -    if (hdrchkTags(il)) {
  +    if ((il * sizeof(struct entryInfo_s)) > (st->st_size - startoff - 
sizeof(block))
  +     || hdrchkTags(il))
  +    {
        (void) snprintf(buf, sizeof(buf),
  -             _("hdr tags: BAD, no. of tags(%u) out of range"), (unsigned) 
il);
  +             _("hdr tags: BAD, no. of tags(%u) out of range"),
  +             (unsigned) il);
   
        goto exit;
       }
       dl = (rpmuint32_t)ntohl(block[3]);
  -    if (hdrchkData(dl)) {
  +    if (dl > (st->st_size - startoff - sizeof(block))
  +     || hdrchkData(dl))
  +    {
        (void) snprintf(buf, sizeof(buf),
  -             _("hdr data: BAD, no. of bytes(%u) out of range\n"), (unsigned) 
dl);
  +             _("hdr data: BAD, no. of bytes(%u) out of range"),
  +             (unsigned) dl);
        goto exit;
       }
   
   /*@-sizeoftype@*/
       nb = (il * sizeof(struct entryInfo_s)) + dl;
  +    if (nb > (st->st_size - startoff - sizeof(block))) {
  +     (void) snprintf(buf, sizeof(buf),
  +             _("hdr blob: BAD, header size (%u) larger than file size"),
  +             (unsigned) nb);
  +       goto exit;
  +    }
   /*@=sizeoftype@*/
       uc = sizeof(il) + sizeof(dl) + nb;
       if (map) {
  @@ -1548,7 +1607,7 @@
       /* OK, blob looks sane, load the header. */
       h = headerLoad(ei);
       if (h == NULL) {
  -     (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
  +     (void) snprintf(buf, sizeof(buf), _("hdr load: BAD"));
           goto exit;
       }
       if (map) {
  @@ -1573,6 +1632,7 @@
            (void) headerSetOrigin(h, origin);
       }
   /*@-mods@*/
  +    /* Save file size in metadata header. */
       {        struct stat * st = headerGetStatbuf(h);
        int saveno = errno;
        (void) Fstat(fd, st);
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to