diff options
author | Svenning Sørensen <sss@secomea.dk> | 2013-08-28 19:35:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-28 22:26:38 -0400 |
commit | 368ae537e056acd3f751fa276f48423f06803922 (patch) | |
tree | c0e8dec82905b231fc74b732fd0966d62d530b22 /ipc/msg.c | |
parent | aaaafb7f953c60d9c9eeb1b10ecdbe6970421b24 (diff) |
IPC: bugfix for msgrcv with msgtyp < 0
According to 'man msgrcv': "If msgtyp is less than 0, the first message of
the lowest type that is less than or equal to the absolute value of msgtyp
shall be received."
Bug: The kernel only returns a message if its type is 1; other messages
with type < abs(msgtype) will never get returned.
Fix: After having traversed the list to find the first message with the
lowest type, we need to actually return that message.
This regression was introduced by commit daaf74cf0867 ("ipc: refactor
msg list search into separate function")
Signed-off-by: Svenning Soerensen <sss@secomea.dk>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/msg.c')
-rw-r--r-- | ipc/msg.c | 5 |
1 files changed, 3 insertions, 2 deletions
@@ -839,7 +839,7 @@ static inline void free_copy(struct msg_msg *copy) | |||
839 | 839 | ||
840 | static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) | 840 | static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) |
841 | { | 841 | { |
842 | struct msg_msg *msg; | 842 | struct msg_msg *msg, *found = NULL; |
843 | long count = 0; | 843 | long count = 0; |
844 | 844 | ||
845 | list_for_each_entry(msg, &msq->q_messages, m_list) { | 845 | list_for_each_entry(msg, &msq->q_messages, m_list) { |
@@ -848,6 +848,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) | |||
848 | *msgtyp, mode)) { | 848 | *msgtyp, mode)) { |
849 | if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) { | 849 | if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) { |
850 | *msgtyp = msg->m_type - 1; | 850 | *msgtyp = msg->m_type - 1; |
851 | found = msg; | ||
851 | } else if (mode == SEARCH_NUMBER) { | 852 | } else if (mode == SEARCH_NUMBER) { |
852 | if (*msgtyp == count) | 853 | if (*msgtyp == count) |
853 | return msg; | 854 | return msg; |
@@ -857,7 +858,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode) | |||
857 | } | 858 | } |
858 | } | 859 | } |
859 | 860 | ||
860 | return ERR_PTR(-EAGAIN); | 861 | return found ?: ERR_PTR(-EAGAIN); |
861 | } | 862 | } |
862 | 863 | ||
863 | long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, | 864 | long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, |