summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-03-19 11:23:49 +1100
committerAndrew Tridgell <tridge@samba.org>2009-03-19 11:23:49 +1100
commitd380c49791d1010d759369cab12d93b6fbd48dc7 (patch)
tree728fab54ab131015a90092fe9ac17149163bec35 /source4
parent13b6663e23a424473d14324ac229a21e1e90580a (diff)
downloadsamba-d380c49791d1010d759369cab12d93b6fbd48dc7.tar.gz
use the tevent nesting code to avoid the uid problem in the VFS
backend The vfs_unixuid module changes the uid of the process when executing operations on behalf of the user. Within the VFS backend we may rely on semi-async calls, such as winbind calls, which will call the event loop again. To cope with this we need to ensure that while inside those calls we revert the uid to root, then revert back to the connected user when we have finished with the semi-async calls.
Diffstat (limited to 'source4')
-rw-r--r--source4/ntvfs/unixuid/vfs_unixuid.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/source4/ntvfs/unixuid/vfs_unixuid.c b/source4/ntvfs/unixuid/vfs_unixuid.c
index db22a85492e..062fa41889f 100644
--- a/source4/ntvfs/unixuid/vfs_unixuid.c
+++ b/source4/ntvfs/unixuid/vfs_unixuid.c
@@ -26,6 +26,8 @@
#include "auth/auth.h"
#include "ntvfs/ntvfs.h"
#include "libcli/wbclient/wbclient.h"
+#define TEVENT_DEPRECATED
+#include <tevent.h>
struct unixuid_private {
struct wbc_context *wbc_ctx;
@@ -91,6 +93,64 @@ static NTSTATUS set_unix_security(struct unix_sec_ctx *sec)
return NT_STATUS_OK;
}
+static int unixuid_nesting_level;
+
+/*
+ called at the start and end of a tevent nesting loop. Needs to save/restore
+ unix security context
+ */
+static int unixuid_event_nesting_hook(struct tevent_context *ev,
+ void *private_data,
+ uint32_t level,
+ bool begin,
+ void *stack_ptr,
+ const char *location)
+{
+ struct unix_sec_ctx *sec_ctx;
+
+ if (unixuid_nesting_level == 0) {
+ /* we don't need to do anything unless we are nested
+ inside of a call in this module */
+ return 0;
+ }
+
+ if (begin) {
+ sec_ctx = save_unix_security(ev);
+ if (sec_ctx == NULL) {
+ DEBUG(0,("%s: Failed to save security context\n", location));
+ return -1;
+ }
+ *(struct unix_sec_ctx **)stack_ptr = sec_ctx;
+ if (seteuid(0) != 0 || setegid(0) != 0) {
+ DEBUG(0,("%s: Failed to change to root\n", location));
+ return -1;
+ }
+ } else {
+ /* called when we come out of a nesting level */
+ NTSTATUS status;
+
+ sec_ctx = *(struct unix_sec_ctx **)stack_ptr;
+ if (sec_ctx == NULL) {
+ /* this happens the first time this function
+ is called, as we install the hook while
+ inside an event in unixuid_connect() */
+ return 0;
+ }
+
+ sec_ctx = talloc_get_type_abort(sec_ctx, struct unix_sec_ctx);
+ status = set_unix_security(sec_ctx);
+ talloc_free(sec_ctx);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("%s: Failed to revert security context (%s)\n",
+ location, nt_errstr(status)));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
/*
form a unix_sec_ctx from the current security_token
*/
@@ -219,7 +279,9 @@ static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs,
struct unix_sec_ctx *sec; \
status = unixuid_setup_security(ntvfs, req, &sec); \
NT_STATUS_NOT_OK_RETURN(status); \
+ unixuid_nesting_level++; \
status = ntvfs_next_##op args; \
+ unixuid_nesting_level--; \
status2 = set_unix_security(sec); \
talloc_free(sec); \
if (!NT_STATUS_IS_OK(status2)) smb_panic("Unable to reset security context"); \
@@ -252,6 +314,10 @@ static NTSTATUS unixuid_connect(struct ntvfs_module_context *ntvfs,
priv->last_sec_ctx = NULL;
priv->last_token = NULL;
+ tevent_loop_set_nesting_hook(ntvfs->ctx->event_ctx,
+ unixuid_event_nesting_hook,
+ &unixuid_nesting_level);
+
/* we don't use PASS_THRU_REQ here, as the connect operation runs with
root privileges. This allows the backends to setup any database
links they might need during the connect. */