From 6259f51dd9918eccc9697f3763d918f7c9b82b50 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 22 Apr 2000 00:33:16 +0000 Subject: This is a *big* checkin that may break some things, but implements the new open mechanism Andrew & I discussed. config.sub: configure: Included the QNX patch. include/vfs.h: smbd/vfs-wrap.c: smbd/vfs.c: Added ftruncate vfs call (needed). Note that we will also need locking calls in the vfs (to be added). lib/util_unistr.c: nmbd/nmbd_processlogon.c: Fix for NT domain logons causing nmbd to core dump. Also fix for sidsize DOS bug. locking/locking.c: Check value of ret before using it for memdup. printing/printing.c: Convert print_fsp_open to return an allocated fsp. rpc_server/srv_lsa.c: Fix for NT domain logons. I have removed all use of lp_share_modes() from the code (although I left the parameter in the table for backwards compatibility). It no longer makes sense for this to exist. smbd/close.c: Removed lp_share_modes(). smbd/fileio.c: Fixed parameters to unlock_share_entry call in panic code. smbd/files.c: Correctly set the unix_ERR_code to ERRnofids on fsp allocation fail. smbd/nttrans.c: smbd/reply.c: smbd/trans2.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. smbd/open.c: Changed all occurrences of open_file_shared/open_directory/ open_file_stat to return an fsp from the call. In addition I have fixed a long standing race condition in the deny mode processing w.r.t. two smbd's creating a file. Andrew, please note that your original idea of using open with O_EXCL in this case would not work (I went over the races very carefully) and so we must re-check deny modes *after* the open() call returns. This is because there is a race between the open with O_EXCL and the lock of the share mode entry. Imagine the case where the first smbd does the open with O_EXCL and a deny mode of DENY_ALL, but is pre-empted before it locks the share modes and creates the deny mode entry for DENY_ALL. A second smbd could then come in with O_RDONLY and a deny mode of DENY_NONE and the two opens would be allowed. The *only* way to fix this race is to lock the share modes after the open and then do the deny mode checks *after* this lock in the case where the file did not originally exist. This code will need extensive testing but seems to initially work. Jeremy. (This used to be commit ab0ecc39d688f16b9692fe90b991f0b89287070a) --- source3/smbd/nttrans.c | 56 +++++++++++++++----------------------------------- 1 file changed, 16 insertions(+), 40 deletions(-) (limited to 'source3/smbd/nttrans.c') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index bd77f17802..c82a8074d9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -747,12 +747,6 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,NULL); - fsp = file_new(); - if (!fsp) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); - } - unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* @@ -762,13 +756,11 @@ int reply_ntcreate_and_X(connection_struct *conn, if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, - unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); restore_case_semantics(file_attributes); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { return(UNIXERROR(ERRDOS,ERRnoaccess)); } } else { @@ -789,10 +781,10 @@ int reply_ntcreate_and_X(connection_struct *conn, * before issuing an oplock break request to * our client. JRA. */ - open_file_shared(fsp,conn,fname,smb_open_mode, + fsp = open_file_shared(conn,fname,smb_open_mode, smb_ofun,unixmode, oplock_request,&rmode,&smb_action); - if (!fsp->open) { + if (!fsp) { /* We cheat here. There are two cases we * care about. One is a directory rename, * where the NT client will attempt to @@ -819,17 +811,15 @@ int reply_ntcreate_and_X(connection_struct *conn, */ if (create_options & FILE_NON_DIRECTORY_FILE) { - file_free(fsp); restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); } oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -845,10 +835,9 @@ int reply_ntcreate_and_X(connection_struct *conn, oplock_request = 0; - open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -860,8 +849,6 @@ int reply_ntcreate_and_X(connection_struct *conn, unix_ERR_code = ERRbadpath; } - file_free(fsp); - restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -1109,12 +1096,6 @@ static int call_nt_transact_create(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,NULL); - fsp = file_new(); - if (!fsp) { - restore_case_semantics(file_attributes); - return(ERROR(ERRSRV,ERRnofids)); - } - unixmode = unix_mode(conn,smb_attr | aARCH, fname); /* @@ -1131,10 +1112,9 @@ static int call_nt_transact_create(connection_struct *conn, * CreateDirectory() call. */ - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1152,10 +1132,10 @@ static int call_nt_transact_create(connection_struct *conn, * Ordinary file case. */ - open_file_shared(fsp,conn,fname,smb_open_mode,smb_ofun,unixmode, + fsp = open_file_shared(conn,fname,smb_open_mode,smb_ofun,unixmode, oplock_request,&rmode,&smb_action); - if (!fsp->open) { + if (!fsp) { if(errno == EISDIR) { @@ -1164,17 +1144,15 @@ static int call_nt_transact_create(connection_struct *conn, */ if (create_options & FILE_NON_DIRECTORY_FILE) { - file_free(fsp); restore_case_semantics(file_attributes); SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); return(ERROR(0, 0xc0000000|NT_STATUS_FILE_IS_A_DIRECTORY)); } oplock_request = 0; - open_directory(fsp, conn, fname, smb_ofun, unixmode, &smb_action); + fsp = open_directory(conn, fname, smb_ofun, unixmode, &smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1191,10 +1169,9 @@ static int call_nt_transact_create(connection_struct *conn, oplock_request = 0; - open_file_stat(fsp,conn,fname,smb_open_mode,&sbuf,&smb_action); + fsp = open_file_stat(conn,fname,smb_open_mode,&sbuf,&smb_action); - if(!fsp->open) { - file_free(fsp); + if(!fsp) { restore_case_semantics(file_attributes); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -1204,7 +1181,6 @@ static int call_nt_transact_create(connection_struct *conn, unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - file_free(fsp); restore_case_semantics(file_attributes); -- cgit