--- fs/ext2/file.c.~1~ Mon Dec 21 23:22:54 1998 +++ fs/ext2/file.c Tue Jan 12 17:46:33 1999 @@ -30,6 +30,7 @@ #include #include #include +#include #define NBUF 32 @@ -257,7 +258,9 @@ break; } } + unlock_kernel(); c -= copy_from_user (bh->b_data + offset, buf, c); + lock_kernel(); if (!c) { brelse(bh); if (!written) --- mm/filemap.c.~1~ Thu Jan 7 00:04:38 1999 +++ mm/filemap.c Wed Jan 13 16:33:14 1999 @@ -212,10 +212,21 @@ if (len > count) len = count; + retry: page = find_page(inode, pos); if (page) { - wait_on_page(page); + if (PageLocked(page)) { + wait_on_page(page); + release_page(page); + goto retry; + } + set_bit(PG_locked, &page->flags); + unlock_kernel(); memcpy((void *) (offset + page_address(page)), buf, len); + lock_kernel(); + clear_bit(PG_locked, &page->flags); + if (waitqueue_active(&page->wait)) + wake_up(&page->wait); release_page(page); } count -= len; @@ -753,7 +764,9 @@ if (size > count) size = count; + unlock_kernel(); left = __copy_to_user(desc->buf, area, size); + lock_kernel(); if (left) { size -= left; desc->error = -EFAULT; --- ./fs/pipe.c.~1~ Sun Jan 3 07:03:03 1999 +++ ./fs/pipe.c Fri Jan 22 06:26:19 1999 @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -68,7 +69,9 @@ static ssize_t pipe_read(struct file * f PIPE_START(*inode) &= (PIPE_BUF-1); PIPE_LEN(*inode) -= chars; count -= chars; + unlock_kernel(); copy_to_user(buf, pipebuf, chars ); + lock_kernel(); buf += chars; } PIPE_LOCK(*inode)--; @@ -134,7 +137,9 @@ static ssize_t pipe_write(struct file * written += chars; PIPE_LEN(*inode) += chars; count -= chars; + unlock_kernel(); copy_from_user(pipebuf, buf, chars ); + lock_kernel(); buf += chars; } PIPE_LOCK(*inode)--; --- ./mm/memory.c.~1~ Mon Jan 18 18:48:34 1999 +++ ./mm/memory.c Fri Jan 22 05:42:08 1999 @@ -545,19 +545,6 @@ int remap_page_range(unsigned long from, } /* - * sanity-check function.. - */ -static void put_page(pte_t * page_table, pte_t pte) -{ - if (!pte_none(*page_table)) { - free_page_and_swap_cache(pte_page(pte)); - return; - } -/* no need for flush_tlb */ - set_pte(page_table, pte); -} - -/* * This routine is used to map in a page into an address space: needed by * execve() for the initial stack and environment pages. */ @@ -817,7 +804,8 @@ static int do_anonymous_page(struct task tsk->min_flt++; flush_page_to_ram(page); } - put_page(page_table, entry); + wmb(); + set_pte(page_table, entry); return 1; } @@ -875,7 +863,8 @@ static int do_no_page(struct task_struct } else if (atomic_read(&mem_map[MAP_NR(page)].count) > 1 && !(vma->vm_flags & VM_SHARED)) entry = pte_wrprotect(entry); - put_page(page_table, entry); + wmb(); + set_pte(page_table, entry); /* no need to invalidate: a not-present page shouldn't be cached */ return 1; } --- ./net/ipv4/tcp.c.~1~ Sat Jan 9 03:20:07 1999 +++ ./net/ipv4/tcp.c Fri Jan 22 06:26:32 1999 @@ -415,6 +415,7 @@ #include #include #include +#include #include #include @@ -891,6 +892,8 @@ int tcp_do_sendmsg(struct sock *sk, int continue; } + unlock_kernel(); + seglen -= copy; /* Prepare control bits for TCP header creation engine. */ @@ -909,8 +912,10 @@ int tcp_do_sendmsg(struct sock *sk, int * Reserve header space and checksum the data. */ skb_reserve(skb, MAX_HEADER + sk->prot->max_header); + skb->csum = csum_and_copy_from_user(from, skb_put(skb, copy), copy, 0, &err); + lock_kernel(); if (err) goto do_fault; @@ -1261,7 +1266,11 @@ int tcp_recvmsg(struct sock *sk, struct * do a second read it relies on the skb->users to avoid * a crash when cleanup_rbuf() gets called. */ + + unlock_kernel(); err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used); + lock_kernel(); + if (err) { /* Exception. Bailout! */ atomic_dec(&skb->users); --- ./net/ipv4/udp.c.~1~ Sun Jan 3 07:56:15 1999 +++ ./net/ipv4/udp.c Fri Jan 22 08:08:06 1999 @@ -105,6 +105,7 @@ #include #include #include +#include #include #include #include @@ -585,10 +586,14 @@ struct udpfakehdr static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned int fraglen) { struct udpfakehdr *ufh = (struct udpfakehdr *)p; + int err = 0; + + unlock_kernel(); if (offset==0) { + err = -EFAULT; if (csum_partial_copy_fromiovecend(to+sizeof(struct udphdr), ufh->iov, offset, fraglen-sizeof(struct udphdr), &ufh->wcheck)) - return -EFAULT; + goto out; ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr), ufh->wcheck); ufh->uh.check = csum_tcpudp_magic(ufh->saddr, ufh->daddr, @@ -597,12 +602,14 @@ static int udp_getfrag(const void *p, ch if (ufh->uh.check == 0) ufh->uh.check = -1; memcpy(to, ufh, sizeof(struct udphdr)); - return 0; - } - if (csum_partial_copy_fromiovecend(to, ufh->iov, offset-sizeof(struct udphdr), - fraglen, &ufh->wcheck)) - return -EFAULT; - return 0; + err = 0; + } else if (csum_partial_copy_fromiovecend(to, ufh->iov, + offset-sizeof(struct udphdr), + fraglen, &ufh->wcheck)) + err = -EFAULT; +out: + lock_kernel(); + return err; } /* @@ -615,14 +622,19 @@ static int udp_getfrag(const void *p, ch static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset, unsigned int fraglen) { struct udpfakehdr *ufh = (struct udpfakehdr *)p; + int ret; + unlock_kernel(); if (offset==0) { memcpy(to, ufh, sizeof(struct udphdr)); - return memcpy_fromiovecend(to+sizeof(struct udphdr), ufh->iov, offset, - fraglen-sizeof(struct udphdr)); - } - return memcpy_fromiovecend(to, ufh->iov, offset-sizeof(struct udphdr), - fraglen); + ret = memcpy_fromiovecend(to+sizeof(struct udphdr), ufh->iov, offset, + fraglen-sizeof(struct udphdr)); + } else + ret = memcpy_fromiovecend(to, ufh->iov, offset-sizeof(struct udphdr), + fraglen); + lock_kernel(); + + return ret; } int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len) @@ -887,24 +899,32 @@ int udp_recvmsg(struct sock *sk, struct } #ifndef CONFIG_UDP_DELAY_CSUM + unlock_kernel(); err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, copied); + lock_kernel(); #else if (sk->no_check || skb->ip_summed==CHECKSUM_UNNECESSARY) { + unlock_kernel(); err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, copied); + lock_kernel(); } else if (copied > msg->msg_iov[0].iov_len || (msg->msg_flags&MSG_TRUNC)) { if (csum_fold(csum_partial(skb->h.raw, ntohs(skb->h.uh->len), skb->csum))) goto csum_copy_err; + unlock_kernel(); err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, copied); + lock_kernel(); } else { unsigned int csum; err = 0; + unlock_kernel(); csum = csum_partial(skb->h.raw, sizeof(struct udphdr), skb->csum); csum = csum_and_copy_to_user((char*)&skb->h.uh[1], msg->msg_iov[0].iov_base, copied, csum, &err); + lock_kernel(); if (err) goto out_free; if (csum_fold(csum)) --- ./net/unix/af_unix.c.~1~ Thu Jan 14 22:54:23 1999 +++ ./net/unix/af_unix.c Fri Jan 22 06:26:45 1999 @@ -93,6 +93,7 @@ #include #include #include +#include #include @@ -936,7 +937,11 @@ static int unix_dgram_sendmsg(struct soc unix_attach_fds(scm, skb); skb->h.raw = skb->data; + + unlock_kernel(); err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); + lock_kernel(); + if (err) goto out_free; @@ -1068,11 +1073,19 @@ static int unix_stream_sendmsg(struct so if (scm->fp) unix_attach_fds(scm, skb); - if (memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) { - kfree_skb(skb); - if (sent) - goto out; - return -EFAULT; + { + int err; + + unlock_kernel(); + err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size); + lock_kernel(); + + if(err) { + kfree_skb(skb); + if (sent) + goto out; + return -EFAULT; + } } other=unix_peer(sk); @@ -1143,7 +1156,10 @@ static int unix_dgram_recvmsg(struct soc else if (size < skb->len) msg->msg_flags |= MSG_TRUNC; + unlock_kernel(); err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); + lock_kernel(); + if (err) goto out_free; @@ -1263,11 +1279,19 @@ static int unix_stream_recvmsg(struct so } chunk = min(skb->len, size); - if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { - skb_queue_head(&sk->receive_queue, skb); - if (copied == 0) - copied = -EFAULT; - break; + { + int err; + + unlock_kernel(); + err = memcpy_toiovec(msg->msg_iov, skb->data, chunk); + lock_kernel(); + + if(err) { + skb_queue_head(&sk->receive_queue, skb); + if (copied == 0) + copied = -EFAULT; + break; + } } copied += chunk; size -= chunk;