~ubuntu-branches/ubuntu/precise/virtualbox/precise-updates

« back to all changes in this revision

Viewing changes to src/VBox/HostDrivers/VBoxUSB/solaris/VBoxUSBHelper.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-07-04 13:02:31 UTC
  • mfrom: (3.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110704130231-l843es6wqhx614n7
Tags: 4.0.10-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Add the Modaliases control field manually for maximum backportability.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** $Id: VBoxUSBHelper.cpp $ */
2
 
/** @file
3
 
 * VBoxUSBHelper, setuid binary wrapper for dynamic driver alias updating.
4
 
 */
5
 
 
6
 
/*
7
 
 * Copyright (C) 2008-2009 Oracle Corporation
8
 
 *
9
 
 * This file is part of VirtualBox Open Source Edition (OSE), as
10
 
 * available from http://www.virtualbox.org. This file is free software;
11
 
 * you can redistribute it and/or modify it under the terms of the GNU
12
 
 * General Public License (GPL) as published by the Free Software
13
 
 * Foundation, in version 2 as it comes in the "COPYING" file of the
14
 
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
 
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16
 
 */
17
 
 
18
 
/*
19
 
 * I think it is currently a security risk using VBoxUSBHelper. By that I mean
20
 
 * here we have an application that can add/remove driver aliases in a generic
21
 
 * fashion without requiring root privileges (well setuid).
22
 
 *
23
 
 * Later maybe we can change this to hardcode aliases to prefix "usb" and then
24
 
 * hardcode the driver as "ugen".
25
 
 */
26
 
 
27
 
/*******************************************************************************
28
 
*   Header Files                                                               *
29
 
*******************************************************************************/
30
 
#include <stdio.h>
31
 
#include <unistd.h>
32
 
#include <stdlib.h>
33
 
#include <string.h>
34
 
#include <limits.h>
35
 
#include <libdevice.h>
36
 
#include <errno.h>
37
 
#include <syslog.h>
38
 
 
39
 
typedef enum AliasOp
40
 
{
41
 
    ADD_ALIAS = 12,
42
 
    DEL_ALIAS
43
 
} AliasOp;
44
 
 
45
 
/**
46
 
 * Print usage to stdout.
47
 
 */
48
 
static void Usage(char *pszName)
49
 
{
50
 
    /* @todo Eventually remove the usage syntax display & only display the copyright and warning. */
51
 
    fprintf(stderr, "Oracle VM VirtualBox USB Helper\nCopyright (C) Oracle Corporation\n\n");
52
 
#if 0
53
 
    fprintf(stderr, "Usage:\n");
54
 
    fprintf(stderr, "Add:    %s add <alias> <drivername>\n", pszName);
55
 
    fprintf(stderr, "Delete: %s del <alias> <drivername>\n", pszName);
56
 
    fprintf(stderr, "Config: %s cfg <device>\n\n", pszName);
57
 
    fprintf(stderr, "Warning!! This program is internally used by VirtualBox and not meant to be used directly.\n");
58
 
#endif
59
 
    exit(-1);
60
 
}
61
 
 
62
 
/**
63
 
 * Return code legend:
64
 
 *      0 - success.
65
 
 *     -1 - no root permission
66
 
 *     -2 - insufficient arguments
67
 
 *     -3 - abnormal termination of update_drv (not likely)
68
 
 *     -4 - update_drv failed (mostly trying to add already existing alias)
69
 
 */
70
 
static int UpdateDrv(AliasOp Op, char *pszAlias, char *pszDrv)
71
 
{
72
 
    char szAlias[256];
73
 
    sprintf(szAlias, "\"%s\"", pszAlias);
74
 
 
75
 
    /* Store current user ID and raise privilege. */
76
 
    uid_t userID = getuid();
77
 
    setuid(0);
78
 
 
79
 
    /* For adding alias add the driver once to make sure we can update alias, no error checking needed. */
80
 
    if (Op == ADD_ALIAS)
81
 
    {
82
 
        char szAddDrvCmd[512];
83
 
        sprintf(szAddDrvCmd, "/usr/sbin/add_drv %s\n", pszDrv);
84
 
        system(szAddDrvCmd);
85
 
    }
86
 
 
87
 
    /* Update the alias. */
88
 
    char *pszArgs[6];
89
 
    int rc = 0;
90
 
    pszArgs[0] = "/usr/sbin/update_drv";
91
 
    pszArgs[1] = (char *)(Op == ADD_ALIAS ? "-a" : "-d");
92
 
    pszArgs[2] = "-i";
93
 
    pszArgs[3] = pszAlias;
94
 
    pszArgs[4] = pszDrv;
95
 
    pszArgs[5] = NULL;
96
 
    pid_t processID = fork();
97
 
    if (processID < 0)
98
 
    {
99
 
        /* Bad. fork() failed! */
100
 
        rc = -2;
101
 
    }
102
 
    if (processID == 0)
103
 
    {
104
 
        /* Child process. */
105
 
        syslog(LOG_ERR, "VBoxUSBHelper: %s %s %s %s %s\n", pszArgs[0], pszArgs[1], pszArgs[2], pszArgs[3], pszArgs[4]);
106
 
        execv(pszArgs[0], pszArgs);
107
 
        _exit(1);
108
 
    }
109
 
 
110
 
    /* Parent process. */
111
 
    int result;
112
 
    while (waitpid(processID, &result, 0) < 0)
113
 
        ;
114
 
    if (!WIFEXITED(result))         /* abnormally terminated. */
115
 
        rc = -3;
116
 
    if (WEXITSTATUS(result) != 0)   /* non-zero exit status. */
117
 
        rc = -4;
118
 
 
119
 
    /* Restore user ID. */
120
 
    setuid(userID);
121
 
 
122
 
    fprintf(stdout, "rc=%d result=%d\n", rc, result);
123
 
    return rc;
124
 
}
125
 
 
126
 
/**
127
 
 * Return code legend:
128
 
 *      0 - success.
129
 
 *     -1 - no root permission
130
 
 *     -2 - invalid USB device path
131
 
 *     -3 - failed to acquire devctl_handle
132
 
 *     -4 - failed to reset
133
 
 */
134
 
static int ResetDev(char *pszDevicePath, bool fHardReset)
135
 
{
136
 
    /* Convert the di_node device path into a devctl compatible Ap-Id. */
137
 
    char szApId[PATH_MAX + 1];
138
 
    char *pszPort = NULL;
139
 
    char *pszDir = NULL;
140
 
    int rc = 0;
141
 
 
142
 
    syslog(LOG_ERR, "VBosUSBHelper: given path=%s\n", pszDevicePath);
143
 
 
144
 
    strcpy(szApId, "/devices");
145
 
    strcat(szApId, pszDevicePath);
146
 
    pszPort = strrchr(pszDevicePath, '@');
147
 
    if (pszPort)
148
 
    {
149
 
        pszPort++;
150
 
        pszDir = strrchr(szApId, '/');
151
 
        if (pszDir)
152
 
        {
153
 
            pszDir[0] = '\0';
154
 
            strcat(szApId, ":");
155
 
            strcat(szApId, pszPort);
156
 
 
157
 
            /* Acquire devctl handle. */
158
 
            devctl_hdl_t pDevHandle;
159
 
            pDevHandle = devctl_ap_acquire(szApId, 0);
160
 
            if (pDevHandle)
161
 
            {
162
 
                /* Prepare to configure. */
163
 
                nvlist_t *pValueList = NULL;
164
 
                nvlist_alloc(&pValueList, NV_UNIQUE_NAME_TYPE, NULL);
165
 
                nvlist_add_int32(pValueList, "port", atoi(pszPort));
166
 
 
167
 
                /* Reset the device */
168
 
                rc = devctl_ap_unconfigure(pDevHandle, pValueList);
169
 
                if (!rc)
170
 
                {
171
 
                    if (fHardReset)
172
 
                        rc = devctl_ap_disconnect(pDevHandle, pValueList);
173
 
 
174
 
                    if (!rc)
175
 
                    {
176
 
                        if (fHardReset)
177
 
                            rc = devctl_ap_connect(pDevHandle, pValueList);
178
 
 
179
 
                        if (!rc)
180
 
                        {
181
 
                            rc = devctl_ap_configure(pDevHandle, pValueList);
182
 
                            if (rc)
183
 
                                syslog(LOG_ERR, "VBoxUSBHelper: Configuring %s failed. rc=%d errno=%d\n", szApId, rc, errno);
184
 
                        }
185
 
                        else
186
 
                            syslog(LOG_ERR, "VBoxUSBHelper: Connecting %s failed. rc=%d errno=%d\n", szApId, rc, errno);
187
 
                    }
188
 
                    else
189
 
                        syslog(LOG_ERR, "VBoxUSBHelper: Disconnecting for %s failed. rc=%d errno=%d\n", szApId, rc, errno);
190
 
                }
191
 
                else
192
 
                    syslog(LOG_ERR, "VBoxUSBHelper: Unconfigure for %s failed. rc=%d errno=%d\n", szApId, rc, errno);
193
 
 
194
 
                if (rc)
195
 
                    rc = -4;
196
 
 
197
 
                /* Free-up the name-value list and the obtained handle. */
198
 
                nvlist_free(pValueList);
199
 
                devctl_release(pDevHandle);
200
 
            }
201
 
            else
202
 
            {
203
 
                syslog(LOG_ERR, "VBoxUSBHelper: devctl_ap_acquire for %s failed. errno=%d\n", szApId, errno);
204
 
                rc = -3;
205
 
            }
206
 
        }
207
 
        else
208
 
        {
209
 
            syslog(LOG_ERR, "VBoxUSBHelper: invalid device %s\n", pszDevicePath);
210
 
            rc = -1;
211
 
        }
212
 
    }
213
 
    else
214
 
    {
215
 
        syslog(LOG_ERR, "VBoxUSBHelper: invalid device %s\n", pszDevicePath);
216
 
        rc = -1;
217
 
    }
218
 
    fprintf(stdout, "rc=%d\n", rc);
219
 
    return rc;
220
 
}
221
 
 
222
 
/**
223
 
 * returns error code from UpdateDrv. See UpdateDrv error codes.
224
 
 */
225
 
int main(int argc, char *argv[])
226
 
{
227
 
    /* Check root permissions. */
228
 
    if (geteuid() != 0)
229
 
    {
230
 
        fprintf(stderr, "This program needs administrator privileges.\n");
231
 
        return -1;
232
 
    }
233
 
 
234
 
    if (argc < 3)
235
 
    {
236
 
        Usage(argv[0]);
237
 
        return -2;
238
 
    }
239
 
 
240
 
    AliasOp Operation = ADD_ALIAS;
241
 
    char *pszOp = argv[1];
242
 
    if (!strcasecmp(pszOp, "hardreset"))
243
 
        return ResetDev(argv[2], true);
244
 
    else if (!strcasecmp(pszOp, "softreset"))
245
 
        return ResetDev(argv[2], false);
246
 
    else if (!strcasecmp(pszOp, "del"))
247
 
        Operation = DEL_ALIAS;
248
 
    else if (!strcasecmp(pszOp, "add"))
249
 
        Operation = ADD_ALIAS;
250
 
    else
251
 
    {
252
 
        Usage(argv[0]);
253
 
        return -2;
254
 
    }
255
 
 
256
 
    char *pszAlias = argv[2];
257
 
    char *pszDrv = argv[3];
258
 
    /* Return status from update_drv */
259
 
    return UpdateDrv(Operation, pszAlias, pszDrv);
260
 
}
261