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:
Bill Zissimopoulos 2016-06-15 23:12:08 -07:00
parent b8ec5ba019
commit b695ef8ad8
7 changed files with 92 additions and 100 deletions

View File

@ -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);

View File

@ -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.
*

View File

@ -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);
}

View File

@ -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 =

View File

@ -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,

View File

@ -59,4 +59,6 @@ NTSTATUS FspEventLogUnregister(VOID);
PWSTR FspDiagIdent(VOID);
BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
#endif

View File

@ -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();