## Automatically generated incremental diff ## From: linux-2.5.64-bk5 ## To: linux-2.5.64-bk6 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.64-bk5/Documentation/crypto/api-intro.txt linux-2.5.64-bk6/Documentation/crypto/api-intro.txt --- linux-2.5.64-bk5/Documentation/crypto/api-intro.txt Tue Mar 4 19:29:31 2003 +++ linux-2.5.64-bk6/Documentation/crypto/api-intro.txt Mon Mar 31 12:28:48 2003 @@ -38,9 +38,8 @@ Compressors. The compression algorithms especially seem to be performing very well so far. -An asynchronous scheduling interface is in planning but not yet -implemented, as we need to further analyze the requirements of all of -the possible hardware scenarios (e.g. IPsec NIC offload). +Support for hardware crypto devices via an asynchronous interface is +under development. Here's an example of how to use the API: @@ -87,8 +86,8 @@ DEVELOPER NOTES -None of this code should be called from hardirq context, only softirq and -user contexts. +Transforms may only be allocated in user context, and cryptographic +methods may only be called from softirq and user contexts. When using the API for ciphers, performance will be optimal if each scatterlist contains data which is a multiple of the cipher's block @@ -137,16 +136,11 @@ list, see: http://samba.org/~jamesm/crypto/ -Ongoing development discussion may also be found on -kerneli cryptoapi-devel, -see http://www.kerneli.org/mailman/listinfo/cryptoapi-devel - AUTHORS James Morris David S. Miller -Jean-Francois Dive (SHA1 algorithm module) CREDITS @@ -191,6 +185,10 @@ Matthew Skala (Twofish) Dag Arne Osvik (Serpent) Brian Gladman (AES) + + +SHA1 algorithm contributors: + Jean-Francois Dive DES algorithm contributors: Raimar Falke @@ -216,6 +214,8 @@ Kyle McMartin Adam J. Richter +Generic scatterwalk code by Adam J. Richter + Please send any credits updates or corrections to: James Morris diff -urN linux-2.5.64-bk5/Makefile linux-2.5.64-bk6/Makefile --- linux-2.5.64-bk5/Makefile Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/Makefile Mon Mar 31 12:28:48 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 64 -EXTRAVERSION = bk5 +EXTRAVERSION = bk6 # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff -urN linux-2.5.64-bk5/arch/i386/boot/Makefile linux-2.5.64-bk6/arch/i386/boot/Makefile --- linux-2.5.64-bk5/arch/i386/boot/Makefile Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/arch/i386/boot/Makefile Mon Mar 31 12:28:48 2003 @@ -65,33 +65,33 @@ # Set this if you want to pass append arguments to the zdisk/fdimage kernel FDARGS = -$(obj)/mtools.conf: $(obj)/mtools.conf.in +$(obj)/mtools.conf: $(src)/mtools.conf.in sed -e 's|@OBJ@|$(obj)|g' < $< > $@ # This requires write access to /dev/fd0 zdisk: $(BOOTIMAGE) $(obj)/mtools.conf - MTOOLSRC=$(src)/mtools.conf mformat a: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync syslinux /dev/fd0 ; sync echo 'default linux $(FDARGS)' | \ MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync # These require being root or having syslinux 2.02 or higher installed -fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf +fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 - MTOOLSRC=$(src)/mtools.conf mformat v: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - v:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync -fdimage288: $(BOOTIMAGE) $(src)/mtools.conf +fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 - MTOOLSRC=$(src)/mtools.conf mformat w: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - w:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync zlilo: $(BOOTIMAGE) if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi diff -urN linux-2.5.64-bk5/arch/i386/kernel/cpu/common.c linux-2.5.64-bk6/arch/i386/kernel/cpu/common.c --- linux-2.5.64-bk5/arch/i386/kernel/cpu/common.c Tue Mar 4 19:28:56 2003 +++ linux-2.5.64-bk6/arch/i386/kernel/cpu/common.c Mon Mar 31 12:28:48 2003 @@ -480,7 +480,7 @@ */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; - if(current->mm) + if (current->mm) BUG(); enter_lazy_tlb(&init_mm, current, cpu); @@ -508,7 +508,7 @@ /* * Force FPU initialization: */ - clear_thread_flag(TIF_USEDFPU); + current_thread_info()->status = 0; current->used_math = 0; stts(); } diff -urN linux-2.5.64-bk5/arch/i386/kernel/entry.S linux-2.5.64-bk6/arch/i386/kernel/entry.S --- linux-2.5.64-bk5/arch/i386/kernel/entry.S Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/arch/i386/kernel/entry.S Mon Mar 31 12:28:48 2003 @@ -72,6 +72,12 @@ NT_MASK = 0x00004000 VM_MASK = 0x00020000 +/* + * ESP0 is at offset 4. 0x100 is the size of the TSS, and + * also thus the top-of-stack pointer offset of SYSENTER_ESP + */ +TSS_ESP0_OFFSET = (4 - 0x100) + #ifdef CONFIG_PREEMPT #define preempt_stop cli #else @@ -229,6 +235,8 @@ # sysenter call handler stub ENTRY(sysenter_entry) + movl TSS_ESP0_OFFSET(%esp),%esp +sysenter_past_esp: sti pushl $(__USER_DS) pushl %ebp @@ -458,12 +466,36 @@ addl $4, %esp jmp ret_from_exception +/* + * Debug traps and NMI can happen at the one SYSENTER instruction + * that sets up the real kernel stack. Check here, since we can't + * allow the wrong stack to be used. + * + * "TSS_ESP0_OFFSET+12" is because the NMI/debug handler will have + * already pushed 3 words if it hits on the sysenter instruction: + * eflags, cs and eip. + * + * We just load the right stack, and push the three (known) values + * by hand onto the new stack - while updating the return eip past + * the instruction that would have done it for sysenter. + */ +#define CHECK_SYSENTER_EIP \ + cmpl $sysenter_entry,(%esp); \ + jne 1f; \ + movl TSS_ESP0_OFFSET+12(%esp),%esp; \ + pushfl; \ + pushl $__KERNEL_CS; \ + pushl $sysenter_past_esp; \ +1: + ENTRY(debug) + CHECK_SYSENTER_EIP pushl $0 pushl $do_debug jmp error_code ENTRY(nmi) + CHECK_SYSENTER_EIP pushl %eax SAVE_ALL movl %esp, %edx diff -urN linux-2.5.64-bk5/arch/i386/kernel/i387.c linux-2.5.64-bk6/arch/i386/kernel/i387.c --- linux-2.5.64-bk5/arch/i386/kernel/i387.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/arch/i386/kernel/i387.c Mon Mar 31 12:28:48 2003 @@ -54,9 +54,11 @@ void kernel_fpu_begin(void) { + struct thread_info *thread = current_thread_info(); + preempt_disable(); - if (test_thread_flag(TIF_USEDFPU)) { - __save_init_fpu(current); + if (thread->status & TS_USEDFPU) { + __save_init_fpu(thread->task); return; } clts(); diff -urN linux-2.5.64-bk5/arch/i386/kernel/process.c linux-2.5.64-bk6/arch/i386/kernel/process.c --- linux-2.5.64-bk5/arch/i386/kernel/process.c Tue Mar 4 19:28:52 2003 +++ linux-2.5.64-bk6/arch/i386/kernel/process.c Mon Mar 31 12:28:48 2003 @@ -275,6 +275,15 @@ release_x86_irqs(dead_task); } +/* + * This gets called before we allocate a new thread and copy + * the current task into it. + */ +void prepare_to_copy(struct task_struct *tsk) +{ + unlazy_fpu(tsk); +} + int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) @@ -297,9 +306,6 @@ savesegment(gs,p->thread.gs); tsk = current; - unlazy_fpu(tsk); - struct_cpy(&p->thread.i387, &tsk->thread.i387); - if (unlikely(NULL != tsk->thread.ts_io_bitmap)) { p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); if (!p->thread.ts_io_bitmap) diff -urN linux-2.5.64-bk5/arch/i386/kernel/sysenter.c linux-2.5.64-bk6/arch/i386/kernel/sysenter.c --- linux-2.5.64-bk5/arch/i386/kernel/sysenter.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/arch/i386/kernel/sysenter.c Mon Mar 31 12:28:48 2003 @@ -41,8 +41,9 @@ struct tss_struct *tss = init_tss + cpu; tss->ss1 = __KERNEL_CS; + tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0); + wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0); wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0); printk("Enabling SEP on CPU %d\n", cpu); diff -urN linux-2.5.64-bk5/arch/i386/kernel/traps.c linux-2.5.64-bk6/arch/i386/kernel/traps.c --- linux-2.5.64-bk5/arch/i386/kernel/traps.c Tue Mar 4 19:29:01 2003 +++ linux-2.5.64-bk6/arch/i386/kernel/traps.c Mon Mar 31 12:28:48 2003 @@ -737,13 +737,14 @@ */ asmlinkage void math_state_restore(struct pt_regs regs) { - struct task_struct *tsk = current; - clts(); /* Allow maths ops (or we recurse) */ + struct thread_info *thread = current_thread_info(); + struct task_struct *tsk = thread->task; + clts(); /* Allow maths ops (or we recurse) */ if (!tsk->used_math) init_fpu(tsk); restore_fpu(tsk); - set_thread_flag(TIF_USEDFPU); /* So we fnsave on switch_to() */ + thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ } #ifndef CONFIG_MATH_EMULATION diff -urN linux-2.5.64-bk5/arch/ia64/ia32/ia32_entry.S linux-2.5.64-bk6/arch/ia64/ia32/ia32_entry.S --- linux-2.5.64-bk5/arch/ia64/ia32/ia32_entry.S Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/arch/ia64/ia32/ia32_entry.S Mon Mar 31 12:28:48 2003 @@ -300,7 +300,7 @@ data8 compat_sys_statfs data8 compat_sys_fstatfs /* 100 */ data8 sys32_ioperm - data8 sys32_socketcall + data8 compat_sys_socketcall data8 sys_syslog data8 compat_sys_setitimer data8 compat_sys_getitimer /* 105 */ diff -urN linux-2.5.64-bk5/arch/ia64/ia32/ia32_ioctl.c linux-2.5.64-bk6/arch/ia64/ia32/ia32_ioctl.c --- linux-2.5.64-bk5/arch/ia64/ia32/ia32_ioctl.c Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/arch/ia64/ia32/ia32_ioctl.c Mon Mar 31 12:28:48 2003 @@ -97,11 +97,9 @@ int info; /* [o] auxiliary information */ } sg_io_hdr32_t; /* 64 bytes long (on IA32) */ -struct iovec32 { unsigned int iov_base; int iov_len; }; - static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32) { - struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); sg_iovec_t *kiov; int i; @@ -136,7 +134,7 @@ static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32) { - struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; int i; diff -urN linux-2.5.64-bk5/arch/ia64/ia32/sys_ia32.c linux-2.5.64-bk6/arch/ia64/ia32/sys_ia32.c --- linux-2.5.64-bk5/arch/ia64/ia32/sys_ia32.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/arch/ia64/ia32/sys_ia32.c Mon Mar 31 12:28:48 2003 @@ -924,12 +924,11 @@ (struct compat_timeval *) A(a.tvp)); } -struct iovec32 { unsigned int iov_base; int iov_len; }; asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long); asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long); static struct iovec * -get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type) +get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) { int i; u32 buf, len; @@ -939,7 +938,7 @@ if (!count) return 0; - if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) return NULL; if (count > UIO_MAXIOV) return NULL; @@ -971,14 +970,14 @@ } asmlinkage long -sys32_readv (int fd, struct iovec32 *vector, u32 count) +sys32_readv (int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; long ret; mm_segment_t old_fs = get_fs(); - iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE); + iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE); if (!iov) return -EFAULT; set_fs(KERNEL_DS); @@ -990,14 +989,14 @@ } asmlinkage long -sys32_writev (int fd, struct iovec32 *vector, u32 count) +sys32_writev (int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; long ret; mm_segment_t old_fs = get_fs(); - iov = get_iovec32(vector, iovstack, count, VERIFY_READ); + iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ); if (!iov) return -EFAULT; set_fs(KERNEL_DS); @@ -1079,701 +1078,6 @@ return ret; } -/* - * Declare the IA32 version of the msghdr - */ - -struct msghdr32 { - unsigned int msg_name; /* Socket name */ - int msg_namelen; /* Length of name */ - unsigned int msg_iov; /* Data blocks */ - unsigned int msg_iovlen; /* Number of blocks */ - unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ - unsigned int msg_controllen; /* Length of cmsg list */ - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) -#define CMSG32_DATA(cmsg) \ - ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) \ - (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) -#define __CMSG32_FIRSTHDR(ctl,len) \ - ((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -static inline struct cmsghdr32 * -__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len) -{ - struct cmsghdr32 * ptr; - - ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len)); - if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size) - return NULL; - return ptr; -} - -static inline struct cmsghdr32 * -cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len) -{ - return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len); -} - -static inline int -get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32) -{ - int ret; - unsigned int i; - - if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) - return -EFAULT; - ret = __get_user(i, &mp32->msg_name); - mp->msg_name = (void *)A(i); - ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); - ret |= __get_user(i, &mp32->msg_iov); - mp->msg_iov = (struct iovec *)A(i); - ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); - ret |= __get_user(i, &mp32->msg_control); - mp->msg_control = (void *)A(i); - ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); - ret |= __get_user(mp->msg_flags, &mp32->msg_flags); - return ret ? -EFAULT : 0; -} - -/* - * There is a lot of hair here because the alignment rules (and thus placement) of cmsg - * headers and length are different for 32-bit apps. -DaveM - */ -static int -get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize) -{ - struct cmsghdr *kcmsg, *kcmsg_base; - __kernel_size_t kcmlen, tmp; - compat_size_t ucmlen; - struct cmsghdr32 *ucmsg; - long err; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - if (get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen) - > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if (kcmlen == 0) - return -EINVAL; - - /* - * The kcmlen holds the 64-bit version of the control length. It may not be - * modified as we do not stick it into the kmsg until we have successfully copied - * over all of the data from the user. - */ - if (kcmlen > *bufsize) { - *bufsize = kcmlen; - kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL); - } - if (kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - err = get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))); - if (err) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if (kcmsg_base != (struct cmsghdr *)stackbuf) - sock_kfree_s(sk, kcmsg_base, kcmlen); - return -EFAULT; -} - -/* - * Verify & re-shape IA32 iovec. The caller must ensure that the - * iovec is big enough to hold the re-shaped message iovec. - * - * Save time not doing verify_area. copy_*_user will make this work - * in any case. - * - * Don't need to check the total size for overflow (cf net/core/iovec.c), - * 32-bit sizes can't overflow a 64-bit count. - */ - -static inline int -verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode) -{ - int size, err, ct; - struct iovec32 *iov32; - - if (m->msg_namelen) { - if (mode == VERIFY_READ) { - err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - if (err < 0) - goto out; - } - m->msg_name = address; - } else - m->msg_name = NULL; - - err = -EFAULT; - size = m->msg_iovlen * sizeof(struct iovec32); - if (copy_from_user(iov, m->msg_iov, size)) - goto out; - m->msg_iov = iov; - - err = 0; - iov32 = (struct iovec32 *)iov; - for (ct = m->msg_iovlen; ct-- > 0; ) { - iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; - iov[ct].iov_base = (void *) A(iov32[ct].iov_base); - err += iov[ct].iov_len; - } -out: - return err; -} - -static void -put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, - cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void -scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) - / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); - i < fdmax; - i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - current->files->fd[new_fd] = fp[i]; - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* - * In these cases we (currently) can just copy to data over verbatim because all CMSGs - * created by the kernel have well defined types which have the same layout in both the - * 32-bit and 64-bit API. One must add some special cased conversions here if we start - * sending control messages with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void -cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - long err; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if (workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while (((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* - * UCMSG is the 64-bit format CMSG entry in user-space. KCMSG32 is within - * the kernel space temporary buffer we use to convert into a 32-bit style - * CMSG. - */ - err = get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - err |= get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - err |= get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - if (err) - goto fail2; - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - if (copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz)) - goto fail2; - - kmsg->msg_control = (struct cmsghdr *) (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - kfree(workbuf); - return; - - fail2: - kfree(workbuf); - fail: - /* - * If we leave the 64-bit format CMSG chunks in there, the application could get - * confused and crash. So to ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ -/* - * BSD sendmsg interface - */ - -int -sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, iov_size, total_len; - size_t ctl_len; - - err = -EFAULT; - if (get_msghdr32(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - if (msg_sys.msg_controllen) { - ctl_len = sizeof(ctl); - err = get_cmsghdr32(&msg_sys, ctl_buf, sock->sk, &ctl_len); - if (err) - goto out_freeiov; - ctl_buf = msg_sys.msg_control; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err = -EFAULT; - if (get_msghdr32(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - - /* XXX This code needs massive updating... -DaveM */ - lock_kernel(); - { - struct sock_iocb *si; - struct kiocb iocb; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &msg_sys; - si->size = total_len; - si->flags = flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len, - flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if (err < 0) - goto out_unlock_freeiov; - - len = err; - if (!msg_sys.msg_control) { - if (sock->passcred || si->scm->fp) - msg_sys.msg_flags |= MSG_CTRUNC; - if (si->scm->fp) - __scm_destroy(si->scm); - } else { - /* - * If recvmsg processing itself placed some control messages into - * user space, it's is using 64-bit CMSG processing, so we need to - * fix it up before we tack on more stuff. - */ - if ((unsigned long) msg_sys.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr); - - /* Wheee... */ - if (sock->passcred) - put_cmsg32(&msg_sys, SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if (si->scm->fp != NULL) - scm_detach_fds32(&msg_sys, si->scm); - } - } - unlock_kernel(); - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - - out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); - out_put: - sockfd_put(sock); - out: - return err; - - out_unlock_freeiov: - goto out_freeiov; -} - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, - int addrlen); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, - int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage long sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); - -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_listen(int fd, int backlog); - -asmlinkage long -sys32_socketcall (int call, u32 *args) -{ - int ret; - u32 a[6]; - u32 a0,a1; - - if (callSYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - ret = sys_socket(a0, a1, a[2]); - break; - case SYS_BIND: - ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a0, a1); - break; - case SYS_ACCEPT: - ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_RECV: - ret = sys_recv(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a0,a1); - break; - case SYS_SETSOCKOPT: - ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]); - break; - default: - ret = EINVAL; - break; - } - return ret; -} - /* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * diff -urN linux-2.5.64-bk5/arch/mips64/kernel/linux32.c linux-2.5.64-bk6/arch/mips64/kernel/linux32.c --- linux-2.5.64-bk5/arch/mips64/kernel/linux32.c Tue Mar 4 19:29:24 2003 +++ linux-2.5.64-bk6/arch/mips64/kernel/linux32.c Mon Mar 31 12:28:48 2003 @@ -729,12 +729,10 @@ return sys_llseek(fd, offset_high, offset_low, result, origin); } -struct iovec32 { unsigned int iov_base; int iov_len; }; - typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); static long -do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, +do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, u32 count) { unsigned long tot_len; @@ -749,7 +747,7 @@ */ if (!count) return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -835,7 +833,7 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -855,7 +853,7 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1155,48 +1153,6 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) { - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - kfprog.filter = kfilter; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - kfree(kfilter); - return ret; - } - return sys_setsockopt(fd, level, optname, optval, optlen); -} - struct flock32 { short l_type; short l_whence; @@ -1873,256 +1829,3 @@ return ret; } -/* - * Declare the 32-bit version of the msghdr - */ - -struct msghdr32 { - unsigned int msg_name; /* Socket name */ - int msg_namelen; /* Length of name */ - unsigned int msg_iov; /* Data blocks */ - unsigned int msg_iovlen; /* Number of blocks */ - unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ - unsigned int msg_controllen; /* Length of cmsg list */ - unsigned msg_flags; -}; - -static inline int -shape_msg(struct msghdr *mp, struct msghdr32 *mp32) -{ - int ret; - unsigned int i; - - if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) - return(-EFAULT); - ret = __get_user(i, &mp32->msg_name); - mp->msg_name = (void *)A(i); - ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); - ret |= __get_user(i, &mp32->msg_iov); - mp->msg_iov = (struct iovec *)A(i); - ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); - ret |= __get_user(i, &mp32->msg_control); - mp->msg_control = (void *)A(i); - ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); - ret |= __get_user(mp->msg_flags, &mp32->msg_flags); - return(ret ? -EFAULT : 0); -} - -/* - * Verify & re-shape IA32 iovec. The caller must ensure that the - * iovec is big enough to hold the re-shaped message iovec. - * - * Save time not doing verify_area. copy_*_user will make this work - * in any case. - * - * Don't need to check the total size for overflow (cf net/core/iovec.c), - * 32-bit sizes can't overflow a 64-bit count. - */ - -static inline int -verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode) -{ - int size, err, ct; - struct iovec32 *iov32; - - if(m->msg_namelen) - { - if(mode==VERIFY_READ) - { - err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - if(err<0) - goto out; - } - - m->msg_name = address; - } else - m->msg_name = NULL; - - err = -EFAULT; - size = m->msg_iovlen * sizeof(struct iovec32); - if (copy_from_user(iov, m->msg_iov, size)) - goto out; - m->msg_iov=iov; - - err = 0; - iov32 = (struct iovec32 *)iov; - for (ct = m->msg_iovlen; ct-- > 0; ) { - iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; - iov[ct].iov_base = (void *) A(iov32[ct].iov_base); - err += iov[ct].iov_len; - } -out: - return err; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -/* - * BSD sendmsg interface - */ - -int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { - if (ctl_len > sizeof(ctl)) - { - err = -ENOBUFS; - ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) - goto out_freeiov; - } - err = -EFAULT; - if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len)) - goto out_freectl; - msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err=-EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &msg_sys, total_len, flags); - if (err < 0) - goto out_freeiov; - len = err; - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} diff -urN linux-2.5.64-bk5/arch/mips64/kernel/scall_o32.S linux-2.5.64-bk6/arch/mips64/kernel/scall_o32.S --- linux-2.5.64-bk5/arch/mips64/kernel/scall_o32.S Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/arch/mips64/kernel/scall_o32.S Mon Mar 31 12:28:48 2003 @@ -378,8 +378,8 @@ sys sys32_select 5 sys sys_flock 2 sys sys_msync 3 - sys sys32_readv 3 /* 4145 */ - sys sys32_writev 3 + sys compat_sys_readv 3 /* 4145 */ + sys compat_sys_writev 3 sys sys_cacheflush 3 sys sys_cachectl 3 sys sys_sysmips 4 @@ -410,11 +410,11 @@ sys sys_listen 2 sys sys_recv 4 /* 4175 */ sys sys_recvfrom 6 - sys sys32_recvmsg 3 + sys compat_sys_recvmsg 3 sys sys_send 4 - sys sys32_sendmsg 3 + sys compat_sys_sendmsg 3 sys sys_sendto 6 /* 4180 */ - sys sys32_setsockopt 5 + sys compat_sys_setsockopt 5 sys sys_shutdown 2 sys sys_socket 3 sys sys_socketpair 4 diff -urN linux-2.5.64-bk5/arch/parisc/kernel/sys_parisc32.c linux-2.5.64-bk6/arch/parisc/kernel/sys_parisc32.c --- linux-2.5.64-bk5/arch/parisc/kernel/sys_parisc32.c Tue Mar 4 19:29:15 2003 +++ linux-2.5.64-bk6/arch/parisc/kernel/sys_parisc32.c Mon Mar 31 12:28:48 2003 @@ -919,12 +919,10 @@ /* readv/writev stolen from mips64 */ -struct iovec32 { unsigned int iov_base; int iov_len; }; - typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); static long -do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, +do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, u32 count) { unsigned long tot_len; @@ -939,7 +937,7 @@ */ if (!count) return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -1025,7 +1023,7 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1045,7 +1043,7 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1063,747 +1061,6 @@ return ret; } -/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/ -#include -#include -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -extern struct socket *sockfd_lookup(int fd, int *err); - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - - -static int do_ipv4_set_replace(int fd, int level, int optname, - char *optval, int optlen) -#if 1 -/* Fields happen to be padded such that this works. -** Don't need to change iptables.h:struct ipt_replace -*/ -{ - struct ipt_replace *repl = (struct ipt_replace *) optval; - unsigned long ptr64; - unsigned int ptr32; - int ret; - - if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32))) - return -EFAULT; - ptr64 = (unsigned long) ptr32; - if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64))) - return -EFAULT; - - ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); - - /* Restore 32-bit ptr */ - if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32))) - return -EFAULT; - - return ret; -} -#else -/* This version tries to "do it right". ie allocate kernel buffers for -** everything and copy data in/out. Way too complicated. -** NOT TESTED for correctness! -*/ -{ - struct ipt_replace *kern_repl; - struct ipt_counters *kern_counters; - unsigned int user_counters; - mm_segment_t old_fs; - int ret = 0; - - kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL); - if (!kern_repl) - return -ENOMEM; - - if (copy_from_user(kern_repl, optval, optlen)) { - ret = -EFAULT; - goto err02; - } - - /* 32-bit ptr is in the MSB's */ - user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32); - /* - ** We are going to set_fs() to kernel space - and thus need - ** "relocate" the counters buffer to the kernel space. - */ - kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL); - if (!user_counters) { - ret = -ENOMEM; - goto err02; - } - - if (copy_from_user(kern_counters, (char *) user_counters, optlen)) { - ret = -EFAULT; - goto err01; - } - - /* We can update the kernel ptr now that we have the data. */ - kern_repl->counters = kern_counters; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); - - set_fs(old_fs); - - /* Copy counters back out to user space */ - if (copy_to_user((char *) user_counters, kern_counters, - kern_repl->num_counters * sizeof(struct ipt_counters))) - { - ret = -EFAULT; - goto err01; - } - - /* restore counters so userspace can consume it */ - kern_repl->counters = NULL; - (unsigned int) kern_repl->counters = user_counters; - - /* Copy repl back out to user space */ - if (copy_to_user(optval, kern_repl, optlen)) - { - ret = -EFAULT; - } - -err01: - kfree(kern_counters); -err02: - kfree(kern_repl); - return ret; -} -#endif - - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, optval, optlen); - - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, optval, optlen); - - /* - ** Beware: IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE - */ - if (level == IPPROTO_IP && optname == IPT_SO_SET_REPLACE) - return do_ipv4_set_replace(fd, level, optname, optval, optlen); - - if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE) -#if 0 - /* FIXME: I don't (yet) use IPV6. -ggg */ - return do_ipv6_set_replace(fd, level, optname, optval, optlen); -#else - { - BUG(); - return -ENXIO; - } -#endif - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - - /*** copied from mips64 ***/ /* * Ooo, nasty. We need here to frob 32-bit unsigned longs to diff -urN linux-2.5.64-bk5/arch/ppc64/kernel/misc.S linux-2.5.64-bk6/arch/ppc64/kernel/misc.S --- linux-2.5.64-bk5/arch/ppc64/kernel/misc.S Tue Mar 4 19:29:34 2003 +++ linux-2.5.64-bk6/arch/ppc64/kernel/misc.S Mon Mar 31 12:28:48 2003 @@ -604,7 +604,7 @@ .llong .compat_sys_statfs .llong .compat_sys_fstatfs /* 100 */ .llong .sys_ioperm - .llong .sys32_socketcall + .llong .compat_sys_socketcall .llong .sys32_syslog .llong .compat_sys_setitimer .llong .compat_sys_getitimer /* 105 */ diff -urN linux-2.5.64-bk5/arch/ppc64/kernel/sys32.S linux-2.5.64-bk6/arch/ppc64/kernel/sys32.S --- linux-2.5.64-bk5/arch/ppc64/kernel/sys32.S Tue Mar 4 19:29:34 2003 +++ linux-2.5.64-bk6/arch/ppc64/kernel/sys32.S Mon Mar 31 12:28:48 2003 @@ -25,7 +25,7 @@ extsw r4,r4 /* sign extend off_t offset parm */ b .sys_lseek -_GLOBAL(sys32_socketcall) /* r3=call, r4=args */ +_GLOBAL(compat_sys_socketcall) /* r3=call, r4=args */ cmpwi r3, 1 blt- .do_einval cmpwi r3, 17 @@ -221,14 +221,14 @@ .llong 2b,.do_efault .previous -_STATIC(do_sys_setsockopt) /* sys32_setsockopt(int, int, int, char *, int) */ +_STATIC(do_sys_setsockopt) /* compat_sys_setsockopt(int, int, int, char *, int) */ mr r10,r4 1: lwa r3,0(r10) 2: lwa r4,4(r10) 3: lwa r5,8(r10) 4: lwz r6,12(r10) 5: lwa r7,16(r10) - b .sys32_setsockopt + b .compat_sys_setsockopt .section __ex_table,"a" .align 3 .llong 1b,.do_efault @@ -238,14 +238,14 @@ .llong 5b,.do_efault .previous -_STATIC(do_sys_getsockopt) /* sys32_getsockopt(int, int, int, u32, u32) */ +_STATIC(do_sys_getsockopt) /* compat_sys_getsockopt(int, int, int, u32, u32) */ mr r10,r4 1: lwa r3,0(r10) 2: lwa r4,4(r10) 3: lwa r5,8(r10) 4: lwz r6,12(r10) 5: lwz r7,16(r10) - b .sys32_getsockopt + b .compat_sys_getsockopt .section __ex_table,"a" .align 3 .llong 1b,.do_efault @@ -255,12 +255,12 @@ .llong 5b,.do_efault .previous -_STATIC(do_sys_sendmsg) /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ +_STATIC(do_sys_sendmsg) /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ mr r10,r4 1: lwa r3,0(r10) 2: lwz r4,4(r10) 3: lwa r5,8(r10) - b .sys32_sendmsg + b .compat_sys_sendmsg .section __ex_table,"a" .align 3 .llong 1b,.do_efault @@ -268,12 +268,12 @@ .llong 3b,.do_efault .previous -_STATIC(do_sys_recvmsg) /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ +_STATIC(do_sys_recvmsg) /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ mr r10,r4 1: lwa r3,0(r10) 2: lwz r4,4(r10) 3: lwa r5,8(r10) - b .sys32_recvmsg + b .compat_sys_recvmsg .section __ex_table,"a" .align 3 .llong 1b,.do_efault diff -urN linux-2.5.64-bk5/arch/ppc64/kernel/sys_ppc32.c linux-2.5.64-bk6/arch/ppc64/kernel/sys_ppc32.c --- linux-2.5.64-bk5/arch/ppc64/kernel/sys_ppc32.c Tue Mar 4 19:29:31 2003 +++ linux-2.5.64-bk6/arch/ppc64/kernel/sys_ppc32.c Mon Mar 31 12:28:48 2003 @@ -74,13 +74,11 @@ #include #include -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -114,7 +112,7 @@ goto out; } retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) goto out; /* @@ -206,7 +204,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -227,7 +225,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -2135,708 +2133,6 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage long sys32_setsockopt(int fd, int level, int optname, char* optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - char *optval, int *optlen); - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage int sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); -} - -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - 16 for IP, 16 for IPX, 24 for IPv6, about 80 for AX.25 */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -struct msghdr32 -{ - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 -{ - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if (kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if (kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if (kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -asmlinkage long sys32_sendmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if (kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if (copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if (copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - if (kcmsg32->cmsg_level == SOL_SOCKET && - kcmsg32->cmsg_type == SO_TIMESTAMP) { - struct timeval tv; - struct compat_timeval *tv32; - - if (clen64 != CMSG_LEN(sizeof(struct timeval))) { - kfree(workbuf); - goto fail; - } - copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv)); - tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32); - tv32->tv_sec = tv.tv_sec; - tv32->tv_usec = tv.tv_usec; - clen32 = sizeof(*tv32) + - CMSG32_ALIGN(sizeof(struct cmsghdr32)); - } else { - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - } - kcmsg32->cmsg_len = clen32; - - switch (kcmsg32->cmsg_type) { - /* - * The timestamp type's data needs to be converted - * from 64-bit time values to 32-bit time values - */ - case SO_TIMESTAMP: { - compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32); - __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); - *ptr_time32 = *ptr_time; - *(ptr_time32+1) = *(ptr_time+1); - kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - - sizeof(compat_time_t)); - } - default:; - } - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage long sys32_recvmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if (uaddr != NULL && err >= 0 && kern_msg.msg_namelen) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - - return len; -} - /* * count32() counts the number of arguments/envelopes */ diff -urN linux-2.5.64-bk5/arch/s390x/kernel/entry.S linux-2.5.64-bk6/arch/s390x/kernel/entry.S --- linux-2.5.64-bk5/arch/s390x/kernel/entry.S Tue Mar 4 19:29:03 2003 +++ linux-2.5.64-bk6/arch/s390x/kernel/entry.S Mon Mar 31 12:28:48 2003 @@ -499,7 +499,7 @@ .long SYSCALL(sys_statfs,compat_sys_statfs_wrapper) .long SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper) /* 100 */ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) - .long SYSCALL(sys_socketcall,sys32_socketcall_wrapper) + .long SYSCALL(sys_socketcall,compat_sys_socketcall_wrapper) .long SYSCALL(sys_syslog,sys32_syslog_wrapper) .long SYSCALL(sys_setitimer,compat_sys_setitimer_wrapper) .long SYSCALL(sys_getitimer,compat_sys_getitimer_wrapper) /* 105 */ diff -urN linux-2.5.64-bk5/arch/s390x/kernel/linux32.c linux-2.5.64-bk6/arch/s390x/kernel/linux32.c --- linux-2.5.64-bk5/arch/s390x/kernel/linux32.c Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/arch/s390x/kernel/linux32.c Mon Mar 31 12:28:48 2003 @@ -904,13 +904,11 @@ return sys_ftruncate(fd, (high << 32) | low); } -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { unsigned long tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -925,7 +923,7 @@ */ if (!count) return 0; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -996,7 +994,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; long ret = -EBADF; @@ -1014,7 +1012,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -1867,740 +1865,6 @@ return ret; } -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - switch (kcmsg32->cmsg_type) { - /* - * The timestamp type's data needs to be converted - * from 64-bit time values to 32-bit time values - */ - case SO_TIMESTAMP: { - compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32); - __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); - get_user(*ptr_time32, ptr_time); - get_user(*(ptr_time32+1), ptr_time+1); - kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - - sizeof(compat_time_t)); - } - default:; - } - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -/* - * BSD sendmsg interface - */ - -int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { - if (ctl_len > sizeof(ctl)) - { - ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) - goto out_freeiov; - } - else if (ctl_len < sizeof(struct cmsghdr)) - { - /* to get same error message as on 31 bit native */ - err = EOPNOTSUPP; - goto out_freeiov; - } - err = -EFAULT; - if (cmsghdr_from_user32_to_kern(&msg_sys, ctl_buf, ctl_len)) - goto out_freectl; -// msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -static __inline__ void -scm_recv32(struct socket *sock, struct msghdr *msg, - struct scm_cookie *scm, int flags, unsigned long cmsg_ptr) -{ - if(!msg->msg_control) - { - if(sock->passcred || scm->fp) - msg->msg_flags |= MSG_CTRUNC; - scm_destroy(scm); - return; - } - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) msg->msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(msg, cmsg_ptr); - /* Wheee... */ - if(sock->passcred) - put_cmsg32(msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(scm->creds), &scm->creds); - if(!scm->fp) - return; - - scm_detach_fds32(msg, scm); -} - -static int -sock_recvmsg32(struct socket *sock, struct msghdr *msg, int size, int flags, - unsigned long cmsg_ptr) -{ - struct sock_iocb *si; - struct kiocb iocb; - - init_sync_kiocb(&iocb, NULL); - - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = msg; - si->size = size; - si->flags = flags; - - memset(si->scm, 0, sizeof(*si->scm)); - - size = sock->ops->recvmsg(&iocb, sock, msg, size, flags, si->scm); - if (size >= 0) - scm_recv32(sock, msg, si->scm, flags, cmsg_ptr); - - if (-EIOCBQUEUED == size) - size = wait_on_sync_kiocb(&iocb); - - return size; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err=-EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr); - if (err < 0) - goto out_freeiov; - len = err; - - if (uaddr != NULL && - /* in order to get same error message as on native 31 bit */ - msg_sys.msg_namelen > 0) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((compat_size_t) ((unsigned long)msg_sys.msg_control - cmsg_ptr), &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - if (level == SOL_SOCKET && - (optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)) { - long ret; - struct timeval tmp; - mm_segment_t old_fs; - - if (get_tv32(&tmp, (struct compat_timeval *)optval )) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, (char *) &tmp, sizeof(struct timeval)); - set_fs(old_fs); - return ret; - } - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - extern void check_pending(int signum); /* @@ -3665,104 +2929,6 @@ return error; } -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); -extern asmlinkage long sys_listen(int fd, int backlog); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]); -extern asmlinkage long sys_send(int fd, void * buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags, - struct sockaddr *addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void * ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags, - struct sockaddr *addr, int *addr_len); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int * optlen); - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[18] = {AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -asmlinkage long sys32_socketcall(int call, u32 *args) -{ - int ret; - u32 a[6]; - - if (call < SYS_SOCKET || call > SYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - switch(call) { - case SYS_SOCKET: - ret = sys_socket(a[0], a[1], a[2]); - break; - case SYS_BIND: - ret = sys_bind(a[0], (struct sockaddr *) A(a[1]), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a[0], (struct sockaddr *) A(a[1]), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a[0], a[1]); - break; - case SYS_ACCEPT: - ret = sys_accept(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a[0], a[1], a[2], (int *) A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a[0], (void *) A(a[1]), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a[0], (void*) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), a[5]); - break; - case SYS_RECV: - ret = sys_recv(a[0], (void *) A(a[1]), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a[0], (void *) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), (int *) A(a[5]) ); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a[0], a[1]); - break; - case SYS_SETSOCKOPT: - ret = sys32_setsockopt(a[0], a[1], a[2], (char *) A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys_getsockopt(a[0], a[1], a[2], (char *) A(a[3]), (int *) A(a[4]) ); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a[0], (struct msghdr32 *) A(a[1]), - a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a[0], (struct msghdr32 *) A(a[1]), - a[2]); - break; - default: - ret = EINVAL; - break; - } - return ret; -} - extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr); diff -urN linux-2.5.64-bk5/arch/s390x/kernel/wrapper32.S linux-2.5.64-bk6/arch/s390x/kernel/wrapper32.S --- linux-2.5.64-bk5/arch/s390x/kernel/wrapper32.S Tue Mar 4 19:29:54 2003 +++ linux-2.5.64-bk6/arch/s390x/kernel/wrapper32.S Mon Mar 31 12:28:48 2003 @@ -452,11 +452,11 @@ llgtr %r3,%r3 # struct compat_statfs * jg compat_sys_fstatfs # branch to system call - .globl sys32_socketcall_wrapper -sys32_socketcall_wrapper: + .globl compat_sys_socketcall_wrapper +compat_sys_socketcall_wrapper: lgfr %r2,%r2 # int llgtr %r3,%r3 # u32 * - jg sys32_socketcall # branch to system call + jg compat_sys_socketcall # branch to system call .globl sys32_syslog_wrapper sys32_syslog_wrapper: diff -urN linux-2.5.64-bk5/arch/sparc/kernel/sys_sunos.c linux-2.5.64-bk6/arch/sparc/kernel/sys_sunos.c --- linux-2.5.64-bk5/arch/sparc/kernel/sys_sunos.c Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/arch/sparc/kernel/sys_sunos.c Mon Mar 31 12:28:48 2003 @@ -1107,38 +1107,16 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sunos_socket(int family, int type, int protocol) -{ - int ret, one = 1; - - ret = sys_socket(family, type, protocol); - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: - return ret; -} - asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen) { - int ret, one = 1; + int ret; while (1) { ret = check_nonblock(sys_accept(fd,sa,addrlen),fd); if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) break; } - if (ret < 0) - goto out; - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: return ret; } diff -urN linux-2.5.64-bk5/arch/sparc/kernel/systbls.S linux-2.5.64-bk6/arch/sparc/kernel/systbls.S --- linux-2.5.64-bk5/arch/sparc/kernel/systbls.S Tue Mar 4 19:29:19 2003 +++ linux-2.5.64-bk6/arch/sparc/kernel/systbls.S Mon Mar 31 12:28:48 2003 @@ -110,7 +110,7 @@ .long sys_getitimer, sys_gethostname, sys_sethostname .long sunos_getdtablesize, sys_dup2, sunos_nop .long sys_fcntl, sunos_select, sunos_nop - .long sys_fsync, sys_setpriority, sunos_socket + .long sys_fsync, sys_setpriority, sys_socket .long sys_connect, sunos_accept /*100*/ .long sys_getpriority, sunos_send, sunos_recv .long sunos_nosys, sys_bind, sunos_setsockopt diff -urN linux-2.5.64-bk5/arch/sparc64/kernel/sparc64_ksyms.c linux-2.5.64-bk6/arch/sparc64/kernel/sparc64_ksyms.c --- linux-2.5.64-bk5/arch/sparc64/kernel/sparc64_ksyms.c Tue Mar 4 19:29:33 2003 +++ linux-2.5.64-bk6/arch/sparc64/kernel/sparc64_ksyms.c Mon Mar 31 12:28:48 2003 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -243,6 +244,7 @@ /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(_sigpause_common); +EXPORT_SYMBOL(verify_compat_iovec); /* Should really be in linux/kernel/ksyms.c */ EXPORT_SYMBOL(dump_thread); diff -urN linux-2.5.64-bk5/arch/sparc64/kernel/sys32.S linux-2.5.64-bk6/arch/sparc64/kernel/sys32.S --- linux-2.5.64-bk5/arch/sparc64/kernel/sys32.S Tue Mar 4 19:29:01 2003 +++ linux-2.5.64-bk6/arch/sparc64/kernel/sys32.S Mon Mar 31 12:28:48 2003 @@ -202,38 +202,38 @@ nop nop nop -do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */ +do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_setsockopt), %g1 + sethi %hi(compat_sys_setsockopt), %g1 ldswa [%o1 + 0x8] %asi, %o2 lduwa [%o1 + 0xc] %asi, %o3 ldswa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(sys32_setsockopt), %g0 + jmpl %g1 + %lo(compat_sys_setsockopt), %g0 ldswa [%o1 + 0x4] %asi, %o1 nop -do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */ +do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_getsockopt), %g1 + sethi %hi(compat_sys_getsockopt), %g1 ldswa [%o1 + 0x8] %asi, %o2 lduwa [%o1 + 0xc] %asi, %o3 lduwa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(sys32_getsockopt), %g0 + jmpl %g1 + %lo(compat_sys_getsockopt), %g0 ldswa [%o1 + 0x4] %asi, %o1 nop -do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ +do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_sendmsg), %g1 + sethi %hi(compat_sys_sendmsg), %g1 lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys32_sendmsg), %g0 + jmpl %g1 + %lo(compat_sys_sendmsg), %g0 lduwa [%o1 + 0x4] %asi, %o1 nop nop nop -do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ +do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_recvmsg), %g1 + sethi %hi(compat_sys_recvmsg), %g1 lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys32_recvmsg), %g0 + jmpl %g1 + %lo(compat_sys_recvmsg), %g0 lduwa [%o1 + 0x4] %asi, %o1 nop nop diff -urN linux-2.5.64-bk5/arch/sparc64/kernel/sys_sparc32.c linux-2.5.64-bk6/arch/sparc64/kernel/sys_sparc32.c --- linux-2.5.64-bk5/arch/sparc64/kernel/sys_sparc32.c Tue Mar 4 19:29:26 2003 +++ linux-2.5.64-bk6/arch/sparc64/kernel/sys_sparc32.c Mon Mar 31 12:28:48 2003 @@ -63,8 +63,6 @@ #include #include -#include - /* Use this to get at 32-bit user passed pointers. */ /* Things to consider: the low-level assembly stub does srl x, 0, x for first four arguments, so if you have @@ -860,13 +858,11 @@ return sys_ftruncate(fd, (high << 32) | low); } -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -900,7 +896,7 @@ goto out; } retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) goto out; /* @@ -992,7 +988,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret; @@ -1015,7 +1011,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret; @@ -1907,773 +1903,6 @@ return ret; } -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - if (kcmsg32->cmsg_level == SOL_SOCKET && - kcmsg32->cmsg_type == SO_TIMESTAMP) { - struct timeval tv; - struct compat_timeval *tv32; - - if (clen64 != CMSG_LEN(sizeof(struct timeval))) { - kfree(workbuf); - goto fail; - } - copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv)); - tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32); - tv32->tv_sec = tv.tv_sec; - tv32->tv_usec = tv.tv_usec; - clen32 = sizeof(*tv32) + - CMSG32_ALIGN(sizeof(struct cmsghdr32)); - } else { - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - } - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_netfilter_replace(int fd, int level, int optname, - char *optval, int optlen) -{ - struct ipt_replace32 { - char name[IPT_TABLE_MAXNAMELEN]; - __u32 valid_hooks; - __u32 num_entries; - __u32 size; - __u32 hook_entry[NF_IP_NUMHOOKS]; - __u32 underflow[NF_IP_NUMHOOKS]; - __u32 num_counters; - __u32 counters; - struct ipt_entry entries[0]; - } *repl32 = (struct ipt_replace32 *)optval; - struct ipt_replace *krepl; - struct ipt_counters *counters32; - __u32 origsize; - unsigned int kreplsize, kcountersize; - mm_segment_t old_fs; - int ret; - - if (optlen < sizeof(repl32)) - return -EINVAL; - - if (copy_from_user(&origsize, - &repl32->size, - sizeof(origsize))) - return -EFAULT; - - kreplsize = sizeof(*krepl) + origsize; - kcountersize = krepl->num_counters * sizeof(struct ipt_counters); - - /* Hack: Causes ipchains to give correct error msg --RR */ - if (optlen != kreplsize) - return -ENOPROTOOPT; - - krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL); - if (krepl == NULL) - return -ENOMEM; - - if (copy_from_user(krepl, optval, kreplsize)) { - kfree(krepl); - return -EFAULT; - } - - counters32 = (struct ipt_counters *)AA( - ((struct ipt_replace32 *)krepl)->counters); - - kcountersize = krepl->num_counters * sizeof(struct ipt_counters); - krepl->counters = (struct ipt_counters *)kmalloc( - kcountersize, GFP_KERNEL); - if (krepl->counters == NULL) { - kfree(krepl); - return -ENOMEM; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)krepl, kreplsize); - set_fs(old_fs); - - if (ret == 0 && - copy_to_user(counters32, krepl->counters, kcountersize)) - ret = -EFAULT; - - kfree(krepl->counters); - kfree(krepl); - - return ret; -} - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == IPT_SO_SET_REPLACE) - return do_netfilter_replace(fd, level, optname, - optval, optlen); - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - char *optval, int *optlen); - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage int sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); -} - extern void check_pending(int signum); asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) diff -urN linux-2.5.64-bk5/arch/sparc64/kernel/sys_sunos32.c linux-2.5.64-bk6/arch/sparc64/kernel/sys_sunos32.c --- linux-2.5.64-bk5/arch/sparc64/kernel/sys_sunos32.c Tue Mar 4 19:29:24 2003 +++ linux-2.5.64-bk6/arch/sparc64/kernel/sys_sunos32.c Mon Mar 31 12:28:48 2003 @@ -54,6 +54,7 @@ #include /* For SOCKET_I */ +#include #include /* Use this to get at 32-bit user passed pointers. */ @@ -1253,26 +1254,9 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sunos_socket(int family, int type, int protocol) -{ - int ret, one = 1; - - ret = sys_socket(family, type, protocol); - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: - return ret; -} - asmlinkage int sunos_accept(int fd, u32 sa, u32 addrlen) { - int ret, one = 1; + int ret; while (1) { ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa), @@ -1280,12 +1264,6 @@ if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) break; } - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: return ret; } @@ -1324,8 +1302,6 @@ extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); -extern asmlinkage int sys32_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval, int optlen) @@ -1353,6 +1329,6 @@ if (tr_opt >=2 && tr_opt <= 6) tr_opt += 30; } - ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen); + ret = compat_sys_getsockopt(fd, level, tr_opt, (void*)(unsigned long)optval, (void*)(unsigned long)optlen); return ret; } diff -urN linux-2.5.64-bk5/arch/sparc64/kernel/systbls.S linux-2.5.64-bk6/arch/sparc64/kernel/systbls.S --- linux-2.5.64-bk5/arch/sparc64/kernel/systbls.S Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/arch/sparc64/kernel/systbls.S Mon Mar 31 12:28:48 2003 @@ -173,13 +173,13 @@ .word compat_sys_getitimer, sys_gethostname, sys_sethostname .word sunos_getdtablesize, sys_dup2, sunos_nop .word sys32_fcntl, sunos_select, sunos_nop - .word sys_fsync, sys_setpriority32, sunos_socket + .word sys_fsync, sys_setpriority32, sys_socket .word sys_connect, sunos_accept /*100*/ .word sys_getpriority, sunos_send, sunos_recv .word sunos_nosys, sys_bind, sunos_setsockopt .word sys_listen, sunos_nosys, sunos_sigaction .word sunos_sigblock, sunos_sigsetmask, sys_sigpause - .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg + .word sys32_sigstack, compat_sys_recvmsg, compat_sys_sendmsg .word sunos_nosys, sys32_gettimeofday, sys32_getrusage .word sunos_getsockopt, sunos_nosys, sunos_readv .word sunos_writev, sys32_settimeofday, sys32_fchown16 diff -urN linux-2.5.64-bk5/arch/sparc64/solaris/socket.c linux-2.5.64-bk6/arch/sparc64/solaris/socket.c --- linux-2.5.64-bk5/arch/sparc64/solaris/socket.c Tue Mar 4 19:29:30 2003 +++ linux-2.5.64-bk6/arch/sparc64/solaris/socket.c Mon Mar 31 12:28:48 2003 @@ -267,35 +267,6 @@ unsigned char cmsg_data[0]; }; -struct iovec32 { - u32 iov_base; - u32 iov_len; -}; - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct sol_nmsghdr *umsg) { @@ -321,42 +292,6 @@ return err; } -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned user_flags) { struct socket *sock; @@ -371,7 +306,7 @@ return -EFAULT; if(kern_msg.msg_iovlen > UIO_MAXIOV) return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); + err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ); if (err < 0) goto out; total_len = err; @@ -439,7 +374,7 @@ uaddr = kern_msg.msg_name; uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); + err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); if (err < 0) goto out; total_len = err; diff -urN linux-2.5.64-bk5/arch/x86_64/boot/Makefile linux-2.5.64-bk6/arch/x86_64/boot/Makefile --- linux-2.5.64-bk5/arch/x86_64/boot/Makefile Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/arch/x86_64/boot/Makefile Mon Mar 31 12:28:48 2003 @@ -62,33 +62,33 @@ # Set this if you want to pass append arguments to the zdisk/fdimage kernel FDARGS = -$(obj)/mtools.conf: $(obj)/mtools.conf.in +$(obj)/mtools.conf: $(src)/mtools.conf.in sed -e 's|@OBJ@|$(obj)|g' < $< > $@ # This requires write access to /dev/fd0 zdisk: $(BOOTIMAGE) $(obj)/mtools.conf - MTOOLSRC=$(src)/mtools.conf mformat a: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync syslinux /dev/fd0 ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync # These require being root or having syslinux 2.02 or higher installed -fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf +fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 - MTOOLSRC=$(src)/mtools.conf mformat v: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - v:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync -fdimage288: $(BOOTIMAGE) $(src)/mtools.conf +fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 - MTOOLSRC=$(src)/mtools.conf mformat w: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - w:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync zlilo: $(BOOTIMAGE) if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi diff -urN linux-2.5.64-bk5/arch/x86_64/boot/setup.S linux-2.5.64-bk6/arch/x86_64/boot/setup.S --- linux-2.5.64-bk5/arch/x86_64/boot/setup.S Tue Mar 4 19:29:53 2003 +++ linux-2.5.64-bk6/arch/x86_64/boot/setup.S Mon Mar 31 12:28:48 2003 @@ -829,13 +829,6 @@ .word 0x9200 # data read/write .word 0x00CF # granularity = 4096, 386 # (+5th nibble of limit) -# this is 64bit descriptor for code - .word 0xFFFF - .word 0 - .word 0x9A00 # code read/exec - .word 0x00AF # as above, but it is long mode and with D=0 - # it does not seem to do the trick. - idt_48: .word 0 # idt limit = 0 .word 0, 0 # idt base = 0L diff -urN linux-2.5.64-bk5/arch/x86_64/ia32/Makefile linux-2.5.64-bk6/arch/x86_64/ia32/Makefile --- linux-2.5.64-bk5/arch/x86_64/ia32/Makefile Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/arch/x86_64/ia32/Makefile Mon Mar 31 12:28:48 2003 @@ -4,4 +4,4 @@ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ ia32_signal.o \ - ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o syscall32.o + ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o diff -urN linux-2.5.64-bk5/arch/x86_64/ia32/ia32_signal.c linux-2.5.64-bk6/arch/x86_64/ia32/ia32_signal.c --- linux-2.5.64-bk5/arch/x86_64/ia32/ia32_signal.c Tue Mar 4 19:29:53 2003 +++ linux-2.5.64-bk6/arch/x86_64/ia32/ia32_signal.c Mon Mar 31 12:28:48 2003 @@ -106,20 +106,24 @@ stack_t uss,uoss; int ret; mm_segment_t seg; + if (uss_ptr) { + u32 ptr; if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) || - __get_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) || - __get_user((u32)uss.ss_flags, &uss_ptr->ss_flags) || - __get_user((u32)uss.ss_size, &uss_ptr->ss_size)) + __get_user(ptr, &uss_ptr->ss_sp) || + __get_user(uss.ss_flags, &uss_ptr->ss_flags) || + __get_user(uss.ss_size, &uss_ptr->ss_size)) return -EFAULT; + uss.ss_sp = (void *)(u64)ptr; + } seg = get_fs(); set_fs(KERNEL_DS); - ret = do_sigaltstack(&uss, &uoss, regs.rsp); + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp); set_fs(seg); if (ret >= 0 && uoss_ptr) { - if (!access_ok(VERIFY_WRITE,uss_ptr,sizeof(stack_ia32_t)) || - __put_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) || - __put_user((u32)uss.ss_flags, &uss_ptr->ss_flags) || - __put_user((u32)uss.ss_size, &uss_ptr->ss_size)) + if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) || + __put_user((u32)(u64)uss.ss_sp, &uoss_ptr->ss_sp) || + __put_user(uss.ss_flags, &uoss_ptr->ss_flags) || + __put_user(uss.ss_size, &uoss_ptr->ss_size)) ret = -EFAULT; } return ret; diff -urN linux-2.5.64-bk5/arch/x86_64/ia32/ia32entry.S linux-2.5.64-bk6/arch/x86_64/ia32/ia32entry.S --- linux-2.5.64-bk5/arch/x86_64/ia32/ia32entry.S Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/arch/x86_64/ia32/ia32entry.S Mon Mar 31 12:28:48 2003 @@ -302,7 +302,7 @@ .quad compat_sys_statfs .quad compat_sys_fstatfs /* 100 */ .quad sys_ioperm - .quad sys32_socketcall + .quad compat_sys_socketcall .quad sys_syslog .quad compat_sys_setitimer .quad compat_sys_getitimer /* 105 */ @@ -443,8 +443,8 @@ .quad compat_sys_futex /* 240 */ .quad sys32_sched_setaffinity .quad sys32_sched_getaffinity - .quad sys_set_thread_area - .quad sys_get_thread_area + .quad sys32_set_thread_area + .quad sys32_get_thread_area .quad sys32_io_setup .quad sys_io_destroy .quad sys32_io_getevents diff -urN linux-2.5.64-bk5/arch/x86_64/ia32/ptrace32.c linux-2.5.64-bk6/arch/x86_64/ia32/ptrace32.c --- linux-2.5.64-bk5/arch/x86_64/ia32/ptrace32.c Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/arch/x86_64/ia32/ptrace32.c Mon Mar 31 12:28:48 2003 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include diff -urN linux-2.5.64-bk5/arch/x86_64/ia32/socket32.c linux-2.5.64-bk6/arch/x86_64/ia32/socket32.c --- linux-2.5.64-bk5/arch/x86_64/ia32/socket32.c Tue Mar 4 19:28:59 2003 +++ linux-2.5.64-bk6/arch/x86_64/ia32/socket32.c Wed Dec 31 16:00:00 1969 @@ -1,756 +0,0 @@ -/* - * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c. - * - * Copyright (C) 2000 VA Linux Co - * Copyright (C) 2000 Don Dugger - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 2000 Hewlett-Packard Co. - * Copyright (C) 2000 David Mosberger-Tang - * Copyright (C) 2000,2001 Andi Kleen, SuSE Labs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define A(__x) ((unsigned long)(__x)) -#define AA(__x) ((unsigned long)(__x)) - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - void * optval, int *optlen); - - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage long sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage long sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage long sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage long sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); -} - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, - int addrlen); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, - int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_listen(int fd, int backlog); - -asmlinkage long sys32_socketcall(int call, u32 *args) -{ - int ret; - u32 a[6]; - u32 a0,a1; - - if (callSYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - ret = sys_socket(a0, a1, a[2]); - break; - case SYS_BIND: - ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a0, a1); - break; - case SYS_ACCEPT: - ret = sys_accept(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_RECV: - ret = sys_recv(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a0,a1); - break; - case SYS_SETSOCKOPT: - ret = sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys32_getsockopt(a0, a1, a[2], (char *)(u64)a[3], (int *)(u64)a[4]); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1), - a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1), - a[2]); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} diff -urN linux-2.5.64-bk5/arch/x86_64/ia32/sys_ia32.c linux-2.5.64-bk6/arch/x86_64/ia32/sys_ia32.c --- linux-2.5.64-bk5/arch/x86_64/ia32/sys_ia32.c Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/arch/x86_64/ia32/sys_ia32.c Mon Mar 31 12:28:48 2003 @@ -738,7 +738,7 @@ asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long); static struct iovec * -get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) +get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) { int i; u32 buf, len; @@ -751,7 +751,7 @@ return 0; if (count > UIO_MAXIOV) return(struct iovec *)0; - if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) return(struct iovec *)0; if (count > UIO_FASTIOV) { *errp = -ENOMEM; @@ -792,14 +792,14 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_readv(fd, iov, count); @@ -810,14 +810,14 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_writev(fd, iov, count); @@ -1261,8 +1261,8 @@ if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; + memcpy(&d->si_int, &s->si_int, + sizeof(siginfo_t) - offsetof(siginfo_t,si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: @@ -1299,8 +1299,9 @@ if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; + memcpy(&d->si_int, + &s->si_int, + sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: diff -urN linux-2.5.64-bk5/arch/x86_64/ia32/tls32.c linux-2.5.64-bk6/arch/x86_64/ia32/tls32.c --- linux-2.5.64-bk5/arch/x86_64/ia32/tls32.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.64-bk6/arch/x86_64/ia32/tls32.c Mon Mar 31 12:28:48 2003 @@ -0,0 +1,162 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * sys_alloc_thread_area: get a yet unused TLS descriptor index. + */ +static int get_free_idx(void) +{ + struct thread_struct *t = ¤t->thread; + int idx; + + for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) + if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx)) + return idx + GDT_ENTRY_TLS_MIN; + return -ESRCH; +} + +/* + * Set a given TLS descriptor: + * When you want addresses > 32bit use arch_prctl() + */ +int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info) +{ + struct user_desc info; + struct n_desc_struct *desc; + int cpu, idx; + + if (copy_from_user(&info, u_info, sizeof(info))) + return -EFAULT; + + idx = info.entry_number; + + /* + * index -1 means the kernel should try to find and + * allocate an empty descriptor: + */ + if (idx == -1) { + idx = get_free_idx(); + if (idx < 0) + return idx; + if (put_user(idx, &u_info->entry_number)) + return -EFAULT; + } + + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; + + /* + * We must not get preempted while modifying the TLS. + */ + cpu = get_cpu(); + + if (LDT_empty(&info)) { + desc->a = 0; + desc->b = 0; + } else { + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + } + if (t == ¤t->thread) + load_TLS(t, cpu); + + put_cpu(); + return 0; +} + +asmlinkage long sys32_set_thread_area(struct user_desc *u_info) +{ + return do_set_thread_area(¤t->thread, u_info); +} + + +/* + * Get the current Thread-Local Storage area: + */ + +#define GET_BASE(desc) ( \ + (((desc)->a >> 16) & 0x0000ffff) | \ + (((desc)->b << 16) & 0x00ff0000) | \ + ( (desc)->b & 0xff000000) ) + +#define GET_LIMIT(desc) ( \ + ((desc)->a & 0x0ffff) | \ + ((desc)->b & 0xf0000) ) + +#define GET_32BIT(desc) (((desc)->b >> 23) & 1) +#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) +#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) +#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) +#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) +#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) +#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1) + +int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info) +{ + struct user_desc info; + struct n_desc_struct *desc; + int idx; + + if (get_user(idx, &u_info->entry_number)) + return -EFAULT; + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; + + memset(&info, 0, sizeof(struct user_desc)); + info.entry_number = idx; + info.base_addr = GET_BASE(desc); + info.limit = GET_LIMIT(desc); + info.seg_32bit = GET_32BIT(desc); + info.contents = GET_CONTENTS(desc); + info.read_exec_only = !GET_WRITABLE(desc); + info.limit_in_pages = GET_LIMIT_PAGES(desc); + info.seg_not_present = !GET_PRESENT(desc); + info.useable = GET_USEABLE(desc); + info.lm = GET_LONGMODE(desc); + + if (copy_to_user(u_info, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +asmlinkage long sys32_get_thread_area(struct user_desc *u_info) +{ + return do_get_thread_area(¤t->thread, u_info); +} + + +int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs) +{ + struct n_desc_struct *desc; + struct user_desc info, *cp; + int idx; + + cp = (void *)childregs->rsi; + if (copy_from_user(&info, cp, sizeof(info))) + return -EFAULT; + if (LDT_empty(&info)) + return -EINVAL; + + idx = info.entry_number; + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN; + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + + return 0; +} diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/apic.c linux-2.5.64-bk6/arch/x86_64/kernel/apic.c --- linux-2.5.64-bk5/arch/x86_64/kernel/apic.c Tue Mar 4 19:29:00 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/apic.c Mon Mar 31 12:28:48 2003 @@ -981,9 +981,6 @@ asmlinkage void smp_spurious_interrupt(void) { unsigned int v; - static unsigned long last_warning; - static unsigned long skipped; - irq_enter(); /* * Check if this really is a spurious interrupt and ACK it @@ -994,8 +991,12 @@ if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) ack_APIC_irq(); +#if 0 + static unsigned long last_warning; + static unsigned long skipped; + /* see sw-dev-man vol 3, chapter 7.4.13.5 */ - if (last_warning+30*HZ < jiffies) { + if (time_before(last_warning+30*HZ,jiffies)) { printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n", smp_processor_id(), skipped); last_warning = jiffies; @@ -1003,6 +1004,7 @@ } else { skipped++; } +#endif irq_exit(); } diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/head64.c linux-2.5.64-bk6/arch/x86_64/kernel/head64.c --- linux-2.5.64-bk5/arch/x86_64/kernel/head64.c Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/head64.c Mon Mar 31 12:28:48 2003 @@ -79,6 +79,9 @@ clear_bss(); pda_init(0); copy_bootdata(real_mode_data); + /* default console: */ + if (!strstr(saved_command_line, "console=")) + strcat(saved_command_line, " console=tty0"); s = strstr(saved_command_line, "earlyprintk="); if (s != NULL) setup_early_printk(s+12); diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/io_apic.c linux-2.5.64-bk6/arch/x86_64/kernel/io_apic.c --- linux-2.5.64-bk5/arch/x86_64/kernel/io_apic.c Tue Mar 4 19:29:19 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/io_apic.c Mon Mar 31 12:28:48 2003 @@ -1110,7 +1110,7 @@ */ static int __init timer_irq_works(void) { - unsigned int t1 = jiffies; + unsigned long t1 = jiffies; local_irq_enable(); /* Let ten ticks pass... */ @@ -1123,6 +1123,8 @@ * might have cached one ExtINT interrupt. Finally, at * least one tick may be lost due to delays. */ + + /* jiffies wrap? */ if (jiffies - t1 > 4) return 1; return 0; diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/process.c linux-2.5.64-bk6/arch/x86_64/kernel/process.c --- linux-2.5.64-bk5/arch/x86_64/kernel/process.c Tue Mar 4 19:29:22 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/process.c Mon Mar 31 12:28:48 2003 @@ -19,46 +19,37 @@ #define __KERNEL_SYSCALLS__ #include -#include #include #include #include #include #include #include -#include -#include #include -#include #include -#include #include #include #include #include -#include #include -#include -#include -#include +#include +#include #include #include #include #include -#include #include #include -#include #include #include #include #include - -#include +#include +#include +#include asmlinkage extern void ret_from_fork(void); -int sys_arch_prctl(int code, unsigned long addr); unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; @@ -245,10 +236,36 @@ } } +static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr) +{ + struct user_desc ud = { + .base_addr = addr, + .limit = 0xfffff, + .seg_32bit = 1, + .limit_in_pages = 1, + .useable = 1, + }; + struct n_desc_struct *desc = (void *)t->thread.tls_array; + desc += tls; + desc->a = LDT_entry_a(&ud); + desc->b = LDT_entry_b(&ud); +} + +static inline u32 read_32bit_tls(struct task_struct *t, int tls) +{ + struct desc_struct *desc = (void *)t->thread.tls_array; + desc += tls; + return desc->base0 | + (((u32)desc->base1) << 16) | + (((u32)desc->base2) << 24); +} + + int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) { + int err; struct pt_regs * childregs; struct task_struct *me = current; @@ -265,7 +282,7 @@ p->thread.rsp = (unsigned long) childregs; p->thread.rsp0 = (unsigned long) (childregs+1); - p->thread.userrsp = current->thread.userrsp; + p->thread.userrsp = me->thread.userrsp; p->thread.rip = (unsigned long) ret_from_fork; @@ -277,8 +294,8 @@ asm("movl %%es,%0" : "=m" (p->thread.es)); asm("movl %%ds,%0" : "=m" (p->thread.ds)); - unlazy_fpu(current); - p->thread.i387 = current->thread.i387; + unlazy_fpu(me); + p->thread.i387 = me->thread.i387; if (unlikely(me->thread.io_bitmap_ptr != NULL)) { p->thread.io_bitmap_ptr = kmalloc((IO_BITMAP_SIZE+1)*4, GFP_KERNEL); @@ -292,27 +309,20 @@ * Set a new TLS for the child thread? */ if (clone_flags & CLONE_SETTLS) { - struct n_desc_struct *desc; - struct user_desc info; - int idx; - - if (copy_from_user(&info, test_thread_flag(TIF_IA32) ? - (void *)childregs->rsi : - (void *)childregs->rdx, sizeof(info))) - return -EFAULT; - if (LDT_empty(&info)) - return -EINVAL; - - idx = info.entry_number; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN; - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - } - - return 0; +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) + err = ia32_child_tls(p, childregs); + else +#endif + err = do_arch_prctl(p, ARCH_SET_FS, childregs->r10); + if (err) + goto out; + } + err = 0; +out: + if (err && p->thread.io_bitmap_ptr) + kfree(p->thread.io_bitmap_ptr); + return err; } /* @@ -422,7 +432,7 @@ if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { if (next->io_bitmap_ptr) { /* - * 4 cachelines copy ... not good, but not that + * 2 cachelines copy ... not good, but not that * bad either. Anyone got something better? * This only affects processes which use ioperm(). */ @@ -537,19 +547,35 @@ #undef last_sched #undef first_sched -int sys_arch_prctl(int code, unsigned long addr) +long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) { int ret = 0; + int doit = task == current; + int cpu; switch (code) { case ARCH_SET_GS: if (addr >= TASK_SIZE) return -EPERM; - get_cpu(); + cpu = get_cpu(); + /* handle small bases via the GDT because that's faster to + switch. */ + if (addr <= 0xffffffff) { + set_32bit_tls(task, GS_TLS, addr); + if (doit) { + load_TLS(&task->thread, cpu); + load_gs_index(GS_TLS_SEL); + } + task->thread.gsindex = GS_TLS_SEL; + task->thread.gs = 0; + } else { + task->thread.gsindex = 0; + task->thread.gs = addr; + if (doit) { load_gs_index(0); - current->thread.gsindex = 0; - current->thread.gs = addr; ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); + } + } put_cpu(); break; case ARCH_SET_FS: @@ -557,22 +583,51 @@ with gs */ if (addr >= TASK_SIZE) return -EPERM; - get_cpu(); + cpu = get_cpu(); + /* handle small bases via the GDT because that's faster to + switch. */ + if (addr <= 0xffffffff) { + set_32bit_tls(task, FS_TLS, addr); + if (doit) { + load_TLS(&task->thread, cpu); + asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL)); + } + task->thread.fsindex = FS_TLS_SEL; + task->thread.fs = 0; + } else { + task->thread.fsindex = 0; + task->thread.fs = addr; + if (doit) { + /* set the selector to 0 to not confuse + __switch_to */ asm volatile("movl %0,%%fs" :: "r" (0)); - current->thread.fsindex = 0; - current->thread.fs = addr; ret = checking_wrmsrl(MSR_FS_BASE, addr); + } + } put_cpu(); break; - - /* Returned value may not be correct when the user changed fs/gs */ - case ARCH_GET_FS: - ret = put_user(current->thread.fs, (unsigned long *)addr); + case ARCH_GET_FS: { + unsigned long base; + if (task->thread.fsindex == FS_TLS_SEL) + base = read_32bit_tls(task, FS_TLS); + else if (doit) { + rdmsrl(MSR_FS_BASE, base); + } else + base = task->thread.fs; + ret = put_user(base, (unsigned long *)addr); break; - - case ARCH_GET_GS: - ret = put_user(current->thread.gs, (unsigned long *)addr); + } + case ARCH_GET_GS: { + unsigned long base; + if (task->thread.gsindex == GS_TLS_SEL) + base = read_32bit_tls(task, GS_TLS); + else if (doit) { + rdmsrl(MSR_KERNEL_GS_BASE, base); + } else + base = task->thread.gs; + ret = put_user(base, (unsigned long *)addr); break; + } default: ret = -EINVAL; @@ -582,131 +637,9 @@ return ret; } -/* - * sys_alloc_thread_area: get a yet unused TLS descriptor index. - */ -static int get_free_idx(void) -{ - struct thread_struct *t = ¤t->thread; - int idx; - - for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) - if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx)) - return idx + GDT_ENTRY_TLS_MIN; - return -ESRCH; -} - -/* - * Set a given TLS descriptor: - * When you want addresses > 32bit use arch_prctl() - */ -int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info) -{ - struct user_desc info; - struct n_desc_struct *desc; - int cpu, idx; - - if (copy_from_user(&info, u_info, sizeof(info))) - return -EFAULT; - - idx = info.entry_number; - - /* - * index -1 means the kernel should try to find and - * allocate an empty descriptor: - */ - if (idx == -1) { - idx = get_free_idx(); - if (idx < 0) - return idx; - if (put_user(idx, &u_info->entry_number)) - return -EFAULT; - } - - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; - - /* - * We must not get preempted while modifying the TLS. - */ - cpu = get_cpu(); - - if (LDT_empty(&info)) { - desc->a = 0; - desc->b = 0; - } else { - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - } - if (t == ¤t->thread) - load_TLS(t, cpu); - - put_cpu(); - return 0; -} - -asmlinkage int sys_set_thread_area(struct user_desc *u_info) -{ - return do_set_thread_area(¤t->thread, u_info); -} - - -/* - * Get the current Thread-Local Storage area: - */ - -#define GET_BASE(desc) ( \ - (((desc)->a >> 16) & 0x0000ffff) | \ - (((desc)->b << 16) & 0x00ff0000) | \ - ( (desc)->b & 0xff000000) ) - -#define GET_LIMIT(desc) ( \ - ((desc)->a & 0x0ffff) | \ - ((desc)->b & 0xf0000) ) - -#define GET_32BIT(desc) (((desc)->b >> 23) & 1) -#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) -#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) -#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) -#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) -#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) -#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1) - -int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info) -{ - struct user_desc info; - struct n_desc_struct *desc; - int idx; - - if (get_user(idx, &u_info->entry_number)) - return -EFAULT; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; - - memset(&info, 0, sizeof(struct user_desc)); - info.entry_number = idx; - info.base_addr = GET_BASE(desc); - info.limit = GET_LIMIT(desc); - info.seg_32bit = GET_32BIT(desc); - info.contents = GET_CONTENTS(desc); - info.read_exec_only = !GET_WRITABLE(desc); - info.limit_in_pages = GET_LIMIT_PAGES(desc); - info.seg_not_present = !GET_PRESENT(desc); - info.useable = GET_USEABLE(desc); - info.lm = GET_LONGMODE(desc); - - if (copy_to_user(u_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -asmlinkage int sys_get_thread_area(struct user_desc *u_info) +long sys_arch_prctl(int code, unsigned long addr) { - return do_get_thread_area(¤t->thread, u_info); + return do_arch_prctl(current, code, addr); } /* diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/ptrace.c linux-2.5.64-bk6/arch/x86_64/kernel/ptrace.c --- linux-2.5.64-bk5/arch/x86_64/kernel/ptrace.c Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/ptrace.c Mon Mar 31 12:28:48 2003 @@ -26,6 +26,7 @@ #include #include #include +#include /* * does not yet catch signals sent when the child dies. @@ -322,6 +323,13 @@ wake_up_process(child); ret = 0; break; + } + +#ifdef CONFIG_IA32_EMULATION + /* This makes only sense with 32bit programs. Allow a + 64bit debugger to fully examine them too. Better + don't use it against 64bit processes, use + PTRACE_ARCH_PRCTL instead. */ case PTRACE_SET_THREAD_AREA: { int old; get_user(old, &((struct user_desc *)data)->entry_number); @@ -338,7 +346,13 @@ put_user(old, &((struct user_desc *)data)->entry_number); break; } - } +#endif + /* normal 64bit interface to access TLS data. + Works just like arch_prctl, except that the arguments + are reversed. */ + case PTRACE_ARCH_PRCTL: + ret = do_arch_prctl(child, data, addr); + break; /* * make the child exit. Best I can do is send it a sigkill. diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/setup64.c linux-2.5.64-bk6/arch/x86_64/kernel/setup64.c --- linux-2.5.64-bk5/arch/x86_64/kernel/setup64.c Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/setup64.c Mon Mar 31 12:28:48 2003 @@ -22,6 +22,7 @@ #include #include #include +#include char x86_boot_params[2048] __initdata = {0,}; @@ -29,9 +30,6 @@ struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; -extern void system_call(void); -extern void ia32_cstar_target(void); - extern struct task_struct init_task; extern unsigned char __per_cpu_start[], __per_cpu_end[]; @@ -130,6 +128,24 @@ #define EXCEPTION_STK_ORDER 0 /* >= N_EXCEPTION_STACKS*EXCEPTION_STKSZ */ char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ]; +void syscall_init(void) +{ + /* + * LSTAR and STAR live in a bit strange symbiosis. + * They both write to the same internal register. STAR allows to set CS/DS + * but only a 32bit target. LSTAR sets the 64bit rip. + */ + wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); + wrmsrl(MSR_LSTAR, system_call); + +#ifdef CONFIG_IA32_EMULATION + wrmsrl(MSR_CSTAR, ia32_cstar_target); +#endif + + /* Flags to clear on syscall */ + wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); +} + /* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT @@ -188,20 +204,7 @@ asm volatile("pushfq ; popq %%rax ; btr $14,%%rax ; pushq %%rax ; popfq" ::: "eax"); - /* - * LSTAR and STAR live in a bit strange symbiosis. - * They both write to the same internal register. STAR allows to set CS/DS - * but only a 32bit target. LSTAR sets the 64bit rip. - */ - wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); - wrmsrl(MSR_LSTAR, system_call); - -#ifdef CONFIG_IA32_EMULATION - wrmsrl(MSR_CSTAR, ia32_cstar_target); -#endif - - /* Flags to clear on syscall */ - wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); + syscall_init(); wrmsrl(MSR_FS_BASE, 0); wrmsrl(MSR_KERNEL_GS_BASE, 0); diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/signal.c linux-2.5.64-bk6/arch/x86_64/kernel/signal.c --- linux-2.5.64-bk5/arch/x86_64/kernel/signal.c Tue Mar 4 19:29:31 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/signal.c Mon Mar 31 12:28:48 2003 @@ -96,14 +96,6 @@ #define COPY(x) err |= __get_user(regs->x, &sc->x) - { - unsigned int seg; - err |= __get_user(seg, &sc->gs); - load_gs_index(seg); - err |= __get_user(seg, &sc->fs); - loadsegment(fs,seg); - } - COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx); COPY(rdx); COPY(rcx); COPY(rip); COPY(r8); @@ -189,13 +181,10 @@ static inline int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) { - int tmp, err = 0; + int err = 0; - tmp = 0; - __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); - err |= __put_user(tmp, (unsigned int *)&sc->gs); - __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); - err |= __put_user(tmp, (unsigned int *)&sc->fs); + err |= __put_user(0, &sc->gs); + err |= __put_user(0, &sc->fs); err |= __put_user(regs->rdi, &sc->rdi); err |= __put_user(regs->rsi, &sc->rsi); diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/suspend.c linux-2.5.64-bk6/arch/x86_64/kernel/suspend.c --- linux-2.5.64-bk5/arch/x86_64/kernel/suspend.c Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/suspend.c Mon Mar 31 12:28:48 2003 @@ -26,6 +26,7 @@ #include #include #include +#include static struct saved_context saved_context; @@ -58,10 +59,9 @@ asm volatile ("movw %%gs, %0" : "=m" (saved_context.gs)); asm volatile ("movw %%ss, %0" : "=m" (saved_context.ss)); - asm volatile ("swapgs"); - rdmsrl(0xc0000100, saved_context.fs_base); - rdmsrl(0xc0000101, saved_context.gs_base); - asm volatile ("swapgs"); + rdmsrl(MSR_FS_BASE, saved_context.fs_base); + rdmsrl(MSR_GS_BASE, saved_context.gs_base); + rdmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base); /* * control registers @@ -99,10 +99,9 @@ load_gs_index(saved_context.gs); asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss)); - asm volatile ("swapgs"); - wrmsrl(0xc0000100, saved_context.fs_base); - wrmsrl(0xc0000101, saved_context.gs_base); - asm volatile ("swapgs"); + wrmsrl(MSR_FS_BASE, saved_context.fs_base); + wrmsrl(MSR_GS_BASE, saved_context.gs_base); + wrmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base); /* * now restore the descriptor tables to their proper values diff -urN linux-2.5.64-bk5/arch/x86_64/kernel/time.c linux-2.5.64-bk6/arch/x86_64/kernel/time.c --- linux-2.5.64-bk5/arch/x86_64/kernel/time.c Tue Mar 4 19:29:31 2003 +++ linux-2.5.64-bk6/arch/x86_64/kernel/time.c Mon Mar 31 12:28:48 2003 @@ -30,7 +30,7 @@ #include #endif -u64 jiffies_64; +u64 jiffies_64 = INITIAL_JIFFIES; extern int using_apic_timer; @@ -47,8 +47,8 @@ struct hpet_data __hpet __section_hpet; /* address, quotient, trigger, hz */ -volatile unsigned long __jiffies __section_jiffies; -unsigned long __wall_jiffies __section_wall_jiffies; +volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; +unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES; struct timespec __xtime __section_xtime; struct timezone __sys_tz __section_sys_tz; diff -urN linux-2.5.64-bk5/arch/x86_64/lib/getuser.S linux-2.5.64-bk6/arch/x86_64/lib/getuser.S --- linux-2.5.64-bk5/arch/x86_64/lib/getuser.S Tue Mar 4 19:28:57 2003 +++ linux-2.5.64-bk6/arch/x86_64/lib/getuser.S Mon Mar 31 12:28:48 2003 @@ -30,7 +30,7 @@ #include .text - .p2align + .p2align 4 .globl __get_user_1 __get_user_1: GET_THREAD_INFO(%rbx) @@ -40,7 +40,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_2 __get_user_2: GET_THREAD_INFO(%rbx) @@ -52,7 +52,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_4 __get_user_4: GET_THREAD_INFO(%rbx) @@ -64,7 +64,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_8 __get_user_8: GET_THREAD_INFO(%rbx) diff -urN linux-2.5.64-bk5/arch/x86_64/mm/pageattr.c linux-2.5.64-bk6/arch/x86_64/mm/pageattr.c --- linux-2.5.64-bk5/arch/x86_64/mm/pageattr.c Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/arch/x86_64/mm/pageattr.c Mon Mar 31 12:28:48 2003 @@ -53,7 +53,7 @@ static void flush_kernel_map(void *address) { - if (address && cpu_has_clflush) { + if (0 && address && cpu_has_clflush) { /* is this worth it? */ int i; for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) diff -urN linux-2.5.64-bk5/arch/x86_64/pci/direct.c linux-2.5.64-bk6/arch/x86_64/pci/direct.c --- linux-2.5.64-bk5/arch/x86_64/pci/direct.c Tue Mar 4 19:29:57 2003 +++ linux-2.5.64-bk6/arch/x86_64/pci/direct.c Mon Mar 31 12:28:48 2003 @@ -196,21 +196,35 @@ static int __devinit pci_sanity_check(struct pci_ops *o) { u32 x = 0; - struct pci_bus bus; /* Fake bus and device */ - struct pci_dev dev; + int retval = 0; + struct pci_bus *bus; /* Fake bus and device */ + struct pci_dev *dev; if (pci_probe & PCI_NO_CHECKS) return 1; - bus.number = 0; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++) - if ((!o->read(&bus, dev.devfn, PCI_CLASS_DEVICE, 2, &x) && + + bus = kmalloc(sizeof(*bus), GFP_ATOMIC); + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if (!bus || !dev) { + printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); + goto exit; + } + + bus->number = 0; + dev->bus = bus; + for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++) + if ((!o->read(bus, dev->devfn, PCI_CLASS_DEVICE, 2, &x) && (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) || - (!o->read(&bus, dev.devfn, PCI_VENDOR_ID, 2, &x) && - (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) - return 1; + (!o->read(bus, dev->devfn, PCI_VENDOR_ID, 2, &x) && + (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) { + retval = 1; + goto exit; + } DBG("PCI: Sanity check failed\n"); - return 0; +exit: + kfree(dev); + kfree(bus); + return retval; } static int __init pci_direct_init(void) @@ -218,7 +232,7 @@ unsigned int tmp; unsigned long flags; - local_save_flags(flags); local_irq_disable(); + local_irq_save(flags); /* * Check if configuration type 1 works. @@ -261,7 +275,6 @@ } local_irq_restore(flags); - pci_root_ops = NULL; return 0; } diff -urN linux-2.5.64-bk5/arch/x86_64/pci/irq.c linux-2.5.64-bk6/arch/x86_64/pci/irq.c --- linux-2.5.64-bk5/arch/x86_64/pci/irq.c Tue Mar 4 19:29:23 2003 +++ linux-2.5.64-bk6/arch/x86_64/pci/irq.c Mon Mar 31 12:28:48 2003 @@ -109,7 +109,7 @@ */ if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL)) printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i); - pcibios_last_bus = -1; + //pcibios_last_bus = -1; } /* @@ -291,14 +291,14 @@ { irq = read_config_nybble(router, 0x56, pirq - 1); } - printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d get irq : %2d\n", + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", dev->vendor, dev->device, pirq, irq); return irq; } static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d SET irq : %2d\n", + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", dev->vendor, dev->device, pirq, irq); if (pirq <= 4) { diff -urN linux-2.5.64-bk5/arch/x86_64/pci/legacy.c linux-2.5.64-bk6/arch/x86_64/pci/legacy.c --- linux-2.5.64-bk5/arch/x86_64/pci/legacy.c Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/arch/x86_64/pci/legacy.c Mon Mar 31 12:28:48 2003 @@ -1,8 +1,8 @@ /* * legacy.c - traditional, old school PCI bus probing */ -#include #include +#include #include "pci.h" /* @@ -12,28 +12,39 @@ void __devinit pcibios_fixup_peer_bridges(void) { int n; - struct pci_bus bus; - struct pci_dev dev; + struct pci_bus *bus; + struct pci_dev *dev; u16 l; - if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff) + if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) return; DBG("PCI: Peer bridge fixup\n"); + + bus = kmalloc(sizeof(*bus), GFP_ATOMIC); + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if (!bus || !dev) { + printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); + goto exit; + } + for (n=0; n <= pcibios_last_bus; n++) { if (pci_bus_exists(&pci_root_buses, n)) continue; - bus.number = n; - bus.ops = pci_root_ops; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) - if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && + bus->number = n; + bus->ops = pci_root_ops; + dev->bus = bus; + for (dev->devfn=0; dev->devfn<256; dev->devfn += 8) + if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) && l != 0x0000 && l != 0xffff) { - DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); + DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l); printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); pci_scan_bus(n, pci_root_ops, NULL); break; } } +exit: + kfree(dev); + kfree(bus); } static int __init pci_legacy_init(void) diff -urN linux-2.5.64-bk5/arch/x86_64/pci/pci.h linux-2.5.64-bk6/arch/x86_64/pci/pci.h --- linux-2.5.64-bk5/arch/x86_64/pci/pci.h Tue Mar 4 19:29:16 2003 +++ linux-2.5.64-bk6/arch/x86_64/pci/pci.h Mon Mar 31 12:28:48 2003 @@ -67,7 +67,6 @@ extern int pcibios_scanned; extern spinlock_t pci_config_lock; -void pcibios_fixup_irqs(void); int pirq_enable_irq(struct pci_dev *dev); extern int (*pcibios_enable_irq)(struct pci_dev *dev); diff -urN linux-2.5.64-bk5/crypto/api.c linux-2.5.64-bk6/crypto/api.c --- linux-2.5.64-bk5/crypto/api.c Tue Mar 4 19:29:52 2003 +++ linux-2.5.64-bk6/crypto/api.c Mon Mar 31 12:28:48 2003 @@ -128,8 +128,6 @@ memset(tfm, 0, sizeof(*tfm)); - tfm->crt_ctx = (void*) &tfm[1]; - tfm->__crt_alg = alg; if (crypto_init_flags(tfm, flags)) diff -urN linux-2.5.64-bk5/crypto/cipher.c linux-2.5.64-bk6/crypto/cipher.c --- linux-2.5.64-bk5/crypto/cipher.c Tue Mar 4 19:29:19 2003 +++ linux-2.5.64-bk6/crypto/cipher.c Mon Mar 31 12:28:48 2003 @@ -23,7 +23,8 @@ #include "internal.h" typedef void (cryptfn_t)(void *, u8 *, const u8 *); -typedef void (procfn_t)(struct crypto_tfm *, u8 *, u8*, cryptfn_t, int enc); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *); struct scatter_walk { struct scatterlist *sg; @@ -34,6 +35,13 @@ unsigned int offset; }; +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + static inline void xor_64(u8 *a, const u8 *b) { ((u32 *)a)[0] ^= ((u32 *)b)[0]; @@ -159,7 +167,8 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes, cryptfn_t crfn, procfn_t prfn, int enc) + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) { struct scatter_walk walk_in, walk_out; const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); @@ -189,7 +198,7 @@ copy_chunks(src_p, &walk_in, bsize, 0); - prfn(tfm, dst_p, src_p, crfn, enc); + prfn(tfm, dst_p, src_p, crfn, enc, info); scatter_done(&walk_in, 0, nbytes); @@ -204,35 +213,35 @@ } static void cbc_process(struct crypto_tfm *tfm, - u8 *dst, u8 *src, cryptfn_t fn, int enc) + u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) { + u8 *iv = info; + /* Null encryption */ - if (!tfm->crt_cipher.cit_iv) + if (!iv) return; if (enc) { - tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src); - fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, dst, - crypto_tfm_alg_blocksize(tfm)); + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(crypto_tfm_ctx(tfm), dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); } else { const int need_stack = (src == dst); u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; u8 *buf = need_stack ? stack : dst; - fn(tfm->crt_ctx, buf, src); - tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, src, - crypto_tfm_alg_blocksize(tfm)); + fn(crypto_tfm_ctx(tfm), buf, src); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); if (buf != dst) memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); } } static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, - cryptfn_t fn, int enc) + cryptfn_t fn, int enc, void *info) { - fn(tfm->crt_ctx, dst, src); + fn(crypto_tfm_ctx(tfm), dst, src); } static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) @@ -243,7 +252,7 @@ tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } else - return cia->cia_setkey(tfm->crt_ctx, key, keylen, + return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, &tfm->crt_flags); } @@ -252,7 +261,8 @@ struct scatterlist *src, unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); } static int ecb_decrypt(struct crypto_tfm *tfm, @@ -261,7 +271,8 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); } static int cbc_encrypt(struct crypto_tfm *tfm, @@ -270,7 +281,18 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); } static int cbc_decrypt(struct crypto_tfm *tfm, @@ -279,7 +301,18 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0); + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); } static int nocrypt(struct crypto_tfm *tfm, @@ -290,6 +323,14 @@ return -ENOSYS; } +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) { u32 mode = flags & CRYPTO_TFM_MODE_MASK; @@ -318,16 +359,22 @@ case CRYPTO_TFM_MODE_CBC: ops->cit_encrypt = cbc_encrypt; ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; break; case CRYPTO_TFM_MODE_CFB: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; case CRYPTO_TFM_MODE_CTR: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; default: diff -urN linux-2.5.64-bk5/crypto/digest.c linux-2.5.64-bk6/crypto/digest.c --- linux-2.5.64-bk5/crypto/digest.c Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/crypto/digest.c Mon Mar 31 12:28:48 2003 @@ -19,7 +19,7 @@ static void init(struct crypto_tfm *tfm) { - tfm->__crt_alg->cra_digest.dia_init(tfm->crt_ctx); + tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); } static void update(struct crypto_tfm *tfm, @@ -29,7 +29,7 @@ for (i = 0; i < nsg; i++) { char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; - tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), p, sg[i].length); crypto_kunmap(p, 0); crypto_yield(tfm); @@ -38,7 +38,7 @@ static void final(struct crypto_tfm *tfm, u8 *out) { - tfm->__crt_alg->cra_digest.dia_final(tfm->crt_ctx, out); + tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); } static void digest(struct crypto_tfm *tfm, @@ -50,7 +50,7 @@ for (i = 0; i < nsg; i++) { char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; - tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), p, sg[i].length); crypto_kunmap(p, 0); crypto_yield(tfm); diff -urN linux-2.5.64-bk5/crypto/internal.h linux-2.5.64-bk6/crypto/internal.h --- linux-2.5.64-bk5/crypto/internal.h Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/crypto/internal.h Mon Mar 31 12:28:48 2003 @@ -18,18 +18,12 @@ #include #include -static enum km_type km_types[] = { - KM_USER0, - KM_USER1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, -}; +extern enum km_type crypto_km_types[]; static inline enum km_type crypto_kmap_type(int out) { - return km_types[(in_softirq() ? 2 : 0) + out]; + return crypto_km_types[(in_softirq() ? 2 : 0) + out]; } - static inline void *crypto_kmap(struct page *page, int out) { @@ -52,6 +46,11 @@ return flags & (CRYPTO_TFM_MODE_MASK|CRYPTO_TFM_REQ_WEAK_KEY); } +static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) +{ + return (void *)&tfm[1]; +} + struct crypto_alg *crypto_alg_lookup(const char *name); #ifdef CONFIG_KMOD diff -urN linux-2.5.64-bk5/drivers/Makefile linux-2.5.64-bk6/drivers/Makefile --- linux-2.5.64-bk5/drivers/Makefile Tue Mar 4 19:29:33 2003 +++ linux-2.5.64-bk6/drivers/Makefile Mon Mar 31 12:28:48 2003 @@ -11,9 +11,13 @@ # PnP must come after ACPI since it will eventually need to check if acpi # was used and do nothing if so obj-$(CONFIG_PNP) += pnp/ + +# char/ comes before serial/ etc so that the VT console is the boot-time +# default. +obj-y += char/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ -obj-y += base/ char/ block/ misc/ net/ media/ +obj-y += base/ block/ misc/ net/ media/ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_IDE) += ide/ diff -urN linux-2.5.64-bk5/drivers/atm/Makefile linux-2.5.64-bk6/drivers/atm/Makefile --- linux-2.5.64-bk5/drivers/atm/Makefile Tue Mar 4 19:28:56 2003 +++ linux-2.5.64-bk6/drivers/atm/Makefile Mon Mar 31 12:28:48 2003 @@ -46,7 +46,7 @@ ifeq ($(CONFIG_ATM_FORE200E_SBA),y) fore_200e-objs += fore200e_sba_fw.o ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y) - CONFIG_ATM_FORE200E_SBA_FW := sba200e_ecd.bin2 + CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 endif endif diff -urN linux-2.5.64-bk5/drivers/block/genhd.c linux-2.5.64-bk6/drivers/block/genhd.c --- linux-2.5.64-bk5/drivers/block/genhd.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/drivers/block/genhd.c Mon Mar 31 12:28:48 2003 @@ -91,9 +91,6 @@ struct blk_major_name **n, *p; int index, ret = 0; - if (devfs_only()) - return 0; - /* temporary */ if (major == 0) { down_read(&block_subsys.rwsem); @@ -141,13 +138,9 @@ int unregister_blkdev(unsigned int major, const char *name) { struct blk_major_name **n, *p; - int index; + int index = major_to_index(major); int ret = 0; - if (devfs_only()) - return 0; - index = major_to_index(major); - down_write(&block_subsys.rwsem); for (n = &major_names[index]; *n; n = &(*n)->next) if ((*n)->major == major) diff -urN linux-2.5.64-bk5/drivers/i2c/i2c-core.c linux-2.5.64-bk6/drivers/i2c/i2c-core.c --- linux-2.5.64-bk5/drivers/i2c/i2c-core.c Tue Mar 4 19:29:00 2003 +++ linux-2.5.64-bk6/drivers/i2c/i2c-core.c Mon Mar 31 12:28:49 2003 @@ -68,22 +68,12 @@ /**** debug level */ static int i2c_debug; -/* --------------------------------------------------- - * /proc entry declarations - *---------------------------------------------------- - */ - #ifdef CONFIG_PROC_FS -static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos); -static int read_bus_i2c(char *buf, char **start, off_t offset, int len, - int *eof , void *private); - -/* To implement the dynamic /proc/bus/i2c-? files, we need our own - implementation of the read hook */ -static struct file_operations i2cproc_operations = { - .read = i2cproc_bus_read, -}; +static int i2cproc_register(struct i2c_adapter *adap, int bus); +static void i2cproc_remove(int bus); +#else +# define i2cproc_register(adap, bus) 0 +# define i2cproc_remove(bus) do { } while (0) #endif /* CONFIG_PROC_FS */ @@ -109,8 +99,7 @@ printk(KERN_WARNING " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n", adap->name); - res = -ENOMEM; - goto ERROR0; + goto fail; } adapters[i] = adap; @@ -119,26 +108,9 @@ /* init data types */ init_MUTEX(&adap->lock); -#ifdef CONFIG_PROC_FS - { - char name[8]; - struct proc_dir_entry *proc_entry; - - sprintf(name,"i2c-%d", i); - - proc_entry = create_proc_entry(name,0,proc_bus); - if (! proc_entry) { - printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", - name); - res = -ENOENT; - goto ERROR1; - } - - proc_entry->proc_fops = &i2cproc_operations; - proc_entry->owner = THIS_MODULE; - adap->inode = proc_entry->low_ino; - } -#endif /* def CONFIG_PROC_FS */ + res = i2cproc_register(adap, i); + if (res) + return res; /* inform drivers of new adapters */ DRV_LOCK(); @@ -154,13 +126,9 @@ return 0; - -ERROR1: - ADAP_LOCK(); - adapters[i] = NULL; -ERROR0: + fail: ADAP_UNLOCK(); - return res; + return -ENOMEM; } @@ -214,13 +182,8 @@ goto ERROR0; } } -#ifdef CONFIG_PROC_FS - { - char name[8]; - sprintf(name,"i2c-%d", i); - remove_proc_entry(name, proc_bus); - } -#endif /* def CONFIG_PROC_FS */ + + i2cproc_remove(i); adapters[i] = NULL; @@ -501,10 +464,9 @@ */ #ifdef CONFIG_PROC_FS - /* This function generates the output for /proc/bus/i2c */ -int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, - void *private) +static int read_bus_i2c(char *buf, char **start, off_t offset, + int len, int *eof, void *private) { int i; int nr = 0; @@ -529,10 +491,10 @@ } /* This function generates the output for /proc/bus/i2c-? */ -ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos) +static ssize_t i2cproc_bus_read(struct file *file, char *buf, + size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; char *kbuf; struct i2c_client *client; int i,j,k,order_nr,len=0; @@ -593,6 +555,38 @@ return -ENOENT; } +static struct file_operations i2cproc_operations = { + .read = i2cproc_bus_read, +}; + +static int i2cproc_register(struct i2c_adapter *adap, int bus) +{ + struct proc_dir_entry *proc_entry; + char name[8]; + + sprintf(name, "i2c-%d", bus); + + proc_entry = create_proc_entry(name, 0, proc_bus); + if (!proc_entry) + goto fail; + + proc_entry->proc_fops = &i2cproc_operations; + proc_entry->owner = THIS_MODULE; + adap->inode = proc_entry->low_ino; + return 0; + fail: + printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", name); + return -ENOENT; +} + +static void i2cproc_remove(int bus) +{ + char name[8]; + + sprintf(name,"i2c-%d", bus); + remove_proc_entry(name, proc_bus); +} + static int i2cproc_init(void) { @@ -611,7 +605,6 @@ static void __exit i2cproc_cleanup(void) { - remove_proc_entry("i2c",proc_bus); } diff -urN linux-2.5.64-bk5/drivers/media/video/video-buf.c linux-2.5.64-bk6/drivers/media/video/video-buf.c --- linux-2.5.64-bk5/drivers/media/video/video-buf.c Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/drivers/media/video/video-buf.c Mon Mar 31 12:28:49 2003 @@ -83,6 +83,8 @@ return NULL; memset(sglist, 0, sizeof(*sglist) * nr_pages); + if (NULL == pages[0]) + goto nopage; if (PageHighMem(pages[0])) /* DMA to highmem pages might not work */ goto highmem; @@ -118,7 +120,7 @@ for (i = 0; i < nr_pages; i++) if (TryLockPage(pages[i])) goto err; - dprintk(2,"lock ok\n"); + dprintk(2,"lock ok [%d pages]\n",nr_pages); return 0; err: @@ -136,7 +138,7 @@ dprintk(2,"unlock start ...\n"); for (i = 0; i < nr_pages; i++) unlock_page(pages[i]); - dprintk(2,"unlock ok\n"); + dprintk(2,"unlock ok [%d pages]\n",nr_pages); return 0; } @@ -270,7 +272,7 @@ /* --------------------------------------------------------------------- */ -void* videobuf_alloc(int size) +void* videobuf_alloc(unsigned int size) { struct videobuf_buffer *vb; @@ -340,7 +342,7 @@ spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, - int msize) + unsigned int msize) { memset(q,0,sizeof(*q)); @@ -417,11 +419,11 @@ if (V4L2_FIELD_ALTERNATE == field) { if (V4L2_FIELD_TOP == q->last) { - field = V4L2_FIELD_TOP; - q->last = V4L2_FIELD_TOP; - } else { field = V4L2_FIELD_BOTTOM; q->last = V4L2_FIELD_BOTTOM; + } else { + field = V4L2_FIELD_TOP; + q->last = V4L2_FIELD_TOP; } } return field; @@ -463,7 +465,8 @@ videobuf_reqbufs(struct file *file, struct videobuf_queue *q, struct v4l2_requestbuffers *req) { - int size,count,retval; + unsigned int size,count; + int retval; if (req->type != q->type) return -EINVAL; @@ -477,6 +480,8 @@ size = 0; q->ops->buf_setup(file,&count,&size); size = PAGE_ALIGN(size); + dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n", + count, size, (count*size)>>PAGE_SHIFT); retval = videobuf_mmap_setup(file,q,count,size); if (retval < 0) @@ -660,7 +665,10 @@ retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); - retval = q->read_buf->size; + if (STATE_ERROR == q->read_buf->state) + retval = -EIO; + else + retval = q->read_buf->size; } done: @@ -676,7 +684,8 @@ { enum v4l2_field field; unsigned long flags; - int retval, bytes, size, nbufs; + unsigned size, nbufs, bytes; + int retval; down(&q->lock); @@ -686,7 +695,7 @@ count >= size && !(file->f_flags & O_NONBLOCK)) { retval = videobuf_read_zerocopy(file,q,data,count,ppos); - if (retval >= 0) + if (retval >= 0 || retval == -EIO) /* ok, all done */ goto done; /* fallback to kernel bounce buffer on failures */ @@ -714,6 +723,15 @@ goto done; videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + if (STATE_ERROR == q->read_buf->state) { + /* catch I/O errors */ + q->ops->buf_release(file,q->read_buf); + kfree(q->read_buf); + q->read_buf = NULL; + retval = -EIO; + goto done; + } + /* copy to userspace */ bytes = count; if (bytes > q->read_buf->size - q->read_off) @@ -788,8 +806,8 @@ char *data, size_t count, loff_t *ppos, int vbihack) { - unsigned int *fc; - int err, bytes, retval; + unsigned int *fc, bytes; + int err, retval; unsigned long flags; down(&q->lock); @@ -968,9 +986,10 @@ }; int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, - int bcount, int bsize) + unsigned int bcount, unsigned int bsize) { - int i,err; + unsigned int i; + int err; err = videobuf_mmap_free(file,q); if (0 != err) @@ -1008,7 +1027,8 @@ struct videobuf_queue *q) { struct videobuf_mapping *map; - int first,last,size,i,retval; + unsigned int first,last,size,i; + int retval; down(&q->lock); retval = -EINVAL; @@ -1025,7 +1045,7 @@ for (first = 0; first < VIDEO_MAX_FRAME; first++) { if (NULL == q->bufs[first]) continue; - if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) + if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) break; } if (VIDEO_MAX_FRAME == first) { diff -urN linux-2.5.64-bk5/drivers/media/video/video-buf.h linux-2.5.64-bk6/drivers/media/video/video-buf.h --- linux-2.5.64-bk5/drivers/media/video/video-buf.h Tue Mar 4 19:29:20 2003 +++ linux-2.5.64-bk6/drivers/media/video/video-buf.h Mon Mar 31 12:28:49 2003 @@ -110,7 +110,7 @@ struct videobuf_queue; struct videobuf_mapping { - int count; + unsigned int count; int highmem_ok; unsigned long start; unsigned long end; @@ -128,19 +128,19 @@ }; struct videobuf_buffer { - int i; + unsigned int i; /* info about the buffer */ - int width; - int height; - long size; + unsigned int width; + unsigned int height; + unsigned long size; enum v4l2_field field; enum videobuf_state state; struct videobuf_dmabuf dma; struct list_head stream; /* QBUF/DQBUF list */ /* for mmap'ed buffers */ - off_t boff; /* buffer offset (mmap) */ + size_t boff; /* buffer offset (mmap) */ size_t bsize; /* buffer size */ unsigned long baddr; /* buffer addr (userland ptr!) */ struct videobuf_mapping *map; @@ -148,12 +148,13 @@ /* touched by irq handler */ struct list_head queue; wait_queue_head_t done; - int field_count; + unsigned int field_count; struct timeval ts; }; struct videobuf_queue_ops { - int (*buf_setup)(struct file *file, int *count, int *size); + int (*buf_setup)(struct file *file, + unsigned int *count, unsigned int *size); int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb, enum v4l2_field field); void (*buf_queue)(struct file *file,struct videobuf_buffer *vb); @@ -166,23 +167,23 @@ struct pci_dev *pci; enum v4l2_buf_type type; - int msize; + unsigned int msize; enum v4l2_field field; enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; struct videobuf_queue_ops *ops; /* capture via mmap() + ioctl(QBUF/DQBUF) */ - int streaming; + unsigned int streaming; struct list_head stream; /* capture via read() */ - int reading; - int read_off; + unsigned int reading; + unsigned int read_off; struct videobuf_buffer *read_buf; }; -void* videobuf_alloc(int size); +void* videobuf_alloc(unsigned int size); int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb); @@ -190,7 +191,8 @@ struct videobuf_queue_ops *ops, struct pci_dev *pci, spinlock_t *irqlock, enum v4l2_buf_type type, - enum v4l2_field field, int msize); + enum v4l2_field field, + unsigned int msize); int videobuf_queue_is_busy(struct videobuf_queue *q); void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q); @@ -218,7 +220,7 @@ poll_table *wait); int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, - int bcount, int bsize); + unsigned int bcount, unsigned int bsize); int videobuf_mmap_free(struct file *file, struct videobuf_queue *q); int videobuf_mmap_mapper(struct vm_area_struct *vma, struct videobuf_queue *q); diff -urN linux-2.5.64-bk5/drivers/net/pppoe.c linux-2.5.64-bk6/drivers/net/pppoe.c --- linux-2.5.64-bk5/drivers/net/pppoe.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/drivers/net/pppoe.c Mon Mar 31 12:28:49 2003 @@ -777,7 +777,7 @@ int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, struct scm_cookie *scm) + int total_len) { struct sk_buff *skb = NULL; struct sock *sk = sock->sk; @@ -937,7 +937,8 @@ struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL }; -int pppoe_rcvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm) +int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, int total_len, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb = NULL; @@ -1089,7 +1090,7 @@ .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = pppoe_sendmsg, - .recvmsg = pppoe_rcvmsg, + .recvmsg = pppoe_recvmsg, .mmap = sock_no_mmap }; diff -urN linux-2.5.64-bk5/drivers/pnp/Kconfig linux-2.5.64-bk6/drivers/pnp/Kconfig --- linux-2.5.64-bk5/drivers/pnp/Kconfig Tue Mar 4 19:29:19 2003 +++ linux-2.5.64-bk6/drivers/pnp/Kconfig Mon Mar 31 12:28:49 2003 @@ -30,15 +30,6 @@ If unsure, say Y. -config PNP_CARD - bool "Plug and Play card services" - depends on PNP - help - Select Y if you want the PnP Layer to manage cards. Cards are groups - of PnP devices. Some drivers, especially PnP sound card drivers, use - these cards. If you want to use the protocol ISAPNP you will need to - say Y here. - config PNP_DEBUG bool "PnP Debug Messages" depends on PNP @@ -51,7 +42,7 @@ config ISAPNP bool "ISA Plug and Play support (EXPERIMENTAL)" - depends on PNP && EXPERIMENTAL && PNP_CARD + depends on PNP && EXPERIMENTAL help Say Y here if you would like support for ISA Plug and Play devices. Some information is in . diff -urN linux-2.5.64-bk5/drivers/pnp/Makefile linux-2.5.64-bk6/drivers/pnp/Makefile --- linux-2.5.64-bk5/drivers/pnp/Makefile Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/drivers/pnp/Makefile Mon Mar 31 12:28:49 2003 @@ -2,9 +2,7 @@ # Makefile for the Linux Plug-and-Play Support. # -pnp-card-$(CONFIG_PNP_CARD) = card.o - -obj-y := core.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o $(pnp-card-y) +obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ diff -urN linux-2.5.64-bk5/drivers/pnp/card.c linux-2.5.64-bk6/drivers/pnp/card.c --- linux-2.5.64-bk5/drivers/pnp/card.c Tue Mar 4 19:29:51 2003 +++ linux-2.5.64-bk6/drivers/pnp/card.c Mon Mar 31 12:28:49 2003 @@ -16,15 +16,14 @@ #endif #include -#include #include "base.h" - LIST_HEAD(pnp_cards); -static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp_card *card) + +static const struct pnp_card_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) { - const struct pnp_card_id *drv_id = drv->id_table; + const struct pnp_card_id * drv_id = drv->id_table; while (*drv_id->id){ if (compare_pnp_id(card->id,drv_id->id)) return drv_id; @@ -33,31 +32,33 @@ return NULL; } -static int card_bus_match(struct device *dev, struct device_driver *drv) +static void generic_card_remove(struct pnp_dev * dev) { - struct pnp_card * card = to_pnp_card(dev); - struct pnpc_driver * pnp_drv = to_pnpc_driver(drv); - if (match_card(pnp_drv, card) == NULL) - return 0; - return 1; + dev->card_link = NULL; } -struct bus_type pnpc_bus_type = { - .name = "pnp_card", - .match = card_bus_match, -}; - +static void generic_card_remove_first(struct pnp_dev * dev) +{ + struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); + if (!dev->card || !drv) + return; + if (drv->remove) + drv->remove(dev->card_link); + drv->link.remove = &generic_card_remove; + kfree(dev->card_link); + generic_card_remove(dev); +} /** - * pnpc_add_id - adds an EISA id to the specified card + * pnp_add_card_id - adds an EISA id to the specified card * @id: pointer to a pnp_id structure * @card: pointer to the desired card * */ -int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) +int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card) { - struct pnp_id *ptr; + struct pnp_id * ptr; if (!id) return -EINVAL; if (!card) @@ -73,7 +74,7 @@ return 0; } -static void pnpc_free_ids(struct pnp_card *card) +static void pnp_free_card_ids(struct pnp_card * card) { struct pnp_id * id; struct pnp_id *next; @@ -90,47 +91,51 @@ static void pnp_release_card(struct device *dmdev) { struct pnp_card * card = to_pnp_card(dmdev); - pnpc_free_ids(card); + pnp_free_card_ids(card); kfree(card); } /** - * pnpc_add_card - adds a PnP card to the PnP Layer + * pnp_add_card - adds a PnP card to the PnP Layer * @card: pointer to the card to add */ -int pnpc_add_card(struct pnp_card *card) +int pnp_add_card(struct pnp_card * card) { - int error = 0; + int error; + struct list_head * pos; if (!card || !card->protocol) return -EINVAL; + sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number); - INIT_LIST_HEAD(&card->rdevs); card->dev.parent = &card->protocol->dev; - card->dev.bus = &pnpc_bus_type; + card->dev.bus = NULL; card->dev.release = &pnp_release_card; - card->status = PNP_READY; error = device_register(&card->dev); - if (error == 0){ - struct list_head *pos; + if (error == 0) { spin_lock(&pnp_lock); list_add_tail(&card->global_list, &pnp_cards); list_add_tail(&card->protocol_list, &card->protocol->cards); spin_unlock(&pnp_lock); + + /* we wait until now to add devices in order to ensure the drivers + * will be able to use all of the related devices on the card + * without waiting any unresonable length of time */ list_for_each(pos,&card->devices){ struct pnp_dev *dev = card_to_pnp_dev(pos); __pnp_add_device(dev); } - } + } else + pnp_err("sysfs failure, card '%s' will be unavailable", card->dev.bus_id); return error; } /** - * pnpc_remove_card - removes a PnP card from the PnP Layer + * pnp_remove_card - removes a PnP card from the PnP Layer * @card: pointer to the card to remove */ -void pnpc_remove_card(struct pnp_card *card) +void pnp_remove_card(struct pnp_card * card) { struct list_head *pos, *temp; if (!card) @@ -142,22 +147,24 @@ spin_unlock(&pnp_lock); list_for_each_safe(pos,temp,&card->devices){ struct pnp_dev *dev = card_to_pnp_dev(pos); - pnpc_remove_device(dev); + pnp_remove_card_device(dev); } } /** - * pnpc_add_device - adds a device to the specified card + * pnp_add_card_device - adds a device to the specified card * @card: pointer to the card to add to * @dev: pointer to the device to add */ -int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) +int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev) { - if (!dev || !dev->protocol || !card) + if (!card || !dev || !dev->protocol) return -EINVAL; dev->dev.parent = &card->dev; - sprintf(dev->dev.bus_id, "%02x:%02x.%02x", dev->protocol->number, card->number,dev->number); + dev->card_link = NULL; + snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", dev->protocol->number, + card->number,dev->number); spin_lock(&pnp_lock); dev->card = card; list_add_tail(&dev->card_list, &card->devices); @@ -166,12 +173,12 @@ } /** - * pnpc_remove_device- removes a device from the specified card + * pnp_remove_card_device- removes a device from the specified card * @card: pointer to the card to remove from * @dev: pointer to the device to remove */ -void pnpc_remove_device(struct pnp_dev *dev) +void pnp_remove_card_device(struct pnp_dev * dev) { spin_lock(&pnp_lock); dev->card = NULL; @@ -182,20 +189,21 @@ /** * pnp_request_card_device - Searches for a PnP device under the specified card - * @card: pointer to the card to search under, cannot be NULL + * @lcard: pointer to the card link, cannot be NULL * @id: pointer to a PnP ID structure that explains the rules for finding the device * @from: Starting place to search from. If NULL it will start from the begining. - * - * Will activate the device */ -struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) +struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) { - struct list_head *pos; - struct pnp_dev *dev; - struct pnpc_driver *cdrv; - if (!card || !id) + struct list_head * pos; + struct pnp_dev * dev; + struct pnp_card_driver * drv; + struct pnp_card * card; + if (!clink || !id) goto done; + card = clink->card; + drv = clink->driver; if (!from) { pos = card->devices.next; } else { @@ -205,7 +213,7 @@ } while (pos != &card->devices) { dev = card_to_pnp_dev(pos); - if (compare_pnp_id(dev->id,id)) + if ((!dev->card_link) && compare_pnp_id(dev->id,id)) goto found; pos = pos->next; } @@ -214,168 +222,93 @@ return NULL; found: - if (pnp_device_attach(dev) < 0) - return NULL; - cdrv = to_pnpc_driver(card->dev.driver); - if (dev->active == 0) { - if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) { - if(pnp_activate_dev(dev)<0) { - pnp_device_detach(dev); - return NULL; - } + down_write(&dev->dev.bus->subsys.rwsem); + dev->card_link = clink; + dev->dev.driver = &drv->link.driver; + if (drv->link.driver.probe) { + if (drv->link.driver.probe(&dev->dev)) { + dev->dev.driver = NULL; + return NULL; } - } else { - if ((cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) - pnp_disable_dev(dev); } - spin_lock(&pnp_lock); - list_add_tail(&dev->rdev_list, &card->rdevs); - spin_unlock(&pnp_lock); + device_bind_driver(&dev->dev); + up_write(&dev->dev.bus->subsys.rwsem); + return dev; } /** * pnp_release_card_device - call this when the driver no longer needs the device * @dev: pointer to the PnP device stucture - * - * Will disable the device */ -void pnp_release_card_device(struct pnp_dev *dev) -{ - spin_lock(&pnp_lock); - list_del(&dev->rdev_list); - spin_unlock(&pnp_lock); - pnp_device_detach(dev); -} - -static void pnpc_recover_devices(struct pnp_card *card) -{ - struct list_head *pos, *temp; - list_for_each_safe(pos,temp,&card->rdevs){ - struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list); - pnp_release_card_device(dev); - } -} - -int pnpc_attach(struct pnp_card *pnp_card) -{ - spin_lock(&pnp_lock); - if(pnp_card->status != PNP_READY){ - spin_unlock(&pnp_lock); - return -EBUSY; - } - pnp_card->status = PNP_ATTACHED; - spin_unlock(&pnp_lock); - return 0; -} - -void pnpc_detach(struct pnp_card *pnp_card) -{ - spin_lock(&pnp_lock); - if (pnp_card->status == PNP_ATTACHED) - pnp_card->status = PNP_READY; - spin_unlock(&pnp_lock); - pnpc_recover_devices(pnp_card); -} - -static int pnpc_card_probe(struct device *dev) -{ - int error = 0; - struct pnpc_driver *drv = to_pnpc_driver(dev->driver); - struct pnp_card *card = to_pnp_card(dev); - const struct pnp_card_id *card_id = NULL; - - pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name); - - error = pnpc_attach(card); - if (error < 0) - return error; - if (drv->probe) { - card_id = match_card(drv, card); - if (card_id != NULL) - error = drv->probe(card, card_id); - if (error >= 0){ - card->driver = drv; - error = 0; - } else - pnpc_detach(card); - } - return error; -} - -static int pnpc_card_remove(struct device *dev) +void pnp_release_card_device(struct pnp_dev * dev) { - struct pnp_card * card = to_pnp_card(dev); - struct pnpc_driver * drv = card->driver; - - if (drv) { - if (drv->remove) - drv->remove(card); - card->driver = NULL; - } - pnpc_detach(card); - return 0; + struct pnp_card_driver * drv = dev->card_link->driver; + if (!drv) + return; + down_write(&dev->dev.bus->subsys.rwsem); + drv->link.remove = &generic_card_remove; + device_release_driver(&dev->dev); + drv->link.remove = &generic_card_remove_first; + up_write(&dev->dev.bus->subsys.rwsem); } /** - * pnpc_register_driver - registers a PnP card driver with the PnP Layer - * @cdrv: pointer to the driver to register + * pnp_register_card_driver - registers a PnP card driver with the PnP Layer + * @drv: pointer to the driver to register */ -int pnpc_register_driver(struct pnpc_driver * drv) +int pnp_register_card_driver(struct pnp_card_driver * drv) { - int count; - struct list_head *pos; - - drv->driver.name = drv->name; - drv->driver.bus = &pnpc_bus_type; - drv->driver.probe = pnpc_card_probe; - drv->driver.remove = pnpc_card_remove; - - pnp_dbg("the card driver '%s' has been registered", drv->name); - - count = driver_register(&drv->driver); + int count = 0; + struct list_head *pos, *temp; - /* get the number of initial matches */ - if (count >= 0){ - count = 0; - list_for_each(pos,&drv->driver.devices){ - count++; + drv->link.name = drv->name; + drv->link.id_table = NULL; /* this will disable auto matching */ + drv->link.flags = drv->flags; + drv->link.probe = NULL; + drv->link.remove = &generic_card_remove_first; + + pnp_register_driver(&drv->link); + + list_for_each_safe(pos,temp,&pnp_cards){ + struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); + const struct pnp_card_id *id = match_card(drv,card); + if (id) { + struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link)); + if (!clink) + continue; + clink->card = card; + clink->driver = drv; + if (drv->probe) { + if (drv->probe(clink, id)>=0) + count++; + } else + count++; } } return count; } /** - * pnpc_unregister_driver - unregisters a PnP card driver from the PnP Layer - * @cdrv: pointer to the driver to unregister - * - * Automatically disables requested devices + * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer + * @drv: pointer to the driver to unregister */ -void pnpc_unregister_driver(struct pnpc_driver *drv) +void pnp_unregister_card_driver(struct pnp_card_driver * drv) { - driver_unregister(&drv->driver); - pnp_dbg("the card driver '%s' has been unregistered", drv->name); -} + pnp_unregister_driver(&drv->link); -static int __init pnp_card_init(void) -{ - printk(KERN_INFO "pnp: Enabling Plug and Play Card Services.\n"); - return bus_register(&pnpc_bus_type); + pnp_dbg("the card driver '%s' has been unregistered", drv->name); } -subsys_initcall(pnp_card_init); - -EXPORT_SYMBOL(pnpc_add_card); -EXPORT_SYMBOL(pnpc_remove_card); -EXPORT_SYMBOL(pnpc_add_device); -EXPORT_SYMBOL(pnpc_remove_device); +EXPORT_SYMBOL(pnp_add_card); +EXPORT_SYMBOL(pnp_remove_card); +EXPORT_SYMBOL(pnp_add_card_device); +EXPORT_SYMBOL(pnp_remove_card_device); +EXPORT_SYMBOL(pnp_add_card_id); EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); -EXPORT_SYMBOL(pnpc_register_driver); -EXPORT_SYMBOL(pnpc_unregister_driver); -EXPORT_SYMBOL(pnpc_add_id); -EXPORT_SYMBOL(pnpc_attach); -EXPORT_SYMBOL(pnpc_detach); +EXPORT_SYMBOL(pnp_register_card_driver); +EXPORT_SYMBOL(pnp_unregister_card_driver); diff -urN linux-2.5.64-bk5/drivers/pnp/driver.c linux-2.5.64-bk6/drivers/pnp/driver.c --- linux-2.5.64-bk5/drivers/pnp/driver.c Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/drivers/pnp/driver.c Mon Mar 31 12:28:49 2003 @@ -53,12 +53,11 @@ static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev) { const struct pnp_device_id *drv_id = drv->id_table; - if (!drv) + if (!drv_id) return NULL; - if (!dev) - return NULL; - while (*drv_id->id){ - if (compare_pnp_id(dev->id,drv_id->id)) + + while (*drv_id->id) { + if (compare_pnp_id(dev->id, drv_id->id)) return drv_id; drv_id++; } @@ -102,14 +101,19 @@ return error; if (pnp_dev->active == 0) { - if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) { + if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { error = pnp_activate_dev(pnp_dev); if (error < 0) return error; } + } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE) + == PNP_DRIVER_RES_DISABLE) { + error = pnp_disable_dev(pnp_dev); + if (error < 0) + return error; } error = 0; - if (pnp_drv->probe && pnp_dev->active) { + if (pnp_drv->probe) { dev_id = match_device(pnp_drv, pnp_dev); if (dev_id != NULL) error = pnp_drv->probe(pnp_dev, dev_id); @@ -117,9 +121,8 @@ if (error >= 0){ pnp_dev->driver = pnp_drv; error = 0; - } - else - goto fail; + } else + goto fail; return error; fail: diff -urN linux-2.5.64-bk5/drivers/pnp/interface.c linux-2.5.64-bk6/drivers/pnp/interface.c --- linux-2.5.64-bk5/drivers/pnp/interface.c Tue Mar 4 19:29:00 2003 +++ linux-2.5.64-bk6/drivers/pnp/interface.c Mon Mar 31 12:28:49 2003 @@ -332,11 +332,18 @@ buffer->buffer = buf; buffer->curr = buffer->buffer; + pnp_printf(buffer,"mode = "); + if (dev->config_mode & PNP_CONFIG_MANUAL) + pnp_printf(buffer,"manual\n"); + else + pnp_printf(buffer,"auto\n"); + pnp_printf(buffer,"state = "); if (dev->active) pnp_printf(buffer,"active\n"); else pnp_printf(buffer,"disabled\n"); + for (i = 0; i < PNP_MAX_PORT; i++) { if (pnp_port_valid(dev, i)) { pnp_printf(buffer,"io"); @@ -402,13 +409,13 @@ retval = pnp_activate_dev(dev); goto done; } - if (!strnicmp(buf,"auto-config",11)) { + if (!strnicmp(buf,"auto",4)) { if (dev->active) goto done; retval = pnp_auto_config_dev(dev); goto done; } - if (!strnicmp(buf,"clear-config",12)) { + if (!strnicmp(buf,"clear",5)) { if (dev->active) goto done; spin_lock(&pnp_lock); diff -urN linux-2.5.64-bk5/drivers/pnp/isapnp/core.c linux-2.5.64-bk6/drivers/pnp/isapnp/core.c --- linux-2.5.64-bk5/drivers/pnp/isapnp/core.c Tue Mar 4 19:29:21 2003 +++ linux-2.5.64-bk6/drivers/pnp/isapnp/core.c Mon Mar 31 12:28:49 2003 @@ -626,7 +626,7 @@ isapnp_peek(name, size1); name[size1] = '\0'; *size -= size1; - + /* clean whitespace from end of string */ while (size1 > 0 && name[--size1] == ' ') name[size1] = '\0'; @@ -647,7 +647,7 @@ return 1; if (pnp_build_resource(dev, 0) == NULL) return 1; - pnpc_add_device(card,dev); + pnp_add_card_device(card,dev); while (1) { if (isapnp_read_tag(&type, &size)<0) return 1; @@ -659,7 +659,7 @@ if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; pnp_build_resource(dev,0); - pnpc_add_device(card,dev); + pnp_add_card_device(card,dev); size = 0; skip = 0; } else { @@ -852,7 +852,7 @@ device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); - pnpc_add_id(id,card); + pnp_add_card_id(id,card); } @@ -962,7 +962,7 @@ isapnp_parse_current_resources(dev, &dev->res); } - pnpc_add_card(card); + pnp_add_card(card); } isapnp_wait(); return 0; diff -urN linux-2.5.64-bk5/drivers/pnp/manager.c linux-2.5.64-bk6/drivers/pnp/manager.c --- linux-2.5.64-bk5/drivers/pnp/manager.c Tue Mar 4 19:29:52 2003 +++ linux-2.5.64-bk6/drivers/pnp/manager.c Mon Mar 31 12:28:49 2003 @@ -532,6 +532,39 @@ return error; } +static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab) +{ + int idx; + for (idx = 0; idx < PNP_MAX_IRQ; idx++) { + if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->irq_resource[idx].start = ntab->irq_resource[idx].start; + ctab->irq_resource[idx].end = ntab->irq_resource[idx].end; + ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_DMA; idx++) { + if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->dma_resource[idx].start = ntab->dma_resource[idx].start; + ctab->dma_resource[idx].end = ntab->dma_resource[idx].end; + ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_PORT; idx++) { + if (ntab->port_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->port_resource[idx].start = ntab->port_resource[idx].start; + ctab->port_resource[idx].end = ntab->port_resource[idx].end; + ctab->port_resource[idx].flags = ntab->port_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_MEM; idx++) { + if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->irq_resource[idx].start = ntab->mem_resource[idx].start; + ctab->irq_resource[idx].end = ntab->mem_resource[idx].end; + ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags; + } +} + /** * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table * @dev: pointer to the desired device @@ -554,7 +587,7 @@ *bak = dev->res; spin_lock(&pnp_lock); - dev->res = *res; + pnp_process_manual_resources(&dev->res, res); if (!(mode & PNP_CONFIG_FORCE)) { for (i = 0; i < PNP_MAX_PORT; i++) { if(pnp_check_port(dev,i)) @@ -681,7 +714,7 @@ return -1; } dev->active = 0; /* just in case the protocol doesn't do this */ - pnp_dbg("the device '%s' has been disabled.", dev->dev.bus_id); + pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id); return 0; } diff -urN linux-2.5.64-bk5/drivers/pnp/resource.c linux-2.5.64-bk6/drivers/pnp/resource.c --- linux-2.5.64-bk5/drivers/pnp/resource.c Tue Mar 4 19:29:22 2003 +++ linux-2.5.64-bk6/drivers/pnp/resource.c Mon Mar 31 12:28:49 2003 @@ -558,25 +558,25 @@ table->irq_resource[idx].name = NULL; table->irq_resource[idx].start = -1; table->irq_resource[idx].end = -1; - table->irq_resource[idx].flags = 0; + table->irq_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { table->dma_resource[idx].name = NULL; table->dma_resource[idx].start = -1; table->dma_resource[idx].end = -1; - table->dma_resource[idx].flags = 0; + table->dma_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { table->port_resource[idx].name = NULL; table->port_resource[idx].start = 0; table->port_resource[idx].end = 0; - table->port_resource[idx].flags = 0; + table->port_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { table->mem_resource[idx].name = NULL; table->mem_resource[idx].start = 0; table->mem_resource[idx].end = 0; - table->mem_resource[idx].flags = 0; + table->mem_resource[idx].flags = IORESOURCE_AUTO; } } diff -urN linux-2.5.64-bk5/drivers/pnp/system.c linux-2.5.64-bk6/drivers/pnp/system.c --- linux-2.5.64-bk5/drivers/pnp/system.c Tue Mar 4 19:29:56 2003 +++ linux-2.5.64-bk6/drivers/pnp/system.c Mon Mar 31 12:28:49 2003 @@ -93,8 +93,8 @@ static struct pnp_driver system_pnp_driver = { .name = "system", - .flags = PNP_DRIVER_DO_NOT_ACTIVATE, .id_table = pnp_dev_table, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, .probe = system_pnp_probe, .remove = NULL, }; diff -urN linux-2.5.64-bk5/fs/char_dev.c linux-2.5.64-bk6/fs/char_dev.c --- linux-2.5.64-bk5/fs/char_dev.c Tue Mar 4 19:29:15 2003 +++ linux-2.5.64-bk6/fs/char_dev.c Mon Mar 31 12:28:50 2003 @@ -191,8 +191,6 @@ int register_chrdev(unsigned int major, const char * name, struct file_operations *fops) { - if (devfs_only()) - return 0; if (major == 0) { write_lock(&chrdevs_lock); for (major = MAX_CHRDEV-1; major > 0; major--) { @@ -221,8 +219,6 @@ int unregister_chrdev(unsigned int major, const char * name) { - if (devfs_only()) - return 0; if (major >= MAX_CHRDEV) return -EINVAL; write_lock(&chrdevs_lock); diff -urN linux-2.5.64-bk5/fs/devfs/base.c linux-2.5.64-bk6/fs/devfs/base.c --- linux-2.5.64-bk5/fs/devfs/base.c Tue Mar 4 19:29:01 2003 +++ linux-2.5.64-bk6/fs/devfs/base.c Mon Mar 31 12:28:50 2003 @@ -729,7 +729,6 @@ #define OPTION_NONE 0x00 #define OPTION_MOUNT 0x01 -#define OPTION_ONLY 0x02 #define PRINTK(format, args...) \ {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);} @@ -773,7 +772,6 @@ { struct block_device_operations *ops; dev_t dev; - unsigned char autogen:1; unsigned char removable:1; }; @@ -938,8 +936,6 @@ if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname); if ( S_ISCHR (de->mode) && de->u.cdev.autogen ) devfs_dealloc_devnum (de->mode, de->u.cdev.dev); - if ( S_ISBLK (de->mode) && de->u.bdev.autogen ) - devfs_dealloc_devnum (de->mode, de->u.bdev.dev); WRITE_ENTRY_MAGIC (de, 0); #ifdef CONFIG_DEVFS_DEBUG spin_lock (&stat_lock); @@ -1495,17 +1491,6 @@ PRINTK ("(%s): creating symlinks is not allowed\n", name); return NULL; } - if ( ( S_ISCHR (mode) || S_ISBLK (mode) ) && - (flags & DEVFS_FL_AUTO_DEVNUM) ) - { - devnum = devfs_alloc_devnum (mode); - if (!devnum) { - PRINTK ("(%s): exhausted %s device numbers\n", - name, S_ISCHR (mode) ? "char" : "block"); - return NULL; - } - dev = devnum; - } if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL ) { PRINTK ("(%s): could not prepare leaf\n", name); @@ -1870,18 +1855,6 @@ /** - * devfs_only - returns true if "devfs=only" is a boot option - * - * If "devfs=only" this function will return 1, otherwise 0 is returned. - */ - -int devfs_only (void) -{ - return (boot_options & OPTION_ONLY) ? 1 : 0; -} /* End Function devfs_only */ - - -/** * devfs_setup - Process kernel boot options. * @str: The boot options after the "devfs=". */ @@ -1909,7 +1882,6 @@ {"dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, {"diunlink", DEBUG_I_UNLINK, &devfs_debug_init}, #endif /* CONFIG_DEVFS_DEBUG */ - {"only", OPTION_ONLY, &boot_options}, {"mount", OPTION_MOUNT, &boot_options}, {NULL, 0, NULL} }; diff -urN linux-2.5.64-bk5/fs/ext2/dir.c linux-2.5.64-bk6/fs/ext2/dir.c --- linux-2.5.64-bk5/fs/ext2/dir.c Tue Mar 4 19:29:20 2003 +++ linux-2.5.64-bk6/fs/ext2/dir.c Mon Mar 31 12:28:50 2003 @@ -337,6 +337,9 @@ struct ext2_inode_info *ei = EXT2_I(dir); ext2_dirent * de; + if (npages == 0) + goto out; + /* OFFSET_CACHE */ *res_page = NULL; diff -urN linux-2.5.64-bk5/fs/ext3/super.c linux-2.5.64-bk6/fs/ext3/super.c --- linux-2.5.64-bk5/fs/ext3/super.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/fs/ext3/super.c Mon Mar 31 12:28:50 2003 @@ -141,8 +141,11 @@ printk (KERN_CRIT "Remounting filesystem read-only\n"); sb->s_flags |= MS_RDONLY; } else { + journal_t *journal = EXT3_SB(sb)->s_journal; + EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT; - journal_abort(EXT3_SB(sb)->s_journal, -EIO); + if (journal) + journal_abort(journal, -EIO); } ext3_commit_super(sb, es, 1); } @@ -1622,11 +1625,15 @@ struct ext3_super_block * es, int sync) { + struct buffer_head *sbh = EXT3_SB(sb)->s_sbh; + + if (!sbh) + return; es->s_wtime = cpu_to_le32(get_seconds()); - BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "marking dirty"); - mark_buffer_dirty(EXT3_SB(sb)->s_sbh); + BUFFER_TRACE(sbh, "marking dirty"); + mark_buffer_dirty(sbh); if (sync) - sync_dirty_buffer(EXT3_SB(sb)->s_sbh); + sync_dirty_buffer(sbh); } diff -urN linux-2.5.64-bk5/fs/locks.c linux-2.5.64-bk6/fs/locks.c --- linux-2.5.64-bk5/fs/locks.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/fs/locks.c Mon Mar 31 12:28:50 2003 @@ -107,22 +107,22 @@ * Use slab allocator instead of kmalloc/kfree. * Use generic list implementation from . * Sped up posix_locks_deadlock by only considering blocked locks. - * Matthew Wilcox , March, 2000. + * Matthew Wilcox , March, 2000. * * Leases and LOCK_MAND - * Matthew Wilcox , June, 2000. + * Matthew Wilcox , June, 2000. * Stephen Rothwell , June, 2000. */ -#include -#include -#include -#include #include -#include -#include +#include #include +#include +#include #include +#include +#include +#include #include #include @@ -519,19 +519,11 @@ */ static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl) { - switch (caller_fl->fl_type) { - case F_RDLCK: - return (sys_fl->fl_type == F_WRLCK); - - case F_WRLCK: - return (1); - - default: - printk(KERN_ERR "locks_conflict(): impossible lock type - %d\n", - caller_fl->fl_type); - break; - } - return (0); /* This should never happen */ + if (sys_fl->fl_type == F_WRLCK) + return 1; + if (caller_fl->fl_type == F_WRLCK) + return 1; + return 0; } /* Determine if lock sys_fl blocks lock caller_fl. POSIX specific @@ -1966,3 +1958,13 @@ } module_init(filelock_init) + +EXPORT_SYMBOL(file_lock_list); +EXPORT_SYMBOL(locks_init_lock); +EXPORT_SYMBOL(locks_copy_lock); +EXPORT_SYMBOL(posix_lock_file); +EXPORT_SYMBOL(posix_test_lock); +EXPORT_SYMBOL(posix_block_lock); +EXPORT_SYMBOL(posix_unblock_lock); +EXPORT_SYMBOL(posix_locks_deadlock); +EXPORT_SYMBOL(locks_mandatory_area); diff -urN linux-2.5.64-bk5/fs/namei.c linux-2.5.64-bk6/fs/namei.c --- linux-2.5.64-bk5/fs/namei.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/fs/namei.c Mon Mar 31 12:28:50 2003 @@ -398,10 +398,7 @@ goto loop; if (current->total_link_count >= 40) goto loop; - if (need_resched()) { - current->state = TASK_RUNNING; - schedule(); - } + cond_resched(); err = security_inode_follow_link(dentry, nd); if (err) goto loop; diff -urN linux-2.5.64-bk5/fs/ncpfs/ioctl.c linux-2.5.64-bk6/fs/ncpfs/ioctl.c --- linux-2.5.64-bk5/fs/ncpfs/ioctl.c Tue Mar 4 19:29:22 2003 +++ linux-2.5.64-bk6/fs/ncpfs/ioctl.c Mon Mar 31 12:28:50 2003 @@ -440,7 +440,7 @@ oldprivatelen = server->priv.len; server->auth.auth_type = user.auth_type; server->auth.object_name_len = user.object_name_len; - server->auth.object_name = user.object_name; + server->auth.object_name = newname; server->priv.len = 0; server->priv.data = NULL; /* leave critical section */ diff -urN linux-2.5.64-bk5/fs/partitions/ldm.c linux-2.5.64-bk6/fs/partitions/ldm.c --- linux-2.5.64-bk5/fs/partitions/ldm.c Tue Mar 4 19:29:16 2003 +++ linux-2.5.64-bk6/fs/partitions/ldm.c Mon Mar 31 12:28:50 2003 @@ -1162,8 +1162,10 @@ return FALSE; } - if (!ldm_parse_vblk (data, len, vb)) + if (!ldm_parse_vblk (data, len, vb)) { + kfree(vb); return FALSE; /* Already logged */ + } /* Put vblk into the correct list. */ switch (vb->type) { diff -urN linux-2.5.64-bk5/fs/smbfs/sock.c linux-2.5.64-bk6/fs/smbfs/sock.c --- linux-2.5.64-bk5/fs/smbfs/sock.c Tue Mar 4 19:29:16 2003 +++ linux-2.5.64-bk6/fs/smbfs/sock.c Mon Mar 31 12:28:50 2003 @@ -41,8 +41,6 @@ { struct iovec iov; struct msghdr msg; - struct kiocb iocb; - struct sock_iocb *si; mm_segment_t fs; fs = get_fs(); @@ -58,21 +56,7 @@ iov.iov_base = ubuf; iov.iov_len = size; - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = socket; - si->scm = &si->async_scm; - si->msg = &msg; - si->size = size; - si->flags = flags; - - memset(si->scm, 0, sizeof(*si->scm)); - - size = socket->ops->recvmsg(&iocb, socket, &msg, size, flags, si->scm); - if (size >= 0) - scm_recv(socket, &msg, si->scm, flags); - if (-EIOCBQUEUED == size) - size = wait_on_sync_kiocb(&iocb); + size = sock_recvmsg(socket, &msg, size, flags); set_fs(fs); return size; @@ -299,8 +283,6 @@ unsigned int flags; struct iovec iov; struct msghdr msg; - struct kiocb iocb; - struct sock_iocb *si; mm_segment_t fs; int rlen = smb_len(server->header) - server->smb_read + 4; int result = -EIO; @@ -327,21 +309,7 @@ if (rlen > PAGE_SIZE) rlen = PAGE_SIZE; - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &msg; - si->size = rlen; - si->flags = flags; - - memset(si->scm, 0, sizeof(*si->scm)); - - result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm); - if (result >= 0) - scm_recv(sock, &msg, si->scm, flags); - if (-EIOCBQUEUED == result) - result = wait_on_sync_kiocb(&iocb); + result = sock_recvmsg(sock, &msg, rlen, flags); set_fs(fs); @@ -370,8 +338,6 @@ unsigned int flags; struct iovec iov[4]; struct msghdr msg; - struct kiocb iocb; - struct sock_iocb *si; mm_segment_t fs; int rlen; int result = -EIO; @@ -398,21 +364,7 @@ if (req->rq_rlen < rlen) rlen = req->rq_rlen; - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &msg; - si->size = rlen; - si->flags = flags; - - memset(si->scm, 0, sizeof(*si->scm)); - - result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm); - if (result >= 0) - scm_recv(sock, &msg, si->scm, flags); - if (-EIOCBQUEUED == result) - result = wait_on_sync_kiocb(&iocb); + result = sock_recvmsg(sock, &msg, rlen, flags); set_fs(fs); @@ -440,8 +392,6 @@ mm_segment_t fs; struct smb_sb_info *server = req->rq_server; struct socket *sock; - struct kiocb iocb; - struct sock_iocb *si; struct msghdr msg; int slen = req->rq_slen - req->rq_bytes_sent; int result = -EIO; @@ -465,23 +415,9 @@ if (req->rq_bytes_sent) smb_move_iov(&msg, iov, req->rq_bytes_sent); - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->scm = &si->async_scm; - si->sock = sock; - si->msg = &msg; - si->size = slen; - fs = get_fs(); set_fs(get_ds()); - result = scm_send(sock, &msg, si->scm); - if (result >= 0) { - result = sock->ops->sendmsg(&iocb, sock, &msg, slen, si->scm); - if (-EIOCBQUEUED != result) - scm_destroy(si->scm); - } - if (-EIOCBQUEUED == result) - result = wait_on_sync_kiocb(&iocb); + result = sock_sendmsg(sock, &msg, slen); set_fs(fs); if (result >= 0) { diff -urN linux-2.5.64-bk5/include/asm-alpha/processor.h linux-2.5.64-bk6/include/asm-alpha/processor.h --- linux-2.5.64-bk5/include/asm-alpha/processor.h Tue Mar 4 19:29:54 2003 +++ linux-2.5.64-bk6/include/asm-alpha/processor.h Mon Mar 31 12:28:50 2003 @@ -51,6 +51,9 @@ /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* Create a kernel thread without removing it from tasklists. */ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); diff -urN linux-2.5.64-bk5/include/asm-arm/processor.h linux-2.5.64-bk6/include/asm-arm/processor.h --- linux-2.5.64-bk5/include/asm-arm/processor.h Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/include/asm-arm/processor.h Mon Mar 31 12:28:50 2003 @@ -62,6 +62,9 @@ /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + unsigned long get_wchan(struct task_struct *p); #define cpu_relax() barrier() diff -urN linux-2.5.64-bk5/include/asm-cris/processor.h linux-2.5.64-bk6/include/asm-cris/processor.h --- linux-2.5.64-bk5/include/asm-cris/processor.h Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/include/asm-cris/processor.h Mon Mar 31 12:28:50 2003 @@ -123,6 +123,9 @@ /* Nothing needs to be done. */ } +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * Return saved PC of a blocked thread. */ diff -urN linux-2.5.64-bk5/include/asm-i386/i387.h linux-2.5.64-bk6/include/asm-i386/i387.h --- linux-2.5.64-bk5/include/asm-i386/i387.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/asm-i386/i387.h Mon Mar 31 12:28:50 2003 @@ -36,7 +36,7 @@ asm volatile( "fnsave %0 ; fwait" : "=m" (tsk->thread.i387.fsave) ); } - tsk->thread_info->flags &= ~_TIF_USEDFPU; + tsk->thread_info->status &= ~TS_USEDFPU; } static inline void save_init_fpu( struct task_struct *tsk ) @@ -47,15 +47,15 @@ #define unlazy_fpu( tsk ) do { \ - if ((tsk)->thread_info->flags & _TIF_USEDFPU) \ + if ((tsk)->thread_info->status & TS_USEDFPU) \ save_init_fpu( tsk ); \ } while (0) #define clear_fpu( tsk ) \ do { \ - if ((tsk)->thread_info->flags & _TIF_USEDFPU) { \ + if ((tsk)->thread_info->status & TS_USEDFPU) { \ asm volatile("fwait"); \ - (tsk)->thread_info->flags &= ~_TIF_USEDFPU; \ + (tsk)->thread_info->status &= ~TS_USEDFPU; \ stts(); \ } \ } while (0) diff -urN linux-2.5.64-bk5/include/asm-i386/mach-bigsmp/mach_apic.h linux-2.5.64-bk6/include/asm-i386/mach-bigsmp/mach_apic.h --- linux-2.5.64-bk5/include/asm-i386/mach-bigsmp/mach_apic.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/asm-i386/mach-bigsmp/mach_apic.h Tue Mar 4 19:29:51 2003 @@ -19,7 +19,7 @@ } #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) -#define TARGET_CPUS ((cpu_callout_map < 0xf)?cpu_callout_map:0xf) +#define TARGET_CPUS ((cpu_online_map < 0xf)?cpu_online_map:0xf) #define INT_DELIVERY_MODE dest_LowestPrio #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ diff -urN linux-2.5.64-bk5/include/asm-i386/mach-default/mach_apic.h linux-2.5.64-bk6/include/asm-i386/mach-default/mach_apic.h --- linux-2.5.64-bk5/include/asm-i386/mach-default/mach_apic.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/asm-i386/mach-default/mach_apic.h Tue Mar 4 19:29:55 2003 @@ -4,7 +4,7 @@ #define APIC_DFR_VALUE (APIC_DFR_FLAT) #ifdef CONFIG_SMP - #define TARGET_CPUS (cpu_callout_map) + #define TARGET_CPUS (cpu_online_map) #else #define TARGET_CPUS 0x01 #endif diff -urN linux-2.5.64-bk5/include/asm-i386/mach-summit/mach_apic.h linux-2.5.64-bk6/include/asm-i386/mach-summit/mach_apic.h --- linux-2.5.64-bk5/include/asm-i386/mach-summit/mach_apic.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/asm-i386/mach-summit/mach_apic.h Tue Mar 4 19:29:26 2003 @@ -13,7 +13,7 @@ ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) ) #define APIC_DFR_VALUE (x86_summit ? APIC_DFR_CLUSTER : APIC_DFR_FLAT) -#define TARGET_CPUS (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_callout_map) +#define TARGET_CPUS (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map) #define INT_DELIVERY_MODE (x86_summit ? dest_Fixed : dest_LowestPrio) #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ diff -urN linux-2.5.64-bk5/include/asm-i386/processor.h linux-2.5.64-bk6/include/asm-i386/processor.h --- linux-2.5.64-bk5/include/asm-i386/processor.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/asm-i386/processor.h Mon Mar 31 12:28:50 2003 @@ -404,6 +404,8 @@ #define INIT_TSS { \ .esp0 = sizeof(init_stack) + (long)&init_stack, \ .ss0 = __KERNEL_DS, \ + .esp1 = sizeof(init_tss[0]) + (long)&init_tss[0], \ + .ss1 = __KERNEL_CS, \ .ldt = GDT_ENTRY_LDT, \ .bitmap = INVALID_IO_BITMAP_OFFSET, \ .io_bitmap = { [ 0 ... IO_BITMAP_SIZE ] = ~0 }, \ @@ -412,12 +414,10 @@ static inline void load_esp0(struct tss_struct *tss, unsigned long esp0) { tss->esp0 = esp0; - if (cpu_has_sep) { - if (tss->ss1 != __KERNEL_CS) { - tss->ss1 = __KERNEL_CS; - wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - } - wrmsr(MSR_IA32_SYSENTER_ESP, esp0, 0); + /* This can only happen when SEP is enabled, no need to test "SEP"arately */ + if (tss->ss1 != __KERNEL_CS) { + tss->ss1 = __KERNEL_CS; + wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); } } @@ -446,6 +446,10 @@ /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); + +/* Prepare to copy thread state - unlazy all lazy status */ +extern void prepare_to_copy(struct task_struct *tsk); + /* * create a kernel thread without removing it from tasklists */ diff -urN linux-2.5.64-bk5/include/asm-i386/thread_info.h linux-2.5.64-bk6/include/asm-i386/thread_info.h --- linux-2.5.64-bk5/include/asm-i386/thread_info.h Tue Mar 4 19:28:59 2003 +++ linux-2.5.64-bk6/include/asm-i386/thread_info.h Mon Mar 31 12:28:50 2003 @@ -25,6 +25,7 @@ struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ unsigned long flags; /* low level flags */ + unsigned long status; /* thread-synchronous flags */ __u32 cpu; /* current CPU */ __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ @@ -43,10 +44,11 @@ #define TI_TASK 0x00000000 #define TI_EXEC_DOMAIN 0x00000004 #define TI_FLAGS 0x00000008 -#define TI_CPU 0x0000000C -#define TI_PRE_COUNT 0x00000010 -#define TI_ADDR_LIMIT 0x00000014 -#define TI_RESTART_BLOCK 0x0000018 +#define TI_STATUS 0x0000000C +#define TI_CPU 0x00000010 +#define TI_PRE_COUNT 0x00000014 +#define TI_ADDR_LIMIT 0x00000018 +#define TI_RESTART_BLOCK 0x000001C #endif @@ -111,8 +113,7 @@ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ #define TIF_IRET 5 /* return with iret */ -#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ -#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define _TIF_SYSCALL_TRACE (1<> 7; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); __asm__ __volatile__ ( #undef BLOCK @@ -83,7 +66,7 @@ : : "memory"); - FPU_RESTORE; + kernel_fpu_end(); } static void @@ -91,9 +74,8 @@ unsigned long *p3) { unsigned long lines = bytes >> 7; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); __asm__ __volatile__ ( #undef BLOCK @@ -133,7 +115,7 @@ : : "memory"); - FPU_RESTORE; + kernel_fpu_end(); } static void @@ -141,9 +123,8 @@ unsigned long *p3, unsigned long *p4) { unsigned long lines = bytes >> 7; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); __asm__ __volatile__ ( #undef BLOCK @@ -188,7 +169,7 @@ : : "memory"); - FPU_RESTORE; + kernel_fpu_end(); } @@ -197,9 +178,8 @@ unsigned long *p3, unsigned long *p4, unsigned long *p5) { unsigned long lines = bytes >> 7; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); /* need to save/restore p4/p5 manually otherwise gcc's 10 argument limit gets exceeded (+ counts as two arguments) */ @@ -255,7 +235,7 @@ : "r" (p4), "r" (p5) : "memory"); - FPU_RESTORE; + kernel_fpu_end(); } #undef LD @@ -270,9 +250,8 @@ xor_p5_mmx_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) { unsigned long lines = bytes >> 6; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); __asm__ __volatile__ ( " .align 32 ;\n" @@ -311,7 +290,7 @@ : : "memory"); - FPU_RESTORE; + kernel_fpu_end(); } static void @@ -319,9 +298,8 @@ unsigned long *p3) { unsigned long lines = bytes >> 6; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); __asm__ __volatile__ ( " .align 32,0x90 ;\n" @@ -369,7 +347,7 @@ : : "memory" ); - FPU_RESTORE; + kernel_fpu_end(); } static void @@ -377,9 +355,8 @@ unsigned long *p3, unsigned long *p4) { unsigned long lines = bytes >> 6; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); __asm__ __volatile__ ( " .align 32,0x90 ;\n" @@ -436,7 +413,7 @@ : : "memory"); - FPU_RESTORE; + kernel_fpu_end(); } static void @@ -444,9 +421,8 @@ unsigned long *p3, unsigned long *p4, unsigned long *p5) { unsigned long lines = bytes >> 6; - char fpu_save[108]; - FPU_SAVE; + kernel_fpu_begin(); /* need to save p4/p5 manually to not exceed gcc's 10 argument limit */ __asm__ __volatile__ ( @@ -517,7 +493,7 @@ : "r" (p4), "r" (p5) : "memory"); - FPU_RESTORE; + kernel_fpu_end(); } static struct xor_block_template xor_block_pII_mmx = { @@ -536,9 +512,6 @@ .do_5 = xor_p5_mmx_5, }; -#undef FPU_SAVE -#undef FPU_RESTORE - /* * Cache avoiding checksumming functions utilizing KNI instructions * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) diff -urN linux-2.5.64-bk5/include/asm-ia64/processor.h linux-2.5.64-bk6/include/asm-ia64/processor.h --- linux-2.5.64-bk5/include/asm-ia64/processor.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/asm-ia64/processor.h Mon Mar 31 12:28:50 2003 @@ -344,6 +344,9 @@ # define release_thread(dead_task) #endif +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * This is the mechanism for creating a new kernel thread. * diff -urN linux-2.5.64-bk5/include/asm-m68k/processor.h linux-2.5.64-bk6/include/asm-m68k/processor.h --- linux-2.5.64-bk5/include/asm-m68k/processor.h Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/include/asm-m68k/processor.h Mon Mar 31 12:28:50 2003 @@ -112,6 +112,9 @@ { } +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* diff -urN linux-2.5.64-bk5/include/asm-m68knommu/processor.h linux-2.5.64-bk6/include/asm-m68knommu/processor.h --- linux-2.5.64-bk5/include/asm-m68knommu/processor.h Tue Mar 4 19:29:21 2003 +++ linux-2.5.64-bk6/include/asm-m68knommu/processor.h Mon Mar 31 12:28:50 2003 @@ -108,6 +108,9 @@ { } +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* diff -urN linux-2.5.64-bk5/include/asm-mips/processor.h linux-2.5.64-bk6/include/asm-mips/processor.h --- linux-2.5.64-bk5/include/asm-mips/processor.h Tue Mar 4 19:28:56 2003 +++ linux-2.5.64-bk6/include/asm-mips/processor.h Mon Mar 31 12:28:50 2003 @@ -208,6 +208,9 @@ /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* diff -urN linux-2.5.64-bk5/include/asm-mips64/processor.h linux-2.5.64-bk6/include/asm-mips64/processor.h --- linux-2.5.64-bk5/include/asm-mips64/processor.h Tue Mar 4 19:29:19 2003 +++ linux-2.5.64-bk6/include/asm-mips64/processor.h Mon Mar 31 12:28:50 2003 @@ -231,6 +231,9 @@ /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* diff -urN linux-2.5.64-bk5/include/asm-parisc/processor.h linux-2.5.64-bk6/include/asm-parisc/processor.h --- linux-2.5.64-bk5/include/asm-parisc/processor.h Tue Mar 4 19:29:56 2003 +++ linux-2.5.64-bk6/include/asm-parisc/processor.h Mon Mar 31 12:28:50 2003 @@ -290,6 +290,9 @@ extern void release_thread(struct task_struct *); extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); static inline unsigned long get_wchan(struct task_struct *p) diff -urN linux-2.5.64-bk5/include/asm-ppc/processor.h linux-2.5.64-bk6/include/asm-ppc/processor.h --- linux-2.5.64-bk5/include/asm-ppc/processor.h Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/include/asm-ppc/processor.h Mon Mar 31 12:28:50 2003 @@ -608,6 +608,9 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); void release_thread(struct task_struct *); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * Create a new kernel thread. */ diff -urN linux-2.5.64-bk5/include/asm-ppc64/processor.h linux-2.5.64-bk6/include/asm-ppc64/processor.h --- linux-2.5.64-bk5/include/asm-ppc64/processor.h Tue Mar 4 19:28:58 2003 +++ linux-2.5.64-bk6/include/asm-ppc64/processor.h Mon Mar 31 12:28:50 2003 @@ -601,6 +601,9 @@ void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); void release_thread(struct task_struct *); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * Create a new kernel thread. */ diff -urN linux-2.5.64-bk5/include/asm-s390/processor.h linux-2.5.64-bk6/include/asm-s390/processor.h --- linux-2.5.64-bk5/include/asm-s390/processor.h Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/include/asm-s390/processor.h Mon Mar 31 12:28:50 2003 @@ -114,6 +114,9 @@ extern void release_thread(struct task_struct *); extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * Return saved PC of a blocked thread. */ diff -urN linux-2.5.64-bk5/include/asm-s390x/processor.h linux-2.5.64-bk6/include/asm-s390x/processor.h --- linux-2.5.64-bk5/include/asm-s390x/processor.h Tue Mar 4 19:29:33 2003 +++ linux-2.5.64-bk6/include/asm-s390x/processor.h Mon Mar 31 12:28:50 2003 @@ -129,6 +129,9 @@ extern void release_thread(struct task_struct *); extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * Return saved PC of a blocked thread. */ diff -urN linux-2.5.64-bk5/include/asm-sh/processor.h linux-2.5.64-bk6/include/asm-sh/processor.h --- linux-2.5.64-bk5/include/asm-sh/processor.h Tue Mar 4 19:29:15 2003 +++ linux-2.5.64-bk6/include/asm-sh/processor.h Mon Mar 31 12:28:50 2003 @@ -134,6 +134,10 @@ /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); + +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * create a kernel thread without removing it from tasklists */ diff -urN linux-2.5.64-bk5/include/asm-sparc/processor.h linux-2.5.64-bk6/include/asm-sparc/processor.h --- linux-2.5.64-bk5/include/asm-sparc/processor.h Tue Mar 4 19:29:54 2003 +++ linux-2.5.64-bk6/include/asm-sparc/processor.h Mon Mar 31 12:28:50 2003 @@ -139,6 +139,9 @@ #define release_thread(tsk) do { } while(0) extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern unsigned long get_wchan(struct task_struct *); #define KSTK_EIP(tsk) ((tsk)->thread.kregs->pc) diff -urN linux-2.5.64-bk5/include/asm-sparc64/processor.h linux-2.5.64-bk6/include/asm-sparc64/processor.h --- linux-2.5.64-bk5/include/asm-sparc64/processor.h Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/include/asm-sparc64/processor.h Mon Mar 31 12:28:50 2003 @@ -186,6 +186,9 @@ /* Free all resources held by a thread. */ #define release_thread(tsk) do { } while (0) +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern unsigned long get_wchan(struct task_struct *task); diff -urN linux-2.5.64-bk5/include/asm-v850/processor.h linux-2.5.64-bk6/include/asm-v850/processor.h --- linux-2.5.64-bk5/include/asm-v850/processor.h Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/include/asm-v850/processor.h Mon Mar 31 12:28:50 2003 @@ -81,6 +81,9 @@ { } +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + extern int kernel_thread (int (*fn)(void *), void * arg, unsigned long flags); /* Free current thread data structures etc. */ diff -urN linux-2.5.64-bk5/include/asm-x86_64/desc.h linux-2.5.64-bk6/include/asm-x86_64/desc.h --- linux-2.5.64-bk5/include/asm-x86_64/desc.h Tue Mar 4 19:29:57 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/desc.h Mon Mar 31 12:28:50 2003 @@ -138,9 +138,11 @@ static inline void set_seg_base(unsigned cpu, int entry, void *base) { struct desc_struct *d = &cpu_gdt_table[cpu][entry]; - d->base0 = PTR_LOW(base); - d->base1 = PTR_MIDDLE(base); - d->base2 = PTR_HIGH(base); + u32 addr = (u32)(u64)base; + BUG_ON((u64)base >> 32); + d->base0 = addr & 0xffff; + d->base1 = (addr >> 16) & 0xff; + d->base2 = (addr >> 24) & 0xff; } #define LDT_entry_a(info) \ diff -urN linux-2.5.64-bk5/include/asm-x86_64/ia32.h linux-2.5.64-bk6/include/asm-x86_64/ia32.h --- linux-2.5.64-bk5/include/asm-x86_64/ia32.h Tue Mar 4 19:29:34 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/ia32.h Mon Mar 31 12:28:50 2003 @@ -153,14 +153,16 @@ char f_fpack[6]; }; -struct iovec32 { - unsigned int iov_base; - int iov_len; -}; - #define IA32_PAGE_OFFSET 0xffffe000 #define IA32_STACK_TOP IA32_PAGE_OFFSET +#ifdef __KERNEL__ +struct user_desc; +int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info); +int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info); +int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs); +#endif + #endif /* !CONFIG_IA32_SUPPORT */ #endif diff -urN linux-2.5.64-bk5/include/asm-x86_64/processor.h linux-2.5.64-bk6/include/asm-x86_64/processor.h --- linux-2.5.64-bk5/include/asm-x86_64/processor.h Tue Mar 4 19:29:53 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/processor.h Mon Mar 31 12:28:50 2003 @@ -267,6 +267,10 @@ /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); + +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + /* * create a kernel thread without removing it from tasklists */ diff -urN linux-2.5.64-bk5/include/asm-x86_64/proto.h linux-2.5.64-bk6/include/asm-x86_64/proto.h --- linux-2.5.64-bk5/include/asm-x86_64/proto.h Tue Mar 4 19:29:34 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/proto.h Mon Mar 31 12:28:50 2003 @@ -57,11 +57,11 @@ extern unsigned long end_pfn; extern unsigned long table_start, table_end; -struct thread_struct; -struct user_desc; +extern void syscall_init(void); -int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info); -int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info); +struct pt_regs; + +long do_arch_prctl(struct task_struct *task, int code, unsigned long addr); #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) #define round_down(x,y) ((x) & ~((y)-1)) diff -urN linux-2.5.64-bk5/include/asm-x86_64/ptrace.h linux-2.5.64-bk6/include/asm-x86_64/ptrace.h --- linux-2.5.64-bk5/include/asm-x86_64/ptrace.h Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/ptrace.h Mon Mar 31 12:28:50 2003 @@ -78,9 +78,11 @@ #define PTRACE_GETFPXREGS 18 #define PTRACE_SETFPXREGS 19 +/* only useful for access 32bit programs */ #define PTRACE_GET_THREAD_AREA 25 #define PTRACE_SET_THREAD_AREA 26 +#define PTRACE_ARCH_PRCTL 30 /* arch_prctl for child */ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) #define user_mode(regs) (!!((regs)->cs & 3)) diff -urN linux-2.5.64-bk5/include/asm-x86_64/segment.h linux-2.5.64-bk6/include/asm-x86_64/segment.h --- linux-2.5.64-bk5/include/asm-x86_64/segment.h Tue Mar 4 19:29:38 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/segment.h Mon Mar 31 12:28:50 2003 @@ -6,8 +6,6 @@ #define __KERNEL32_CS 0x38 -#define __USER_LONGBASE ((GDT_ENTRY_LONGBASE * 8) | 3) - /* * we cannot use the same code segment descriptor for user and kernel * -- not even in the long flat mode, because of different DPL /kkeil @@ -31,6 +29,13 @@ #define GDT_ENTRY_TLS_ENTRIES 3 +/* TLS indexes for 64bit - hardcoded in arch_prctl */ +#define FS_TLS 0 +#define GS_TLS 1 + +#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3) +#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3) + #define IDT_ENTRIES 256 #define GDT_ENTRIES 16 #define GDT_SIZE (GDT_ENTRIES * 8) diff -urN linux-2.5.64-bk5/include/asm-x86_64/socket32.h linux-2.5.64-bk6/include/asm-x86_64/socket32.h --- linux-2.5.64-bk5/include/asm-x86_64/socket32.h Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/socket32.h Wed Dec 31 16:00:00 1969 @@ -1,64 +0,0 @@ -#ifndef SOCKET32_H -#define SOCKET32_H 1 - -#include - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -#endif diff -urN linux-2.5.64-bk5/include/asm-x86_64/suspend.h linux-2.5.64-bk6/include/asm-x86_64/suspend.h --- linux-2.5.64-bk5/include/asm-x86_64/suspend.h Tue Mar 4 19:29:20 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/suspend.h Mon Mar 31 12:28:50 2003 @@ -14,7 +14,7 @@ /* image of the saved processor state */ struct saved_context { u16 ds, es, fs, gs, ss; - unsigned long gs_base, fs_base; + unsigned long gs_base, gs_kernel_base, fs_base; unsigned long cr0, cr2, cr3, cr4; u16 gdt_pad; u16 gdt_limit; diff -urN linux-2.5.64-bk5/include/asm-x86_64/uaccess.h linux-2.5.64-bk6/include/asm-x86_64/uaccess.h --- linux-2.5.64-bk5/include/asm-x86_64/uaccess.h Tue Mar 4 19:29:03 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/uaccess.h Mon Mar 31 12:28:50 2003 @@ -5,6 +5,7 @@ * User space memory access functions */ #include +#include #include #include #include @@ -47,7 +48,7 @@ #define access_ok(type,addr,size) (__range_not_ok(addr,size) == 0) -extern inline int verify_area(int type, const void * addr, unsigned long size) +extern __force_inline int verify_area(int type, const void * addr, unsigned long size) { return access_ok(type,addr,size) ? 0 : -EFAULT; } @@ -237,7 +238,7 @@ extern unsigned long copy_to_user(void *to, const void *from, unsigned len); extern unsigned long copy_from_user(void *to, const void *from, unsigned len); -static inline int __copy_from_user(void *dst, const void *src, unsigned size) +static __force_inline int __copy_from_user(void *dst, const void *src, unsigned size) { if (!__builtin_constant_p(size)) return copy_user_generic(dst,src,size); @@ -266,7 +267,7 @@ } } -static inline int __copy_to_user(void *dst, const void *src, unsigned size) +static __force_inline int __copy_to_user(void *dst, const void *src, unsigned size) { if (!__builtin_constant_p(size)) return copy_user_generic(dst,src,size); diff -urN linux-2.5.64-bk5/include/asm-x86_64/unistd.h linux-2.5.64-bk6/include/asm-x86_64/unistd.h --- linux-2.5.64-bk5/include/asm-x86_64/unistd.h Tue Mar 4 19:29:31 2003 +++ linux-2.5.64-bk6/include/asm-x86_64/unistd.h Mon Mar 31 12:28:50 2003 @@ -469,7 +469,7 @@ #define __NR_sched_getaffinity 204 __SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity) #define __NR_set_thread_area 205 -__SYSCALL(__NR_set_thread_area, sys_set_thread_area) +__SYSCALL(__NR_set_thread_area, sys_ni_syscall) /* use arch_prctl */ #define __NR_io_setup 206 __SYSCALL(__NR_io_setup, sys_io_setup) #define __NR_io_destroy 207 @@ -481,7 +481,7 @@ #define __NR_io_cancel 210 __SYSCALL(__NR_io_cancel, sys_io_cancel) #define __NR_get_thread_area 211 -__SYSCALL(__NR_get_thread_area, sys_get_thread_area) +__SYSCALL(__NR_get_thread_area, sys_ni_syscall) /* use arch_prctl */ #define __NR_lookup_dcookie 212 __SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie) #define __NR_epoll_create 213 diff -urN linux-2.5.64-bk5/include/linux/atmdev.h linux-2.5.64-bk6/include/linux/atmdev.h --- linux-2.5.64-bk5/include/linux/atmdev.h Tue Mar 4 19:29:33 2003 +++ linux-2.5.64-bk6/include/linux/atmdev.h Mon Mar 31 12:28:50 2003 @@ -277,7 +277,6 @@ struct atm_vcc { unsigned long flags; /* VCC flags (ATM_VF_*) */ - unsigned char family; /* address family; 0 if unused */ short vpi; /* VPI and VCI (types must be equal */ /* with sockaddr) */ int vci; @@ -286,7 +285,6 @@ struct atm_dev *dev; /* device back pointer */ struct atm_qos qos; /* QOS */ struct atm_sap sap; /* SAP */ - atomic_t tx_inuse,rx_inuse; /* buffer space in use */ void (*push)(struct atm_vcc *vcc,struct sk_buff *skb); void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */ struct sk_buff *(*alloc_tx)(struct atm_vcc *vcc,unsigned int size); @@ -297,7 +295,6 @@ int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); void *dev_data; /* per-device data */ void *proto_data; /* per-protocol data */ - struct sk_buff_head recvq; /* receive queue */ struct k_atm_aal_stats *stats; /* pointer to AAL stats group */ wait_queue_head_t sleep; /* if socket is busy */ struct sock *sk; /* socket backpointer */ @@ -346,7 +343,7 @@ struct proc_dir_entry *proc_entry; /* proc entry */ char *proc_name; /* proc entry name */ #endif - struct atm_dev *prev,*next; /* linkage */ + struct list_head dev_list; /* linkage */ }; @@ -425,19 +422,19 @@ static __inline__ void atm_force_charge(struct atm_vcc *vcc,int truesize) { - atomic_add(truesize+ATM_PDU_OVHD,&vcc->rx_inuse); + atomic_add(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc); } static __inline__ void atm_return(struct atm_vcc *vcc,int truesize) { - atomic_sub(truesize+ATM_PDU_OVHD,&vcc->rx_inuse); + atomic_sub(truesize+ATM_PDU_OVHD,&vcc->sk->rmem_alloc); } static __inline__ int atm_may_send(struct atm_vcc *vcc,unsigned int size) { - return size+atomic_read(&vcc->tx_inuse)+ATM_PDU_OVHD < vcc->sk->sndbuf; + return size+atomic_read(&vcc->sk->wmem_alloc)+ATM_PDU_OVHD < vcc->sk->sndbuf; } diff -urN linux-2.5.64-bk5/include/linux/compat.h linux-2.5.64-bk6/include/linux/compat.h --- linux-2.5.64-bk5/include/linux/compat.h Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/include/linux/compat.h Mon Mar 31 12:28:50 2003 @@ -45,5 +45,12 @@ extern int get_compat_timespec(struct timespec *, struct compat_timespec *); extern int put_compat_timespec(struct timespec *, struct compat_timespec *); +struct compat_iovec { + u32 iov_base; + compat_size_t iov_len; +}; +#else /* no CONFIG_COMPAT */ +#define compat_size_t size_t + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff -urN linux-2.5.64-bk5/include/linux/compiler.h linux-2.5.64-bk6/include/linux/compiler.h --- linux-2.5.64-bk5/include/linux/compiler.h Tue Mar 4 19:29:26 2003 +++ linux-2.5.64-bk6/include/linux/compiler.h Mon Mar 31 12:28:50 2003 @@ -1,6 +1,12 @@ #ifndef __LINUX_COMPILER_H #define __LINUX_COMPILER_H +#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +#define inline __inline__ __attribute__((always_inline)) +#define __inline__ __inline__ __attribute__((always_inline)) +#define __inline __inline__ __attribute__((always_inline)) +#endif + /* Somewhere in the middle of the GCC 2.96 development cycle, we implemented a mechanism by which the user can annotate likely branch directions and expect the blocks to be reordered appropriately. Define __builtin_expect diff -urN linux-2.5.64-bk5/include/linux/crypto.h linux-2.5.64-bk6/include/linux/crypto.h --- linux-2.5.64-bk5/include/linux/crypto.h Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/include/linux/crypto.h Mon Mar 31 12:28:50 2003 @@ -134,10 +134,18 @@ struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes); + int (*cit_encrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); int (*cit_decrypt)(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes); + int (*cit_decrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); void (*cit_xor_block)(u8 *dst, const u8 *src); }; @@ -164,7 +172,6 @@ struct crypto_tfm { - void *crt_ctx; u32 crt_flags; union { @@ -286,6 +293,16 @@ return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); } +static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); +} + static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, @@ -295,6 +312,16 @@ return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); } +static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); +} + static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, const u8 *src, unsigned int len) { diff -urN linux-2.5.64-bk5/include/linux/devfs_fs_kernel.h linux-2.5.64-bk6/include/linux/devfs_fs_kernel.h --- linux-2.5.64-bk5/include/linux/devfs_fs_kernel.h Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/include/linux/devfs_fs_kernel.h Mon Mar 31 12:28:50 2003 @@ -13,8 +13,6 @@ #define DEVFS_FL_NONE 0x000 /* This helps to make code more readable */ -#define DEVFS_FL_AUTO_DEVNUM 0x002 /* Automatically generate device number - */ #define DEVFS_FL_REMOVABLE 0x008 /* This is a removable media device */ #define DEVFS_FL_WAIT 0x010 /* Wait for devfsd to finish */ #define DEVFS_FL_CURRENT_OWNER 0x020 /* Set initial ownership to current */ @@ -52,7 +50,6 @@ void *info); extern int devfs_generate_path (devfs_handle_t de, char *path, int buflen); extern int devfs_set_file_size (devfs_handle_t de, unsigned long size); -extern int devfs_only (void); extern int devfs_register_tape (devfs_handle_t de); extern void devfs_unregister_tape(int num); extern int devfs_alloc_unique_number (struct unique_numspace *space); @@ -111,10 +108,6 @@ { return -ENOSYS; } -static inline int devfs_only (void) -{ - return 0; -} static inline int devfs_register_tape (devfs_handle_t de) { return -1; diff -urN linux-2.5.64-bk5/include/linux/net.h linux-2.5.64-bk6/include/linux/net.h --- linux-2.5.64-bk5/include/linux/net.h Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/include/linux/net.h Mon Mar 31 12:28:50 2003 @@ -78,7 +78,6 @@ unsigned char passcred; }; -struct scm_cookie; struct vm_area_struct; struct page; struct kiocb; @@ -106,11 +105,9 @@ int (*getsockopt) (struct socket *sock, int level, int optname, char *optval, int *optlen); int (*sendmsg) (struct kiocb *iocb, struct socket *sock, - struct msghdr *m, int total_len, - struct scm_cookie *scm); + struct msghdr *m, int total_len); int (*recvmsg) (struct kiocb *iocb, struct socket *sock, - struct msghdr *m, int total_len, int flags, - struct scm_cookie *scm); + struct msghdr *m, int total_len, int flags); int (*mmap) (struct file *file, struct socket *sock, struct vm_area_struct * vma); ssize_t (*sendpage) (struct socket *sock, struct page *page, int offset, size_t size, int flags); }; @@ -202,10 +199,10 @@ char *optval, int optlen), (sock, level, optname, optval, optlen)) \ SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \ char *optval, int *optlen), (sock, level, optname, optval, optlen)) \ -SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, struct scm_cookie *scm), \ - (iocb, sock, m, len, scm)) \ -SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags, struct scm_cookie *scm), \ - (iocb, sock, m, len, flags, scm)) \ +SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len), \ + (iocb, sock, m, len)) \ +SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags), \ + (iocb, sock, m, len, flags)) \ SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \ (file, sock, vma)) \ \ diff -urN linux-2.5.64-bk5/include/linux/pnp.h linux-2.5.64-bk6/include/linux/pnp.h --- linux-2.5.64-bk5/include/linux/pnp.h Tue Mar 4 19:29:54 2003 +++ linux-2.5.64-bk6/include/linux/pnp.h Mon Mar 31 12:28:50 2003 @@ -138,11 +138,8 @@ struct list_head global_list; /* node in global list of cards */ struct list_head protocol_list; /* node in protocol's list of cards */ struct list_head devices; /* devices attached to the card */ - struct list_head rdevs; /* a list of devices requested by the card driver */ - int status; struct pnp_protocol * protocol; - struct pnpc_driver * driver; struct pnp_id * id; /* contains supported EISA IDs*/ void * protocol_data; /* Used to store protocol specific data */ @@ -161,24 +158,30 @@ (card) != global_to_pnp_card(&pnp_cards); \ (card) = global_to_pnp_card((card)->global_list.next)) -static inline void *pnpc_get_drvdata (struct pnp_card *pcard) +static inline void *pnp_get_card_protodata (struct pnp_card *pcard) { - return dev_get_drvdata(&pcard->dev); + return pcard->protocol_data; } -static inline void pnpc_set_drvdata (struct pnp_card *pcard, void *data) +static inline void pnp_set_card_protodata (struct pnp_card *pcard, void *data) { - dev_set_drvdata(&pcard->dev, data); + pcard->protocol_data = data; } -static inline void *pnpc_get_protodata (struct pnp_card *pcard) +struct pnp_card_link { + struct pnp_card * card; + struct pnp_card_driver * driver; + void * driver_data; +}; + +static inline void *pnp_get_card_drvdata (struct pnp_card_link *pcard) { - return pcard->protocol_data; + return pcard->driver_data; } -static inline void pnpc_set_protodata (struct pnp_card *pcard, void *data) +static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data) { - pcard->protocol_data = data; + pcard->driver_data = data; } struct pnp_dev { @@ -196,6 +199,7 @@ struct pnp_protocol * protocol; struct pnp_card * card; /* card the device is attached to, none if NULL */ struct pnp_driver * driver; + struct pnp_card_link * card_link; struct pnp_id * id; /* supported EISA IDs*/ struct pnp_resource_table res; /* contains the currently chosen resources */ @@ -299,11 +303,8 @@ } devs[PNP_MAX_DEVICES]; /* logical devices */ }; -#define PNP_DRIVER_DO_NOT_ACTIVATE (1<<0) - struct pnp_driver { - struct list_head node; - char *name; + char * name; const struct pnp_device_id *id_table; unsigned int flags; int (*probe) (struct pnp_dev *dev, const struct pnp_device_id *dev_id); @@ -311,21 +312,22 @@ struct device_driver driver; }; -#define to_pnp_driver(drv) container_of(drv,struct pnp_driver, driver) - -#define PNPC_DRIVER_DO_NOT_ACTIVATE (1<<0) +#define to_pnp_driver(drv) container_of(drv, struct pnp_driver, driver) -struct pnpc_driver { - struct list_head node; - char *name; +struct pnp_card_driver { + char * name; const struct pnp_card_id *id_table; unsigned int flags; - int (*probe) (struct pnp_card *card, const struct pnp_card_id *card_id); - void (*remove) (struct pnp_card *card); - struct device_driver driver; + int (*probe) (struct pnp_card_link *card, const struct pnp_card_id *card_id); + void (*remove) (struct pnp_card_link *card); + struct pnp_driver link; }; -#define to_pnpc_driver(drv) container_of(drv,struct pnpc_driver, driver) +#define to_pnp_card_driver(drv) container_of(drv, struct pnp_card_driver, link) + +/* pnp driver flags */ +#define PNP_DRIVER_RES_DO_NOT_CHANGE 0x0001 /* do not change the state of the device */ +#define PNP_DRIVER_RES_DISABLE 0x0003 /* ensure the device is disabled */ /* @@ -366,9 +368,21 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol); int pnp_add_device(struct pnp_dev *dev); void pnp_remove_device(struct pnp_dev *dev); -extern struct list_head pnp_global; int pnp_device_attach(struct pnp_dev *pnp_dev); void pnp_device_detach(struct pnp_dev *pnp_dev); +extern struct list_head pnp_global; + +/* card */ +int pnp_add_card(struct pnp_card *card); +void pnp_remove_card(struct pnp_card *card); +int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); +void pnp_remove_card_device(struct pnp_dev *dev); +int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card); +struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from); +void pnp_release_card_device(struct pnp_dev * dev); +int pnp_register_card_driver(struct pnp_card_driver * drv); +void pnp_unregister_card_driver(struct pnp_card_driver * drv); +extern struct list_head pnp_cards; /* resource */ struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent); @@ -413,6 +427,17 @@ static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; } +/* card */ +static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; } +static inline void pnp_remove_card(struct pnp_card *card) { ; } +static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; } +static inline void pnp_remove_card_device(struct pnp_dev *dev) { ; } +static inline int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; } +static inline struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) { return NULL; } +static inline void pnp_release_card_device(struct pnp_dev * dev) { ; } +static inline int pnp_register_card_driver(struct pnp_card_driver * drv) { return -ENODEV; } +static inline void pnp_unregister_card_driver(struct pnp_card_driver * drv) { ; } + /* resource */ static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; } static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; } @@ -446,37 +471,6 @@ #endif /* CONFIG_PNP */ -#if defined(CONFIG_PNP_CARD) - -/* card */ -int pnpc_add_card(struct pnp_card *card); -void pnpc_remove_card(struct pnp_card *card); -int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev); -void pnpc_remove_device(struct pnp_dev *dev); -struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from); -void pnp_release_card_device(struct pnp_dev *dev); -int pnpc_register_driver(struct pnpc_driver * drv); -void pnpc_unregister_driver(struct pnpc_driver *drv); -int pnpc_add_id(struct pnp_id *id, struct pnp_card *card); -extern struct list_head pnp_cards; -int pnpc_attach(struct pnp_card *card); -void pnpc_detach(struct pnp_card *card); - -#else - -/* card */ -static inline int pnpc_add_card(struct pnp_card *card) { return -ENODEV; } -static inline void pnpc_remove_card(struct pnp_card *card) { ; } -static inline int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; } -static inline void pnpc_remove_device(struct pnp_dev *dev) { ; } -static inline struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) { return NULL; } -static inline void pnp_release_card_device(struct pnp_dev *dev) { ; } -static inline int pnpc_register_driver(struct pnpc_driver *drv) { return -ENODEV; } -static inline void pnpc_unregister_driver(struct pnpc_driver *drv) { ; } -static inline int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; } - -#endif /* CONFIG_PNP_CARD */ - #define pnp_err(format, arg...) printk(KERN_ERR "pnp: " format "\n" , ## arg) #define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg) #define pnp_warn(format, arg...) printk(KERN_WARNING "pnp: " format "\n" , ## arg) diff -urN linux-2.5.64-bk5/include/linux/socket.h linux-2.5.64-bk6/include/linux/socket.h --- linux-2.5.64-bk5/include/linux/socket.h Tue Mar 4 19:29:33 2003 +++ linux-2.5.64-bk6/include/linux/socket.h Mon Mar 31 12:28:50 2003 @@ -3,6 +3,7 @@ #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) +#include #include /* arch-dependent defines */ #include /* the SIOCxxx I/O controls */ #include /* iovec support */ @@ -234,6 +235,24 @@ #define MSG_EOF MSG_FIN +#if defined(CONFIG_COMPAT) +#define MSG_CMSG_COMPAT 0x80000000 /* This message needs 32 bit fixups */ +#else +#define MSG_CMSG_COMPAT 0 /* We never have 32 bit fixups */ +#define compat_msghdr msghdr /* Needed to avoid compiler hoops */ +#endif + +struct compat_msghdr; +extern int msghdr_from_user_compat_to_kern(struct msghdr *, struct compat_msghdr *); +extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int); +extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr *,unsigned); +extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr *,unsigned); +extern asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags); +extern asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned flags); +extern asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, + char *optval, int *optlen); + + /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */ #define SOL_IP 0 @@ -276,6 +295,11 @@ extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen); extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr); extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); +extern int put_cmsg_compat(struct msghdr*, int level, int type, int len, void *data); +extern void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr); +extern int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, + unsigned char *stackbuf, int stackbuf_size); + #endif #endif /* not kernel and not glibc */ #endif /* _LINUX_SOCKET_H */ diff -urN linux-2.5.64-bk5/include/net/bluetooth/bluetooth.h linux-2.5.64-bk6/include/net/bluetooth/bluetooth.h --- linux-2.5.64-bk5/include/net/bluetooth/bluetooth.h Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/include/net/bluetooth/bluetooth.h Mon Mar 31 12:28:50 2003 @@ -128,7 +128,7 @@ struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio); void bt_sock_link(struct bt_sock_list *l, struct sock *s); void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); -int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm); +int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags); uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait); int bt_sock_w4_connect(struct sock *sk, int flags); diff -urN linux-2.5.64-bk5/include/net/compat_socket.h linux-2.5.64-bk6/include/net/compat_socket.h --- linux-2.5.64-bk5/include/net/compat_socket.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.64-bk6/include/net/compat_socket.h Mon Mar 31 12:28:50 2003 @@ -0,0 +1,67 @@ +#ifndef NET_COMPAT_SOCKET_H +#define NET_COMPAT_SOCKET_H 1 + +#include + +#if defined(CONFIG_COMPAT) + +/* XXX This really belongs in some header file... -DaveM */ +#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - + 16 for IP, 16 for IPX, + 24 for IPv6, + about 80 for AX.25 */ + +struct compat_msghdr { + u32 msg_name; + int msg_namelen; + u32 msg_iov; + compat_size_t msg_iovlen; + u32 msg_control; + compat_size_t msg_controllen; + unsigned msg_flags; +}; + +struct compat_cmsghdr { + compat_size_t cmsg_len; + int cmsg_level; + int cmsg_type; +}; + +/* Bleech... */ +#define __CMSG_COMPAT_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg_compat_nxthdr((ctl),(len),(cmsg),(cmsglen)) +#define CMSG_COMPAT_NXTHDR(mhdr, cmsg, cmsglen) cmsg_compat_nxthdr((mhdr), (cmsg), (cmsglen)) + +#define CMSG_COMPAT_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) + +#define CMSG_COMPAT_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)))) +#define CMSG_COMPAT_SPACE(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + CMSG_COMPAT_ALIGN(len)) +#define CMSG_COMPAT_LEN(len) (CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr)) + (len)) + +#define __CMSG_COMPAT_FIRSTHDR(ctl,len) ((len) >= sizeof(struct compat_cmsghdr) ? \ + (struct compat_cmsghdr *)(ctl) : \ + (struct compat_cmsghdr *)NULL) +#define CMSG_COMPAT_FIRSTHDR(msg) __CMSG_COMPAT_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) + +static __inline__ struct compat_cmsghdr *__cmsg_compat_nxthdr(void *__ctl, __kernel_size_t __size, + struct compat_cmsghdr *__cmsg, int __cmsg_len) +{ + struct compat_cmsghdr * __ptr; + + __ptr = (struct compat_cmsghdr *)(((unsigned char *) __cmsg) + + CMSG_COMPAT_ALIGN(__cmsg_len)); + if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) + return NULL; + + return __ptr; +} + +static __inline__ struct compat_cmsghdr *cmsg_compat_nxthdr (struct msghdr *__msg, + struct compat_cmsghdr *__cmsg, + int __cmsg_len) +{ + return __cmsg_compat_nxthdr(__msg->msg_control, __msg->msg_controllen, + __cmsg, __cmsg_len); +} + +#endif /* CONFIG_COMPAT */ +#endif diff -urN linux-2.5.64-bk5/include/net/inet_common.h linux-2.5.64-bk6/include/net/inet_common.h --- linux-2.5.64-bk5/include/net/inet_common.h Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/include/net/inet_common.h Mon Mar 31 12:28:50 2003 @@ -23,11 +23,11 @@ extern int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *ubuf, - int size, int flags, struct scm_cookie *scm); + int size, int flags); extern int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - int size, struct scm_cookie *scm); + int size); extern int inet_shutdown(struct socket *sock, int how); extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait); extern int inet_setsockopt(struct socket *sock, int level, diff -urN linux-2.5.64-bk5/include/net/scm.h linux-2.5.64-bk6/include/net/scm.h --- linux-2.5.64-bk5/include/net/scm.h Tue Mar 4 19:29:18 2003 +++ linux-2.5.64-bk6/include/net/scm.h Mon Mar 31 12:28:50 2003 @@ -22,6 +22,7 @@ }; extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); +extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); extern void __scm_destroy(struct scm_cookie *scm); extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); diff -urN linux-2.5.64-bk5/include/net/snmp.h linux-2.5.64-bk6/include/net/snmp.h --- linux-2.5.64-bk5/include/net/snmp.h Tue Mar 4 19:29:16 2003 +++ linux-2.5.64-bk6/include/net/snmp.h Mon Mar 31 12:28:50 2003 @@ -299,8 +299,8 @@ #define DECLARE_SNMP_STAT(type, name) \ extern __typeof__(type) *name[2] -#define SNMP_STAT_USRPTR(name) (name[0]) -#define SNMP_STAT_BHPTR(name) (name[1]) +#define SNMP_STAT_BHPTR(name) (name[0]) +#define SNMP_STAT_USRPTR(name) (name[1]) #define SNMP_INC_STATS_BH(mib, field) \ (per_cpu_ptr(mib[0], smp_processor_id())->field++) diff -urN linux-2.5.64-bk5/include/net/sock.h linux-2.5.64-bk6/include/net/sock.h --- linux-2.5.64-bk5/include/net/sock.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/net/sock.h Mon Mar 31 12:28:50 2003 @@ -54,7 +54,6 @@ #include #include -#include /* * This structure really needs to be cleaned up. @@ -71,7 +70,6 @@ SOCK_LINGER, SOCK_DESTROY, SOCK_BROADCAST, - SOCK_BSDISM, }; /* Define this to get the sk->debug debugging facility. */ @@ -310,9 +308,9 @@ int size; struct socket *sock; struct sock *sk; + struct scm_cookie *scm; struct msghdr *msg, async_msg; struct iovec async_iov; - struct scm_cookie *scm, async_scm; }; static inline struct sock_iocb *kiocb_to_siocb(struct kiocb *iocb) @@ -438,11 +436,9 @@ extern int sock_no_setsockopt(struct socket *, int, int, char *, int); extern int sock_no_sendmsg(struct kiocb *, struct socket *, - struct msghdr *, int, - struct scm_cookie *); + struct msghdr *, int); extern int sock_no_recvmsg(struct kiocb *, struct socket *, - struct msghdr *, int, int, - struct scm_cookie *); + struct msghdr *, int, int); extern int sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma); diff -urN linux-2.5.64-bk5/include/net/tcp.h linux-2.5.64-bk6/include/net/tcp.h --- linux-2.5.64-bk5/include/net/tcp.h Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/include/net/tcp.h Mon Mar 31 12:28:50 2003 @@ -144,6 +144,7 @@ extern kmem_cache_t *tcp_bucket_cachep; extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head, unsigned short snum); +extern void tcp_bucket_destroy(struct tcp_bind_bucket *tb); extern void tcp_bucket_unlock(struct sock *sk); extern int tcp_port_rover; extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif); diff -urN linux-2.5.64-bk5/init/Kconfig linux-2.5.64-bk6/init/Kconfig --- linux-2.5.64-bk5/init/Kconfig Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/init/Kconfig Mon Mar 31 12:28:50 2003 @@ -45,7 +45,7 @@ This option allows you to choose whether you want to have support for socalled swap devices or swap files in your kernel that are used to provide more virtual memory than the actual RAM present - in your computer. If unusre say Y. + in your computer. If unsure say Y. config SYSVIPC bool "System V IPC" diff -urN linux-2.5.64-bk5/kernel/fork.c linux-2.5.64-bk6/kernel/fork.c --- linux-2.5.64-bk5/kernel/fork.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/kernel/fork.c Mon Mar 31 12:28:50 2003 @@ -188,7 +188,7 @@ task_struct_cachep = kmem_cache_create("task_struct", sizeof(struct task_struct),0, - SLAB_HWCACHE_ALIGN, NULL, NULL); + SLAB_MUST_HWCACHE_ALIGN, NULL, NULL); if (!task_struct_cachep) panic("fork_init(): cannot create task_struct SLAB cache"); @@ -214,6 +214,8 @@ struct thread_info *ti; int cpu = get_cpu(); + prepare_to_copy(orig); + tsk = task_cache[cpu]; task_cache[cpu] = NULL; put_cpu(); diff -urN linux-2.5.64-bk5/kernel/ksyms.c linux-2.5.64-bk6/kernel/ksyms.c --- linux-2.5.64-bk5/kernel/ksyms.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/kernel/ksyms.c Mon Mar 31 12:28:50 2003 @@ -235,15 +235,6 @@ EXPORT_SYMBOL(generic_file_mmap); EXPORT_SYMBOL(generic_file_readonly_mmap); EXPORT_SYMBOL(generic_ro_fops); -EXPORT_SYMBOL(file_lock_list); -EXPORT_SYMBOL(locks_init_lock); -EXPORT_SYMBOL(locks_copy_lock); -EXPORT_SYMBOL(posix_lock_file); -EXPORT_SYMBOL(posix_test_lock); -EXPORT_SYMBOL(posix_block_lock); -EXPORT_SYMBOL(posix_unblock_lock); -EXPORT_SYMBOL(posix_locks_deadlock); -EXPORT_SYMBOL(locks_mandatory_area); EXPORT_SYMBOL(dput); EXPORT_SYMBOL(have_submounts); EXPORT_SYMBOL(d_find_alias); diff -urN linux-2.5.64-bk5/mm/pdflush.c linux-2.5.64-bk6/mm/pdflush.c --- linux-2.5.64-bk5/mm/pdflush.c Tue Mar 4 19:29:57 2003 +++ linux-2.5.64-bk6/mm/pdflush.c Mon Mar 31 12:28:50 2003 @@ -106,6 +106,7 @@ schedule(); if (current->flags & PF_FREEZE) { refrigerator(PF_IOTHREAD); + spin_lock_irq(&pdflush_lock); continue; } diff -urN linux-2.5.64-bk5/net/8021q/vlanproc.c linux-2.5.64-bk6/net/8021q/vlanproc.c --- linux-2.5.64-bk5/net/8021q/vlanproc.c Tue Mar 4 19:29:15 2003 +++ linux-2.5.64-bk6/net/8021q/vlanproc.c Mon Mar 31 12:28:50 2003 @@ -251,8 +251,10 @@ offs = file->f_pos; if (offs < pos) { len = min_t(int, pos - offs, count); - if (copy_to_user(buf, (page + offs), len)) + if (copy_to_user(buf, (page + offs), len)) { + kfree(page); return -EFAULT; + } file->f_pos += len; } else { diff -urN linux-2.5.64-bk5/net/Makefile linux-2.5.64-bk6/net/Makefile --- linux-2.5.64-bk5/net/Makefile Tue Mar 4 19:29:17 2003 +++ linux-2.5.64-bk6/net/Makefile Mon Mar 31 12:28:50 2003 @@ -7,6 +7,8 @@ obj-y := socket.o core/ +obj-$(CONFIG_COMPAT) += compat.o + # LLC has to be linked before the files in net/802/ obj-$(CONFIG_LLC) += llc/ obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ diff -urN linux-2.5.64-bk5/net/appletalk/ddp.c linux-2.5.64-bk6/net/appletalk/ddp.c --- linux-2.5.64-bk5/net/appletalk/ddp.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/appletalk/ddp.c Mon Mar 31 12:28:50 2003 @@ -1493,7 +1493,7 @@ } static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - int len, struct scm_cookie *scm) + int len) { struct sock *sk = sock->sk; struct atalk_sock *at = at_sk(sk); @@ -1653,7 +1653,7 @@ } static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - int size, int flags, struct scm_cookie *scm) + int size, int flags) { struct sock *sk = sock->sk; struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; diff -urN linux-2.5.64-bk5/net/atm/atm_misc.c linux-2.5.64-bk6/net/atm/atm_misc.c --- linux-2.5.64-bk5/net/atm/atm_misc.c Tue Mar 4 19:29:03 2003 +++ linux-2.5.64-bk6/net/atm/atm_misc.c Mon Mar 31 12:28:50 2003 @@ -16,7 +16,7 @@ int atm_charge(struct atm_vcc *vcc,int truesize) { atm_force_charge(vcc,truesize); - if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) return 1; + if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) return 1; atm_return(vcc,truesize); atomic_inc(&vcc->stats->rx_drop); return 0; @@ -29,11 +29,11 @@ int guess = atm_guess_pdu2truesize(pdu_size); atm_force_charge(vcc,guess); - if (atomic_read(&vcc->rx_inuse) <= vcc->sk->rcvbuf) { + if (atomic_read(&vcc->sk->rmem_alloc) <= vcc->sk->rcvbuf) { struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags); if (skb) { - atomic_add(skb->truesize-guess,&vcc->rx_inuse); + atomic_add(skb->truesize-guess,&vcc->sk->rmem_alloc); return skb; } } diff -urN linux-2.5.64-bk5/net/atm/clip.c linux-2.5.64-bk6/net/atm/clip.c --- linux-2.5.64-bk5/net/atm/clip.c Tue Mar 4 19:29:53 2003 +++ linux-2.5.64-bk6/net/atm/clip.c Mon Mar 31 12:28:50 2003 @@ -63,7 +63,7 @@ ctrl->itf_num = itf; ctrl->ip = ip; atm_force_charge(atmarpd,skb->truesize); - skb_queue_tail(&atmarpd->recvq,skb); + skb_queue_tail(&atmarpd->sk->receive_queue,skb); wake_up(&atmarpd->sleep); return 0; } @@ -426,7 +426,7 @@ memcpy(here,llc_oui,sizeof(llc_oui)); ((u16 *) here)[3] = skb->protocol; } - atomic_add(skb->truesize,&vcc->tx_inuse); + atomic_add(skb->truesize,&vcc->sk->wmem_alloc); ATM_SKB(skb)->iovcnt = 0; ATM_SKB(skb)->atm_options = vcc->atm_options; entry->vccs->last_use = jiffies; @@ -485,7 +485,7 @@ vcc->push = clip_push; vcc->pop = clip_pop; skb_queue_head_init(©); - skb_migrate(&vcc->recvq,©); + skb_migrate(&vcc->sk->receive_queue,©); /* re-process everything received between connection setup and MKIP */ while ((skb = skb_dequeue(©))) if (!clip_devs) { @@ -691,10 +691,10 @@ barrier(); unregister_inetaddr_notifier(&clip_inet_notifier); unregister_netdevice_notifier(&clip_dev_notifier); - if (skb_peek(&vcc->recvq)) + if (skb_peek(&vcc->sk->receive_queue)) printk(KERN_ERR "atmarpd_close: closing with requests " "pending\n"); - skb_queue_purge(&vcc->recvq); + skb_queue_purge(&vcc->sk->receive_queue); DPRINTK("(done)\n"); } diff -urN linux-2.5.64-bk5/net/atm/common.c linux-2.5.64-bk6/net/atm/common.c --- linux-2.5.64-bk5/net/atm/common.c Tue Mar 4 19:29:57 2003 +++ linux-2.5.64-bk6/net/atm/common.c Mon Mar 31 12:28:50 2003 @@ -85,14 +85,14 @@ { struct sk_buff *skb; - if (atomic_read(&vcc->tx_inuse) && !atm_may_send(vcc,size)) { - DPRINTK("Sorry: tx_inuse = %d, size = %d, sndbuf = %d\n", - atomic_read(&vcc->tx_inuse),size,vcc->sk->sndbuf); + if (atomic_read(&vcc->sk->wmem_alloc) && !atm_may_send(vcc,size)) { + DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n", + atomic_read(&vcc->sk->wmem_alloc),size,vcc->sk->sndbuf); return NULL; } while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule(); - DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->tx_inuse),skb->truesize); - atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); + DPRINTK("AlTx %d += %d\n",atomic_read(&vcc->sk->wmem_alloc),skb->truesize); + atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc); return skb; } @@ -108,21 +108,19 @@ vcc = atm_sk(sk); memset(&vcc->flags,0,sizeof(vcc->flags)); vcc->dev = NULL; - vcc->family = sock->ops->family; vcc->alloc_tx = alloc_tx; vcc->callback = NULL; memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc)); memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc)); vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */ - atomic_set(&vcc->tx_inuse,0); - atomic_set(&vcc->rx_inuse,0); + atomic_set(&vcc->sk->wmem_alloc,0); + atomic_set(&vcc->sk->rmem_alloc,0); vcc->push = NULL; vcc->pop = NULL; vcc->push_oam = NULL; vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */ vcc->atm_options = vcc->aal_options = 0; init_waitqueue_head(&vcc->sleep); - skb_queue_head_init(&vcc->recvq); skb_queue_head_init(&vcc->listenq); sk->sleep = &vcc->sleep; sock->sk = sk; @@ -139,7 +137,7 @@ if (vcc->dev) { if (vcc->dev->ops->close) vcc->dev->ops->close(vcc); if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */ - while ((skb = skb_dequeue(&vcc->recvq))) { + while ((skb = skb_dequeue(&vcc->sk->receive_queue))) { atm_return(vcc,skb->truesize); if (vcc->dev->ops->free_rx_skb) vcc->dev->ops->free_rx_skb(vcc,skb); @@ -147,10 +145,10 @@ } spin_lock (&atm_dev_lock); fops_put (vcc->dev->ops); - if (atomic_read(&vcc->rx_inuse)) + if (atomic_read(&vcc->sk->rmem_alloc)) printk(KERN_WARNING "atm_release_vcc: strange ... " - "rx_inuse == %d after closing\n", - atomic_read(&vcc->rx_inuse)); + "rmem_alloc == %d after closing\n", + atomic_read(&vcc->sk->rmem_alloc)); bind_vcc(vcc,NULL); } else spin_lock (&atm_dev_lock); @@ -305,11 +303,15 @@ if (error) return error; } else { - struct atm_dev *dev; + struct atm_dev *dev = NULL; + struct list_head *p; spin_lock (&atm_dev_lock); - for (dev = atm_devs; dev; dev = dev->next) + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); if (!atm_do_connect_dev(vcc,dev,vpi,vci)) break; + dev = NULL; + } spin_unlock (&atm_dev_lock); if (!dev) return -ENODEV; } @@ -336,7 +338,7 @@ int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, int flags, struct scm_cookie *scm) + int total_len, int flags) { DECLARE_WAITQUEUE(wait,current); struct atm_vcc *vcc; @@ -354,7 +356,7 @@ add_wait_queue(&vcc->sleep,&wait); set_current_state(TASK_INTERRUPTIBLE); error = 1; /* <= 0 is error */ - while (!(skb = skb_dequeue(&vcc->recvq))) { + while (!(skb = skb_dequeue(&vcc->sk->receive_queue))) { if (test_bit(ATM_VF_RELEASED,&vcc->flags) || test_bit(ATM_VF_CLOSE,&vcc->flags)) { error = vcc->reply; @@ -385,7 +387,7 @@ if (vcc->dev->ops->feedback) vcc->dev->ops->feedback(vcc,skb,(unsigned long) skb->data, (unsigned long) buff,eff_len); - DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->rx_inuse),skb->truesize); + DPRINTK("RcvM %d -= %d\n",atomic_read(&vcc->sk->rmem_alloc),skb->truesize); atm_return(vcc,skb->truesize); if (ATM_SKB(skb)->iovcnt) { /* @@@ hack */ /* iovcnt set, use scatter-gather for receive */ @@ -417,7 +419,7 @@ int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, struct scm_cookie *scm) + int total_len) { DECLARE_WAITQUEUE(wait,current); struct atm_vcc *vcc; @@ -488,14 +490,14 @@ vcc = ATM_SD(sock); poll_wait(file,&vcc->sleep,wait); mask = 0; - if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq)) + if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq)) mask |= POLLIN | POLLRDNORM; if (test_bit(ATM_VF_RELEASED,&vcc->flags) || test_bit(ATM_VF_CLOSE,&vcc->flags)) mask |= POLLHUP; if (sock->state != SS_CONNECTING) { if (vcc->qos.txtp.traffic_class != ATM_NONE && - vcc->qos.txtp.max_sdu+atomic_read(&vcc->tx_inuse)+ + vcc->qos.txtp.max_sdu+atomic_read(&vcc->sk->wmem_alloc)+ ATM_PDU_OVHD <= vcc->sk->sndbuf) mask |= POLLOUT | POLLWRNORM; } @@ -546,6 +548,7 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) { struct atm_dev *dev; + struct list_head *p; struct atm_vcc *vcc; int *tmp_buf, *tmp_p; void *buf; @@ -562,7 +565,7 @@ goto done; } ret_val = put_user(vcc->sk->sndbuf- - atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD, + atomic_read(&vcc->sk->wmem_alloc)-ATM_PDU_OVHD, (int *) arg) ? -EFAULT : 0; goto done; case SIOCINQ: @@ -573,7 +576,7 @@ ret_val = -EINVAL; goto done; } - skb = skb_peek(&vcc->recvq); + skb = skb_peek(&vcc->sk->receive_queue); ret_val = put_user(skb ? skb->len : 0,(int *) arg) ? -EFAULT : 0; goto done; @@ -590,7 +593,7 @@ goto done; } size = 0; - for (dev = atm_devs; dev; dev = dev->next) + list_for_each(p, &atm_devs) size += sizeof(int); if (size > len) { ret_val = -E2BIG; @@ -602,8 +605,10 @@ goto done; } tmp_p = tmp_buf; - for (dev = atm_devs; dev; dev = dev->next) + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); *tmp_p++ = dev->number; + } ret_val = ((copy_to_user(buf, tmp_buf, size)) || put_user(size, &((struct atm_iobuf *) arg)->length) ) ? -EFAULT : 0; @@ -963,7 +968,7 @@ if (!error) error = adjust_tp(&qos->rxtp,qos->aal); if (error) return error; if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP; - if (vcc->family == AF_ATMPVC) + if (vcc->sk->family == AF_ATMPVC) return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET); return svc_change_qos(vcc,qos); } diff -urN linux-2.5.64-bk5/net/atm/common.h linux-2.5.64-bk6/net/atm/common.h --- linux-2.5.64-bk5/net/atm/common.h Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/net/atm/common.h Mon Mar 31 12:28:50 2003 @@ -14,9 +14,9 @@ int atm_release(struct socket *sock); int atm_connect(struct socket *sock,int itf,short vpi,int vci); int atm_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, int flags, struct scm_cookie *scm); + int total_len, int flags); int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, struct scm_cookie *scm); + int total_len); unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait); int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg); int atm_setsockopt(struct socket *sock,int level,int optname,char *optval, diff -urN linux-2.5.64-bk5/net/atm/lec.c linux-2.5.64-bk6/net/atm/lec.c --- linux-2.5.64-bk5/net/atm/lec.c Tue Mar 4 19:29:24 2003 +++ linux-2.5.64-bk6/net/atm/lec.c Mon Mar 31 12:28:50 2003 @@ -125,7 +125,7 @@ priv = (struct lec_priv *)dev->priv; atm_force_charge(priv->lecd, skb2->truesize); - skb_queue_tail(&priv->lecd->recvq, skb2); + skb_queue_tail(&priv->lecd->sk->receive_queue, skb2); wake_up(&priv->lecd->sleep); } @@ -202,7 +202,7 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv) { if (atm_may_send(vcc, skb->len)) { - atomic_add(skb->truesize, &vcc->tx_inuse); + atomic_add(skb->truesize, &vcc->sk->wmem_alloc); ATM_SKB(skb)->vcc = vcc; ATM_SKB(skb)->iovcnt = 0; ATM_SKB(skb)->atm_options = vcc->atm_options; @@ -399,7 +399,7 @@ int i; char *tmp; /* FIXME */ - atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse); + atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc); mesg = (struct atmlec_msg *)skb->data; tmp = skb->data; tmp += sizeof(struct atmlec_msg); @@ -505,7 +505,7 @@ skb2->len = sizeof(struct atmlec_msg); memcpy(skb2->data, mesg, sizeof(struct atmlec_msg)); atm_force_charge(priv->lecd, skb2->truesize); - skb_queue_tail(&priv->lecd->recvq, skb2); + skb_queue_tail(&priv->lecd->sk->receive_queue, skb2); wake_up(&priv->lecd->sleep); } if (f != NULL) br_fdb_put_hook(f); @@ -534,10 +534,10 @@ netif_stop_queue(dev); lec_arp_destroy(priv); - if (skb_peek(&vcc->recvq)) + if (skb_peek(&vcc->sk->receive_queue)) printk("%s lec_atm_close: closing with messages pending\n", dev->name); - while ((skb = skb_dequeue(&vcc->recvq))) { + while ((skb = skb_dequeue(&vcc->sk->receive_queue))) { atm_return(vcc, skb->truesize); dev_kfree_skb(skb); } @@ -595,13 +595,13 @@ memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); atm_force_charge(priv->lecd, skb->truesize); - skb_queue_tail(&priv->lecd->recvq, skb); + skb_queue_tail(&priv->lecd->sk->receive_queue, skb); wake_up(&priv->lecd->sleep); if (data != NULL) { DPRINTK("lec: about to send %d bytes of data\n", data->len); atm_force_charge(priv->lecd, data->truesize); - skb_queue_tail(&priv->lecd->recvq, data); + skb_queue_tail(&priv->lecd->sk->receive_queue, data); wake_up(&priv->lecd->sleep); } @@ -683,7 +683,7 @@ #endif /* DUMP_PACKETS > 0 */ if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/ DPRINTK("%s: To daemon\n",dev->name); - skb_queue_tail(&vcc->recvq, skb); + skb_queue_tail(&vcc->sk->receive_queue, skb); wake_up(&vcc->sleep); } else { /* Data frame, queue to protocol handlers */ unsigned char *dst; @@ -784,16 +784,20 @@ size = sizeof(struct lec_priv); #ifdef CONFIG_TR if (is_trdev) - dev_lec[i] = init_trdev(NULL, size); + dev_lec[i] = alloc_trdev(size); else #endif - dev_lec[i] = init_etherdev(NULL, size); + dev_lec[i] = alloc_etherdev(size); if (!dev_lec[i]) return -ENOMEM; + snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i); + if (register_netdev(dev_lec[i])) { + kfree(dev_lec[i]); + return -EINVAL; + } priv = dev_lec[i]->priv; priv->is_trdev = is_trdev; - sprintf(dev_lec[i]->name, "lec%d", i); lec_init(dev_lec[i]); } else { priv = dev_lec[i]->priv; diff -urN linux-2.5.64-bk5/net/atm/mpc.c linux-2.5.64-bk6/net/atm/mpc.c --- linux-2.5.64-bk5/net/atm/mpc.c Tue Mar 4 19:29:33 2003 +++ linux-2.5.64-bk6/net/atm/mpc.c Mon Mar 31 12:28:50 2003 @@ -520,7 +520,7 @@ memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)); } - atomic_add(skb->truesize, &entry->shortcut->tx_inuse); + atomic_add(skb->truesize, &entry->shortcut->sk->wmem_alloc); ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */ ATM_SKB(skb)->atm_options = entry->shortcut->atm_options; entry->shortcut->send(entry->shortcut, skb); @@ -665,7 +665,7 @@ skb->dev = dev; if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) { dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name); - skb_queue_tail(&vcc->recvq, skb); /* Pass control packets to daemon */ + skb_queue_tail(&vcc->sk->receive_queue, skb); /* Pass control packets to daemon */ wake_up(&vcc->sleep); return; } @@ -841,7 +841,7 @@ mpc->in_ops->destroy_cache(mpc); mpc->eg_ops->destroy_cache(mpc); - while ( (skb = skb_dequeue(&vcc->recvq)) ){ + while ( (skb = skb_dequeue(&vcc->sk->receive_queue)) ){ atm_return(vcc, skb->truesize); kfree_skb(skb); } @@ -861,7 +861,7 @@ struct mpoa_client *mpc = find_mpc_by_vcc(vcc); struct k_message *mesg = (struct k_message*)skb->data; - atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse); + atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->sk->wmem_alloc); if (mpc == NULL) { printk("mpoa: msg_from_mpoad: no mpc found\n"); @@ -938,7 +938,7 @@ skb_put(skb, sizeof(struct k_message)); memcpy(skb->data, mesg, sizeof(struct k_message)); atm_force_charge(mpc->mpoad_vcc, skb->truesize); - skb_queue_tail(&mpc->mpoad_vcc->recvq, skb); + skb_queue_tail(&mpc->mpoad_vcc->sk->receive_queue, skb); wake_up(&mpc->mpoad_vcc->sleep); return 0; @@ -1215,7 +1215,7 @@ purge_msg->content.eg_info = entry->ctrl_info; atm_force_charge(vcc, skb->truesize); - skb_queue_tail(&vcc->recvq, skb); + skb_queue_tail(&vcc->sk->receive_queue, skb); wake_up(&vcc->sleep); dprintk("mpoa: purge_egress_shortcut: exiting:\n"); diff -urN linux-2.5.64-bk5/net/atm/proc.c linux-2.5.64-bk6/net/atm/proc.c --- linux-2.5.64-bk5/net/atm/proc.c Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/net/atm/proc.c Mon Mar 31 12:28:50 2003 @@ -135,7 +135,7 @@ unsigned char *ip; int svc,off,ip_len; - svc = !clip_vcc || clip_vcc->vcc->family == AF_ATMSVC; + svc = !clip_vcc || clip_vcc->vcc->sk->family == AF_ATMSVC; off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC", !clip_vcc || clip_vcc->encap ? "LLC" : "NULL", (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/ @@ -210,7 +210,7 @@ if (!vcc->dev) here += sprintf(here,"Unassigned "); else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi, vcc->vci); - switch (vcc->family) { + switch (vcc->sk->family) { case AF_ATMPVC: here += sprintf(here,"PVC"); break; @@ -218,12 +218,12 @@ here += sprintf(here,"SVC"); break; default: - here += sprintf(here,"%3d",vcc->family); + here += sprintf(here,"%3d",vcc->sk->family); } here += sprintf(here," %04lx %5d %7d/%7d %7d/%7d\n",vcc->flags, vcc->reply, - atomic_read(&vcc->tx_inuse),vcc->sk->sndbuf, - atomic_read(&vcc->rx_inuse),vcc->sk->rcvbuf); + atomic_read(&vcc->sk->wmem_alloc),vcc->sk->sndbuf, + atomic_read(&vcc->sk->rmem_alloc),vcc->sk->rcvbuf); } @@ -303,6 +303,7 @@ static int atm_devices_info(loff_t pos,char *buf) { struct atm_dev *dev; + struct list_head *p; int left; if (!pos) { @@ -310,10 +311,14 @@ "AAL(TX,err,RX,err,drop) ...\n"); } left = pos-1; - for (dev = atm_devs; dev && left; dev = dev->next) left--; - if (!dev) return 0; - dev_info(dev,buf); - return strlen(buf); + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); + if (left-- == 0) { + dev_info(dev,buf); + return strlen(buf); + } + } + return 0; } /* @@ -324,6 +329,7 @@ static int atm_pvc_info(loff_t pos,char *buf) { struct atm_dev *dev; + struct list_head *p; struct atm_vcc *vcc; int left; @@ -332,13 +338,15 @@ "TX(PCR,Class)\n"); } left = pos-1; - for (dev = atm_devs; dev; dev = dev->next) + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); for (vcc = dev->vccs; vcc; vcc = vcc->next) - if (vcc->family == PF_ATMPVC && + if (vcc->sk->family == PF_ATMPVC && vcc->dev && !left--) { pvc_info(vcc,buf); return strlen(buf); } + } return 0; } @@ -346,6 +354,7 @@ static int atm_vc_info(loff_t pos,char *buf) { struct atm_dev *dev; + struct list_head *p; struct atm_vcc *vcc; int left; @@ -354,12 +363,14 @@ "Address"," Itf VPI VCI Fam Flags Reply Send buffer" " Recv buffer\n"); left = pos-1; - for (dev = atm_devs; dev; dev = dev->next) + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); for (vcc = dev->vccs; vcc; vcc = vcc->next) if (!left--) { vc_info(vcc,buf); return strlen(buf); } + } for (vcc = nodev_vccs; vcc; vcc = vcc->next) if (!left--) { vc_info(vcc,buf); @@ -373,20 +384,23 @@ static int atm_svc_info(loff_t pos,char *buf) { struct atm_dev *dev; + struct list_head *p; struct atm_vcc *vcc; int left; if (!pos) return sprintf(buf,"Itf VPI VCI State Remote\n"); left = pos-1; - for (dev = atm_devs; dev; dev = dev->next) + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); for (vcc = dev->vccs; vcc; vcc = vcc->next) - if (vcc->family == PF_ATMSVC && !left--) { + if (vcc->sk->family == PF_ATMSVC && !left--) { svc_info(vcc,buf); return strlen(buf); } + } for (vcc = nodev_vccs; vcc; vcc = vcc->next) - if (vcc->family == PF_ATMSVC && !left--) { + if (vcc->sk->family == PF_ATMSVC && !left--) { svc_info(vcc,buf); return strlen(buf); } diff -urN linux-2.5.64-bk5/net/atm/raw.c linux-2.5.64-bk6/net/atm/raw.c --- linux-2.5.64-bk5/net/atm/raw.c Tue Mar 4 19:29:39 2003 +++ linux-2.5.64-bk6/net/atm/raw.c Mon Mar 31 12:28:50 2003 @@ -28,7 +28,7 @@ void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb) { if (skb) { - skb_queue_tail(&vcc->recvq,skb); + skb_queue_tail(&vcc->sk->receive_queue,skb); wake_up(&vcc->sleep); } } @@ -36,8 +36,8 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) { - DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize); - atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); + DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->sk->wmem_alloc,skb->truesize); + atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc); dev_kfree_skb_any(skb); wake_up(&vcc->sleep); } diff -urN linux-2.5.64-bk5/net/atm/resources.c linux-2.5.64-bk6/net/atm/resources.c --- linux-2.5.64-bk5/net/atm/resources.c Tue Mar 4 19:29:51 2003 +++ linux-2.5.64-bk6/net/atm/resources.c Mon Mar 31 12:28:50 2003 @@ -26,8 +26,7 @@ #endif -struct atm_dev *atm_devs = NULL; -static struct atm_dev *last_dev = NULL; +LIST_HEAD(atm_devs); struct atm_vcc *nodev_vccs = NULL; extern spinlock_t atm_dev_lock; @@ -43,15 +42,7 @@ dev->type = type; dev->signal = ATM_PHY_SIG_UNKNOWN; dev->link_rate = ATM_OC3_PCR; - dev->next = NULL; - - dev->prev = last_dev; - - if (atm_devs) - last_dev->next = dev; - else - atm_devs = dev; - last_dev = dev; + list_add_tail(&dev->dev_list, &atm_devs); return dev; } @@ -59,14 +50,7 @@ /* Caller must hold atm_dev_lock. */ static void __free_atm_dev(struct atm_dev *dev) { - if (dev->prev) - dev->prev->next = dev->next; - else - atm_devs = dev->next; - if (dev->next) - dev->next->prev = dev->prev; - else - last_dev = dev->prev; + list_del(&dev->dev_list); kfree(dev); } @@ -74,10 +58,13 @@ struct atm_dev *atm_find_dev(int number) { struct atm_dev *dev; + struct list_head *p; - for (dev = atm_devs; dev; dev = dev->next) + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); if (dev->ops && dev->number == number) return dev; + } return NULL; } diff -urN linux-2.5.64-bk5/net/atm/resources.h linux-2.5.64-bk6/net/atm/resources.h --- linux-2.5.64-bk5/net/atm/resources.h Tue Mar 4 19:29:33 2003 +++ linux-2.5.64-bk6/net/atm/resources.h Mon Mar 31 12:28:50 2003 @@ -10,7 +10,7 @@ #include -extern struct atm_dev *atm_devs; +extern struct list_head atm_devs; extern struct atm_vcc *nodev_vccs; /* VCCs not linked to any device */ diff -urN linux-2.5.64-bk5/net/atm/signaling.c linux-2.5.64-bk6/net/atm/signaling.c --- linux-2.5.64-bk5/net/atm/signaling.c Tue Mar 4 19:29:32 2003 +++ linux-2.5.64-bk6/net/atm/signaling.c Mon Mar 31 12:28:50 2003 @@ -61,7 +61,7 @@ } #endif atm_force_charge(sigd,skb->truesize); - skb_queue_tail(&sigd->recvq,skb); + skb_queue_tail(&sigd->sk->receive_queue,skb); wake_up(&sigd->sleep); } @@ -98,7 +98,7 @@ struct atm_vcc *session_vcc; msg = (struct atmsvc_msg *) skb->data; - atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); + atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->sk->wmem_alloc); DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type, (unsigned long) msg->vcc); vcc = *(struct atm_vcc **) &msg->vcc; @@ -198,7 +198,7 @@ static void purge_vccs(struct atm_vcc *vcc) { while (vcc) { - if (vcc->family == PF_ATMSVC && + if (vcc->sk->family == PF_ATMSVC && !test_bit(ATM_VF_META,&vcc->flags)) { set_bit(ATM_VF_RELEASED,&vcc->flags); vcc->reply = -EUNATCH; @@ -212,16 +212,20 @@ static void sigd_close(struct atm_vcc *vcc) { struct atm_dev *dev; + struct list_head *p; DPRINTK("sigd_close\n"); sigd = NULL; - if (skb_peek(&vcc->recvq)) + if (skb_peek(&vcc->sk->receive_queue)) printk(KERN_ERR "sigd_close: closing with requests pending\n"); - skb_queue_purge(&vcc->recvq); + skb_queue_purge(&vcc->sk->receive_queue); purge_vccs(nodev_vccs); spin_lock (&atm_dev_lock); - for (dev = atm_devs; dev; dev = dev->next) purge_vccs(dev->vccs); + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); + purge_vccs(dev->vccs); + } spin_unlock (&atm_dev_lock); } diff -urN linux-2.5.64-bk5/net/ax25/af_ax25.c linux-2.5.64-bk6/net/ax25/af_ax25.c --- linux-2.5.64-bk5/net/ax25/af_ax25.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/ax25/af_ax25.c Mon Mar 31 12:28:50 2003 @@ -1411,8 +1411,7 @@ } static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, - struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; struct sock *sk = sock->sk; @@ -1590,7 +1589,7 @@ } static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb; diff -urN linux-2.5.64-bk5/net/bluetooth/af_bluetooth.c linux-2.5.64-bk6/net/bluetooth/af_bluetooth.c --- linux-2.5.64-bk5/net/bluetooth/af_bluetooth.c Tue Mar 4 19:29:02 2003 +++ linux-2.5.64-bk6/net/bluetooth/af_bluetooth.c Mon Mar 31 12:28:50 2003 @@ -212,7 +212,7 @@ } int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, int flags, struct scm_cookie *scm) + struct msghdr *msg, int len, int flags) { int noblock = flags & MSG_DONTWAIT; struct sock *sk = sock->sk; diff -urN linux-2.5.64-bk5/net/bluetooth/bnep/core.c linux-2.5.64-bk6/net/bluetooth/bnep/core.c --- linux-2.5.64-bk5/net/bluetooth/bnep/core.c Tue Mar 4 19:29:31 2003 +++ linux-2.5.64-bk6/net/bluetooth/bnep/core.c Mon Mar 31 12:28:50 2003 @@ -97,26 +97,12 @@ static int bnep_send(struct bnep_session *s, void *data, size_t len) { - struct kiocb iocb; - struct sock_iocb *si; struct socket *sock = s->sock; struct iovec iv = { data, len }; - int err; s->msg.msg_iov = &iv; s->msg.msg_iovlen = 1; - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->scm = NULL; - si->sock = sock; - si->msg = &s->msg; - si->size = len; - - err = sock->ops->sendmsg(&iocb, sock, &s->msg, len, NULL); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - return err; + return sock_sendmsg(sock, &s->msg, len); } static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp) @@ -444,20 +430,9 @@ /* FIXME: linearize skb */ { - struct kiocb iocb; - struct sock_iocb *si; - s->msg.msg_iov = iv; s->msg.msg_iovlen = il; - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->scm = NULL; - si->sock = sock; - si->msg = &s->msg; - si->size = len; - len = sock->ops->sendmsg(&iocb, sock, &s->msg, len, NULL); - if (-EIOCBQUEUED == len) - len = wait_on_sync_kiocb(&iocb); + len = sock_sendmsg(sock, &s->msg, len); } kfree_skb(skb); diff -urN linux-2.5.64-bk5/net/bluetooth/hci_sock.c linux-2.5.64-bk6/net/bluetooth/hci_sock.c --- linux-2.5.64-bk5/net/bluetooth/hci_sock.c Tue Mar 4 19:29:22 2003 +++ linux-2.5.64-bk6/net/bluetooth/hci_sock.c Mon Mar 31 12:28:50 2003 @@ -320,7 +320,7 @@ put_cmsg(msg, SOL_HCI, HCI_CMSG_TSTAMP, sizeof(skb->stamp), &skb->stamp); } -static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm) +static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags) { int noblock = flags & MSG_DONTWAIT; struct sock *sk = sock->sk; @@ -356,8 +356,7 @@ return err ? : copied; } -static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, - struct scm_cookie *scm) +static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct hci_dev *hdev; diff -urN linux-2.5.64-bk5/net/bluetooth/l2cap.c linux-2.5.64-bk6/net/bluetooth/l2cap.c --- linux-2.5.64-bk5/net/bluetooth/l2cap.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/bluetooth/l2cap.c Mon Mar 31 12:28:50 2003 @@ -712,7 +712,7 @@ return err; } -static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) +static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len) { struct sock *sk = sock->sk; int err = 0; diff -urN linux-2.5.64-bk5/net/bluetooth/rfcomm/core.c linux-2.5.64-bk6/net/bluetooth/rfcomm/core.c --- linux-2.5.64-bk5/net/bluetooth/rfcomm/core.c Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/net/bluetooth/rfcomm/core.c Mon Mar 31 12:28:50 2003 @@ -605,29 +605,17 @@ /* ---- RFCOMM frame sending ---- */ static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len) { - struct kiocb iocb; - struct sock_iocb *si; struct socket *sock = s->sock; struct iovec iv = { data, len }; struct msghdr msg; - int err; BT_DBG("session %p len %d", s, len); memset(&msg, 0, sizeof(msg)); msg.msg_iovlen = 1; msg.msg_iov = &iv; - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->scm = NULL; - si->sock = sock; - si->msg = &msg; - si->size = len; - - err = sock->ops->sendmsg(&iocb, sock, &msg, len, NULL); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - return err; + + return sock_sendmsg(sock, &msg, len); } static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci) @@ -839,13 +827,10 @@ static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len) { - struct kiocb iocb; - struct sock_iocb *si; struct socket *sock = s->sock; struct iovec iv[3]; struct msghdr msg; unsigned char hdr[5], crc[1]; - int err; if (len > 125) return -EINVAL; @@ -870,18 +855,8 @@ memset(&msg, 0, sizeof(msg)); msg.msg_iovlen = 3; msg.msg_iov = iv; - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->scm = NULL; - si->sock = sock; - si->msg = &msg; - si->size = 6 + len; - - err = sock->ops->sendmsg(&iocb, sock, &msg, 6 + len, NULL); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - return err; + return sock_sendmsg(sock, &msg, 6 + len); } static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits) diff -urN linux-2.5.64-bk5/net/bluetooth/rfcomm/sock.c linux-2.5.64-bk6/net/bluetooth/rfcomm/sock.c --- linux-2.5.64-bk5/net/bluetooth/rfcomm/sock.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/bluetooth/rfcomm/sock.c Mon Mar 31 12:28:50 2003 @@ -479,7 +479,7 @@ } static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; @@ -553,8 +553,7 @@ } static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; int target, err = 0, copied = 0; diff -urN linux-2.5.64-bk5/net/bluetooth/sco.c linux-2.5.64-bk6/net/bluetooth/sco.c --- linux-2.5.64-bk5/net/bluetooth/sco.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/bluetooth/sco.c Mon Mar 31 12:28:50 2003 @@ -632,7 +632,7 @@ return 0; } -static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) +static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len) { struct sock *sk = sock->sk; int err = 0; diff -urN linux-2.5.64-bk5/net/compat.c linux-2.5.64-bk6/net/compat.c --- linux-2.5.64-bk5/net/compat.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.64-bk6/net/compat.c Mon Mar 31 12:28:50 2003 @@ -0,0 +1,700 @@ +/* + * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c. + * + * Copyright (C) 2000 VA Linux Co + * Copyright (C) 2000 Don Dugger + * Copyright (C) 1999 Arun Sharma + * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2000 Hewlett-Packard Co. + * Copyright (C) 2000 David Mosberger-Tang + * Copyright (C) 2000,2001 Andi Kleen, SuSE Labs + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define A(__x) ((unsigned long)(__x)) +#define AA(__x) ((unsigned long)(__x)) + +extern asmlinkage long sys_getsockopt(int fd, int level, int optname, + void * optval, int *optlen); + + +static inline int iov_from_user_compat_to_kern(struct iovec *kiov, + struct compat_iovec *uiov32, + int niov) +{ + int tot_len = 0; + + while(niov > 0) { + u32 len, buf; + + if(get_user(len, &uiov32->iov_len) || + get_user(buf, &uiov32->iov_base)) { + tot_len = -EFAULT; + break; + } + tot_len += len; + kiov->iov_base = (void *)A(buf); + kiov->iov_len = (__kernel_size_t) len; + uiov32++; + kiov++; + niov--; + } + return tot_len; +} + +int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *umsg) +{ + u32 tmp1, tmp2, tmp3; + int err; + + err = get_user(tmp1, &umsg->msg_name); + err |= __get_user(tmp2, &umsg->msg_iov); + err |= __get_user(tmp3, &umsg->msg_control); + if (err) + return -EFAULT; + + kmsg->msg_name = (void *)A(tmp1); + kmsg->msg_iov = (struct iovec *)A(tmp2); + kmsg->msg_control = (void *)A(tmp3); + + err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); + err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); + err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); + err |= get_user(kmsg->msg_flags, &umsg->msg_flags); + + return err; +} + +/* I've named the args so it is easy to tell whose space the pointers are in. */ +int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, + char *kern_address, int mode) +{ + int tot_len; + + if(kern_msg->msg_namelen) { + if(mode==VERIFY_READ) { + int err = move_addr_to_kernel(kern_msg->msg_name, + kern_msg->msg_namelen, + kern_address); + if(err < 0) + return err; + } + kern_msg->msg_name = kern_address; + } else + kern_msg->msg_name = NULL; + + if(kern_msg->msg_iovlen > UIO_FASTIOV) { + kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), + GFP_KERNEL); + if(!kern_iov) + return -ENOMEM; + } + + tot_len = iov_from_user_compat_to_kern(kern_iov, + (struct compat_iovec *)kern_msg->msg_iov, + kern_msg->msg_iovlen); + if(tot_len >= 0) + kern_msg->msg_iov = kern_iov; + else if(kern_msg->msg_iovlen > UIO_FASTIOV) + kfree(kern_iov); + + return tot_len; +} + +/* There is a lot of hair here because the alignment rules (and + * thus placement) of cmsg headers and length are different for + * 32-bit apps. -DaveM + */ +int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, + unsigned char *stackbuf, int stackbuf_size) +{ + struct compat_cmsghdr *ucmsg; + struct cmsghdr *kcmsg, *kcmsg_base; + compat_size_t ucmlen; + __kernel_size_t kcmlen, tmp; + + kcmlen = 0; + kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; + ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); + while(ucmsg != NULL) { + if(get_user(ucmlen, &ucmsg->cmsg_len)) + return -EFAULT; + + /* Catch bogons. */ + if(CMSG_COMPAT_ALIGN(ucmlen) < + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))) + return -EINVAL; + if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + + ucmlen) > kmsg->msg_controllen) + return -EINVAL; + + tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) + + CMSG_ALIGN(sizeof(struct cmsghdr))); + kcmlen += tmp; + ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen); + } + if(kcmlen == 0) + return -EINVAL; + + /* The kcmlen holds the 64-bit version of the control length. + * It may not be modified as we do not stick it into the kmsg + * until we have successfully copied over all of the data + * from the user. + */ + if(kcmlen > stackbuf_size) + kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); + if(kcmsg == NULL) + return -ENOBUFS; + + /* Now copy them over neatly. */ + memset(kcmsg, 0, kcmlen); + ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg); + while(ucmsg != NULL) { + __get_user(ucmlen, &ucmsg->cmsg_len); + tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) + + CMSG_ALIGN(sizeof(struct cmsghdr))); + kcmsg->cmsg_len = tmp; + __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); + + /* Copy over the data. */ + if(copy_from_user(CMSG_DATA(kcmsg), + CMSG_COMPAT_DATA(ucmsg), + (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))))) + goto out_free_efault; + + /* Advance. */ + kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); + ucmsg = CMSG_COMPAT_NXTHDR(kmsg, ucmsg, ucmlen); + } + + /* Ok, looks like we made it. Hook it up and return success. */ + kmsg->msg_control = kcmsg_base; + kmsg->msg_controllen = kcmlen; + return 0; + +out_free_efault: + if(kcmsg_base != (struct cmsghdr *)stackbuf) + kfree(kcmsg_base); + return -EFAULT; +} + +int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) +{ + struct compat_cmsghdr *cm = (struct compat_cmsghdr *) kmsg->msg_control; + struct compat_cmsghdr cmhdr; + int cmlen = CMSG_COMPAT_LEN(len); + + if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { + kmsg->msg_flags |= MSG_CTRUNC; + return 0; /* XXX: return error? check spec. */ + } + + if(kmsg->msg_controllen < cmlen) { + kmsg->msg_flags |= MSG_CTRUNC; + cmlen = kmsg->msg_controllen; + } + cmhdr.cmsg_level = level; + cmhdr.cmsg_type = type; + cmhdr.cmsg_len = cmlen; + + if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) + return -EFAULT; + if(copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr))) + return -EFAULT; + cmlen = CMSG_COMPAT_SPACE(len); + kmsg->msg_control += cmlen; + kmsg->msg_controllen -= cmlen; + return 0; +} + +void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) +{ + struct compat_cmsghdr *cm = (struct compat_cmsghdr *) kmsg->msg_control; + int fdmax = (kmsg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int); + int fdnum = scm->fp->count; + struct file **fp = scm->fp->fp; + int *cmfptr; + int err = 0, i; + + if (fdnum < fdmax) + fdmax = fdnum; + + for (i = 0, cmfptr = (int *) CMSG_COMPAT_DATA(cm); i < fdmax; i++, cmfptr++) { + int new_fd; + err = get_unused_fd(); + if (err < 0) + break; + new_fd = err; + err = put_user(new_fd, cmfptr); + if (err) { + put_unused_fd(new_fd); + break; + } + /* Bump the usage count and install the file. */ + get_file(fp[i]); + fd_install(new_fd, fp[i]); + } + + if (i > 0) { + int cmlen = CMSG_COMPAT_LEN(i * sizeof(int)); + if (!err) + err = put_user(SOL_SOCKET, &cm->cmsg_level); + if (!err) + err = put_user(SCM_RIGHTS, &cm->cmsg_type); + if (!err) + err = put_user(cmlen, &cm->cmsg_len); + if (!err) { + cmlen = CMSG_COMPAT_SPACE(i * sizeof(int)); + kmsg->msg_control += cmlen; + kmsg->msg_controllen -= cmlen; + } + } + if (i < fdnum) + kmsg->msg_flags |= MSG_CTRUNC; + + /* + * All of the files that fit in the message have had their + * usage counts incremented, so we just free the list. + */ + __scm_destroy(scm); +} + +/* In these cases we (currently) can just copy to data over verbatim + * because all CMSGs created by the kernel have well defined types which + * have the same layout in both the 32-bit and 64-bit API. One must add + * some special cased conversions here if we start sending control messages + * with incompatible types. + * + * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg_compat right after + * we do our work. The remaining cases are: + * + * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean + * IP_TTL int 32-bit clean + * IP_TOS __u8 32-bit clean + * IP_RECVOPTS variable length 32-bit clean + * IP_RETOPTS variable length 32-bit clean + * (these last two are clean because the types are defined + * by the IPv4 protocol) + * IP_RECVERR struct sock_extended_err + + * struct sockaddr_in 32-bit clean + * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + + * struct sockaddr_in6 32-bit clean + * IPV6_PKTINFO struct in6_pktinfo 32-bit clean + * IPV6_HOPLIMIT int 32-bit clean + * IPV6_FLOWINFO u32 32-bit clean + * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean + * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) +{ + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; + struct cmsghdr *ucmsg; + + bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; + space_avail = kmsg->msg_controllen + bufsz; + wp = workbuf = kmalloc(bufsz, GFP_KERNEL); + if(workbuf == NULL) + goto fail; + + /* To make this more sane we assume the kernel sends back properly + * formatted control messages. Because of how the kernel will truncate + * the cmsg_len for MSG_TRUNC cases, we need not check that case either. + */ + ucmsg = (struct cmsghdr *) orig_cmsg_uptr; + while(((unsigned long)ucmsg) <= + (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { + struct compat_cmsghdr *kcmsg_compat = (struct compat_cmsghdr *) wp; + int clen64, clen32; + + /* UCMSG is the 64-bit format CMSG entry in user-space. + * KCMSG_COMPAT is within the kernel space temporary buffer + * we use to convert into a 32-bit style CMSG. + */ + __get_user(kcmsg_compat->cmsg_len, &ucmsg->cmsg_len); + __get_user(kcmsg_compat->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg_compat->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg_compat->cmsg_len; + copy_from_user(CMSG_COMPAT_DATA(kcmsg_compat), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + + CMSG_COMPAT_ALIGN(sizeof(struct compat_cmsghdr))); + kcmsg_compat->cmsg_len = clen32; + + ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); + wp = (((char *)kcmsg_compat) + CMSG_COMPAT_ALIGN(clen32)); + } + + /* Copy back fixed up data, and adjust pointers. */ + bufsz = (wp - workbuf); + copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); + + kmsg->msg_control = (struct cmsghdr *) + (((char *)orig_cmsg_uptr) + bufsz); + kmsg->msg_controllen = space_avail - bufsz; + + kfree(workbuf); + return; + +fail: + /* If we leave the 64-bit format CMSG chunks in there, + * the application could get confused and crash. So to + * ensure greater recovery, we report no CMSGs. + */ + kmsg->msg_controllen += bufsz; + kmsg->msg_control = (void *) orig_cmsg_uptr; +} + +extern asmlinkage int sys_setsockopt(int fd, int level, int optname, + char *optval, int optlen); + +static int do_netfilter_replace(int fd, int level, int optname, + char *optval, int optlen) +{ + struct ipt_replace32 { + char name[IPT_TABLE_MAXNAMELEN]; + __u32 valid_hooks; + __u32 num_entries; + __u32 size; + __u32 hook_entry[NF_IP_NUMHOOKS]; + __u32 underflow[NF_IP_NUMHOOKS]; + __u32 num_counters; + __u32 counters; + struct ipt_entry entries[0]; + } *repl32 = (struct ipt_replace32 *)optval; + struct ipt_replace *krepl; + struct ipt_counters *counters32; + __u32 origsize; + unsigned int kreplsize, kcountersize; + mm_segment_t old_fs; + int ret; + + if (optlen < sizeof(repl32)) + return -EINVAL; + + if (copy_from_user(&origsize, + &repl32->size, + sizeof(origsize))) + return -EFAULT; + + kreplsize = sizeof(*krepl) + origsize; + kcountersize = krepl->num_counters * sizeof(struct ipt_counters); + + /* Hack: Causes ipchains to give correct error msg --RR */ + if (optlen != kreplsize) + return -ENOPROTOOPT; + + krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL); + if (krepl == NULL) + return -ENOMEM; + + if (copy_from_user(krepl, optval, kreplsize)) { + kfree(krepl); + return -EFAULT; + } + + counters32 = (struct ipt_counters *)AA( + ((struct ipt_replace32 *)krepl)->counters); + + kcountersize = krepl->num_counters * sizeof(struct ipt_counters); + krepl->counters = (struct ipt_counters *)kmalloc( + kcountersize, GFP_KERNEL); + if (krepl->counters == NULL) { + kfree(krepl); + return -ENOMEM; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, + (char *)krepl, kreplsize); + set_fs(old_fs); + + if (ret == 0 && + copy_to_user(counters32, krepl->counters, kcountersize)) + ret = -EFAULT; + + kfree(krepl->counters); + kfree(krepl); + + return ret; +} + +static int do_set_attach_filter(int fd, int level, int optname, + char *optval, int optlen) +{ + struct sock_fprog32 { + __u16 len; + __u32 filter; + } *fprog32 = (struct sock_fprog32 *)optval; + struct sock_fprog kfprog; + struct sock_filter *kfilter; + unsigned int fsize; + mm_segment_t old_fs; + __u32 uptr; + int ret; + + if (get_user(kfprog.len, &fprog32->len) || + __get_user(uptr, &fprog32->filter)) + return -EFAULT; + + kfprog.filter = (struct sock_filter *)A(uptr); + fsize = kfprog.len * sizeof(struct sock_filter); + + kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); + if (kfilter == NULL) + return -ENOMEM; + + if (copy_from_user(kfilter, kfprog.filter, fsize)) { + kfree(kfilter); + return -EFAULT; + } + + kfprog.filter = kfilter; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, + (char *)&kfprog, sizeof(kfprog)); + set_fs(old_fs); + + kfree(kfilter); + + return ret; +} + +static int do_set_icmpv6_filter(int fd, int level, int optname, + char *optval, int optlen) +{ + struct icmp6_filter kfilter; + mm_segment_t old_fs; + int ret, i; + + if (copy_from_user(&kfilter, optval, sizeof(kfilter))) + return -EFAULT; + + + for (i = 0; i < 8; i += 2) { + u32 tmp = kfilter.data[i]; + + kfilter.data[i] = kfilter.data[i + 1]; + kfilter.data[i + 1] = tmp; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, + (char *) &kfilter, sizeof(kfilter)); + set_fs(old_fs); + + return ret; +} + +static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) +{ + struct compat_timeval *up = (struct compat_timeval *) optval; + struct timeval ktime; + mm_segment_t old_fs; + int err; + + if (optlen < sizeof(*up)) + return -EINVAL; + if (get_user(ktime.tv_sec, &up->tv_sec) || + __get_user(ktime.tv_usec, &up->tv_usec)) + return -EFAULT; + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); + set_fs(old_fs); + + return err; +} + +asmlinkage int compat_sys_setsockopt(int fd, int level, int optname, + char *optval, int optlen) +{ + if (optname == IPT_SO_SET_REPLACE) + return do_netfilter_replace(fd, level, optname, + optval, optlen); + if (optname == SO_ATTACH_FILTER) + return do_set_attach_filter(fd, level, optname, + optval, optlen); + if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) + return do_set_sock_timeout(fd, level, optname, optval, optlen); + if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) + return do_set_icmpv6_filter(fd, level, optname, + optval, optlen); + + return sys_setsockopt(fd, level, optname, optval, optlen); +} + +static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) +{ + struct compat_timeval *up = (struct compat_timeval *) optval; + struct timeval ktime; + mm_segment_t old_fs; + int len, err; + + if (get_user(len, optlen)) + return -EFAULT; + if (len < sizeof(*up)) + return -EINVAL; + len = sizeof(ktime); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); + set_fs(old_fs); + + if (!err) { + if (put_user(sizeof(*up), optlen) || + put_user(ktime.tv_sec, &up->tv_sec) || + __put_user(ktime.tv_usec, &up->tv_usec)) + err = -EFAULT; + } + return err; +} + +asmlinkage long compat_sys_getsockopt(int fd, int level, int optname, + char *optval, int *optlen) +{ + if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) + return do_get_sock_timeout(fd, level, optname, optval, optlen); + return sys_getsockopt(fd, level, optname, optval, optlen); +} + +/* Argument list sizes for compat_sys_socketcall */ +#define AL(x) ((x) * sizeof(u32)) +static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), + AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), + AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; +#undef AL + +extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); +extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, + int addrlen); +extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, + int *upeer_addrlen); +extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, + int *usockaddr_len); +extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, + int *usockaddr_len); +extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags); +extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len, + unsigned flags, u32 addr, int addr_len); +extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags); +extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size, + unsigned flags, u32 addr, u32 addr_len); +extern asmlinkage long sys_socket(int family, int type, int protocol); +extern asmlinkage long sys_socketpair(int family, int type, int protocol, + int usockvec[2]); +extern asmlinkage long sys_shutdown(int fd, int how); +extern asmlinkage long sys_listen(int fd, int backlog); + + +asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr *msg, unsigned flags) +{ + return sys_sendmsg(fd, (struct msghdr *)msg, flags | MSG_CMSG_COMPAT); +} + +asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr *msg, unsigned int flags) +{ + return sys_recvmsg(fd, (struct msghdr *)msg, flags | MSG_CMSG_COMPAT); +} + +asmlinkage long compat_sys_socketcall(int call, u32 *args) +{ + int ret; + u32 a[6]; + u32 a0, a1; + + if (call < SYS_SOCKET || call > SYS_RECVMSG) + return -EINVAL; + if (copy_from_user(a, args, nas[call])) + return -EFAULT; + a0 = a[0]; + a1 = a[1]; + + switch(call) { + case SYS_SOCKET: + ret = sys_socket(a0, a1, a[2]); + break; + case SYS_BIND: + ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); + break; + case SYS_CONNECT: + ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); + break; + case SYS_LISTEN: + ret = sys_listen(a0, a1); + break; + case SYS_ACCEPT: + ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); + break; + case SYS_GETSOCKNAME: + ret = sys_getsockname(a0, (struct sockaddr *)A(a1), + (int *)A(a[2])); + break; + case SYS_GETPEERNAME: + ret = sys_getpeername(a0, (struct sockaddr *)A(a1), + (int *)A(a[2])); + break; + case SYS_SOCKETPAIR: + ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); + break; + case SYS_SEND: + ret = sys_send(a0, (void *)A(a1), a[2], a[3]); + break; + case SYS_SENDTO: + ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); + break; + case SYS_RECV: + ret = sys_recv(a0, (void *)A(a1), a[2], a[3]); + break; + case SYS_RECVFROM: + ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); + break; + case SYS_SHUTDOWN: + ret = sys_shutdown(a0,a1); + break; + case SYS_SETSOCKOPT: + ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), + a[4]); + break; + case SYS_GETSOCKOPT: + ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3], + (int *)(u64)a[4]); + break; + case SYS_SENDMSG: + ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1), + a[2]); + break; + case SYS_RECVMSG: + ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1), + a[2]); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} diff -urN linux-2.5.64-bk5/net/core/scm.c linux-2.5.64-bk6/net/core/scm.c --- linux-2.5.64-bk5/net/core/scm.c Tue Mar 4 19:29:16 2003 +++ linux-2.5.64-bk6/net/core/scm.c Mon Mar 31 12:28:50 2003 @@ -172,6 +172,9 @@ int cmlen = CMSG_LEN(len); int err; + if (MSG_CMSG_COMPAT & msg->msg_flags) + return put_cmsg_compat(msg, level, type, len, data); + if (cm==NULL || msg->msg_controllen < sizeof(*cm)) { msg->msg_flags |= MSG_CTRUNC; return 0; /* XXX: return error? check spec. */ @@ -207,6 +210,9 @@ int *cmfptr; int err = 0, i; + if (MSG_CMSG_COMPAT & msg->msg_flags) + return scm_detach_fds_compat(msg, scm); + if (msg->msg_controllen > sizeof(struct cmsghdr)) fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr)) / sizeof(int)); diff -urN linux-2.5.64-bk5/net/core/sock.c linux-2.5.64-bk6/net/core/sock.c --- linux-2.5.64-bk5/net/core/sock.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/core/sock.c Mon Mar 31 12:28:50 2003 @@ -153,6 +153,12 @@ return 0; } +static void sock_warn_obsolete_bsdism(const char *name) +{ + printk(KERN_WARNING "process `%s' is using obsolete " + "%s SO_BSDCOMPAT\n", current->comm, name); +} + /* * This is meant for all protocols to use and covers goings on * at the socket level. Everything here is generic. @@ -303,7 +309,7 @@ break; case SO_BSDCOMPAT: - sock_valbool_flag(sk, SOCK_BSDISM, valbool); + sock_warn_obsolete_bsdism("setsockopt"); break; case SO_PASSCRED: @@ -491,7 +497,7 @@ break; case SO_BSDCOMPAT: - v.val = test_bit(SOCK_BSDISM, &sk->flags); + sock_warn_obsolete_bsdism("getsockopt"); break; case SO_TIMESTAMP: @@ -961,13 +967,13 @@ } int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int flags, struct scm_cookie *scm) + int flags) { return -EOPNOTSUPP; } int sock_no_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int len, int flags, struct scm_cookie *scm) + int len, int flags) { return -EOPNOTSUPP; } diff -urN linux-2.5.64-bk5/net/decnet/af_decnet.c linux-2.5.64-bk6/net/decnet/af_decnet.c --- linux-2.5.64-bk5/net/decnet/af_decnet.c Tue Mar 4 19:29:19 2003 +++ linux-2.5.64-bk6/net/decnet/af_decnet.c Mon Mar 31 12:28:50 2003 @@ -1718,7 +1718,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; struct dn_scp *scp = DN_SK(sk); @@ -1889,7 +1889,7 @@ } static int dn_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, struct scm_cookie *scm) + struct msghdr *msg, int size) { struct sock *sk = sock->sk; struct dn_scp *scp = DN_SK(sk); diff -urN linux-2.5.64-bk5/net/econet/af_econet.c linux-2.5.64-bk6/net/econet/af_econet.c --- linux-2.5.64-bk5/net/econet/af_econet.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/econet/af_econet.c Mon Mar 31 12:28:50 2003 @@ -126,8 +126,7 @@ */ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int len, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb; @@ -260,7 +259,7 @@ */ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name; diff -urN linux-2.5.64-bk5/net/ipv4/af_inet.c linux-2.5.64-bk6/net/ipv4/af_inet.c --- linux-2.5.64-bk5/net/ipv4/af_inet.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/ipv4/af_inet.c Mon Mar 31 12:28:50 2003 @@ -731,7 +731,7 @@ int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - int size, int flags, struct scm_cookie *scm) + int size, int flags) { struct sock *sk = sock->sk; int addr_len = 0; @@ -746,7 +746,7 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, - int size, struct scm_cookie *scm) + int size) { struct sock *sk = sock->sk; diff -urN linux-2.5.64-bk5/net/ipv4/icmp.c linux-2.5.64-bk6/net/ipv4/icmp.c --- linux-2.5.64-bk5/net/ipv4/icmp.c Tue Mar 4 19:29:51 2003 +++ linux-2.5.64-bk6/net/ipv4/icmp.c Mon Mar 31 12:28:50 2003 @@ -116,7 +116,7 @@ DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics); /* An array of errno for error messages from dest unreach. */ -/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errs'. */ +/* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */ struct icmp_err icmp_err_convert[] = { { diff -urN linux-2.5.64-bk5/net/ipv4/tcp_ipv4.c linux-2.5.64-bk6/net/ipv4/tcp_ipv4.c --- linux-2.5.64-bk5/net/ipv4/tcp_ipv4.c Tue Mar 4 19:29:15 2003 +++ linux-2.5.64-bk6/net/ipv4/tcp_ipv4.c Mon Mar 31 12:28:50 2003 @@ -142,6 +142,17 @@ return tb; } +/* Caller must hold hashbucket lock for this tb with local BH disabled */ +void tcp_bucket_destroy(struct tcp_bind_bucket *tb) +{ + if (!tb->owners) { + if (tb->next) + tb->next->pprev = tb->pprev; + *(tb->pprev) = tb->next; + kmem_cache_free(tcp_bucket_cachep, tb); + } +} + /* Caller must disable local BH processing. */ static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child) { @@ -300,12 +311,7 @@ *(sk->bind_pprev) = sk->bind_next; sk->prev = NULL; inet->num = 0; - if (!tb->owners) { - if (tb->next) - tb->next->pprev = tb->pprev; - *(tb->pprev) = tb->next; - kmem_cache_free(tcp_bucket_cachep, tb); - } + tcp_bucket_destroy(tb); spin_unlock(&head->lock); } diff -urN linux-2.5.64-bk5/net/ipv4/tcp_minisocks.c linux-2.5.64-bk6/net/ipv4/tcp_minisocks.c --- linux-2.5.64-bk5/net/ipv4/tcp_minisocks.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/ipv4/tcp_minisocks.c Mon Mar 31 12:28:50 2003 @@ -81,12 +81,7 @@ tw->bind_next->bind_pprev = tw->bind_pprev; *(tw->bind_pprev) = tw->bind_next; tw->tb = NULL; - if (tb->owners == NULL) { - if (tb->next) - tb->next->pprev = tb->pprev; - *(tb->pprev) = tb->next; - kmem_cache_free(tcp_bucket_cachep, tb); - } + tcp_bucket_destroy(tb); spin_unlock(&bhead->lock); #ifdef INET_REFCNT_DEBUG diff -urN linux-2.5.64-bk5/net/ipv6/icmp.c linux-2.5.64-bk6/net/ipv6/icmp.c --- linux-2.5.64-bk5/net/ipv6/icmp.c Tue Mar 4 19:29:04 2003 +++ linux-2.5.64-bk6/net/ipv6/icmp.c Mon Mar 31 12:28:50 2003 @@ -353,7 +353,7 @@ ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1, MSG_DONTWAIT); if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB) - ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-1]++; + ICMP6_STATS_PTR_BH(Icmp6OutDestUnreachs) [type-ICMPV6_DEST_UNREACH]++; ICMP6_INC_STATS_BH(Icmp6OutMsgs); out: icmpv6_xmit_unlock(); @@ -524,7 +524,7 @@ break; case ICMPV6_ECHO_REPLY: - /* we coulnd't care less */ + /* we couldn't care less */ break; case ICMPV6_PKT_TOOBIG: @@ -577,7 +577,7 @@ default: if (net_ratelimit()) - printk(KERN_DEBUG "icmpv6: msg of unkown type\n"); + printk(KERN_DEBUG "icmpv6: msg of unknown type\n"); /* informational */ if (type & ICMPV6_INFOMSG_MASK) diff -urN linux-2.5.64-bk5/net/ipv6/netfilter/ip6table_filter.c linux-2.5.64-bk6/net/ipv6/netfilter/ip6table_filter.c --- linux-2.5.64-bk5/net/ipv6/netfilter/ip6table_filter.c Tue Mar 4 19:28:58 2003 +++ linux-2.5.64-bk6/net/ipv6/netfilter/ip6table_filter.c Mon Mar 31 12:28:50 2003 @@ -81,9 +81,13 @@ } }; -static struct ip6t_table packet_filter -= { { NULL, NULL }, "filter", &initial_table.repl, - FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE }; +static struct ip6t_table packet_filter = { + .name = "filter", + .table = &initial_table.repl, + .valid_hooks = FILTER_VALID_HOOKS, + .lock = RW_LOCK_UNLOCKED, + .me = THIS_MODULE, +}; /* The work comes in here from netfilter.c. */ static unsigned int @@ -116,11 +120,25 @@ return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL); } -static struct nf_hook_ops ip6t_ops[] -= { { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_LOCAL_IN, NF_IP6_PRI_FILTER }, - { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_FORWARD, NF_IP6_PRI_FILTER }, - { { NULL, NULL }, ip6t_local_out_hook, PF_INET6, NF_IP6_LOCAL_OUT, - NF_IP6_PRI_FILTER } +static struct nf_hook_ops ip6t_ops[] = { + { + .hook = ip6t_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_LOCAL_IN, + .priority = NF_IP6_PRI_FILTER, + }, + { + .hook = ip6t_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_FORWARD, + .priority = NF_IP6_PRI_FILTER, + }, + { + .hook = ip6t_local_out_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_LOCAL_OUT, + .priority = NF_IP6_PRI_FILTER, + }, }; /* Default to forward because I got too much mail already. */ diff -urN linux-2.5.64-bk5/net/ipv6/netfilter/ip6table_mangle.c linux-2.5.64-bk6/net/ipv6/netfilter/ip6table_mangle.c --- linux-2.5.64-bk5/net/ipv6/netfilter/ip6table_mangle.c Tue Mar 4 19:29:16 2003 +++ linux-2.5.64-bk6/net/ipv6/netfilter/ip6table_mangle.c Mon Mar 31 12:28:50 2003 @@ -111,9 +111,13 @@ } }; -static struct ip6t_table packet_mangler -= { { NULL, NULL }, "mangle", &initial_table.repl, - MANGLE_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL, THIS_MODULE }; +static struct ip6t_table packet_mangler = { + .name = "mangle", + .table = &initial_table.repl, + .valid_hooks = MANGLE_VALID_HOOKS, + .lock = RW_LOCK_UNLOCKED, + .me = THIS_MODULE, +}; /* The work comes in here from netfilter.c. */ static unsigned int @@ -175,12 +179,37 @@ return ret; } -static struct nf_hook_ops ip6t_ops[] -= { { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_PRE_ROUTING, NF_IP6_PRI_MANGLE }, - { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_IN, NF_IP6_PRI_MANGLE }, - { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_FORWARD, NF_IP6_PRI_MANGLE }, - { { NULL, NULL }, ip6t_local_hook, PF_INET6, NF_IP6_LOCAL_OUT, NF_IP6_PRI_MANGLE }, - { { NULL, NULL }, ip6t_route_hook, PF_INET6, NF_IP6_POST_ROUTING, NF_IP6_PRI_MANGLE } +static struct nf_hook_ops ip6t_ops[] = { + { + .hook = ip6t_route_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_PRE_ROUTING, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6t_local_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_LOCAL_IN, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6t_route_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_FORWARD, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6t_local_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_LOCAL_OUT, + .priority = NF_IP6_PRI_MANGLE, + }, + { + .hook = ip6t_route_hook, + .pf = PF_INET6, + .hooknum = NF_IP6_POST_ROUTING, + .priority = NF_IP6_PRI_MANGLE, + }, }; static int __init init(void) diff -urN linux-2.5.64-bk5/net/ipx/af_ipx.c linux-2.5.64-bk6/net/ipx/af_ipx.c --- linux-2.5.64-bk5/net/ipx/af_ipx.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/ipx/af_ipx.c Mon Mar 31 12:28:50 2003 @@ -2010,7 +2010,7 @@ } static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct ipx_opt *ipxs = ipx_sk(sk); @@ -2070,7 +2070,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; struct ipx_opt *ipxs = ipx_sk(sk); diff -urN linux-2.5.64-bk5/net/irda/af_irda.c linux-2.5.64-bk6/net/irda/af_irda.c --- linux-2.5.64-bk5/net/irda/af_irda.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/irda/af_irda.c Mon Mar 31 12:28:50 2003 @@ -1253,14 +1253,14 @@ } /* - * Function irda_sendmsg (iocb, sock, msg, len, scm) + * Function irda_sendmsg (iocb, sock, msg, len) * * Send message down to TinyTP. This function is used for both STREAM and * SEQPACK services. This is possible since it forces the client to * fragment the message if necessary */ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct irda_sock *self; @@ -1326,14 +1326,13 @@ } /* - * Function irda_recvmsg_dgram (iocb, sock, msg, size, flags, scm) + * Function irda_recvmsg_dgram (iocb, sock, msg, size, flags) * * Try to receive message and copy it to user. The frame is discarded * after being read, regardless of how much the user actually read */ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; struct irda_sock *self = irda_sk(sk); @@ -1380,11 +1379,10 @@ } /* - * Function irda_recvmsg_stream (iocb, sock, msg, size, flags, scm) + * Function irda_recvmsg_stream (iocb, sock, msg, size, flags) */ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; struct irda_sock *self = irda_sk(sk); @@ -1504,14 +1502,14 @@ } /* - * Function irda_sendmsg_dgram (iocb, sock, msg, len, scm) + * Function irda_sendmsg_dgram (iocb, sock, msg, len) * * Send message down to TinyTP for the unreliable sequenced * packet service... * */ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct irda_sock *self; @@ -1570,14 +1568,14 @@ } /* - * Function irda_sendmsg_ultra (iocb, sock, msg, len, scm) + * Function irda_sendmsg_ultra (iocb, sock, msg, len) * * Send message down to IrLMP for the unreliable Ultra * packet service... */ #ifdef CONFIG_IRDA_ULTRA static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct irda_sock *self; diff -urN linux-2.5.64-bk5/net/irda/ircomm/ircomm_core.c linux-2.5.64-bk6/net/irda/ircomm/ircomm_core.c --- linux-2.5.64-bk5/net/irda/ircomm/ircomm_core.c Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/net/irda/ircomm/ircomm_core.c Mon Mar 31 12:28:50 2003 @@ -119,8 +119,10 @@ } else ret = ircomm_open_tsap(self); - if (ret < 0) + if (ret < 0) { + kfree(self); return NULL; + } self->service_type = service_type; self->line = line; diff -urN linux-2.5.64-bk5/net/key/af_key.c linux-2.5.64-bk6/net/key/af_key.c --- linux-2.5.64-bk5/net/key/af_key.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/key/af_key.c Mon Mar 31 12:28:50 2003 @@ -2457,8 +2457,7 @@ } static int pfkey_sendmsg(struct kiocb *kiocb, - struct socket *sock, struct msghdr *msg, int len, - struct scm_cookie *scm) + struct socket *sock, struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct sk_buff *skb = NULL; @@ -2501,7 +2500,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg, int len, - int flags, struct scm_cookie *scm) + int flags) { struct sock *sk = sock->sk; struct sk_buff *skb; diff -urN linux-2.5.64-bk5/net/llc/af_llc.c linux-2.5.64-bk6/net/llc/af_llc.c --- linux-2.5.64-bk5/net/llc/af_llc.c Tue Mar 4 19:28:53 2003 +++ linux-2.5.64-bk6/net/llc/af_llc.c Mon Mar 31 12:28:50 2003 @@ -672,14 +672,12 @@ * @msg: Various user space related information. * @size: Size of user buffer. * @flags: User specified flags. - * @scm: Unknown. * * Copy received data to the socket user. * Returns non-negative upon success, negative otherwise. */ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; @@ -727,13 +725,12 @@ * @sock: Socket to transmit data from. * @msg: Various user related information. * @len: Length of data to transmit. - * @scm: Unknown. * * Transmit data provided by the socket user. * Returns non-negative upon success, negative otherwise. */ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct llc_opt *llc = llc_sk(sk); diff -urN linux-2.5.64-bk5/net/netlink/af_netlink.c linux-2.5.64-bk6/net/netlink/af_netlink.c --- linux-2.5.64-bk5/net/netlink/af_netlink.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/netlink/af_netlink.c Mon Mar 31 12:28:50 2003 @@ -595,10 +595,10 @@ wake_up_interruptible(&nlk->wait); } -static int netlink_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, - struct scm_cookie *scm) +static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, + struct msghdr *msg, int len) { + struct sock_iocb *siocb = kiocb_to_siocb(kiocb); struct sock *sk = sock->sk; struct netlink_opt *nlk = nlk_sk(sk); struct sockaddr_nl *addr=msg->msg_name; @@ -606,10 +606,17 @@ u32 dst_groups; struct sk_buff *skb; int err; + struct scm_cookie scm; if (msg->msg_flags&MSG_OOB) return -EOPNOTSUPP; + if (NULL == siocb->scm) + siocb->scm = &scm; + err = scm_send(sock, msg, siocb->scm); + if (err < 0) + return err; + if (msg->msg_namelen) { if (addr->nl_family != AF_NETLINK) return -EINVAL; @@ -640,7 +647,7 @@ NETLINK_CB(skb).groups = nlk->groups; NETLINK_CB(skb).dst_pid = dst_pid; NETLINK_CB(skb).dst_groups = dst_groups; - memcpy(NETLINK_CREDS(skb), &scm->creds, sizeof(struct ucred)); + memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); /* What can I do? Netlink is asynchronous, so that we will have to save current capabilities to @@ -670,10 +677,12 @@ return err; } -static int netlink_recvmsg(struct kiocb *iocb, struct socket *sock, +static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, struct msghdr *msg, int len, - int flags, struct scm_cookie *scm) + int flags) { + struct sock_iocb *siocb = kiocb_to_siocb(kiocb); + struct scm_cookie scm; struct sock *sk = sock->sk; struct netlink_opt *nlk = nlk_sk(sk); int noblock = flags&MSG_DONTWAIT; @@ -709,12 +718,18 @@ msg->msg_namelen = sizeof(*addr); } - scm->creds = *NETLINK_CREDS(skb); + if (NULL == siocb->scm) { + memset(&scm, 0, sizeof(scm)); + siocb->scm = &scm; + } + siocb->scm->creds = *NETLINK_CREDS(skb); skb_free_datagram(sk, skb); if (nlk->cb && atomic_read(&sk->rmem_alloc) <= sk->rcvbuf / 2) netlink_dump(sk); + scm_recv(sock, msg, siocb->scm, flags); + out: netlink_rcv_wake(sk); return err ? : copied; diff -urN linux-2.5.64-bk5/net/netrom/af_netrom.c linux-2.5.64-bk6/net/netrom/af_netrom.c --- linux-2.5.64-bk5/net/netrom/af_netrom.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/netrom/af_netrom.c Mon Mar 31 12:28:50 2003 @@ -967,7 +967,7 @@ } static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; nr_cb *nr = nr_sk(sk); @@ -1058,8 +1058,7 @@ } static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name; diff -urN linux-2.5.64-bk5/net/packet/af_packet.c linux-2.5.64-bk6/net/packet/af_packet.c --- linux-2.5.64-bk5/net/packet/af_packet.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/packet/af_packet.c Mon Mar 31 12:28:50 2003 @@ -280,8 +280,7 @@ */ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, - struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name; @@ -658,7 +657,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct sockaddr_ll *saddr=(struct sockaddr_ll *)msg->msg_name; @@ -1013,8 +1012,7 @@ */ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, - int flags, struct scm_cookie *scm) + struct msghdr *msg, int len, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb; diff -urN linux-2.5.64-bk5/net/rose/af_rose.c linux-2.5.64-bk6/net/rose/af_rose.c --- linux-2.5.64-bk5/net/rose/af_rose.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/rose/af_rose.c Mon Mar 31 12:28:50 2003 @@ -1026,7 +1026,7 @@ } static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; rose_cb *rose = rose_sk(sk); @@ -1190,8 +1190,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int size, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int size, int flags) { struct sock *sk = sock->sk; rose_cb *rose = rose_sk(sk); diff -urN linux-2.5.64-bk5/net/socket.c linux-2.5.64-bk6/net/socket.c --- linux-2.5.64-bk5/net/socket.c Tue Mar 4 19:29:16 2003 +++ linux-2.5.64-bk6/net/socket.c Mon Mar 31 12:28:50 2003 @@ -78,6 +78,7 @@ #include #include #include +#include #if defined(CONFIG_KMOD) && defined(CONFIG_NET) #include @@ -88,9 +89,9 @@ #endif /* CONFIG_NET_RADIO */ #include +#include #include -#include #include static int sock_no_open(struct inode *irrelevant, struct file *dontcare); @@ -518,13 +519,13 @@ sock->file=NULL; } -static int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size) +static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size) { struct sock_iocb *si = kiocb_to_siocb(iocb); int err; - si->scm = &si->async_scm; si->sock = sock; + si->scm = NULL; si->msg = msg; si->size = size; @@ -532,13 +533,7 @@ if (err) return err; - err = scm_send(sock, msg, si->scm); - if (err >= 0) { - err = sock->ops->sendmsg(iocb, sock, msg, size, si->scm); - if (-EIOCBQUEUED != err) - scm_destroy(si->scm); - } - return err; + return sock->ops->sendmsg(iocb, sock, msg, size); } int sock_sendmsg(struct socket *sock, struct msghdr *msg, int size) @@ -554,14 +549,13 @@ } -int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags) +static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, int flags) { int err; struct sock_iocb *si = kiocb_to_siocb(iocb); si->sock = sock; - si->scm = &si->async_scm; - si->sock = sock; + si->scm = NULL; si->msg = msg; si->size = size; si->flags = flags; @@ -570,13 +564,7 @@ if (err) return err; - memset(si->scm, 0, sizeof(*si->scm)); - - size = sock->ops->recvmsg(iocb, sock, msg, size, flags, si->scm); - if (size >= 0) - scm_recv(sock, msg, si->scm, flags); - - return size; + return sock->ops->recvmsg(iocb, sock, msg, size, flags); } int sock_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) @@ -1545,12 +1533,21 @@ return err; } +/* A couple of helpful macros for getting the address of the 32/64 bit + * fields which are the same type (int / unsigned) on our platforms. + */ +#define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) +#define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) +#define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) + + /* * BSD sendmsg interface */ asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags) { + struct compat_msghdr *msg_compat = (struct compat_msghdr *)msg; struct socket *sock; char address[MAX_SOCK_ADDR]; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; @@ -1560,8 +1557,11 @@ int err, ctl_len, iov_size, total_len; err = -EFAULT; - if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) - goto out; + if (MSG_CMSG_COMPAT & flags) { + if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat)) + return -EFAULT; + } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) + return -EFAULT; sock = sockfd_lookup(fd, &err); if (!sock) @@ -1582,7 +1582,10 @@ } /* This will also move the address data into kernel space */ - err = verify_iovec(&msg_sys, iov, address, VERIFY_READ); + if (MSG_CMSG_COMPAT & flags) { + err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); + } else + err = verify_iovec(&msg_sys, iov, address, VERIFY_READ); if (err < 0) goto out_freeiov; total_len = err; @@ -1592,8 +1595,12 @@ if (msg_sys.msg_controllen > INT_MAX) goto out_freeiov; ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { + if ((MSG_CMSG_COMPAT & flags) && ctl_len) { + err = cmsghdr_from_user_compat_to_kern(&msg_sys, ctl, sizeof(ctl)); + if (err) + goto out_freeiov; + ctl_buf = msg_sys.msg_control; + } else if (ctl_len) { if (ctl_len > sizeof(ctl)) { ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); @@ -1629,6 +1636,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags) { + struct compat_msghdr *msg_compat = (struct compat_msghdr *)msg; struct socket *sock; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack; @@ -1643,9 +1651,12 @@ struct sockaddr *uaddr; int *uaddr_len; - err=-EFAULT; - if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) - goto out; + if (MSG_CMSG_COMPAT & flags) { + if (msghdr_from_user_compat_to_kern(&msg_sys, msg_compat)) + return -EFAULT; + } else + if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) + return -EFAULT; sock = sockfd_lookup(fd, &err); if (!sock) @@ -1670,8 +1681,11 @@ */ uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE); + uaddr_len = COMPAT_NAMELEN(msg); + if (MSG_CMSG_COMPAT & flags) { + err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); + } else + err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE); if (err < 0) goto out_freeiov; total_len=err; @@ -1691,11 +1705,20 @@ if (err < 0) goto out_freeiov; } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); + err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg)); if (err) goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); + if (MSG_CMSG_COMPAT & flags) { + unsigned long ucmsg_ptr; + compat_size_t uclen; + if((unsigned long) msg_sys.msg_control != cmsg_ptr) + cmsg_compat_recvmsg_fixup(&msg_sys, cmsg_ptr); + ucmsg_ptr = ((unsigned long)msg_sys.msg_control); + uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); + err = __put_user(uclen, &msg_compat->msg_controllen); + } else + err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, + &msg->msg_controllen); if (err) goto out_freeiov; err = len; diff -urN linux-2.5.64-bk5/net/unix/af_unix.c linux-2.5.64-bk6/net/unix/af_unix.c --- linux-2.5.64-bk5/net/unix/af_unix.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/unix/af_unix.c Mon Mar 31 12:28:50 2003 @@ -1193,10 +1193,10 @@ * Send AF_UNIX data. */ -static int unix_dgram_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, - struct scm_cookie *scm) +static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, + struct msghdr *msg, int len) { + struct sock_iocb *siocb = kiocb_to_siocb(kiocb); struct sock *sk = sock->sk; struct unix_sock *u = unix_sk(sk); struct sockaddr_un *sunaddr=msg->msg_name; @@ -1206,6 +1206,13 @@ unsigned hash; struct sk_buff *skb; long timeo; + struct scm_cookie tmp_scm; + + if (NULL == siocb->scm) + siocb->scm = &tmp_scm; + err = scm_send(sock, msg, siocb->scm); + if (err < 0) + return err; err = -EOPNOTSUPP; if (msg->msg_flags&MSG_OOB) @@ -1235,9 +1242,9 @@ if (skb==NULL) goto out; - memcpy(UNIXCREDS(skb), &scm->creds, sizeof(struct ucred)); - if (scm->fp) - unix_attach_fds(scm, skb); + memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); + if (siocb->scm->fp) + unix_attach_fds(siocb->scm, skb); skb->h.raw = skb->data; err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); @@ -1317,6 +1324,7 @@ unix_state_runlock(other); other->data_ready(other, len); sock_put(other); + scm_destroy(siocb->scm); return len; out_unlock: @@ -1326,20 +1334,28 @@ out: if (other) sock_put(other); + scm_destroy(siocb->scm); return err; } -static int unix_stream_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, - struct scm_cookie *scm) +static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, + struct msghdr *msg, int len) { + struct sock_iocb *siocb = kiocb_to_siocb(kiocb); struct sock *sk = sock->sk; unix_socket *other = NULL; struct sockaddr_un *sunaddr=msg->msg_name; int err,size; struct sk_buff *skb; int sent=0; + struct scm_cookie tmp_scm; + + if (NULL == siocb->scm) + siocb->scm = &tmp_scm; + err = scm_send(sock, msg, siocb->scm); + if (err < 0) + return err; err = -EOPNOTSUPP; if (msg->msg_flags&MSG_OOB) @@ -1393,9 +1409,9 @@ */ size = min_t(int, size, skb_tailroom(skb)); - memcpy(UNIXCREDS(skb), &scm->creds, sizeof(struct ucred)); - if (scm->fp) - unix_attach_fds(scm, skb); + memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); + if (siocb->scm->fp) + unix_attach_fds(siocb->scm, skb); if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) { kfree_skb(skb); @@ -1414,6 +1430,10 @@ sent+=size; } sock_put(other); + + scm_destroy(siocb->scm); + siocb->scm = NULL; + return sent; pipe_err_free: @@ -1426,6 +1446,8 @@ out_err: if (other) sock_put(other); + scm_destroy(siocb->scm); + siocb->scm = NULL; return sent ? : err; } @@ -1442,8 +1464,10 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, - int flags, struct scm_cookie *scm) + int flags) { + struct sock_iocb *siocb = kiocb_to_siocb(iocb); + struct scm_cookie tmp_scm; struct sock *sk = sock->sk; struct unix_sock *u = unix_sk(sk); int noblock = flags & MSG_DONTWAIT; @@ -1474,12 +1498,16 @@ if (err) goto out_free; - scm->creds = *UNIXCREDS(skb); + if (!siocb->scm) { + siocb->scm = &tmp_scm; + memset(&tmp_scm, 0, sizeof(tmp_scm)); + } + siocb->scm->creds = *UNIXCREDS(skb); if (!(flags & MSG_PEEK)) { if (UNIXCB(skb).fp) - unix_detach_fds(scm, skb); + unix_detach_fds(siocb->scm, skb); } else { @@ -1496,10 +1524,12 @@ */ if (UNIXCB(skb).fp) - scm->fp = scm_fp_dup(UNIXCB(skb).fp); + siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); } err = size; + scm_recv(sock, msg, siocb->scm, flags); + out_free: skb_free_datagram(sk,skb); out: @@ -1545,8 +1575,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, - int flags, struct scm_cookie *scm) + int flags) { + struct sock_iocb *siocb = kiocb_to_siocb(iocb); + struct scm_cookie tmp_scm; struct sock *sk = sock->sk; struct unix_sock *u = unix_sk(sk); struct sockaddr_un *sunaddr=msg->msg_name; @@ -1573,6 +1605,11 @@ * while sleeps in memcpy_tomsg */ + if (!siocb->scm) { + siocb->scm = &tmp_scm; + memset(&tmp_scm, 0, sizeof(tmp_scm)); + } + down(&u->readsem); do @@ -1611,13 +1648,13 @@ if (check_creds) { /* Never glue messages from different writers */ - if (memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) { + if (memcmp(UNIXCREDS(skb), &siocb->scm->creds, sizeof(siocb->scm->creds)) != 0) { skb_queue_head(&sk->receive_queue, skb); break; } } else { /* Copy credentials */ - scm->creds = *UNIXCREDS(skb); + siocb->scm->creds = *UNIXCREDS(skb); check_creds = 1; } @@ -1644,7 +1681,7 @@ skb_pull(skb, chunk); if (UNIXCB(skb).fp) - unix_detach_fds(scm, skb); + unix_detach_fds(siocb->scm, skb); /* put the skb back if we didn't use it up.. */ if (skb->len) @@ -1655,7 +1692,7 @@ kfree_skb(skb); - if (scm->fp) + if (siocb->scm->fp) break; } else @@ -1663,7 +1700,7 @@ /* It is questionable, see note in unix_dgram_recvmsg. */ if (UNIXCB(skb).fp) - scm->fp = scm_fp_dup(UNIXCB(skb).fp); + siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); /* put message back and return */ skb_queue_head(&sk->receive_queue, skb); @@ -1672,6 +1709,7 @@ } while (size); up(&u->readsem); + scm_recv(sock, msg, siocb->scm, flags); out: return copied ? : err; } diff -urN linux-2.5.64-bk5/net/wanrouter/af_wanpipe.c linux-2.5.64-bk6/net/wanrouter/af_wanpipe.c --- linux-2.5.64-bk5/net/wanrouter/af_wanpipe.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/wanrouter/af_wanpipe.c Mon Mar 31 12:28:50 2003 @@ -535,7 +535,7 @@ *===========================================================*/ static int wanpipe_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { wanpipe_opt *wp; struct sock *sk = sock->sk; @@ -1566,8 +1566,7 @@ *===========================================================*/ static int wanpipe_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, int flags, - struct scm_cookie *scm) + struct msghdr *msg, int len, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb; diff -urN linux-2.5.64-bk5/net/x25/af_x25.c linux-2.5.64-bk6/net/x25/af_x25.c --- linux-2.5.64-bk5/net/x25/af_x25.c Mon Mar 31 12:28:46 2003 +++ linux-2.5.64-bk6/net/x25/af_x25.c Mon Mar 31 12:28:50 2003 @@ -917,7 +917,7 @@ } static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, int len, struct scm_cookie *scm) + struct msghdr *msg, int len) { struct sock *sk = sock->sk; struct x25_opt *x25 = x25_sk(sk); @@ -1093,7 +1093,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int size, - int flags, struct scm_cookie *scm) + int flags) { struct sock *sk = sock->sk; struct x25_opt *x25 = x25_sk(sk); diff -urN linux-2.5.64-bk5/sound/isa/als100.c linux-2.5.64-bk6/sound/isa/als100.c --- linux-2.5.64-bk5/sound/isa/als100.c Tue Mar 4 19:28:58 2003 +++ linux-2.5.64-bk6/sound/isa/als100.c Mon Mar 31 12:28:50 2003 @@ -24,11 +24,7 @@ #include #include #include -#ifndef LINUX_ISAPNP_H -#include -#define isapnp_card pci_bus -#define isapnp_dev pci_dev -#endif +#include #include #define SNDRV_GET_ID #include @@ -96,167 +92,124 @@ MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC); struct snd_card_als100 { -#ifdef __ISAPNP__ - struct isapnp_dev *dev; - struct isapnp_dev *devmpu; - struct isapnp_dev *devopl; -#endif /* __ISAPNP__ */ + int dev_no; + struct pnp_dev *dev; + struct pnp_dev *devmpu; + struct pnp_dev *devopl; }; -static snd_card_t *snd_als100_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; - -#ifdef __ISAPNP__ -static struct isapnp_card *snd_als100_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR; -static const struct isapnp_card_id *snd_als100_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR; - -#define ISAPNP_ALS100(_va, _vb, _vc, _device, _audio, _mpu401, _opl) \ - { \ - ISAPNP_CARD_ID(_va, _vb, _vc, _device), \ - devs : { ISAPNP_DEVICE_ID('@', '@', '@', _audio), \ - ISAPNP_DEVICE_ID('@', 'X', '@', _mpu401), \ - ISAPNP_DEVICE_ID('@', 'H', '@', _opl) } \ - } - -static struct isapnp_card_id snd_als100_pnpids[] __devinitdata = { +static struct pnp_card_id snd_als100_pnpids[] __devinitdata = { /* ALS100 - PRO16PNP */ - ISAPNP_ALS100('A','L','S',0x0001,0x0001,0x0001,0x0001), + { .id = "ALS0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" }, } }, /* ALS110 - MF1000 - Digimate 3D Sound */ - ISAPNP_ALS100('A','L','S',0x0110,0x1001,0x1001,0x1001), + { .id = "ALS0110", .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" }, } }, /* ALS120 */ - ISAPNP_ALS100('A','L','S',0x0120,0x2001,0x2001,0x2001), + { .id = "ALS0120", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } }, /* ALS200 */ - ISAPNP_ALS100('A','L','S',0x0200,0x0020,0x0020,0x0001), + { .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" }, } }, /* RTL3000 */ - ISAPNP_ALS100('R','T','L',0x3000,0x2001,0x2001,0x2001), - { ISAPNP_CARD_END, } + { .id = "RTL3000", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } }, + { .id = "", } /* end */ }; -ISAPNP_CARD_TABLE(snd_als100_pnpids); - -#endif /* __ISAPNP__ */ +MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids); #define DRIVER_NAME "snd-card-als100" - -#ifdef __ISAPNP__ -static int __init snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard) +static int __devinit snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard, + struct pnp_card_link *card, + const struct pnp_card_id *id) { - const struct isapnp_card_id *id = snd_als100_isapnp_id[dev]; - struct isapnp_card *card = snd_als100_isapnp_cards[dev]; - struct isapnp_dev *pdev; - - acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL); - if (acard->dev->active) { - acard->dev = NULL; - return -EBUSY; - } - acard->devmpu = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL); - if (acard->devmpu->active) { - acard->dev = acard->devmpu = NULL; - return -EBUSY; - } - acard->devopl = isapnp_find_dev(card, id->devs[2].vendor, id->devs[2].function, NULL); - if (acard->devopl->active) { - acard->dev = acard->devmpu = acard->devopl = NULL; - return -EBUSY; + struct pnp_dev *pdev; + struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table)); + int err; + if (!cfg) + return -ENOMEM; + acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); + if (acard->dev == NULL) { + kfree(cfg); + return -ENODEV; } + acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev); + acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu); pdev = acard->dev; - if (pdev->prepare(pdev)<0) - return -EAGAIN; + pnp_init_resource_table(cfg); + + /* override resources */ if (port[dev] != SNDRV_AUTO_PORT) - isapnp_resource_change(&pdev->resource[0], port[dev], 16); + pnp_resource_change(&cfg->port_resource[0], port[dev], 16); if (dma8[dev] != SNDRV_AUTO_DMA) - isapnp_resource_change(&pdev->dma_resource[0], dma8[dev], - 1); + pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1); if (dma16[dev] != SNDRV_AUTO_DMA) - isapnp_resource_change(&pdev->dma_resource[1], dma16[dev], - 1); + pnp_resource_change(&cfg->dma_resource[1], dma16[dev], 1); if (irq[dev] != SNDRV_AUTO_IRQ) - isapnp_resource_change(&pdev->irq_resource[0], irq[dev], 1); - - if (pdev->activate(pdev)<0) { - printk(KERN_ERR PFX "AUDIO isapnp configure failure\n"); - return -EBUSY; - } - - port[dev] = pdev->resource[0].start; - dma8[dev] = pdev->dma_resource[1].start; - dma16[dev] = pdev->dma_resource[0].start; - irq[dev] = pdev->irq_resource[0].start; + pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); + if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0) + printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n"); + err = pnp_activate_dev(pdev); + if (err < 0) { + printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); + return err; + } + port[dev] = pnp_port_start(pdev, 0); + dma8[dev] = pnp_dma(pdev, 1); + dma16[dev] = pnp_dma(pdev, 0); + irq[dev] = pnp_irq(pdev, 0); pdev = acard->devmpu; - if (pdev == NULL || pdev->prepare(pdev)<0) { - mpu_port[dev] = -1; - return 0; - } - - if (mpu_port[dev] != SNDRV_AUTO_PORT) - isapnp_resource_change(&pdev->resource[0], mpu_port[dev], - 2); - if (mpu_irq[dev] != SNDRV_AUTO_IRQ) - isapnp_resource_change(&pdev->irq_resource[0], mpu_irq[dev], - 1); - - if (pdev->activate(pdev)<0) { - printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n"); - mpu_port[dev] = -1; - acard->devmpu = NULL; + if (pdev != NULL) { + pnp_init_resource_table(cfg); + if (mpu_port[dev] != SNDRV_AUTO_PORT) + pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2); + if (mpu_irq[dev] != SNDRV_AUTO_IRQ) + pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1); + if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0) + printk(KERN_ERR PFX "MPU401 the requested resources are invalid, using auto config\n"); + err = pnp_activate_dev(pdev); + if (err < 0) + goto __mpu_error; + mpu_port[dev] = pnp_port_start(pdev, 0); + mpu_irq[dev] = pnp_irq(pdev, 0); } else { - mpu_port[dev] = pdev->resource[0].start; - mpu_irq[dev] = pdev->irq_resource[0].start; + __mpu_error: + if (pdev) { + pnp_release_card_device(pdev); + printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n"); + } + acard->devmpu = NULL; + mpu_port[dev] = -1; } pdev = acard->devopl; - if (pdev == NULL || pdev->prepare(pdev)<0) { - fm_port[dev] = -1; - return 0; - } - - if (fm_port[dev] != SNDRV_AUTO_PORT) - isapnp_resource_change(&pdev->resource[0], fm_port[dev], 4); - - if (pdev->activate(pdev)<0) { - printk(KERN_ERR PFX "OPL isapnp configure failure\n"); - fm_port[dev] = -1; - acard->devopl = NULL; + if (pdev != NULL) { + pnp_init_resource_table(cfg); + if (fm_port[dev] != SNDRV_AUTO_PORT) + pnp_resource_change(&cfg->port_resource[0], fm_port[dev], 4); + if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0) + printk(KERN_ERR PFX "OPL3 the requested resources are invalid, using auto config\n"); + err = pnp_activate_dev(pdev); + if (err < 0) + goto __fm_error; + fm_port[dev] = pnp_port_start(pdev, 0); } else { - fm_port[dev] = pdev->resource[0].start; + __fm_error: + if (pdev) { + pnp_release_card_device(pdev); + printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n"); + } + acard->devopl = NULL; + fm_port[dev] = -1; } + kfree(cfg); return 0; } -static void snd_card_als100_deactivate(struct snd_card_als100 *acard) -{ - if (acard->dev) { - acard->dev->deactivate(acard->dev); - acard->dev = NULL; - } - if (acard->devmpu) { - acard->devmpu->deactivate(acard->devmpu); - acard->devmpu = NULL; - } - if (acard->devopl) { - acard->devopl->deactivate(acard->devopl); - acard->devopl = NULL; - } -} -#endif /* __ISAPNP__ */ - -static void snd_card_als100_free(snd_card_t *card) -{ - struct snd_card_als100 *acard = (struct snd_card_als100 *)card->private_data; - - if (acard) { -#ifdef __ISAPNP__ - snd_card_als100_deactivate(acard); -#endif /* __ISAPNP__ */ - } -} - -static int __init snd_card_als100_probe(int dev) +static int __init snd_card_als100_probe(int dev, + struct pnp_card_link *pcard, + const struct pnp_card_id *pid) { int error; sb_t *chip; @@ -268,18 +221,11 @@ sizeof(struct snd_card_als100))) == NULL) return -ENOMEM; acard = (struct snd_card_als100 *)card->private_data; - card->private_free = snd_card_als100_free; -#ifdef __ISAPNP__ - if ((error = snd_card_als100_isapnp(dev, acard))) { + if ((error = snd_card_als100_isapnp(dev, acard, pcard, pid))) { snd_card_free(card); return error; } -#else - printk(KERN_ERR PFX "you have to enable PnP support ...\n"); - snd_card_free(card); - return -ENOSYS; -#endif /* __ISAPNP__ */ if ((error = snd_sbdsp_create(card, port[dev], irq[dev], @@ -336,13 +282,12 @@ snd_card_free(card); return error; } - snd_als100_cards[dev] = card; + pnp_set_card_drvdata(pcard, card); return 0; } -#ifdef __ISAPNP__ -static int __init snd_als100_isapnp_detect(struct isapnp_card *card, - const struct isapnp_card_id *id) +static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card, + const struct pnp_card_id *id) { static int dev; int res; @@ -350,9 +295,7 @@ for ( ; dev < SNDRV_CARDS; dev++) { if (!enable[dev]) continue; - snd_als100_isapnp_cards[dev] = card; - snd_als100_isapnp_id[dev] = id; - res = snd_card_als100_probe(dev); + res = snd_card_als100_probe(dev, card, id); if (res < 0) return res; dev++; @@ -360,17 +303,28 @@ } return -ENODEV; } -#endif + +static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard) +{ + snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard); + + snd_card_disconnect(card); + snd_card_free_in_thread(card); +} + +static struct pnp_card_driver als100_pnpc_driver = { + .flags = PNP_DRIVER_RES_DISABLE, + .name = "als100", + .id_table = snd_als100_pnpids, + .probe = snd_als100_pnp_detect, + .remove = __devexit_p(snd_als100_pnp_remove), +}; static int __init alsa_card_als100_init(void) { int cards = 0; -#ifdef __ISAPNP__ - cards += isapnp_probe_cards(snd_als100_pnpids, snd_als100_isapnp_detect); -#else - printk(KERN_ERR PFX "you have to enable ISA PnP support.\n"); -#endif + cards += pnp_register_card_driver(&als100_pnpc_driver); #ifdef MODULE if (!cards) printk(KERN_ERR "no ALS100 based soundcards found\n"); @@ -380,10 +334,7 @@ static void __exit alsa_card_als100_exit(void) { - int dev; - - for (dev = 0; dev < SNDRV_CARDS; dev++) - snd_card_free(snd_als100_cards[dev]); + pnp_unregister_card_driver(&als100_pnpc_driver); } module_init(alsa_card_als100_init) diff -urN linux-2.5.64-bk5/sound/oss/sb_card.c linux-2.5.64-bk6/sound/oss/sb_card.c --- linux-2.5.64-bk5/sound/oss/sb_card.c Tue Mar 4 19:29:29 2003 +++ linux-2.5.64-bk6/sound/oss/sb_card.c Mon Mar 31 12:28:50 2003 @@ -32,9 +32,9 @@ #include "sound_config.h" #include "sb_mixer.h" #include "sb.h" -#ifdef CONFIG_PNP_CARD +#ifdef CONFIG_PNP #include -#endif +#endif /* CONFIG_PNP */ #include "sb_card.h" MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver"); @@ -54,7 +54,7 @@ struct sb_card_config *legacy = NULL; -#ifdef CONFIG_PNP_CARD +#ifdef CONFIG_PNP static int __initdata pnp = 1; /* static int __initdata uart401 = 0; @@ -85,7 +85,7 @@ MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks "\ "(doesn't work with pnp)"); -#ifdef CONFIG_PNP_CARD +#ifdef CONFIG_PNP module_param(pnp, int, 000); MODULE_PARM_DESC(pnp, "Went set to 0 will disable detection using PnP. "\ "Default is 1.\n"); @@ -95,7 +95,7 @@ MODULE_PARM_DESC(uart401, "When set to 1, will attempt to detect and enable"\ "the mpu on some clones"); */ -#endif /* CONFIG_PNP_CARD */ +#endif /* CONFIG_PNP */ /* OSS subsystem card registration shared by PnP and legacy routines */ static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo) @@ -157,7 +157,7 @@ return sb_register_oss(legacy, &sbmo); } -#ifdef CONFIG_PNP_CARD +#ifdef CONFIG_PNP /* Populate the OSS subsystem structures with information from PnP */ static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc) @@ -224,7 +224,7 @@ } /* Probe callback function for the PnP API */ -static int sb_pnp_probe(struct pnp_card *card, const struct pnp_card_id *card_id) +static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_id *card_id) { struct sb_card_config *scc; struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */ @@ -252,14 +252,14 @@ "dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq, scc->conf.dma, scc->conf.dma2); - pnpc_set_drvdata(card, scc); + pnp_set_card_drvdata(card, scc); return sb_register_oss(scc, &sbmo); } -static void sb_pnp_remove(struct pnp_card *card) +static void sb_pnp_remove(struct pnp_card_link *card) { - struct sb_card_config *scc = pnpc_get_drvdata(card); + struct sb_card_config *scc = pnp_get_card_drvdata(card); if(!scc) return; @@ -269,13 +269,13 @@ sb_unload(scc); } -static struct pnpc_driver sb_pnp_driver = { +static struct pnp_card_driver sb_pnp_driver = { .name = "OSS SndBlstr", /* 16 character limit */ .id_table = sb_pnp_card_table, .probe = sb_pnp_probe, .remove = sb_pnp_remove, }; -#endif /* CONFIG_PNP_CARD */ +#endif /* CONFIG_PNP */ static int __init sb_init(void) { @@ -293,9 +293,9 @@ printk(KERN_ERR "sb: Error: At least io, irq, and dma "\ "must be set for legacy cards.\n"); -#ifdef CONFIG_PNP_CARD +#ifdef CONFIG_PNP if(pnp) { - pres = pnpc_register_driver(&sb_pnp_driver); + pres = pnp_register_card_driver(&sb_pnp_driver); } #endif printk(KERN_INFO "sb: Init: Done\n"); @@ -315,8 +315,8 @@ sb_unload(legacy); } -#ifdef CONFIG_PNP_CARD - pnpc_unregister_driver(&sb_pnp_driver); +#ifdef CONFIG_PNP + pnp_unregister_card_driver(&sb_pnp_driver); #endif if (smw_free) { diff -urN linux-2.5.64-bk5/sound/oss/sb_card.h linux-2.5.64-bk6/sound/oss/sb_card.h --- linux-2.5.64-bk5/sound/oss/sb_card.h Tue Mar 4 19:29:20 2003 +++ linux-2.5.64-bk6/sound/oss/sb_card.h Mon Mar 31 12:28:50 2003 @@ -16,7 +16,7 @@ int mpu; }; -#ifdef CONFIG_PNP_CARD +#ifdef CONFIG_PNP /* * SoundBlaster PnP tables and structures.