diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-11-11 03:19:24 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-13 22:56:51 -0500 |
commit | f9c67811ebc00a42f62f5d542d3abd36bd49ae35 (patch) | |
tree | f58d9f0c0ae23ded2f758b73e2c47a97a25376a3 /net/sctp | |
parent | 409b95aff3583c05ac7a9247fa3d8c9aa7f9cae3 (diff) |
sctp: Fix regression introduced by new sctp_connectx api
A new (unrealeased to the user) sctp_connectx api
c6ba68a26645dbc5029a9faa5687ebe6fcfc53e4
sctp: support non-blocking version of the new sctp_connectx() API
introduced a regression cought by the user regression test
suite. In particular, the API requires the user library to
re-allocate the buffer and could potentially trigger a SIGFAULT.
This change corrects that regression by passing the original
address buffer to the kernel unmodified, but still allows for
a returned association id.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/socket.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index bf705ba97231..3a95fcb17a9e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1276,22 +1276,30 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | |||
1276 | } | 1276 | } |
1277 | 1277 | ||
1278 | /* | 1278 | /* |
1279 | * New (hopefully final) interface for the API. The option buffer is used | 1279 | * New (hopefully final) interface for the API. |
1280 | * both for the returned association id and the addresses. | 1280 | * We use the sctp_getaddrs_old structure so that use-space library |
1281 | * can avoid any unnecessary allocations. The only defferent part | ||
1282 | * is that we store the actual length of the address buffer into the | ||
1283 | * addrs_num structure member. That way we can re-use the existing | ||
1284 | * code. | ||
1281 | */ | 1285 | */ |
1282 | SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, | 1286 | SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, |
1283 | char __user *optval, | 1287 | char __user *optval, |
1284 | int __user *optlen) | 1288 | int __user *optlen) |
1285 | { | 1289 | { |
1290 | struct sctp_getaddrs_old param; | ||
1286 | sctp_assoc_t assoc_id = 0; | 1291 | sctp_assoc_t assoc_id = 0; |
1287 | int err = 0; | 1292 | int err = 0; |
1288 | 1293 | ||
1289 | if (len < sizeof(assoc_id)) | 1294 | if (len < sizeof(param)) |
1290 | return -EINVAL; | 1295 | return -EINVAL; |
1291 | 1296 | ||
1297 | if (copy_from_user(¶m, optval, sizeof(param))) | ||
1298 | return -EFAULT; | ||
1299 | |||
1292 | err = __sctp_setsockopt_connectx(sk, | 1300 | err = __sctp_setsockopt_connectx(sk, |
1293 | (struct sockaddr __user *)(optval + sizeof(assoc_id)), | 1301 | (struct sockaddr __user *)param.addrs, |
1294 | len - sizeof(assoc_id), &assoc_id); | 1302 | param.addr_num, &assoc_id); |
1295 | 1303 | ||
1296 | if (err == 0 || err == -EINPROGRESS) { | 1304 | if (err == 0 || err == -EINPROGRESS) { |
1297 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) | 1305 | if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) |