[patch 1/3] copy_to_user check in fs/cifs/file.c

Jesper Juhl juhl-lkml at dif.dk
Tue Dec 28 23:48:01 GMT 2004


On Sun, 26 Dec 2004, Alan Cox wrote:

> On Sul, 2004-12-26 at 23:24, Jesper Juhl wrote:
> > Hi,
> > 
> > Patch below adds a check for the copy_to_user return value and makes a few 
> > whitespace cleanups in  fs/cifs/file.c::cifs_user_read()
> > I hope bundling two different things together in one patch is OK when the 
> > change is as small as this, but if you want it spplit in two patches, then 
> > just say so.
> 
> Corrupts the stats
> Fails to free smb_read_data where in some cases it was freed before
> 
> I'm not sure the stats matter but I think you need something more like
> 
Like this patch perhaps? :

It implements what you sugested except it breaks the loop when there's 
some residue from the copy_to_user call, since the logic after the while 
loop handles the   return total_read ? total_read : -EFAULT;  case if we 
set rc and break (I've cut the diff with a few lines of extra context to 
make this easy to verify).

Comments welcome as always.


Signed-off-by: Jesper Juhl <juhl-lkml at dif.dk>

diff --unified=8 -p linux-2.6.10-orig/fs/cifs/file.c linux-2.6.10/fs/cifs/file.c
--- linux-2.6.10-orig/fs/cifs/file.c	2004-12-24 22:33:48.000000000 +0100
+++ linux-2.6.10/fs/cifs/file.c	2004-12-28 23:27:17.000000000 +0100
@@ -1142,16 +1142,17 @@ cifs_user_read(struct file * file, char 
 	open_file = (struct cifsFileInfo *)file->private_data;
 
 	if((file->f_flags & O_ACCMODE) == O_WRONLY) {
 		cFYI(1,("attempting read on write only file instance"));
 	}
 
 	for (total_read = 0,current_offset=read_data; read_size > total_read;
 				total_read += bytes_read,current_offset+=bytes_read) {
+		unsigned residue;
 		current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
 		rc = -EAGAIN;
 		smb_read_data = NULL;
 		while(rc == -EAGAIN) {
 			if ((open_file->invalidHandle) && (!open_file->closePend)) {
 				rc = cifs_reopen_file(file->f_dentry->d_inode,
 					file,TRUE);
 				if(rc != 0)
@@ -1159,22 +1160,27 @@ cifs_user_read(struct file * file, char 
 			}
 
 			rc = CIFSSMBRead(xid, pTcon,
 				 open_file->netfid,
 				 current_read_size, *poffset,
 				 &bytes_read, &smb_read_data);
 
 			pSMBr = (struct smb_com_read_rsp *)smb_read_data;
-			copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/
+			residue = copy_to_user(current_offset, smb_read_data + 4 /* RFC1001 hdr */
 				+ le16_to_cpu(pSMBr->DataOffset), bytes_read);
 			if(smb_read_data) {
 				cifs_buf_release(smb_read_data);
 				smb_read_data = NULL;
 			}
+			if (residue) {
+				total_read += bytes_read - residue;
+				rc = -EFAULT;
+				break;
+			}
 		}
 		if (rc || (bytes_read == 0)) {
 			if (total_read) {
 				break;
 			} else {
 				FreeXid(xid);
 				return rc;
 			}





More information about the samba-technical mailing list