Hi, there's some memory errors (malloc?) with this application and I was wondering if anyone might know where the problem is and how to possibly fix it?
The error:
Code:
*** glibc detected *** ./tur-ftpwho: corrupted double-linked list: 0x0000000000c82090 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3433278228]
/lib64/libc.so.6[0x343327a638]
/lib64/libc.so.6(cfree+0x76)[0x343327a866]
./tur-ftpwho[0x401a92]
./tur-ftpwho[0x4014ae]
/lib64/libc.so.6(__libc_start_main+0xfa)[0x343321e32a]
./tur-ftpwho[0x400b39]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:03 310097 /root/tur-ftpwho
00602000-00603000 rw-p 00002000 08:03 310097 /root/tur-ftpwho
00c82000-00ca3000 rw-p 00c82000 00:00 0 [heap]
3432e00000-3432e1d000 r-xp 00000000 08:03 758906 /lib64/ld-2.8.so
343301c000-343301d000 r--p 0001c000 08:03 758906 /lib64/ld-2.8.so
343301d000-343301e000 rw-p 0001d000 08:03 758906 /lib64/ld-2.8.so
3433200000-3433362000 r-xp 00000000 08:03 758908 /lib64/libc-2.8.so
3433362000-3433562000 ---p 00162000 08:03 758908 /lib64/libc-2.8.so
3433562000-3433566000 r--p 00162000 08:03 758908 /lib64/libc-2.8.so
3433566000-3433567000 rw-p 00166000 08:03 758908 /lib64/libc-2.8.so
3433567000-343356c000 rw-p 3433567000 00:00 0
3434a00000-3434a16000 r-xp 00000000 08:03 758999 /lib64/libgcc_s-4.3.0-20080428.so.1
3434a16000-3434c15000 ---p 00016000 08:03 758999 /lib64/libgcc_s-4.3.0-20080428.so.1
3434c15000-3434c16000 rw-p 00015000 08:03 758999 /lib64/libgcc_s-4.3.0-20080428.so.1
7fd974000000-7fd974021000 rw-p 7fd974000000 00:00 0
7fd974021000-7fd978000000 ---p 7fd974021000 00:00 0
7fd979c7c000-7fd979c7e000 rw-p 7fd979c7c000 00:00 0
7fd979c8b000-7fd979c8d000 rw-p 7fd979c8b000 00:00 0
7fff81c78000-7fff81c8d000 rw-p 7ffffffea000 00:00 0 [stack]
7fff81dff000-7fff81e00000 r-xp 7fff81dff000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted
Here's a bit of valgrind:
Code:
==18854== Memcheck, a memory error detector.
==18854== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==18854== Using LibVEX rev 1804, a library for dynamic binary translation.
==18854== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==18854== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==18854== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==18854==
--18854-- Command line
--18854-- ./tur-ftpwho
--18854-- Startup, with flags:
--18854-- -v
--18854-- Contents of /proc/version:
--18854-- Linux version 2.6.25.3-18.fc9.x86_64 (mockbuild@) (gcc version 4.3.0 20080428 (Red Hat 4.3.0-8) (GCC) ) #1 SMP Tue May 13 04:54:47 EDT 2008
--18854-- Arch and hwcaps: AMD64, amd64-sse2
--18854-- Page sizes: currently 4096, max supported 4096
--18854-- Valgrind library directory: /usr/lib64/valgrind
--18854-- Reading syms from /root/tur-ftpwho (0x400000)
--18854-- Reading syms from /usr/lib64/valgrind/amd64-linux/memcheck (0x38000000)
--18854-- object doesn't have a dynamic symbol table
--18854-- Reading syms from /lib64/ld-2.8.so (0x3432E00000)
--18854-- Reading suppressions file: /usr/lib64/valgrind/default.supp
--18854-- Reading syms from /usr/lib64/valgrind/amd64-linux/vgpreload_core.so (0x4802000)
--18854-- Reading syms from /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so (0x4A03000)
--18854-- REDIR: 0x3432e16070 (index) redirected to 0x4a07890 (index)
--18854-- REDIR: 0x3432e16220 (strcmp) redirected to 0x4a07e50 (strcmp)
--18854-- REDIR: 0x3432e16330 (strlen) redirected to 0x4a07b50 (strlen)
--18854-- Reading syms from /lib64/libc-2.8.so (0x3433200000)
--18854-- REDIR: 0x3433281420 (rindex) redirected to 0x4a076f0 (rindex)
--18854-- REDIR: 0x3433280f50 (strlen) redirected to 0x4a07b10 (strlen)
--18854-- REDIR: 0x343327cd80 (malloc) redirected to 0x4a072d0 (malloc)
--18854-- REDIR: 0x3433280a00 (strcpy) redirected to 0x4a07b70 (strcpy)
==18854== Invalid write of size 8
==18854== at 0x4019D9: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854==
==18854== Invalid read of size 8
==18854== at 0x4019F3: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854==
==18854== Invalid read of size 8
==18854== at 0x401A20: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854==
==18854== Invalid read of size 8
==18854== at 0x401A46: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
--18854-- REDIR: 0x343327a7f0 (free) redirected to 0x4a05fd0 (free)
--18854-- REDIR: 0xffffffffff600000 (???) redirected to 0x3802d093 (vgPlain_amd64_linux_REDIR_FOR_vgettimeofday)
--18854-- REDIR: 0x34332848a0 (strchrnul) redirected to 0x4a088a0 (strchrnul)
--18854-- REDIR: 0xffffffffff600400 (???) redirected to 0x3802d09d (vgPlain_amd64_linux_REDIR_FOR_vtime)
--18854-- REDIR: 0x3433281040 (strnlen) redirected to 0x4a07ac0 (strnlen)
^13809^Idle:^art03.rar^glftpd^339913:10:15
==18854==
==18854== ERROR SUMMARY: 8 errors from 4 contexts (suppressed: 4 from 1)
==18854==
==18854== 2 errors in context 1 of 4:
==18854== Invalid read of size 8
==18854== at 0x401A46: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854==
==18854== 2 errors in context 2 of 4:
==18854== Invalid read of size 8
==18854== at 0x401A20: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854==
==18854== 2 errors in context 3 of 4:
==18854== Invalid read of size 8
==18854== at 0x4019F3: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854==
==18854== 2 errors in context 4 of 4:
==18854== Invalid write of size 8
==18854== at 0x4019D9: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
==18854== Address 0x4c1a110 is 0 bytes after a block of size 16 alloc'd
==18854== at 0x4A0739E: malloc (vg_replace_malloc.c:207)
==18854== by 0x4018A4: buffer_groups (in /root/tur-ftpwho)
==18854== by 0x4014AD: main (in /root/tur-ftpwho)
--18854--
--18854-- supp: 4 dl-hack3-1
==18854==
==18854== IN SUMMARY: 8 errors from 4 contexts (suppressed: 4 from 1)
==18854==
==18854== malloc/free: in use at exit: 110 bytes in 9 blocks.
==18854== malloc/free: 11 allocs, 2 frees, 219 bytes allocated.
==18854==
==18854== searching for pointers to 9 not-freed blocks.
==18854== checked 64,272 bytes.
==18854==
==18854== LEAK SUMMARY:
==18854== definitely lost: 47 bytes in 4 blocks.
==18854== possibly lost: 0 bytes in 0 blocks.
==18854== still reachable: 63 bytes in 5 blocks.
==18854== suppressed: 0 bytes in 0 blocks.
==18854== Rerun with --leak-check=full to see details of leaked memory.
--18854-- memcheck: sanity checks: 3 cheap, 2 expensive
--18854-- memcheck: auxmaps: 58 auxmap entries (3712k, 3M) in use
--18854-- memcheck: auxmaps_L1: 2006 searches, 10841 cmps, ratio 54:10
--18854-- memcheck: auxmaps_L2: 75 searches, 58 nodes
--18854-- memcheck: SMs: n_issued = 15 (240k, 0M)
--18854-- memcheck: SMs: n_deissued = 0 (0k, 0M)
--18854-- memcheck: SMs: max_noaccess = 524287 (8388592k, 8191M)
--18854-- memcheck: SMs: max_undefined = 0 (0k, 0M)
--18854-- memcheck: SMs: max_defined = 117 (1872k, 1M)
--18854-- memcheck: SMs: max_non_DSM = 15 (240k, 0M)
--18854-- memcheck: max sec V bit nodes: 0 (0k, 0M)
--18854-- memcheck: set_sec_vbits8 calls: 0 (new: 0, updates: 0)
--18854-- memcheck: max shadow mem size: 4384k, 4M
--18854-- translate: fast SP updates identified: 1,186 ( 86.0%)
--18854-- translate: generic_known SP updates identified: 129 ( 9.3%)
--18854-- translate: generic_unknown SP updates identified: 64 ( 4.6%)
--18854-- tt/tc: 3,881 tt lookups requiring 3,942 probes
--18854-- tt/tc: 3,881 fast-cache updates, 5 flushes
--18854-- transtab: new 1,830 (42,362 -> 687,343; ratio 162:10) [0 scs]
--18854-- transtab: dumped 0 (0 -> ??)
--18854-- transtab: discarded 12 (257 -> ??)
--18854-- scheduler: 362,540 jumps (bb entries).
--18854-- scheduler: 3/2,124 major/minor sched events.
--18854-- sanity: 4 cheap, 2 expensive checks.
--18854-- exectx: 769 lists, 15 contexts (avg 0 per list)
--18854-- exectx: 25 searches, 10 full compares (400 per 1000)
--18854-- exectx: 0 cmp2, 28 cmp4, 0 cmpAll
--18854-- errormgr: 8 supplist searches, 116 comparisons during search
--18854-- errormgr: 12 errlist searches, 44 comparisons during search
and finally the source:
Code:
#define VER "3.0 (gl2.1)"
#define KEY 0x0000DEAD // Default KEY used by DAEMON
#define GLGROUP "/mnt/array/glftpd/etc/group"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/param.h>
#include <fcntl.h>
#include <sys/stat.h>
struct ONLINE {
char tagline[64]; /* The users tagline */
char username[24]; /* The username of the user */
char status[256]; /* The status of the user, idle, RETR, etc */
short int ssl_flag; /* 0 = no ssl, 1 = ssl on control, 2 = ssl on control and data */
char host[256]; /* The host the user is comming from (with ident) */
char currentdir[256]; /* The users current dir (fullpath) */
long groupid; /* The groupid of the users primary group */
time_t login_time; /* The login time since the epoch (man 2 time) */
struct timeval tstart; /* replacement for last_update. */
struct timeval txfer; /* The time of the last succesfull transfer. */
unsigned long long bytes_xfer; /* bytes transferred so far. */
unsigned long long bytes_txfer; /* bytes transferred in the last loop (speed limiting) */
pid_t procid; /* The processor id of the process */
};
static struct ONLINE *online;
static int dl = 0;
static int ul = 0;
static int num_users = 0;
static int shmid;
static struct shmid_ds ipcbuf;
static void quit();
static double calc_time();
struct GROUP {
char *name;
gid_t id;
};
int groups = 0,
GROUPS = 0;
static struct GROUP **group;
struct stat filestat;
char* get_g_name(int gid) {
int n;
for ( n = 0 ; n < groups ; n++ ) if ( group[n]->id == gid ) return group[n]->name;
return "NoGroup";
}
static char *
trim( char *str )
{
char *ibuf;
char *obuf;
if ( str )
{
for ( ibuf = obuf = str; *ibuf; )
{
while ( *ibuf && ( isspace ( *ibuf ) ) )
ibuf++;
if ( *ibuf && ( obuf != str ) )
*( obuf++ ) = ' ';
while ( *ibuf && ( !isspace ( *ibuf ) ) )
*( obuf++ ) = *( ibuf++ );
}
*obuf = '\0';
}
return( str );
}
static char hmsbuf[50];
void
pid_hms_format( time_t testtime )
{
time_t timenow = time( NULL );
time_t difftime;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
difftime = timenow - testtime;
while ( difftime >= (time_t)3600 )
{
difftime -= (time_t)3600;
hours++;
}
while ( difftime >= (time_t)60 )
{
difftime -= (time_t)60;
minutes++;
}
if ( hours != 0 )
sprintf( hmsbuf, "%02d:%02d:%02d", hours, minutes, difftime );
else
sprintf( hmsbuf, " %02d:%02d", minutes, difftime );
}
static int
checkusers(void)
{
register int i, j, found = 0;
char statbuf[ 500 ];
char idletime[ 500 ];
char pidbuf[ 10 ];
char filename[20];
char bar[20];
struct timeval tstop;
unsigned hours;
unsigned char minutes;
unsigned seconds;
gettimeofday(&tstop, (struct timezone *)0);
for (i=0; i<num_users; i++)
{
if (online[i].procid == 0)
continue;
sprintf( pidbuf, "%u", online[i].procid );
pid_hms_format( online[i].tstart.tv_sec );
if ((!strncasecmp (online[i].status, "STOR", 4) ||
!strncasecmp (online[i].status, "APPE", 4)) &&
online[i].bytes_xfer != 0) {
strncpy(filename, online[i].status+5, sizeof(filename));
j = strlen(filename);
if (!isprint(filename[j-2]))
filename[j-2] = '\0';
else if (!isprint(filename[j-1]))
filename[j-1] = '\0';
sprintf( statbuf, "Up:^%.1f", calc_time(i) );
sprintf( idletime, "", hmsbuf );
ul++;
}
/* Downloading */
else if (!strncasecmp (online[i].status, "RETR", 4) && online[i].bytes_xfer != 0)
{
strncpy(filename, online[i].status+5, sizeof(filename));
j = strlen(filename);
if (!isprint(filename[j-2]))
filename[j-2] = '\0';
else if (!isprint(filename[j-1]))
filename[j-1] = '\0';
sprintf( statbuf, "Dn:^%.1f", calc_time(i) );
sprintf( idletime, "", hmsbuf );
dl++;
}
/* Idling */
else if (time(NULL) - online[i].tstart.tv_sec > 5)
{
*bar = *filename = hours = minutes = 0;
seconds = tstop.tv_sec - online[i].tstart.tv_sec;
while ( seconds >= 3600 ) { hours++; seconds -= 3600; }
while ( seconds >= 60 ) { minutes++; seconds -= 60; }
sprintf( statbuf, "Idle:", hmsbuf );
sprintf( idletime, "%02d:%02d:%02d", hours, minutes, seconds);
}
/* Doing something else... */
else
{
sprintf( statbuf, "\"%s\"", online[i].status );
trim(statbuf);
sprintf( idletime, "", hmsbuf );
}
pid_hms_format( online[i].login_time);
fprintf( stdout, "%-1.12s^%-1.5s^%-1.44s^%s^%s^%s\n",
online[i].username, pidbuf, statbuf, online[i].currentdir, get_g_name(online[i].groupid), idletime);
found++;
}
return (found);
}
int
main( int argc, char **argv )
{
int numusers;
if (argc >= 2)
{
if (strstr(argv[1],"-v") != NULL)
{
printf ("Tur-FtpWho. A modified ftpwho by Turranius\n");
printf ("Version %s - modified by f|lowman.\n",VER);
quit (0);
}
}
buffer_groups(GLGROUP);
if ((shmid = shmget( (key_t)KEY, 0, 0))
== -1)
{
fprintf(stdout, "No Users Currently On Site!\n");
exit(0);
}
if ((online = (struct ONLINE *)shmat( shmid, NULL, SHM_RDONLY))
== (struct ONLINE *)-1)
{
fprintf(stdout, "Error: (SHMAT) Failed!\n");
exit(1);
}
shmctl( shmid, IPC_STAT, &ipcbuf);
num_users = ipcbuf.shm_segsz / sizeof( struct ONLINE );
numusers = checkusers();
quit( 0 );
}
static double
calc_time(int pid)
{
struct timeval tstop;
double delta, rate;
if (online[pid].bytes_xfer < 1)
return 0;
gettimeofday(&tstop, (struct timezone *)0 );
delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000.)) -
((online[pid].tstart.tv_sec*10.)+(online[pid].tstart.tv_usec/100000.));
delta = delta/10.;
rate = ((online[pid].bytes_xfer / 1024.0) / (delta));
if (!rate) rate++;
return (double)(rate);
}
static void
quit(int exit_status)
{
shmctl( shmid, IPC_STAT, &ipcbuf);
if (ipcbuf.shm_nattch <= 1) {
shmctl( shmid, IPC_RMID, 0);
}
shmdt(0);
exit(exit_status);
}
/* Buffer groups file */
int buffer_groups(char *groupfile) {
char *f_buf,
*g_name,
*f_name;
long f, n, m,
f_size,
g_id,
g_n_size,
l_start = 0;
f_name = malloc( strlen(groupfile) + 2 );
sprintf( f_name, "%s", groupfile );
f = open( f_name, O_NONBLOCK );
fstat( f, &filestat );
f_size = filestat.st_size;
f_buf = malloc( f_size );
read( f, f_buf, f_size );
for ( n = 0 ; n < f_size ; n++ ) if ( f_buf[n] == '\n' ) GROUPS++;
group = malloc( GROUPS * sizeof( int ) );
for ( n = 0 ; n < f_size ; n++ ) {
if ( f_buf[n] == '\n' || n == f_size ) {
f_buf[n] = 0;
m = l_start;
while ( f_buf[m] != ':' && m < n ) m++;
if ( m != l_start ) {
f_buf[m] = 0;
g_name = f_buf + l_start;
g_n_size = m - l_start;
m = n;
while ( f_buf[m] != ':' && m > l_start ) m--;
f_buf[m] = 0;
while ( f_buf[m] != ':' && m > l_start ) m--;
if ( m != n ) {
g_id = atoi( f_buf + m + 1 );
group[groups] = malloc( sizeof( struct GROUP ) );
group[groups]->name = malloc( g_n_size + 1 );
strcpy( group[groups]->name, g_name );
group[groups]->id = g_id;
groups++;
}
}
l_start = n + 1;
}
}
close( f );
free( f_buf );
free( f_name );
}