Commit 8ac6ed5857c8d583e0dc2ab2165966ab143930ad

Authored by Peter Hurley
Committed by Linus Torvalds
1 parent 852028af86

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>

Showing 1 changed file with 9 additions and 13 deletions Side-by-side Diff

... ... @@ -66,6 +66,7 @@
66 66 #define SEARCH_EQUAL 2
67 67 #define SEARCH_NOTEQUAL 3
68 68 #define SEARCH_LESSEQUAL 4
  69 +#define SEARCH_NUMBER 5
69 70  
70 71 #define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
71 72  
... ... @@ -583,6 +584,7 @@
583 584 switch(mode)
584 585 {
585 586 case SEARCH_ANY:
  587 + case SEARCH_NUMBER:
586 588 return 1;
587 589 case SEARCH_LESSEQUAL:
588 590 if (msg->m_type <=type)
... ... @@ -738,6 +740,8 @@
738 740  
739 741 static inline int convert_mode(long *msgtyp, int msgflg)
740 742 {
  743 + if (msgflg & MSG_COPY)
  744 + return SEARCH_NUMBER;
741 745 /*
742 746 * find message of correct type.
743 747 * msgtyp = 0 => get first.
744 748  
... ... @@ -774,14 +778,10 @@
774 778 * This function creates new kernel message structure, large enough to store
775 779 * bufsz message bytes.
776 780 */
777   -static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
778   - int msgflg, long *msgtyp,
779   - unsigned long *copy_number)
  781 +static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
780 782 {
781 783 struct msg_msg *copy;
782 784  
783   - *copy_number = *msgtyp;
784   - *msgtyp = 0;
785 785 /*
786 786 * Create dummy message to copy real message to.
787 787 */
... ... @@ -797,9 +797,7 @@
797 797 free_msg(copy);
798 798 }
799 799 #else
800   -static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
801   - int msgflg, long *msgtyp,
802   - unsigned long *copy_number)
  800 +static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
803 801 {
804 802 return ERR_PTR(-ENOSYS);
805 803 }
806 804  
... ... @@ -818,15 +816,13 @@
818 816 int mode;
819 817 struct ipc_namespace *ns;
820 818 struct msg_msg *copy = NULL;
821   - unsigned long copy_number = 0;
822 819  
823 820 ns = current->nsproxy->ipc_ns;
824 821  
825 822 if (msqid < 0 || (long) bufsz < 0)
826 823 return -EINVAL;
827 824 if (msgflg & MSG_COPY) {
828   - copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax),
829   - msgflg, &msgtyp, &copy_number);
  825 + copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax));
830 826 if (IS_ERR(copy))
831 827 return PTR_ERR(copy);
832 828 }
... ... @@ -861,8 +857,8 @@
861 857 if (mode == SEARCH_LESSEQUAL &&
862 858 walk_msg->m_type != 1) {
863 859 msgtyp = walk_msg->m_type - 1;
864   - } else if (msgflg & MSG_COPY) {
865   - if (copy_number == msg_counter)
  860 + } else if (mode == SEARCH_NUMBER) {
  861 + if (msgtyp == msg_counter)
866 862 break;
867 863 msg = ERR_PTR(-EAGAIN);
868 864 } else