Hello,
I just encountered a bug on my CentOS5 using su -c.
I have a small piece of C code to spawn processes, and I wanted theses
processes to run under a certain user with specific rights to the
filesystem.
To execute this, I created a user named 'ejabberd', my daemon executable
file was 'dispatch_daemon'.
As you can see in dispatch_daemon.c, I realloc my buffer when it needs
to.
Here is the error I get when running the daemon through su -c
'./dispatch_daemon 5284' ejabberd :
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for
device]
*** glibc detected
*** /usr/local/ejabberd/bin/IperExternModule/dispatch_daemon:
realloc(): invalid next size: 0x09d79008 ***
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for
device]
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for
device]
======= Backtrace: =========
/lib/libc.so.6[0x43f63920]
/lib/libc.so.6(realloc+0xfe)[0x43f6580e]
/lib/libc.so.6[0x43f65be1]
/lib/libc.so.6(realloc+0x3c)[0x43f6574c]
/usr/local/ejabberd/bin/IperExternModule/dispatch_daemon[0x804891e]
/lib/libc.so.6(__libc_start_main+0xdc)[0x43f11dec]
/usr/local/ejabberd/bin/IperExternModule/dispatch_daemon[0x8048681]
Even though the tcsetpgrp errors which disappear when the Suid bit is
set on the daemon, realloc keeps raising an error just like here.
By the way, gdb told me 0x09d79008 is the value of the data pointer, not
the new size as the error message lead me to think at first.
And finally, it appears that using su to log as ejabberd, then starting
the daemon doesn't raise the error, as opposed to su -c.
I hope this report was of any use to you,
Cheers, Mathieu Sivade
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 4096
#define BACKLOG_SIZE 50
#define PHP_BIN "/usr/bin/php"
#define PHP_MODULE "./JabberExternModule.php"
void spawn_php(char *data);
int main(int argc, char** argv) {
int port, sock, nsock;
ssize_t datacount, ndata;
size_t datasize = 0;
char *data = NULL;
struct sockaddr_in saddr;
if (argc < 2) {
fprintf(stderr,"USAGE : %s <listening_port>\n", argv[0]);
return 2;
}
port = atoi(argv[1]);
printf("Daemon serving at port %d\n", port);
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket failed to be created");
return 1;
}
memset(&saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);
inet_aton("0.0.0.0", &saddr.sin_addr);
if(bind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)) < 0) {
perror("socket failed to bind");
return 1;
}
if (listen(sock, BACKLOG_SIZE) < 0) {
perror("socket failed to start listening");
return 1;
}
printf("Daemon connected, waiting for connections\n");
while ((nsock = accept(sock, NULL, NULL)) >= 0) {
printf("Incoming connection accepted\n");
if (!data) {
data = (char*)calloc(BUFFER_SIZE, sizeof(char));
datasize = BUFFER_SIZE * sizeof(char);
}
else {
memset(data,0,datasize);
}
datacount = 0;
do {
ndata = recv(nsock, data+datacount, datasize, 0);
datacount += ndata;
if (datacount >= datasize) {
data = (char*)realloc(data,datasize+BUFFER_SIZE);
memset(data+datasize,0,BUFFER_SIZE);
datasize += BUFFER_SIZE;
}
} while (ndata > 0);
/* no need to maintain connection */
close(nsock);
if (datacount > 0)
spawn_php(data);
else
perror("Failed getting a command, connection shut down");
printf("Waiting for another job to connect\n");
}
perror("Connexion lost, stopping daemon");
return 1;
}
void spawn_php(char *data) {
int cpid = fork();
if (cpid == 0) {
execlp(PHP_BIN, "-f", PHP_MODULE, data, NULL);
perror("Couldn't spawn child process");
exit(1);
}
else if (cpid < 0) {
fprintf(stderr, "Couldn't fork : restarter will now shut down\n");
exit(1);
}
}
_______________________________________________
Bug-coreutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-coreutils