summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/msg.c81
-rw-r--r--ipc/shm.c10
-rw-r--r--ipc/util.c2
3 files changed, 43 insertions, 50 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index e505bcc01..bcc58a4c5 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -1,6 +1,13 @@
/*
* linux/ipc/msg.c
* Copyright (C) 1992 Krishna Balasubramanian
+ *
+ * Removed all the remaining kerneld mess
+ * Catch the -EFAULT stuff properly
+ * Use GFP_KERNEL for messages as in 1.2
+ * Fixed up the unchecked user space derefs
+ * Copyright (C) 1998 Alan Cox & Andi Kleen
+ *
*/
#include <linux/errno.h>
@@ -29,7 +36,7 @@ static int used_queues = 0;
static int max_msqid = 0;
static struct wait_queue *msg_lock = NULL;
-__initfunc(void msg_init (void))
+void __init msg_init (void)
{
int id;
@@ -42,21 +49,16 @@ __initfunc(void msg_init (void))
static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
{
- int id, err;
+ int id;
struct msqid_ds *msq;
struct ipc_perm *ipcp;
struct msg *msgh;
long mtype;
- unsigned long flags;
if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
return -EINVAL;
- if (!msgp)
- return -EFAULT;
- err = verify_area (VERIFY_READ, msgp->mtext, msgsz);
- if (err)
- return err;
- get_user(mtype, &msgp->mtype);
+ if (get_user(mtype, &msgp->mtype))
+ return -EFAULT;
if (mtype < 1)
return -EINVAL;
id = (unsigned int) msqid % MSGMNI;
@@ -85,12 +87,16 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
}
/* allocate message header and text space*/
- msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_ATOMIC);
+ msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL);
if (!msgh)
return -ENOMEM;
msgh->msg_spot = (char *) (msgh + 1);
- copy_from_user (msgh->msg_spot, msgp->mtext, msgsz);
+ if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz))
+ {
+ kfree(msgh);
+ return -EFAULT;
+ }
if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
|| msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
@@ -103,8 +109,6 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
msgh->msg_type = mtype;
msgh->msg_stime = CURRENT_TIME;
- save_flags(flags);
- cli();
if (!msq->msg_first)
msq->msg_first = msq->msg_last = msgh;
else {
@@ -117,7 +121,6 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
msq->msg_qnum++;
msq->msg_lspid = current->pid;
msq->msg_stime = CURRENT_TIME;
- restore_flags(flags);
wake_up (&msq->rwait);
return 0;
}
@@ -128,17 +131,10 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
struct ipc_perm *ipcp;
struct msg *tmsg, *leastp = NULL;
struct msg *nmsg = NULL;
- int id, err;
- unsigned long flags;
+ int id;
if (msqid < 0 || (long) msgsz < 0)
return -EINVAL;
- if (!msgp || !msgp->mtext)
- return -EFAULT;
-
- err = verify_area (VERIFY_WRITE, msgp->mtext, msgsz);
- if (err)
- return err;
id = (unsigned int) msqid % MSGMNI;
msq = msgque [id];
@@ -160,8 +156,6 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
return -EACCES;
}
- save_flags(flags);
- cli();
if (msgtyp == 0)
nmsg = msq->msg_first;
else if (msgtyp > 0) {
@@ -186,15 +180,12 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
if (leastp && leastp->msg_type <= - msgtyp)
nmsg = leastp;
}
- restore_flags(flags);
if (nmsg) { /* done finding a message */
if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR)) {
return -E2BIG;
}
msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;
- save_flags(flags);
- cli();
if (nmsg == msq->msg_first)
msq->msg_first = nmsg->msg_next;
else {
@@ -214,10 +205,10 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
msgbytes -= nmsg->msg_ts;
msghdrs--;
msq->msg_cbytes -= nmsg->msg_ts;
- restore_flags(flags);
wake_up (&msq->wwait);
- put_user (nmsg->msg_type, &msgp->mtype);
- copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz);
+ if (put_user (nmsg->msg_type, &msgp->mtype) ||
+ copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz))
+ msgsz = -EFAULT;
kfree(nmsg);
return msgsz;
} else { /* did not find a message */
@@ -395,19 +386,16 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
msginfo.msgmap = msghdrs;
msginfo.msgtql = msgbytes;
}
- err = verify_area (VERIFY_WRITE, buf, sizeof (struct msginfo));
- if (err)
- goto out;
- copy_to_user (buf, &msginfo, sizeof(struct msginfo));
+
+ err = -EFAULT;
+ if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
+ goto out;
err = max_msqid;
goto out;
}
case MSG_STAT:
if (!buf)
goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof (*buf));
- if (err)
- goto out;
err = -EINVAL;
if (msqid > max_msqid)
goto out;
@@ -427,23 +415,21 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
- copy_to_user (buf, &tbuf, sizeof(*buf));
+ err = -EFAULT;
+ if (copy_to_user (buf, &tbuf, sizeof(*buf)))
+ goto out;
err = id;
goto out;
case IPC_SET:
if (!buf)
goto out;
- err = verify_area (VERIFY_READ, buf, sizeof (*buf));
- if (err)
- goto out;
- copy_from_user (&tbuf, buf, sizeof (*buf));
+ err = -EFAULT;
+ if (!copy_from_user (&tbuf, buf, sizeof (*buf)))
+ err = 0;
break;
case IPC_STAT:
if (!buf)
goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof(*buf));
- if (err)
- goto out;
break;
}
@@ -471,8 +457,9 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
- copy_to_user (buf, &tbuf, sizeof (*buf));
- err = 0;
+ err = -EFAULT;
+ if (!copy_to_user (buf, &tbuf, sizeof (*buf)))
+ err = 0;
goto out;
case IPC_SET:
err = -EPERM;
diff --git a/ipc/shm.c b/ipc/shm.c
index 0962be882..c7568b784 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -136,6 +136,7 @@ asmlinkage int sys_shmget (key_t key, int size, int shmflg)
struct shmid_ds *shp;
int err, id = 0;
+ down(&current->mm->mmap_sem);
lock_kernel();
if (size < 0 || size > SHMMAX) {
err = -EINVAL;
@@ -160,6 +161,7 @@ asmlinkage int sys_shmget (key_t key, int size, int shmflg)
err = (int) shp->shm_perm.seq * SHMMNI + id;
}
unlock_kernel();
+ up(&current->mm->mmap_sem);
return err;
}
@@ -484,6 +486,7 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
unsigned long addr;
unsigned long len;
+ down(&current->mm->mmap_sem);
lock_kernel();
if (shmid < 0) {
/* printk("shmat() -> EINVAL because shmid = %d < 0\n",shmid); */
@@ -584,6 +587,7 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
err = 0;
out:
unlock_kernel();
+ up(&current->mm->mmap_sem);
return err;
}
@@ -634,6 +638,7 @@ asmlinkage int sys_shmdt (char *shmaddr)
{
struct vm_area_struct *shmd, *shmdnext;
+ down(&current->mm->mmap_sem);
lock_kernel();
for (shmd = current->mm->mmap; shmd; shmd = shmdnext) {
shmdnext = shmd->vm_next;
@@ -642,6 +647,7 @@ asmlinkage int sys_shmdt (char *shmaddr)
do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start);
}
unlock_kernel();
+ up(&current->mm->mmap_sem);
return 0;
}
@@ -720,7 +726,7 @@ done: /* pte_val(pte) == shp->shm_pages[idx] */
static unsigned long swap_id = 0; /* currently being swapped */
static unsigned long swap_idx = 0; /* next to swap */
-int shm_swap (int prio, int dma)
+int shm_swap (int prio, int gfp_mask)
{
pte_t page;
struct shmid_ds *shp;
@@ -757,7 +763,7 @@ int shm_swap (int prio, int dma)
page = __pte(shp->shm_pages[idx]);
if (!pte_present(page))
goto check_table;
- if (dma && !PageDMA(&mem_map[MAP_NR(pte_page(page))]))
+ if ((gfp_mask & __GFP_DMA) && !PageDMA(&mem_map[MAP_NR(pte_page(page))]))
goto check_table;
swap_attempts++;
diff --git a/ipc/util.c b/ipc/util.c
index fe13f8676..c7933273a 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -64,7 +64,7 @@ void sem_exit (void)
return;
}
-int shm_swap (int prio, unsigned long limit)
+int shm_swap (int prio, int gfp_mask)
{
return 0;
}