diff options
author | alyaeanyx <alexandra.hollmeier@mailbox.org> | 2021-11-14 18:04:54 +0100 |
---|---|---|
committer | alyaeanyx <alexandra.hollmeier@mailbox.org> | 2021-11-14 18:04:54 +0100 |
commit | 842a855325c8e050a874bc8249904b02405de74e (patch) | |
tree | 9709ec95b4bcc4983d4cc354c92100a536f065b7 /pkgs/tools/compression | |
parent | 84245c843f30a7b535280e35f4d2d56e2a0ab789 (diff) |
bsdiff: fix patch file for aarch64-linux
Diffstat (limited to 'pkgs/tools/compression')
-rw-r--r-- | pkgs/tools/compression/bsdiff/CVE-2020-14315.patch | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/pkgs/tools/compression/bsdiff/CVE-2020-14315.patch b/pkgs/tools/compression/bsdiff/CVE-2020-14315.patch new file mode 100644 index 0000000000000..dabb8deee00ac --- /dev/null +++ b/pkgs/tools/compression/bsdiff/CVE-2020-14315.patch @@ -0,0 +1,384 @@ +Description: patch for CVE-2020-14315 + A memory corruption vulnerability is present in bspatch as shipped in + Colin Percival’s bsdiff tools version 4.3. Insufficient checks when + handling external inputs allows an attacker to bypass the sanity checks + in place and write out of a dynamically allocated buffer boundaries. +Source: https://svnweb.freebsd.org/base/head/usr.bin/bsdiff/bspatch/bspatch.c?revision=352742&view=co +Author: tony mancill <tmancill@debian.org> +Comment: The patch was created by comparing the Debian sources to the + "Confirmed Patched Version" [1] documented in the + X41 D-SEC GmbH Security Advisory: X41-2020-006 [2]. + References to FreeBSD capsicum have been dropped. Definitions for + TYPE_MINIMUM and TYPE_MAXIMUM have been borrowed from the Debian + coreutils package sources but originate in gnulib [3] and are used to + define OFF_MIN and OFF_MAX (limits of off_t). Whitespace changes from + the confirmed patched version are also included and keep the difference + between the Debian sources and the confirmed patched version minimal. + . + [1] https://svnweb.freebsd.org/base/head/usr.bin/bsdiff/bspatch/bspatch.c?revision=352742&view=co + [2] https://www.openwall.com/lists/oss-security/2020/07/09/2 + [3] https://www.gnu.org/software/gnulib/ +Last-Update: 2021-04-03 +Forwarded: not-needed +Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=964796 + +--- a/bspatch.c ++++ b/bspatch.c +@@ -1,4 +1,6 @@ + /*- ++ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD ++ * + * Copyright 2003-2005 Colin Percival + * All rights reserved + * +@@ -24,56 +26,149 @@ + * POSSIBILITY OF SUCH DAMAGE. + */ + ++#include <sys/cdefs.h> + #if 0 +-__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $"); ++__FBSDID("$FreeBSD$"); + #endif + + #include <bzlib.h> +-#include <stdlib.h> ++#include <err.h> ++#include <fcntl.h> ++#include <libgen.h> ++#include <limits.h> ++#include <stdint.h> + #include <stdio.h> ++#include <stdlib.h> + #include <string.h> +-#include <err.h> + #include <unistd.h> +-#include <fcntl.h> ++ ++#ifndef O_BINARY ++#define O_BINARY 0 ++#endif ++#define HEADER_SIZE 32 ++ ++/* TYPE_MINIMUM and TYPE_MAXIMUM taken from coreutils */ ++#ifndef TYPE_MINIMUM ++#define TYPE_MINIMUM(t) \ ++ ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ TYPE_MAXIMUM (t))) ++#endif ++#ifndef TYPE_MAXIMUM ++#define TYPE_MAXIMUM(t) \ ++ ((t) ((t) 0 < (t) -1 \ ++ ? (t) -1 \ ++ : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1))) ++#endif ++ ++#ifndef OFF_MAX ++#define OFF_MAX TYPE_MAXIMUM(off_t) ++#endif ++ ++#ifndef OFF_MIN ++#define OFF_MIN TYPE_MINIMUM(off_t) ++#endif ++ ++static char *newfile; ++static int dirfd = -1; ++ ++static void ++exit_cleanup(void) ++{ ++ ++ if (dirfd != -1 && newfile != NULL) ++ if (unlinkat(dirfd, newfile, 0)) ++ warn("unlinkat"); ++} ++ ++static inline off_t ++add_off_t(off_t a, off_t b) ++{ ++ off_t result; ++ ++#if __GNUC__ >= 5 || \ ++ if (__builtin_add_overflow(a, b, &result)) ++ errx(1, "Corrupt patch"); ++#else ++ if ((b > 0 && a > OFF_MAX - b) || (b < 0 && a < OFF_MIN - b)) ++ errx(1, "Corrupt patch"); ++ result = a + b; ++#endif ++ return result; ++} + + static off_t offtin(u_char *buf) + { + off_t y; + +- y=buf[7]&0x7F; +- y=y*256;y+=buf[6]; +- y=y*256;y+=buf[5]; +- y=y*256;y+=buf[4]; +- y=y*256;y+=buf[3]; +- y=y*256;y+=buf[2]; +- y=y*256;y+=buf[1]; +- y=y*256;y+=buf[0]; ++ y = buf[7] & 0x7F; ++ y = y * 256; y += buf[6]; ++ y = y * 256; y += buf[5]; ++ y = y * 256; y += buf[4]; ++ y = y * 256; y += buf[3]; ++ y = y * 256; y += buf[2]; ++ y = y * 256; y += buf[1]; ++ y = y * 256; y += buf[0]; + +- if(buf[7]&0x80) y=-y; ++ if (buf[7] & 0x80) ++ y = -y; + +- return y; ++ return (y); + } + +-int main(int argc,char * argv[]) ++static void ++usage(void) + { +- FILE * f, * cpf, * dpf, * epf; +- BZFILE * cpfbz2, * dpfbz2, * epfbz2; ++ ++ fprintf(stderr, "usage: bspatch oldfile newfile patchfile\n"); ++ exit(1); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ FILE *f, *cpf, *dpf, *epf; ++ BZFILE *cpfbz2, *dpfbz2, *epfbz2; ++ char *directory, *namebuf; + int cbz2err, dbz2err, ebz2err; +- int fd; +- ssize_t oldsize,newsize; +- ssize_t bzctrllen,bzdatalen; +- u_char header[32],buf[8]; ++ int newfd, oldfd; ++ off_t oldsize, newsize; ++ off_t bzctrllen, bzdatalen; ++ u_char header[HEADER_SIZE], buf[8]; + u_char *old, *new; +- off_t oldpos,newpos; ++ off_t oldpos, newpos; + off_t ctrl[3]; +- off_t lenread; +- off_t i; ++ off_t i, lenread, offset; + +- if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); ++ if (argc != 4) ++ usage(); + + /* Open patch file */ +- if ((f = fopen(argv[3], "r")) == NULL) ++ if ((f = fopen(argv[3], "rb")) == NULL) ++ err(1, "fopen(%s)", argv[3]); ++ /* Open patch file for control block */ ++ if ((cpf = fopen(argv[3], "rb")) == NULL) ++ err(1, "fopen(%s)", argv[3]); ++ /* open patch file for diff block */ ++ if ((dpf = fopen(argv[3], "rb")) == NULL) + err(1, "fopen(%s)", argv[3]); ++ /* open patch file for extra block */ ++ if ((epf = fopen(argv[3], "rb")) == NULL) ++ err(1, "fopen(%s)", argv[3]); ++ /* open oldfile */ ++ if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0) ++ err(1, "open(%s)", argv[1]); ++ /* open directory where we'll write newfile */ ++ if ((namebuf = strdup(argv[2])) == NULL || ++ (directory = dirname(namebuf)) == NULL || ++ (dirfd = open(directory, O_DIRECTORY)) < 0) ++ err(1, "open %s", argv[2]); ++ free(namebuf); ++ if ((newfile = basename(argv[2])) == NULL) ++ err(1, "basename"); ++ /* open newfile */ ++ if ((newfd = openat(dirfd, newfile, ++ O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0) ++ err(1, "open(%s)", argv[2]); ++ atexit(exit_cleanup); + + /* + File format: +@@ -90,104 +185,104 @@ + */ + + /* Read header */ +- if (fread(header, 1, 32, f) < 32) { ++ if (fread(header, 1, HEADER_SIZE, f) < HEADER_SIZE) { + if (feof(f)) +- errx(1, "Corrupt patch\n"); ++ errx(1, "Corrupt patch"); + err(1, "fread(%s)", argv[3]); + } + + /* Check for appropriate magic */ + if (memcmp(header, "BSDIFF40", 8) != 0) +- errx(1, "Corrupt patch\n"); ++ errx(1, "Corrupt patch"); + + /* Read lengths from header */ +- bzctrllen=offtin(header+8); +- bzdatalen=offtin(header+16); +- newsize=offtin(header+24); +- if((bzctrllen<0) || (bzdatalen<0) || (newsize<0)) +- errx(1,"Corrupt patch\n"); ++ bzctrllen = offtin(header + 8); ++ bzdatalen = offtin(header + 16); ++ newsize = offtin(header + 24); ++ if (bzctrllen < 0 || bzctrllen > OFF_MAX - HEADER_SIZE || ++ bzdatalen < 0 || bzctrllen + HEADER_SIZE > OFF_MAX - bzdatalen || ++ newsize < 0 || newsize > SSIZE_MAX) ++ errx(1, "Corrupt patch"); + + /* Close patch file and re-open it via libbzip2 at the right places */ + if (fclose(f)) + err(1, "fclose(%s)", argv[3]); +- if ((cpf = fopen(argv[3], "r")) == NULL) +- err(1, "fopen(%s)", argv[3]); +- if (fseeko(cpf, 32, SEEK_SET)) +- err(1, "fseeko(%s, %lld)", argv[3], +- (long long)32); ++ offset = HEADER_SIZE; ++ if (fseeko(cpf, offset, SEEK_SET)) ++ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); + if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) + errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); +- if ((dpf = fopen(argv[3], "r")) == NULL) +- err(1, "fopen(%s)", argv[3]); +- if (fseeko(dpf, 32 + bzctrllen, SEEK_SET)) +- err(1, "fseeko(%s, %lld)", argv[3], +- (long long)(32 + bzctrllen)); ++ offset = add_off_t(offset, bzctrllen); ++ if (fseeko(dpf, offset, SEEK_SET)) ++ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); + if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) + errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); +- if ((epf = fopen(argv[3], "r")) == NULL) +- err(1, "fopen(%s)", argv[3]); +- if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET)) +- err(1, "fseeko(%s, %lld)", argv[3], +- (long long)(32 + bzctrllen + bzdatalen)); ++ offset = add_off_t(offset, bzdatalen); ++ if (fseeko(epf, offset, SEEK_SET)) ++ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset); + if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) + errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); + +- if(((fd=open(argv[1],O_RDONLY,0))<0) || +- ((oldsize=lseek(fd,0,SEEK_END))==-1) || +- ((old=malloc(oldsize+1))==NULL) || +- (lseek(fd,0,SEEK_SET)!=0) || +- (read(fd,old,oldsize)!=oldsize) || +- (close(fd)==-1)) err(1,"%s",argv[1]); +- if((new=malloc(newsize+1))==NULL) err(1,NULL); +- +- oldpos=0;newpos=0; +- while(newpos<newsize) { ++ if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 || ++ oldsize > SSIZE_MAX || ++ (old = malloc(oldsize)) == NULL || ++ lseek(oldfd, 0, SEEK_SET) != 0 || ++ read(oldfd, old, oldsize) != oldsize || ++ close(oldfd) == -1) ++ err(1, "%s", argv[1]); ++ if ((new = malloc(newsize)) == NULL) ++ err(1, NULL); ++ ++ oldpos = 0; ++ newpos = 0; ++ while (newpos < newsize) { + /* Read control data */ +- for(i=0;i<=2;i++) { ++ for (i = 0; i <= 2; i++) { + lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8); + if ((lenread < 8) || ((cbz2err != BZ_OK) && + (cbz2err != BZ_STREAM_END))) +- errx(1, "Corrupt patch\n"); +- ctrl[i]=offtin(buf); +- }; ++ errx(1, "Corrupt patch"); ++ ctrl[i] = offtin(buf); ++ } + + /* Sanity-check */ +- if ((ctrl[0] < 0) || (ctrl[1] < 0)) +- errx(1,"Corrupt patch\n"); ++ if (ctrl[0] < 0 || ctrl[0] > INT_MAX || ++ ctrl[1] < 0 || ctrl[1] > INT_MAX) ++ errx(1, "Corrupt patch"); + + /* Sanity-check */ +- if(newpos+ctrl[0]>newsize) +- errx(1,"Corrupt patch\n"); ++ if (add_off_t(newpos, ctrl[0]) > newsize) ++ errx(1, "Corrupt patch"); + + /* Read diff string */ + lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); + if ((lenread < ctrl[0]) || + ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) +- errx(1, "Corrupt patch\n"); ++ errx(1, "Corrupt patch"); + + /* Add old data to diff string */ +- for(i=0;i<ctrl[0];i++) +- if((oldpos+i>=0) && (oldpos+i<oldsize)) +- new[newpos+i]+=old[oldpos+i]; ++ for (i = 0; i < ctrl[0]; i++) ++ if (add_off_t(oldpos, i) < oldsize) ++ new[newpos + i] += old[oldpos + i]; + + /* Adjust pointers */ +- newpos+=ctrl[0]; +- oldpos+=ctrl[0]; ++ newpos = add_off_t(newpos, ctrl[0]); ++ oldpos = add_off_t(oldpos, ctrl[0]); + + /* Sanity-check */ +- if(newpos+ctrl[1]>newsize) +- errx(1,"Corrupt patch\n"); ++ if (add_off_t(newpos, ctrl[1]) > newsize) ++ errx(1, "Corrupt patch"); + + /* Read extra string */ + lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); + if ((lenread < ctrl[1]) || + ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) +- errx(1, "Corrupt patch\n"); ++ errx(1, "Corrupt patch"); + + /* Adjust pointers */ +- newpos+=ctrl[1]; +- oldpos+=ctrl[2]; +- }; ++ newpos = add_off_t(newpos, ctrl[1]); ++ oldpos = add_off_t(oldpos, ctrl[2]); ++ } + + /* Clean up the bzip2 reads */ + BZ2_bzReadClose(&cbz2err, cpfbz2); +@@ -197,12 +292,13 @@ + err(1, "fclose(%s)", argv[3]); + + /* Write the new file */ +- if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || +- (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) +- err(1,"%s",argv[2]); ++ if (write(newfd, new, newsize) != newsize || close(newfd) == -1) ++ err(1, "%s", argv[2]); ++ /* Disable atexit cleanup */ ++ newfile = NULL; + + free(new); + free(old); + +- return 0; ++ return (0); + } |