Blame usr/sbin/pkcsslotd/shmem.c

Packit 8681c6
/*
Packit 8681c6
 * COPYRIGHT (c) International Business Machines Corp. 2001-2017
Packit 8681c6
 *
Packit 8681c6
 * This program is provided under the terms of the Common Public License,
Packit 8681c6
 * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
Packit 8681c6
 * software constitutes recipient's acceptance of CPL-1.0 terms which can be
Packit 8681c6
 * found in the file LICENSE file or at
Packit 8681c6
 * https://opensource.org/licenses/cpl1.0.php
Packit 8681c6
 */
Packit 8681c6
Packit 8681c6
#include <stdlib.h>
Packit 8681c6
#include <stdio.h>
Packit 8681c6
#include <errno.h>
Packit 8681c6
#include <grp.h>
Packit 8681c6
#include <string.h>
Packit 8681c6
#include <sys/shm.h>
Packit 8681c6
#include <sys/stat.h>
Packit 8681c6
Packit 8681c6
#include "slotmgr.h"
Packit 8681c6
#include "log.h"
Packit 8681c6
#include "pkcsslotd.h"
Packit 8681c6
Packit 8681c6
#define MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
Packit 8681c6
#define MAPFILENAME CONFIG_PATH "/.apimap"
Packit 8681c6
Packit 8681c6
pthread_mutexattr_t mtxattr;    // Mutex attribute for the shared memory Mutex
Packit 8681c6
Packit 8681c6
/***********************************************************************
Packit 8681c6
 *  CreateSharedMemory -
Packit 8681c6
 *
Packit 8681c6
 *      Creates and initializes a shared memory file.  This function will fail
Packit 8681c6
 *      if the memory is already allocated since we're the owner of it.
Packit 8681c6
 *
Packit 8681c6
 ***********************************************************************/
