diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 73 |
1 files changed, 40 insertions, 33 deletions
diff --git a/net/socket.c b/net/socket.c index 7ec8f9b669b3..2517e11a5300 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1871,8 +1871,14 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how) | |||
1871 | #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) | 1871 | #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) |
1872 | #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) | 1872 | #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) |
1873 | 1873 | ||
1874 | struct used_address { | ||
1875 | struct sockaddr_storage name; | ||
1876 | unsigned int name_len; | ||
1877 | }; | ||
1878 | |||
1874 | static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | 1879 | static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, |
1875 | struct msghdr *msg_sys, unsigned flags, int nosec) | 1880 | struct msghdr *msg_sys, unsigned flags, |
1881 | struct used_address *used_address) | ||
1876 | { | 1882 | { |
1877 | struct compat_msghdr __user *msg_compat = | 1883 | struct compat_msghdr __user *msg_compat = |
1878 | (struct compat_msghdr __user *)msg; | 1884 | (struct compat_msghdr __user *)msg; |
@@ -1953,8 +1959,28 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | |||
1953 | 1959 | ||
1954 | if (sock->file->f_flags & O_NONBLOCK) | 1960 | if (sock->file->f_flags & O_NONBLOCK) |
1955 | msg_sys->msg_flags |= MSG_DONTWAIT; | 1961 | msg_sys->msg_flags |= MSG_DONTWAIT; |
1956 | err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys, | 1962 | /* |
1957 | total_len); | 1963 | * If this is sendmmsg() and current destination address is same as |
1964 | * previously succeeded address, omit asking LSM's decision. | ||
1965 | * used_address->name_len is initialized to UINT_MAX so that the first | ||
1966 | * destination address never matches. | ||
1967 | */ | ||
1968 | if (used_address && used_address->name_len == msg_sys->msg_namelen && | ||
1969 | !memcmp(&used_address->name, msg->msg_name, | ||
1970 | used_address->name_len)) { | ||
1971 | err = sock_sendmsg_nosec(sock, msg_sys, total_len); | ||
1972 | goto out_freectl; | ||
1973 | } | ||
1974 | err = sock_sendmsg(sock, msg_sys, total_len); | ||
1975 | /* | ||
1976 | * If this is sendmmsg() and sending to current destination address was | ||
1977 | * successful, remember it. | ||
1978 | */ | ||
1979 | if (used_address && err >= 0) { | ||
1980 | used_address->name_len = msg_sys->msg_namelen; | ||
1981 | memcpy(&used_address->name, msg->msg_name, | ||
1982 | used_address->name_len); | ||
1983 | } | ||
1958 | 1984 | ||
1959 | out_freectl: | 1985 | out_freectl: |
1960 | if (ctl_buf != ctl) | 1986 | if (ctl_buf != ctl) |
@@ -1979,7 +2005,7 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) | |||
1979 | if (!sock) | 2005 | if (!sock) |
1980 | goto out; | 2006 | goto out; |
1981 | 2007 | ||
1982 | err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0); | 2008 | err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL); |
1983 | 2009 | ||
1984 | fput_light(sock->file, fput_needed); | 2010 | fput_light(sock->file, fput_needed); |
1985 | out: | 2011 | out: |
@@ -1998,6 +2024,10 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
1998 | struct mmsghdr __user *entry; | 2024 | struct mmsghdr __user *entry; |
1999 | struct compat_mmsghdr __user *compat_entry; | 2025 | struct compat_mmsghdr __user *compat_entry; |
2000 | struct msghdr msg_sys; | 2026 | struct msghdr msg_sys; |
2027 | struct used_address used_address; | ||
2028 | |||
2029 | if (vlen > UIO_MAXIOV) | ||
2030 | vlen = UIO_MAXIOV; | ||
2001 | 2031 | ||
2002 | datagrams = 0; | 2032 | datagrams = 0; |
2003 | 2033 | ||
@@ -2005,27 +2035,22 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2005 | if (!sock) | 2035 | if (!sock) |
2006 | return err; | 2036 | return err; |
2007 | 2037 | ||
2008 | err = sock_error(sock->sk); | 2038 | used_address.name_len = UINT_MAX; |
2009 | if (err) | ||
2010 | goto out_put; | ||
2011 | |||
2012 | entry = mmsg; | 2039 | entry = mmsg; |
2013 | compat_entry = (struct compat_mmsghdr __user *)mmsg; | 2040 | compat_entry = (struct compat_mmsghdr __user *)mmsg; |
2041 | err = 0; | ||
2014 | 2042 | ||
2015 | while (datagrams < vlen) { | 2043 | while (datagrams < vlen) { |
2016 | /* | ||
2017 | * No need to ask LSM for more than the first datagram. | ||
2018 | */ | ||
2019 | if (MSG_CMSG_COMPAT & flags) { | 2044 | if (MSG_CMSG_COMPAT & flags) { |
2020 | err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, | 2045 | err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, |
2021 | &msg_sys, flags, datagrams); | 2046 | &msg_sys, flags, &used_address); |
2022 | if (err < 0) | 2047 | if (err < 0) |
2023 | break; | 2048 | break; |
2024 | err = __put_user(err, &compat_entry->msg_len); | 2049 | err = __put_user(err, &compat_entry->msg_len); |
2025 | ++compat_entry; | 2050 | ++compat_entry; |
2026 | } else { | 2051 | } else { |
2027 | err = __sys_sendmsg(sock, (struct msghdr __user *)entry, | 2052 | err = __sys_sendmsg(sock, (struct msghdr __user *)entry, |
2028 | &msg_sys, flags, datagrams); | 2053 | &msg_sys, flags, &used_address); |
2029 | if (err < 0) | 2054 | if (err < 0) |
2030 | break; | 2055 | break; |
2031 | err = put_user(err, &entry->msg_len); | 2056 | err = put_user(err, &entry->msg_len); |
@@ -2037,29 +2062,11 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
2037 | ++datagrams; | 2062 | ++datagrams; |
2038 | } | 2063 | } |
2039 | 2064 | ||
2040 | out_put: | ||
2041 | fput_light(sock->file, fput_needed); | 2065 | fput_light(sock->file, fput_needed); |
2042 | 2066 | ||
2043 | if (err == 0) | 2067 | /* We only return an error if no datagrams were able to be sent */ |
2044 | return datagrams; | 2068 | if (datagrams != 0) |
2045 | |||
2046 | if (datagrams != 0) { | ||
2047 | /* | ||
2048 | * We may send less entries than requested (vlen) if the | ||
2049 | * sock is non blocking... | ||
2050 | */ | ||
2051 | if (err != -EAGAIN) { | ||
2052 | /* | ||
2053 | * ... or if sendmsg returns an error after we | ||
2054 | * send some datagrams, where we record the | ||
2055 | * error to return on the next call or if the | ||
2056 | * app asks about it using getsockopt(SO_ERROR). | ||
2057 | */ | ||
2058 | sock->sk->sk_err = -err; | ||
2059 | } | ||
2060 | |||
2061 | return datagrams; | 2069 | return datagrams; |
2062 | } | ||
2063 | 2070 | ||
2064 | return err; | 2071 | return err; |
2065 | } | 2072 | } |