diff options
Diffstat (limited to 'net/sctp/socket.c')
| -rw-r--r-- | net/sctp/socket.c | 90 |
1 files changed, 56 insertions, 34 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 02e068d3450d..b529af5e6f2a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -1010,6 +1010,19 @@ static int __sctp_connect(struct sock* sk, | |||
| 1010 | err = -EAGAIN; | 1010 | err = -EAGAIN; |
| 1011 | goto out_free; | 1011 | goto out_free; |
| 1012 | } | 1012 | } |
| 1013 | } else { | ||
| 1014 | /* | ||
| 1015 | * If an unprivileged user inherits a 1-many | ||
| 1016 | * style socket with open associations on a | ||
| 1017 | * privileged port, it MAY be permitted to | ||
| 1018 | * accept new associations, but it SHOULD NOT | ||
| 1019 | * be permitted to open new associations. | ||
| 1020 | */ | ||
| 1021 | if (ep->base.bind_addr.port < PROT_SOCK && | ||
| 1022 | !capable(CAP_NET_BIND_SERVICE)) { | ||
| 1023 | err = -EACCES; | ||
| 1024 | goto out_free; | ||
| 1025 | } | ||
| 1013 | } | 1026 | } |
| 1014 | 1027 | ||
| 1015 | scope = sctp_scope(&to); | 1028 | scope = sctp_scope(&to); |
| @@ -1389,27 +1402,27 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1389 | SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n", | 1402 | SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n", |
| 1390 | msg_len, sinfo_flags); | 1403 | msg_len, sinfo_flags); |
| 1391 | 1404 | ||
| 1392 | /* MSG_EOF or MSG_ABORT cannot be set on a TCP-style socket. */ | 1405 | /* SCTP_EOF or SCTP_ABORT cannot be set on a TCP-style socket. */ |
| 1393 | if (sctp_style(sk, TCP) && (sinfo_flags & (MSG_EOF | MSG_ABORT))) { | 1406 | if (sctp_style(sk, TCP) && (sinfo_flags & (SCTP_EOF | SCTP_ABORT))) { |
| 1394 | err = -EINVAL; | 1407 | err = -EINVAL; |
| 1395 | goto out_nounlock; | 1408 | goto out_nounlock; |
| 1396 | } | 1409 | } |
| 1397 | 1410 | ||
| 1398 | /* If MSG_EOF is set, no data can be sent. Disallow sending zero | 1411 | /* If SCTP_EOF is set, no data can be sent. Disallow sending zero |
| 1399 | * length messages when MSG_EOF|MSG_ABORT is not set. | 1412 | * length messages when SCTP_EOF|SCTP_ABORT is not set. |
| 1400 | * If MSG_ABORT is set, the message length could be non zero with | 1413 | * If SCTP_ABORT is set, the message length could be non zero with |
| 1401 | * the msg_iov set to the user abort reason. | 1414 | * the msg_iov set to the user abort reason. |
| 1402 | */ | 1415 | */ |
| 1403 | if (((sinfo_flags & MSG_EOF) && (msg_len > 0)) || | 1416 | if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) || |
| 1404 | (!(sinfo_flags & (MSG_EOF|MSG_ABORT)) && (msg_len == 0))) { | 1417 | (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) { |
| 1405 | err = -EINVAL; | 1418 | err = -EINVAL; |
| 1406 | goto out_nounlock; | 1419 | goto out_nounlock; |
| 1407 | } | 1420 | } |
| 1408 | 1421 | ||
| 1409 | /* If MSG_ADDR_OVER is set, there must be an address | 1422 | /* If SCTP_ADDR_OVER is set, there must be an address |
| 1410 | * specified in msg_name. | 1423 | * specified in msg_name. |
| 1411 | */ | 1424 | */ |
| 1412 | if ((sinfo_flags & MSG_ADDR_OVER) && (!msg->msg_name)) { | 1425 | if ((sinfo_flags & SCTP_ADDR_OVER) && (!msg->msg_name)) { |
| 1413 | err = -EINVAL; | 1426 | err = -EINVAL; |
| 1414 | goto out_nounlock; | 1427 | goto out_nounlock; |
| 1415 | } | 1428 | } |
| @@ -1458,14 +1471,14 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1458 | goto out_unlock; | 1471 | goto out_unlock; |
| 1459 | } | 1472 | } |
| 1460 | 1473 | ||
| 1461 | if (sinfo_flags & MSG_EOF) { | 1474 | if (sinfo_flags & SCTP_EOF) { |
| 1462 | SCTP_DEBUG_PRINTK("Shutting down association: %p\n", | 1475 | SCTP_DEBUG_PRINTK("Shutting down association: %p\n", |
| 1463 | asoc); | 1476 | asoc); |
| 1464 | sctp_primitive_SHUTDOWN(asoc, NULL); | 1477 | sctp_primitive_SHUTDOWN(asoc, NULL); |
| 1465 | err = 0; | 1478 | err = 0; |
| 1466 | goto out_unlock; | 1479 | goto out_unlock; |
| 1467 | } | 1480 | } |
| 1468 | if (sinfo_flags & MSG_ABORT) { | 1481 | if (sinfo_flags & SCTP_ABORT) { |
| 1469 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); | 1482 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); |
| 1470 | sctp_primitive_ABORT(asoc, msg); | 1483 | sctp_primitive_ABORT(asoc, msg); |
| 1471 | err = 0; | 1484 | err = 0; |
| @@ -1477,7 +1490,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1477 | if (!asoc) { | 1490 | if (!asoc) { |
| 1478 | SCTP_DEBUG_PRINTK("There is no association yet.\n"); | 1491 | SCTP_DEBUG_PRINTK("There is no association yet.\n"); |
| 1479 | 1492 | ||
| 1480 | if (sinfo_flags & (MSG_EOF | MSG_ABORT)) { | 1493 | if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) { |
| 1481 | err = -EINVAL; | 1494 | err = -EINVAL; |
| 1482 | goto out_unlock; | 1495 | goto out_unlock; |
| 1483 | } | 1496 | } |
| @@ -1515,6 +1528,19 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1515 | err = -EAGAIN; | 1528 | err = -EAGAIN; |
| 1516 | goto out_unlock; | 1529 | goto out_unlock; |
| 1517 | } | 1530 | } |
| 1531 | } else { | ||
| 1532 | /* | ||
| 1533 | * If an unprivileged user inherits a one-to-many | ||
| 1534 | * style socket with open associations on a privileged | ||
| 1535 | * port, it MAY be permitted to accept new associations, | ||
| 1536 | * but it SHOULD NOT be permitted to open new | ||
| 1537 | * associations. | ||
| 1538 | */ | ||
| 1539 | if (ep->base.bind_addr.port < PROT_SOCK && | ||
| 1540 | !capable(CAP_NET_BIND_SERVICE)) { | ||
| 1541 | err = -EACCES; | ||
| 1542 | goto out_unlock; | ||
| 1543 | } | ||
| 1518 | } | 1544 | } |
| 1519 | 1545 | ||
| 1520 | scope = sctp_scope(&to); | 1546 | scope = sctp_scope(&to); |
| @@ -1611,10 +1637,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1611 | 1637 | ||
| 1612 | /* If an address is passed with the sendto/sendmsg call, it is used | 1638 | /* If an address is passed with the sendto/sendmsg call, it is used |
| 1613 | * to override the primary destination address in the TCP model, or | 1639 | * to override the primary destination address in the TCP model, or |
| 1614 | * when MSG_ADDR_OVER flag is set in the UDP model. | 1640 | * when SCTP_ADDR_OVER flag is set in the UDP model. |
| 1615 | */ | 1641 | */ |
| 1616 | if ((sctp_style(sk, TCP) && msg_name) || | 1642 | if ((sctp_style(sk, TCP) && msg_name) || |
| 1617 | (sinfo_flags & MSG_ADDR_OVER)) { | 1643 | (sinfo_flags & SCTP_ADDR_OVER)) { |
| 1618 | chunk_tp = sctp_assoc_lookup_paddr(asoc, &to); | 1644 | chunk_tp = sctp_assoc_lookup_paddr(asoc, &to); |
| 1619 | if (!chunk_tp) { | 1645 | if (!chunk_tp) { |
| 1620 | err = -EINVAL; | 1646 | err = -EINVAL; |
| @@ -2306,16 +2332,14 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl | |||
| 2306 | return -EINVAL; | 2332 | return -EINVAL; |
| 2307 | if (get_user(val, (int __user *)optval)) | 2333 | if (get_user(val, (int __user *)optval)) |
| 2308 | return -EFAULT; | 2334 | return -EFAULT; |
| 2309 | if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)) | 2335 | if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) |
| 2310 | return -EINVAL; | 2336 | return -EINVAL; |
| 2311 | sp->user_frag = val; | 2337 | sp->user_frag = val; |
| 2312 | 2338 | ||
| 2313 | if (val) { | 2339 | /* Update the frag_point of the existing associations. */ |
| 2314 | /* Update the frag_point of the existing associations. */ | 2340 | list_for_each(pos, &(sp->ep->asocs)) { |
| 2315 | list_for_each(pos, &(sp->ep->asocs)) { | 2341 | asoc = list_entry(pos, struct sctp_association, asocs); |
| 2316 | asoc = list_entry(pos, struct sctp_association, asocs); | 2342 | asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); |
| 2317 | asoc->frag_point = sctp_frag_point(sp, asoc->pmtu); | ||
| 2318 | } | ||
| 2319 | } | 2343 | } |
| 2320 | 2344 | ||
| 2321 | return 0; | 2345 | return 0; |
| @@ -2384,14 +2408,14 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva | |||
| 2384 | static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval, | 2408 | static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval, |
| 2385 | int optlen) | 2409 | int optlen) |
| 2386 | { | 2410 | { |
| 2387 | __u32 val; | 2411 | struct sctp_setadaption adaption; |
| 2388 | 2412 | ||
| 2389 | if (optlen < sizeof(__u32)) | 2413 | if (optlen != sizeof(struct sctp_setadaption)) |
| 2390 | return -EINVAL; | 2414 | return -EINVAL; |
| 2391 | if (copy_from_user(&val, optval, sizeof(__u32))) | 2415 | if (copy_from_user(&adaption, optval, optlen)) |
| 2392 | return -EFAULT; | 2416 | return -EFAULT; |
| 2393 | 2417 | ||
| 2394 | sctp_sk(sk)->adaption_ind = val; | 2418 | sctp_sk(sk)->adaption_ind = adaption.ssb_adaption_ind; |
| 2395 | 2419 | ||
| 2396 | return 0; | 2420 | return 0; |
| 2397 | } | 2421 | } |
| @@ -3672,17 +3696,15 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, | |||
| 3672 | static int sctp_getsockopt_adaption_layer(struct sock *sk, int len, | 3696 | static int sctp_getsockopt_adaption_layer(struct sock *sk, int len, |
| 3673 | char __user *optval, int __user *optlen) | 3697 | char __user *optval, int __user *optlen) |
| 3674 | { | 3698 | { |
| 3675 | __u32 val; | 3699 | struct sctp_setadaption adaption; |
| 3676 | 3700 | ||
| 3677 | if (len < sizeof(__u32)) | 3701 | if (len != sizeof(struct sctp_setadaption)) |
| 3678 | return -EINVAL; | 3702 | return -EINVAL; |
| 3679 | 3703 | ||
| 3680 | len = sizeof(__u32); | 3704 | adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind; |
| 3681 | val = sctp_sk(sk)->adaption_ind; | 3705 | if (copy_to_user(optval, &adaption, len)) |
| 3682 | if (put_user(len, optlen)) | ||
| 3683 | return -EFAULT; | ||
| 3684 | if (copy_to_user(optval, &val, len)) | ||
| 3685 | return -EFAULT; | 3706 | return -EFAULT; |
| 3707 | |||
| 3686 | return 0; | 3708 | return 0; |
| 3687 | } | 3709 | } |
| 3688 | 3710 | ||
| @@ -4640,8 +4662,8 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, | |||
| 4640 | 4662 | ||
| 4641 | /* Minimally, validate the sinfo_flags. */ | 4663 | /* Minimally, validate the sinfo_flags. */ |
| 4642 | if (cmsgs->info->sinfo_flags & | 4664 | if (cmsgs->info->sinfo_flags & |
| 4643 | ~(MSG_UNORDERED | MSG_ADDR_OVER | | 4665 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | |
| 4644 | MSG_ABORT | MSG_EOF)) | 4666 | SCTP_ABORT | SCTP_EOF)) |
| 4645 | return -EINVAL; | 4667 | return -EINVAL; |
| 4646 | break; | 4668 | break; |
| 4647 | 4669 | ||
