Skip to content

Commit

Permalink
usbip: prevent vhci_hcd driver from leaking a socket pointer address
Browse files Browse the repository at this point in the history
commit 2f2d008 upstream.

When a client has a USB device attached over IP, the vhci_hcd driver is
locally leaking a socket pointer address via the

/sys/devices/platform/vhci_hcd/status file (world-readable) and in debug
output when "usbip --debug port" is run.

Fix it to not leak. The socket pointer address is not used at the moment
and it was made visible as a convenient way to find IP address from socket
pointer address by looking up /proc/net/{tcp,tcp6}.

As this opens a security hole, the fix replaces socket pointer address with
sockfd.

Reported-by: Secunia Research <vuln@secunia.com>
Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[bwh: Backported to 3.2:
 - usbip port status does not include hub type
 - Adjust filenames, context, indentation]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
  • Loading branch information
Shuah Khan authored and Ben Hutchings committed Feb 13, 2018
1 parent 629f509 commit 1140602
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 11 deletions.
1 change: 1 addition & 0 deletions drivers/staging/usbip/usbip_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ struct usbip_device {
/* lock for status */
spinlock_t lock;

int sockfd;
struct socket *tcp_socket;

struct task_struct *tcp_rx;
Expand Down
8 changes: 4 additions & 4 deletions drivers/staging/usbip/userspace/libsrc/vhci_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ static int parse_status(char *value)

while (*c != '\0') {
int port, status, speed, devid;
unsigned long socket;
int sockfd;
char lbusid[SYSFS_BUS_ID_SIZE];

ret = sscanf(c, "%d %d %d %x %lx %31s\n",
ret = sscanf(c, "%d %d %d %x %u %31s\n",
&port, &status, &speed,
&devid, &socket, lbusid);
&devid, &sockfd, lbusid);

if (ret < 5) {
dbg("sscanf failed: %d", ret);
Expand All @@ -77,7 +77,7 @@ static int parse_status(char *value)

dbg("port %d status %d speed %d devid %x",
port, status, speed, devid);
dbg("socket %lx lbusid %s", socket, lbusid);
dbg("sockfd %u lbusid %s", sockfd, lbusid);


/* if a device is connected, look at it */
Expand Down
20 changes: 13 additions & 7 deletions drivers/staging/usbip/vhci_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,18 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr,

/*
* output example:
* prt sta spd dev socket local_busid
* 000 004 000 000 c5a7bb80 1-2.3
* 001 004 000 000 d8cee980 2-3.4
* prt sta spd dev sockfd local_busid
* 000 004 000 000 3 1-2.3
* 001 004 000 000 4 2-3.4
*
* Output includes socket fd instead of socket pointer address to avoid
* leaking kernel memory address in:
* /sys/devices/platform/vhci_hcd.0/status and in debug output.
* The socket pointer address is not used at the moment and it was made
* visible as a convenient way to find IP address from socket pointer
* address by looking up /proc/net/{tcp,tcp6}. As this opens a security
* hole, the change is made to use sockfd instead.
*
* IP address can be retrieved from a socket pointer address by looking
* up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
* port number and its peer IP address.
*/
out += sprintf(out, "prt sta spd bus dev socket "
"local_busid\n");
Expand All @@ -58,7 +63,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr,
if (vdev->ud.status == VDEV_ST_USED) {
out += sprintf(out, "%03u %08x ",
vdev->speed, vdev->devid);
out += sprintf(out, "%16p ", vdev->ud.tcp_socket);
out += sprintf(out, "%u", vdev->ud.sockfd);
out += sprintf(out, "%s", dev_name(&vdev->udev->dev));

} else {
Expand Down Expand Up @@ -215,6 +220,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,

vdev->devid = devid;
vdev->speed = speed;
vdev->ud.sockfd = sockfd;
vdev->ud.tcp_socket = socket;
vdev->ud.status = VDEV_ST_NOTASSIGNED;

Expand Down

0 comments on commit 1140602

Please sign in to comment.