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