From fb27bc139f8d321e50471c595b65b277ee114801 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Oct 1997 18:46:19 +0000 Subject: locking.c: Added fix for race condition in slow share mode code. lsaparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. pipes.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. server.c: Fixed last known oplock race condition. smb.h: Re-removed USE_OPLOCK defines - someone checked in an old version. smbparse.c: #ifdef'ed out code so this will compile - LUKE PLEASE CHECK THIS. Jeremy (jallison@whistle.com) (This used to be commit 1e1366ddc5542283a37debdf830ca139bbade1b0) --- source3/include/smb.h | 15 ---------- source3/locking/locking.c | 71 +++++++++++++++++++++++++++++++++++++---------- source3/lsaparse.c | 2 ++ source3/smbd/pipes.c | 4 +++ source3/smbd/server.c | 29 +++++++++++++++++++ source3/smbparse.c | 2 ++ 6 files changed, 93 insertions(+), 30 deletions(-) diff --git a/source3/include/smb.h b/source3/include/smb.h index 3adb3e5a4c..c347202743 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1042,10 +1042,8 @@ typedef struct { smb_shm_offset_t next_share_mode_entry; int pid; -#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; -#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } share_mode_entry; @@ -1054,10 +1052,8 @@ typedef struct typedef struct { int pid; -#ifdef USE_OPLOCKS uint16 op_port; uint16 op_type; -#endif /* USE_OPLOCKS */ int share_mode; struct timeval time; } min_share_mode_entry; @@ -1083,11 +1079,7 @@ struct connect_record }; #ifndef LOCKING_VERSION -#ifdef USE_OPLOCKS #define LOCKING_VERSION 4 -#else /* USE_OPLOCKS */ -#define LOCKING_VERSION 3 -#endif /* USE_OPLOCKS */ #endif /* LOCKING_VERSION */ #if !defined(FAST_SHARE_MODES) @@ -1103,11 +1095,7 @@ struct connect_record #define SMF_FILENAME_LEN_OFFSET 8 #define SMF_HEADER_LENGTH 10 -#ifdef USE_OPLOCKS #define SMF_ENTRY_LENGTH 20 -#else /* USE_OPLOCKS */ -#define SMF_ENTRY_LENGTH 16 -#endif /* USE_OPLOCKS */ /* * Share mode record offsets. @@ -1117,11 +1105,8 @@ struct connect_record #define SME_USEC_OFFSET 4 #define SME_SHAREMODE_OFFSET 8 #define SME_PID_OFFSET 12 - -#ifdef USE_OPLOCKS #define SME_PORT_OFFSET 16 #define SME_OPLOCK_TYPE_OFFSET 18 -#endif /* USE_OPLOCKS */ #endif /* FAST_SHARE_MODES */ diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 6e321d0626..639bc7be0b 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -25,6 +25,10 @@ May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode locking to deal with multiple share modes per open file. + + September 1997. Jeremy Allison (jallison@whistle.com). Added oplock + support. + */ #include "includes.h" @@ -726,13 +730,60 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok { int old_umask; + BOOL gotlock = False; unbecome_user(); old_umask = umask(0); + + /* + * There was a race condition in the original slow share mode code. + * A smbd could open a share mode file, and before getting + * the lock, another smbd could delete the last entry for + * the share mode file and delete the file entry from the + * directory. Thus this smbd would be left with a locked + * share mode fd attached to a file that no longer had a + * directory entry. Thus another smbd would think that + * there were no outstanding opens on the file. To fix + * this we now check we can do a stat() call on the filename + * before allowing the lock to proceed, and back out completely + * and try the open again if we cannot. + * Jeremy Allison (jallison@whistle.com). + */ + + do + { + struct stat dummy_stat; + #ifdef SECURE_SHARE_MODES - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); #else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); + fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666); #endif /* SECURE_SHARE_MODES */ + + /* At this point we have an open fd to the share mode file. + Lock the first byte exclusively to signify a lock. */ + if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) + { + DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n", + fname, strerror(errno))); + close(fd); + return False; + } + + /* + * If we cannot stat the filename, the file was deleted between + * the open and the lock call. Back out and try again. + */ + + if(stat(fname, &dummy_stat)!=0) + { + DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", + fname, strerror(errno))); + close(fd); + } + else + gotlock = True; + } while(!gotlock); + umask(old_umask); if(!become_user(cnum,Connections[cnum].vuid)) { @@ -750,18 +801,8 @@ BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok } } - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - close(fd); - return False; - } - - *ptok = (share_lock_token)fd; - return True; + *ptok = (share_lock_token)fd; + return True; } /******************************************************************* @@ -781,7 +822,7 @@ BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token tok ret = False; } - close((int)token); + close(fd); return ret; } diff --git a/source3/lsaparse.c b/source3/lsaparse.c index 2113b19cd3..b1d9d73924 100644 --- a/source3/lsaparse.c +++ b/source3/lsaparse.c @@ -24,6 +24,7 @@ extern int DEBUGLEVEL; +#if 0 /* NEED TO DO THIS TO GET A COMPILE - LUKE PLEASE CHECK THIS !!! */ /******************************************************************* reads or writes an LSA_R_OPEN_POL structure. ********************************************************************/ @@ -446,6 +447,7 @@ char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, i return q; } +#endif /* 0 LUKE PLEASE CHECK !! */ #if 0 /******************************************************************* reads or writes a structure. diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 95b69ef4d9..ffa64a4e80 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -364,6 +364,8 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, return(True); } +#if 0 /* HAVING TO DO THIS TO GET THINGS TO COMPILE - LUKE PLEASE CHECK THIS !!! */ + /* PAXX: Someone fix above. The above API is indexing RPC calls based on RPC flags and @@ -757,3 +759,5 @@ static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, /* return length of SMB data stored */ return q - start; } + +#endif /* LUKE PLEASE CHECK THIS !! */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4f5b01ba91..92c219c71b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -2455,6 +2455,9 @@ address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); } oplock_port = ntohs(sock_name.sin_port); + DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", + getpid(), oplock_port)); + return True; } @@ -2545,6 +2548,31 @@ pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, } break; + /* + * Keep this as a debug case - eventually we can remove it. + */ + case 0x8001: + DEBUG(0,("process_local_message: Received unsolicited break \ +reply - dumping info.\n")); + + if(msg_len != OPLOCK_BREAK_MSG_LEN) + { + DEBUG(0,("process_local_message: ubr: incorrect length for reply \ +(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); + return False; + } + + { + uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); + uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); + uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); + + DEBUG(0,("process_local_message: unsolicited oplock break reply from \ +pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); + + } + return False; + default: DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", (unsigned int)SVAL(msg_start,0))); @@ -2860,6 +2888,7 @@ oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", share_entry->pid, share_entry->op_port, dev, inode)); if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) return False; + continue; } break; diff --git a/source3/smbparse.c b/source3/smbparse.c index 7ea140f7cb..ae1f4f4b25 100644 --- a/source3/smbparse.c +++ b/source3/smbparse.c @@ -456,7 +456,9 @@ char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) if (d_q->buffer_dom_name != 0) { +#if 0 /* REMOVED AS WON'T COMPILE AS IS - LUKE PLEASE CHECK !!!!! */ q = smb_io_unistr(io, &(d_q->uni_domain_name), q, base, align); /* domain name (unicode string) */ +#endif } if (d_q->buffer_dom_sid != 0) { -- cgit