mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	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
This commit is contained in:
		| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -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 = | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -59,4 +59,6 @@ NTSTATUS FspEventLogUnregister(VOID); | ||||
|  | ||||
| PWSTR FspDiagIdent(VOID); | ||||
|  | ||||
| BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user