PERFORCE change 147174 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Mon Aug 11 19:47:03 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=147174
Change 147174 by hselasky at hselasky_laptop001 on 2008/08/11 19:46:17
Implement a set of IOCTLs that can change the permissions
on the USB root, bus, device and interface.
A permission is inactive when the mode is zero.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_core.h#16 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.c#23 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#20 edit
.. //depot/projects/usb/src/sys/dev/usb2/include/usb2_ioctl.h#11 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_core.h#16 (text+ko) ====
@@ -156,7 +156,6 @@
uint32_t uid;
uint32_t gid;
uint16_t mode;
- uint8_t active;
};
/*
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.c#23 (text+ko) ====
@@ -111,7 +111,6 @@
.uid = UID_ROOT,
.gid = GID_OPERATOR,
.mode = 0660,
- .active = 1,
};
static struct cdevsw usb2_devsw = {
@@ -238,7 +237,6 @@
iface->perm.uid = uid;
iface->perm.gid = gid;
iface->perm.mode = mode;
- iface->perm.active = 1;
mtx_unlock(&usb2_ref_lock);
}
@@ -246,6 +244,168 @@
}
/*------------------------------------------------------------------------*
+ * usb2_set_perm
+ *
+ * This function will set the permissions at the given level.
+ *
+ * Return values:
+ * 0: Success.
+ * Else: Failure.
+ *------------------------------------------------------------------------*/
+static int
+usb2_set_perm(struct usb2_dev_perm *psrc, uint8_t level)
+{
+ struct usb2_location loc;
+ struct usb2_perm *pdst;
+ uint32_t devloc;
+ int error;
+
+ /* only super-user can set permissions */
+ error = suser(curthread);
+ if (error) {
+ return (error);
+ }
+ if ((psrc->bus_index >= USB_BUS_MAX) ||
+ (psrc->dev_index >= USB_DEV_MAX) ||
+ (psrc->iface_index >= USB_IFACE_MAX)) {
+ return (EINVAL);
+ }
+ devloc = 0;
+ switch (level) {
+ case 3:
+ devloc += psrc->iface_index *
+ USB_DEV_MAX * USB_BUS_MAX;
+ /* FALLTHROUGH */
+ case 2:
+ devloc += psrc->dev_index *
+ USB_BUS_MAX;
+ /* FALLTHROUGH */
+ case 1:
+ devloc += psrc->bus_index;
+ break;
+ default:
+ break;
+ }
+
+ if ((level > 0) && (level < 4)) {
+ error = usb2_ref_device(NULL, &loc, devloc);
+ if (error) {
+ return (error);
+ }
+ }
+ switch (level) {
+ case 3:
+ pdst = &loc.iface->perm;
+ break;
+ case 2:
+ pdst = &loc.udev->perm;
+ break;
+ case 1:
+ pdst = &loc.bus->perm;
+ break;
+ default:
+ pdst = &usb2_perm;
+ break;
+ }
+
+ /* all permissions are protected by "usb2_ref_lock" */
+ mtx_lock(&usb2_ref_lock);
+ pdst->uid = psrc->user_id;
+ pdst->gid = psrc->group_id;
+ pdst->mode = psrc->mode;
+ mtx_unlock(&usb2_ref_lock);
+
+ if ((level > 0) && (level < 4)) {
+ usb2_unref_device(&loc);
+ }
+ return (0); /* success */
+}
+
+/*------------------------------------------------------------------------*
+ * usb2_get_perm
+ *
+ * This function will get the permissions at the given level.
+ *
+ * Return values:
+ * 0: Success.
+ * Else: Failure.
+ *------------------------------------------------------------------------*/
+static int
+usb2_get_perm(struct usb2_dev_perm *pdst, uint8_t level)
+{
+ struct usb2_location loc;
+ struct usb2_perm *psrc;
+ uint32_t devloc;
+ int error;
+
+ if ((pdst->bus_index >= USB_BUS_MAX) ||
+ (pdst->dev_index >= USB_DEV_MAX) ||
+ (pdst->iface_index >= USB_IFACE_MAX)) {
+ return (EINVAL);
+ }
+retry:
+ devloc = 0;
+ switch (level) {
+ case 3:
+ devloc += pdst->iface_index *
+ USB_DEV_MAX * USB_BUS_MAX;
+ /* FALLTHROUGH */
+ case 2:
+ devloc += pdst->dev_index *
+ USB_BUS_MAX;
+ /* FALLTHROUGH */
+ case 1:
+ devloc += pdst->bus_index;
+ break;
+ default:
+ break;
+ }
+
+ if ((level > 0) && (level < 4)) {
+ error = usb2_ref_device(NULL, &loc, devloc);
+ if (error) {
+ return (error);
+ }
+ }
+ switch (level) {
+ case 3:
+ psrc = &loc.iface->perm;
+ break;
+ case 2:
+ psrc = &loc.udev->perm;
+ break;
+ case 1:
+ psrc = &loc.bus->perm;
+ break;
+ default:
+ psrc = &usb2_perm;
+ break;
+ }
+
+ /* all permissions are protected by "usb2_ref_lock" */
+ mtx_lock(&usb2_ref_lock);
+ if (psrc->mode != 0) {
+ pdst->user_id = psrc->uid;
+ pdst->group_id = psrc->gid;
+ pdst->mode = psrc->mode;
+ error = 0;
+ } else {
+ error = EINVAL;
+ }
+ mtx_unlock(&usb2_ref_lock);
+
+ if ((level > 0) && (level < 4)) {
+ usb2_unref_device(&loc);
+ if (error) {
+ /* try to find the permission one level down */
+ level--;
+ goto retry;
+ }
+ }
+ return (error);
+}
+
+/*------------------------------------------------------------------------*
* usb2_match_perm
*
* This function will compare two permission structures and see if
@@ -260,7 +420,7 @@
{
uint16_t mode;
- if (psystem->active && puser->active) {
+ if ((psystem->mode != 0) && (puser->mode != 0)) {
/* continue */
} else {
return (0); /* no access */
@@ -962,9 +1122,6 @@
perm.mode |= 0444;
if (fflags & FWRITE)
perm.mode |= 0222;
- perm.active = 1;
-
- mtx_lock(udev->default_mtx);
/* scan down the permissions tree */
if ((ep_index != 0) && iface &&
@@ -984,7 +1141,6 @@
/* no access */
err = EPERM;
}
- mtx_unlock(udev->default_mtx);
return (err);
}
@@ -1108,16 +1264,44 @@
usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
int fflag, struct thread *td)
{
+ union {
+ struct usb2_read_dir *urd;
+ struct usb2_dev_perm *udp;
+ void *data;
+ } u;
int err;
+ u.data = data;
+
switch (cmd) {
- case USB_READ_DIR:{
- struct usb2_read_dir *urd = (void *)data;
-
- err = usb2_read_symlink(urd->urd_data,
- urd->urd_startentry, urd->urd_maxlen);
- break;
- }
+ case USB_READ_DIR:
+ err = usb2_read_symlink(u.urd->urd_data,
+ u.urd->urd_startentry, u.urd->urd_maxlen);
+ break;
+ case USB_SET_IFACE_PERM:
+ err = usb2_set_perm(u.udp, 3);
+ break;
+ case USB_SET_DEVICE_PERM:
+ err = usb2_set_perm(u.udp, 2);
+ break;
+ case USB_SET_BUS_PERM:
+ err = usb2_set_perm(u.udp, 1);
+ break;
+ case USB_SET_ROOT_PERM:
+ err = usb2_set_perm(u.udp, 0);
+ break;
+ case USB_GET_IFACE_PERM:
+ err = usb2_get_perm(u.udp, 3);
+ break;
+ case USB_GET_DEVICE_PERM:
+ err = usb2_get_perm(u.udp, 2);
+ break;
+ case USB_GET_BUS_PERM:
+ err = usb2_get_perm(u.udp, 1);
+ break;
+ case USB_GET_ROOT_PERM:
+ err = usb2_get_perm(u.udp, 0);
+ break;
default:
err = ENOTTY;
break;
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#20 (text+ko) ====
@@ -470,7 +470,7 @@
iface->idesc = NULL;
iface->alt_index = 0;
iface->parent_iface_index = USB_IFACE_INDEX_ANY;
- iface->perm.active = 0; /* disable permissions */
+ iface->perm.mode = 0; /* disable permissions */
iface++;
}
==== //depot/projects/usb/src/sys/dev/usb2/include/usb2_ioctl.h#11 (text+ko) ====
@@ -180,6 +180,18 @@
uint8_t ep_index;
};
+struct usb2_dev_perm {
+ /* Permissions */
+ uint16_t user_id;
+ uint16_t group_id;
+ uint16_t mode;
+
+ /* Device location */
+ uint16_t bus_index;
+ uint16_t dev_index;
+ uint16_t iface_index;
+};
+
/* USB controller */
#define USB_REQUEST _IOWR('U', 1, struct usb2_ctl_request)
#define USB_SETDEBUG _IOW ('U', 2, int)
@@ -222,10 +234,18 @@
#define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int)
#define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t)
#define USB_READ_DIR _IOW ('U', 127, struct usb2_read_dir)
+#define USB_SET_ROOT_PERM _IOW ('U', 128, struct usb2_dev_perm)
+#define USB_SET_BUS_PERM _IOW ('U', 129, struct usb2_dev_perm)
+#define USB_SET_DEVICE_PERM _IOW ('U', 130, struct usb2_dev_perm)
+#define USB_SET_IFACE_PERM _IOW ('U', 131, struct usb2_dev_perm)
+#define USB_GET_ROOT_PERM _IOW ('U', 132, struct usb2_dev_perm)
+#define USB_GET_BUS_PERM _IOW ('U', 133, struct usb2_dev_perm)
+#define USB_GET_DEVICE_PERM _IOW ('U', 134, struct usb2_dev_perm)
+#define USB_GET_IFACE_PERM _IOW ('U', 135, struct usb2_dev_perm)
/* Modem device */
-#define USB_GET_CM_OVER_DATA _IOR ('U', 130, int)
-#define USB_SET_CM_OVER_DATA _IOW ('U', 131, int)
+#define USB_GET_CM_OVER_DATA _IOR ('U', 160, int)
+#define USB_SET_CM_OVER_DATA _IOW ('U', 161, int)
/* USB file system interface */
#define USB_FS_START _IOW ('U', 192, struct usb2_fs_start)
More information about the p4-projects
mailing list