rpms/libsafe/devel libsafe-2.0-16c.patch, NONE, 1.1 libsafe-2.0-16.spec, 1.1, 1.2

Warren Togami (wtogami) fedora-extras-commits at redhat.com
Fri Dec 17 01:38:39 UTC 2004


Author: wtogami

Update of /cvs/extras/rpms/libsafe/devel
In directory cvs.fedora.redhat.com:/tmp/cvs-serv19613

Modified Files:
	libsafe-2.0-16.spec 
Added Files:
	libsafe-2.0-16c.patch 
Log Message:
Patch with Steve Grubb's libsafe-2.0-16c improvements


libsafe-2.0-16c.patch:

--- NEW FILE libsafe-2.0-16c.patch ---
diff -urN libsafe-2.0-16/ChangeLog libsafe-2.0-16c/ChangeLog
--- libsafe-2.0-16/ChangeLog	2002-05-30 04:05:41.000000000 -1000
+++ libsafe-2.0-16c/ChangeLog	2003-04-19 17:24:07.000000000 -1000
@@ -1,6 +1,12 @@
 $Name: release2_0-16 $
 $Id: ChangeLog,v 1.19 2002/05/30 14:05:41 ttsai Exp $
 
+Version 2.0.16b
+* April 19 2003 Steve Grubb <linux_4ever at yahoo.com>
+	- Added interception of read, recv, recvfrom, & readlink. This helps
+	  prevent overflows whenever programmers trust a value they shouldn't.
+	- Code cleanup.
+
 Version 2.0-16
 * Mon May 21 2002 Timothy Tsai <ttsai at avaya.com>
 - src/intercept.c:
Binary files libsafe-2.0-16/exploits/file.old and libsafe-2.0-16c/exploits/file.old differ
diff -urN libsafe-2.0-16/exploits/t1.c libsafe-2.0-16c/exploits/t1.c
--- libsafe-2.0-16/exploits/t1.c	2002-06-12 10:30:37.000000000 -1000
+++ libsafe-2.0-16c/exploits/t1.c	2003-03-12 09:06:11.000000000 -1000
@@ -9,7 +9,7 @@
 #include <sys/types.h>
 #include <stdlib.h>
 
-char shellcode[] =
+const char shellcode[] =
     "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
     "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
     "\x80\xe8\xdc\xff\xff\xff/bin/sh";
diff -urN libsafe-2.0-16/README_C_VERSION libsafe-2.0-16c/README_C_VERSION
--- libsafe-2.0-16/README_C_VERSION	1969-12-31 14:00:00.000000000 -1000
+++ libsafe-2.0-16c/README_C_VERSION	2003-04-20 14:18:38.000000000 -1000
@@ -0,0 +1,10 @@
+Notice of third party modifications as per the GNU GENERAL PUBLIC LICENSE.
+
+This is a hacked up copy of libsafe. It is not published by avaya or lucent. 
+So, do not contact them for support. Any questions should probably come my way
+since I hacked it up. Also, feel free to compare this against the original.
+Hopefully, they will publish a new copy soon, so that these improvements can
+see the light of day.
+
+-Steve Grubb
+<linux_4ever at yahoo.com>
diff -urN libsafe-2.0-16/src/intercept.c libsafe-2.0-16c/src/intercept.c
--- libsafe-2.0-16/src/intercept.c	2002-05-31 07:37:34.000000000 -1000
+++ libsafe-2.0-16c/src/intercept.c	2003-04-20 12:17:20.000000000 -1000
@@ -35,7 +35,7 @@
  *              getwd(3), gets(3), realpath(3),
  *              fscanf(3), scanf(3), sscanf(3)
  * safe but supported (as we must): 
- *              memcpy(3)
+ *              memcpy(3), read(2), recv(2), recvfrom(2), readlink(2)
  * might be problematic, but I can't figure out why:
  *              getopt(3), getpass(3), index(3), streadd(?) 
  */
@@ -54,6 +54,7 @@
 #include <dlfcn.h>		/* defines dlsym() */
 #include <wchar.h>		/* for the wide-char functions */
 #include <ctype.h>		/* for the isdigit() */
+#include <sys/socket.h>		/* for struct sockaddr */
 #include "util.h"
 #include "log.h"
 
@@ -75,9 +76,14 @@
 	ap);
 typedef int (*vprintf_t) (const char *format, va_list ap);
 typedef int (*vfprintf_t) (FILE *fp, const char *format, va_list ap);
+typedef ssize_t (*read_t) (int fd, void *buf, size_t count);
+typedef int (*recv_t) (int  s, void *buf, size_t len, int flags);
+typedef int (*recvfrom_t) (int  s, void *buf, size_t len, int flags, 
+		struct sockaddr *from, socklen_t *fromlen);
+typedef int (*readlink_t) (const char *path, char *buf, size_t bufsiz);
 typedef char *(*getwd_t) (char *buf);
 typedef char *(*gets_t) (char *s);
-typedef char *(*realpath_t) (char *path, char resolved_path[]);
+typedef char *(*realpath_t) (const char *path, char *resolved_path);
 typedef int (*_IO_vfscanf_t) (_IO_FILE *s, const char *format, _IO_va_list
 	argptr, int *errp);
 
@@ -866,7 +872,7 @@
     char *p, *pnum;
     int c = -1;		/* Next var arg to be used */
     int in_mth;		/* Are we currently looking for an m-th argument? */
-    int atoi(const char *nptr);
+    long int strtol(const char *nptr, char **endptr, int base);
 
     if (!real_vfprintf)
 	real_vfprintf = (vfprintf_t) getLibraryFunction("vfprintf");
@@ -924,7 +930,8 @@
 	    /*
 	     * Check for [<flags>].
 	     */
-	    for (; *p && is_printf_flag[(int)*p]; p++);
+	    for (; *p && is_printf_flag[(int)*p]; p++)
+		    ; /* Do nothing */
 	    if (*p == (char)NULL) break;
 
 	    /*
@@ -949,7 +956,8 @@
 		}
 	    }
 	    else {
-		for (; *p && isdigit((int)*p); p++);
+		for (; *p && isdigit((int)*p); p++)
+			; /* Do nothing */
 		if (*p == (char)NULL) break;
 	    }
 
@@ -977,7 +985,8 @@
 		    }
 		}
 		else {
-		    for (; *p && isdigit((int)*p); p++);
+		    for (; *p && isdigit((int)*p); p++)
+			    ; /* Do nothing */
 		    if (*p == (char)NULL) break;
 		}
 	    }
@@ -1003,7 +1012,17 @@
 		caddr_t addr;
 		c++;
 		if (pnum) {
-		    addr = *((caddr_t*)(ap + (atoi(pnum)-1)*sizeof(char*)));
+                    /*
+		     * SUSv3 says that errno must be cleared and checked
+		     * to make sure the string being converted really is
+		     * a legal number
+		     */
+                     long value;
+                     errno = 0;
+                     value = strtol(pnum, (char **)NULL, 10);
+                     if (errno)
+                         _libsafe_die("printf(\"%%n\" NaN)");
+		    addr = *((caddr_t*)(ap + (value-1)*sizeof(char*)));
 		}
 		else {
 		    addr = *((caddr_t*)(ap + c*sizeof(char*)));
@@ -1031,7 +1050,7 @@
     char *p, *pnum;
     int c = -1;		/* Next var arg to be used */
     int in_mth;		/* Are we currently looking for an m-th argument? */
-    int atoi(const char *nptr);
+    long int strtol(const char *nptr, char **endptr, int base);
 
     if (!real_vfprintf)
 	real_vfprintf = (vfprintf_t) getLibraryFunction("vfprintf");
@@ -1089,7 +1108,8 @@
 	    /*
 	     * Check for [<flags>].
 	     */
-	    for (; *p && is_printf_flag[(int)*p]; p++);
+	    for (; *p && is_printf_flag[(int)*p]; p++)
+		    ; /* Do nothing */
 	    if (*p == (char)NULL) break;
 
 	    /*
@@ -1114,7 +1134,8 @@
 		}
 	    }
 	    else {
-		for (; *p && isdigit((int)*p); p++);
+		for (; *p && isdigit((int)*p); p++)
+			; /* Do nothing */
 		if (*p == (char)NULL) break;
 	    }
 
@@ -1142,7 +1163,8 @@
 		    }
 		}
 		else {
-		    for (; *p && isdigit((int)*p); p++);
+		    for (; *p && isdigit((int)*p); p++)
+			    ; /* Do nothing */
 		    if (*p == (char)NULL) break;
 		}
 	    }
