1
/** $Id: VBoxUSBHelper.cpp $ */
3
* VBoxUSBHelper, setuid binary wrapper for dynamic driver alias updating.
7
* Copyright (C) 2008-2009 Oracle Corporation
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.
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).
23
* Later maybe we can change this to hardcode aliases to prefix "usb" and then
24
* hardcode the driver as "ugen".
27
/*******************************************************************************
29
*******************************************************************************/
35
#include <libdevice.h>
46
* Print usage to stdout.
48
static void Usage(char *pszName)
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");
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");
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)
70
static int UpdateDrv(AliasOp Op, char *pszAlias, char *pszDrv)
73
sprintf(szAlias, "\"%s\"", pszAlias);
75
/* Store current user ID and raise privilege. */
76
uid_t userID = getuid();
79
/* For adding alias add the driver once to make sure we can update alias, no error checking needed. */
82
char szAddDrvCmd[512];
83
sprintf(szAddDrvCmd, "/usr/sbin/add_drv %s\n", pszDrv);
87
/* Update the alias. */
90
pszArgs[0] = "/usr/sbin/update_drv";
91
pszArgs[1] = (char *)(Op == ADD_ALIAS ? "-a" : "-d");
93
pszArgs[3] = pszAlias;
96
pid_t processID = fork();
99
/* Bad. fork() failed! */
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);
110
/* Parent process. */
112
while (waitpid(processID, &result, 0) < 0)
114
if (!WIFEXITED(result)) /* abnormally terminated. */
116
if (WEXITSTATUS(result) != 0) /* non-zero exit status. */
119
/* Restore user ID. */
122
fprintf(stdout, "rc=%d result=%d\n", rc, result);
127
* Return code legend:
129
* -1 - no root permission
130
* -2 - invalid USB device path
131
* -3 - failed to acquire devctl_handle
132
* -4 - failed to reset
134
static int ResetDev(char *pszDevicePath, bool fHardReset)
136
/* Convert the di_node device path into a devctl compatible Ap-Id. */
137
char szApId[PATH_MAX + 1];
138
char *pszPort = NULL;
142
syslog(LOG_ERR, "VBosUSBHelper: given path=%s\n", pszDevicePath);
144
strcpy(szApId, "/devices");
145
strcat(szApId, pszDevicePath);
146
pszPort = strrchr(pszDevicePath, '@');
150
pszDir = strrchr(szApId, '/');
155
strcat(szApId, pszPort);
157
/* Acquire devctl handle. */
158
devctl_hdl_t pDevHandle;
159
pDevHandle = devctl_ap_acquire(szApId, 0);
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));
167
/* Reset the device */
168
rc = devctl_ap_unconfigure(pDevHandle, pValueList);
172
rc = devctl_ap_disconnect(pDevHandle, pValueList);
177
rc = devctl_ap_connect(pDevHandle, pValueList);
181
rc = devctl_ap_configure(pDevHandle, pValueList);
183
syslog(LOG_ERR, "VBoxUSBHelper: Configuring %s failed. rc=%d errno=%d\n", szApId, rc, errno);
186
syslog(LOG_ERR, "VBoxUSBHelper: Connecting %s failed. rc=%d errno=%d\n", szApId, rc, errno);
189
syslog(LOG_ERR, "VBoxUSBHelper: Disconnecting for %s failed. rc=%d errno=%d\n", szApId, rc, errno);
192
syslog(LOG_ERR, "VBoxUSBHelper: Unconfigure for %s failed. rc=%d errno=%d\n", szApId, rc, errno);
197
/* Free-up the name-value list and the obtained handle. */
198
nvlist_free(pValueList);
199
devctl_release(pDevHandle);
203
syslog(LOG_ERR, "VBoxUSBHelper: devctl_ap_acquire for %s failed. errno=%d\n", szApId, errno);
209
syslog(LOG_ERR, "VBoxUSBHelper: invalid device %s\n", pszDevicePath);
215
syslog(LOG_ERR, "VBoxUSBHelper: invalid device %s\n", pszDevicePath);
218
fprintf(stdout, "rc=%d\n", rc);
223
* returns error code from UpdateDrv. See UpdateDrv error codes.
225
int main(int argc, char *argv[])
227
/* Check root permissions. */
230
fprintf(stderr, "This program needs administrator privileges.\n");
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;
256
char *pszAlias = argv[2];
257
char *pszDrv = argv[3];
258
/* Return status from update_drv */
259
return UpdateDrv(Operation, pszAlias, pszDrv);