Commit 8ac6ed58 authored by Peter Hurley's avatar Peter Hurley Committed by Linus Torvalds

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: default avatarPeter Hurley <peter@hurleysoftware.com>
Acked-by: default avatarStanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 852028af
...@@ -66,6 +66,7 @@ struct msg_sender { ...@@ -66,6 +66,7 @@ struct msg_sender {
#define SEARCH_EQUAL 2 #define SEARCH_EQUAL 2
#define SEARCH_NOTEQUAL 3 #define SEARCH_NOTEQUAL 3
#define SEARCH_LESSEQUAL 4 #define SEARCH_LESSEQUAL 4
#define SEARCH_NUMBER 5
#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS]) #define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
...@@ -583,6 +584,7 @@ static int testmsg(struct msg_msg *msg, long type, int mode) ...@@ -583,6 +584,7 @@ static int testmsg(struct msg_msg *msg, long type, int mode)
switch(mode) switch(mode)
{ {
case SEARCH_ANY: case SEARCH_ANY:
case SEARCH_NUMBER:
return 1; return 1;
case SEARCH_LESSEQUAL: case SEARCH_LESSEQUAL:
if (msg->m_type <=type) if (msg->m_type <=type)
...@@ -738,6 +740,8 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, ...@@ -738,6 +740,8 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
static inline int convert_mode(long *msgtyp, int msgflg) static inline int convert_mode(long *msgtyp, int msgflg)
{ {
if (msgflg & MSG_COPY)
return SEARCH_NUMBER;
/* /*
* find message of correct type. * find message of correct type.
* msgtyp = 0 => get first. * msgtyp = 0 => get first.
...@@ -774,14 +778,10 @@ static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) ...@@ -774,14 +778,10 @@ static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
* This function creates new kernel message structure, large enough to store * This function creates new kernel message structure, large enough to store
* bufsz message bytes. * bufsz message bytes.
*/ */
static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
int msgflg, long *msgtyp,
unsigned long *copy_number)
{ {
struct msg_msg *copy; struct msg_msg *copy;
*copy_number = *msgtyp;
*msgtyp = 0;
/* /*
* Create dummy message to copy real message to. * Create dummy message to copy real message to.
*/ */
...@@ -797,9 +797,7 @@ static inline void free_copy(struct msg_msg *copy) ...@@ -797,9 +797,7 @@ static inline void free_copy(struct msg_msg *copy)
free_msg(copy); free_msg(copy);
} }
#else #else
static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz, static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
int msgflg, long *msgtyp,
unsigned long *copy_number)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
...@@ -818,15 +816,13 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, ...@@ -818,15 +816,13 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
int mode; int mode;
struct ipc_namespace *ns; struct ipc_namespace *ns;
struct msg_msg *copy = NULL; struct msg_msg *copy = NULL;
unsigned long copy_number = 0;
ns = current->nsproxy->ipc_ns; ns = current->nsproxy->ipc_ns;
if (msqid < 0 || (long) bufsz < 0) if (msqid < 0 || (long) bufsz < 0)
return -EINVAL; return -EINVAL;
if (msgflg & MSG_COPY) { if (msgflg & MSG_COPY) {
copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax), copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax));
msgflg, &msgtyp, &copy_number);
if (IS_ERR(copy)) if (IS_ERR(copy))
return PTR_ERR(copy); return PTR_ERR(copy);
} }
...@@ -861,8 +857,8 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, ...@@ -861,8 +857,8 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
if (mode == SEARCH_LESSEQUAL && if (mode == SEARCH_LESSEQUAL &&
walk_msg->m_type != 1) { walk_msg->m_type != 1) {
msgtyp = walk_msg->m_type - 1; msgtyp = walk_msg->m_type - 1;
} else if (msgflg & MSG_COPY) { } else if (mode == SEARCH_NUMBER) {
if (copy_number == msg_counter) if (msgtyp == msg_counter)
break; break;
msg = ERR_PTR(-EAGAIN); msg = ERR_PTR(-EAGAIN);
} else } else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment