aboutsummaryrefslogtreecommitdiffstats
path: root/0015-tty-n_r3964-add-reference-counting-to-the-client-str.patch
diff options
context:
space:
mode:
Diffstat (limited to '0015-tty-n_r3964-add-reference-counting-to-the-client-str.patch')
-rw-r--r--0015-tty-n_r3964-add-reference-counting-to-the-client-str.patch245
1 files changed, 0 insertions, 245 deletions
diff --git a/0015-tty-n_r3964-add-reference-counting-to-the-client-str.patch b/0015-tty-n_r3964-add-reference-counting-to-the-client-str.patch
deleted file mode 100644
index 862be5f5310f93..00000000000000
--- a/0015-tty-n_r3964-add-reference-counting-to-the-client-str.patch
+++ /dev/null
@@ -1,245 +0,0 @@
-From da04c3926a73304489a320796045814ac48f2e37 Mon Sep 17 00:00:00 2001
-From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Date: Fri, 1 Feb 2019 10:44:55 +0100
-Subject: [PATCH 15/15] tty: n_r3964: add reference counting to the client
- structure
-
-The client structure pointer is thrown around a lot, and trying to keep
-track of who has, and does not have, a valid pointer is almost
-impossible to audit properly, especially when looking up client
-structures from the lists. So add a kref to the structure so that it
-will be automatically reference counted and no one can access a stale
-pointer and memory will be freed when everything is finished.
-
-This should resolve the problem with the client structure pointer beging
-able to be accessed when it was removed by someone else at the same
-time.
-
-Reported-by: Jann Horn <jannh@google.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/tty/n_r3964.c | 82 +++++++++++++++++++++++++++++++++++++++-----------
- 1 file changed, 64 insertions(+), 18 deletions(-)
-
---- a/drivers/tty/n_r3964.c
-+++ b/drivers/tty/n_r3964.c
-@@ -106,6 +106,7 @@ struct tx_block_header;
-
- struct r3964_client_info {
- spinlock_t lock;
-+ struct kref kref;
- struct pid *pid;
- unsigned int sig_flags;
-
-@@ -298,6 +299,30 @@ static int __init r3964_init(void)
- module_init(r3964_init);
- module_exit(r3964_exit);
-
-+static struct r3964_client_info *client_get(struct r3964_client_info *client)
-+{
-+ if (client)
-+ kref_get(&client->kref);
-+ return client;
-+}
-+
-+static void client_free(struct kref *kref)
-+{
-+ struct r3964_client_info *client;
-+
-+ client = container_of(kref, struct r3964_client_info, kref);
-+
-+ put_pid(client->pid);
-+ list_del(&client->node);
-+ kfree(client);
-+}
-+
-+static void client_put(struct r3964_client_info *client)
-+{
-+ if (client)
-+ kref_put(&client->kref, client_free);
-+}
-+
- /*************************************************************
- * Protocol implementation routines
- *************************************************************/
-@@ -339,6 +364,7 @@ static void remove_from_tx_queue(struct
- wake_up_interruptible(&pInfo->tty->read_wait);
- }
-
-+ client_put(pHeader->owner);
- kfree(pHeader);
- }
-
-@@ -550,6 +576,7 @@ static void on_receive_block(struct r396
- unsigned long client_flags;
- unsigned int sig_flags;
-
-+ client_get(pClient);
- spin_lock_irqsave(&pClient->lock, client_flags);
- sig_flags = pClient->sig_flags;
- spin_unlock_irqrestore(&pClient->lock, client_flags);
-@@ -558,6 +585,7 @@ static void on_receive_block(struct r396
- add_msg(pClient, R3964_MSG_DATA, length, R3964_OK,
- pBlock);
- }
-+ client_put(pClient);
- }
- spin_unlock_irqrestore(&pInfo->lock, flags);
- wake_up_interruptible(&pInfo->tty->read_wait);
-@@ -751,25 +779,40 @@ static void on_timeout(struct timer_list
- }
- }
-
-+/*
-+ * The reference count of the pointer returned will be incremented
-+ * (if it is not NULL) so client_put() must be called on it when the
-+ * caller is finished with it.
-+ */
- static struct r3964_client_info *findClient(struct r3964_info *pInfo,
- struct pid *pid)
- {
- struct r3964_client_info *pClient;
-- unsigned long flags;
-+ unsigned long client_flags;
-+ unsigned long info_flags;
-
-- spin_lock_irqsave(&pInfo->lock, flags);
-+ spin_lock_irqsave(&pInfo->lock, info_flags);
- list_for_each_entry(pClient, &pInfo->clients, node) {
-+ client_get(pClient);
-+ spin_lock_irqsave(&pClient->lock, client_flags);
- if (pClient->pid == pid) {
-+ spin_unlock_irqrestore(&pClient->lock, client_flags);
- goto exit;
- }
-+ spin_unlock_irqrestore(&pClient->lock, client_flags);
-+ client_put(pClient);
- }
- pClient = NULL;
- exit:
-- spin_unlock_irqrestore(&pInfo->lock, flags);
-+ spin_unlock_irqrestore(&pInfo->lock, info_flags);
- return pClient;
- }
-
--/* Find a client that refers to the pid of the current task */
-+/*
-+ * Find a client that refers to the pid of the current task
-+ * The reference count of the pointer will be incremented so
-+ * client_put() must be called when the caller is finished with it
-+ */
- static struct r3964_client_info *find_client_current(struct r3964_info *info)
- {
- struct r3964_client_info *client;
-@@ -792,6 +835,7 @@ static int enable_signals(struct r3964_i
-
- /* Remove client from client list */
- list_for_each_entry(pClient, &pInfo->clients, node) {
-+ client_get(pClient);
- if (pClient->pid == pid) {
- TRACE_PS("removing client %d from client list",
- pid_nr(pid));
-@@ -803,13 +847,13 @@ static int enable_signals(struct r3964_i
- "kfree %p", pMsg);
- }
- }
-- put_pid(pClient->pid);
-- list_del(&pClient->node);
-- kfree(pClient);
-- TRACE_M("enable_signals - kfree %p", pClient);
-+ /* Second put will free the structure */
-+ client_put(pClient);
-+ client_put(pClient);
- spin_unlock_irqrestore(&pInfo->lock, flags);
- return 0;
- }
-+ client_put(pClient);
- }
- spin_unlock_irqrestore(&pInfo->lock, flags);
- return -EINVAL;
-@@ -822,6 +866,7 @@ static int enable_signals(struct r3964_i
- spin_lock_irqsave(&pClient->lock, client_flags);
- pClient->sig_flags = arg;
- spin_unlock_irqrestore(&pClient->lock, client_flags);
-+ client_put(pClient);
- } else {
- /* add client to client list */
- pClient = kmalloc(sizeof(struct r3964_client_info),
-@@ -833,6 +878,7 @@ static int enable_signals(struct r3964_i
- spin_lock_irqsave(&pInfo->lock, flags);
- TRACE_PS("add client %d to client list", pid_nr(pid));
- spin_lock_init(&pClient->lock);
-+ kref_init(&pClient->kref);
- pClient->sig_flags = arg;
- pClient->pid = get_pid(pid);
- INIT_LIST_HEAD(&pClient->msgs);
-@@ -886,6 +932,7 @@ static int read_telegram(struct r3964_in
-
- if (copy_to_user(buf, data, length)) {
- kfree(data);
-+ client_put(pClient);
- return -EFAULT;
- }
- kfree(data);
-@@ -905,6 +952,7 @@ static int read_telegram(struct r3964_in
-
- exit:
- spin_unlock_irqrestore(&pClient->lock, flags);
-+ client_put(pClient);
- return retval;
- }
-
-@@ -1090,10 +1138,7 @@ static void r3964_close(struct tty_struc
- TRACE_M("r3964_close - msg kfree %p", pMsg);
- }
- }
-- put_pid(pClient->pid);
-- list_del(&pClient->node);
-- kfree(pClient);
-- TRACE_M("r3964_close - client kfree %p", pClient);
-+ client_put(pClient);
- }
- /* Remove jobs from tx_queue: */
- spin_lock_irqsave(&pInfo->lock, flags);
-@@ -1171,6 +1216,7 @@ static ssize_t r3964_read(struct tty_str
- ret = -EPERM;
- unlock:
- mutex_unlock(&pInfo->read_lock);
-+ client_put(pClient);
- return ret;
- }
-
-@@ -1179,7 +1225,6 @@ static ssize_t r3964_write(struct tty_st
- {
- struct r3964_info *pInfo = tty->disc_data;
- struct tx_block_header *pHeader;
-- struct r3964_client_info *pClient;
- unsigned char *new_data;
-
- TRACE_L("write request, %d characters", count);
-@@ -1215,12 +1260,12 @@ static ssize_t r3964_write(struct tty_st
- pHeader = (struct tx_block_header *)new_data;
- pHeader->data = new_data + sizeof(*pHeader);
- pHeader->length = count;
-- pHeader->owner = NULL;
-
-- pClient = find_client_current(pInfo);
-- if (pClient) {
-- pHeader->owner = pClient;
-- }
-+ /*
-+ * The reference count is left incremented as the last user of
-+ * this pointer will drop it when needed
-+ */
-+ pHeader->owner = find_client_current(pInfo);
-
- memcpy(pHeader->data, data, count); /* We already verified this */
-
-@@ -1331,6 +1376,7 @@ static __poll_t r3964_poll(struct tty_st
- if (!list_empty(&pClient->msgs))
- result |= EPOLLIN | EPOLLRDNORM;
- spin_unlock_irqrestore(&pClient->lock, flags);
-+ client_put(pClient);
- } else {
- result = EPOLLNVAL | EPOLLERR;
- }