diff options
Diffstat (limited to 'kernels/linux-libre-knock')
-rw-r--r-- | kernels/linux-libre-knock/0001-tty-n_hdlc-get-rid-of-racy-n_hdlc_tbuf.patch | 311 | ||||
-rw-r--r-- | kernels/linux-libre-knock/PKGBUILD | 11 |
2 files changed, 3 insertions, 319 deletions
diff --git a/kernels/linux-libre-knock/0001-tty-n_hdlc-get-rid-of-racy-n_hdlc_tbuf.patch b/kernels/linux-libre-knock/0001-tty-n_hdlc-get-rid-of-racy-n_hdlc_tbuf.patch deleted file mode 100644 index 0c13c9867..000000000 --- a/kernels/linux-libre-knock/0001-tty-n_hdlc-get-rid-of-racy-n_hdlc_tbuf.patch +++ /dev/null @@ -1,311 +0,0 @@ ->From 1dea7a8061ad9212f4464464a80d0dcd477eceab Mon Sep 17 00:00:00 2001 -From: Alexander Popov <alex.popov () linux com> -Date: Tue, 28 Feb 2017 19:28:54 +0300 -Subject: [PATCH 1/1] tty: n_hdlc: get rid of racy n_hdlc.tbuf - -Currently N_HDLC line discipline uses a self-made singly linked list for -data buffers and has n_hdlc.tbuf pointer for buffer retransmitting after -an error. - -The commit be10eb7589337e5defbe214dae038a53dd21add8 -("tty: n_hdlc add buffer flushing") introduced racy access to n_hdlc.tbuf. -After tx error concurrent flush_tx_queue() and n_hdlc_send_frames() can put -one data buffer to tx_free_buf_list twice. That causes double free in -n_hdlc_release(). - -Let's use standard kernel linked list and get rid of n_hdlc.tbuf: -in case of tx error put current data buffer after the head of tx_buf_list. - -Signed-off-by: Alexander Popov <alex.popov () linux com> ---- - drivers/tty/n_hdlc.c | 132 +++++++++++++++++++++++++++------------------------ - 1 file changed, 69 insertions(+), 63 deletions(-) - -diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c -index eb27883..728c824 100644 ---- a/drivers/tty/n_hdlc.c -+++ b/drivers/tty/n_hdlc.c -@@ -114,7 +114,7 @@ - #define DEFAULT_TX_BUF_COUNT 3 - - struct n_hdlc_buf { -- struct n_hdlc_buf *link; -+ struct list_head list_item; - int count; - char buf[1]; - }; -@@ -122,8 +122,7 @@ struct n_hdlc_buf { - #define N_HDLC_BUF_SIZE (sizeof(struct n_hdlc_buf) + maxframe) - - struct n_hdlc_buf_list { -- struct n_hdlc_buf *head; -- struct n_hdlc_buf *tail; -+ struct list_head list; - int count; - spinlock_t spinlock; - }; -@@ -136,7 +135,6 @@ struct n_hdlc_buf_list { - * @backup_tty - TTY to use if tty gets closed - * @tbusy - reentrancy flag for tx wakeup code - * @woke_up - FIXME: describe this field -- * @tbuf - currently transmitting tx buffer - * @tx_buf_list - list of pending transmit frame buffers - * @rx_buf_list - list of received frame buffers - * @tx_free_buf_list - list unused transmit frame buffers -@@ -149,7 +147,6 @@ struct n_hdlc { - struct tty_struct *backup_tty; - int tbusy; - int woke_up; -- struct n_hdlc_buf *tbuf; - struct n_hdlc_buf_list tx_buf_list; - struct n_hdlc_buf_list rx_buf_list; - struct n_hdlc_buf_list tx_free_buf_list; -@@ -159,6 +156,8 @@ struct n_hdlc { - /* - * HDLC buffer list manipulation functions - */ -+static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, -+ struct n_hdlc_buf *buf); - static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, - struct n_hdlc_buf *buf); - static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); -@@ -208,16 +207,9 @@ static void flush_tx_queue(struct tty_struct *tty) - { - struct n_hdlc *n_hdlc = tty2n_hdlc(tty); - struct n_hdlc_buf *buf; -- unsigned long flags; - - while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list))) - n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf); -- spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); -- if (n_hdlc->tbuf) { -- n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf); -- n_hdlc->tbuf = NULL; -- } -- spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); - } - - static struct tty_ldisc_ops n_hdlc_ldisc = { -@@ -283,7 +275,6 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc) - } else - break; - } -- kfree(n_hdlc->tbuf); - kfree(n_hdlc); - - } /* end of n_hdlc_release() */ -@@ -402,13 +393,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) - n_hdlc->woke_up = 0; - spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); - -- /* get current transmit buffer or get new transmit */ -- /* buffer from list of pending transmit buffers */ -- -- tbuf = n_hdlc->tbuf; -- if (!tbuf) -- tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); -- -+ tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); - while (tbuf) { - if (debuglevel >= DEBUG_LEVEL_INFO) - printk("%s(%d)sending frame %p, count=%d\n", -@@ -420,7 +405,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) - - /* rollback was possible and has been done */ - if (actual == -ERESTARTSYS) { -- n_hdlc->tbuf = tbuf; -+ n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); - break; - } - /* if transmit error, throw frame away by */ -@@ -435,10 +420,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) - - /* free current transmit buffer */ - n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf); -- -- /* this tx buffer is done */ -- n_hdlc->tbuf = NULL; -- -+ - /* wait up sleeping writers */ - wake_up_interruptible(&tty->write_wait); - -@@ -448,10 +430,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) - if (debuglevel >= DEBUG_LEVEL_INFO) - printk("%s(%d)frame %p pending\n", - __FILE__,__LINE__,tbuf); -- -- /* buffer not accepted by driver */ -- /* set this buffer as pending buffer */ -- n_hdlc->tbuf = tbuf; -+ -+ /* -+ * the buffer was not accepted by driver, -+ * return it back into tx queue -+ */ -+ n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); - break; - } - } -@@ -749,7 +733,8 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, - int error = 0; - int count; - unsigned long flags; -- -+ struct n_hdlc_buf *buf = NULL; -+ - if (debuglevel >= DEBUG_LEVEL_INFO) - printk("%s(%d)n_hdlc_tty_ioctl() called %d\n", - __FILE__,__LINE__,cmd); -@@ -763,8 +748,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, - /* report count of read data available */ - /* in next available frame (if any) */ - spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags); -- if (n_hdlc->rx_buf_list.head) -- count = n_hdlc->rx_buf_list.head->count; -+ buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list, -+ struct n_hdlc_buf, list_item); -+ if (buf) -+ count = buf->count; - else - count = 0; - spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags); -@@ -776,8 +763,10 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, - count = tty_chars_in_buffer(tty); - /* add size of next output frame in queue */ - spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); -- if (n_hdlc->tx_buf_list.head) -- count += n_hdlc->tx_buf_list.head->count; -+ buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list, -+ struct n_hdlc_buf, list_item); -+ if (buf) -+ count += buf->count; - spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags); - error = put_user(count, (int __user *)arg); - break; -@@ -825,14 +814,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, - poll_wait(filp, &tty->write_wait, wait); - - /* set bits for operations that won't block */ -- if (n_hdlc->rx_buf_list.head) -+ if (!list_empty(&n_hdlc->rx_buf_list.list)) - mask |= POLLIN | POLLRDNORM; /* readable */ - if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) - mask |= POLLHUP; - if (tty_hung_up_p(filp)) - mask |= POLLHUP; - if (!tty_is_writelocked(tty) && -- n_hdlc->tx_free_buf_list.head) -+ !list_empty(&n_hdlc->tx_free_buf_list.list)) - mask |= POLLOUT | POLLWRNORM; /* writable */ - } - return mask; -@@ -856,7 +845,12 @@ static struct n_hdlc *n_hdlc_alloc(void) - spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); - spin_lock_init(&n_hdlc->rx_buf_list.spinlock); - spin_lock_init(&n_hdlc->tx_buf_list.spinlock); -- -+ -+ INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list); -+ INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list); -+ INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list); -+ INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list); -+ - /* allocate free rx buffer list */ - for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) { - buf = kmalloc(N_HDLC_BUF_SIZE, GFP_KERNEL); -@@ -884,53 +878,65 @@ static struct n_hdlc *n_hdlc_alloc(void) - } /* end of n_hdlc_alloc() */ - - /** -+ * n_hdlc_buf_return - put the HDLC buffer after the head of the specified list -+ * @buf_list - pointer to the buffer list -+ * @buf - pointer to the buffer -+ */ -+static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, -+ struct n_hdlc_buf *buf) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&buf_list->spinlock, flags); -+ -+ list_add(&buf->list_item, &buf_list->list); -+ buf_list->count++; -+ -+ spin_unlock_irqrestore(&buf_list->spinlock, flags); -+} -+ -+/** - * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list -- * @list - pointer to buffer list -+ * @buf_list - pointer to buffer list - * @buf - pointer to buffer - */ --static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, -+static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list, - struct n_hdlc_buf *buf) - { - unsigned long flags; -- spin_lock_irqsave(&list->spinlock,flags); -- -- buf->link=NULL; -- if (list->tail) -- list->tail->link = buf; -- else -- list->head = buf; -- list->tail = buf; -- (list->count)++; -- -- spin_unlock_irqrestore(&list->spinlock,flags); -- -+ -+ spin_lock_irqsave(&buf_list->spinlock, flags); -+ -+ list_add_tail(&buf->list_item, &buf_list->list); -+ buf_list->count++; -+ -+ spin_unlock_irqrestore(&buf_list->spinlock, flags); - } /* end of n_hdlc_buf_put() */ - - /** - * n_hdlc_buf_get - remove and return an HDLC buffer from list -- * @list - pointer to HDLC buffer list -+ * @buf_list - pointer to HDLC buffer list - * - * Remove and return an HDLC buffer from the head of the specified HDLC buffer - * list. - * Returns a pointer to HDLC buffer if available, otherwise %NULL. - */ --static struct n_hdlc_buf* n_hdlc_buf_get(struct n_hdlc_buf_list *list) -+static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list) - { - unsigned long flags; - struct n_hdlc_buf *buf; -- spin_lock_irqsave(&list->spinlock,flags); -- -- buf = list->head; -+ -+ spin_lock_irqsave(&buf_list->spinlock, flags); -+ -+ buf = list_first_entry_or_null(&buf_list->list, -+ struct n_hdlc_buf, list_item); - if (buf) { -- list->head = buf->link; -- (list->count)--; -+ list_del(&buf->list_item); -+ buf_list->count--; - } -- if (!list->head) -- list->tail = NULL; -- -- spin_unlock_irqrestore(&list->spinlock,flags); -+ -+ spin_unlock_irqrestore(&buf_list->spinlock, flags); - return buf; -- - } /* end of n_hdlc_buf_get() */ - - static char hdlc_banner[] __initdata = --- -2.7.4 - diff --git a/kernels/linux-libre-knock/PKGBUILD b/kernels/linux-libre-knock/PKGBUILD index c1294082b..af8a29edb 100644 --- a/kernels/linux-libre-knock/PKGBUILD +++ b/kernels/linux-libre-knock/PKGBUILD @@ -10,7 +10,7 @@ pkgbase=linux-libre-knock _pkgbasever=4.10-gnu -_pkgver=4.10.2-gnu +_pkgver=4.10.3-gnu _knockpatchver=4.10_1 _replacesarchkernel=('linux%') # '%' gets replaced with _kernelname @@ -48,7 +48,6 @@ source=("https://linux-libre.fsfla.org/pub/linux-libre/releases/${_pkgbasever}/l '99-linux.hook' # standard config files for mkinitcpio ramdisk 'linux.preset' - '0001-tty-n_hdlc-get-rid-of-racy-n_hdlc_tbuf.patch' '0001-usb-serial-gadget-no-TTY-hangup-on-USB-disconnect-WI.patch' '0002-fix-Atmel-maXTouch-touchscreen-support.patch' # armv7h patches @@ -66,7 +65,7 @@ source=("https://linux-libre.fsfla.org/pub/linux-libre/releases/${_pkgbasever}/l '0010-disable-USB3-port-on-ODROID-XU.patch') sha512sums=('44d1774a1d43a15322297d351737fbcbf92c6f433266ce2b17587437d433562cf5811fdae48fafd5a8e00d18ed9ac2e1ad4b12a657f322eb234384316ad131e0' 'SKIP' - '02e518e8192f7b71dcb3724d1b9f4bc502d210387548a77a8edf6900281ccd13de55986382c9be00afacf0dc0ca2f13a70327be9230b1c93d95bc917cfd17643' + 'c2e674578fa3b0e86941009034c69aea09267b322e0a58f7850c7e5b79db69486d1ada277a37825e94dcbbd4798ee56655db1900dabf34f00097f331d08e5fc6' 'SKIP' '61b12333aaaeec86fc51feff8a46dc3e8e89b49530de66a389a3ed6ce974912772b8126d6a4bbc71b2d7b133974432141b896924db0e46df50537499447c0a95' 'SKIP' @@ -81,10 +80,9 @@ sha512sums=('44d1774a1d43a15322297d351737fbcbf92c6f433266ce2b17587437d433562cf58 'b318298a61f49af63fc3dad87db3d7549370bc3a412966526293e1eac574adfcf4c6424501f95b24a1aea738a3636325168cc210a0dca036368d407e61d45a6c' 'd6faa67f3ef40052152254ae43fee031365d0b1524aa0718b659eb75afc21a3f79ea8d62d66ea311a800109bed545bc8f79e8752319cd378eef2cbd3a09aba22' '2dc6b0ba8f7dbf19d2446c5c5f1823587de89f4e28e9595937dd51a87755099656f2acec50e3e2546ea633ad1bfd1c722e0c2b91eef1d609103d8abdc0a7cbaf' - '397fc751697cc4e2ceb7e6d854f5e7fc115ed8511df406ffe5d8f80afeec385ba64cd28c4666bb206612fdcd7a578b60ca6ff125c2138c615aee6135d86b0197' '02af4dd2a007e41db0c63822c8ab3b80b5d25646af1906dc85d0ad9bb8bbf5236f8e381d7f91cf99ed4b0978c50aee37cb9567cdeef65b7ec3d91b882852b1af' 'b8fe56e14006ab866970ddbd501c054ae37186ddc065bb869cf7d18db8c0d455118d5bda3255fb66a0dde38b544655cfe9040ffe46e41d19830b47959b2fb168' - '08f47087aa71d1aca8dc4d5b7bb28cff3a7bb99f5bd64fc47664d3927ef470e256d22018da0726c186d9f9d19711c91ae4f3333aa161a0b18c082b5b60e5d74d' + '84d9cc5a46ce437ffbb83525d72473ba00ed7ab9012af52a1e0226a22380b2224a48a1bce4e1030e08dfbdde0b760702217b5107673d62770eea26d503a42e0c' 'SKIP' 'dd4e2482d6e3d91d00e37e665933515a4fa876d39c036d639f21c48a09f03202f3dec0dbe04b7c60c4b7e1f49617b5f94ace688afacbe33dc6d6818c0c797031' 'cf0a3061cef91c04fa5e6d50c4ee235f817cb97f6b7a77f42d42ada707e71bd9731dfafdfcf396e767362998acd8b98ad9942a989c2dd8457e57177c354ec7d2' @@ -151,9 +149,6 @@ prepare() { # add latest fixes from stable queue, if needed # http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git - # patch for CVE-2017-2636 - patch -p1 -i "${srcdir}/0001-tty-n_hdlc-get-rid-of-racy-n_hdlc_tbuf.patch" - # maintain the TTY over USB disconnects # http://www.coreboot.org/EHCI_Gadget_Debug patch -p1 -i "${srcdir}/0001-usb-serial-gadget-no-TTY-hangup-on-USB-disconnect-WI.patch" |