usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)
This commit is contained in:
parent
646ec82800
commit
7e156f0d65
|
@ -673,6 +673,8 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch
|
|||
|
||||
Patch800: linux-2.6-crash-driver.patch
|
||||
|
||||
Patch1000: usb-wwan-ioctls.patch
|
||||
|
||||
# crypto/
|
||||
|
||||
# virt + ksm patches
|
||||
|
@ -1453,6 +1455,9 @@ ApplyPatch create-sys-fs-cgroup-to-mount-cgroupfs-on.patch
|
|||
# /dev/crash driver.
|
||||
ApplyPatch linux-2.6-crash-driver.patch
|
||||
|
||||
# usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)
|
||||
ApplyPatch usb-wwan-ioctls.patch
|
||||
|
||||
# Hack e1000e to work on Montevina SDV
|
||||
ApplyPatch linux-2.6-e1000-ich9-montevina.patch
|
||||
|
||||
|
@ -2265,6 +2270,9 @@ fi
|
|||
# and build.
|
||||
|
||||
%changelog
|
||||
* Tue Oct 11 2011 Dave Jones <davej@redhat.com>
|
||||
- usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)
|
||||
|
||||
* Fri Sep 23 2011 Josh Boyer <jwboyer@redhat.com> 2.6.35.14-98
|
||||
- CVE-2011-1161 CVE-2011-1161: tpm: infoleaks
|
||||
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
commit 02303f73373aa1da19dbec510ec5a4e2576f9610
|
||||
Author: Dan Williams <dcbw@redhat.com>
|
||||
Date: Fri Nov 19 16:04:00 2010 -0600
|
||||
|
||||
usb-wwan: implement TIOCGSERIAL and TIOCSSERIAL to avoid blocking close(2)
|
||||
|
||||
Some devices (ex ZTE 2726) simply don't respond at all when data is sent
|
||||
to some of their USB interfaces. The data gets stuck in the TTYs queue
|
||||
and sits there until close(2), which them blocks because closing_wait
|
||||
defaults to 30 seconds (even though the fd is O_NONBLOCK). This is
|
||||
rarely desired. Implement the standard mechanism to adjust closing_wait
|
||||
and let applications handle it how they want to.
|
||||
|
||||
Signed-off-by: Dan Williams <dcbw@redhat.com>
|
||||
|
||||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
||||
index 2297fb1..2a56cc3 100644
|
||||
--- a/drivers/usb/serial/option.c
|
||||
+++ b/drivers/usb/serial/option.c
|
||||
@@ -989,6 +989,7 @@ static struct usb_serial_driver option_1port_device = {
|
||||
.set_termios = usb_wwan_set_termios,
|
||||
.tiocmget = usb_wwan_tiocmget,
|
||||
.tiocmset = usb_wwan_tiocmset,
|
||||
+ .ioctl = usb_wwan_ioctl,
|
||||
.attach = usb_wwan_startup,
|
||||
.disconnect = usb_wwan_disconnect,
|
||||
.release = usb_wwan_release,
|
||||
diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
|
||||
index 2be298a..3ab77c5 100644
|
||||
--- a/drivers/usb/serial/usb-wwan.h
|
||||
+++ b/drivers/usb/serial/usb-wwan.h
|
||||
@@ -18,6 +18,8 @@ extern void usb_wwan_set_termios(struct tty_struct *tty,
|
||||
extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file);
|
||||
extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
unsigned int set, unsigned int clear);
|
||||
+extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
|
||||
+ unsigned int cmd, unsigned long arg);
|
||||
extern int usb_wwan_send_setup(struct usb_serial_port *port);
|
||||
extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||
const unsigned char *buf, int count);
|
||||
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
|
||||
index fbc9467..660b7ca 100644
|
||||
--- a/drivers/usb/serial/usb_wwan.c
|
||||
+++ b/drivers/usb/serial/usb_wwan.c
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/serial.h>
|
||||
+#include <linux/serial.h>
|
||||
#include "usb-wwan.h"
|
||||
|
||||
static int debug;
|
||||
@@ -123,6 +124,83 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
|
||||
}
|
||||
EXPORT_SYMBOL(usb_wwan_tiocmset);
|
||||
|
||||
+static int get_serial_info(struct usb_serial_port *port,
|
||||
+ struct serial_struct __user *retinfo)
|
||||
+{
|
||||
+ struct serial_struct tmp;
|
||||
+
|
||||
+ if (!retinfo)
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ memset(&tmp, 0, sizeof(tmp));
|
||||
+ tmp.line = port->serial->minor;
|
||||
+ tmp.port = port->number;
|
||||
+ tmp.baud_base = tty_get_baud_rate(port->port.tty);
|
||||
+ tmp.close_delay = port->port.close_delay / 10;
|
||||
+ tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
|
||||
+ ASYNC_CLOSING_WAIT_NONE :
|
||||
+ port->port.closing_wait / 10;
|
||||
+
|
||||
+ if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
+ return -EFAULT;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int set_serial_info(struct usb_serial_port *port,
|
||||
+ struct serial_struct __user *newinfo)
|
||||
+{
|
||||
+ struct serial_struct new_serial;
|
||||
+ unsigned int closing_wait, close_delay;
|
||||
+ int retval = 0;
|
||||
+
|
||||
+ if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ close_delay = new_serial.close_delay * 10;
|
||||
+ closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
|
||||
+ ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10;
|
||||
+
|
||||
+ mutex_lock(&port->port.mutex);
|
||||
+
|
||||
+ if (!capable(CAP_SYS_ADMIN)) {
|
||||
+ if ((close_delay != port->port.close_delay) ||
|
||||
+ (closing_wait != port->port.closing_wait))
|
||||
+ retval = -EPERM;
|
||||
+ else
|
||||
+ retval = -EOPNOTSUPP;
|
||||
+ } else {
|
||||
+ port->port.close_delay = close_delay;
|
||||
+ port->port.closing_wait = closing_wait;
|
||||
+ }
|
||||
+
|
||||
+ mutex_unlock(&port->port.mutex);
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
|
||||
+ unsigned int cmd, unsigned long arg)
|
||||
+{
|
||||
+ struct usb_serial_port *port = tty->driver_data;
|
||||
+
|
||||
+ dbg("%s cmd 0x%04x", __func__, cmd);
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case TIOCGSERIAL:
|
||||
+ return get_serial_info(port,
|
||||
+ (struct serial_struct __user *) arg);
|
||||
+ case TIOCSSERIAL:
|
||||
+ return set_serial_info(port,
|
||||
+ (struct serial_struct __user *) arg);
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ dbg("%s arg not supported", __func__);
|
||||
+
|
||||
+ return -ENOIOCTLCMD;
|
||||
+}
|
||||
+EXPORT_SYMBOL(usb_wwan_ioctl);
|
||||
+
|
||||
/* Write */
|
||||
int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||
const unsigned char *buf, int count)
|
Loading…
Reference in New Issue