Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: convert tty_ldisc_ops 'read()' function to take a kernel pointer

The tty line discipline .read() function was passed the final user
pointer destination as an argument, which doesn't match the 'write()'
function, and makes it very inconvenient to do a splice method for
ttys.

This is a conversion to use a kernel buffer instead.

NOTE! It does this by passing the tty line discipline ->read() function
an additional "cookie" to fill in, and an offset into the cookie data.

The line discipline can fill in the cookie data with its own private
information, and then the reader will repeat the read until either the
cookie is cleared or it runs out of data.

The only real user of this is N_HDLC, which can use this to handle big
packets, even if the kernel buffer is smaller than the whole packet.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+178 -102
+17 -17
drivers/bluetooth/hci_ldisc.c
··· 802 802 * We don't provide read/write/poll interface for user space. 803 803 */ 804 804 static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, 805 - unsigned char __user *buf, size_t nr) 805 + unsigned char *buf, size_t nr, 806 + void **cookie, unsigned long offset) 806 807 { 807 808 return 0; 808 809 } ··· 820 819 return 0; 821 820 } 822 821 822 + static struct tty_ldisc_ops hci_uart_ldisc = { 823 + .owner = THIS_MODULE, 824 + .magic = TTY_LDISC_MAGIC, 825 + .name = "n_hci", 826 + .open = hci_uart_tty_open, 827 + .close = hci_uart_tty_close, 828 + .read = hci_uart_tty_read, 829 + .write = hci_uart_tty_write, 830 + .ioctl = hci_uart_tty_ioctl, 831 + .compat_ioctl = hci_uart_tty_ioctl, 832 + .poll = hci_uart_tty_poll, 833 + .receive_buf = hci_uart_tty_receive, 834 + .write_wakeup = hci_uart_tty_wakeup, 835 + }; 836 + 823 837 static int __init hci_uart_init(void) 824 838 { 825 - static struct tty_ldisc_ops hci_uart_ldisc; 826 839 int err; 827 840 828 841 BT_INFO("HCI UART driver ver %s", VERSION); 829 842 830 843 /* Register the tty discipline */ 831 - 832 - memset(&hci_uart_ldisc, 0, sizeof(hci_uart_ldisc)); 833 - hci_uart_ldisc.magic = TTY_LDISC_MAGIC; 834 - hci_uart_ldisc.name = "n_hci"; 835 - hci_uart_ldisc.open = hci_uart_tty_open; 836 - hci_uart_ldisc.close = hci_uart_tty_close; 837 - hci_uart_ldisc.read = hci_uart_tty_read; 838 - hci_uart_ldisc.write = hci_uart_tty_write; 839 - hci_uart_ldisc.ioctl = hci_uart_tty_ioctl; 840 - hci_uart_ldisc.compat_ioctl = hci_uart_tty_ioctl; 841 - hci_uart_ldisc.poll = hci_uart_tty_poll; 842 - hci_uart_ldisc.receive_buf = hci_uart_tty_receive; 843 - hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup; 844 - hci_uart_ldisc.owner = THIS_MODULE; 845 - 846 844 err = tty_register_ldisc(N_HCI, &hci_uart_ldisc); 847 845 if (err) { 848 846 BT_ERR("HCI line discipline registration failed. (%d)", err);
+3 -1
drivers/input/serio/serport.c
··· 156 156 * returning 0 characters. 157 157 */ 158 158 159 - static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr) 159 + static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, 160 + unsigned char *kbuf, size_t nr, 161 + void **cookie, unsigned long offset) 160 162 { 161 163 struct serport *serport = (struct serport*) tty->disc_data; 162 164 struct serio *serio;
+2 -1
drivers/net/ppp/ppp_async.c
··· 259 259 */ 260 260 static ssize_t 261 261 ppp_asynctty_read(struct tty_struct *tty, struct file *file, 262 - unsigned char __user *buf, size_t count) 262 + unsigned char *buf, size_t count, 263 + void **cookie, unsigned long offset) 263 264 { 264 265 return -EAGAIN; 265 266 }
+2 -1
drivers/net/ppp/ppp_synctty.c
··· 257 257 */ 258 258 static ssize_t 259 259 ppp_sync_read(struct tty_struct *tty, struct file *file, 260 - unsigned char __user *buf, size_t count) 260 + unsigned char *buf, size_t count, 261 + void **cookie, unsigned long offset) 261 262 { 262 263 return -EAGAIN; 263 264 }
+2 -1
drivers/tty/n_gsm.c
··· 2557 2557 */ 2558 2558 2559 2559 static ssize_t gsmld_read(struct tty_struct *tty, struct file *file, 2560 - unsigned char __user *buf, size_t nr) 2560 + unsigned char *buf, size_t nr, 2561 + void **cookie, unsigned long offset) 2561 2562 { 2562 2563 return -EOPNOTSUPP; 2563 2564 }
+41 -19
drivers/tty/n_hdlc.c
··· 416 416 * Returns the number of bytes returned or error code. 417 417 */ 418 418 static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, 419 - __u8 __user *buf, size_t nr) 419 + __u8 *kbuf, size_t nr, 420 + void **cookie, unsigned long offset) 420 421 { 421 422 struct n_hdlc *n_hdlc = tty->disc_data; 422 423 int ret = 0; 423 424 struct n_hdlc_buf *rbuf; 424 425 DECLARE_WAITQUEUE(wait, current); 426 + 427 + /* Is this a repeated call for an rbuf we already found earlier? */ 428 + rbuf = *cookie; 429 + if (rbuf) 430 + goto have_rbuf; 425 431 426 432 add_wait_queue(&tty->read_wait, &wait); 427 433 ··· 442 436 set_current_state(TASK_INTERRUPTIBLE); 443 437 444 438 rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); 445 - if (rbuf) { 446 - if (rbuf->count > nr) { 447 - /* too large for caller's buffer */ 448 - ret = -EOVERFLOW; 449 - } else { 450 - __set_current_state(TASK_RUNNING); 451 - if (copy_to_user(buf, rbuf->buf, rbuf->count)) 452 - ret = -EFAULT; 453 - else 454 - ret = rbuf->count; 455 - } 456 - 457 - if (n_hdlc->rx_free_buf_list.count > 458 - DEFAULT_RX_BUF_COUNT) 459 - kfree(rbuf); 460 - else 461 - n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); 439 + if (rbuf) 462 440 break; 463 - } 464 441 465 442 /* no data */ 466 443 if (tty_io_nonblock(tty, file)) { ··· 461 472 462 473 remove_wait_queue(&tty->read_wait, &wait); 463 474 __set_current_state(TASK_RUNNING); 475 + 476 + if (!rbuf) 477 + return ret; 478 + *cookie = rbuf; 479 + 480 + have_rbuf: 481 + /* Have we used it up entirely? */ 482 + if (offset >= rbuf->count) 483 + goto done_with_rbuf; 484 + 485 + /* More data to go, but can't copy any more? EOVERFLOW */ 486 + ret = -EOVERFLOW; 487 + if (!nr) 488 + goto done_with_rbuf; 489 + 490 + /* Copy as much data as possible */ 491 + ret = rbuf->count - offset; 492 + if (ret > nr) 493 + ret = nr; 494 + memcpy(kbuf, rbuf->buf+offset, ret); 495 + offset += ret; 496 + 497 + /* If we still have data left, we leave the rbuf in the cookie */ 498 + if (offset < rbuf->count) 499 + return ret; 500 + 501 + done_with_rbuf: 502 + *cookie = NULL; 503 + 504 + if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) 505 + kfree(rbuf); 506 + else 507 + n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); 464 508 465 509 return ret; 466 510
+2 -1
drivers/tty/n_null.c
··· 20 20 } 21 21 22 22 static ssize_t n_null_read(struct tty_struct *tty, struct file *file, 23 - unsigned char __user * buf, size_t nr) 23 + unsigned char *buf, size_t nr, 24 + void **cookie, unsigned long offset) 24 25 { 25 26 return -EOPNOTSUPP; 26 27 }
+4 -6
drivers/tty/n_r3964.c
··· 129 129 static int r3964_open(struct tty_struct *tty); 130 130 static void r3964_close(struct tty_struct *tty); 131 131 static ssize_t r3964_read(struct tty_struct *tty, struct file *file, 132 - unsigned char __user * buf, size_t nr); 132 + void *cookie, unsigned char *buf, size_t nr); 133 133 static ssize_t r3964_write(struct tty_struct *tty, struct file *file, 134 134 const unsigned char *buf, size_t nr); 135 135 static int r3964_ioctl(struct tty_struct *tty, struct file *file, ··· 1058 1058 } 1059 1059 1060 1060 static ssize_t r3964_read(struct tty_struct *tty, struct file *file, 1061 - unsigned char __user * buf, size_t nr) 1061 + unsigned char *kbuf, size_t nr, 1062 + void **cookie, unsigned long offset) 1062 1063 { 1063 1064 struct r3964_info *pInfo = tty->disc_data; 1064 1065 struct r3964_client_info *pClient; ··· 1110 1109 kfree(pMsg); 1111 1110 TRACE_M("r3964_read - msg kfree %p", pMsg); 1112 1111 1113 - if (copy_to_user(buf, &theMsg, ret)) { 1114 - ret = -EFAULT; 1115 - goto unlock; 1116 - } 1112 + memcpy(kbuf, &theMsg, ret); 1117 1113 1118 1114 TRACE_PS("read - return %d", ret); 1119 1115 goto unlock;
+3 -1
drivers/tty/n_tracerouter.c
··· 118 118 * -EINVAL 119 119 */ 120 120 static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file, 121 - unsigned char __user *buf, size_t nr) { 121 + unsigned char *buf, size_t nr, 122 + void **cookie, unsigned long offset) 123 + { 122 124 return -EINVAL; 123 125 } 124 126
+3 -1
drivers/tty/n_tracesink.c
··· 115 115 * -EINVAL 116 116 */ 117 117 static ssize_t n_tracesink_read(struct tty_struct *tty, struct file *file, 118 - unsigned char __user *buf, size_t nr) { 118 + unsigned char *buf, size_t nr, 119 + void **cookie, unsigned long offset) 120 + { 119 121 return -EINVAL; 120 122 } 121 123
+34 -48
drivers/tty/n_tty.c
··· 164 164 memset(buffer, 0x00, size); 165 165 } 166 166 167 - static int tty_copy_to_user(struct tty_struct *tty, void __user *to, 168 - size_t tail, size_t n) 167 + static void tty_copy(struct tty_struct *tty, void *to, size_t tail, size_t n) 169 168 { 170 169 struct n_tty_data *ldata = tty->disc_data; 171 170 size_t size = N_TTY_BUF_SIZE - tail; 172 171 void *from = read_buf_addr(ldata, tail); 173 - int uncopied; 174 172 175 173 if (n > size) { 176 174 tty_audit_add_data(tty, from, size); 177 - uncopied = copy_to_user(to, from, size); 178 - zero_buffer(tty, from, size - uncopied); 179 - if (uncopied) 180 - return uncopied; 175 + memcpy(to, from, size); 176 + zero_buffer(tty, from, size); 181 177 to += size; 182 178 n -= size; 183 179 from = ldata->read_buf; 184 180 } 185 181 186 182 tty_audit_add_data(tty, from, n); 187 - uncopied = copy_to_user(to, from, n); 188 - zero_buffer(tty, from, n - uncopied); 189 - return uncopied; 183 + memcpy(to, from, n); 184 + zero_buffer(tty, from, n); 190 185 } 191 186 192 187 /** ··· 1937 1942 /** 1938 1943 * copy_from_read_buf - copy read data directly 1939 1944 * @tty: terminal device 1940 - * @b: user data 1945 + * @kbp: data 1941 1946 * @nr: size of data 1942 1947 * 1943 1948 * Helper function to speed up n_tty_read. It is only called when 1944 - * ICANON is off; it copies characters straight from the tty queue to 1945 - * user space directly. It can be profitably called twice; once to 1946 - * drain the space from the tail pointer to the (physical) end of the 1947 - * buffer, and once to drain the space from the (physical) beginning of 1948 - * the buffer to head pointer. 1949 + * ICANON is off; it copies characters straight from the tty queue. 1950 + * 1951 + * It can be profitably called twice; once to drain the space from 1952 + * the tail pointer to the (physical) end of the buffer, and once 1953 + * to drain the space from the (physical) beginning of the buffer 1954 + * to head pointer. 1949 1955 * 1950 1956 * Called under the ldata->atomic_read_lock sem 1951 1957 * ··· 1956 1960 */ 1957 1961 1958 1962 static int copy_from_read_buf(struct tty_struct *tty, 1959 - unsigned char __user **b, 1963 + unsigned char **kbp, 1960 1964 size_t *nr) 1961 1965 1962 1966 { ··· 1972 1976 n = min(*nr, n); 1973 1977 if (n) { 1974 1978 unsigned char *from = read_buf_addr(ldata, tail); 1975 - retval = copy_to_user(*b, from, n); 1976 - n -= retval; 1979 + memcpy(*kbp, from, n); 1977 1980 is_eof = n == 1 && *from == EOF_CHAR(tty); 1978 1981 tty_audit_add_data(tty, from, n); 1979 1982 zero_buffer(tty, from, n); ··· 1981 1986 if (L_EXTPROC(tty) && ldata->icanon && is_eof && 1982 1987 (head == ldata->read_tail)) 1983 1988 n = 0; 1984 - *b += n; 1989 + *kbp += n; 1985 1990 *nr -= n; 1986 1991 } 1987 1992 return retval; ··· 1990 1995 /** 1991 1996 * canon_copy_from_read_buf - copy read data in canonical mode 1992 1997 * @tty: terminal device 1993 - * @b: user data 1998 + * @kbp: data 1994 1999 * @nr: size of data 1995 2000 * 1996 2001 * Helper function for n_tty_read. It is only called when ICANON is on; 1997 2002 * it copies one line of input up to and including the line-delimiting 1998 - * character into the user-space buffer. 2003 + * character into the result buffer. 1999 2004 * 2000 2005 * NB: When termios is changed from non-canonical to canonical mode and 2001 2006 * the read buffer contains data, n_tty_set_termios() simulates an EOF ··· 2011 2016 */ 2012 2017 2013 2018 static int canon_copy_from_read_buf(struct tty_struct *tty, 2014 - unsigned char __user **b, 2019 + unsigned char **kbp, 2015 2020 size_t *nr) 2016 2021 { 2017 2022 struct n_tty_data *ldata = tty->disc_data; 2018 2023 size_t n, size, more, c; 2019 2024 size_t eol; 2020 2025 size_t tail; 2021 - int ret, found = 0; 2026 + int found = 0; 2022 2027 2023 2028 /* N.B. avoid overrun if nr == 0 */ 2024 2029 if (!*nr) ··· 2054 2059 n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n", 2055 2060 __func__, eol, found, n, c, tail, more); 2056 2061 2057 - ret = tty_copy_to_user(tty, *b, tail, n); 2058 - if (ret) 2059 - return -EFAULT; 2060 - *b += n; 2062 + tty_copy(tty, *kbp, tail, n); 2063 + *kbp += n; 2061 2064 *nr -= n; 2062 2065 2063 2066 if (found) ··· 2123 2130 */ 2124 2131 2125 2132 static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, 2126 - unsigned char __user *buf, size_t nr) 2133 + unsigned char *kbuf, size_t nr, 2134 + void **cookie, unsigned long offset) 2127 2135 { 2128 2136 struct n_tty_data *ldata = tty->disc_data; 2129 - unsigned char __user *b = buf; 2137 + unsigned char *kb = kbuf; 2130 2138 DEFINE_WAIT_FUNC(wait, woken_wake_function); 2131 2139 int c; 2132 2140 int minimum, time; ··· 2173 2179 /* First test for status change. */ 2174 2180 if (packet && tty->link->ctrl_status) { 2175 2181 unsigned char cs; 2176 - if (b != buf) 2182 + if (kb != kbuf) 2177 2183 break; 2178 2184 spin_lock_irq(&tty->link->ctrl_lock); 2179 2185 cs = tty->link->ctrl_status; 2180 2186 tty->link->ctrl_status = 0; 2181 2187 spin_unlock_irq(&tty->link->ctrl_lock); 2182 - if (put_user(cs, b)) { 2183 - retval = -EFAULT; 2184 - break; 2185 - } 2186 - b++; 2188 + *kb++ = cs; 2187 2189 nr--; 2188 2190 break; 2189 2191 } ··· 2222 2232 } 2223 2233 2224 2234 if (ldata->icanon && !L_EXTPROC(tty)) { 2225 - retval = canon_copy_from_read_buf(tty, &b, &nr); 2235 + retval = canon_copy_from_read_buf(tty, &kb, &nr); 2226 2236 if (retval) 2227 2237 break; 2228 2238 } else { 2229 2239 int uncopied; 2230 2240 2231 2241 /* Deal with packet mode. */ 2232 - if (packet && b == buf) { 2233 - if (put_user(TIOCPKT_DATA, b)) { 2234 - retval = -EFAULT; 2235 - break; 2236 - } 2237 - b++; 2242 + if (packet && kb == kbuf) { 2243 + *kb++ = TIOCPKT_DATA; 2238 2244 nr--; 2239 2245 } 2240 2246 2241 - uncopied = copy_from_read_buf(tty, &b, &nr); 2242 - uncopied += copy_from_read_buf(tty, &b, &nr); 2247 + uncopied = copy_from_read_buf(tty, &kb, &nr); 2248 + uncopied += copy_from_read_buf(tty, &kb, &nr); 2243 2249 if (uncopied) { 2244 2250 retval = -EFAULT; 2245 2251 break; ··· 2244 2258 2245 2259 n_tty_check_unthrottle(tty); 2246 2260 2247 - if (b - buf >= minimum) 2261 + if (kb - kbuf >= minimum) 2248 2262 break; 2249 2263 if (time) 2250 2264 timeout = time; ··· 2256 2270 remove_wait_queue(&tty->read_wait, &wait); 2257 2271 mutex_unlock(&ldata->atomic_read_lock); 2258 2272 2259 - if (b - buf) 2260 - retval = b - buf; 2273 + if (kb - kbuf) 2274 + retval = kb - kbuf; 2261 2275 2262 2276 return retval; 2263 2277 }
+61 -3
drivers/tty/tty_io.c
··· 833 833 time->tv_sec = sec; 834 834 } 835 835 836 + /* 837 + * Iterate on the ldisc ->read() function until we've gotten all 838 + * the data the ldisc has for us. 839 + * 840 + * The "cookie" is something that the ldisc read function can fill 841 + * in to let us know that there is more data to be had. 842 + * 843 + * We promise to continue to call the ldisc until it stops returning 844 + * data or clears the cookie. The cookie may be something that the 845 + * ldisc maintains state for and needs to free. 846 + */ 847 + static int iterate_tty_read(struct tty_ldisc *ld, struct tty_struct *tty, struct file *file, 848 + char __user *buf, size_t count) 849 + { 850 + int retval = 0; 851 + void *cookie = NULL; 852 + unsigned long offset = 0; 853 + char kernel_buf[64]; 854 + 855 + do { 856 + int size, uncopied; 857 + 858 + size = count > sizeof(kernel_buf) ? sizeof(kernel_buf) : count; 859 + size = ld->ops->read(tty, file, kernel_buf, size, &cookie, offset); 860 + if (!size) 861 + break; 862 + 863 + /* 864 + * A ldisc read error return will override any previously copied 865 + * data (eg -EOVERFLOW from HDLC) 866 + */ 867 + if (size < 0) { 868 + memzero_explicit(kernel_buf, sizeof(kernel_buf)); 869 + return size; 870 + } 871 + 872 + uncopied = copy_to_user(buf+offset, kernel_buf, size); 873 + size -= uncopied; 874 + offset += size; 875 + count -= size; 876 + 877 + /* 878 + * If the user copy failed, we still need to do another ->read() 879 + * call if we had a cookie to let the ldisc clear up. 880 + * 881 + * But make sure size is zeroed. 882 + */ 883 + if (unlikely(uncopied)) { 884 + count = 0; 885 + retval = -EFAULT; 886 + } 887 + } while (cookie); 888 + 889 + /* We always clear tty buffer in case they contained passwords */ 890 + memzero_explicit(kernel_buf, sizeof(kernel_buf)); 891 + return offset ? offset : retval; 892 + } 893 + 894 + 836 895 /** 837 896 * tty_read - read method for tty device files 838 897 * @file: pointer to tty file ··· 925 866 ld = tty_ldisc_ref_wait(tty); 926 867 if (!ld) 927 868 return hung_up_tty_read(file, buf, count, ppos); 869 + i = -EIO; 928 870 if (ld->ops->read) 929 - i = ld->ops->read(tty, file, buf, count); 930 - else 931 - i = -EIO; 871 + i = iterate_tty_read(ld, tty, file, buf, count); 932 872 tty_ldisc_deref(ld); 933 873 934 874 if (i > 0)
+2 -1
include/linux/tty_ldisc.h
··· 185 185 void (*close)(struct tty_struct *); 186 186 void (*flush_buffer)(struct tty_struct *tty); 187 187 ssize_t (*read)(struct tty_struct *tty, struct file *file, 188 - unsigned char __user *buf, size_t nr); 188 + unsigned char *buf, size_t nr, 189 + void **cookie, unsigned long offset); 189 190 ssize_t (*write)(struct tty_struct *tty, struct file *file, 190 191 const unsigned char *buf, size_t nr); 191 192 int (*ioctl)(struct tty_struct *tty, struct file *file,
+2 -1
net/nfc/nci/uart.c
··· 292 292 293 293 /* We don't provide read/write/poll interface for user space. */ 294 294 static ssize_t nci_uart_tty_read(struct tty_struct *tty, struct file *file, 295 - unsigned char __user *buf, size_t nr) 295 + unsigned char *buf, size_t nr, 296 + void **cookie, unsigned long offset) 296 297 { 297 298 return 0; 298 299 }