Hi, Here's an security fix for chicken 4.11.0 fixing CVE-2016-6830 and CVE-2016-6831. The patch is a bit large.
While here I dropped the patched test file, its not really needed so we could drop it. Timo Index: Makefile.inc =================================================================== RCS file: /cvs/ports/lang/chicken/Makefile.inc,v retrieving revision 1.7 diff -u -u -p -r1.7 Makefile.inc --- Makefile.inc 8 Jun 2016 01:24:45 -0000 1.7 +++ Makefile.inc 20 Aug 2016 05:15:06 -0000 @@ -4,6 +4,7 @@ COMMENT= practical and portable Scheme s V= 4.11.0 DISTNAME= chicken-${V} +REVISION= 0 MAINTAINER= Timo Myyra <timo.my...@wickedbsd.net> @@ -32,4 +33,3 @@ pre-build: .if ${MACHINE_ARCH} == "hppa" sed -i 's/C_STACK_GROWS_DOWNWARD 1/C_STACK_GROWS_DOWNWARD 0/g' "${WRKSRC}/Makefile.bsd" .endif - Index: core/patches/patch-csc_scm =================================================================== RCS file: /cvs/ports/lang/chicken/core/patches/patch-csc_scm,v retrieving revision 1.3 diff -u -u -p -r1.3 patch-csc_scm --- core/patches/patch-csc_scm 27 Aug 2015 22:40:33 -0000 1.3 +++ core/patches/patch-csc_scm 20 Aug 2016 05:15:06 -0000 @@ -1,7 +1,7 @@ $OpenBSD: patch-csc_scm,v 1.3 2015/08/27 22:40:33 juanfra Exp $ ---- csc.scm.orig Tue Aug 4 21:46:22 2015 -+++ csc.scm Thu Aug 27 19:07:56 2015 -@@ -981,9 +981,7 @@ EOF +--- csc.scm.orig Sat May 28 14:48:08 2016 ++++ csc.scm Mon Aug 15 07:51:43 2016 +@@ -990,9 +990,7 @@ EOF dynamic-libchicken (cond (osx "dylib") ((or mingw cygwin) "dll") Index: core/patches/patch-posix-common_scm =================================================================== RCS file: core/patches/patch-posix-common_scm diff -N core/patches/patch-posix-common_scm --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ core/patches/patch-posix-common_scm 20 Aug 2016 05:15:06 -0000 @@ -0,0 +1,81 @@ +$OpenBSD$ +fix buffer overflow and mem leak in execvp/execve wrappers +see CVE-2016-6830 and CVE-2016-6831. +--- posix-common.scm.orig Mon Aug 15 16:24:59 2016 ++++ posix-common.scm Mon Aug 15 16:30:27 2016 +@@ -25,7 +25,8 @@ + + + (declare +- (hide ##sys#stat posix-error check-time-vector ##sys#find-files) ++ (hide ##sys#stat posix-error check-time-vector ##sys#find-files ++ list->c-string-buffer free-c-string-buffer call-with-exec-args) + (foreign-declare #<<EOF + + #include <signal.h> +@@ -679,3 +680,65 @@ EOF + (if (fx= epid -1) + (posix-error #:process-error 'process-wait "waiting for child process failed" pid) + (values epid enorm ecode) ) ) ) ) ) ) ++ ++;; This can construct argv or envp for process-execute or process-run ++(define list->c-string-buffer ++ (let* ((c-string->allocated-pointer ++ (foreign-lambda* c-pointer ((scheme-object o)) ++ "char *ptr = malloc(C_header_size(o)); \n" ++ "if (ptr != NULL) {\n" ++ " C_memcpy(ptr, C_data_pointer(o), C_header_size(o)); \n" ++ "}\n" ++ "C_return(ptr);")) ) ++ (lambda (string-list convert loc) ++ (##sys#check-list string-list loc) ++ ++ (let* ((string-count (##sys#length string-list)) ++ ;; NUL-terminated, so we must add one ++ (buffer (make-pointer-vector (add1 string-count) #f))) ++ ++ (handle-exceptions exn ++ ;; Free to avoid memory leak, then reraise ++ (begin (free-c-string-buffer buffer) (signal exn)) ++ ++ (do ((sl string-list (cdr sl)) ++ (i 0 (fx+ i 1)) ) ++ ((or (null? sl) (fx= i string-count))) ; Should coincide ++ ++ (##sys#check-string (car sl) loc) ++ ;; This avoids embedded NULs and appends a NUL, so "cs" is ++ ;; safe to copy and use as-is in the pointer-vector. ++ (let* ((cs (##sys#make-c-string (convert (car sl)) loc)) ++ (csp (c-string->allocated-pointer cs))) ++ (unless csp (error loc "Out of memory")) ++ (pointer-vector-set! buffer i csp)) ) ++ ++ buffer) ) ) ) ) ++ ++(define (free-c-string-buffer buffer-array) ++ (let ((size (pointer-vector-length buffer-array))) ++ (do ((i 0 (fx+ i 1))) ++ ((fx= i size)) ++ (and-let* ((s (pointer-vector-ref buffer-array i))) ++ (free s))))) ++ ++(define call-with-exec-args ++ (let ((pathname-strip-directory pathname-strip-directory) ++ (nop (lambda (x) x))) ++ (lambda (loc filename argconv arglist envlist proc) ++ (let* ((stripped-filename (pathname-strip-directory filename)) ++ (args (cons stripped-filename arglist)) ; Add argv[0] ++ (argbuf (list->c-string-buffer args argconv loc)) ++ (envbuf #f)) ++ ++ (handle-exceptions exn ++ ;; Free to avoid memory leak, then reraise ++ (begin (free-c-string-buffer argbuf) ++ (when envbuf (free-c-string-buffer envbuf)) ++ (signal exn)) ++ ++ ;; Envlist is never converted, so we always use nop here ++ (when envlist ++ (set! envbuf (list->c-string-buffer envlist nop loc))) ++ ++ (proc (##sys#make-c-string filename loc) argbuf envbuf) ))))) Index: core/patches/patch-posixunix_scm =================================================================== RCS file: core/patches/patch-posixunix_scm diff -N core/patches/patch-posixunix_scm --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ core/patches/patch-posixunix_scm 20 Aug 2016 05:15:06 -0000 @@ -0,0 +1,129 @@ +$OpenBSD$ +fix buffer overflow and mem leak in execvp/execve wrappers +see CVE-2016-6830 and CVE-2016-6831. + +--- posixunix.scm.orig Sat May 28 14:48:08 2016 ++++ posixunix.scm Mon Aug 15 16:32:17 2016 +@@ -27,7 +27,7 @@ + + (declare + (unit posix) +- (uses scheduler irregex extras files ports) ++ (uses scheduler irregex extras files ports lolevel) + (disable-interrupts) + (hide group-member _get-groups _ensure-groups posix-error ##sys#terminal-check) + (not inline ##sys#interrupt-hook ##sys#user-interrupt-hook)) +@@ -88,10 +88,6 @@ static C_TLS int C_wait_status; + # define O_TEXT 0 + #endif + +-#ifndef ARG_MAX +-# define ARG_MAX 256 +-#endif +- + #ifndef MAP_FILE + # define MAP_FILE 0 + #endif +@@ -110,16 +106,10 @@ extern char **environ; + # define C_getenventry(i) (environ[ i ]) + #endif + +-#ifndef ENV_MAX +-# define ENV_MAX 1024 +-#endif +- + #ifndef FILENAME_MAX + # define FILENAME_MAX 1024 + #endif + +-static C_TLS char *C_exec_args[ ARG_MAX ]; +-static C_TLS char *C_exec_env[ ENV_MAX ]; + static C_TLS struct utsname C_utsname; + static C_TLS struct flock C_flock; + static C_TLS DIR *temphandle; +@@ -199,30 +189,9 @@ static C_TLS struct stat C_statbuf; + + #define C_lstat(fn) C_fix(lstat((char *)C_data_pointer(fn), &C_statbuf)) + +-static void C_fcall C_set_arg_string(char **where, int i, char *a, int len) { +- char *ptr; +- if(a != NULL) { +- ptr = (char *)C_malloc(len + 1); +- C_memcpy(ptr, a, len); +- ptr[ len ] = '\0'; +- /* Can't barf() here, so the NUL byte check happens in Scheme */ +- } +- else ptr = NULL; +- where[ i ] = ptr; +-} ++#define C_u_i_execvp(f,a) C_fix(execvp(C_data_pointer(f), (char *const *)C_c_pointer_vector_or_null(a))) ++#define C_u_i_execve(f,a,e) C_fix(execve(C_data_pointer(f), (char *const *)C_c_pointer_vector_or_null(a), (char *const *)C_c_pointer_vector_or_null(e))) + +-static void C_fcall C_free_arg_string(char **where) { +- while((*where) != NULL) C_free(*(where++)); +-} +- +-#define C_set_exec_arg(i, a, len) C_set_arg_string(C_exec_args, i, a, len) +-#define C_free_exec_args() C_free_arg_string(C_exec_args) +-#define C_set_exec_env(i, a, len) C_set_arg_string(C_exec_env, i, a, len) +-#define C_free_exec_env() C_free_arg_string(C_exec_env) +- +-#define C_execvp(f) C_fix(execvp(C_data_pointer(f), C_exec_args)) +-#define C_execve(f) C_fix(execve(C_data_pointer(f), C_exec_args, C_exec_env)) +- + #if defined(__FreeBSD__) || defined(C_MACOSX) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sgi__) || defined(sgi) || defined(__DragonFly__) || defined(__SUNPRO_C) + static C_TLS int C_uw; + # define C_WIFEXITED(n) (C_uw = C_unfix(n), C_mk_bool(WIFEXITED(C_uw))) +@@ -1591,43 +1560,15 @@ EOF + (exit 0))) + pid))))) + +-(define process-execute +- ;; NOTE: We use c-string here instead of scheme-object. +- ;; Because set_exec_* make a copy, this implies a double copy. +- ;; At least it's secure, we can worry about performance later, if at all +- (let ([setarg (foreign-lambda void "C_set_exec_arg" int c-string int)] +- [freeargs (foreign-lambda void "C_free_exec_args")] +- [setenv (foreign-lambda void "C_set_exec_env" int c-string int)] +- [freeenv (foreign-lambda void "C_free_exec_env")] +- [pathname-strip-directory pathname-strip-directory] ) +- (lambda (filename #!optional (arglist '()) envlist) +- (##sys#check-string filename 'process-execute) +- (##sys#check-list arglist 'process-execute) +- (let ([s (pathname-strip-directory filename)]) +- (setarg 0 s (##sys#size s)) ) +- (do ([al arglist (cdr al)] +- [i 1 (fx+ i 1)] ) +- ((null? al) +- (setarg i #f 0) +- (when envlist +- (##sys#check-list envlist 'process-execute) +- (do ([el envlist (cdr el)] +- [i 0 (fx+ i 1)] ) +- ((null? el) (setenv i #f 0)) +- (let ([s (car el)]) +- (##sys#check-string s 'process-execute) +- (setenv i s (##sys#size s)) ) ) ) +- (let* ([prg (##sys#make-c-string filename 'process-execute)] +- [r (if envlist +- (##core#inline "C_execve" prg) +- (##core#inline "C_execvp" prg) )] ) +- (when (fx= r -1) +- (freeargs) +- (freeenv) +- (posix-error #:process-error 'process-execute "cannot execute process" filename) ) ) ) +- (let ([s (car al)]) +- (##sys#check-string s 'process-execute) +- (setarg i s (##sys#size s)) ) ) ) ) ) ++(define (process-execute filename #!optional (arglist '()) envlist) ++ (call-with-exec-args ++ 'process-execute filename (lambda (x) x) arglist envlist ++ (lambda (prg argbuf envbuf) ++ (let ((r (if envbuf ++ (##core#inline "C_u_i_execve" prg argbuf envbuf) ++ (##core#inline "C_u_i_execvp" prg argbuf) )) ) ++ (when (fx= r -1) ++ (posix-error #:process-error 'process-execute "cannot execute process" filename) ) ))) ) + + (define-foreign-variable _wnohang int "WNOHANG") + (define-foreign-variable _wait-status int "C_wait_status") Index: core/patches/patch-tests_data-structures-tests_scm =================================================================== RCS file: core/patches/patch-tests_data-structures-tests_scm diff -N core/patches/patch-tests_data-structures-tests_scm --- core/patches/patch-tests_data-structures-tests_scm 16 Jun 2015 14:45:04 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,45 +0,0 @@ -$OpenBSD: patch-tests_data-structures-tests_scm,v 1.2 2015/06/16 14:45:04 jasper Exp $ - -Security fix for CVE-2014-9651 -http://lists.nongnu.org/archive/html/chicken-hackers/2014-12/msg00000.html - -Security fix for CVE-2015-4556 -http://lists.nongnu.org/archive/html/chicken-hackers/2015-06/msg00037.html - ---- tests/data-structures-tests.scm.orig Tue Jun 16 10:11:45 2015 -+++ tests/data-structures-tests.scm Tue Jun 16 10:11:37 2015 -@@ -1,6 +1,6 @@ - ;;;; data-structures-tests.scm - --(use data-structures) -+(use data-structures lolevel) - - (define-syntax assert-error - (syntax-rules () -@@ -42,6 +42,26 @@ - (assert (> 0 (string-compare3-ci "foo\x00A" "foo\x00b"))) - (assert (< 0 (string-compare3-ci "foo\x00b" "foo\x00a"))) - (assert (< 0 (string-compare3-ci "foo\x00b" "foo\x00A"))) -+ -+ -+;; This used to fail because substring-index and co. used to search -+;; beyond the end of the subject string when a start index > 0 was -+;; provided. We use object-evict to ensure that the strings are placed -+;; in adjacent memory ranges so we can detect this error. -+(let* ((foo (object-evict (make-string 32 #\x))) -+ (bar (object-evict "y"))) -+ (assert (not (substring-index "y" foo 30)))) -+ -+(assert (string=? "bde" (string-translate* "abcd" -+ '(("a" . "b") -+ ("b" . "") -+ ("c" . "d") -+ ("d" . "e"))))) -+(assert (string=? "bc" (string-translate* "abc" -+ '(("ab" . "b") -+ ("bc" . "WRONG"))))) -+(assert (string=? "x" (string-translate* "ab" '(("ab" . "x"))))) -+(assert (string=? "xy" (string-translate* "xyz" '(("z" . ""))))) - - ;; topological-sort -