|
@@ -64,6 +64,7 @@
|
|
|
#include <linux/crypto.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/file.h>
|
|
|
+#include <linux/compat.h>
|
|
|
|
|
|
#include <net/ip.h>
|
|
|
#include <net/icmp.h>
|
|
@@ -1368,11 +1369,19 @@ static int sctp_setsockopt_connectx(struct sock *sk,
|
|
|
/*
|
|
|
* New (hopefully final) interface for the API.
|
|
|
* We use the sctp_getaddrs_old structure so that use-space library
|
|
|
- * can avoid any unnecessary allocations. The only defferent part
|
|
|
+ * can avoid any unnecessary allocations. The only different part
|
|
|
* is that we store the actual length of the address buffer into the
|
|
|
- * addrs_num structure member. That way we can re-use the existing
|
|
|
+ * addrs_num structure member. That way we can re-use the existing
|
|
|
* code.
|
|
|
*/
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+struct compat_sctp_getaddrs_old {
|
|
|
+ sctp_assoc_t assoc_id;
|
|
|
+ s32 addr_num;
|
|
|
+ compat_uptr_t addrs; /* struct sockaddr * */
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
static int sctp_getsockopt_connectx3(struct sock *sk, int len,
|
|
|
char __user *optval,
|
|
|
int __user *optlen)
|
|
@@ -1381,16 +1390,30 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len,
|
|
|
sctp_assoc_t assoc_id = 0;
|
|
|
int err = 0;
|
|
|
|
|
|
- if (len < sizeof(param))
|
|
|
- return -EINVAL;
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+ if (is_compat_task()) {
|
|
|
+ struct compat_sctp_getaddrs_old param32;
|
|
|
|
|
|
- if (copy_from_user(¶m, optval, sizeof(param)))
|
|
|
- return -EFAULT;
|
|
|
+ if (len < sizeof(param32))
|
|
|
+ return -EINVAL;
|
|
|
+ if (copy_from_user(¶m32, optval, sizeof(param32)))
|
|
|
+ return -EFAULT;
|
|
|
|
|
|
- err = __sctp_setsockopt_connectx(sk,
|
|
|
- (struct sockaddr __user *)param.addrs,
|
|
|
- param.addr_num, &assoc_id);
|
|
|
+ param.assoc_id = param32.assoc_id;
|
|
|
+ param.addr_num = param32.addr_num;
|
|
|
+ param.addrs = compat_ptr(param32.addrs);
|
|
|
+ } else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ if (len < sizeof(param))
|
|
|
+ return -EINVAL;
|
|
|
+ if (copy_from_user(¶m, optval, sizeof(param)))
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
|
|
|
+ err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *)
|
|
|
+ param.addrs, param.addr_num,
|
|
|
+ &assoc_id);
|
|
|
if (err == 0 || err == -EINPROGRESS) {
|
|
|
if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))
|
|
|
return -EFAULT;
|