diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-04-30 22:14:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 11:12:57 -0400 |
commit | 8ac6ed5857c8d583e0dc2ab2165966ab143930ad (patch) | |
tree | d5c7606ce371ff52213915267b8b34898232a7e3 /ipc/msg.c | |
parent | 852028af861ed6c7ab7e73053dd664eb28e55200 (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/msg.c')
-rw-r--r-- | ipc/msg.c | 22 |
1 files changed, 9 insertions, 13 deletions
@@ -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 | ||
739 | static inline int convert_mode(long *msgtyp, int msgflg) | 741 | static 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 | */ |
777 | static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, | 781 | static 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 |
800 | static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, | 800 | static 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, ©_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 |