Exemple #1
0
/* called from the CRYPTO_UNLOAD_SOFT_MODULE ioctl */
int
crypto_unload_soft_module(caddr_t name)
{
	int error;
	modid_t id;
	kcf_provider_desc_t *provider;
	struct modctl *mcp;

	/* verify that 'name' refers to a registered crypto provider */
	if ((provider = kcf_prov_tab_lookup_by_name(name)) == NULL)
		return (CRYPTO_UNKNOWN_PROVIDER);

	/*
	 * We save the module id and release the reference. We need to
	 * do this as modunload() calls unregister which waits for the
	 * refcnt to drop to zero.
	 */
	id = provider->pd_module_id;
	KCF_PROV_REFRELE(provider);

	if ((mcp = mod_hold_by_name(name)) != NULL) {
		mcp->mod_loadflags &= ~(MOD_NOAUTOUNLOAD);
		mod_release_mod(mcp);
	}

	if ((error = modunload(id)) != 0) {
		return (error == EBUSY ? CRYPTO_BUSY : CRYPTO_FAILED);
	}

	return (CRYPTO_SUCCESS);
}
Exemple #2
0
static uintptr_t
kctl_lookup_by_name(char *modname, char *symname)
{
	struct modctl *mctl;
	Sym *ksym;
	uintptr_t addr;

	if ((mctl = mod_hold_by_name(modname)) == NULL)
		return (0);
	if ((ksym = kobj_lookup_all(mctl->mod_mp, symname, 1)) == NULL) {
		mod_release_mod(mctl);
		return (0);
	}

	addr = ksym->st_value;

	mod_release_mod(mctl);

	return (addr);
}
Exemple #3
0
/*
 * Called from CRYPTO_LOAD_SOFT_DISABLED ioctl.
 * If new_count is 0, then completely remove the entry.
 */
