some people are now using rsync as a public server, using various
authorAndrew Tridgell <tridge@samba.org>
Mon, 15 Dec 1997 21:35:37 +0000 (21:35 +0000)
committerAndrew Tridgell <tridge@samba.org>
Mon, 15 Dec 1997 21:35:37 +0000 (21:35 +0000)
patches or wrappers. One problem with this is that rsync was not
written with this in mind and wasn't very careful about possible stack
overflows etc which could lead to security breaches. This wasn't a
problem when run in the traditional way as any user that can run rsync
can login anyway and cause much more damage that way.
This patch attempts to close possible stack overflow problems. I've
checked for all strcpy(), strcat(), sprintf() and memcpy()
overflows. I would appreciate it if someone else with a devious mind
could also go through the rsync source code and see if there are any
other stack overflows possible. Let me know if you do.

exclude.c
flist.c
rsync.c

index e82bafa5254a1d889a735f46068795b6a69bb636..a55b2f6200715abf03c345cd043becb9eec91043 100644 (file)
--- a/exclude.c
+++ b/exclude.c
@@ -188,7 +188,7 @@ void add_cvs_excludes(void)
   for (i=0; cvs_ignore_list[i]; i++)
     add_exclude(cvs_ignore_list[i]);
 
-  if ((p=getenv("HOME"))) {
+  if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
     sprintf(fname,"%s/.cvsignore",p);
     add_exclude_file(fname,0);
   }
diff --git a/flist.c b/flist.c
index 6ef990c3f1f802907a7c53b4a10252aa236e460b..d298db1dcd30b1b95cee2ef9017afc1c5a76a3cd 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -159,8 +159,8 @@ void send_file_entry_v11(struct file_struct *file,int f)
   last_gid = file->gid;
   last_time = file->modtime;
 
-  strcpy(lastname,file->name);
-  lastname[255] = 0;
+  strncpy(lastname,file->name,MAXPATHLEN-1);
+  lastname[MAXPATHLEN-1] = 0;
 }
 
 
@@ -229,8 +229,8 @@ void receive_file_entry_v11(struct file_struct *file,
   last_gid = file->gid;
   last_time = file->modtime;
 
-  strcpy(lastname,file->name);
-  lastname[255] = 0;
+  strncpy(lastname,file->name,MAXPATHLEN-1);
+  lastname[MAXPATHLEN-1] = 0;
 }
 
 
@@ -357,7 +357,8 @@ static void send_directory(int f,struct file_list *flist,char *dir)
     return;
   }
 
-  strcpy(fname,dir);
+  strncpy(fname,dir,MAXPATHLEN-1);
+  fname[MAXPATHLEN-1]=0;
   l = strlen(fname);
   if (fname[l-1] != '/')
     strcat(fname,"/");
@@ -372,7 +373,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
     if (strcmp(di->d_name,".")==0 ||
        strcmp(di->d_name,"..")==0)
       continue;
-    strcpy(p,di->d_name);
+    strncpy(p,di->d_name,MAXPATHLEN-l);
     send_file_name(f,flist,fname);
   }
 
@@ -407,7 +408,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
     char fname2[MAXPATHLEN];
     char *fname = fname2;
 
-    strcpy(fname,argv[i]);
+    strncpy(fname,argv[i],MAXPATHLEN-1);
+    fname[MAXPATHLEN-1] = 0;
 
     l = strlen(fname);
     if (l != 1 && fname[l-1] == '/') {
diff --git a/rsync.c b/rsync.c
index ea05f1e00be84983f0102dac738ff5da09308ecc..f66efc6377d1bbe1827a66e8488e7b8ede10d233 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -654,6 +654,10 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
       }
 
       /* open tmp file */
+      if (strlen(fname) > (MAXPATHLEN-8)) {
+       fprintf(FERROR,"filename too long\n");
+       continue;
+      }
       sprintf(fnametmp,"%s.XXXXXX",fname);
       if (NULL == mktemp(fnametmp)) {
        fprintf(FERROR,"mktemp %s failed\n",fnametmp);
@@ -694,6 +698,10 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
 
       if (make_backups) {
        char fnamebak[MAXPATHLEN];
+       if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
+               fprintf(FERROR,"backup filename too long\n");
+               continue;
+       }
        sprintf(fnamebak,"%s%s",fname,backup_suffix);
        if (rename(fname,fnamebak) != 0 && errno != ENOENT) {
          fprintf(FERROR,"rename %s %s : %s\n",fname,fnamebak,strerror(errno));
@@ -777,10 +785,11 @@ off_t send_files(struct file_list *flist,int f_out,int f_in)
 
       fname[0] = 0;
       if (file->dir) {
-       strcpy(fname,file->dir);
+       strncpy(fname,file->dir,MAXPATHLEN-1);
+       fname[MAXPATHLEN-1] = 0;
        strcat(fname,"/");
       }
-      strcat(fname,file->name);
+      strncat(fname,file->name,MAXPATHLEN-strlen(fname));
 
       if (verbose > 2) 
        fprintf(FERROR,"send_files(%d,%s)\n",i,fname);