Import 2.0.22.0.2
authorLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:08 +0000 (23 15:11 -0500)
committerLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:08 +0000 (23 15:11 -0500)
28 files changed:
CREDITS
Documentation/Changes
Makefile
arch/alpha/config.in
arch/alpha/defconfig
drivers/char/serial.c
drivers/net/lance32.c
fs/exec.c
fs/fcntl.c
fs/open.c
fs/pipe.c
fs/select.c
fs/smbfs/proc.c
include/asm-alpha/errno.h
include/asm-alpha/posix_types.h
include/asm-i386/errno.h
include/linux/fs.h
include/linux/in.h
include/linux/posix_types.h
include/linux/sched.h
include/net/tcp.h
kernel/exit.c
kernel/fork.c
net/ipv4/af_inet.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/socket.c
net/unix/af_unix.c

index 4fc5a08..b2eb4aa 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1029,6+1029,13 @@ S: RR #5, 497 Pole Line Road
 S: Thunder Bay, Ontario
 S: CANADA P7C 5M9
 
+N: Yuri Per
+E: yuri@pts.mipt.ru
+D: Some smbfs fixes
+S: Demonstratsii 8-382
+S: Tula 300000
+S: Russia
+
 N: Kai Petzke
 E: wpp@marie.physik.tu-berlin.de
 W: http://physik.tu-berlin.de/~wpp
index 0b04cd0..dc2c254 100644 (file)
@@ -179,7+179,9 @@ or earlier, you will probably get a weird error on shutdown in which
 your computer shuts down fine but "INIT: error reading initrequest" or
 words to that effect scroll across your screen hundreds of times.  To
 fix, upgrade to
-ftp://ftp.cistron.nl/pub/people/miquels/debian/sysvinit-2.62.tar.gz.
+
+ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.64.tar.gz or
+ftp://tsx-11.mit.edu /pub/linux/sources/sbin/sysvinit-2.64.tar.gz
 
    If you're trying to run NCSA httpd, you have to set pre-spawning of
 daemons to zero, as it incorrectly assumes SunOS behavior.  I recommend
index f5800b8..045c3d3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6+1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 1
+SUBLEVEL = 2
 
 ARCH = i386
 
index 0705f8d..436eb43 100644 (file)
@@ -123,6+123,15 @@ if [ "$CONFIG_NET" = "y" ]; then
 fi
 
 mainmenu_option next_comment
+comment 'ISDN subsystem'
+
+tristate 'ISDN support' CONFIG_ISDN
+if [ "$CONFIG_ISDN" != "n" ]; then
+  source drivers/isdn/Config.in
+fi
+endmenu
+
+mainmenu_option next_comment
 comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
 bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
index 052a7c6..2feff67 100644 (file)
@@ -162,6+162,11 @@ CONFIG_DE4X5=y
 # CONFIG_ARCNET is not set
 
 #
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
index 4db019f..2af378b 100644 (file)
@@ -2755,8+2755,9 @@ int rs_init(void)
        serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
        serial_driver.subtype = SERIAL_TYPE_NORMAL;
        serial_driver.init_termios = tty_std_termios;
-       serial_driver.init_termios.c_lflag &=~ (ISIG | ICANON | ECHO);
-       serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
+       serial_driver.init_termios.c_cflag =
+               B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       serial_driver.flags = TTY_DRIVER_REAL_RAW;
        serial_driver.refcount = &serial_refcount;
        serial_driver.table = serial_table;
        serial_driver.termios = serial_termios;
