Пример #1
0
/**
 * Mount VBoxVFS.
 *
 * @param mp        Mount data provided by VFS layer.
 * @param pDev      Device structure provided by VFS layer.
 * @param pUserData Mounting parameters provided by user space mount tool.
 * @param pContext  kAuth context needed in order to authentificate mount operation.
 *
 * @return 0 on success or BSD error code otherwise.
 */
static int
vboxvfs_mount(struct mount *mp, vnode_t pDev, user_addr_t pUserData, vfs_context_t pContext)
{
    NOREF(pDev);
    NOREF(pContext);

    vboxvfs_mount_t *pMount;

    int rc = ENOMEM;

    PDEBUG("Mounting...");

    pMount = vboxvfs_alloc_internal_data(mp, pUserData);
    if (pMount)
    {
        rc = VbglR0SfMapFolder(&g_vboxSFClient, pMount->pShareName, &pMount->pMap);
        if (RT_SUCCESS(rc))
        {
            /* Private data should be set before vboxvfs_create_vnode_internal() call
             * because we need it in order to create vnode. */
            vfs_setfsprivate(mp, pMount);

            /* Reset root vnode */
            pMount->pRootVnode = NULL;

            vfs_setflags(mp, MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC | MNT_NOSUID | MNT_NODEV);

            PDEBUG("VirtualBox shared folder successfully mounted");

            return 0;
        }

        PDEBUG("Unable to map shared folder");
        vboxvfs_destroy_internal_data(&pMount);
    }
    else
        PDEBUG("Unable to allocate internal data");

    return rc;
}
Пример #2
0
NTSTATUS VBoxMRxCreateVNetRoot(IN PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
{
    NTSTATUS Status;

    PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)pCreateNetRootContext->pVNetRoot;

    PMRX_VBOX_DEVICE_EXTENSION pDeviceExtension = VBoxMRxGetDeviceExtension(pCreateNetRootContext->RxContext);
    PMRX_VBOX_NETROOT_EXTENSION pNetRootExtension = VBoxMRxGetNetRootExtension(pVNetRoot->pNetRoot);

    PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
    PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;

    BOOLEAN fInitializeNetRoot = FALSE;

    Log(("VBOXSF: MRxCreateVNetRoot: pNetRoot = %p, pNetRootExtension = %p, name = [%.*ls]\n",
         pNetRoot, pNetRootExtension, pNetRoot->pNetRootName->Length / sizeof(WCHAR), pNetRoot->pNetRootName->Buffer));

    /* IMPORTANT:
     *
     * This function must always call 'pCreateNetRootContext->Callback(pCreateNetRootContext)' before
     * returning and then return STATUS_PENDING. Otherwise Win64 will hang.
     */

    if (pNetRoot->Type == NET_ROOT_PIPE)
    {
        /* VBoxSF claims everything which starts with '\vboxsrv'.
         *
         * So sometimes the system tries to open \vboxsrv\ipc$ pipe for DFS
         * and fails the application call if an unexpected code is returned.
         *
         * According to MSDN: The Windows client returns STATUS_MORE_PROCESSING_REQUIRED to the calling
         * application to indicate that the path does not correspond to a DFS Namespace.
         */
        pVNetRoot->Context = NULL;

        if (pNetRoot->pNetRootName->Length >= 13 * sizeof (WCHAR)) /* Number of bytes in '\vboxsrv\ipc$' unicode string. */
        {
            const WCHAR *Suffix = &pNetRoot->pNetRootName->Buffer[8]; /* Number of chars in '\vboxsrv' */

            if (   Suffix[0] == L'\\'
                && (Suffix[1] == L'I' || Suffix[1] == L'i')
                && (Suffix[2] == L'P' || Suffix[2] == L'p')
                && (Suffix[3] == L'C' || Suffix[3] == L'c')
                && Suffix[4] == L'$'
               )
            {
                if (   pNetRoot->pNetRootName->Length == 13 * sizeof (WCHAR)
                    || (Suffix[5] == L'\\' || Suffix[5] == 0)
                   )
                {
                    /* It is '\vboxsrv\IPC$[\*]'. */
                    Log(("VBOXSF: MRxCreateVNetRoot: IPC$\n"));
                    Status = STATUS_MORE_PROCESSING_REQUIRED;
                    goto l_Exit;
                }
            }
        }

        /* Fail all other pipe open requests. */
        Log(("VBOXSF: MRxCreateVNetRoot: Pipe open not supported!\n"));
        Status = STATUS_NOT_SUPPORTED;
        goto l_Exit;
    }
    else if (pNetRoot->Type == NET_ROOT_MAILSLOT)
    {
        Log(("VBOXSF: MRxCreateVNetRoot: Mailslot open not supported!\n"));
        pVNetRoot->Context = NULL;
        Status = STATUS_NOT_SUPPORTED;
        goto l_Exit;
    }

    if (!pNetRoot->Context)
    {
        /* MRxNetRootSize is not zero in VBoxSF, so it is expected
         * that the Context, which is NetRootExtension, is already allocated.
         */
        Log(("VBOXSF: MRxCreateVNetRoot: NULL netroot context\n"));
        pVNetRoot->Context = NULL;
        Status = STATUS_NOT_SUPPORTED;
        goto l_Exit;
    }

    /* Detect an already initialized NetRoot.
     * pNetRootExtension is actually the pNetRoot->Context and it is not NULL.
     */
    fInitializeNetRoot = (pNetRootExtension->phgcmClient == NULL);

    Status = STATUS_SUCCESS;

    if (fInitializeNetRoot)
    {
        PWCHAR pRootName;
        ULONG RootNameLength;
        int vboxRC;
        PSHFLSTRING ParsedPath = 0;

        Log(("VBOXSF: MRxCreateVNetRoot: initialize NET_ROOT\n"));

        pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;

        RootNameLength = pNetRoot->pNetRootName->Length - pSrvCall->pSrvCallName->Length;
        if (RootNameLength < sizeof(WCHAR))
        {
            /* Refuse a netroot path with an empty shared folder name */
            Log(("VBOXSF: MRxCreateVNetRoot: Empty shared folder name!\n"));
            pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_ERROR;

            Status = STATUS_BAD_NETWORK_NAME;
            goto l_Exit;
        }

        RootNameLength -= sizeof(WCHAR); /* Remove leading backslash. */
        pRootName = (PWCHAR)(pNetRoot->pNetRootName->Buffer + (pSrvCall->pSrvCallName->Length / sizeof(WCHAR)));
        pRootName++; /* Remove leading backslash. */

        /* Strip the trailing \0. Sometimes there is one, sometimes not... */
        if (   RootNameLength >= sizeof(WCHAR)
            && pRootName[RootNameLength / sizeof(WCHAR) - 1] == 0)
            RootNameLength -= sizeof(WCHAR);

        if (!pNetRootExtension->phgcmClient)
        {
            Log(("VBOXSF: MRxCreateVNetRoot: Initialize netroot length = %d, name = %.*ls\n",
                 RootNameLength, RootNameLength / sizeof(WCHAR), pRootName));

            Status = vbsfShflStringFromUnicodeAlloc(&ParsedPath, pRootName, (uint16_t)RootNameLength);
            if (Status != STATUS_SUCCESS)
            {
                goto l_Exit;
            }

            vboxRC = VbglR0SfMapFolder(&pDeviceExtension->hgcmClient, ParsedPath, &pNetRootExtension->map);
            vbsfFreeNonPagedMem(ParsedPath);
            if (vboxRC != VINF_SUCCESS)
            {
                Log(("VBOXSF: MRxCreateVNetRoot: VbglR0SfMapFolder failed with %d\n", vboxRC));
                Status = STATUS_BAD_NETWORK_NAME;
            }
            else
            {
                Status = STATUS_SUCCESS;
                pNetRootExtension->phgcmClient = &pDeviceExtension->hgcmClient;
            }
        }
    }
    else
        Log(("VBOXSF: MRxCreateVNetRoot: Creating V_NET_ROOT on existing NET_ROOT!\n"));

    vbsfUpdateNetRoot(pNetRoot);

l_Exit:
    if (Status != STATUS_PENDING)
    {
        Log(("VBOXSF: MRxCreateVNetRoot: Returning 0x%08X\n", Status));
        pCreateNetRootContext->VirtualNetRootStatus = Status;
        if (fInitializeNetRoot)
            pCreateNetRootContext->NetRootStatus = Status;
        else
            pCreateNetRootContext->NetRootStatus = STATUS_SUCCESS;

        /* Inform RDBSS. */
        pCreateNetRootContext->Callback(pCreateNetRootContext);

        /* RDBSS expects this. */
        Status = STATUS_PENDING;
    }

    Log(("VBOXSF: MRxCreateVNetRoot: Returned STATUS_PENDING\n"));
    return Status;
}
static int vboxvfs_mount(struct mount *mp, struct thread *td)
{
    int rc;
    char *pszShare;
    int  cbShare, cbOption;
    int uid = 0, gid = 0;
    struct sf_glob_info *pShFlGlobalInfo;
    SHFLSTRING *pShFlShareName = NULL;
    int cbShFlShareName;

    printf("%s: Enter\n", __FUNCTION__);

    if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
        return EOPNOTSUPP;

    if (vfs_filteropt(mp->mnt_optnew, vboxvfs_opts))
    {
        vfs_mount_error(mp, "%s", "Invalid option");
        return EINVAL;
    }

    rc = vfs_getopt(mp->mnt_optnew, "from", (void **)&pszShare, &cbShare);
    if (rc || pszShare[cbShare-1] != '\0' || cbShare > 0xfffe)
        return EINVAL;

    rc = vfs_getopt(mp->mnt_optnew, "gid", (void **)&gid, &cbOption);
    if ((rc != ENOENT) && (rc || cbOption != sizeof(gid)))
        return EINVAL;

    rc = vfs_getopt(mp->mnt_optnew, "uid", (void **)&uid, &cbOption);
    if ((rc != ENOENT) && (rc || cbOption != sizeof(uid)))
        return EINVAL;

    pShFlGlobalInfo = RTMemAllocZ(sizeof(struct sf_glob_info));
    if (!pShFlGlobalInfo)
        return ENOMEM;

    cbShFlShareName = offsetof (SHFLSTRING, String.utf8) + cbShare + 1;
    pShFlShareName  = RTMemAllocZ(cbShFlShareName);
    if (!pShFlShareName)
        return VERR_NO_MEMORY;

    pShFlShareName->u16Length = cbShare;
    pShFlShareName->u16Size   = cbShare + 1;
    memcpy (pShFlShareName->String.utf8, pszShare, cbShare + 1);

    rc = VbglR0SfMapFolder (&g_vboxSFClient, pShFlShareName, &pShFlGlobalInfo->map);
    RTMemFree(pShFlShareName);

    if (RT_FAILURE (rc))
    {
        RTMemFree(pShFlGlobalInfo);
        printf("VbglR0SfMapFolder failed rc=%d\n", rc);
        return EPROTO;
    }

    pShFlGlobalInfo->uid = uid;
    pShFlGlobalInfo->gid = gid;

    mp->mnt_data = pShFlGlobalInfo;

    /** @todo root vnode. */

    vfs_getnewfsid(mp);
    vfs_mountedfrom(mp, pszShare);

    printf("%s: Leave rc=0\n", __FUNCTION__);

    return 0;
}
Пример #4
0
/* allocate global info, try to map host share */
static int sf_glob_alloc(struct vbsf_mount_info_new *info, struct sf_glob_info **sf_gp)
{
    int err, rc;
    SHFLSTRING *str_name;
    size_t name_len, str_len;
    struct sf_glob_info *sf_g;

    TRACE();
    sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
    if (!sf_g)
    {
        err = -ENOMEM;
        LogRelFunc(("could not allocate memory for global info\n"));
        goto fail0;
    }

    RT_ZERO(*sf_g);

    if (   info->nullchar     != '\0'
        || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
        || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
        || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2)
    {
        /* An old version of mount.vboxsf made the syscall. Translate the
         * old parameters to the new structure. */
        struct vbsf_mount_info_old *info_old = (struct vbsf_mount_info_old *)info;
        static struct vbsf_mount_info_new info_compat;

        info = &info_compat;
        memset(info, 0, sizeof(*info));
        memcpy(&info->name, &info_old->name, MAX_HOST_NAME);
        memcpy(&info->nls_name, &info_old->nls_name, MAX_NLS_NAME);
        info->length = offsetof(struct vbsf_mount_info_new, dmode);
        info->uid    = info_old->uid;
        info->gid    = info_old->gid;
        info->ttl    = info_old->ttl;
    }

    info->name[sizeof(info->name) - 1] = 0;
    info->nls_name[sizeof(info->nls_name) - 1] = 0;

    name_len = strlen(info->name);
    if (name_len > 0xfffe)
    {
        err = -ENAMETOOLONG;
        LogFunc(("map name too big\n"));
        goto fail1;
    }

    str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
    str_name = kmalloc(str_len, GFP_KERNEL);
    if (!str_name)
    {
        err = -ENOMEM;
        LogRelFunc(("could not allocate memory for host name\n"));
        goto fail1;
    }

    str_name->u16Length = name_len;
    str_name->u16Size = name_len + 1;
    memcpy(str_name->String.utf8, info->name, name_len + 1);

#define _IS_UTF8(_str) \
    (strcmp(_str, "utf8") == 0)
#define _IS_EMPTY(_str) \
    (strcmp(_str, "") == 0)

    /* Check if NLS charset is valid and not points to UTF8 table */
    if (info->nls_name[0])
    {
        if (_IS_UTF8(info->nls_name))
            sf_g->nls = NULL;
        else
        {
            sf_g->nls = load_nls(info->nls_name);
            if (!sf_g->nls)
            {
                err = -EINVAL;
                LogFunc(("failed to load nls %s\n", info->nls_name));
                goto fail1;
            }
        }
    }
    else
    {
#ifdef CONFIG_NLS_DEFAULT
        /* If no NLS charset specified, try to load the default
         * one if it's not points to UTF8. */
        if (!_IS_UTF8(CONFIG_NLS_DEFAULT) && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
            sf_g->nls = load_nls_default();
        else
            sf_g->nls = NULL;
#else
        sf_g->nls = NULL;
#endif

#undef _IS_UTF8
#undef _IS_EMPTY
    }

    rc = VbglR0SfMapFolder(&client_handle, str_name, &sf_g->map);
    kfree(str_name);

    if (RT_FAILURE(rc))
    {
        err = -EPROTO;
        LogFunc(("VbglR0SfMapFolder failed rc=%d\n", rc));
        goto fail2;
    }

    sf_g->ttl = info->ttl;
    sf_g->uid = info->uid;
    sf_g->gid = info->gid;

    if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new))
    {
        /* new fields */
        sf_g->dmode = info->dmode;
        sf_g->fmode = info->fmode;
        sf_g->dmask = info->dmask;
        sf_g->fmask = info->fmask;
    }
    else
    {
        sf_g->dmode = ~0;
        sf_g->fmode = ~0;
    }

    *sf_gp = sf_g;
    return 0;

fail2:
    if (sf_g->nls)
        unload_nls(sf_g->nls);

fail1:
    kfree(sf_g);

fail0:
    return err;
}