diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/msg.c | 81 | ||||
-rw-r--r-- | ipc/shm.c | 10 | ||||
-rw-r--r-- | ipc/util.c | 2 |
3 files changed, 43 insertions, 50 deletions
@@ -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; @@ -136,6 +136,7 @@ asmlinkage int sys_shmget (key_t key, int size, int shmflg) struct shmid_ds *shp; int err, id = 0; + down(¤t->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(¤t->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(¤t->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(¤t->mm->mmap_sem); return err; } @@ -634,6 +638,7 @@ asmlinkage int sys_shmdt (char *shmaddr) { struct vm_area_struct *shmd, *shmdnext; + down(¤t->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(¤t->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; } |