OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

pkcs11-comment message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]


Subject: PKCS#11 Usage Guide vs. POSIX issue


Hi,

It has come to my attention that the PKCS#11 Usage Guide is making a
recommendation which triggers POSIX-undefined behaviour.

The recommendation in question is §2.5.2 of the Usage Guide:
http://docs.oasis-open.org/pkcs11/pkcs11-ug/v2.40/cn02/pkcs11-ug-v2.40-cn02.html#_Toc406759987

It says that it is good Cryptoki programming practice to call
C_Initialize() again "immediately" in the child process after fork().

This has been implemented in some cases by using a pthread_atfork()
child handler and directly calling C_Initialize() from it, for any
PKCS#11 providers which were loaded in the parent.

That behaviour is problematic for a number of reasons, which I'll
present in increasing order of importance:

Firstly, in most cases all we're going to do after a fork is exec, so to
call C_Initialize() is at best a gratuitous performance issue on every
fork() call.

Secondly, there are a number of PKCS#11 providers which simply don't
cope. For PKCS#11 providers whose main development is not on POSIX
systems, the whole concept of fork() is alien, and it's largely
untested.

So calling C_Initialize() again in the child might deadlock, or it might
disrupt the state of the module in the *parent* such that it no longer
works (to cite but two that I've actually seen in the last week — and
those were OpenSC and p11-kit-proxy which *are* developed on Linux!).

Third, there's the POSIX issue I reference in $SUBJECT...

The pthread_atfork() documentation¹ says:

 "It is suggested that programs that use fork() call an exec function
  very soon afterwards in the child process, thus resetting all states.
  In the meantime, only a short list of async-signal-safe library
  routines are promised to be available."

It then goes on to explain why pthread_atfork() doesn't really work for
its original intended purpose, before concluding more forcefully and
using the word 'requires' instead of 'suggested':

 "As explained, there is no suitable solution for functionality which
  requires non-atomic operations to be protected through mutexes and
  locks. This is why the POSIX.1 standard since the 1996 release
  requires that the child process after fork() in a multi-threaded
  process only calls async-signal-safe interfaces."

The fork() documentation² does indeed say that, as well as:

 "When the application calls fork() from a signal handler and any of the
  fork handlers registered by pthread_atfork() calls a function that is
  not async-signal-safe, the behavior is undefined."

The "short list of async-signal-safe library functions" is indeed
short³.

It certainly doesn't seem to be the case that C_Initialize() is
guaranteed to call only functions on that short list. So calling
C_Initialize() from within the atfork child handler would appear to
trigger undefined behaviour according to POSIX.


It would be useful, therefore, to change the PKCS#11 Usage Guide to
reflect this.

My personal preference might be to add a short paragraph warning that
POSIX effectively forbids the child process from calling *any* functions
of a PKCS#11 provider after fork() from a multi-threaded program, and
also to recommend that C_Initialize() should *only* be called if the
child process is going to be long-lived rather than immediately exiting
or executing something else.

Thanks.


-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

¹ http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html
² http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
³ http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03



Attachment: smime.p7s
Description: S/MIME cryptographic signature



[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]