简体   繁体   中英

Check pointer handle is valid

I want to implement a Microsoft CryptographicServiceProvider library and currently I thinking about the best way how to deal with context handle which I create.

My question is specific to this case but the design approach can be used in other situations.

I come from a managed code background and I am not 100% shure about multithread pointer handling in C/C++.

In general there are two functions which are responsible for handle creation and destruction (CryptAcquireContext, CryptReleaseContext), and all subsequent CSP functions uses the handle which is return by the creator function.

I didn't found any concrete information or specification from Microsoft which gives a design approach or rules how to do it. But I did research with other CSP providers created by Microsoft to find out the design rules, which are:

  • The functions must be thread safe
  • The context handle will not be shared between threads
  • If a context handle is not valid return with an error

Other MS CSP Provider will return a valid pointer as handle, or NULL if not.

I don't think that the calling application will pass complete garbage but it could happen that it passes a handle which has been already released and my library should return with an error.

This brought me to three ideas how to implement that:

  1. Just allocate memory of my context struct with malloc or new and return the raw pointer as handle.

    I can expect that the applications which call my library will pass a valid handle. But if not my library will run into an undefined behaviour. So I need a better solution.

  2. Add the pointer which I create to a list (std::list, std::map). So I can iterate the list to check if the pointer exists. The access to the list is guarded with a mutex.

    This should be safe and a regular API usage shouldn't be a performance issue. But in a Terminal Server scenario it could be. In this case the Windows process lsass.exe creates for every user who wants to login a CSP context in a separate thread and makes around 10 API calls per context.

    The design goal is that my library should be able to handle 300 clients parallel. I don't know how many threads a created by Windows in this case.

    So if possible I would prefer a lockless implementation.

  3. I allocate a basic struct which holds a check value and the pointer of the actual data. Use the pointer of this struct as context handle.

     typedef struct CSPHandle { int Type; // (eg. magic number CSPContext=0xA1B2C3D4) CSPContextPtr pCSPContext; }; 

    So I could read the first byte of the passed pointer and check if the data equals my defined type. And I have the full control about actual data pointer, which is set to NULL if the context is released. Is this a good or bad idea?

What are your thoughts about this case? Should I go with one of these approaches or is there a other solution?

Thanks

I found a solution and will answer my question.

I overlooked a little but important detail

In CSP there are not direct API calls to the dll (load library, get function pointer, call function) because the function calls are forwarded by the Microsoft CSP which loads the CSP library by name.

So the Microsoft CSP needs to know and to check the passed context to get a correct mapping to the specific library.

Example:
1. client->cryptacquirecontext( in cspname, out ctx)
2. MS CSP->loads libray from the cspname
3. MS CSP->calls the function pointer of the loaded library
4. CSP LIB->cryptacquirecontext creates new context
5. MS CSP->receives the returned csp handle and saves it to the dll mapping
6. MS CSP->returns the result to the calling application
7. client->cryptsetprovparam(ctx) // which was created before
8. MS CSP->checks if the context exists and which library is responsible
9. MS CSP->if the given context can not be mapped to a csp dll an error will be returned, because the MS CSP doesn't know which function pointer should be called.

So in this case it should be sufficient just to allocate memory. If the client application passes invalid context handle it will never hit the csp library.

I think that the MS CSP uses a list with mutex guard to store the context mappings. Because the context can be anything from a random number to a valid pointer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM