patch-2.1.25 linux/net/socket.c
Next file: linux/net/wanrouter/Makefile
Previous file: linux/net/rose/sysctl_net_rose.c
Back to the patch index
Back to the overall index
- Lines: 743
- Date:
Sun Feb 2 15:18:52 1997
- Orig file:
v2.1.24/linux/net/socket.c
- Orig date:
Tue Jan 28 18:50:59 1997
diff -u --recursive --new-file v2.1.24/linux/net/socket.c linux/net/socket.c
@@ -35,6 +35,9 @@
* Alan Cox : sendmsg/recvmsg basics.
* Tom Dyas : Export net symbols.
* Marcin Dalecki : Fixed problems with CONFIG_NET="n".
+ * Alan Cox : Added thread locking to sys_* calls
+ * for sockets. May have errors at the
+ * moment.
*
*
* This program is free software; you can redistribute it and/or
@@ -46,14 +49,6 @@
* This module is effectively the top level interface to the BSD socket
* paradigm.
*
- * PROBLEMS:
- * - CLONE_FILES. Big problem, cloned thread can close file,
- * while other thread sleeps in kernel. It can be solved
- * by increasing f_count and releasing it on exit from syscall.
- * _HAS_ to be fixed before 2.2 is released. I assume whoever is
- * working on the CLONE stuff will fix that pile of accidents. If
- * you find this comment in a 2.2-preXXX kernel scream loudly.
- *
*/
#include <linux/config.h>
@@ -68,11 +63,13 @@
#include <linux/stat.h>
#include <linux/socket.h>
#include <linux/fcntl.h>
+#include <linux/file.h>
#include <linux/net.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/firewall.h>
+#include <linux/wanrouter.h>
#if defined(CONFIG_KERNELD) && defined(CONFIG_NET)
#include <linux/kerneld.h>
@@ -232,7 +229,7 @@
struct file *file;
struct inode *inode;
- if (fd < 0 || fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ if (!(file = fget(fd)))
{
*err = -EBADF;
return NULL;
@@ -242,12 +239,18 @@
if (!inode || !inode->i_sock || !socki_lookup(inode))
{
*err = -ENOTSOCK;
+ fput(file,inode);
return NULL;
}
return socki_lookup(inode);
}
+extern __inline__ void sockfd_put(struct socket *sock)
+{
+ fput(sock->file,sock->inode);
+}
+
/*
* Allocate a socket.
*/
@@ -713,22 +716,16 @@
asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen)
{
struct socket *sock;
- int i;
char address[MAX_SOCK_ADDR];
int err;
lock_kernel();
- if (!(sock = sockfd_lookup(fd,&err)))
- goto out;
-
- if((err=move_addr_to_kernel(umyaddr,addrlen,address))<0)
- goto out;
-
- if ((i = sock->ops->bind(sock, (struct sockaddr *)address, addrlen)) < 0)
- err = i;
- else
- err = 0;
-out:
+ if((sock = sockfd_lookup(fd,&err))!=NULL)
+ {
+ if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0)
+ err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen);
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -743,15 +740,14 @@
asmlinkage int sys_listen(int fd, int backlog)
{
struct socket *sock;
- int err=-EOPNOTSUPP;
+ int err;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- if (sock->ops && sock->ops->listen)
+ if((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
err=sock->ops->listen(sock, backlog);
-out:
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -778,54 +774,50 @@
int len;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
- err = -EOPNOTSUPP;
- if (!sock->ops->accept)
- goto out;
-
- err = -ENOSR;
- if (!(newsock = sock_alloc()))
- {
- printk(KERN_WARNING "accept: no more sockets\n");
- goto out; /* Was: EAGAIN, but we are out of system
- resources! */
- }
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ if (!(newsock = sock_alloc()))
+ {
+ printk(KERN_WARNING "accept: no more sockets\n");
+ err=-EMFILE;
+ goto out;
+ }
- inode = newsock->inode;
- newsock->type = sock->type;
+ inode = newsock->inode;
+ newsock->type = sock->type;
- if ((err = sock->ops->dup(newsock, sock)) < 0)
- {
- sock_release(newsock);
- goto out;
- }
+ if ((err = sock->ops->dup(newsock, sock)) < 0)
+ {
+ sock_release(newsock);
+ goto out;
+ }
- err = newsock->ops->accept(sock, newsock, current->files->fd[fd]->f_flags);
+ err = newsock->ops->accept(sock, newsock, current->files->fd[fd]->f_flags);
- if (err < 0)
- {
- sock_release(newsock);
- goto out;
- }
- newsock = socki_lookup(inode);
+ if (err < 0)
+ {
+ sock_release(newsock);
+ goto out;
+ }
+ newsock = socki_lookup(inode);
- if ((fd = get_fd(inode)) < 0)
- {
- sock_release(newsock);
- err = -EINVAL;
- goto out;
- }
+ if ((err = get_fd(inode)) < 0)
+ {
+ sock_release(newsock);
+ err=-EINVAL;
+ goto out;
+ }
- newsock->file = current->files->fd[fd];
+ newsock->file = current->files->fd[err];
- if (upeer_sockaddr)
- {
- newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 1);
- move_addr_to_user(address,len, upeer_sockaddr, upeer_addrlen);
- }
- err = fd;
+ if (upeer_sockaddr)
+ {
+ newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 1);
+ move_addr_to_user(address,len, upeer_sockaddr, upeer_addrlen);
+ }
out:
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -850,17 +842,13 @@
int err;
lock_kernel();
- if (!(sock = sockfd_lookup(fd,&err)))
- goto out;
-
- if((err=move_addr_to_kernel(uservaddr,addrlen,address))<0)
- goto out;
-
- err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
+ if ((sock = sockfd_lookup(fd,&err))!=NULL)
+ {
+ if((err=move_addr_to_kernel(uservaddr,addrlen,address))>=0)
+ err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen,
current->files->fd[fd]->f_flags);
- if (err >= 0)
- err = 0;
-out:
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -878,16 +866,12 @@
int err;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- err=sock->ops->getname(sock, (struct sockaddr *)address, &len, 0);
- if(err)
- goto out;
- if((err=move_addr_to_user(address,len, usockaddr, usockaddr_len))<0)
- goto out;
- err = 0;
-out:
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ if((err=sock->ops->getname(sock, (struct sockaddr *)address, &len, 0))==0)
+ err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -905,16 +889,12 @@
int err;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- err=sock->ops->getname(sock, (struct sockaddr *)address, &len, 1);
- if(err)
- goto out;
- if((err=move_addr_to_user(address,len, usockaddr, usockaddr_len))<0)
- goto out;
- err = 0;
-out:
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ if((err=sock->ops->getname(sock, (struct sockaddr *)address, &len, 1))==0)
+ err=move_addr_to_user(address,len, usockaddr, usockaddr_len);
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -932,30 +912,27 @@
struct iovec iov;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- err = -EINVAL;
- if(len<0)
- goto out;
- err=verify_area(VERIFY_READ, buff, len);
- if(err)
- goto out;
-
- iov.iov_base=buff;
- iov.iov_len=len;
- msg.msg_name=NULL;
- msg.msg_namelen=0;
- msg.msg_iov=&iov;
- msg.msg_iovlen=1;
- msg.msg_control=NULL;
- msg.msg_controllen=0;
- if (current->files->fd[fd]->f_flags & O_NONBLOCK)
- flags |= MSG_DONTWAIT;
- msg.msg_flags=flags;
-
- err = sock_sendmsg(sock, &msg, len);
-out:
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ if(len>=0)
+ {
+ iov.iov_base=buff;
+ iov.iov_len=len;
+ msg.msg_name=NULL;
+ msg.msg_namelen=0;
+ msg.msg_iov=&iov;
+ msg.msg_iovlen=1;
+ msg.msg_control=NULL;
+ msg.msg_controllen=0;
+ if (current->files->fd[fd]->f_flags & O_NONBLOCK)
+ flags |= MSG_DONTWAIT;
+ msg.msg_flags=flags;
+ err=sock_sendmsg(sock, &msg, len);
+ }
+ else
+ err=-EINVAL;
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -976,35 +953,30 @@
struct iovec iov;
lock_kernel();
- if (!(sock = sockfd_lookup(fd,&err)))
- goto out;
-
- err=verify_area(VERIFY_READ,buff,len);
- if(err)
- goto out;
-
- iov.iov_base=buff;
- iov.iov_len=len;
- msg.msg_name=NULL;
- msg.msg_iov=&iov;
- msg.msg_iovlen=1;
- msg.msg_control=NULL;
- msg.msg_controllen=0;
- msg.msg_namelen=addr_len;
- if(addr)
+ if ((sock = sockfd_lookup(fd,&err))!=NULL)
{
- err=move_addr_to_kernel(addr,addr_len,address);
- if (err < 0)
- goto out;
- msg.msg_name=address;
+ iov.iov_base=buff;
+ iov.iov_len=len;
+ msg.msg_name=NULL;
+ msg.msg_iov=&iov;
+ msg.msg_iovlen=1;
+ msg.msg_control=NULL;
+ msg.msg_controllen=0;
+ msg.msg_namelen=addr_len;
+ if(addr)
+ {
+ err=move_addr_to_kernel(addr,addr_len,address);
+ if (err < 0)
+ goto bad;
+ msg.msg_name=address;
+ }
+ if (current->files->fd[fd]->f_flags & O_NONBLOCK)
+ flags |= MSG_DONTWAIT;
+ msg.msg_flags=flags;
+ err=sock_sendmsg(sock, &msg, len);
+bad:
+ sockfd_put(sock);
}
-
- if (current->files->fd[fd]->f_flags & O_NONBLOCK)
- flags |= MSG_DONTWAIT;
- msg.msg_flags=flags;
-
- err = sock_sendmsg(sock, &msg, len);
-out:
unlock_kernel();
return err;
}
@@ -1022,28 +994,20 @@
int err;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- err = 0;
- if(size==0)
- goto out;
- err=verify_area(VERIFY_WRITE, ubuf, size);
- if(err)
- goto out;
-
- msg.msg_name=NULL;
- msg.msg_iov=&iov;
- msg.msg_iovlen=1;
- msg.msg_control=NULL;
- msg.msg_controllen=0;
- iov.iov_base=ubuf;
- iov.iov_len=size;
-
- err = sock_recvmsg(sock, &msg, size,
- (current->files->fd[fd]->f_flags & O_NONBLOCK)
- ? flags | MSG_DONTWAIT : flags);
-out:
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ msg.msg_name=NULL;
+ msg.msg_iov=&iov;
+ msg.msg_iovlen=1;
+ msg.msg_control=NULL;
+ msg.msg_controllen=0;
+ iov.iov_base=ubuf;
+ iov.iov_len=size;
+
+ err=sock_recvmsg(sock, &msg, size,
+ (current->files->fd[fd]->f_flags & O_NONBLOCK) ? flags | MSG_DONTWAIT : flags);
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -1061,39 +1025,29 @@
struct iovec iov;
struct msghdr msg;
char address[MAX_SOCK_ADDR];
- int err;
+ int err,err2;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
- err = 0;
- if (size==0)
- goto out;
-
- err=verify_area(VERIFY_WRITE,ubuf,size);
- if(err)
- goto out;
-
- msg.msg_control=NULL;
- msg.msg_controllen=0;
- msg.msg_iovlen=1;
- msg.msg_iov=&iov;
- iov.iov_len=size;
- iov.iov_base=ubuf;
- msg.msg_name=address;
- msg.msg_namelen=MAX_SOCK_ADDR;
- err = sock_recvmsg(sock, &msg, size,
- (current->files->fd[fd]->f_flags & O_NONBLOCK)
- ? (flags | MSG_DONTWAIT) : flags);
-
- if(err<0)
- goto out;
- size=err;
- if(addr!=NULL &&
- (err=move_addr_to_user(address, msg.msg_namelen, addr, addr_len))<0)
- goto out;
- err = size;
-out:
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ msg.msg_control=NULL;
+ msg.msg_controllen=0;
+ msg.msg_iovlen=1;
+ msg.msg_iov=&iov;
+ iov.iov_len=size;
+ iov.iov_base=ubuf;
+ msg.msg_name=address;
+ msg.msg_namelen=MAX_SOCK_ADDR;
+ err=sock_recvmsg(sock, &msg, size,
+ (current->files->fd[fd]->f_flags & O_NONBLOCK) ? (flags | MSG_DONTWAIT) : flags);
+ if(err>=0 && addr!=NULL)
+ {
+ err2=move_addr_to_user(address, msg.msg_namelen, addr, addr_len);
+ if(err2<0)
+ err=err2;
+ }
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -1109,16 +1063,14 @@
struct socket *sock;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- if (level == SOL_SOCKET)
- err = sock_setsockopt(sock,level,optname,optval,optlen);
- else if (sock->ops->setsockopt)
- err = sock->ops->setsockopt(sock, level, optname, optval, optlen);
- else
- err = -EOPNOTSUPP;
-out:
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ if (level == SOL_SOCKET)
+ err=sock_setsockopt(sock,level,optname,optval,optlen);
+ else
+ err=sock->ops->setsockopt(sock, level, optname, optval, optlen);
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -1134,16 +1086,14 @@
struct socket *sock;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- if (level == SOL_SOCKET)
- err = sock_getsockopt(sock,level,optname,optval,optlen);
- else if (sock->ops->getsockopt)
- err = sock->ops->getsockopt(sock, level, optname, optval, optlen);
- else
- err = -EOPNOTSUPP;
-out:
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ if (level == SOL_SOCKET)
+ err=sock_getsockopt(sock,level,optname,optval,optlen);
+ else
+ err=sock->ops->getsockopt(sock, level, optname, optval, optlen);
+ sockfd_put(sock);
+ }
unlock_kernel();
return err;
}
@@ -1159,12 +1109,11 @@
struct socket *sock;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- err = sock->ops->shutdown(sock, how);
-out:
- unlock_kernel();
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ err=sock->ops->shutdown(sock, how);
+ sockfd_put(sock);
+ }
return err;
}
@@ -1179,36 +1128,32 @@
struct iovec iov[UIO_FASTIOV];
unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */
struct msghdr msg_sys;
- int err;
+ int err= -EINVAL;
int total_len;
lock_kernel();
- if (!(sock = sockfd_lookup(fd,&err)))
- goto out;
-
- err = -EOPNOTSUPP;
- if (sock->ops->sendmsg==NULL)
- goto out;
- err = -EFAULT;
if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
- goto out;
-
+ {
+ err=-EFAULT;
+ goto out;
+ }
/* do not move before msg_sys is valid */
- err = -EINVAL;
if (msg_sys.msg_iovlen>UIO_MAXIOV)
goto out;
-
/* This will also move the address data into kernel space */
err = verify_iovec(&msg_sys, iov, address, VERIFY_READ);
if (err < 0)
goto out;
total_len=err;
- if (msg_sys.msg_controllen) {
- if (msg_sys.msg_controllen > sizeof(ctl)) {
+ if (msg_sys.msg_controllen)
+ {
+ if (msg_sys.msg_controllen > sizeof(ctl))
+ {
char *tmp = kmalloc(msg_sys.msg_controllen, GFP_KERNEL);
- if (tmp == NULL) {
+ if (tmp == NULL)
+ {
err = -ENOBUFS;
goto failed2;
}
@@ -1221,12 +1166,15 @@
if (err)
goto failed;
}
-
msg_sys.msg_flags = flags;
if (current->files->fd[fd]->f_flags & O_NONBLOCK)
msg_sys.msg_flags |= MSG_DONTWAIT;
- err = sock_sendmsg(sock, &msg_sys, total_len);
+ if ((sock = sockfd_lookup(fd,&err))!=NULL)
+ {
+ err = sock_sendmsg(sock, &msg_sys, total_len);
+ sockfd_put(sock);
+ }
failed:
if (msg_sys.msg_controllen && msg_sys.msg_control != ctl)
@@ -1262,17 +1210,17 @@
int *uaddr_len;
lock_kernel();
- if (!(sock = sockfd_lookup(fd, &err)))
- goto out;
-
- err = -EFAULT;
if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
- goto out;
-
- err = -EINVAL;
+ {
+ err=-EFAULT;
+ goto out;
+ }
if (msg_sys.msg_iovlen>UIO_MAXIOV)
+ {
+ err=-EFAULT;
goto out;
-
+ }
+
/*
* Save the user-mode address (verify_iovec will change the
* kernel msghdr to use the kernel address space)
@@ -1291,34 +1239,35 @@
if (current->files->fd[fd]->f_flags&O_NONBLOCK)
flags |= MSG_DONTWAIT;
- len=sock_recvmsg(sock, &msg_sys, total_len, flags);
+
+
+ if ((sock = sockfd_lookup(fd, &err))!=NULL)
+ {
+ err=sock_recvmsg(sock, &msg_sys, total_len, flags);
+ if(err>=0)
+ len=err;
+ sockfd_put(sock);
+ }
if (msg_sys.msg_iov != iov)
kfree(msg_sys.msg_iov);
- if (len<0) {
- err = len;
- goto out;
- }
- if (uaddr != NULL)
- {
+ if (uaddr != NULL && err>=0)
err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
- if (err)
- goto out;
- }
- err = -EFAULT;
- if (put_user(msg_sys.msg_flags, &msg->msg_flags))
- goto out;
- if (put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, &msg->msg_controllen))
- goto out;
- err = len;
+ if (err>=0 && (put_user(msg_sys.msg_flags, &msg->msg_flags) ||
+ put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, &msg->msg_controllen)))
+ err = -EFAULT;
out:
unlock_kernel();
- return err;
+ if(err<0)
+ return err;
+ return len;
}
/*
* Perform a file control on a socket file descriptor.
+ *
+ * FIXME: does this need an fd lock ?
*/
int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -1356,6 +1305,12 @@
if(call<1||call>SYS_RECVMSG)
goto out;
err = -EFAULT;
+
+ /*
+ * Ideally we want to precompute the maths, but unsigned long
+ * isnt a fixed size....
+ */
+
if ((copy_from_user(a, args, nargs[call] * sizeof(unsigned long))))
goto out;
@@ -1478,7 +1433,8 @@
* Initialize all address (protocol) families.
*/
- for (i = 0; i < NPROTO; i++) net_families[i] = NULL;
+ for (i = 0; i < NPROTO; i++)
+ net_families[i] = NULL;
/*
* Initialize sock SLAB cache.
@@ -1492,6 +1448,14 @@
#ifdef CONFIG_NETLINK
init_netlink();
+#endif
+
+ /*
+ * Wan router layer.
+ */
+
+#ifdef CONFIG_WAN_ROUTER
+ wanrouter_init();
#endif
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov