Commit b6a823e7 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.0.2

parent a96e1f22
...@@ -1029,6 +1029,13 @@ S: RR #5, 497 Pole Line Road ...@@ -1029,6 +1029,13 @@ S: RR #5, 497 Pole Line Road
S: Thunder Bay, Ontario S: Thunder Bay, Ontario
S: CANADA P7C 5M9 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 N: Kai Petzke
E: wpp@marie.physik.tu-berlin.de E: wpp@marie.physik.tu-berlin.de
W: http://physik.tu-berlin.de/~wpp W: http://physik.tu-berlin.de/~wpp
......
...@@ -179,7 +179,9 @@ or earlier, you will probably get a weird error on shutdown in which ...@@ -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 your computer shuts down fine but "INIT: error reading initrequest" or
words to that effect scroll across your screen hundreds of times. To words to that effect scroll across your screen hundreds of times. To
fix, upgrade 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 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 daemons to zero, as it incorrectly assumes SunOS behavior. I recommend
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 0 PATCHLEVEL = 0
SUBLEVEL = 1 SUBLEVEL = 2
ARCH = i386 ARCH = i386
......
...@@ -122,6 +122,15 @@ if [ "$CONFIG_NET" = "y" ]; then ...@@ -122,6 +122,15 @@ if [ "$CONFIG_NET" = "y" ]; then
endmenu endmenu
fi 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 mainmenu_option next_comment
comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)' comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
......
...@@ -161,6 +161,11 @@ CONFIG_DE4X5=y ...@@ -161,6 +161,11 @@ CONFIG_DE4X5=y
# CONFIG_TR is not set # CONFIG_TR is not set
# CONFIG_ARCNET is not set # CONFIG_ARCNET is not set
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
# #
# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
# #
......
...@@ -2755,8 +2755,9 @@ int rs_init(void) ...@@ -2755,8 +2755,9 @@ int rs_init(void)
serial_driver.type = TTY_DRIVER_TYPE_SERIAL; serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
serial_driver.subtype = SERIAL_TYPE_NORMAL; serial_driver.subtype = SERIAL_TYPE_NORMAL;
serial_driver.init_termios = tty_std_termios; serial_driver.init_termios = tty_std_termios;
serial_driver.init_termios.c_lflag &=~ (ISIG | ICANON | ECHO); serial_driver.init_termios.c_cflag =
serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver.flags = TTY_DRIVER_REAL_RAW;
serial_driver.refcount = &serial_refcount; serial_driver.refcount = &serial_refcount;
serial_driver.table = serial_table; serial_driver.table = serial_table;
serial_driver.termios = serial_termios; serial_driver.termios = serial_termios;
......
...@@ -789,8 +789,8 @@ static struct enet_statistics * ...@@ -789,8 +789,8 @@ static struct enet_statistics *
lance32_get_stats(struct device *dev) lance32_get_stats(struct device *dev)
{ {
struct lance32_private *lp = (struct lance32_private *)dev->priv; struct lance32_private *lp = (struct lance32_private *)dev->priv;
short ioaddr = dev->base_addr; int ioaddr = dev->base_addr;
short saved_addr; unsigned short saved_addr;
unsigned long flags; unsigned long flags;
save_flags(flags); save_flags(flags);
...@@ -809,7 +809,7 @@ lance32_get_stats(struct device *dev) ...@@ -809,7 +809,7 @@ lance32_get_stats(struct device *dev)
static void lance32_set_multicast_list(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; struct lance32_private *lp = (struct lance32_private *)dev->priv;
if (dev->flags&IFF_PROMISC) { if (dev->flags&IFF_PROMISC) {
......
...@@ -114,41 +114,34 @@ int unregister_binfmt(struct linux_binfmt * fmt) ...@@ -114,41 +114,34 @@ int unregister_binfmt(struct linux_binfmt * fmt)
int open_inode(struct inode * inode, int mode) int open_inode(struct inode * inode, int mode)
{ {
int error, fd; int fd;
struct file *f, **fpp;
if (!inode->i_op || !inode->i_op->default_file_ops) if (!inode->i_op || !inode->i_op->default_file_ops)
return -EINVAL; return -EINVAL;
f = get_empty_filp(); fd = get_unused_fd();
if (!f) if (fd >= 0) {
return -ENFILE; struct file * f = get_empty_filp();
fd = 0; if (!f) {
fpp = current->files->fd; put_unused_fd(fd);
for (;;) { return -ENFILE;
if (!*fpp)
break;
if (++fd >= NR_OPEN) {
f->f_count--;
return -EMFILE;
} }
fpp++; f->f_flags = mode;
} f->f_mode = (mode+1) & O_ACCMODE;
*fpp = f; f->f_inode = inode;
f->f_flags = mode; f->f_pos = 0;
f->f_mode = (mode+1) & O_ACCMODE; f->f_reada = 0;
f->f_inode = inode; f->f_op = inode->i_op->default_file_ops;
f->f_pos = 0; if (f->f_op->open) {
f->f_reada = 0; int error = f->f_op->open(inode,f);
f->f_op = inode->i_op->default_file_ops; if (error) {
if (f->f_op->open) { f->f_count--;
error = f->f_op->open(inode,f); put_unused_fd(fd);
if (error) { return error;
*fpp = NULL; }
f->f_count--;
return error;
} }
current->files->fd[fd] = f;
inode->i_count++;
} }
inode->i_count++;
return fd; return fd;
} }
...@@ -399,10 +392,45 @@ static void exec_mmap(void) ...@@ -399,10 +392,45 @@ static void exec_mmap(void)
} }
/* /*
* This function flushes out all traces of the currently running executable so * These functions flushes out all traces of the currently running executable
* that a new one can be started * 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) void flush_old_exec(struct linux_binprm * bprm)
{ {
int i; int i;
...@@ -429,16 +457,9 @@ void flush_old_exec(struct linux_binprm * bprm) ...@@ -429,16 +457,9 @@ void flush_old_exec(struct linux_binprm * bprm)
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
permission(bprm->inode,MAY_READ)) permission(bprm->inode,MAY_READ))
current->dumpable = 0; current->dumpable = 0;
for (i=0 ; i<32 ; i++) {
current->sig->action[i].sa_mask = 0; flush_old_signals(current->sig);
current->sig->action[i].sa_flags = 0; flush_old_files(current->files);
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);
} }
/* /*
......
...@@ -13,23 +13,24 @@ ...@@ -13,23 +13,24 @@
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/bitops.h>
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg); extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
static inline int dupfd(unsigned int fd, unsigned int 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; return -EBADF;
if (arg >= NR_OPEN) if (arg >= NR_OPEN)
return -EINVAL; return -EINVAL;
while (arg < NR_OPEN) arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
if (current->files->fd[arg]) if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
arg++;
else
break;
if (arg >= NR_OPEN)
return -EMFILE; return -EMFILE;
FD_CLR(arg, &current->files->close_on_exec); FD_SET(arg, &files->open_fds);
(current->files->fd[arg] = current->files->fd[fd])->f_count++; FD_CLR(arg, &files->close_on_exec);
(files->fd[arg] = files->fd[fd])->f_count++;
return arg; return arg;
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/bitops.h>
asmlinkage int sys_statfs(const char * path, struct statfs * buf) 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) ...@@ -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 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
* used by symlinks. * 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 inode * inode;
struct file * f; struct file * f;
int flag,error,fd; int flag,error;
f = get_empty_filp(); f = get_empty_filp();
if (!f) if (!f)
...@@ -533,21 +534,9 @@ int do_open(const char * filename,int flags,int mode) ...@@ -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); f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
/* current->files->fd[fd] = f;
* We have to do this last, because we mustn't export return 0;
* 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);
cleanup_all: cleanup_all:
if (f->f_mode & FMODE_WRITE) if (f->f_mode & FMODE_WRITE)
put_write_access(inode); put_write_access(inode);
...@@ -558,16 +547,44 @@ int do_open(const char * filename,int flags,int mode) ...@@ -558,16 +547,44 @@ int do_open(const char * filename,int flags,int mode)
return error; 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) asmlinkage int sys_open(const char * filename,int flags,int mode)
{ {
char * tmp; char * tmp;
int error; int fd, error;
fd = get_unused_fd();
if (fd < 0)
return fd;
error = getname(filename, &tmp); error = getname(filename, &tmp);
if (error) if (!error) {
return error; error = do_open(tmp,flags,mode, fd);
error = do_open(tmp,flags,mode); putname(tmp);
putname(tmp); if (!error)
return fd;
}
put_unused_fd(fd);
return error; return error;
} }
...@@ -610,16 +627,20 @@ int close_fp(struct file *filp) ...@@ -610,16 +627,20 @@ int close_fp(struct file *filp)
} }
asmlinkage int sys_close(unsigned int fd) asmlinkage int sys_close(unsigned int fd)
{ {
int error;
struct file * filp; struct file * filp;
struct files_struct * files;
if (fd >= NR_OPEN)
return -EBADF; files = current->files;
FD_CLR(fd, &current->files->close_on_exec); error = -EBADF;
if (!(filp = current->files->fd[fd])) if (fd < NR_OPEN && (filp = files->fd[fd]) != NULL) {
return -EBADF; put_unused_fd(fd);
current->files->fd[fd] = NULL; FD_CLR(fd, &files->close_on_exec);
return (close_fp (filp)); files->fd[fd] = NULL;
error = close_fp(filp);
}
return error;
} }
/* /*
......
...@@ -414,45 +414,58 @@ struct inode_operations pipe_inode_operations = { ...@@ -414,45 +414,58 @@ struct inode_operations pipe_inode_operations = {
int do_pipe(int *fd) int do_pipe(int *fd)
{ {
struct inode * inode; struct inode * inode;
struct file *f[2]; struct file *f1, *f2;
int error;
int i,j; 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(); inode = get_pipe_inode();
if (!inode) if (!inode)
return -ENFILE; goto close_f12;
for(j=0 ; j<2 ; j++) error = get_unused_fd();
if (!(f[j] = get_empty_filp())) if (error < 0)
break; goto close_f12_inode;
if (j < 2) { i = error;
iput(inode);
iput(inode); error = get_unused_fd();
if (j) if (error < 0)
f[0]->f_count--; goto close_f12_inode_i;
return -ENFILE; j = error;
}
j=0; f1->f_inode = f2->f_inode = inode;
for(i=0;j<2 && i<NR_OPEN && i<current->rlim[RLIMIT_NOFILE].rlim_cur;i++) /* read file */
if (!current->files->fd[i]) { f1->f_pos = f2->f_pos = 0;
current->files->fd[ fd[j]=i ] = f[j]; f1->f_flags = O_RDONLY;
j++; f1->f_op = &read_pipe_fops;
} f1->f_mode = 1;
if (j<2) { /* write file */
iput(inode); f2->f_flags = O_WRONLY;
iput(inode); f2->f_op = &write_pipe_fops;
f[0]->f_count--; f2->f_mode = 2;
f[1]->f_count--; current->files->fd[i] = f1;
if (j) current->files->fd[j] = f2;
current->files->fd[fd[0]] = NULL; fd[0] = i;
return -EMFILE; fd[1] = j;
}
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 */
return 0; 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;
} }
...@@ -92,11 +92,13 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex, ...@@ -92,11 +92,13 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
int i,j; int i,j;
int max = -1; int max = -1;
for (j = 0 ; j < __FDSET_INTS ; j++) { j = 0;
for (;;) {
i = j * __NFDBITS; i = j * __NFDBITS;
if (i >= n) if (i >= n)
break; break;
set = in->fds_bits[j] | out->fds_bits[j] | ex->fds_bits[j]; set = in->fds_bits[j] | out->fds_bits[j] | ex->fds_bits[j];
j++;
for ( ; set ; i++,set >>= 1) { for ( ; set ; i++,set >>= 1) {
if (i >= n) if (i >= n)
goto end_check; goto end_check;
...@@ -113,9 +115,6 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex, ...@@ -113,9 +115,6 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
n = max + 1; n = max + 1;
if(!(entry = (struct select_table_entry*) __get_free_page(GFP_KERNEL))) if(!(entry = (struct select_table_entry*) __get_free_page(GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
FD_ZERO(res_in);
FD_ZERO(res_out);
FD_ZERO(res_ex);
count = 0; count = 0;
wait_table.nr = 0; wait_table.nr = 0;
wait_table.entry = entry; wait_table.entry = entry;
...@@ -153,51 +152,79 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex, ...@@ -153,51 +152,79 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
/* /*
* We do a VERIFY_WRITE here even though we are only reading this time: * We do a VERIFY_WRITE here even though we are only reading this time:
* we'll write to it eventually.. * 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; /* round up nr to nearest "int" */
unsigned int * tmp; nr = (nr + 8*sizeof(int)-1) / (8*sizeof(int));
if (fs_pointer) {
FD_ZERO(fdset); int error = verify_area(VERIFY_WRITE,fs_pointer,nr*sizeof(int));
if (!fs_pointer) if (!error) {
return 0; while (nr) {
error = verify_area(VERIFY_WRITE,fs_pointer,sizeof(fd_set)); *fdset = get_user(fs_pointer);
if (error) nr--;
fs_pointer++;
fdset++;
}
}
return error; return error;
tmp = fdset->fds_bits; }
for (i = __FDSET_INTS; i > 0; i--) { while (nr) {
if (nr <= 0) *fdset = 0;
break; nr--;
*tmp = get_user(fs_pointer); fdset++;
tmp++;
fs_pointer++;
nr -= 8 * sizeof(unsigned int);
} }
return 0; 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) if (!fs_pointer)
return; return;
for (i = __FDSET_INTS; i > 0; i--) { while (nr >= 0) {
if (nr <= 0)
break;
put_user(*fdset, fs_pointer); put_user(*fdset, fs_pointer);
nr -= 8 * sizeof(int);
fdset++; fdset++;
fs_pointer++; 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) \ #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) \ #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 * 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)) ...@@ -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) asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
{ {
int i; int error;
fd_set res_in, in; limited_fd_set res_in, in;
fd_set res_out, out; limited_fd_set res_out, out;
fd_set res_ex, ex; limited_fd_set res_ex, ex;
unsigned long timeout; unsigned long timeout;
error = -EINVAL;
if (n < 0) if (n < 0)
return -EINVAL; goto out;
if (n > NR_OPEN) if (n > NR_OPEN)
n = NR_OPEN; n = NR_OPEN;
if ((i = get_fd_set(n, inp, &in)) || if ((error = get_fd_set(n, inp, &in)) ||
(i = get_fd_set(n, outp, &out)) || (error = get_fd_set(n, outp, &out)) ||
(i = get_fd_set(n, exp, &ex))) return i; (error = get_fd_set(n, exp, &ex))) goto out;
timeout = ~0UL; timeout = ~0UL;
if (tvp) { if (tvp) {
i = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp)); error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
if (i) if (error)
return i; goto out;
timeout = ROUND_UP(get_user(&tvp->tv_usec),(1000000/HZ)); timeout = ROUND_UP(get_user(&tvp->tv_usec),(1000000/HZ));
timeout += get_user(&tvp->tv_sec) * (unsigned long) HZ; timeout += get_user(&tvp->tv_sec) * (unsigned long) HZ;
if (timeout) if (timeout)
timeout += jiffies + 1; timeout += jiffies + 1;
} }
zero_fd_set(n, &res_in);
zero_fd_set(n, &res_out);
zero_fd_set(n, &res_ex);
current->timeout = timeout; 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; timeout = current->timeout - jiffies - 1;
current->timeout = 0; current->timeout = 0;
if ((long) 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 ...@@ -244,12 +281,17 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct
timeout *= (1000000/HZ); timeout *= (1000000/HZ);
put_user(timeout, &tvp->tv_usec); put_user(timeout, &tvp->tv_usec);
} }
if (i < 0) if (error < 0)
return i; goto out;
if (!i && (current->signal & ~current->blocked)) if (!error) {
return -ERESTARTNOHAND; error = -ERESTARTNOHAND;
if (current->signal & ~current->blocked)
goto out;
error = 0;
}
set_fd_set(n, inp, &res_in); set_fd_set(n, inp, &res_in);
set_fd_set(n, outp, &res_out); set_fd_set(n, outp, &res_out);
set_fd_set(n, exp, &res_ex); set_fd_set(n, exp, &res_ex);
return i; out:
return error;
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke * 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> #include <linux/config.h>
...@@ -1152,6 +1153,7 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos, ...@@ -1152,6 +1153,7 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
int info_level = 1; int info_level = 1;
char *p; char *p;
char *lastname;
int i; int i;
int first, total_count; int first, total_count;
struct smb_dirent *current_entry; struct smb_dirent *current_entry;
...@@ -1171,9 +1173,15 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos, ...@@ -1171,9 +1173,15 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
int ff_dir_handle=0; int ff_dir_handle=0;
int loop_count = 0; int loop_count = 0;
int dirlen = strlen(SMB_FINFO(dir)->path); int dirlen = strlen(SMB_FINFO(dir)->path) + 3;
char mask[dirlen + 5]; 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); strcpy(mask, SMB_FINFO(dir)->path);
strcat(mask, "\\*"); strcat(mask, "\\*");
...@@ -1297,22 +1305,37 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos, ...@@ -1297,22 +1305,37 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
p = resp_data; p = resp_data;
/* we might need the lastname for continuations */ /* we might need the lastname for continuations */
lastname = "";
if (ff_lastname > 0) if (ff_lastname > 0)
{ {
switch(info_level) switch(info_level)
{ {
case 260: case 260:
ff_resume_key =0; lastname = p + ff_lastname + 94;
strcpy(mask,p+ff_lastname+94); ff_resume_key = 0;
break; break;
case 1: case 1:
strcpy(mask,p + ff_lastname + 1); lastname = p + ff_lastname + 1;
ff_resume_key = 0; ff_resume_key = 0;
break; 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. */ /* 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, ...@@ -1355,6 +1378,9 @@ smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
} }
finished: finished:
if (mask != NULL)
smb_kfree_s(mask, 0);
if (resp_data != NULL) { if (resp_data != NULL) {
smb_kfree_s(resp_data, 0); smb_kfree_s(resp_data, 0);
resp_data = NULL; resp_data = NULL;
......
...@@ -106,9 +106,9 @@ ...@@ -106,9 +106,9 @@
#define ENOANO 100 /* No anode */ #define ENOANO 100 /* No anode */
#define EBADRQC 101 /* Invalid request code */ #define EBADRQC 101 /* Invalid request code */
#define EBADSLT 102 /* Invalid slot */ #define EBADSLT 102 /* Invalid slot */
#if 0
#define EDEADLOCK 103 /* File locking deadlock error */ #define EDEADLOCK EDEADLK
#endif
#define EBFONT 104 /* Bad font file format */ #define EBFONT 104 /* Bad font file format */
#define ENONET 105 /* Machine is not on the network */ #define ENONET 105 /* Machine is not on the network */
#define ENOLINK 106 /* Link has been severed */ #define ENOLINK 106 /* Link has been severed */
......
...@@ -74,18 +74,18 @@ static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) ...@@ -74,18 +74,18 @@ static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
#undef __FD_ZERO #undef __FD_ZERO
static __inline__ void __FD_ZERO(__kernel_fd_set *p) static __inline__ void __FD_ZERO(__kernel_fd_set *p)
{ {
unsigned int *tmp = p->fds_bits; unsigned long *tmp = p->fds_bits;
int i; int i;
if (__builtin_constant_p(__FDSET_INTS)) { if (__builtin_constant_p(__FDSET_LONGS)) {
switch (__FDSET_INTS) { switch (__FDSET_LONGS) {
case 8: case 8:
tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0; tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0; tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
return; return;
} }
} }
i = __FDSET_INTS; i = __FDSET_LONGS;
while (i) { while (i) {
i--; i--;
*tmp = 0; *tmp = 0;
......
...@@ -58,9 +58,9 @@ ...@@ -58,9 +58,9 @@
#define ENOANO 55 /* No anode */ #define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */ #define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */ #define EBADSLT 57 /* Invalid slot */
#if 0
#define EDEADLOCK 58 /* File locking deadlock error */ #define EDEADLOCK EDEADLK
#endif
#define EBFONT 59 /* Bad font file format */ #define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */ #define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */ #define ENODATA 61 /* No data available */
......
...@@ -623,6 +623,8 @@ extern struct inode * get_empty_inode(void); ...@@ -623,6 +623,8 @@ extern struct inode * get_empty_inode(void);
extern void insert_inode_hash(struct inode *); extern void insert_inode_hash(struct inode *);
extern void clear_inode(struct inode *); extern void clear_inode(struct inode *);
extern struct inode * get_pipe_inode(void); 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 struct file * get_empty_filp(void);
extern int close_fp(struct file *filp); extern int close_fp(struct file *filp);
extern struct buffer_head * get_hash_table(kdev_t dev, int block, int size); extern struct buffer_head * get_hash_table(kdev_t dev, int block, int size);
......
...@@ -101,7 +101,7 @@ struct sockaddr_in { ...@@ -101,7 +101,7 @@ struct sockaddr_in {
#define INADDR_BROADCAST ((unsigned long int) 0xffffffff) #define INADDR_BROADCAST ((unsigned long int) 0xffffffff)
/* Address indicating an error return. */ /* Address indicating an error return. */
#define INADDR_NONE 0xffffffff #define INADDR_NONE ((unsigned long int) 0xffffffff)
/* Network number for local host loopback. */ /* Network number for local host loopback. */
#define IN_LOOPBACKNET 127 #define IN_LOOPBACKNET 127
......
...@@ -27,22 +27,22 @@ ...@@ -27,22 +27,22 @@
* use the ones here. * use the ones here.
*/ */
#undef __NFDBITS #undef __NFDBITS
#define __NFDBITS (8 * sizeof(unsigned int)) #define __NFDBITS (8 * sizeof(unsigned long))
#undef __FD_SETSIZE #undef __FD_SETSIZE
#define __FD_SETSIZE 1024 #define __FD_SETSIZE 1024
#undef __FDSET_INTS #undef __FDSET_LONGS
#define __FDSET_INTS (__FD_SETSIZE/__NFDBITS) #define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS)
#undef __FDELT #undef __FDELT
#define __FDELT(d) ((d) / __NFDBITS) #define __FDELT(d) ((d) / __NFDBITS)
#undef __FDMASK #undef __FDMASK
#define __FDMASK(d) (1 << ((d) % __NFDBITS)) #define __FDMASK(d) (1UL << ((d) % __NFDBITS))
typedef struct { typedef struct {
unsigned int fds_bits [__FDSET_INTS]; unsigned long fds_bits [__FDSET_LONGS];
} __kernel_fd_set; } __kernel_fd_set;
#include <asm/posix_types.h> #include <asm/posix_types.h>
......
...@@ -108,20 +108,18 @@ extern void trap_init(void); ...@@ -108,20 +108,18 @@ extern void trap_init(void);
asmlinkage void schedule(void); asmlinkage void schedule(void);
/* ??? */ /* Open file table structure */
struct files_struct { struct files_struct {
/* ??? */
int count; int count;
/* bit mask to close fds on exec */
fd_set close_on_exec; fd_set close_on_exec;
/* do we have at most NR_OPEN available fds? I assume fd i maps into fd_set open_fds;
* each open file */
struct file * fd[NR_OPEN]; struct file * fd[NR_OPEN];
}; };
#define INIT_FILES { \ #define INIT_FILES { \
1, \ 1, \
{ { 0, } }, \ { { 0, } }, \
{ { 0, } }, \
{ NULL, } \ { NULL, } \
} }
......
...@@ -174,22 +174,6 @@ extern void tcp_reset_xmit_timer(struct sock *, int, unsigned long); ...@@ -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_delack_timer(unsigned long);
extern void tcp_retransmit_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) static __inline__ int tcp_old_window(struct sock * sk)
{ {
return sk->window - (sk->acked_seq - sk->lastwin_seq); return sk->window - (sk->acked_seq - sk->lastwin_seq);
......
...@@ -393,6 +393,26 @@ static inline void forget_original_parent(struct task_struct * father) ...@@ -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) static inline void __exit_files(struct task_struct *tsk)
{ {
struct files_struct * files = tsk->files; struct files_struct * files = tsk->files;
...@@ -400,14 +420,7 @@ static inline void __exit_files(struct task_struct *tsk) ...@@ -400,14 +420,7 @@ static inline void __exit_files(struct task_struct *tsk)
if (files) { if (files) {
tsk->files = NULL; tsk->files = NULL;
if (!--files->count) { if (!--files->count) {
int i; close_files(files);
for (i=0 ; i<NR_OPEN ; i++) {
struct file * filp = files->fd[i];
if (!filp)
continue;
files->fd[i] = NULL;
close_fp(filp);
}
kfree(files); kfree(files);
} }
} }
......
...@@ -160,22 +160,33 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk) ...@@ -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) static inline int copy_files(unsigned long clone_flags, struct task_struct * tsk)
{ {
int i; int i;
struct files_struct *oldf, *newf;
struct file **old_fds, **new_fds;
oldf = current->files;
if (clone_flags & CLONE_FILES) { if (clone_flags & CLONE_FILES) {
current->files->count++; oldf->count++;
return 0; 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; return -1;
tsk->files->count = 1;
memcpy(&tsk->files->close_on_exec, &current->files->close_on_exec, newf->count = 1;
sizeof(tsk->files->close_on_exec)); newf->close_on_exec = oldf->close_on_exec;
for (i = 0; i < NR_OPEN; i++) { newf->open_fds = oldf->open_fds;
struct file * f = current->files->fd[i];
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) if (f)
f->f_count++; f->f_count++;
tsk->files->fd[i] = f;
} }
return 0; return 0;
} }
......
...@@ -926,7 +926,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, ...@@ -926,7 +926,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
* Reuse ? * Reuse ?
*/ */
if (!sk2->dead) if (!sk2->reuse || sk2->state==TCP_LISTEN)
{ {
sti(); sti();
return(-EADDRINUSE); return(-EADDRINUSE);
......
...@@ -202,6 +202,7 @@ ...@@ -202,6 +202,7 @@
* improvement. * improvement.
* Stefan Magdalinski : adjusted tcp_readable() to fix FIONREAD * Stefan Magdalinski : adjusted tcp_readable() to fix FIONREAD
* Willy Konynenberg : Transparent proxying support. * Willy Konynenberg : Transparent proxying support.
* Theodore Ts'o : Do secure TCP sequence numbers.
* *
* To Fix: * To Fix:
* Fast path the code. Two things here - fix the window calculation * Fast path the code. Two things here - fix the window calculation
...@@ -427,6 +428,7 @@ ...@@ -427,6 +428,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/random.h>
#include <net/icmp.h> #include <net/icmp.h>
#include <net/tcp.h> #include <net/tcp.h>
...@@ -1886,6 +1888,36 @@ static struct sock *tcp_accept(struct sock *sk, int flags) ...@@ -1886,6 +1888,36 @@ static struct sock *tcp_accept(struct sock *sk, int flags)
goto out; 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. * This will initiate an outgoing connection.
...@@ -1921,7 +1953,7 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len) ...@@ -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). * 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(); 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) ...@@ -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) if ((atype=ip_chk_addr(usin->sin_addr.s_addr)) == IS_BROADCAST || atype==IS_MULTICAST)
return -ENETUNREACH; return -ENETUNREACH;
if (!tcp_unique_address(sk->saddr, sk->num, usin->sin_addr.s_addr, usin->sin_port))
return -EADDRNOTAVAIL;
lock_sock(sk); lock_sock(sk);
sk->daddr = usin->sin_addr.s_addr; 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->rcv_ack_cnt = 1;
sk->err = 0; sk->err = 0;
sk->dummy_th.dest = usin->sin_port; sk->dummy_th.dest = usin->sin_port;
release_sock(sk);
buff = sock_wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL); buff = sock_wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
if (buff == NULL) if (buff == NULL)
{ {
release_sock(sk);
return(-ENOMEM); return(-ENOMEM);
} }
lock_sock(sk);
buff->sk = sk; buff->sk = sk;
buff->free = 0; buff->free = 0;
buff->localroute = sk->localroute; buff->localroute = sk->localroute;
/* /*
* Put in the IP header and routing stuff. * 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) ...@@ -1968,6 +1999,15 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
sk->saddr = rt->rt_src; sk->saddr = rt->rt_src;
sk->rcv_saddr = sk->saddr; 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)); t1 = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr));
memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1)); memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
......
...@@ -28,9 +28,12 @@ ...@@ -28,9 +28,12 @@
* Eric Schenk : Skip fast retransmit on small windows. * Eric Schenk : Skip fast retransmit on small windows.
* Eric schenk : Fixes to retransmission code to * Eric schenk : Fixes to retransmission code to
* : avoid extra retransmission. * : avoid extra retransmission.
* Theodore Ts'o : Do secure TCP sequence numbers.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/types.h>
#include <linux/random.h>
#include <net/tcp.h> #include <net/tcp.h>
/* /*
...@@ -208,7 +211,17 @@ static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, u32 end_seq, ...@@ -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 * from the far end, but sometimes it means the far end lost
* an ACK we sent, so we better send an ACK. * 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, ...@@ -1722,6 +1735,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
struct tcphdr *th; struct tcphdr *th;
struct sock *sk; struct sock *sk;
int syn_ok=0; int syn_ok=0;
__u32 seq;
#ifdef CONFIG_IP_TRANSPARENT_PROXY #ifdef CONFIG_IP_TRANSPARENT_PROXY
int r; int r;
#endif #endif
...@@ -1859,10 +1873,12 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, ...@@ -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
*/ */
seq = secure_tcp_sequence_number(saddr, daddr,
tcp_conn_request(sk, skb, daddr, saddr, opt, dev, tcp_init_seq()); 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 * Now we have several options: In theory there is nothing else
......
...@@ -172,36 +172,31 @@ int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen) ...@@ -172,36 +172,31 @@ int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen)
static int get_fd(struct inode *inode) static int get_fd(struct inode *inode)
{ {
int fd; int fd;
struct file *file;
/* /*
* Find a file descriptor suitable for return to the user. * Find a file descriptor suitable for return to the user.
*/ */
file = get_empty_filp(); fd = get_unused_fd();
if (!file) if (fd >= 0) {
return(-1); struct file *file = get_empty_filp();
for (fd = 0; fd < NR_OPEN; ++fd) if (!file) {
if (!current->files->fd[fd]) put_unused_fd(fd);
break; return -ENFILE;
if (fd == NR_OPEN) }
{
file->f_count = 0;
return(-1);
}
FD_CLR(fd, &current->files->close_on_exec);
current->files->fd[fd] = file; current->files->fd[fd] = file;
file->f_op = &socket_file_ops; file->f_op = &socket_file_ops;
file->f_mode = 3; file->f_mode = 3;
file->f_flags = O_RDWR; file->f_flags = O_RDWR;
file->f_count = 1; file->f_count = 1;
file->f_inode = inode; file->f_inode = inode;
if (inode) if (inode)
inode->i_count++; inode->i_count++;
file->f_pos = 0; file->f_pos = 0;
return(fd); }
return fd;
} }
......
...@@ -710,10 +710,9 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp) ...@@ -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 num=cmsg->cmsg_len-sizeof(struct cmsghdr);
int i; int i;
int *fdp=(int *)cmsg->cmsg_data; 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; return -EINVAL;
/* /*
...@@ -728,9 +727,9 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp) ...@@ -728,9 +727,9 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
#if 0 #if 0
printk("testing fd %d\n", fd); printk("testing fd %d\n", fd);
#endif #endif
if(fd < 0|| fd >=NR_OPEN) if (fd < 0 || fd >= NR_OPEN)
return -EBADF; return -EBADF;
if(current->files->fd[fd]==NULL) if (current->files->fd[fd]==NULL)
return -EBADF; return -EBADF;
} }
...@@ -759,30 +758,6 @@ static void unix_fd_free(struct sock *sk, struct file **fp, int num) ...@@ -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 * 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) ...@@ -795,50 +770,39 @@ static void unix_detach_fds(struct sk_buff *skb, struct cmsghdr *cmsg)
/* count of space in parent for fds */ /* count of space in parent for fds */
int cmnum; int cmnum;
struct file **fp; struct file **fp;
struct file **ufp; int *cmfptr;
int *cmfptr=NULL; /* =NULL To keep gcc happy */
/* number of fds actually passed */
int fdnum; int fdnum;
int ffree;
int ufn=0;
if(cmsg==NULL) cmfptr = NULL;
cmnum=0; cmnum = 0;
else if (cmsg)
{ {
cmnum=cmsg->cmsg_len-sizeof(struct cmsghdr); cmnum = (cmsg->cmsg_len-sizeof(struct cmsghdr)) / sizeof(int);
cmnum/=sizeof(int); cmfptr = (int *)&cmsg->cmsg_data;
cmfptr=(int *)&cmsg->cmsg_data;
} }
memcpy(&fdnum,skb->h.filp,sizeof(int)); fdnum = *(int *)skb->h.filp;
fp=(struct file **)(skb->h.filp+sizeof(int)); fp = (struct file **)(skb->h.filp+sizeof(long));
if(cmnum>fdnum)
cmnum=fdnum; if (cmnum > fdnum)
ffree=unix_files_free(); cmnum = fdnum;
if(cmnum>ffree)
cmnum=ffree;
ufp=&current->files->fd[0];
/* /*
* Copy those that fit * Copy those that fit
*/ */
for(i=0;i<cmnum;i++) for (i = 0 ; i < cmnum ; i++)
{ {
/* int new_fd = get_unused_fd();
* Insert the fd if (new_fd < 0)
*/ break;
while(ufp[ufn]!=NULL) current->files->fd[new_fd]=fp[i];
ufn++; *cmfptr++ = new_fd;
ufp[ufn]=fp[i];
*cmfptr++=ufn;
FD_CLR(ufn,&current->files->close_on_exec);
unix_notinflight(fp[i]); unix_notinflight(fp[i]);
} }
/* /*
* Dump those that don't * Dump those that don't
*/ */
for(;i<fdnum;i++) for( ; i < fdnum ; i++)
{ {
close_fp(fp[i]); close_fp(fp[i]);
unix_notinflight(fp[i]); unix_notinflight(fp[i]);
...@@ -861,12 +825,12 @@ static void unix_destruct_fds(struct sk_buff *skb) ...@@ -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) 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); GFP_KERNEL);
/* number of descriptors starts block */ /* number of descriptors starts block */
memcpy(skb->h.filp,&fpnum,sizeof(int)); *(int *)skb->h.filp = fpnum;
/* actual descriptors */ /* 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; skb->destructor = unix_destruct_fds;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment