diff options
| -rw-r--r-- | net/socket.c | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/net/socket.c b/net/socket.c index b5c6de4f268a..24a77400b65e 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,7 @@ 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; | ||
| 2001 | 2028 | ||
| 2002 | if (vlen > UIO_MAXIOV) | 2029 | if (vlen > UIO_MAXIOV) |
| 2003 | vlen = UIO_MAXIOV; | 2030 | vlen = UIO_MAXIOV; |
| @@ -2008,24 +2035,22 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
| 2008 | if (!sock) | 2035 | if (!sock) |
| 2009 | return err; | 2036 | return err; |
| 2010 | 2037 | ||
| 2038 | used_address.name_len = UINT_MAX; | ||
| 2011 | entry = mmsg; | 2039 | entry = mmsg; |
| 2012 | compat_entry = (struct compat_mmsghdr __user *)mmsg; | 2040 | compat_entry = (struct compat_mmsghdr __user *)mmsg; |
| 2013 | err = 0; | 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); |