Packit 8681c6
Packit 8681c6
int CreateSharedMemory(void)
Packit 8681c6
{
Packit 8681c6
    struct stat statbuf;
Packit 8681c6
    char *Path = NULL;
Packit 8681c6
    struct group *grp;
Packit 8681c6
    struct shmid_ds shm_info;
Packit 8681c6
Packit 8681c6
#if !MMAP
Packit Service 8aa27d
    /*
Packit Service 8aa27d
     * getenv() is safe here since we will exclusively create the segment and
Packit Service 8aa27d
     * make sure only members of "pkcs11" group can attach to it.
Packit Service 8aa27d
     */
Packit 8681c6
    if (((Path = getenv("PKCS11_SHMEM_FILE")) == NULL) || (Path[0] == '\0')) {
Packit 8681c6
        Path = TOK_PATH;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    // Get shared memory key token all users of the shared memory
Packit 8681c6
    // need to get the same token
Packit 8681c6
Packit 8681c6
    if (stat(Path, &statbuf) < 0) {
Packit 8681c6
        ErrLog("Shared Memory Key Token creation file does not exist");
Packit 8681c6
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
    // SAB  Get the group information for the PKCS#11 group... fail if
Packit 8681c6
    // it does not exist
Packit 8681c6
    grp = getgrnam("pkcs11");
Packit 8681c6
    if (!grp) {
Packit 8681c6
        ErrLog("Group PKCS#11 does not exist ");
Packit 8681c6
        return FALSE;           // Group does not exist... setup is wrong..
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
Packit 8681c6
    tok = ftok(Path, 'b');
Packit 8681c6
    // Allocate the shared memory... Fail if the memory is already
Packit 8681c6
    // allocated since the slot mgr is the owner of it.
Packit 8681c6
Packit 8681c6
    // Is this some attempt at exclusivity, or is that just a side effect?
Packit 8681c6
    // - SCM 9/1
Packit 8681c6
Packit 8681c6
    shmid = shmget(tok, sizeof(Slot_Mgr_Shr_t),
Packit 8681c6
                   IPC_CREAT | IPC_EXCL | S_IRUSR |
Packit 8681c6
                   S_IRGRP | S_IWUSR | S_IWGRP);
Packit 8681c6
Packit 8681c6
    // Explanation of options to shmget():
Packit 8681c6
Packit 8681c6
    /*
Packit 8681c6
     *  IPC_CREAT Creates the data structure if it does not already exist.
Packit 8681c6
     *  IPC_EXCL  Causes the shmget subroutine to be unsuccessful if the
Packit 8681c6
     *            IPC_CREAT flag is also set, and the data structure already
Packit 8681c6
     *            exists.
Packit 8681c6
     *  S_IRUSR   Permits the process that owns the data structure to read it.
Packit 8681c6
     *  S_IWUSR   Permits the process that owns the data structure to modify it.
Packit 8681c6
     *  S_IRGRP   Permits the group associated with the data structure to
Packit 8681c6
     *            read it.
Packit 8681c6
     *  S_IWGRP   Permits the group associated with the data structure to
Packit 8681c6
     *            modify it.
Packit 8681c6
     *
Packit 8681c6
     *
Packit 8681c6
     *  WE DON"T WANT OTHERS
Packit 8681c6
     *  S_IROTH   Permits others to read the data structure.
Packit 8681c6
     *  S_IWOTH   Permits others to modify the data structure.
Packit 8681c6
     */
Packit 8681c6
Packit 8681c6
Packit 8681c6
    if (shmid < 0) {
Packit 8681c6
        ErrLog("Shared memory creation failed (0x%X)\n", errno);
Packit 8681c6
        ErrLog("Reclaiming 0x%X\n", tok);
Packit 8681c6
        shmid = shmget(tok, sizeof(Slot_Mgr_Shr_t), 0);
Packit 8681c6
        DestroySharedMemory();
Packit 8681c6
        shmid = shmget(tok, sizeof(Slot_Mgr_Shr_t),
Packit 8681c6
                       IPC_CREAT | IPC_EXCL | S_IRUSR |
Packit 8681c6
                       S_IRGRP | S_IWUSR | S_IWGRP);
Packit 8681c6
        if (shmid < 0) {
Packit 8681c6
            ErrLog("Shared memory reclamation failed (0x%X)\n", errno);
Packit 8681c6
            ErrLog("perform ipcrm -M 0x%X\n", tok);
Packit 8681c6
            return FALSE;
Packit 8681c6
        }
Packit 8681c6
    }
Packit 8681c6
    // SAB Set the group ownership of the shared mem segment..
Packit 8681c6
    // we already have the group structure..
Packit 8681c6
Packit 8681c6
    if (shmctl(shmid, IPC_STAT, &shm_info) == 0) {
Packit 8681c6
Packit 8681c6
        shm_info.shm_perm.gid = grp->gr_gid;
Packit 8681c6
Packit 8681c6
        if (shmctl(shmid, IPC_SET, &shm_info) == -1) {
Packit 8681c6
            ErrLog("Failed to set group ownership for shm \n");
Packit 8681c6
            shmctl(shmid, IPC_RMID, NULL);
Packit Service 8aa27d
            // Not safe to use this segment
Packit Service 8aa27d
            return FALSE;
Packit 8681c6
        }
Packit 8681c6
Packit 8681c6
    } else {
Packit 8681c6
        ErrLog("Can't get status of shared memory %d\n", errno);
Packit 8681c6
        // we know it was created... we need to destroy it...
Packit 8681c6
        shmctl(shmid, IPC_RMID, NULL);
Packit Service 8aa27d
        // Not safe to use this segment
Packit Service 8aa27d
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return TRUE;
Packit 8681c6
#else
Packit 8681c6
    {
Packit 8681c6
#warning "EXPERIMENTAL"
Packit 8681c6
        int fd;
Packit 8681c6
        int i;
Packit 8681c6
        char *buffer;
Packit 8681c6
Packit 8681c6
        grp = getgrnam("pkcs11");
Packit 8681c6
        if (!grp) {
Packit 8681c6
            ErrLog("Group \"pkcs11\" does not exist! "
Packit 8681c6
                   "Opencryptoki setup is incorrect.");
Packit 8681c6
            return FALSE;       // Group does not exist... setup is wrong..
Packit 8681c6
        }
Packit 8681c6
Packit 8681c6
        fd = open(MAPFILENAME, O_RDWR, MODE);
Packit 8681c6
        if (fd < 0) {
Packit 8681c6
            // File does not exist... this is cool, we creat it here
Packit 8681c6
            fd = open(MAPFILENAME, O_RDWR | O_CREAT, MODE); // Create the file
Packit 8681c6
            if (fd < 0) {   // We are really hosed here, since we should be able
Packit 8681c6
                // to create the file now
Packit 8681c6
                ErrLog("%s: open(%s): %s", __func__, MAPFILENAME,
Packit 8681c6
                       strerror(errno));
Packit 8681c6
                return FALSE;
Packit 8681c6
            } else {
Packit 8681c6
                if (fchmod(fd, MODE) == -1) {
Packit 8681c6
                    ErrLog("%s: fchmod(%s): %s", __func__, MAPFILENAME,
Packit 8681c6
                           strerror(errno));
Packit 8681c6
                    close(fd);
Packit 8681c6
                    return FALSE;
Packit 8681c6
                }
Packit 8681c6
                if (fchown(fd, 0, grp->gr_gid) == -1) {
Packit 8681c6
                    ErrLog("%s: fchown(%s, root, pkcs11): %s", __func__,
Packit 8681c6
                           MAPFILENAME, strerror(errno));
Packit 8681c6
                    close(fd);
Packit 8681c6
                    return FALSE;
Packit 8681c6
                }
Packit 8681c6
                // Create a buffer and make the file the right length
Packit 8681c6
                i = sizeof(Slot_Mgr_Shr_t);
Packit 8681c6
                buffer = malloc(sizeof(Slot_Mgr_Shr_t));
Packit 8681c6
                memset(buffer, '\0', i);
Packit 8681c6
                write(fd, buffer, i);
Packit 8681c6
                free(buffer);
Packit 8681c6
                close(fd);
Packit 8681c6
            }
Packit 8681c6
        } else {
Packit 8681c6
            ErrLog("%s: [%s] exists; you may already have a pkcsslot daemon "
Packit 8681c6
                   "running. If this is not the case, then the prior daemon "
Packit 8681c6
                   "was not shut down cleanly. Please delete this file and "
Packit 8681c6
                   "try again\n", __func__, MAPFILENAME);
Packit 8681c6
            close(fd);
Packit 8681c6
            return FALSE;
Packit 8681c6
        }
Packit 8681c6
        return TRUE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
#endif
Packit 8681c6
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
Packit 8681c6
Packit 8681c6
/***********************************************************************
Packit 8681c6
 *
Packit 8681c6
 * AttachToSharedMemory -
Packit 8681c6
 *
Packit 8681c6
 *     Called after creating the shared memory file
Packit 8681c6
 *     Basically allows us to have access to the memory we've just created
Packit 8681c6
 *
Packit 8681c6
 ***********************************************************************/
Packit 8681c6
Packit 8681c6
int AttachToSharedMemory(void)
Packit 8681c6
{
Packit 8681c6
Packit 8681c6
#if !MMAP
Packit 8681c6
    shmp = NULL;
Packit 8681c6
    shmp = (Slot_Mgr_Shr_t *) shmat(shmid, NULL, 0);
Packit 8681c6
Packit 8681c6
    if (!shmp) {
Packit 8681c6
        ErrLog("Shared memory attach failed (0x%X)\n", errno);
Packit 8681c6
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Initizalize the memory to 0  */
Packit 8681c6
    memset(shmp, '\0', sizeof(*shmp));
Packit 8681c6
Packit 8681c6
    return TRUE;
Packit 8681c6
#else
Packit 8681c6
    {
Packit 8681c6
#warning "EXPERIMENTAL"
Packit 8681c6
        int fd;
Packit 8681c6
        int i;
Packit 8681c6
        char *buffer;
Packit 8681c6
Packit 8681c6
        fd = open(MAPFILENAME, O_RDWR, MODE);
Packit 8681c6
        if (fd < 0) {
Packit 8681c6
            return FALSE;       //Failed
Packit 8681c6
        }
Packit 8681c6
        shmp =
Packit 8681c6
            (Slot_Mgr_Shr_t *) mmap(NULL, sizeof(Slot_Mgr_Shr_t),
Packit 8681c6
                                    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Packit 8681c6
        close(fd);
Packit 8681c6
        if (!shmp) {
Packit 8681c6
            return FALSE;
Packit 8681c6
        }
Packit 8681c6
        return TRUE;
Packit 8681c6
    }
Packit 8681c6
#endif
Packit 8681c6
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
Packit 8681c6
/***********************************************************************
Packit 8681c6
 *
Packit 8681c6
 * DetachFromSharedMemory -
Packit 8681c6
 *
Packit 8681c6
 *     Un-does AttachToSharedMemory() :)
Packit 8681c6
 *
Packit 8681c6
 ***********************************************************************/
Packit 8681c6
Packit 8681c6
void DetachFromSharedMemory(void)
Packit 8681c6
{
Packit 8681c6
Packit 8681c6
#if !MMAP
Packit 8681c6
    if (shmp == NULL)
Packit 8681c6
        return;
Packit 8681c6
Packit 8681c6
    if (shmdt(shmp) != 0) {
Packit 8681c6
        ErrLog("Attempted to detach from an invalid shared memory pointer");
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    shmp = NULL;
Packit 8681c6
    return;
Packit 8681c6
#else
Packit 8681c6
    if (shmp == NULL)
Packit 8681c6
        return;
Packit 8681c6
Packit 8681c6
    munmap((void *) shmp, sizeof(*shmp));
Packit 8681c6
Packit 8681c6
    unlink(MAPFILENAME);
Packit 8681c6
#endif
Packit 8681c6
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
/***********************************************************************
Packit 8681c6
 *
Packit 8681c6
 * DestroySharedMemory -
Packit 8681c6
 *
Packit 8681c6
 *     Closes (destroys) the shared memory file we created with
Packit 8681c6
 *     CreateSharedMemory()
Packit 8681c6
 *
Packit 8681c6
 *     We should make sure that everyone else has detached before we do this
Packit 8681c6
 *     if we manage to exit before this gets called, you have to call ipcrm
Packit 8681c6
 *     to clean things up...
Packit 8681c6
 *
Packit 8681c6
 ***********************************************************************/
Packit 8681c6
Packit 8681c6
void DestroySharedMemory(void)
Packit 8681c6
{
Packit 8681c6
    if (shmctl(shmid, IPC_RMID, 0) != 0) {
Packit 8681c6
        perror("error in closing shared memory segment");
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
Packit 8681c6
Packit 8681c6
/***********************************************************************
Packit 8681c6
 *
Packit 8681c6
 * InitSharedMemory -
Packit 8681c6
 *
Packit 8681c6
 *      Set up our newly allocated shared memory segment
Packit 8681c6
 *
Packit 8681c6
 *
Packit 8681c6
 ***********************************************************************/
Packit 8681c6
Packit 8681c6
Packit 8681c6
int InitSharedMemory(Slot_Mgr_Shr_t *sp)
Packit 8681c6
{
Packit 8681c6
    uint16 procindex;
Packit 8681c6
Packit 8681c6
    memset(sp->slot_global_sessions, 0, NUMBER_SLOTS_MANAGED * sizeof(uint32));
Packit 8681c6
Packit 8681c6
    /* Initialize the process side of things. */
Packit 8681c6
    /* for now don't worry about the condition variables */
Packit 8681c6
    for (procindex = 0; procindex < NUMBER_PROCESSES_ALLOWED; procindex++) {
Packit 8681c6
        /* Initialize the mutex variables. */
Packit 8681c6
        sp->proc_table[procindex].inuse = FALSE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return TRUE;
Packit 8681c6
}