int
crypto_load_soft_disabled(char *name, uint_t new_count,
    crypto_mech_name_t *new_array)
{
	kcf_provider_desc_t *provider = NULL;
	crypto_mech_name_t *prev_array;
	uint_t prev_count = 0;
	int rv;

	provider = kcf_prov_tab_lookup_by_name(name);
	if (provider != NULL) {
		mutex_enter(&provider->pd_lock);
		/*
		 * Check if any other thread is disabling or removing
		 * this provider. We return if this is the case.
		 */
		if (provider->pd_state >= KCF_PROV_DISABLED) {
			mutex_exit(&provider->pd_lock);
			KCF_PROV_REFRELE(provider);
			return (CRYPTO_BUSY);
		}
		provider->pd_state = KCF_PROV_DISABLED;
		mutex_exit(&provider->pd_lock);

		undo_register_provider(provider, B_TRUE);
		KCF_PROV_REFRELE(provider);
		if (provider->pd_kstat != NULL)
			KCF_PROV_REFRELE(provider);

		mutex_enter(&provider->pd_lock);
		/* Wait till the existing requests complete. */
		while (provider->pd_state != KCF_PROV_FREED) {
			cv_wait(&provider->pd_remove_cv, &provider->pd_lock);
		}
		mutex_exit(&provider->pd_lock);
	}

	if (new_count == 0) {
		kcf_policy_remove_by_name(name, &prev_count, &prev_array);
		crypto_free_mech_list(prev_array, prev_count);
		rv = CRYPTO_SUCCESS;
		goto out;
	}

	/* put disabled mechanisms into policy table */
	if ((rv = kcf_policy_load_soft_disabled(name, new_count, new_array,
	    &prev_count, &prev_array)) == CRYPTO_SUCCESS) {
		crypto_free_mech_list(prev_array, prev_count);
	}

out:
	if (provider != NULL) {
		redo_register_provider(provider);
		if (provider->pd_kstat != NULL)
			KCF_PROV_REFHOLD(provider);
		mutex_enter(&provider->pd_lock);
		provider->pd_state = KCF_PROV_READY;
		mutex_exit(&provider->pd_lock);
	} else if (rv == CRYPTO_SUCCESS) {
		/*
		 * There are some cases where it is useful to kCF clients
		 * to have a provider whose mechanism is enabled now to be
		 * available. So, we attempt to load it here.
		 *
		 * The check, new_count < prev_count, ensures that we do this
		 * only in the case where a mechanism(s) is now enabled.
		 * This check assumes that enable and disable are separate
		 * administrative actions and are not done in a single action.
		 */
		if (new_count < prev_count && (in_soft_config_list(name)) &&
		    (modload("crypto", name) != -1)) {
			struct modctl *mcp;
			boolean_t load_again = B_FALSE;

			if ((mcp = mod_hold_by_name(name)) != NULL) {
				mcp->mod_loadflags |= MOD_NOAUTOUNLOAD;

				/* memory pressure may have unloaded module */
				if (!mcp->mod_installed)
					load_again = B_TRUE;
				mod_release_mod(mcp);

				if (load_again)
					(void) modload("crypto", name);
			}
		}
	}

	return (rv);
}
int  VBOXCALL   supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
{
    pImage->idSolMod   = -1;
    pImage->pSolModCtl = NULL;

# if 1 /* This approach requires _init/_fini/_info stubs. */
    /*
     * Construct a filename that escapes the module search path and let us
     * specify a root path.
     */
    /** @todo change this to use modctl and use_path=0. */
    const char *pszName = RTPathFilename(pszFilename);
    AssertReturn(pszName, VERR_INVALID_PARAMETER);
    char *pszSubDir = RTStrAPrintf2("../../../../../../../../../../..%.*s", pszName - pszFilename - 1, pszFilename);
    if (!pszSubDir)
        return VERR_NO_STR_MEMORY;
    int idMod = modload(pszSubDir, pszName);
    if (idMod == -1)
    {
        /* This is an horrible hack for avoiding the mod-present check in
           modrload on S10.  Fortunately, nobody else seems to be using that
           variable... */
        extern int swaploaded;
        int saved_swaploaded = swaploaded;
        swaploaded = 0;
        idMod = modload(pszSubDir, pszName);
        swaploaded = saved_swaploaded;
    }
    RTStrFree(pszSubDir);
    if (idMod == -1)
    {
        LogRel(("modload(,%s): failed, could be anything...\n", pszFilename));
        return VERR_LDR_GENERAL_FAILURE;
    }

    modctl_t *pModCtl = mod_hold_by_id(idMod);
    if (!pModCtl)
    {
        LogRel(("mod_hold_by_id(,%s): failed, weird.\n", pszFilename));
        /* No point in calling modunload. */
        return VERR_LDR_GENERAL_FAILURE;
    }
    pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD | MOD_NOUNLOAD; /* paranoia */

# else

    const int idMod = -1;
    modctl_t *pModCtl = mod_hold_by_name(pszFilename);
    if (!pModCtl)
    {
        LogRel(("mod_hold_by_name failed for '%s'\n", pszFilename));
        return VERR_LDR_GENERAL_FAILURE;
    }

    int rc = kobj_load_module(pModCtl, 0 /*use_path*/);
    if (rc != 0)
    {
        LogRel(("kobj_load_module failed with rc=%d for '%s'\n", rc, pszFilename));
        mod_release_mod(pModCtl);
        return RTErrConvertFromErrno(rc);
    }
# endif

    /*
     * Get the module info.
     *
     * Note! The text section is actually not at mi_base, but and the next
     *       alignment boundrary and there seems to be no easy way of
     *       getting at this address.  This sabotages supdrvOSLdrLoad.
     *       Bastards!
     */
    struct modinfo ModInfo;
    kobj_getmodinfo(pModCtl->mod_mp, &ModInfo);
    pImage->pvImage    = ModInfo.mi_base;
    pImage->idSolMod   = idMod;
    pImage->pSolModCtl = pModCtl;

    mod_release_mod(pImage->pSolModCtl);
    LogRel(("supdrvOSLdrOpen: succeeded for '%s' (mi_base=%p mi_size=%#x), id=%d ctl=%p\n",
            pszFilename, ModInfo.mi_base, ModInfo.mi_size, idMod, pModCtl));
    return VINF_SUCCESS;
}