summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2012-04-04 14:54:02 -0700
committerJeremy Allison <jra@samba.org>2012-04-04 14:58:42 -0700
commitc10ed730d481e3d5b6710999b11b8e6969e1c16e (patch)
tree21c815c14da2fdd2bf7e7da2315cdc49ff94b9e4
parentf042de2f346c98a852957cdbb09a7f8ac871b69c (diff)
downloadsamba-c10ed730d481e3d5b6710999b11b8e6969e1c16e.tar.gz
samba-c10ed730d481e3d5b6710999b11b8e6969e1c16e.tar.bz2
samba-c10ed730d481e3d5b6710999b11b8e6969e1c16e.zip
Second part of bugfix for bug #8837 - smbd crashes when deleting directory and veto files are enabled.
Store the 'struct security_token' as well as the 'struct security_unix_token' inside the locking db when setting a delete on close.
-rw-r--r--source3/librpc/idl/open_files.idl1
-rw-r--r--source3/locking/locking.c51
-rw-r--r--source3/locking/proto.h10
-rw-r--r--source3/smbd/close.c23
-rw-r--r--source3/smbd/reply.c8
-rw-r--r--source3/smbd/trans2.c1
6 files changed, 74 insertions, 20 deletions
diff --git a/source3/librpc/idl/open_files.idl b/source3/librpc/idl/open_files.idl
index cefb75a2a3..98e1c32db0 100644
--- a/source3/librpc/idl/open_files.idl
+++ b/source3/librpc/idl/open_files.idl
@@ -27,6 +27,7 @@ interface open_files
typedef [public] struct {
uint32 name_hash;
+ security_token *delete_nt_token;
security_unix_token *delete_token;
} delete_token;
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 149a79d27a..cc92152727 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -867,6 +867,7 @@ static struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct
static bool add_delete_on_close_token(struct share_mode_data *d,
uint32_t name_hash,
+ const struct security_token *nt_tok,
const struct security_unix_token *tok)
{
struct delete_token *tmp, *dtl;
@@ -880,6 +881,10 @@ static bool add_delete_on_close_token(struct share_mode_data *d,
dtl = &d->delete_tokens[d->num_delete_tokens];
dtl->name_hash = name_hash;
+ dtl->delete_nt_token = dup_nt_token(d->delete_tokens, nt_tok);
+ if (dtl->delete_nt_token == NULL) {
+ return false;
+ }
dtl->delete_token = copy_unix_token(d->delete_tokens, tok);
if (dtl->delete_token == NULL) {
return false;
@@ -903,6 +908,7 @@ static bool add_delete_on_close_token(struct share_mode_data *d,
void set_delete_on_close_lck(files_struct *fsp,
struct share_mode_lock *lck,
bool delete_on_close,
+ const struct security_token *nt_tok,
const struct security_unix_token *tok)
{
struct share_mode_data *d = lck->data;
@@ -910,8 +916,10 @@ void set_delete_on_close_lck(files_struct *fsp,
bool ret;
if (delete_on_close) {
+ SMB_ASSERT(nt_tok != NULL);
SMB_ASSERT(tok != NULL);
} else {
+ SMB_ASSERT(nt_tok == NULL);
SMB_ASSERT(tok == NULL);
}
@@ -921,6 +929,7 @@ void set_delete_on_close_lck(files_struct *fsp,
d->modified = true;
if (delete_on_close == false) {
/* Delete this entry. */
+ TALLOC_FREE(dt->delete_nt_token);
TALLOC_FREE(dt->delete_token);
*dt = d->delete_tokens[
d->num_delete_tokens-1];
@@ -929,6 +938,9 @@ void set_delete_on_close_lck(files_struct *fsp,
}
/* Replace this token with the
given tok. */
+ TALLOC_FREE(dt->delete_nt_token);
+ dt->delete_nt_token = dup_nt_token(dt, nt_tok);
+ SMB_ASSERT(dt->delete_nt_token != NULL);
TALLOC_FREE(dt->delete_token);
dt->delete_token = copy_unix_token(dt, tok);
SMB_ASSERT(dt->delete_token != NULL);
@@ -940,11 +952,13 @@ void set_delete_on_close_lck(files_struct *fsp,
return;
}
- ret = add_delete_on_close_token(lck->data, fsp->name_hash, tok);
+ ret = add_delete_on_close_token(lck->data, fsp->name_hash, nt_tok, tok);
SMB_ASSERT(ret);
}
-bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const struct security_unix_token *tok)
+bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
+ const struct security_token *nt_tok,
+ const struct security_unix_token *tok)
{
struct share_mode_lock *lck;
@@ -958,8 +972,15 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const struct s
return False;
}
- set_delete_on_close_lck(fsp, lck, delete_on_close,
- delete_on_close ? tok : NULL);
+ if (delete_on_close) {
+ set_delete_on_close_lck(fsp, lck, true,
+ nt_tok,
+ tok);
+ } else {
+ set_delete_on_close_lck(fsp, lck, false,
+ NULL,
+ NULL);
+ }
if (fsp->is_directory) {
SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));
@@ -974,7 +995,15 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const struct s
return True;
}
-const struct security_unix_token *get_delete_on_close_token(struct share_mode_lock *lck, uint32_t name_hash)
+/****************************************************************************
+ Return the NT token and UNIX token if there's a match. Return true if
+ found, false if not.
+****************************************************************************/
+
+bool get_delete_on_close_token(struct share_mode_lock *lck,
+ uint32_t name_hash,
+ const struct security_token **pp_nt_tok,
+ const struct security_unix_token **pp_tok)
{
int i;
@@ -986,15 +1015,21 @@ const struct security_unix_token *get_delete_on_close_token(struct share_mode_lo
DEBUG(10,("get_delete_on_close_token: dtl->name_hash = 0x%x\n",
(unsigned int)dt->name_hash ));
if (dt->name_hash == name_hash) {
- return dt->delete_token;
+ if (pp_nt_tok) {
+ *pp_nt_tok = dt->delete_nt_token;
+ }
+ if (pp_tok) {
+ *pp_tok = dt->delete_token;
+ }
+ return true;
}
}
- return NULL;
+ return false;
}
bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash)
{
- return (get_delete_on_close_token(lck, name_hash) != NULL);
+ return get_delete_on_close_token(lck, name_hash, NULL, NULL);
}
bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 3a6df37e93..54badd9149 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -178,12 +178,18 @@ void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
struct server_id pid);
bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp);
bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp);
-const struct security_unix_token *get_delete_on_close_token(struct share_mode_lock *lck, uint32_t name_hash);
+bool get_delete_on_close_token(struct share_mode_lock *lck,
+ uint32_t name_hash,
+ const struct security_token **pp_nt_tok,
+ const struct security_unix_token **pp_tok);
void set_delete_on_close_lck(files_struct *fsp,
struct share_mode_lock *lck,
bool delete_on_close,
+ const struct security_token *nt_tok,
+ const struct security_unix_token *tok);
+bool set_delete_on_close(files_struct *fsp, bool delete_on_close,
+ const struct security_token *nt_tok,
const struct security_unix_token *tok);
-bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const struct security_unix_token *tok);
bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash);
bool set_sticky_write_time(struct file_id fileid, struct timespec write_time);
bool set_write_time(struct file_id fileid, struct timespec write_time);
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 34ce7858be..8b91da81d5 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -332,6 +332,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
NTSTATUS tmp_status;
struct file_id id;
const struct security_unix_token *del_token = NULL;
+ const struct security_token *del_nt_token = NULL;
+ bool got_tokens = false;
/* Ensure any pending write time updates are done. */
if (fsp->update_write_time_event) {
@@ -395,7 +397,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
became_user = True;
}
fsp->delete_on_close = true;
- set_delete_on_close_lck(fsp, lck, True, get_current_utok(conn));
+ set_delete_on_close_lck(fsp, lck, True,
+ get_current_nttok(conn),
+ get_current_utok(conn));
if (became_user) {
unbecome_user();
}
@@ -448,8 +452,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
*/
fsp->update_write_time_on_close = false;
- del_token = get_delete_on_close_token(lck, fsp->name_hash);
- SMB_ASSERT(del_token != NULL);
+ got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
+ &del_nt_token, &del_token);
+ SMB_ASSERT(got_tokens);
if (!unix_token_equal(del_token, get_current_utok(conn))) {
/* Become the user who requested the delete. */
@@ -468,7 +473,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
del_token->gid,
del_token->ngroups,
del_token->groups,
- NULL);
+ del_nt_token);
changed_user = true;
}
@@ -541,7 +546,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
*/
fsp->delete_on_close = false;
- set_delete_on_close_lck(fsp, lck, false, NULL);
+ set_delete_on_close_lck(fsp, lck, false, NULL, NULL);
done:
@@ -1010,6 +1015,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
bool delete_dir = False;
NTSTATUS status = NT_STATUS_OK;
NTSTATUS status1 = NT_STATUS_OK;
+ const struct security_token *del_nt_token = NULL;
const struct security_unix_token *del_token = NULL;
/*
@@ -1044,6 +1050,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx,
fsp->fsp_name->base_name);
set_delete_on_close_lck(fsp, lck, true,
+ get_current_nttok(fsp->conn),
get_current_utok(fsp->conn));
fsp->delete_on_close = true;
if (became_user) {
@@ -1051,8 +1058,8 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
}
}
- del_token = get_delete_on_close_token(lck, fsp->name_hash);
- delete_dir = (del_token != NULL);
+ delete_dir = get_delete_on_close_token(lck, fsp->name_hash,
+ &del_nt_token, &del_token);
if (delete_dir) {
int i;
@@ -1084,7 +1091,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
del_token->gid,
del_token->ngroups,
del_token->groups,
- NULL);
+ del_nt_token);
TALLOC_FREE(lck);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 6e4bcab774..884731088a 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2546,7 +2546,9 @@ static NTSTATUS do_unlink(connection_struct *conn,
}
/* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
+ if (!set_delete_on_close(fsp, True,
+ conn->session_info->security_token,
+ conn->session_info->unix_token)) {
close_file(req, fsp, NORMAL_CLOSE);
return NT_STATUS_ACCESS_DENIED;
}
@@ -5664,7 +5666,9 @@ void reply_rmdir(struct smb_request *req)
goto out;
}
- if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
+ if (!set_delete_on_close(fsp, true,
+ conn->session_info->security_token,
+ conn->session_info->unix_token)) {
close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
goto out;
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 24642cd818..da552f5a51 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5885,6 +5885,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
/* The set is across all open files on this dev/inode pair. */
if (!set_delete_on_close(fsp, delete_on_close,
+ conn->session_info->security_token,
conn->session_info->unix_token)) {
return NT_STATUS_ACCESS_DENIED;
}