aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-08-18 00:25:51 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-09-26 21:08:50 -0400
commit56b31d1c9f1e6a3ad92e7bfe252721e05d92b285 (patch)
tree44521dbcdf51695b6092f2a4dabe83f460c2ed7c /net/sctp/socket.c
parent28407630513b1a86133db0ef8b39fabad6c494af (diff)
unexport sock_map_fd(), switch to sock_alloc_file()
Both modular callers of sock_map_fd() had been buggy; sctp one leaks descriptor and file if copy_to_user() fails, 9p one shouldn't be exposing file in the descriptor table at all. Switch both to sock_alloc_file(), export it, unexport sock_map_fd() and make it static. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5e259817a7f..fb5931ca50d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -70,6 +70,7 @@
70#include <linux/init.h> 70#include <linux/init.h>
71#include <linux/crypto.h> 71#include <linux/crypto.h>
72#include <linux/slab.h> 72#include <linux/slab.h>
73#include <linux/file.h>
73 74
74#include <net/ip.h> 75#include <net/ip.h>
75#include <net/icmp.h> 76#include <net/icmp.h>
@@ -4276,6 +4277,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
4276{ 4277{
4277 sctp_peeloff_arg_t peeloff; 4278 sctp_peeloff_arg_t peeloff;
4278 struct socket *newsock; 4279 struct socket *newsock;
4280 struct file *newfile;
4279 int retval = 0; 4281 int retval = 0;
4280 4282
4281 if (len < sizeof(sctp_peeloff_arg_t)) 4283 if (len < sizeof(sctp_peeloff_arg_t))
@@ -4289,22 +4291,35 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
4289 goto out; 4291 goto out;
4290 4292
4291 /* Map the socket to an unused fd that can be returned to the user. */ 4293 /* Map the socket to an unused fd that can be returned to the user. */
4292 retval = sock_map_fd(newsock, 0); 4294 retval = get_unused_fd();
4293 if (retval < 0) { 4295 if (retval < 0) {
4294 sock_release(newsock); 4296 sock_release(newsock);
4295 goto out; 4297 goto out;
4296 } 4298 }
4297 4299
4300 newfile = sock_alloc_file(newsock, 0);
4301 if (unlikely(IS_ERR(newfile))) {
4302 put_unused_fd(retval);
4303 sock_release(newsock);
4304 return PTR_ERR(newfile);
4305 }
4306
4298 SCTP_DEBUG_PRINTK("%s: sk: %p newsk: %p sd: %d\n", 4307 SCTP_DEBUG_PRINTK("%s: sk: %p newsk: %p sd: %d\n",
4299 __func__, sk, newsock->sk, retval); 4308 __func__, sk, newsock->sk, retval);
4300 4309
4301 /* Return the fd mapped to the new socket. */ 4310 /* Return the fd mapped to the new socket. */
4311 if (put_user(len, optlen)) {
4312 fput(newfile);
4313 put_unused_fd(retval);
4314 return -EFAULT;
4315 }
4302 peeloff.sd = retval; 4316 peeloff.sd = retval;
4303 if (put_user(len, optlen)) 4317 if (copy_to_user(optval, &peeloff, len)) {
4318 fput(newfile);
4319 put_unused_fd(retval);
4304 return -EFAULT; 4320 return -EFAULT;
4305 if (copy_to_user(optval, &peeloff, len)) 4321 }
4306 retval = -EFAULT; 4322 fd_install(retval, newfile);
4307
4308out: 4323out:
4309 return retval; 4324 return retval;
4310} 4325}