index 953f5ea..2e8fd20 100644 (file)
@@ -789,8+789,8 @@ static struct enet_statistics *
 lance32_get_stats(struct device *dev)
 {
        struct lance32_private *lp = (struct lance32_private *)dev->priv;
-       short ioaddr = dev->base_addr;
-       short saved_addr;
+       int ioaddr = dev->base_addr;
+       unsigned short saved_addr;
        unsigned long flags;
 
        save_flags(flags);
@@ -809,7+809,7 @@ lance32_get_stats(struct device *dev)
 
 static void lance32_set_multicast_list(struct device *dev)
 {
-       short ioaddr = dev->base_addr;
+       int ioaddr = dev->base_addr;
        struct lance32_private *lp = (struct lance32_private *)dev->priv;    
 
        if (dev->flags&IFF_PROMISC) {
index 69f9ed5..d71dd5d 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -114,41+114,34 @@ int unregister_binfmt(struct linux_binfmt * fmt)
 
 int open_inode(struct inode * inode, int mode)
 {
-       int error, fd;
-       struct file *f, **fpp;
+       int fd;
 
        if (!inode->i_op || !inode->i_op->default_file_ops)
                return -EINVAL;
-       f = get_empty_filp();
-       if (!f)
-               return -ENFILE;
-       fd = 0;
-       fpp = current->files->fd;
-       for (;;) {
-               if (!*fpp)
-                       break;
-               if (++fd >= NR_OPEN) {
-                       f->f_count--;
-                       return -EMFILE;
+       fd = get_unused_fd();
+       if (fd >= 0) {
+               struct file * f = get_empty_filp();
+               if (!f) {
+                       put_unused_fd(fd);
+                       return -ENFILE;
                }
-               fpp++;
-       }
-       *fpp = f;
-       f->f_flags = mode;
-       f->f_mode = (mode+1) & O_ACCMODE;
-       f->f_inode = inode;
-       f->f_pos = 0;
-       f->f_reada = 0;
-       f->f_op = inode->i_op->default_file_ops;
-       if (f->f_op->open) {
-               error = f->f_op->open(inode,f);
-               if (error) {
-                       *fpp = NULL;
-                       f->f_count--;
-                       return error;
+               f->f_flags = mode;
+               f->f_mode = (mode+1) & O_ACCMODE;
+               f->f_inode = inode;
+               f->f_pos = 0;
+               f->f_reada = 0;
+               f->f_op = inode->i_op->default_file_ops;
+               if (f->f_op->open) {
+                       int error = f->f_op->open(inode,f);
+                       if (error) {
+                               f->f_count--;
+                               put_unused_fd(fd);
+                               return error;
+                       }
                }
+               current->files->fd[fd] = f;
+               inode->i_count++;
        }
-       inode->i_count++;
        return fd;
 }
 
@@ -399,10+392,45 @@ static void exec_mmap(void)
 }
 
 /*
- * This function flushes out all traces of the currently running executable so
- * that a new one can be started
+ * These functions flushes out all traces of the currently running executable
+ * so that a new one can be started
  */
 
+static inline void flush_old_signals(struct signal_struct *sig)
+{
+       int i;
+       struct sigaction * sa = sig->action;
+
+       for (i=32 ; i != 0 ; i--) {
+               sa->sa_mask = 0;
+               sa->sa_flags = 0;
+               if (sa->sa_handler != SIG_IGN)
+                       sa->sa_handler = NULL;
+               sa++;
+       }
+}
+
+static inline void flush_old_files(struct files_struct * files)
+{
+       unsigned long j;
+
+       j = 0;
+       for (;;) {
+               unsigned long set, i;
+
+               i = j * __NFDBITS;
+               if (i >= NR_OPEN)
+                       break;
+               set = files->close_on_exec.fds_bits[j];
+               files->close_on_exec.fds_bits[j] = 0;
+               j++;
+               for ( ; set ; i++,set >>= 1) {
+                       if (set & 1)
+                               sys_close(i);
+               }
+       }
+}
+
 void flush_old_exec(struct linux_binprm * bprm)
 {
        int i;
@@ -429,16+457,9 @@ void flush_old_exec(struct linux_binprm * bprm)
        if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
            permission(bprm->inode,MAY_READ))
                current->dumpable = 0;
-       for (i=0 ; i<32 ; i++) {
-               current->sig->action[i].sa_mask = 0;
-               current->sig->action[i].sa_flags = 0;
-               if (current->sig->action[i].sa_handler != SIG_IGN)
-                       current->sig->action[i].sa_handler = NULL;
-       }
-       for (i=0 ; i<NR_OPEN ; i++)
-               if (FD_ISSET(i,&current->files->close_on_exec))
-                       sys_close(i);
-       FD_ZERO(&current->files->close_on_exec);
+
+       flush_old_signals(current->sig);
+       flush_old_files(current->files);
 }
 
 /* 
index ee7daee..b5dde21 100644 (file)
 #include <linux/fcntl.h>
 #include <linux/string.h>
 
+#include <asm/bitops.h>
+
 extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
 
 static inline int dupfd(unsigned int fd, unsigned int arg)
 {
-       if (fd >= NR_OPEN || !current->files->fd[fd])
+       struct files_struct * files = current->files;
+
+       if (fd >= NR_OPEN || !files->fd[fd])
                return -EBADF;
        if (arg >= NR_OPEN)
                return -EINVAL;
-       while (arg < NR_OPEN)
-               if (current->files->fd[arg])
-                       arg++;
-               else
-                       break;
-       if (arg >= NR_OPEN)
+       arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
+       if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
                return -EMFILE;
-       FD_CLR(arg, &current->files->close_on_exec);
-       (current->files->fd[arg] = current->files->fd[fd])->f_count++;
+       FD_SET(arg, &files->open_fds);
+       FD_CLR(arg, &files->close_on_exec);
+       (files->fd[arg] = files->fd[fd])->f_count++;
        return arg;
 }
 
index 5877bc2..4d908b0 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
 #include <linux/mm.h>
 
 #include <asm/segment.h>
+#include <asm/bitops.h>
 
 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
 {
@@ -496,11+497,11 @@ asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  * used by symlinks.
  */
-int do_open(const char * filename,int flags,int mode)
+static int do_open(const char * filename,int flags,int mode, int fd)
 {
        struct inode * inode;
        struct file * f;
-       int flag,error,fd;
+       int flag,error;
 
        f = get_empty_filp();
        if (!f)
@@ -533,21+534,9 @@ int do_open(const char * filename,int flags,int mode)
        }
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
-       /*
-        * We have to do this last, because we mustn't export
-        * an incomplete fd to other processes which may share
-        * the same file table with us.
-        */
-       for(fd = 0; fd < NR_OPEN && fd < current->rlim[RLIMIT_NOFILE].rlim_cur; fd++) {
-               if (!current->files->fd[fd]) {
-                       current->files->fd[fd] = f;
-                       FD_CLR(fd,&current->files->close_on_exec);
-                       return fd;
-               }
-       }
-       error = -EMFILE;
-       if (f->f_op && f->f_op->release)
-               f->f_op->release(inode,f);
+       current->files->fd[fd] = f;
+       return 0;
+
 cleanup_all:
        if (f->f_mode & FMODE_WRITE)
                put_write_access(inode);
@@ -558,16+547,44 @@ cleanup_file:
        return error;
 }
 
+/*
+ * Find a empty file descriptor entry, and mark it busy
+ */
+int get_unused_fd(void)
+{
+       int fd;
+       struct files_struct * files = current->files;
+
+       fd = find_first_zero_bit(&files->open_fds, NR_OPEN);
+       if (fd < current->rlim[RLIMIT_NOFILE].rlim_cur) {
+               FD_SET(fd, &files->open_fds);
+               FD_CLR(fd, &files->close_on_exec);
+               return fd;
+       }
+       return -EMFILE;
+}
+
+inline void put_unused_fd(int fd)
+{
+       FD_CLR(fd, &current->files->open_fds);
+}
+
 asmlinkage int sys_open(const char * filename,int flags,int mode)
 {
        char * tmp;
-       int error;
+       int fd, error;
 
+       fd = get_unused_fd();
+       if (fd < 0)
+               return fd;
        error = getname(filename, &tmp);
-       if (error)
-               return error;
-       error = do_open(tmp,flags,mode);
-       putname(tmp);
+       if (!error) {
+               error = do_open(tmp,flags,mode, fd);
+               putname(tmp);
+               if (!error)
+                       return fd;
+       }
+       put_unused_fd(fd);
        return error;
 }
 
@@ -610,16+627,20 @@ int close_fp(struct file *filp)
 }
 
 asmlinkage int sys_close(unsigned int fd)
-{      
+{
+       int error;
        struct file * filp;
-
-       if (fd >= NR_OPEN)
-               return -EBADF;
-       FD_CLR(fd, &current->files->close_on_exec);
-       if (!(filp = current->files->fd[fd]))
-               return -EBADF;
-       current->files->fd[fd] = NULL;
-       return (close_fp (filp));
+       struct files_struct * files;
+
+       files = current->files;
+       error = -EBADF;
+       if (fd < NR_OPEN && (filp = files->fd[fd]) != NULL) {
+               put_unused_fd(fd);
+               FD_CLR(fd, &files->close_on_exec);
+               files->fd[fd] = NULL;
+               error = close_fp(filp);
+       }
+       return error;
 }
 
 /*
index cb8c6ed..0d8277c 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -414,45+414,58 @@ struct inode_operations pipe_inode_operations = {
 int do_pipe(int *fd)
 {
        struct inode * inode;
-       struct file *f[2];
+       struct file *f1, *f2;
+       int error;
        int i,j;
 
+       error = ENFILE;
+       f1 = get_empty_filp();
+       if (!f1)
+               goto no_files;
+
+       f2 = get_empty_filp();
+       if (!f2)
+               goto close_f1;
+
        inode = get_pipe_inode();
        if (!inode)
-               return -ENFILE;
-
-       for(j=0 ; j<2 ; j++)
-               if (!(f[j] = get_empty_filp()))
-                       break;
-       if (j < 2) {
-               iput(inode);
-               iput(inode);
-               if (j)
-                       f[0]->f_count--;
-               return -ENFILE;
-       }
-       j=0;
-       for(i=0;j<2 && i<NR_OPEN && i<current->rlim[RLIMIT_NOFILE].rlim_cur;i++)
-               if (!current->files->fd[i]) {
-                       current->files->fd[ fd[j]=i ] = f[j];
-                       j++;
-               }
-       if (j<2) {
-               iput(inode);
-               iput(inode);
-               f[0]->f_count--;
-               f[1]->f_count--;
-               if (j)
-                       current->files->fd[fd[0]] = NULL;
-               return -EMFILE;
-       }
-       f[0]->f_inode = f[1]->f_inode = inode;
-       f[0]->f_pos = f[1]->f_pos = 0;
-       f[0]->f_flags = O_RDONLY;
-       f[0]->f_op = &read_pipe_fops;
-       f[0]->f_mode = 1;               /* read */
-       f[1]->f_flags = O_WRONLY;
-       f[1]->f_op = &write_pipe_fops;
-       f[1]->f_mode = 2;               /* write */
+               goto close_f12;
+
+       error = get_unused_fd();
+       if (error < 0)
+               goto close_f12_inode;
+       i = error;
+
+       error = get_unused_fd();
+       if (error < 0)
+               goto close_f12_inode_i;
+       j = error;
+
+       f1->f_inode = f2->f_inode = inode;
+       /* read file */
+       f1->f_pos = f2->f_pos = 0;
+       f1->f_flags = O_RDONLY;
+       f1->f_op = &read_pipe_fops;
+       f1->f_mode = 1;
+       /* write file */
+       f2->f_flags = O_WRONLY;
+       f2->f_op = &write_pipe_fops;
+       f2->f_mode = 2;
+       current->files->fd[i] = f1;
+       current->files->fd[j] = f2;
+       fd[0] = i;
+       fd[1] = j;
        return 0;
+
+close_f12_inode_i:
+       put_unused_fd(i);
+close_f12_inode:
+       inode->i_count--;
+       iput(inode);
+close_f12:
+       f2->f_count--;
+close_f1:
+       f1->f_count--;
+no_files:
+       return error;   
 }
index 98a7ddd..3d39e18 100644 (file)
@@ -92,11+92,13 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
        int i,j;
        int max = -1;
 
-       for (j = 0 ; j < __FDSET_INTS ; j++) {
+       j = 0;
+       for (;;) {
                i = j * __NFDBITS;
                if (i >= n)
                        break;
                set = in->fds_bits[j] | out->fds_bits[j] | ex->fds_bits[j];
+               j++;
                for ( ; set ; i++,set >>= 1) {
                        if (i >= n)
                                goto end_check;
@@ -113,9+115,6 @@ end_check:
        n = max + 1;
        if(!(entry = (struct select_table_entry*) __get_free_page(GFP_KERNEL)))
                return -ENOMEM;
-       FD_ZERO(res_in);
-       FD_ZERO(res_out);
-       FD_ZERO(res_ex);
        count = 0;
        wait_table.nr = 0;
        wait_table.entry = entry;
@@ -153,51+152,79 @@ repeat:
 /*
  * We do a VERIFY_WRITE here even though we are only reading this time:
  * we'll write to it eventually..
+ *
+ * Use "int" accesses to let user-mode fd_set's be int-aligned.
  */
-static int __get_fd_set(int nr, unsigned int * fs_pointer, fd_set * fdset)
+static int __get_fd_set(unsigned long nr, int * fs_pointer, int * fdset)
 {
-       int error, i;
-       unsigned int * tmp;
-
-       FD_ZERO(fdset);
-       if (!fs_pointer)
-               return 0;
-       error = verify_area(VERIFY_WRITE,fs_pointer,sizeof(fd_set));
-       if (error)
+       /* round up nr to nearest "int" */
+       nr = (nr + 8*sizeof(int)-1) / (8*sizeof(int));
+       if (fs_pointer) {
+               int error = verify_area(VERIFY_WRITE,fs_pointer,nr*sizeof(int));
+               if (!error) {
+                       while (nr) {
+                               *fdset = get_user(fs_pointer);
+                               nr--;
+                               fs_pointer++;
+                               fdset++;
+                       }
+               }
                return error;
-       tmp = fdset->fds_bits;
-       for (i = __FDSET_INTS; i > 0; i--) {
-               if (nr <= 0)
-                       break;
-               *tmp = get_user(fs_pointer);
-               tmp++;
-               fs_pointer++;
-               nr -= 8 * sizeof(unsigned int);
+       }
+       while (nr) {
+               *fdset = 0;
+               nr--;
+               fdset++;
        }
        return 0;
 }
 
-static void __set_fd_set(int nr, unsigned int * fs_pointer, unsigned int * fdset)
+static void __set_fd_set(long nr, int * fs_pointer, int * fdset)
 {
-       int i;
-
        if (!fs_pointer)
                return;
-       for (i = __FDSET_INTS; i > 0; i--) {
-               if (nr <= 0)
-                       break;
+       while (nr >= 0) {
                put_user(*fdset, fs_pointer);
+               nr -= 8 * sizeof(int);
                fdset++;
                fs_pointer++;
-               nr -= 8 * sizeof(unsigned int);
        }
 }
 
+/* We can do long accesses here, kernel fdsets are always long-aligned */
+static inline void __zero_fd_set(long nr, unsigned long * fdset)
+{
+       while (nr >= 0) {
+               *fdset = 0;
+               nr -= 8 * sizeof(unsigned long);
+               fdset++;
+       }
+}              
+
+/*
+ * Due to kernel stack usage, we use a _limited_ fd_set type here, and once
+ * we really start supporting >256 file descriptors we'll probably have to
+ * allocate the kernel fd_set copies dynamically.. (The kernel select routines
+ * are careful to touch only the defined low bits of any fd_set pointer, this
+ * is important for performance too).
+ *
+ * Note a few subtleties: we use "long" for the dummy, not int, and we do a
+ * subtract by 1 on the nr of file descriptors. The former is better for
+ * machines with long > int, and the latter allows us to test the bit count
+ * against "zero or positive", which can mostly be just a sign bit test..
+ */
+typedef struct {
+       unsigned long dummy[NR_OPEN/(8*(sizeof(unsigned long)))];
+} limited_fd_set;
+
 #define get_fd_set(nr,fsp,fdp) \
-__get_fd_set(nr, (unsigned int *) (fsp), fdp)
+__get_fd_set(nr, (int *) (fsp), (int *) (fdp))
 
 #define set_fd_set(nr,fsp,fdp) \
-__set_fd_set(nr, (unsigned int *) (fsp), (unsigned int *) (fdp))
+__set_fd_set((nr)-1, (int *) (fsp), (int *) (fdp))
+
+#define zero_fd_set(nr,fdp) \
+__zero_fd_set((nr)-1, (unsigned long *) (fdp))
 
 /*
  * We can actually return ERESTARTSYS instead of EINTR, but I'd
@@ -209,31+236,41 @@ __set_fd_set(nr, (unsigned int *) (fsp), (unsigned int *) (fdp))
  */
 asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
 {
-       int i;
-       fd_set res_in, in;
-       fd_set res_out, out;
-       fd_set res_ex, ex;
+       int error;
+       limited_fd_set res_in, in;
+       limited_fd_set res_out, out;
+       limited_fd_set res_ex, ex;
        unsigned long timeout;
 
+       error = -EINVAL;
        if (n < 0)
-               return -EINVAL;
+               goto out;
        if (n > NR_OPEN)
                n = NR_OPEN;
-       if ((i = get_fd_set(n, inp, &in)) ||
-           (i = get_fd_set(n, outp, &out)) ||
-           (i = get_fd_set(n, exp, &ex))) return i;
+       if ((error = get_fd_set(n, inp, &in)) ||
+           (error = get_fd_set(n, outp, &out)) ||
+           (error = get_fd_set(n, exp, &ex))) goto out;
        timeout = ~0UL;
        if (tvp) {
-               i = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
-               if (i)
-                       return i;
+               error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
+               if (error)
+                       goto out;
                timeout = ROUND_UP(get_user(&tvp->tv_usec),(1000000/HZ));
                timeout += get_user(&tvp->tv_sec) * (unsigned long) HZ;
                if (timeout)
                        timeout += jiffies + 1;
        }
+       zero_fd_set(n, &res_in);
+       zero_fd_set(n, &res_out);
+       zero_fd_set(n, &res_ex);
        current->timeout = timeout;
-       i = do_select(n, &in, &out, &ex, &res_in, &res_out, &res_ex);
+       error = do_select(n,
+               (fd_set *) &in,
+               (fd_set *) &out,
+               (fd_set *) &ex,
+               (fd_set *) &res_in,
+               (fd_set *) &res_out,
+               (fd_set *) &res_ex);
        timeout = current->timeout - jiffies - 1;
        current->timeout = 0;
        if ((long) timeout < 0)
@@ -244,12+281,17 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct
                timeout *= (1000000/HZ);
                put_user(timeout, &tvp->tv_usec);
        }
-       if (i < 0)
-               return i;
-       if (!i && (current->signal & ~current->blocked))
-               return -ERESTARTNOHAND;
+       if (error < 0)
+               goto out;
+       if (!error) {
+               error = -ERESTARTNOHAND;
+               if (current->signal & ~current->blocked)
+                       goto out;
+               error = 0;
+       }
        set_fd_set(n, inp, &res_in);
        set_fd_set(n, outp, &res_out);
        set_fd_set(n, exp, &res_ex);
-       return i;
+out:
+       return error;
 }
index 62106a0..197aa33 100644 (file)
@@ -3,6+3,7 @@
  *
  *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
  *
+ *  28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per
  */
 
 #include <linux/config.h>
@@ -1152,6+1153,7 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
         int info_level = 1;
 
        char *p;
+       char *lastname;
        int i;
        int first, total_count;
         struct smb_dirent *current_entry;
@@ -1171,9+1173,15 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
         int ff_dir_handle=0;
         int loop_count = 0;
 
-       int dirlen = strlen(SMB_FINFO(dir)->path);
-       char mask[dirlen + 5];
+       int dirlen = strlen(SMB_FINFO(dir)->path) + 3;
+       char *mask;
 
+       mask = smb_kmalloc(dirlen, GFP_KERNEL);
+       if (mask == NULL)
+       {
+               printk("smb_proc_readdir_long: Memory allocation failed\n");
+               return -ENOMEM;
+       }
        strcpy(mask, SMB_FINFO(dir)->path);
        strcat(mask, "\\*");
 
@@ -1297,22+1305,37 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
                 p = resp_data;
 
                 /* we might need the lastname for continuations */
+               lastname = "";
                 if (ff_lastname > 0)
                 {
                         switch(info_level)
                         {
                         case 260:
-                                ff_resume_key =0;
-                                strcpy(mask,p+ff_lastname+94);
+                               lastname = p + ff_lastname + 94;
+                               ff_resume_key = 0;
                                 break;
                         case 1:
-                                strcpy(mask,p + ff_lastname + 1);
+                               lastname = p + ff_lastname + 1;
                                 ff_resume_key = 0;
                                 break;
                         }
                 }
-                else
-                        strcpy(mask,"");
+  
+               /* Increase size of mask, if it is too small */
+               i = strlen(lastname) + 1;
+               if (i > dirlen)
+               {
+                       smb_kfree_s(mask,  0);
+                       dirlen = i;
+                       mask = smb_kmalloc(dirlen, GFP_KERNEL);
+                       if (mask == NULL)
+                       {
+                               printk("smb_proc_readdir_long: Memory allocation failed\n");
+                               result = -ENOMEM;
+                               break;
+                       }
+                       strcpy(mask, lastname);
+               }
   
                /* Now we are ready to parse smb directory entries. */
                
@@ -1355,6+1378,9 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
         }
 
  finished:
+       if (mask != NULL)
+               smb_kfree_s(mask,  0);
+
         if (resp_data != NULL) {
                 smb_kfree_s(resp_data,  0);
                 resp_data = NULL;
index 560a69d..3641c34 100644 (file)
 #define        ENOANO          100     /* No anode */
 #define        EBADRQC         101     /* Invalid request code */
 #define        EBADSLT         102     /* Invalid slot */
-#if 0
-#define        EDEADLOCK       103     /* File locking deadlock error */
-#endif
+
+#define        EDEADLOCK       EDEADLK
+
 #define        EBFONT          104     /* Bad font file format */
 #define        ENONET          105     /* Machine is not on the network */
 #define        ENOLINK         106     /* Link has been severed */
index a12d5c0..3311ada 100644 (file)
@@ -74,18+74,18 @@ static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
 #undef __FD_ZERO
 static __inline__ void __FD_ZERO(__kernel_fd_set *p)
 {
-       unsigned int *tmp = p->fds_bits;
+       unsigned long *tmp = p->fds_bits;
        int i;
 
-       if (__builtin_constant_p(__FDSET_INTS)) {
-               switch (__FDSET_INTS) {
+       if (__builtin_constant_p(__FDSET_LONGS)) {
+               switch (__FDSET_LONGS) {
                        case 8:
                                tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
                                tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
                                return;
                }
        }
-       i = __FDSET_INTS;
+       i = __FDSET_LONGS;
        while (i) {
                i--;
                *tmp = 0;
index 1e0f642..1936cb7 100644 (file)
 #define        ENOANO          55      /* No anode */
 #define        EBADRQC         56      /* Invalid request code */
 #define        EBADSLT         57      /* Invalid slot */
-#if 0
-#define        EDEADLOCK       58      /* File locking deadlock error */
-#endif
+
+#define        EDEADLOCK       EDEADLK
+
 #define        EBFONT          59      /* Bad font file format */
 #define        ENOSTR          60      /* Device not a stream */
 #define        ENODATA         61      /* No data available */
index 014d0ad..c52b8b4 100644 (file)
@@ -623,6+623,8 @@ extern struct inode * get_empty_inode(void);
 extern void insert_inode_hash(struct inode *);
 extern void clear_inode(struct inode *);
 extern struct inode * get_pipe_inode(void);
+extern int get_unused_fd(void);
+extern void put_unused_fd(int);
 extern struct file * get_empty_filp(void);
 extern int close_fp(struct file *filp);
 extern struct buffer_head * get_hash_table(kdev_t dev, int block, int size);
index f839f98..10da486 100644 (file)
@@ -101,7+101,7 @@ struct sockaddr_in {
 #define        INADDR_BROADCAST        ((unsigned long int) 0xffffffff)
 
 /* Address indicating an error return. */
-#define        INADDR_NONE             0xffffffff
+#define        INADDR_NONE             ((unsigned long int) 0xffffffff)
 
 /* Network number for local host loopback. */
 #define        IN_LOOPBACKNET          127
index d3dfbb0..d3ceb0b 100644 (file)
  * use the ones here. 
  */
 #undef __NFDBITS
-#define __NFDBITS      (8 * sizeof(unsigned int))
+#define __NFDBITS      (8 * sizeof(unsigned long))
 
 #undef __FD_SETSIZE
 #define __FD_SETSIZE   1024
 
-#undef __FDSET_INTS
-#define __FDSET_INTS   (__FD_SETSIZE/__NFDBITS)
+#undef __FDSET_LONGS
+#define __FDSET_LONGS  (__FD_SETSIZE/__NFDBITS)
 
 #undef __FDELT
 #define        __FDELT(d)      ((d) / __NFDBITS)
 
 #undef __FDMASK
-#define        __FDMASK(d)     (1 << ((d) % __NFDBITS))
+#define        __FDMASK(d)     (1UL << ((d) % __NFDBITS))
 
 typedef struct {
-       unsigned int fds_bits [__FDSET_INTS];
+       unsigned long fds_bits [__FDSET_LONGS];
 } __kernel_fd_set;
 
 #include <asm/posix_types.h>
index 14a4494..eaa4e93 100644 (file)
@@ -108,20+108,18 @@ extern void trap_init(void);
 
 asmlinkage void schedule(void);
 
-/* ??? */
+/* Open file table structure */
 struct files_struct {
-       /* ??? */
        int count;
-       /* bit mask to close fds on exec */
        fd_set close_on_exec;
-       /* do we have at most NR_OPEN available fds? I assume fd i maps into
-        * each open file */    
+       fd_set open_fds;
        struct file * fd[NR_OPEN];
 };
 
 #define INIT_FILES { \
        1, \
        { { 0, } }, \
+       { { 0, } }, \
        { NULL, } \
 }
 
index 5329e46..0977df9 100644 (file)
@@ -174,22+174,6 @@ extern void tcp_reset_xmit_timer(struct sock *, int, unsigned long);
 extern void tcp_delack_timer(unsigned long);
 extern void tcp_retransmit_timer(unsigned long);
 
-/*
- *     Default sequence number picking algorithm.
- *     As close as possible to RFC 793, which
- *     suggests using a 250kHz clock.
- *     Further reading shows this assumes 2MB/s networks.
- *     For 10MB/s ethernet, a 1MHz clock is appropriate.
- *     That's funny, Linux has one built in!  Use it!
- */
-
-static inline u32 tcp_init_seq(void)
-{
-       struct timeval tv;
-       do_gettimeofday(&tv);
-       return tv.tv_usec+tv.tv_sec*1000000;
-}
-
 static __inline__ int tcp_old_window(struct sock * sk)
 {
        return sk->window - (sk->acked_seq - sk->lastwin_seq);
index 07a9a88..f233851 100644 (file)
@@ -393,6+393,26 @@ static inline void forget_original_parent(struct task_struct * father)
        }
 }
 
+static inline void close_files(struct files_struct * files)
+{
+       int i, j;
+
+       j = 0;
+       for (;;) {
+               unsigned long set = files->open_fds.fds_bits[j];
+               i = j * __NFDBITS;
+               j++;
+               if (i >= NR_OPEN)
+                       break;
+               while (set) {
+                       if (set & 1)
+                               close_fp(files->fd[i]);
+                       i++;
+                       set >>= 1;
+               }
+       }
+}
+
 static inline void __exit_files(struct task_struct *tsk)
 {
        struct files_struct * files = tsk->files;
@@ -400,14+420,7 @@ static inline void __exit_files(struct task_struct *tsk)
        if (files) {
                tsk->files = NULL;
                if (!--files->count) {
-                       int i;
-                       for (i=0 ; i<NR_OPEN ; i++) {
-                               struct file * filp = files->fd[i];
-                               if (!filp)
-                                       continue;
-                               files->fd[i] = NULL;
-                               close_fp(filp);
-                       }
+                       close_files(files);
                        kfree(files);
                }
        }
index 4f06b65..723e424 100644 (file)
@@ -160,22+160,33 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
 static inline int copy_files(unsigned long clone_flags, struct task_struct * tsk)
 {
        int i;
+       struct files_struct *oldf, *newf;
+       struct file **old_fds, **new_fds;
 
+       oldf = current->files;
        if (clone_flags & CLONE_FILES) {
-               current->files->count++;
+               oldf->count++;
                return 0;
        }
-       tsk->files = kmalloc(sizeof(*tsk->files), GFP_KERNEL);
-       if (!tsk->files)
+
+       newf = kmalloc(sizeof(*newf), GFP_KERNEL);
+       tsk->files = newf;
+       if (!newf)
                return -1;
-       tsk->files->count = 1;
-       memcpy(&tsk->files->close_on_exec, &current->files->close_on_exec,
-               sizeof(tsk->files->close_on_exec));
-       for (i = 0; i < NR_OPEN; i++) {
-               struct file * f = current->files->fd[i];
+                       
+       newf->count = 1;
+       newf->close_on_exec = oldf->close_on_exec;
+       newf->open_fds = oldf->open_fds;
+
+       old_fds = oldf->fd;
+       new_fds = newf->fd;
+       for (i = NR_OPEN; i != 0; i--) {
+               struct file * f = *old_fds;
+               old_fds++;
+               *new_fds = f;
+               new_fds++;
                if (f)
                        f->f_count++;
-               tsk->files->fd[i] = f;
        }
        return 0;
 }
index f1bc1bf..4308398 100644 (file)
@@ -926,7+926,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
                         *      Reuse ?
                         */
                         
-                       if (!sk2->dead)
+                       if (!sk2->reuse || sk2->state==TCP_LISTEN)
                        {
                                sti();
                                return(-EADDRINUSE);
index aee1fb8..a751fc9 100644 (file)
  *                                     improvement.
  *     Stefan Magdalinski      :       adjusted tcp_readable() to fix FIONREAD
  *     Willy Konynenberg       :       Transparent proxying support.
+ *             Theodore Ts'o   :       Do secure TCP sequence numbers.
  *                                     
  * To Fix:
  *             Fast path the code. Two things here - fix the window calculation
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
+#include <linux/random.h>
 
 #include <net/icmp.h>
 #include <net/tcp.h>
@@ -1886,6+1888,36 @@ no_listen:
        goto out;
 }
 
+/*
+ * Check that a TCP address is unique, don't allow multiple
+ * connects to/from the same address
+ */
+static int tcp_unique_address(u32 saddr, u16 snum, u32 daddr, u16 dnum)
+{
+       int retval = 1;
+       struct sock * sk;
+
+       /* Make sure we are allowed to connect here. */
+       cli();
+       for (sk = tcp_prot.sock_array[snum & (SOCK_ARRAY_SIZE -1)];
+                       sk != NULL; sk = sk->next)
+       {
+               /* hash collision? */
+               if (sk->num != snum)
+                       continue;
+               if (sk->saddr != saddr)
+                       continue;
+               if (sk->daddr != daddr)
+                       continue;
+               if (sk->dummy_th.dest != dnum)
+                       continue;
+               retval = 0;
+               break;
+       }
+       sti();
+       return retval;
+}
+
 
 /*
  *     This will initiate an outgoing connection.
@@ -1921,7+1953,7 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
         *      connect() to INADDR_ANY means loopback (BSD'ism).
         */
 
-       if(usin->sin_addr.s_addr==INADDR_ANY)
+       if (usin->sin_addr.s_addr==INADDR_ANY)
                usin->sin_addr.s_addr=ip_my_addr();
 
        /*
@@ -1931,27+1963,26 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
        if ((atype=ip_chk_addr(usin->sin_addr.s_addr)) == IS_BROADCAST || atype==IS_MULTICAST)
                return -ENETUNREACH;
 
+       if (!tcp_unique_address(sk->saddr, sk->num, usin->sin_addr.s_addr, usin->sin_port))
+               return -EADDRNOTAVAIL;
+
        lock_sock(sk);
        sk->daddr = usin->sin_addr.s_addr;
-       sk->write_seq = tcp_init_seq();
-       sk->window_seq = sk->write_seq;
-       sk->rcv_ack_seq = sk->write_seq -1;
+
        sk->rcv_ack_cnt = 1;
        sk->err = 0;
        sk->dummy_th.dest = usin->sin_port;
-       release_sock(sk);
 
        buff = sock_wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
        if (buff == NULL)
        {
+               release_sock(sk);
                return(-ENOMEM);
        }
-       lock_sock(sk);
        buff->sk = sk;
        buff->free = 0;
        buff->localroute = sk->localroute;
 
-
        /*
         *      Put in the IP header and routing stuff.
         */
@@ -1968,6+1999,15 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
                sk->saddr = rt->rt_src;
        sk->rcv_saddr = sk->saddr;
 
+       /*
+        * Set up our outgoing TCP sequence number
+        */
+       sk->write_seq = secure_tcp_sequence_number(sk->saddr, sk->daddr,
+                                                  sk->dummy_th.source,
+                                                  usin->sin_port);
+       sk->window_seq = sk->write_seq;
+       sk->rcv_ack_seq = sk->write_seq -1;
+
        t1 = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr));
 
        memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
index dbc624e..ef2bd0a 100644 (file)
  *             Eric Schenk     :       Skip fast retransmit on small windows.
  *             Eric schenk     :       Fixes to retransmission code to
  *                             :       avoid extra retransmission.
+ *             Theodore Ts'o   :       Do secure TCP sequence numbers.
  */
 
 #include <linux/config.h>
+#include <linux/types.h>
+#include <linux/random.h>
 #include <net/tcp.h>
 
 /*
@@ -208,7+211,17 @@ static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, u32 end_seq,
         *      from the far end, but sometimes it means the far end lost
         *      an ACK we sent, so we better send an ACK.
         */
-       tcp_send_ack(sk);
+       /*
+        *      BEWARE! Unconditional answering by ack to out-of-window ack
+        *      can result in infinite exchange of empty acks.
+        *      This check cures bug, found by Michiel Boland, but
+        *      not another possible cases.
+        *      If we are in TCP_TIME_WAIT, we have already received
+        *      FIN, so that our peer need not window update. If our
+        *      ACK were lost, peer would retransmit his FIN anyway. --ANK
+        */
+       if (sk->state != TCP_TIME_WAIT || ntohl(th->seq) != end_seq)
+               tcp_send_ack(sk);
 }
 
 /*
@@ -1722,6+1735,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        struct tcphdr *th;
        struct sock *sk;
        int syn_ok=0;
+       __u32 seq;
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
        int r;
 #endif
@@ -1859,10+1873,12 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                        }
                
                        /*      
-                        *      Guess we need to make a new socket up 
+                        *      Guess we need to make a new socket up
                         */
-               
-                       tcp_conn_request(sk, skb, daddr, saddr, opt, dev, tcp_init_seq());
+                       seq = secure_tcp_sequence_number(saddr, daddr,
+                                                        skb->h.th->dest,
+                                                        skb->h.th->source);
+                       tcp_conn_request(sk, skb, daddr, saddr, opt, dev, seq);
                
                        /*
                         *      Now we have several options: In theory there is nothing else
index 6f495a0..44a9aae 100644 (file)
@@ -172,36+172,31 @@ int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen)
 static int get_fd(struct inode *inode)
 {
        int fd;
-       struct file *file;
 
        /*
         *      Find a file descriptor suitable for return to the user. 
         */
 
-       file = get_empty_filp();
-       if (!file) 
-               return(-1);
+       fd = get_unused_fd();
+       if (fd >= 0) {
+               struct file *file = get_empty_filp();
 
-       for (fd = 0; fd < NR_OPEN; ++fd)
-               if (!current->files->fd[fd]) 
-                       break;
-       if (fd == NR_OPEN) 
-       {
-               file->f_count = 0;
-               return(-1);
-       }
+               if (!file) {
+                       put_unused_fd(fd);
+                       return -ENFILE;
+               }
 
-       FD_CLR(fd, &current->files->close_on_exec);
                current->files->fd[fd] = file;
-       file->f_op = &socket_file_ops;
-       file->f_mode = 3;
-       file->f_flags = O_RDWR;
-       file->f_count = 1;
-       file->f_inode = inode;
-       if (inode) 
-               inode->i_count++;
-       file->f_pos = 0;
-       return(fd);
+               file->f_op = &socket_file_ops;
+               file->f_mode = 3;
+               file->f_flags = O_RDWR;
+               file->f_count = 1;
+               file->f_inode = inode;
+               if (inode) 
+                       inode->i_count++;
+               file->f_pos = 0;
+       }
+       return fd;
 }
 
 
index 481ecac..ff86725 100644 (file)
@@ -710,10+710,9 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
        int num=cmsg->cmsg_len-sizeof(struct cmsghdr);
        int i;
        int *fdp=(int *)cmsg->cmsg_data;
-       num/=4; /* Odd bytes are forgotten in BSD not errored */
-       
 
-       if(num>=UNIX_MAX_FD)
+       num /= sizeof(int);     /* Odd bytes are forgotten in BSD not errored */
+       if (num >= UNIX_MAX_FD)
                return -EINVAL;
        
        /*
@@ -728,9+727,9 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
 #if 0
                printk("testing  fd %d\n", fd);
 #endif
-               if(fd < 0|| fd >=NR_OPEN)
+               if (fd < 0 || fd >= NR_OPEN)
                        return -EBADF;
-               if(current->files->fd[fd]==NULL)
+               if (current->files->fd[fd]==NULL)
                        return -EBADF;
        }
        
@@ -759,30+758,6 @@ static void unix_fd_free(struct sock *sk, struct file **fp, int num)
        }
 }
 
-/*
- *     Count the free descriptors available to a process. 
- *     Interpretation issue: Is the limit the highest descriptor (buggy
- *     allowing passed fd's higher up to cause a limit to be exceeded) -
- *     but how the old code did it - or like this...
- */
-
-static int unix_files_free(void)
-{
-       int i;
-       int n=0;
-       for (i=0;i<NR_OPEN;i++)
-       {
-               if(current->files->fd[i])
-                       n++;
-       }
-       
-       i=NR_OPEN;
-       if(i>current->rlim[RLIMIT_NOFILE].rlim_cur)
-               i=current->rlim[RLIMIT_NOFILE].rlim_cur;
-       if(n>=i)
-               return 0;
-       return i-n;
-}
 
 /*
  *     Perform the AF_UNIX file descriptor pass out functionality. This
@@ -795,50+770,39 @@ static void unix_detach_fds(struct sk_buff *skb, struct cmsghdr *cmsg)
        /* count of space in parent for fds */
        int cmnum;
        struct file **fp;
-       struct file **ufp;
-       int *cmfptr=NULL;       /* =NULL To keep gcc happy */
-       /* number of fds actually passed */
+       int *cmfptr;
        int fdnum;
-       int ffree;
-       int ufn=0;
 
-       if(cmsg==NULL)
-               cmnum=0;
-       else
+       cmfptr = NULL;
+       cmnum = 0;
+       if (cmsg)
        {
-               cmnum=cmsg->cmsg_len-sizeof(struct cmsghdr);
-               cmnum/=sizeof(int);
-               cmfptr=(int *)&cmsg->cmsg_data;
+               cmnum = (cmsg->cmsg_len-sizeof(struct cmsghdr)) / sizeof(int);
+               cmfptr = (int *)&cmsg->cmsg_data;
        }
        
-       memcpy(&fdnum,skb->h.filp,sizeof(int));
-       fp=(struct file **)(skb->h.filp+sizeof(int));
-       if(cmnum>fdnum)
-               cmnum=fdnum;
-       ffree=unix_files_free();
-       if(cmnum>ffree)
-               cmnum=ffree;
-       ufp=&current->files->fd[0];
-       
+       fdnum = *(int *)skb->h.filp;
+       fp = (struct file **)(skb->h.filp+sizeof(long));
+
+       if (cmnum > fdnum)
+               cmnum = fdnum;
+
        /*
         *      Copy those that fit
         */
-       for(i=0;i<cmnum;i++)
+       for (i = 0 ; i < cmnum ; i++)
        {
-               /*
-                *      Insert the fd
-                */
-               while(ufp[ufn]!=NULL)
-                       ufn++;
-               ufp[ufn]=fp[i];
-               *cmfptr++=ufn;
-               FD_CLR(ufn,&current->files->close_on_exec);
+               int new_fd = get_unused_fd();
+               if (new_fd < 0)
+                       break;
+               current->files->fd[new_fd]=fp[i];
+               *cmfptr++ = new_fd;
                unix_notinflight(fp[i]);
        }
        /*
         *      Dump those that don't
         */
-       for(;i<fdnum;i++)
+       for( ; i < fdnum ; i++)
        {
                close_fp(fp[i]);
                unix_notinflight(fp[i]);
@@ -861,12+825,12 @@ static void unix_destruct_fds(struct sk_buff *skb)
 static void unix_attach_fds(int fpnum,struct file **fp,struct sk_buff *skb)
 {
 
-       skb->h.filp=kmalloc(sizeof(int)+fpnum*sizeof(struct file *), 
+       skb->h.filp = kmalloc(sizeof(long)+fpnum*sizeof(struct file *), 
                                                        GFP_KERNEL);
        /* number of descriptors starts block */
-       memcpy(skb->h.filp,&fpnum,sizeof(int));
+       *(int *)skb->h.filp = fpnum;
        /* actual  descriptors */
-       memcpy(skb->h.filp+sizeof(int),fp,fpnum*sizeof(struct file *));
+       memcpy(skb->h.filp+sizeof(long),fp,fpnum*sizeof(struct file *));
        skb->destructor = unix_destruct_fds;
 }
 
close