From 9a0b6a2273f2b9ff58466a6a7402390dfbf512d2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Dec 2002 08:02:21 +0000 Subject: Fixed nasty bug where file writes with start offsets in the range 0x80000000 -> 0xFFFFFFFF would fail as they were being cast from IVAL (uint32) to SMB_OFF_T (off_t or off64_t, both *signed* types). The sign extension would cause the offset to be treated as negative. Thanks to Herb for helping me track this one down (IRIX is good for large file tests :-). Jeremy. PS. That horrid EXEXIST thing has broken configure..... (This used to be commit fc7d3faed798e7496f2991ec7d795c3b1a3758f5) --- source3/include/includes.h | 2 ++ source3/smbd/blocking.c | 16 ++++++++-------- source3/smbd/nttrans.c | 4 ++-- source3/smbd/reply.c | 27 ++++++++++++++------------- 4 files changed, 26 insertions(+), 23 deletions(-) (limited to 'source3') diff --git a/source3/include/includes.h b/source3/include/includes.h index a7dd967bf3..9ea6e91bdf 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -589,9 +589,11 @@ typedef int socklen_t; #ifdef LARGE_SMB_OFF_T #define SOFF_T(p, ofs, v) (SIVAL(p,ofs,(v)&0xFFFFFFFF), SIVAL(p,(ofs)+4,(v)>>32)) #define SOFF_T_R(p, ofs, v) (SIVAL(p,(ofs)+4,(v)&0xFFFFFFFF), SIVAL(p,ofs,(v)>>32)) +#define IVAL_TO_SMB_OFF_T(buf,off) ((SMB_OFF_T)(( ((SMB_BIG_UINT)(IVAL((buf),(off)))) & ((SMB_BIG_UINT)0xFFFFFFFF) ))) #else #define SOFF_T(p, ofs, v) (SIVAL(p,ofs,v),SIVAL(p,(ofs)+4,0)) #define SOFF_T_R(p, ofs, v) (SIVAL(p,(ofs)+4,v),SIVAL(p,ofs,0)) +#define IVAL_TO_SMB_OFF_T(buf,off) ((SMB_OFF_T)(( ((uint32)(IVAL((buf),(off)))) & 0xFFFFFFFF ))) #endif /* diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 9d411711cb..14239272c2 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -267,20 +267,20 @@ static BOOL process_lockread(blocking_lock_record *blr) ssize_t nread = -1; char *data, *p; int outsize = 0; - SMB_OFF_T startpos; + SMB_BIG_UINT startpos; size_t numtoread; NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv2); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); data = smb_buf(outbuf) + 3; status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread, - (SMB_BIG_UINT)startpos, READ_LOCK); + startpos, READ_LOCK); if (NT_STATUS_V(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { @@ -337,17 +337,17 @@ static BOOL process_lock(blocking_lock_record *blr) char *outbuf = OutBuffer; char *inbuf = blr->inbuf; int outsize; - SMB_OFF_T count = 0, offset = 0; + SMB_BIG_UINT count = (SMB_BIG_UINT)0, offset = (SMB_BIG_UINT)0; NTSTATUS status; connection_struct *conn = conn_find(SVAL(inbuf,smb_tid)); files_struct *fsp = blr->fsp; - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); + count = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); + offset = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); errno = 0; - status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count, - (SMB_BIG_UINT)offset, WRITE_LOCK); + status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, + offset, WRITE_LOCK); if (NT_STATUS_IS_ERR(status)) { if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 1f3bbd488e..8aecd63de0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1304,9 +1304,9 @@ static int call_nt_transact_create(connection_struct *conn, restore_case_semantics(file_attributes); /* Save the requested allocation size. */ - allocation_size = IVAL(params,12); + allocation_size = IVAL_TO_SMB_OFF_T(params,12); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_OFF_T)IVAL(params,16)) << 32); + allocation_size |= ((IVAL_TO_SMB_OFF_T(params,16)) << 32); #endif if (allocation_size && (allocation_size > file_len)) { fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 2c29ffdf51..f320bf8ff5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1532,7 +1532,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s flush_write_cache(fsp, READRAW_FLUSH); - startpos = IVAL(inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); if(CVAL(inbuf,smb_wct) == 10) { /* * This is a large offset (64 bit) read. @@ -1627,7 +1627,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length release_level_2_oplocks_on_change(fsp); numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); outsize = set_message(outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); @@ -1696,7 +1696,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int CHECK_READ(fsp); numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); outsize = set_message(outbuf,5,3,True); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); @@ -1822,7 +1822,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); - SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); + SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); ssize_t nread = -1; size_t smb_maxcnt = SVAL(inbuf,smb_vwv5); #if 0 @@ -1900,7 +1900,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_WRITE(fsp); tcount = IVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); write_through = BITSETW(inbuf+smb_vwv7,0); /* We have to deal with slightly different formats depending @@ -2030,7 +2030,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, CHECK_WRITE(fsp); numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, @@ -2097,7 +2097,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d CHECK_WRITE(fsp); numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); data = smb_buf(inbuf) + 3; if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) { @@ -2158,7 +2158,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); - SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3); + SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); size_t numtowrite = SVAL(inbuf,smb_vwv10); BOOL write_through = BITSETW(inbuf+smb_vwv7,0); ssize_t nwritten = -1; @@ -2269,7 +2269,8 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int flush_write_cache(fsp, SEEK_FLUSH); mode = SVAL(inbuf,smb_vwv1) & 3; - startpos = IVALS(inbuf,smb_vwv2); + /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ + startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2); switch (mode) { case 0: umode = SEEK_SET; break; @@ -2478,7 +2479,7 @@ int reply_writeclose(connection_struct *conn, CHECK_WRITE(fsp); numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); mtime = make_unix_date3(inbuf+smb_vwv4); data = smb_buf(inbuf) + 1; @@ -4056,7 +4057,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, CHECK_FSP(fsp,conn); CHECK_READ(fsp); - startpos = IVAL(inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1); maxcount = SVAL(inbuf,smb_vwv3); data = smb_buf(outbuf); @@ -4184,7 +4185,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_ERROR(fsp); tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); write_through = BITSETW(inbuf+smb_vwv7,0); numtowrite = SVAL(inbuf,smb_vwv10); smb_doff = SVAL(inbuf,smb_vwv11); @@ -4284,7 +4285,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz CHECK_WRITE(fsp); tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); + startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); numtowrite = SVAL(inbuf,smb_vwv6); smb_doff = SVAL(inbuf,smb_vwv7); -- cgit