VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/solaris/VBoxUSBHelper.cpp@ 32162

Last change on this file since 32162 was 31898, checked in by vboxsync, 14 years ago

OSE header fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.8 KB
Line 
1/** $Id: VBoxUSBHelper.cpp 31898 2010-08-24 09:28:43Z vboxsync $ */
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
39typedef enum AliasOp
40{
41 ADD_ALIAS = 12,
42 DEL_ALIAS
43} AliasOp;
44
45/**
46 * Print usage to stdout.
47 */
48static 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 - abormal termination of udpate_drv (not likely)
68 * -4 - update_drv failed (mostly trying to add already existing alias)
69 */
70static 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 */
134static 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 */
225int 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
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette