Index: SAMBA_3_0/source/smbd/close.c =================================================================== --- SAMBA_3_0/source/smbd/close.c (revision 12863) +++ SAMBA_3_0/source/smbd/close.c (working copy) @@ -241,31 +241,39 @@ static int close_normal_file(files_struc DEBUG(5,("close_file: file %s. Delete on close was set " "and stat failed with error %s\n", fsp->fsp_name, strerror(errno) )); - } else { - if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { - DEBUG(5,("close_file: file %s. Delete on close was set and " - "dev and/or inode does not match\n", - fsp->fsp_name )); - DEBUG(5,("close_file: file %s. stored dev = %x, inode = %.0f " - "stat dev = %x, inode = %.0f\n", - fsp->fsp_name, - (unsigned int)fsp->dev, (double)fsp->inode, - (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); - - } else if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { - /* - * This call can potentially fail as another smbd may have - * had the file open with delete on close set and deleted - * it when its last reference to this file went away. Hence - * we log this but not at debug level zero. - */ + } else if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) { + DEBUG(5,("close_file: file %s. Delete on close was set and " + "dev and/or inode does not match\n", + fsp->fsp_name )); + DEBUG(5,("close_file: file %s. stored dev = %x, inode = %.0f " + "stat dev = %x, inode = %.0f\n", + fsp->fsp_name, + (unsigned int)fsp->dev, (double)fsp->inode, + (unsigned int)sbuf.st_dev, (double)sbuf.st_ino )); + } else if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { + int ret = -1; + /* + * This call can potentially fail as another smbd may have + * had the file open with delete on close set and deleted + * it when its last reference to this file went away. + * But if a user who set DELETE_ON_CLOSE has authority of + * delete, we must delete on close. We checked directory + * permissions to delete when open with DELETE_ACCESS. + * This ensures we are not violating security. + */ + if ((errno == EPERM) || (errno == EACCES)) { + become_root(); + ret = SMB_VFS_UNLINK(conn, fsp->fsp_name); + unbecome_root(); + } - DEBUG(5,("close_file: file %s. Delete on close was set " + if (ret != 0) { + DEBUG(0,("close_file: file %s. Delete on close was set " "and unlink failed with error %s\n", fsp->fsp_name, strerror(errno) )); } - process_pending_change_notify_queue((time_t)0); } + process_pending_change_notify_queue((time_t)0); } talloc_free(lck);