/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <pthread.h>
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <security/cryptoki.h>
#include "kernelGlobal.h"
#include "kernelSession.h"
#include "kernelSlot.h"
#include "kernelEmulate.h"
/*
* Delete all the sessions. First, obtain the slot lock.
* Then start to delete one session at a time. The boolean wrapper_only
* argument indicates that whether the caller only wants to clean up the
* session wrappers and the object wrappers in the library.
* - When this function is called by C_CloseAllSessions or indirectly by
* C_Finalize, wrapper_only is FALSE.
* - When this function is called by cleanup_child, wrapper_only is TRUE.
*/
void
{
(void) pthread_mutex_lock(&delete_sessions_mutex);
/*
* Delete all the sessions in the slot's session list.
* The routine kernel_delete_session() updates the linked list.
* So, we do not need to maintain the list here.
*/
for (;;) {
break;
}
/*
* Set SESSION_IS_CLOSING flag so any access to this
* session will be rejected.
*/
}
(void) pthread_mutex_unlock(&delete_sessions_mutex);
}
/*
* Create a new session struct, and add it to the slot's session list.
*
* This function is called by C_OpenSession(), which hold the slot lock.
*/
{
int r;
/* Allocate a new session struct */
return (CKR_HOST_MEMORY);
}
new_sp->ses_refcnt = 0;
new_sp->ses_close_sync = 0;
/* Initialize the lock for the newly created session */
return (CKR_CANT_LOCK);
}
break;
}
if (r < 0) {
} else {
}
return (rv);
}
/* Insert the new session in front of the slot's session list */
} else {
}
/* Type casting the address of a session struct to a session handle */
return (CKR_OK);
}
/*
* Delete a session:
* - Remove the session from the slot's session list.
* - Release all the objects created by the session.
*
* The boolean argument slot_lock_held is used to indicate that whether
* the caller of this function holds the slot lock or not.
* - When called by kernel_delete_all_sessions(), which is called by
* C_Finalize() or C_CloseAllSessions() -- slot_lock_held = TRUE.
* - When called by C_CloseSession() -- slot_lock_held = FALSE.
*/
void
{
/*
* Check to see if the caller holds the lock on the global
* session list. If not, we need to acquire that lock in
* order to proceed.
*/
if (!slot_lock_held) {
/* Acquire the slot lock */
}
/*
* Remove the session from the slot's session list first.
*/
/* Session is the first one in the list */
} else {
/* Session is the only one in the list */
}
} else {
/* Session is not the first one in the list */
/* Session is in the middle of the list */
} else {
/* Session is the last one in the list */
}
}
if (!slot_lock_held) {
/*
* If the slot lock is obtained by
* this function, then release that lock after
* removing the session from session linked list.
* We want the releasing of the objects of the
* session, and freeing of the session itself to
* be done without holding the slot's session list
* lock.
*/
}
/* Acquire the individual session lock */
/*
* Make sure another thread hasn't freed the session.
*/
return;
}
/*
* The deletion of a session must be blocked when the session reference
* count is not zero. This means that if the thread that is attempting
* to close the session must wait until the prior operations on this
* session are finished.
*
* Unless we are being forced to shut everything down, this only
* happens if the library's _fini() is running not if someone
* explicitly called C_Finalize().
*/
if (wrapper_only) {
session_p->ses_refcnt = 0;
}
while (session_p->ses_refcnt != 0) {
/*
* We set the SESSION_REFCNT_WAITING flag before we put
* this closing thread in a wait state, so other non-closing
* operation thread will wake it up only when
* the session reference count becomes zero and this flag
* is set.
*/
}
/*
* Remove all the objects created in this session, waiting
* until each object's refcnt is 0.
*/
/*
* Mark session as no longer valid. This should be after the call
* to kernel_delete_all_objects_in_session().
*/
session_p->magic_marker = 0;
/* In case application did not call Final */
}
}
}
}
}
}
/* Reset SESSION_IS_CLOSING flag. */
/* Destroy the individual session lock */
if (!wrapper_only) {
&close_session) < 0) {
break;
}
/*
* Ignore ioctl return codes. If the library tells the kernel
* to close a session and the kernel says "I don't know what
* session you're talking about", there's not much that can be
* done. All sessions in the kernel will be closed when the
*/
}
/*
* If there is no more session remained in this slot, reset the slot's
* session state to CKU_PUBLIC. Also, clean up all the token object
* wrappers in the library for this slot.
*/
/* Acquire the slot lock if lock is not held */
if (!slot_lock_held) {
}
/* Reset the session auth state. */
/* Clean up token object wrappers. */
while (objp) {
(void) kernel_object_delay_free(objp);
}
}
/* Release the slot lock if lock is not held */
if (!slot_lock_held) {
}
}
/*
* This function is used to type cast a session handle to a pointer to
* the session struct. Also, it does the following things:
* 1) Check to see if the session struct is tagged with a session
* magic number. This is to detect when an application passes
* a bogus session pointer.
* 2) Acquire the locks on the designated session.
* 3) Check to see if the session is in the closing state that another
* thread is performing.
* 4) Increment the session reference count by one. This is to prevent
* this session from being closed by other thread.
* 5) Release the locks on the designated session.
*/
{
return (CKR_SESSION_HANDLE_INVALID);
} else {
} else {
/* Increment session ref count. */
sp->ses_refcnt++;
}
}
return (rv);
}
/*
* This function adds the to-be-freed session to a linked list.
* When the number of sessions queued in the linked list reaches the
* maximum threshold MAX_SES_TO_BE_FREED, it will free the first
* session (FIFO) in the list.
*/
void
{
/* Add the newly deleted session at the end of the list */
} else {
}
/*
* Free the first session in the list only if
* the total count reaches maximum threshold.
*/
}
}
/*
* Acquire all slot mutexes and all their session mutexes.
* Order:
* 1. delete_sessions_mutex
* for each slot:
* 2. pslot->sl_mutex
* for each session:
* 3. session_p->session_mutex
* 4. session_p->ses_free_mutex
* when sessions are locked we can lock their objects and
* for each session go through the session_p->object_list
* 5. objp->object_mutex
*
* Note 1: We have to lock all sessions first and after that we can lock their
* objects, because sometimes a function is called with a session and an object
* which does not belong to the session. Because session lock is acquired always
* before the object lock, it avoids deadlock.
*
* Note 2: The unlocking of the sessions and objects list should optimally be
* in the opposite order, but currently no thread locks two sessions or objects
* at the same time.
*/
void
{
int slotID;
(void) pthread_mutex_lock(&delete_sessions_mutex);
/* Iterate through sessions acquiring all mutexes */
while (session_p) {
}
/* Iterate through sessions acquiring all object's mutexes */
while (session_p) {
while (objp) {
}
}
}
}
/* Release in opposite order to kernel_acquire_all_slots_mutexes(). */
void
{
int slotID;
/* Iterate through sessions releasing all object's mutexes */
while (session_p) {
while (objp) {
(void) pthread_mutex_unlock(
&objp->object_mutex);
}
}
/* Iterate through sessions releasing all mutexes */
while (session_p) {
}
}
(void) pthread_mutex_unlock(&delete_sessions_mutex);
}