我一直在和朋友一起编写一些代码,而且它主要是在archlinux上测试过的。当我们重新编译并测试ubuntu时,它会通过程序获得一个方法,然后返回一个堆栈粉碎错误。 我添加了一些打印语句来确定崩溃发生的位置,但我们都不能看到原因。
代码如下所示,当代码从“authenticate”函数返回时,似乎发生了错误:
/** Includes **/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <mysql.h>
/* Definitions */
#define LIC_SERVER_PORTNO 2325
//#define LIC_SERVER_ADDR "69.68.67.66"
#define SERVER_PORTNO 4959
#define UPLEN 45
#define MAX_USER_NUM 100
//#define MAX_KA_TIME 2000
#define MAX_KA_TIME 20
/** Structure to hold info on logged in users **/
typedef struct {
char *ip;
time_t login_time;
time_t last_check;
} user;
/** GLOBALS **/
user *users;
int user_num;
/** Version string function **/
const char* version()
{
return "0.1r3";
}
void exit_signal(int sig)
{
pthread_exit(NULL);
printf("\nTerminating server. Goodbye!\n\n");
(void) signal(SIGINT, SIG_DFL);
exit(0);
}
/** Function for error reporting **/
void error(char *msg)
{
perror(msg);
exit(1);
}
int authenticate(char* uname,char* pwd)
{
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
int r=0;
const char *server = "localhost";
const char *user = "root";
const char *password = "12345"; /* set me first */
const char *database = "test";
printf("inside authenticate %s\n","one");
conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(conn, server,user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
printf("inside authenticate %s\n","two");
/* send SQL query */
char query [] = "select * from users where username='";
char q2 [] = "';";
//char *tmp,*query;
strcat(query,uname);
strcat(query,q2);
printf("inside authenticate %s\n","three");
if (mysql_query(conn,query)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_use_result(conn);
if (res==NULL) return 0;
row = mysql_fetch_row(res);
if (row==NULL) return 0;
printf("inside authenticate %s\n","four");
if ( (strcmp(row[2],uname)==0) && (strcmp(row[3],pwd)==0) )
r = 1;
/* close connection */
mysql_free_result(res);
mysql_close(conn);
printf("inside authenticate %s\n","five");
return r;
}
/** Keep alive guard **/
void *keep_alive_guard(void *thread_data)
{
int i,k,c;
time_t ts;
while (1) {
ts = time(NULL);
for (i=0;i<user_num;i++) {
char the_ip[50],the_ip2[50];
char scall1[1024],scall2[1024];
if (ts-users[i].last_check>MAX_KA_TIME) {
strncpy(the_ip,users[i].ip,50);
strncpy(the_ip2,users[i].ip,50);
// system call to delete redirection for all incoming packets to licence server for port 1055
strncpy(scall1,"iptables -t nat -D PREROUTING -s ",1024);
strcat(scall1,the_ip);
strcat(scall1," -j REDIRECT -p tcp --to-port 1055 --dport 4957");
//printf("%s\n",scall1);
FILE *phony = popen(scall1,"r");
pclose(phony);
// system call to delete redirection for all incoming packets to licence server for port 2325
strncpy(scall2,"iptables -t nat -D PREROUTING -s ",1024);
strcat(scall2,the_ip2);
strcat(scall2," -j REDIRECT -p tcp --to-port 2325 --dport 4958");
//printf("%s\n",scall2);
FILE *phony2 = popen(scall2,"r");
pclose(phony2);
for (k=i;k<user_num;k++) {
if (k!=MAX_USER_NUM-1) {
memcpy(&users[k],&users[k+1],sizeof(user));
}
}
user_num--;
}
}
}
}
/* Main function */
int main(int argc,char* argv[])
{
// Initializing
printf("Licence proxy (server) v%s\n",version());
printf("Initializing...");
user_num = 0;
users = (user*)malloc(MAX_USER_NUM*sizeof(user));
(void) signal(SIGINT, exit_signal);
FILE *notha = popen("iptables -A INPUT ! -s 127.0.0.1 -p tcp --dport 1055 -j DROP","r");
pclose(notha);
FILE *notha2 = popen("iptables -A INPUT ! -s 127.0.0.1 -p tcp --dport 2325 -j DROP","r");
pclose(notha2);
// Basic variables for socket handling
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr; //addresses
int n,i;
// Create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error((char*)"ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = SERVER_PORTNO; // Set port number to listen
// Set options for socket and bind to port
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error((char*)"ERROR on binding");
printf("ok!\n\nRunning...\n\n");
// Start listening
listen(sockfd,5);
// Create thread for keep alive guard
pthread_t kag;
int rc;
rc = pthread_create(&kag,NULL,keep_alive_guard,(void *)user_num);
char datauser [UPLEN],*user;
char datapass [UPLEN],*pass;
char datareq_id [UPLEN],*req_id;
char respOK [] = "OK";
char respNK [] = "NK";
while (1) {
// Accept connection from peer
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,(socklen_t*)&clilen);
if (newsockfd < 0)
error((char*)"ERROR on accept");
n = recv(newsockfd,datareq_id,UPLEN,0);
if (n < 0) error((char*)"ERROR reading username from client");
req_id = (char*)malloc(strlen(datareq_id));
strncpy(req_id,datareq_id,strlen(datareq_id));
if (req_id[0]=='K') {
for (i=0;i<user_num;i++) {
if (strcmp(users[i].ip,inet_ntoa(cli_addr.sin_addr))==0) {
users[i].last_check = time(NULL);
}
}
}
else if (req_id[0]=='L') {
printf("Transaction requested from %s\n",inet_ntoa(cli_addr.sin_addr));
// Read and wrap username from client
n = recv(newsockfd,datauser,UPLEN,0);
if (n < 0) error((char*)"ERROR reading username from client");
user = (char*)malloc(strlen(datauser));
strncpy(user,datauser,strlen(datauser));
printf("here %s\n","one");
// Read and wrap password from client
n = recv(newsockfd,datapass,UPLEN,0);
if (n < 0) error((char*)"ERROR reading password from client");
pass = (char*)malloc(strlen(datapass));
strncpy(pass,datapass,strlen(datapass));
printf("here %s\n","two");
char scall[1024],scall2[1024];
printf("here %s\n","two + one line");
//Cross-check authorization data against MYSQL database and take action
if (authenticate(user,pass)==1) {
printf("outside authenticate (success) %s\n","one");
n = send(newsockfd,respOK,UPLEN,0);
printf("outside authenticate (success) %s\n","two");
if (n < 0) error((char*)"ERROR writing to socket");
printf("here %s\n","two and a lot");
// system call to redirect all incoming packets to licence server for port 1055
strncpy(scall,"iptables -t nat -A PREROUTING -s ",1024);
printf("here %s\n","three");
strcat(scall,inet_ntoa(cli_addr.sin_addr));
strcat(scall," -j REDIRECT -p tcp --to-port 1055 --dport 4957");
//printf("%s\n",scall);
FILE *phony = popen(scall,"r");
pclose(phony);
printf("here %s\n","four");
// system call to redirect all incoming packets to licence server for port 2325
strncpy(scall2,"iptables -t nat -A PREROUTING -s ",1024);
strcat(scall2,inet_ntoa(cli_addr.sin_addr));
strcat(scall2," -j REDIRECT -p tcp --to-port 2325 --dport 4958");
//printf("%s\n",scall2);
FILE *phony2 = popen(scall2,"r");
pclose(phony2);
printf("here %s\n","five");
printf("%s successfully logged in.\n",inet_ntoa(cli_addr.sin_addr));
users[user_num].ip = (char*)malloc(strlen(inet_ntoa(cli_addr.sin_addr)));
strncpy(users[user_num].ip,inet_ntoa(cli_addr.sin_addr),strlen(inet_ntoa(cli_addr.sin_addr)));
printf("here %s\n","six");
users[user_num].login_time = time(NULL);
users[user_num].last_check = time(NULL);
user_num++;
}
else
{
printf("outside authenticate (fail) %s","one");
n = send(newsockfd,respNK,UPLEN,0);
if (n < 0) error((char*)"ERROR writing to socket");
printf("Access denied to %s.\n",inet_ntoa(cli_addr.sin_addr));
}
free(user);
free(pass);
}
close(newsockfd);
}
shutdown(sockfd,SHUT_RDWR);
close(sockfd);
pthread_exit(NULL);
return 0;
}
错误位置远离下面的控制台输出:
Transaction requested from 192.168.1.10
here one
here two
here two + one line
inside authenticate one
inside authenticate two
inside authenticate three
inside authenticate four
inside authenticate five
*** stack smashing detected ***: ./lproxy-server terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x50)[0xb757f390]
/lib/tls/i686/cmov/libc.so.6(+0xe233a)[0xb757f33a]
./lproxy-server(authenticate+0x28c)[0x8049299]
./lproxy-server(main+0x49d)[0x804998e]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb74b3bd6]
./lproxy-server[0x8048f41]
======= Memory map: ========
08048000-0804b000 r-xp 00000000 08:01 128583 /home/martin/Downloads/licproxy-server2/lproxy-server
0804b000-0804c000 r--p 00002000 08:01 128583 /home/martin/Downloads/licproxy-server2/lproxy-server
0804c000-0804d000 rw-p 00003000 08:01 128583 /home/martin/Downloads/licproxy-server2/lproxy-server
0915b000-0917c000 rw-p 00000000 00:00 0 [heap]
b6bce000-b6beb000 r-xp 00000000 08:01 2648 /lib/libgcc_s.so.1
b6beb000-b6bec000 r--p 0001c000 08:01 2648 /lib/libgcc_s.so.1
b6bec000-b6bed000 rw-p 0001d000 08:01 2648 /lib/libgcc_s.so.1
b6bfc000-b6bfd000 ---p 00000000 00:00 0
b6bfd000-b73ff000 rw-p 00000000 00:00 0
b73ff000-b7412000 r-xp 00000000 08:01 2763 /lib/libz.so.1.2.3.3
b7412000-b7413000 r--p 00012000 08:01 2763 /lib/libz.so.1.2.3.3
b7413000-b7414000 rw-p 00013000 08:01 2763 /lib/libz.so.1.2.3.3
b7414000-b7438000 r-xp 00000000 08:01 8012 /lib/tls/i686/cmov/libm-2.11.1.so
b7438000-b7439000 r--p 00023000 08:01 8012 /lib/tls/i686/cmov/libm-2.11.1.so
b7439000-b743a000 rw-p 00024000 08:01 8012 /lib/tls/i686/cmov/libm-2.11.1.so
b743a000-b744d000 r-xp 00000000 08:01 8048 /lib/tls/i686/cmov/libnsl-2.11.1.so
b744d000-b744e000 r--p 00012000 08:01 8048 /lib/tls/i686/cmov/libnsl-2.11.1.so
b744e000-b744f000 rw-p 00013000 08:01 8048 /lib/tls/i686/cmov/libnsl-2.11.1.so
b744f000-b7451000 rw-p 00000000 00:00 0
b7451000-b745a000 r-xp 00000000 08:01 7807 /lib/tls/i686/cmov/libcrypt-2.11.1.so
b745a000-b745b000 r--p 00008000 08:01 7807 /lib/tls/i686/cmov/libcrypt-2.11.1.so
b745b000-b745c000 rw-p 00009000 08:01 7807 /lib/tls/i686/cmov/libcrypt-2.11.1.so
b745c000-b7483000 rw-p 00000000 00:00 0
b7483000-b7498000 r-xp 00000000 08:01 8259 /lib/tls/i686/cmov/libpthread-2.11.1.so
b7498000-b7499000 r--p 00014000 08:01 8259 /lib/tls/i686/cmov/libpthread-2.11.1.so
b7499000-b749a000 rw-p 00015000 08:01 8259 /lib/tls/i686/cmov/libpthread-2.11.1.so
b749a000-b749d000 rw-p 00000000 00:00 0
b749d000-b75f0000 r-xp 00000000 08:01 7789 /lib/tls/i686/cmov/libc-2.11.1.so
b75f0000-b75f1000 ---p 00153000 08:01 7789 /lib/tls/i686/cmov/libc-2.11.1.so
b75f1000-b75f3000 r--p 00153000 08:01 7789 /lib/tls/i686/cmov/libc-2.11.1.so
b75f3000-b75f4000 rw-p 00155000 08:01 7789 /lib/tls/i686/cmov/libc-2.11.1.so
b75f4000-b75f7000 rw-p 00000000 00:00 0
b75f7000-b77a1000 r-xp 00000000 08:01 5403 /usr/lib/libmysqlclient.so.16.0.0
b77a1000-b77a2000 ---p 001aa000 08:01 5403 /usr/lib/libmysqlclient.so.16.0.0
b77a2000-b77a5000 r--p 001aa000 08:01 5403 /usr/lib/libmysqlclient.so.16.0.0
b77a5000-b77ea000 rw-p 001ad000 08:01 5403 /usr/lib/libmysqlclient.so.16.0.0
b77ea000-b77eb000 rw-p 00000000 00:00 0
b77ed000-b77f7000 r-xp 00000000 08:01 8119 /lib/tls/i686/cmov/libnss_files-2.11.1.so
b77f7000-b77f8000 r--p 00009000 08:01 8119 /lib/tls/i686/cmov/libnss_files-2.11.1.so
b77f8000-b77f9000 rw-p 0000a000 08:01 8119 /lib/tls/i686/cmov/libnss_files-2.11.1.so
b77f9000-b77fc000 rw-p 00000000 00:00 0
b77fc000-b77fd000 r-xp 00000000 00:00 0 [vdso]
b77fd000-b7818000 r-xp 00000000 08:01 2813 /lib/ld-2.11.1.so
b7818000-b7819000 r--p 0001a000 08:01 2813 /lib/ld-2.11.1.so
b7819000-b781a000 rw-p 0001b000 08:01 2813 /lib/ld-2.11.1.so
bfd4c000-bfd61000 rw-p 00000000 00:00 0 [stack]
Aborted
任何人都可以了解我们做错了什么,我们如何能够自己解决这个问题,以及我们如何在将来避免类似的错误。
此外,如果有人对archlinux的工作原理有什么了解,而不是ubuntu,我会非常有兴趣听到它。
答案 0 :(得分:3)
使用strcat追加到堆栈上的数组(query
),并且只具有初始值所需的确切大小。这样,你就会溢出堆栈上的缓冲区,这会导致各种好奇和有趣的行为。
它适用于Arch Linux是巧合; Ubuntu上的gcc默认启用堆栈检查并找到错误。
答案 1 :(得分:1)
这条线看起来很可疑:
strncpy(users[user_num].ip,inet_ntoa(cli_addr.sin_addr),strlen(inet_ntoa(cli_addr.sin_addr)));
BTW,strncpy
不会添加任何尾随\0
。当malloc返回的区域未被清除时,可能会导致后续的字符串操作溢出。