@@ -1168,7 +1190,17 @@
 		caddr_t addr;
 		c++;
 		if (pnum) {
-		    addr = *((caddr_t*)(ap + (atoi(pnum)-1)*sizeof(char*)));
+                    /* 
+		     * SUSv3 says that errno must be cleared and checked
+		     * to make sure the string being converted really is
+		     * a legal number 
+		     */
+                    long value;
+		    errno = 0;
+		    value = strtol(pnum, (char **)NULL, 10);
+		    if (errno)
+		   	_libsafe_die("printf(\"%%n\" NaN)"); 
+		    addr = *((caddr_t*)(ap + (value-1)*sizeof(char*)));
 		}
 		else {
 		    addr = *((caddr_t*)(ap + c*sizeof(char*)));
@@ -1359,6 +1391,121 @@
 }
 
 
+// Added by Steve Grubb <linux_4ever at yahoo.com>
+ssize_t read(int fd, void *buf, size_t count)
+{
+    static read_t real_read = NULL;
+    size_t max_size;
+
+    if (!real_read) 
+       real_read = (read_t) getLibraryFunction("read");
+
+    if (_libsafe_exclude)
+        return real_read(fd, buf, count);
+
+    if ((max_size = _libsafe_stackVariableP(buf)) == 0) {
+        LOG(5, "read(<heap var>)\n");
+        return real_read(fd, buf, count);
+    }
+
+    /*
+     * read copies len chars into buf. The contents are not
+     * NULL terminated, therefore the char count is returned. It is
+     * therefore OK to return max_size.
+     */
+    LOG(4, "read(<stack var>) stack limit=%d\n", max_size);
+    if (count > max_size)
+        _libsafe_die("Overflow caused by read() count:%ul max_size:%ul", 
+	count, max_size);
+    return real_read(fd, buf, count);
+}
+
+
+int recv(int s, void *buf, size_t len, int flags)
+{
+    static recv_t real_recv = NULL;
+    size_t max_size;
+
+    if (!real_recv)
+       real_recv = (recv_t) getLibraryFunction("recv");
+
+    if (_libsafe_exclude)
+        return real_recv(s, buf, len, flags);
+
+    if ((max_size = _libsafe_stackVariableP(buf)) == 0) {
+        LOG(5, "recv(<heap var>)\n");
+        return real_recv(s, buf, len, flags);
+    }
+
+    /*
+     * recv reads len chars into buf. The contents are not
+     * NULL terminated, therefore the char count is returned. It is
+     * therefore OK to return max_size.
+     */
+    LOG(4, "recv(<stack var>) stack limit=%d\n", max_size);
+    if (len > max_size)
+        _libsafe_die("Overflow caused by recv()");
+    return real_recv(s, buf, len, flags);
+}
+
+
+int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr
+		       *from, socklen_t *fromlen)
+{
+    static recvfrom_t real_recvfrom = NULL;
+    size_t max_size;
+
+    if (!real_recvfrom)
+       real_recvfrom = (recvfrom_t) getLibraryFunction("recvfrom");
+
+    if (_libsafe_exclude)
+        return real_recvfrom(s, buf, len, flags, from, fromlen);
+
+    if ((max_size = _libsafe_stackVariableP(buf)) == 0) {
+        LOG(5, "recvfrom(<heap var>)\n");
+        return real_recvfrom(s, buf, len, flags, from, fromlen);
+    }
+
+    /*
+     * recvfrom reads len chars into buf. The contents are not
+     * NULL terminated, therefore the char count is returned. It is
+     * therefore OK to return max_size.
+     */
+    LOG(4, "recvfrom(<stack var>) stack limit=%d\n", max_size);
+    if (len > max_size)
+        _libsafe_die("Overflow caused by recvfrom()");
+    return real_recvfrom(s, buf, len, flags, from, fromlen);
+}
+
+
+int readlink(const char *path, char *buf, size_t bufsiz)
+{
+    static readlink_t real_readlink = NULL;
+    size_t max_size;
+
+    if (!real_readlink) 
+       real_readlink = (readlink_t) getLibraryFunction("readlink");
+
+    if (_libsafe_exclude)
+        return real_readlink(path, buf, bufsiz);
+
+    if ((max_size = _libsafe_stackVariableP(buf)) == 0) {
+        LOG(5, "readlink(<heap var>)\n");
+        return real_readlink(path, buf, bufsiz);
+    }
+
+    /*
+     * readlink reads bufsiz chars into buf. The contents are not
+     * NULL terminated, therefore the char count is returned. It is
+     * therefore OK to return max_size.
+     */
+    LOG(4, "readlink(<stack var>) stack limit=%d\n", max_size);
+    if (bufsiz > max_size)
+        _libsafe_die("Overflow caused by readlink()");
+    return real_readlink(path, buf, bufsiz);
+}
+
+
 char *getwd(char *buf)
 {
     static getwd_t real_getwd = NULL;
@@ -1410,7 +1557,7 @@
 }
 
 
