diff options
author | Atul Gupta <atul.gupta@chelsio.com> | 2018-05-27 11:45:19 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2018-05-30 12:13:58 -0400 |
commit | 3b8305f5c844685d00637a0ad155e90e423a4445 (patch) | |
tree | 7f9eefab8b29dbd5488af16d09d19b5828f67792 | |
parent | 09e53d8289477449ddd74cfff640792ca02fa90d (diff) |
crypto: chtls - wait for memory sendmsg, sendpage
address suspicious code <gustavo@embeddedor.com>
1210 set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
1211 }
The issue is that in the code above, set_bit is never reached
due to the 'continue' statement at line 1208.
Also reported by bug report:<dan.carpenter@oracle.com>
1210 set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Not reachable.
Its required to wait for buffer in the send path and takes care of
unaddress and un-handled SOCK_NOSPACE.
v2: use csk_mem_free where appropriate
proper indent of goto do_nonblock
replace out with do_rm_wq
Reported-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Atul Gupta <atul.gupta@chelsio.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/crypto/chelsio/chtls/chtls.h | 1 | ||||
-rw-r--r-- | drivers/crypto/chelsio/chtls/chtls_io.c | 90 | ||||
-rw-r--r-- | drivers/crypto/chelsio/chtls/chtls_main.c | 1 |
3 files changed, 89 insertions, 3 deletions
diff --git a/drivers/crypto/chelsio/chtls/chtls.h b/drivers/crypto/chelsio/chtls/chtls.h index 1b2f43ccb11e..a53a0e6ba024 100644 --- a/drivers/crypto/chelsio/chtls/chtls.h +++ b/drivers/crypto/chelsio/chtls/chtls.h | |||
@@ -144,6 +144,7 @@ struct chtls_dev { | |||
144 | struct list_head rcu_node; | 144 | struct list_head rcu_node; |
145 | struct list_head na_node; | 145 | struct list_head na_node; |
146 | unsigned int send_page_order; | 146 | unsigned int send_page_order; |
147 | int max_host_sndbuf; | ||
147 | struct key_map kmap; | 148 | struct key_map kmap; |
148 | }; | 149 | }; |
149 | 150 | ||
diff --git a/drivers/crypto/chelsio/chtls/chtls_io.c b/drivers/crypto/chelsio/chtls/chtls_io.c index 840dd0100c2f..7aa5d90c6ebd 100644 --- a/drivers/crypto/chelsio/chtls/chtls_io.c +++ b/drivers/crypto/chelsio/chtls/chtls_io.c | |||
@@ -914,6 +914,78 @@ static u16 tls_header_read(struct tls_hdr *thdr, struct iov_iter *from) | |||
914 | return (__force u16)cpu_to_be16(thdr->length); | 914 | return (__force u16)cpu_to_be16(thdr->length); |
915 | } | 915 | } |
916 | 916 | ||
917 | static int csk_mem_free(struct chtls_dev *cdev, struct sock *sk) | ||
918 | { | ||
919 | return (cdev->max_host_sndbuf - sk->sk_wmem_queued); | ||
920 | } | ||
921 | |||
922 | static int csk_wait_memory(struct chtls_dev *cdev, | ||
923 | struct sock *sk, long *timeo_p) | ||
924 | { | ||
925 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | ||
926 | int sndbuf, err = 0; | ||
927 | long current_timeo; | ||
928 | long vm_wait = 0; | ||
929 | bool noblock; | ||
930 | |||
931 | current_timeo = *timeo_p; | ||
932 | noblock = (*timeo_p ? false : true); | ||
933 | sndbuf = cdev->max_host_sndbuf; | ||
934 | if (csk_mem_free(cdev, sk)) { | ||
935 | current_timeo = (prandom_u32() % (HZ / 5)) + 2; | ||
936 | vm_wait = (prandom_u32() % (HZ / 5)) + 2; | ||
937 | } | ||
938 | |||
939 | add_wait_queue(sk_sleep(sk), &wait); | ||
940 | while (1) { | ||
941 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); | ||
942 | |||
943 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | ||
944 | goto do_error; | ||
945 | if (!*timeo_p) { | ||
946 | if (noblock) | ||
947 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
948 | goto do_nonblock; | ||
949 | } | ||
950 | if (signal_pending(current)) | ||
951 | goto do_interrupted; | ||
952 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); | ||
953 | if (csk_mem_free(cdev, sk) && !vm_wait) | ||
954 | break; | ||
955 | |||
956 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
957 | sk->sk_write_pending++; | ||
958 | sk_wait_event(sk, ¤t_timeo, sk->sk_err || | ||
959 | (sk->sk_shutdown & SEND_SHUTDOWN) || | ||
960 | (csk_mem_free(cdev, sk) && !vm_wait), &wait); | ||
961 | sk->sk_write_pending--; | ||
962 | |||
963 | if (vm_wait) { | ||
964 | vm_wait -= current_timeo; | ||
965 | current_timeo = *timeo_p; | ||
966 | if (current_timeo != MAX_SCHEDULE_TIMEOUT) { | ||
967 | current_timeo -= vm_wait; | ||
968 | if (current_timeo < 0) | ||
969 | current_timeo = 0; | ||
970 | } | ||
971 | vm_wait = 0; | ||
972 | } | ||
973 | *timeo_p = current_timeo; | ||
974 | } | ||
975 | do_rm_wq: | ||
976 | remove_wait_queue(sk_sleep(sk), &wait); | ||
977 | return err; | ||
978 | do_error: | ||
979 | err = -EPIPE; | ||
980 | goto do_rm_wq; | ||
981 | do_nonblock: | ||
982 | err = -EAGAIN; | ||
983 | goto do_rm_wq; | ||
984 | do_interrupted: | ||
985 | err = sock_intr_errno(*timeo_p); | ||
986 | goto do_rm_wq; | ||
987 | } | ||
988 | |||
917 | int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) | 989 | int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) |
918 | { | 990 | { |
919 | struct chtls_sock *csk = rcu_dereference_sk_user_data(sk); | 991 | struct chtls_sock *csk = rcu_dereference_sk_user_data(sk); |
@@ -952,6 +1024,8 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) | |||
952 | copy = mss - skb->len; | 1024 | copy = mss - skb->len; |
953 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1025 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
954 | } | 1026 | } |
1027 | if (!csk_mem_free(cdev, sk)) | ||
1028 | goto wait_for_sndbuf; | ||
955 | 1029 | ||
956 | if (is_tls_tx(csk) && !csk->tlshws.txleft) { | 1030 | if (is_tls_tx(csk) && !csk->tlshws.txleft) { |
957 | struct tls_hdr hdr; | 1031 | struct tls_hdr hdr; |
@@ -1099,8 +1173,10 @@ copy: | |||
1099 | if (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) | 1173 | if (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) |
1100 | push_frames_if_head(sk); | 1174 | push_frames_if_head(sk); |
1101 | continue; | 1175 | continue; |
1176 | wait_for_sndbuf: | ||
1177 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
1102 | wait_for_memory: | 1178 | wait_for_memory: |
1103 | err = sk_stream_wait_memory(sk, &timeo); | 1179 | err = csk_wait_memory(cdev, sk, &timeo); |
1104 | if (err) | 1180 | if (err) |
1105 | goto do_error; | 1181 | goto do_error; |
1106 | } | 1182 | } |
@@ -1131,6 +1207,7 @@ int chtls_sendpage(struct sock *sk, struct page *page, | |||
1131 | int offset, size_t size, int flags) | 1207 | int offset, size_t size, int flags) |
1132 | { | 1208 | { |
1133 | struct chtls_sock *csk; | 1209 | struct chtls_sock *csk; |
1210 | struct chtls_dev *cdev; | ||
1134 | int mss, err, copied; | 1211 | int mss, err, copied; |
1135 | struct tcp_sock *tp; | 1212 | struct tcp_sock *tp; |
1136 | long timeo; | 1213 | long timeo; |
@@ -1138,6 +1215,7 @@ int chtls_sendpage(struct sock *sk, struct page *page, | |||
1138 | tp = tcp_sk(sk); | 1215 | tp = tcp_sk(sk); |
1139 | copied = 0; | 1216 | copied = 0; |
1140 | csk = rcu_dereference_sk_user_data(sk); | 1217 | csk = rcu_dereference_sk_user_data(sk); |
1218 | cdev = csk->cdev; | ||
1141 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | 1219 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); |
1142 | 1220 | ||
1143 | err = sk_stream_wait_connect(sk, &timeo); | 1221 | err = sk_stream_wait_connect(sk, &timeo); |
@@ -1156,6 +1234,8 @@ int chtls_sendpage(struct sock *sk, struct page *page, | |||
1156 | if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) || | 1234 | if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) || |
1157 | copy <= 0) { | 1235 | copy <= 0) { |
1158 | new_buf: | 1236 | new_buf: |
1237 | if (!csk_mem_free(cdev, sk)) | ||
1238 | goto wait_for_sndbuf; | ||
1159 | 1239 | ||
1160 | if (is_tls_tx(csk)) { | 1240 | if (is_tls_tx(csk)) { |
1161 | skb = get_record_skb(sk, | 1241 | skb = get_record_skb(sk, |
@@ -1167,7 +1247,7 @@ new_buf: | |||
1167 | skb = get_tx_skb(sk, 0); | 1247 | skb = get_tx_skb(sk, 0); |
1168 | } | 1248 | } |
1169 | if (!skb) | 1249 | if (!skb) |
1170 | goto do_error; | 1250 | goto wait_for_memory; |
1171 | copy = mss; | 1251 | copy = mss; |
1172 | } | 1252 | } |
1173 | if (copy > size) | 1253 | if (copy > size) |
@@ -1206,8 +1286,12 @@ new_buf: | |||
1206 | if (unlikely(ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND)) | 1286 | if (unlikely(ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND)) |
1207 | push_frames_if_head(sk); | 1287 | push_frames_if_head(sk); |
1208 | continue; | 1288 | continue; |
1209 | 1289 | wait_for_sndbuf: | |
1210 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 1290 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
1291 | wait_for_memory: | ||
1292 | err = csk_wait_memory(cdev, sk, &timeo); | ||
1293 | if (err) | ||
1294 | goto do_error; | ||
1211 | } | 1295 | } |
1212 | out: | 1296 | out: |
1213 | csk_reset_flag(csk, CSK_TX_MORE_DATA); | 1297 | csk_reset_flag(csk, CSK_TX_MORE_DATA); |
diff --git a/drivers/crypto/chelsio/chtls/chtls_main.c b/drivers/crypto/chelsio/chtls/chtls_main.c index 53ffb00d45bf..273afd3b6537 100644 --- a/drivers/crypto/chelsio/chtls/chtls_main.c +++ b/drivers/crypto/chelsio/chtls/chtls_main.c | |||
@@ -238,6 +238,7 @@ static void *chtls_uld_add(const struct cxgb4_lld_info *info) | |||
238 | spin_lock_init(&cdev->idr_lock); | 238 | spin_lock_init(&cdev->idr_lock); |
239 | cdev->send_page_order = min_t(uint, get_order(32768), | 239 | cdev->send_page_order = min_t(uint, get_order(32768), |
240 | send_page_order); | 240 | send_page_order); |
241 | cdev->max_host_sndbuf = 48 * 1024; | ||
241 | 242 | ||
242 | if (lldi->vr->key.size) | 243 | if (lldi->vr->key.size) |
243 | if (chtls_init_kmap(cdev, lldi)) | 244 | if (chtls_init_kmap(cdev, lldi)) |