@@ -1146,7 +1146,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1146
1146
struct ipv6_pinfo * np = inet6_sk (sk );
1147
1147
struct inet_cork * cork ;
1148
1148
struct sk_buff * skb , * skb_prev = NULL ;
1149
- unsigned int maxfraglen , fragheaderlen , mtu , orig_mtu , headersize ;
1149
+ unsigned int maxfraglen , fragheaderlen , mtu , orig_mtu , headersize , pmtu ;
1150
1150
int exthdrlen ;
1151
1151
int dst_exthdrlen ;
1152
1152
int hh_len ;
@@ -1242,6 +1242,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1242
1242
sizeof (struct frag_hdr ) : 0 ) +
1243
1243
rt -> rt6i_nfheader_len ;
1244
1244
1245
+ /* as per RFC 7112 section 5, the entire IPv6 Header Chain must fit
1246
+ * the first fragment
1247
+ */
1248
+ if (headersize + transhdrlen > mtu )
1249
+ goto emsgsize ;
1250
+
1245
1251
if (mtu <= sizeof (struct ipv6hdr ) + IPV6_MAXPLEN ) {
1246
1252
unsigned int maxnonfragsize ;
1247
1253
@@ -1261,9 +1267,8 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1261
1267
1262
1268
if (cork -> length + length > maxnonfragsize - headersize ) {
1263
1269
emsgsize :
1264
- ipv6_local_error (sk , EMSGSIZE , fl6 ,
1265
- mtu - headersize +
1266
- sizeof (struct ipv6hdr ));
1270
+ pmtu = max_t (int , mtu - headersize + sizeof (struct ipv6hdr ), 0 );
1271
+ ipv6_local_error (sk , EMSGSIZE , fl6 , pmtu );
1267
1272
return - EMSGSIZE ;
1268
1273
}
1269
1274
}
0 commit comments