From b695ef8ad8c3d78ed56f563d7081205a690558ef Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Wed, 15 Jun 2016 23:12:08 -0700 Subject: [PATCH] dll: fuse: only use the environment's malloc prior to fsp_fuse_loop - this allows an environment like Cygwin to safely call fork prior to fuse_loop/fuse_loop_mt --- inc/fuse/winfsp_fuse.h | 8 --- inc/winfsp/winfsp.h | 13 ++++- src/dll/fuse/fuse.c | 119 +++++++++++++++++---------------------- src/dll/fuse/fuse_intf.c | 25 ++++---- src/dll/fuse/library.h | 14 ++--- src/dll/library.h | 2 + src/dll/service.c | 11 ++-- 7 files changed, 92 insertions(+), 100 deletions(-) diff --git a/inc/fuse/winfsp_fuse.h b/inc/fuse/winfsp_fuse.h index f1073165..e94af8f2 100644 --- a/inc/fuse/winfsp_fuse.h +++ b/inc/fuse/winfsp_fuse.h @@ -229,7 +229,6 @@ struct fsp_fuse_env }; FSP_FUSE_API void fsp_fuse_signal_handler(int sig); -FSP_FUSE_API void fsp_fuse_set_signal_arg(void *se); #if defined(_WIN64) || defined(_WIN32) @@ -304,13 +303,8 @@ static inline int fsp_fuse_set_signal_handlers(void *se) if (0 != pthread_sigmask(SIG_BLOCK, &sigmask, 0)) return -1; - fsp_fuse_set_signal_arg(se); - if (0 != pthread_create(&sigthr, 0, fsp_fuse_signal_thread, &sigmask)) - { - fsp_fuse_set_signal_arg(0); return -1; - } } } else @@ -321,8 +315,6 @@ static inline int fsp_fuse_set_signal_handlers(void *se) pthread_join(sigthr, 0); sigthr = 0; - fsp_fuse_set_signal_arg(0); - if (0 != pthread_sigmask(SIG_UNBLOCK, &sigmask, 0)) return -1; sigemptyset(&sigmask); diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 94ed0630..148f8e05 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -931,10 +931,19 @@ typedef struct _FSP_SERVICE * @return * Service process exit code. */ -FSP_API ULONG FspServiceRun(PWSTR ServiceName, +FSP_API ULONG FspServiceRunEx(PWSTR ServiceName, FSP_SERVICE_START *OnStart, FSP_SERVICE_STOP *OnStop, - FSP_SERVICE_CONTROL *OnControl); + FSP_SERVICE_CONTROL *OnControl, + PVOID UserContext); +static inline +ULONG FspServiceRun(PWSTR ServiceName, + FSP_SERVICE_START *OnStart, + FSP_SERVICE_STOP *OnStop, + FSP_SERVICE_CONTROL *OnControl) +{ + return FspServiceRunEx(ServiceName, OnStart, OnStop, OnControl, 0); +} /** * Create a service object. * diff --git a/src/dll/fuse/fuse.c b/src/dll/fuse/fuse.c index e7c34889..34021c92 100644 --- a/src/dll/fuse/fuse.c +++ b/src/dll/fuse/fuse.c @@ -103,6 +103,32 @@ static struct fuse_opt fsp_fuse_core_opts[] = static DWORD fsp_fuse_tlskey = TLS_OUT_OF_INDEXES; static INIT_ONCE fsp_fuse_initonce_v = INIT_ONCE_STATIC_INIT; +struct fsp_fuse_obj_hdr +{ + void (*dtor)(void *); + __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ObjectBuf[]; +}; + +static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size) +{ + struct fsp_fuse_obj_hdr *hdr; + + hdr = env->memalloc(sizeof(struct fsp_fuse_obj_hdr) + size); + if (0 == hdr) + return 0; + + hdr->dtor = env->memfree; + memset(hdr->ObjectBuf, 0, size); + return hdr->ObjectBuf; +} + +static inline void fsp_fuse_obj_free(void *obj) +{ + struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr)); + + hdr->dtor(hdr); +} + VOID fsp_fuse_initialize(BOOLEAN Dynamic) { } @@ -139,10 +165,7 @@ VOID fsp_fuse_finalize_thread(VOID) context = TlsGetValue(fsp_fuse_tlskey); if (0 != context) { - struct fsp_fuse_context_header *contexthdr = - (PVOID)((PUINT8)context - sizeof *contexthdr); - - MemFree(contexthdr); + fsp_fuse_obj_free(FSP_FUSE_HDR_FROM_CONTEXT(context)); TlsSetValue(fsp_fuse_tlskey, 0); } } @@ -178,7 +201,7 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env, if (0 == Size) goto fail; - ch = MemAlloc(sizeof *ch + Size * sizeof(WCHAR)); + ch = fsp_fuse_obj_alloc(env, sizeof *ch + Size * sizeof(WCHAR)); if (0 == ch) goto fail; @@ -190,7 +213,7 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env, return ch; fail: - MemFree(ch); + fsp_fuse_obj_free(ch); return 0; } @@ -198,7 +221,7 @@ fail: FSP_FUSE_API void fsp_fuse_unmount(struct fsp_fuse_env *env, const char *mountpoint, struct fuse_chan *ch) { - MemFree(ch); + fsp_fuse_obj_free(ch); } FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env, @@ -246,7 +269,9 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) struct fuse_conn_info conn; NTSTATUS Result; - context = fsp_fuse_get_context(0); + f->Service = Service; + + context = fsp_fuse_get_context(f->env); if (0 == context) { Result = STATUS_INSUFFICIENT_RESOURCES; @@ -410,6 +435,8 @@ static void fsp_fuse_cleanup(struct fuse *f) f->ops.destroy(f->data); f->fsinit = FALSE; } + + f->Service = 0; } static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key, @@ -484,10 +511,9 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, opt_data.VolumeParams.NamedStreams = !!opt_data.NamedStreams; opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume; - f = MemAlloc(sizeof *f); + f = fsp_fuse_obj_alloc(env, sizeof *f); if (0 == f) goto fail; - memset(f, 0, sizeof *f); f->env = env; memcpy(&f->ops, ops, opsize); @@ -496,17 +522,11 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, memcpy(&f->VolumeParams, &opt_data.VolumeParams, sizeof opt_data.VolumeParams); Size = (lstrlenW(ch->MountPoint) + 1) * sizeof(WCHAR); - f->MountPoint = MemAlloc(Size); + f->MountPoint = fsp_fuse_obj_alloc(env, Size); if (0 == f->MountPoint) goto fail; memcpy(f->MountPoint, ch->MountPoint, Size); - Result = FspServiceCreate(FspDiagIdent(), fsp_fuse_svcstart, fsp_fuse_svcstop, 0, &f->Service); - if (!NT_SUCCESS(Result)) - goto fail; - FspServiceAllowConsoleMode(f->Service); - f->Service->UserContext = f; - Result = fsp_fuse_preflight(f); if (!NT_SUCCESS(Result)) { @@ -554,62 +574,35 @@ FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env, { fsp_fuse_cleanup(f); - if (0 != f->Service) - FspServiceDelete(f->Service); + fsp_fuse_obj_free(f->MountPoint); - MemFree(f->MountPoint); - - MemFree(f); -} - -static int fsp_fuse_loop_internal(struct fsp_fuse_env *env, - struct fuse *f, FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY GuardStrategy) -{ - NTSTATUS Result; - ULONG ExitCode; - - f->OpGuardStrategy = GuardStrategy; - - Result = FspServiceLoop(f->Service); - ExitCode = FspServiceGetExitCode(f->Service); - - if (!NT_SUCCESS(Result)) - goto fail; - - if (0 != ExitCode) - FspServiceLog(EVENTLOG_WARNING_TYPE, - L"The service %s has exited (ExitCode=%ld).", f->Service->ServiceName, ExitCode); - - return 0; - -fail: - FspServiceLog(EVENTLOG_ERROR_TYPE, - L"The service %s has failed to run (Status=%lx).", f->Service->ServiceName, Result); - - return -1; + fsp_fuse_obj_free(f); } FSP_FUSE_API int fsp_fuse_loop(struct fsp_fuse_env *env, struct fuse *f) { - return fsp_fuse_loop_internal(env, f, - FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE); + f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE; + return 0 == FspServiceRunEx(FspDiagIdent(), fsp_fuse_svcstart, fsp_fuse_svcstop, 0, f) ? + 0 : -1; } FSP_FUSE_API int fsp_fuse_loop_mt(struct fsp_fuse_env *env, struct fuse *f) { - return fsp_fuse_loop_internal(env, f, - FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE); + f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE; + return 0 == FspServiceRunEx(FspDiagIdent(), fsp_fuse_svcstart, fsp_fuse_svcstop, 0, f) ? + 0 : -1; } FSP_FUSE_API void fsp_fuse_exit(struct fsp_fuse_env *env, struct fuse *f) { - FspServiceStop(f->Service); + if (0 != f->Service) + FspServiceStop(f->Service); } -FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *reserved) +FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env) { struct fuse_context *context; @@ -622,12 +615,12 @@ FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *rese { struct fsp_fuse_context_header *contexthdr; - contexthdr = MemAlloc(sizeof *contexthdr + sizeof *context); + contexthdr = fsp_fuse_obj_alloc(env, + sizeof(struct fsp_fuse_context_header) + sizeof(struct fuse_context)); if (0 == contexthdr) return 0; - memset(contexthdr, 0, sizeof *contexthdr + sizeof *context); - context = (PVOID)contexthdr->ContextBuf; + context = FSP_FUSE_CONTEXT_FROM_HDR(contexthdr); context->pid = -1; TlsSetValue(fsp_fuse_tlskey, context); @@ -664,15 +657,7 @@ FSP_FUSE_API int32_t fsp_fuse_ntstatus_from_errno(struct fsp_fuse_env *env, /* Cygwin signal support */ -static FSP_SERVICE *fsp_fuse_signal_svc; - FSP_FUSE_API void fsp_fuse_signal_handler(int sig) { - if (0 != fsp_fuse_signal_svc) - FspServiceStop(fsp_fuse_signal_svc); -} - -FSP_FUSE_API void fsp_fuse_set_signal_arg(void *se) -{ - fsp_fuse_signal_svc = 0 != se ? ((struct fuse *)se)->Service : 0; + FspServiceConsoleCtrlHandler(CTRL_BREAK_EVENT); } diff --git a/src/dll/fuse/fuse_intf.c b/src/dll/fuse/fuse_intf.c index b94623de..95a0e315 100644 --- a/src/dll/fuse/fuse_intf.c +++ b/src/dll/fuse/fuse_intf.c @@ -20,6 +20,7 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) { + struct fuse *f = FileSystem->UserContext; struct fuse_context *context; struct fsp_fuse_context_header *contexthdr; char *PosixPath = 0; @@ -123,7 +124,7 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem, goto exit; } - context = fsp_fuse_get_context(0); + context = fsp_fuse_get_context(f->env); if (0 == context) { Result = STATUS_INSUFFICIENT_RESOURCES; @@ -134,12 +135,12 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) goto exit; - context->fuse = FileSystem->UserContext; - context->private_data = context->fuse->data; + context->fuse = f; + context->private_data = f->data; context->uid = Uid; context->gid = Gid; - contexthdr = (PVOID)((PUINT8)context - sizeof *contexthdr); + contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context); contexthdr->Request = Request; contexthdr->Response = Response; contexthdr->PosixPath = PosixPath; @@ -162,18 +163,19 @@ exit: NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response) { + struct fuse *f = FileSystem->UserContext; struct fuse_context *context; struct fsp_fuse_context_header *contexthdr; FspFileSystemOpLeave(FileSystem, Request, Response); - context = fsp_fuse_get_context(0); + context = fsp_fuse_get_context(f->env); context->fuse = 0; context->private_data = 0; context->uid = -1; context->gid = -1; - contexthdr = (PVOID)((PUINT8)context - sizeof *contexthdr); + contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context); if (0 != contexthdr->PosixPath) FspPosixDeletePath(contexthdr->PosixPath); memset(contexthdr, 0, sizeof *contexthdr); @@ -349,9 +351,8 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem, PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo) { struct fuse *f = FileSystem->UserContext; - struct fuse_context *context = fsp_fuse_get_context(0); - struct fsp_fuse_context_header *contexthdr = - (PVOID)((PUINT8)context - sizeof *contexthdr); + struct fuse_context *context = fsp_fuse_get_context(f->env); + struct fsp_fuse_context_header *contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context); UINT32 Uid, Gid, Mode; FSP_FSCTL_FILE_INFO FileInfoBuf; struct fsp_fuse_file_desc *filedesc = 0; @@ -505,7 +506,8 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem, PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo) { struct fuse *f = FileSystem->UserContext; - struct fsp_fuse_context_header *contexthdr = fsp_fuse_context_header(); + struct fuse_context *context = fsp_fuse_get_context(f->env); + struct fsp_fuse_context_header *contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context); UINT32 Uid, Gid, Mode; FSP_FSCTL_FILE_INFO FileInfoBuf; struct fsp_fuse_file_desc *filedesc = 0; @@ -1074,7 +1076,8 @@ static NTSTATUS fsp_fuse_intf_Rename(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists) { struct fuse *f = FileSystem->UserContext; - struct fsp_fuse_context_header *contexthdr = fsp_fuse_context_header(); + struct fuse_context *context = fsp_fuse_get_context(f->env); + struct fsp_fuse_context_header *contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context); UINT32 Uid, Gid, Mode; FSP_FSCTL_FILE_INFO FileInfoBuf; struct fsp_fuse_file_desc *filedesc = diff --git a/src/dll/fuse/library.h b/src/dll/fuse/library.h index 2aec5040..ebde4c8f 100644 --- a/src/dll/fuse/library.h +++ b/src/dll/fuse/library.h @@ -24,6 +24,11 @@ #define FSP_FUSE_LIBRARY_NAME LIBRARY_NAME "-FUSE" +#define FSP_FUSE_HDR_FROM_CONTEXT(c) \ + (struct fsp_fuse_context_header *)((PUINT8)(c) - sizeof(struct fsp_fuse_context_header)) +#define FSP_FUSE_CONTEXT_FROM_HDR(h) \ + (struct fuse_context *)((PUINT8)(h) + sizeof(struct fsp_fuse_context_header)) + struct fuse { struct fsp_fuse_env *env; @@ -33,9 +38,9 @@ struct fuse FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy; FSP_FSCTL_VOLUME_PARAMS VolumeParams; PWSTR MountPoint; - FSP_SERVICE *Service; FSP_FILE_SYSTEM *FileSystem; BOOLEAN fsinit; + FSP_SERVICE *Service; /* weak */ }; struct fsp_fuse_context_header @@ -74,13 +79,6 @@ struct fsp_fuse_dirinfo char PosixNameBuf[]; /* includes term-0 (unlike FSP_FSCTL_DIR_INFO) */ }; -static inline -struct fsp_fuse_context_header *fsp_fuse_context_header(VOID) -{ - struct fuse_context *context = fsp_fuse_get_context(0); - return (PVOID)((PUINT8)context - sizeof(struct fsp_fuse_context_header)); -} - NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem, FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem, diff --git a/src/dll/library.h b/src/dll/library.h index 0f3402f7..e74cd2d1 100644 --- a/src/dll/library.h +++ b/src/dll/library.h @@ -59,4 +59,6 @@ NTSTATUS FspEventLogUnregister(VOID); PWSTR FspDiagIdent(VOID); +BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType); + #endif diff --git a/src/dll/service.c b/src/dll/service.c index ccafb0aa..305689fa 100644 --- a/src/dll/service.c +++ b/src/dll/service.c @@ -46,7 +46,7 @@ static VOID FspServiceMain(FSP_SERVICE *Service, DWORD Argc, PWSTR *Argv); static DWORD WINAPI FspServiceCtrlHandler( DWORD Control, DWORD EventType, PVOID EventData, PVOID Context); static DWORD WINAPI FspServiceConsoleModeThread(PVOID Context); -static BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType); +BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType); #define FspServiceFromTable() (0 != FspServiceTable ?\ (FSP_SERVICE *)((PUINT8)FspServiceTable[0].lpServiceName - FIELD_OFFSET(FSP_SERVICE, ServiceName)) :\ @@ -69,10 +69,11 @@ VOID FspServiceFinalize(BOOLEAN Dynamic) CloseHandle(FspServiceConsoleModeEvent); } -FSP_API ULONG FspServiceRun(PWSTR ServiceName, +FSP_API ULONG FspServiceRunEx(PWSTR ServiceName, FSP_SERVICE_START *OnStart, FSP_SERVICE_STOP *OnStop, - FSP_SERVICE_CONTROL *OnControl) + FSP_SERVICE_CONTROL *OnControl, + PVOID UserContext) { FSP_SERVICE *Service; NTSTATUS Result; @@ -85,6 +86,7 @@ FSP_API ULONG FspServiceRun(PWSTR ServiceName, L"The service %s cannot be created (Status=%lx).", Service->ServiceName, Result); return FspWin32FromNtStatus(Result); } + Service->UserContext = UserContext; FspServiceAllowConsoleMode(Service); Result = FspServiceLoop(Service); @@ -510,7 +512,8 @@ static DWORD WINAPI FspServiceConsoleModeThread(PVOID Context) return 0; } -static BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType) +/* expose FspServiceConsoleCtrlHandler so it can be used from fsp_fuse_signal_handler */ +BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType) { UINT32 Disabled = FspServiceConsoleCtrlHandlerDisabled; MemoryBarrier();