in some cases we were not sufficiently careful about reading integers
from the network.
Also, make sure log messages are always nul-terminated.
+ SECURITY FIXES:
+
+ * Signedness security patch from Sebastian Krahmer
+ <krahmer@suse.de> -- in some cases we were not sufficiently
+ careful about reading integers from the network.
+
+ * Fix possible string mangling in log files.
+
* Fix for setting local address of outgoing sockets.
* Better handling of hardlinks and devices on platforms with
* Fix for setting local address of outgoing sockets.
* Better handling of hardlinks and devices on platforms with
void recv_exclude_list(int f)
{
char line[MAXPATHLEN];
void recv_exclude_list(int f)
{
char line[MAXPATHLEN];
while ((l=read_int(f))) {
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
while ((l=read_int(f))) {
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
-static int write_sparse(int f,char *buf,int len)
+static int write_sparse(int f,char *buf,size_t len)
{
int l1=0,l2=0;
int ret;
{
int l1=0,l2=0;
int ret;
-int write_file(int f,char *buf,int len)
+int write_file(int f,char *buf,size_t len)
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
+ unsigned int l1=0,l2=0;
char *p;
struct file_struct *file;
char *p;
struct file_struct *file;
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
+ if (l < 0) {
+ rprintf(FERROR,"overflow: l=%d\n", l);
+ overflow("receive_file_entry");
+ }
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry 2");
read_sbuf(f,file->link,l);
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry 2");
read_sbuf(f,file->link,l);
static int io_error_fd = -1;
static int io_error_fd = -1;
-static void read_loop(int fd, char *buf, int len);
+static void read_loop(int fd, char *buf, size_t len);
static void check_timeout(void)
{
static void check_timeout(void)
{
* give a better explanation. We can tell whether the connection has
* started by looking e.g. at whether the remote version is known yet.
*/
* give a better explanation. We can tell whether the connection has
* started by looking e.g. at whether the remote version is known yet.
*/
-static int read_timeout (int fd, char *buf, int len)
+static int read_timeout (int fd, char *buf, size_t len)
/*! Continue trying to read len bytes - don't return until len has
been read. */
/*! Continue trying to read len bytes - don't return until len has
been read. */
-static void read_loop (int fd, char *buf, int len)
+static void read_loop (int fd, char *buf, size_t len)
{
while (len) {
int n = read_timeout(fd, buf, len);
{
while (len) {
int n = read_timeout(fd, buf, len);
*
* Never returns <= 0.
*/
*
* Never returns <= 0.
*/
-static int read_unbuffered(int fd, char *buf, int len)
+static int read_unbuffered(int fd, char *buf, size_t len)
{
static int remaining;
int tag, ret=0;
{
static int remaining;
int tag, ret=0;
/* do a buffered read from fd. don't return until all N bytes
have been read. If all N can't be read then exit with an error */
/* do a buffered read from fd. don't return until all N bytes
have been read. If all N can't be read then exit with an error */
-static void readfd (int fd, char *buffer, int N)
+static void readfd (int fd, char *buffer, size_t N)
-void read_buf(int f,char *buf,int len)
+void read_buf(int f,char *buf,size_t len)
-void read_sbuf(int f,char *buf,int len)
+void read_sbuf(int f,char *buf,size_t len)
{
read_buf (f,buf,len);
buf[len] = 0;
{
read_buf (f,buf,len);
buf[len] = 0;
}
/* write len bytes to fd */
}
/* write len bytes to fd */
-static void writefd_unbuffered(int fd,char *buf,int len)
+static void writefd_unbuffered(int fd,char *buf,size_t len)
{
int total = 0;
fd_set w_fds, r_fds;
{
int total = 0;
fd_set w_fds, r_fds;
/* write an message to a multiplexed stream. If this fails then rsync
exits */
/* write an message to a multiplexed stream. If this fails then rsync
exits */
-static void mplex_write(int fd, enum logcode code, char *buf, int len)
+static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
{
char buffer[4096];
int n = len;
{
char buffer[4096];
int n = len;
-static void writefd(int fd,char *buf,int len)
+static void writefd(int fd,char *buf,size_t len)
{
stats.total_written += len;
{
stats.total_written += len;
-void write_buf(int f,char *buf,int len)
+void write_buf(int f,char *buf,size_t len)
-int read_line(int f, char *buf, int maxlen)
+int read_line(int f, char *buf, size_t maxlen)
{
while (maxlen) {
buf[0] = 0;
{
while (maxlen) {
buf[0] = 0;
}
/* write an message to the multiplexed error stream */
}
/* write an message to the multiplexed error stream */
-int io_multiplex_write(enum logcode code, char *buf, int len)
+int io_multiplex_write(enum logcode code, char *buf, size_t len)
{
if (!io_multiplexing_out) return 0;
{
if (!io_multiplexing_out) return 0;
- if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
+ if (l + ((int)(s - &buf[0])) >= sizeof(buf)) {
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
p[0]);
exit_cleanup(RERR_MESSAGEIO);
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
p[0]);
exit_cleanup(RERR_MESSAGEIO);
static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
OFF_T total_size)
{
static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
OFF_T total_size)
{
- int i,n,remainder,len,count;
+ int i;
+ unsigned int n,remainder,len,count;
OFF_T offset = 0;
OFF_T offset2;
char *data;
OFF_T offset = 0;
OFF_T offset2;
char *data;
struct sum_struct {
OFF_T flength; /* total file length */
struct sum_struct {
OFF_T flength; /* total file length */
- int count; /* how many chunks */
- int remainder; /* flength % block_length */
- int n; /* block_length */
+ size_t count; /* how many chunks */
+ size_t remainder; /* flength % block_length */
+ size_t n; /* block_length */
struct sum_buf *sums; /* points to info for each chunk */
};
struct sum_buf *sums; /* points to info for each chunk */
};
derived from GNU C's cccp.c.
*/
derived from GNU C's cccp.c.
*/
-static int full_write(int desc, char *ptr, int len)
+static int full_write(int desc, char *ptr, size_t len)
for an error.
derived from GNU C's cccp.c. */
for an error.
derived from GNU C's cccp.c. */
-static int safe_read(int desc, char *ptr, int len)
+static int safe_read(int desc, char *ptr, size_t len)