-char *realpath(char *path, char resolved_path[])
+char *realpath(const char *path, char *resolved_path)
 {
     static realpath_t real_realpath = NULL;
     size_t max_size, len;
@@ -1422,7 +1569,11 @@
     if (!real_realpath)
 	real_realpath = (realpath_t) getLibraryFunction("realpath");
 
-    if (_libsafe_exclude)
+    /*
+     * if resolved_path is NULL, the result will be malloc'ed.
+     * we do not need to check it.
+     */
+    if ((_libsafe_exclude) || (resolved_path == NULL))
 	return real_realpath(path, resolved_path);
 
     if ((max_size = _libsafe_stackVariableP(resolved_path)) == 0) {
@@ -1435,11 +1586,20 @@
      * realpath(3) copies at most MAXNAMLEN characters
      */
     res = real_realpath(path, buf);
+
+    /*
+     * See if we succeeded. If there was an error, return since the
+     * results are undefined.
+     */
+    if (res == NULL)
+        return NULL;
+
     if ((len = strnlen(buf, max_size)) == max_size)
-	_libsafe_die("Overflow caused by realpath()");
+	_libsafe_die("Overflow caused by realpath()\nmax_size=%u, len=%u",
+	max_size, len);
 
     real_memcpy(resolved_path, buf, len + 1);
-    return (res == NULL) ? NULL : resolved_path;
+    return resolved_path;
 }
 
 
diff -urN libsafe-2.0-16/src/Makefile libsafe-2.0-16c/src/Makefile
--- libsafe-2.0-16/src/Makefile	2002-05-30 04:13:07.000000000 -1000
+++ libsafe-2.0-16c/src/Makefile	2003-04-20 13:03:10.000000000 -1000
@@ -30,7 +30,7 @@
 
 MAJOR_VERSION	= 2
 MINOR_VERSION	= 0
-PATCHLEVEL	= 16
+PATCHLEVEL	= 16c
 
 VERSION		= $(MAJOR_VERSION).$(MINOR_VERSION).$(PATCHLEVEL)
 
@@ -40,7 +40,7 @@
 PRELOAD		= /etc/ld.so.preload
 
 MANNAME		= ../doc/libsafe.8
-MANDIR		= /usr/man/man8
+MANDIR		= /usr/share/man/man8
 
 CC		= gcc
 CPP		= g++
@@ -74,7 +74,7 @@
 		  -DLIBSAFE_DUMP_STACK_FILE=\"/tmp/libsafe_stack_dump\" \
 		  -DDUMP_CORE \
 		  -DNOTIFY_WITH_EMAIL
-CCFLAGS		= -O2 -Wall -fPIC -DLIBSAFE_VERSION=\"$(VERSION)\" $(LIBPRELUDE_CFLAGS)
+CCFLAGS		= -O2 -Wall -W -fPIC -DLIBSAFE_VERSION=\"$(VERSION)\" $(LIBPRELUDE_CFLAGS)
 # Uncomment the following line to enable all debugging options.  Better way is
 # to do "make debug".
 #CCFLAGS		= -O2 -Wall -fPIC $(DEBUG_FLAGS)
diff -urN libsafe-2.0-16/src/util.c libsafe-2.0-16c/src/util.c
--- libsafe-2.0-16/src/util.c	2002-05-30 04:44:38.000000000 -1000
+++ libsafe-2.0-16c/src/util.c	2003-04-19 03:01:44.000000000 -1000
@@ -44,10 +44,23 @@
 #define __USE_GNU		/* defines strnlen() */
 #include <string.h>
 
-// Sometimes environ is defined in unistd.h.  If so, then comment out the
-// following declaration.
-extern char **environ[];
+static void _libsafe_warn(const char *format, ...)
+#ifdef __GNUC__
+        __attribute__ ((format (printf, 1, 2)));
+#else
+        ;
+#endif
 
+#ifdef NOTIFY_WITH_EMAIL
+static int send_command(int s, int expected, const char *format, ...)
+#ifdef __GNUC__
+        __attribute__ ((format (printf, 3, 4)));
+#else
+        ;
+#endif
+#endif
+			
+			
 
 /*****************************************************************************
  *
@@ -91,13 +104,13 @@
  */
 #define find_stack_start(addr)						    \
      /* Past stack area */						    \
-    ((addr > (void*)0xc0000000) ? NULL :				    \
+    (((addr) > (void*)0xc0000000) ? NULL :				    \
 									    \
      /* Main thread stack */						    \
-     (addr > (void*)0xbf800000) ? (void*)0xc0000000 :			    \
+     ((addr) > (void*)0xbf800000) ? (void*)0xc0000000 :			    \
 									    \
      /* Other thread stacks */						    \
-	((void*)(((uint)addr & (~PTHREAD_STACK_SIZE)) + PTHREAD_STACK_SIZE))\
+     ((void*)(((uint)(addr) & (~PTHREAD_STACK_SIZE)) + PTHREAD_STACK_SIZE)) \
 									    \
     )
 
@@ -645,7 +658,7 @@
 	    /*
 	     * This is the only correct way to end the stack.
 	     */
-	    return is_ra;
+	    return (uint)is_ra;
 	}
 
 	/*
@@ -841,7 +854,7 @@
  * return 0;  else return -1.  expected should be the first digit of the
  * 3-digit response code.  If expected==-1, then don't check the response.
  */
-static int send_command(int s, int expected, char *format, ...) {
+static int send_command(int s, int expected, const char *format, ...) {
     char	response;
     char	command[2048];
     int	len, res;
@@ -1069,8 +1082,10 @@
         userid->number = uid;
         
         uent = getpwuid(uid);
-        if ( uent )
+        if ( uent ) {
+		memset(uent->pw_passwd, 0, sizeof(uent->pw_passwd));
                 idmef_string_set(&userid->name, uent->pw_name);
+	}
                 
         /*
          * effective user id
@@ -1082,8 +1097,10 @@
         userid->type = user_privs;
         userid->number = euid;
         uent = getpwuid(euid);
-        if ( uent )
+        if ( uent ) {
+		memset(uent->pw_passwd, 0, sizeof(uent->pw_passwd));
                 idmef_string_set(&userid->name, uent->pw_name);
+	}
 
         /*
          * real group id
@@ -1362,13 +1379,15 @@
     fclose(fp);
 
     maps = (struct maps_st *) malloc(count * sizeof(struct maps_st));
+    if (maps == NULL)
+	    return 0;
     *mapsptr = maps;
 
     /*
      * Second pass:  Fill in the table with the region info.
      */
     if ((fp=fopen(filename, "r")) == NULL) {
-	if (maps) free(maps);
+	free(maps);
 	return 0;
     }
 
@@ -1421,7 +1440,7 @@
  * customized actions triggered by detection put them here.  (format,...) is
  * similar to printf() and passed to syslog().
  */
-void _libsafe_warn(char *format, ...)
+static void _libsafe_warn(const char *format, ...)
 {
     char    exename[MAXPATHLEN];
     va_list args;
@@ -1633,7 +1652,7 @@
  * 'name' is the name of this library, and (format,...) is similar to printf()
  * and passed to syslog().
  */
-void _libsafe_die(char *format, ...)
+void _libsafe_die(const char *format, ...)
 {
     va_list args;
 
@@ -1682,8 +1701,14 @@
      * least it kills all threads and can't be caught. -- tkt
      */
     //_exit(1);
+  {
+    sigset_t mask;
+    sigfillset(&mask);
+    sigdelset(&mask, SIGKILL);                 /* Block all signal handlers */
+    sigprocmask(SIG_BLOCK, &mask, NULL);       /* except SIGKILL            */
+  }
+	
     raise(SIGKILL);
 #endif
 }
 
-
diff -urN libsafe-2.0-16/src/util.h libsafe-2.0-16c/src/util.h
--- libsafe-2.0-16/src/util.h	2002-05-30 04:13:08.000000000 -1000
+++ libsafe-2.0-16c/src/util.h	2003-03-12 05:59:43.000000000 -1000
@@ -44,8 +44,12 @@
 extern uint _libsafe_stackVariableP(void *addr);
 extern uint _libsafe_raVariableP(void *addr);
 extern uint _libsafe_span_stack_frames(void *start_addr, void *end_addr);
-extern void _libsafe_die(char *format, ...);
-extern void _libsafe_warn(char *format, ...);
+extern void _libsafe_die(const char *format, ...)
+#ifdef __GNUC__
+        __attribute__ ((format (printf, 1, 2)));
+#else
+        ;
+#endif
 extern int _libsafe_save_ra_fp(int maxcount, caddr_t *ra_array, caddr_t
 	*fp_array);
 extern int _libsafe_verify_ra_fp(int maxcount, caddr_t *ra_array, caddr_t


Index: libsafe-2.0-16.spec
===================================================================
RCS file: /cvs/extras/rpms/libsafe/devel/libsafe-2.0-16.spec,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- libsafe-2.0-16.spec	8 Nov 2004 04:46:16 -0000	1.1
+++ libsafe-2.0-16.spec	17 Dec 2004 01:38:37 -0000	1.2
@@ -1,12 +1,13 @@
 Summary: Libsafe: Protecting Critical Elements of Stacks
 Name: libsafe
 Version: 2.0
-Release: 16.fdr.1.rh80
-# Override upstream 2.0-16 rather than 0.fdr.1 because that is the tarball name
+Release: 16c
 Epoch: 0
 License: LGPL
 Group: System Environment/Libraries
 Source: http://www.research.avayalabs.com/project/libsafe/libsafe-2.0-16.tgz
+# Steve Grubb's libsafe improvements http://www.web-insights.net/libsafe/
+Patch0: libsafe-2.0-16c.patch
 URL: http://www.research.avayalabs.com/project/libsafe/index.html
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
 
@@ -22,19 +23,16 @@
 potentially prevent yet unknown attacks. Experiments indicate that the
 performance overhead of libsafe is negligible.
 
-If libsafe is compiled on a system with libprelude installed, libsafe will
-additionally emit a stack overflow alert to the Prelude Manager.  For more
-information about the Prelude Hybrid IDS, please see http://www.prelude-ids.org
-(Fedora libsafe is not compiled with libprelude.  Talk to fedora-devel if you
-really want this to become default.)
-
 Be aware that any RPMS built while libsafe is installed will require libsafe 
 in order to install because of RPM's autodeps. You are encouraged to use a 
 chroot for RPM builds rather than a libsafe protected system.
 
+This libsafe is modified from upstream's 2002 release by Steve Grubb's
+2.0-16c patch, fixing bugs and protecting more functions.
 
 %prep
 %setup -q -n libsafe-2.0-16
+%patch0 -p1
 
 %build
 make
@@ -42,12 +40,12 @@
 %install
 rm -rf $RPM_BUILD_ROOT
 mkdir -p $RPM_BUILD_ROOT/lib
-install -m 0755 src/libsafe.so.2.0.16 $RPM_BUILD_ROOT/lib/libsafe.so.2.0.16
+install -m 0755 src/libsafe.so.2.0.16c $RPM_BUILD_ROOT/lib/libsafe.so.2.0.16c
 
 %files
 %defattr(-,root,root,-)
 %doc README EMAIL_NOTIFICATION LIBPRELUDE COPYING ChangeLog doc tools
-/lib/libsafe.so.2.0.16
+/lib/libsafe.so.2.0.16c
 
 %clean 
 rm -rf $RPM_BUILD_ROOT
@@ -89,5 +87,8 @@
 rm -f /etc/ld.so.preload.tmp
 
 %changelog
+* Thu Dec 16 2004 Warren Togami <wtogami at redhat.com> 2.0-16c
+- Patch with Steve Grubb's libsafe-2.0-16c improvements
+
 * Mon Apr 14 2003 Warren Togami <warren at togami.com> 2.0-16.fdr.1
 - Initial Fedora release, converted from 2.0-16 upstream




More information about the fedora-extras-commits mailing list