aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2013-04-30 22:14:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-01 11:12:57 -0400
commit8ac6ed5857c8d583e0dc2ab2165966ab143930ad (patch)
treed5c7606ce371ff52213915267b8b34898232a7e3 /ipc
parent852028af861ed6c7ab7e73053dd664eb28e55200 (diff)
ipc: implement MSG_COPY as a new receive mode
Teach the helper routines about MSG_COPY so that msgtyp is preserved as the message number to copy. The security functions affected by this change were audited and no additional changes are necessary. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Acked-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/msg.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index b46473074662..7c209b4f5e38 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -66,6 +66,7 @@ struct msg_sender {
66#define SEARCH_EQUAL 2 66#define SEARCH_EQUAL 2
67#define SEARCH_NOTEQUAL 3 67#define SEARCH_NOTEQUAL 3
68#define SEARCH_LESSEQUAL 4 68#define SEARCH_LESSEQUAL 4
69#define SEARCH_NUMBER 5
69 70
70#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS]) 71#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
71 72
@@ -583,6 +584,7 @@ static int testmsg(struct msg_msg *msg, long type, int mode)
583 switch(mode) 584 switch(mode)
584 { 585 {
585 case SEARCH_ANY: 586 case SEARCH_ANY:
587 case SEARCH_NUMBER:
586 return 1; 588 return 1;
587 case SEARCH_LESSEQUAL: 589 case SEARCH_LESSEQUAL:
588 if (msg->m_type <=type) 590 if (msg->m_type <=type)
@@ -738,6 +740,8 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
738 740
739static inline int convert_mode(long *msgtyp, int msgflg) 741static inline int convert_mode(long *msgtyp, int msgflg)
740{ 742{
743 if (msgflg & MSG_COPY)
744 return SEARCH_NUMBER;
741 /* 745 /*
742 * find message of correct type. 746 * find message of correct type.
743 * msgtyp = 0 => get first. 747 * msgtyp = 0 => get first.
@@ -774,14 +778,10 @@ static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
774 * This function creates new kernel message structure, large enough to store 778 * This function creates new kernel message structure, large enough to store
775 * bufsz message bytes. 779 * bufsz message bytes.
776 */ 780 */
777static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, 781static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
778 int msgflg, long *msgtyp,
779 unsigned long *copy_number)
780{ 782{
781 struct msg_msg *copy; 783 struct msg_msg *copy;
782 784
783 *copy_number = *msgtyp;
784 *msgtyp = 0;
785 /* 785 /*
786 * Create dummy message to copy real message to. 786 * Create dummy message to copy real message to.
787 */ 787 */
@@ -797,9 +797,7 @@ static inline void free_copy(struct msg_msg *copy)
797 free_msg(copy); 797 free_msg(copy);
798} 798}
799#else 799#else
800static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, 800static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
801 int msgflg, long *msgtyp,
802 unsigned long *copy_number)
803{ 801{
804 return ERR_PTR(-ENOSYS); 802 return ERR_PTR(-ENOSYS);
805} 803}
@@ -818,15 +816,13 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
818 int mode; 816 int mode;
819 struct ipc_namespace *ns; 817 struct ipc_namespace *ns;
820 struct msg_msg *copy = NULL; 818 struct msg_msg *copy = NULL;
821 unsigned long copy_number = 0;
822 819
823 ns = current->nsproxy->ipc_ns; 820 ns = current->nsproxy->ipc_ns;
824 821
825 if (msqid < 0 || (long) bufsz < 0) 822 if (msqid < 0 || (long) bufsz < 0)
826 return -EINVAL; 823 return -EINVAL;
827 if (msgflg & MSG_COPY) { 824 if (msgflg & MSG_COPY) {
828 copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax), 825 copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax));
829 msgflg, &msgtyp, &copy_number);
830 if (IS_ERR(copy)) 826 if (IS_ERR(copy))
831 return PTR_ERR(copy); 827 return PTR_ERR(copy);
832 } 828 }
@@ -861,8 +857,8 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
861 if (mode == SEARCH_LESSEQUAL && 857 if (mode == SEARCH_LESSEQUAL &&
862 walk_msg->m_type != 1) { 858 walk_msg->m_type != 1) {
863 msgtyp = walk_msg->m_type - 1; 859 msgtyp = walk_msg->m_type - 1;
864 } else if (msgflg & MSG_COPY) { 860 } else if (mode == SEARCH_NUMBER) {
865 if (copy_number == msg_counter) 861 if (msgtyp == msg_counter)
866 break; 862 break;
867 msg = ERR_PTR(-EAGAIN); 863 msg = ERR_PTR(-EAGAIN);
868 } else 864 } else