aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c122
1 files changed, 79 insertions, 43 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 32f087b5233e..142257307fa2 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1045,13 +1045,13 @@ pull_pages:
1045int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) 1045int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
1046{ 1046{
1047 int i, copy; 1047 int i, copy;
1048 int end = skb_headlen(skb); 1048 int start = skb_headlen(skb);
1049 1049
1050 if (offset > (int)skb->len - len) 1050 if (offset > (int)skb->len - len)
1051 goto fault; 1051 goto fault;
1052 1052
1053 /* Copy header. */ 1053 /* Copy header. */
1054 if ((copy = end - offset) > 0) { 1054 if ((copy = start - offset) > 0) {
1055 if (copy > len) 1055 if (copy > len)
1056 copy = len; 1056 copy = len;
1057 skb_copy_from_linear_data_offset(skb, offset, to, copy); 1057 skb_copy_from_linear_data_offset(skb, offset, to, copy);
@@ -1062,9 +1062,11 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
1062 } 1062 }
1063 1063
1064 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1064 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1065 BUG_TRAP(len >= 0); 1065 int end;
1066 1066
1067 end = offset + skb_shinfo(skb)->frags[i].size; 1067 BUG_TRAP(start <= offset + len);
1068
1069 end = start + skb_shinfo(skb)->frags[i].size;
1068 if ((copy = end - offset) > 0) { 1070 if ((copy = end - offset) > 0) {
1069 u8 *vaddr; 1071 u8 *vaddr;
1070 1072
@@ -1073,8 +1075,8 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
1073 1075
1074 vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); 1076 vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]);
1075 memcpy(to, 1077 memcpy(to,
1076 vaddr + skb_shinfo(skb)->frags[i].page_offset, 1078 vaddr + skb_shinfo(skb)->frags[i].page_offset+
1077 copy); 1079 offset - start, copy);
1078 kunmap_skb_frag(vaddr); 1080 kunmap_skb_frag(vaddr);
1079 1081
1080 if ((len -= copy) == 0) 1082 if ((len -= copy) == 0)
@@ -1082,25 +1084,30 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
1082 offset += copy; 1084 offset += copy;
1083 to += copy; 1085 to += copy;
1084 } 1086 }
1087 start = end;
1085 } 1088 }
1086 1089
1087 if (skb_shinfo(skb)->frag_list) { 1090 if (skb_shinfo(skb)->frag_list) {
1088 struct sk_buff *list = skb_shinfo(skb)->frag_list; 1091 struct sk_buff *list = skb_shinfo(skb)->frag_list;
1089 1092
1090 for (; list; list = list->next) { 1093 for (; list; list = list->next) {
1091 BUG_TRAP(len >= 0); 1094 int end;
1095
1096 BUG_TRAP(start <= offset + len);
1092 1097
1093 end = offset + list->len; 1098 end = start + list->len;
1094 if ((copy = end - offset) > 0) { 1099 if ((copy = end - offset) > 0) {
1095 if (copy > len) 1100 if (copy > len)
1096 copy = len; 1101 copy = len;
1097 if (skb_copy_bits(list, 0, to, copy)) 1102 if (skb_copy_bits(list, offset - start,
1103 to, copy))
1098 goto fault; 1104 goto fault;
1099 if ((len -= copy) == 0) 1105 if ((len -= copy) == 0)
1100 return 0; 1106 return 0;
1101 offset += copy; 1107 offset += copy;
1102 to += copy; 1108 to += copy;
1103 } 1109 }
1110 start = end;
1104 } 1111 }
1105 } 1112 }
1106 if (!len) 1113 if (!len)
@@ -1125,12 +1132,12 @@ fault:
1125int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) 1132int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
1126{ 1133{
1127 int i, copy; 1134 int i, copy;
1128 int end = skb_headlen(skb); 1135 int start = skb_headlen(skb);
1129 1136
1130 if (offset > (int)skb->len - len) 1137 if (offset > (int)skb->len - len)
1131 goto fault; 1138 goto fault;
1132 1139
1133 if ((copy = end - offset) > 0) { 1140 if ((copy = start - offset) > 0) {
1134 if (copy > len) 1141 if (copy > len)
1135 copy = len; 1142 copy = len;
1136 skb_copy_to_linear_data_offset(skb, offset, from, copy); 1143 skb_copy_to_linear_data_offset(skb, offset, from, copy);
@@ -1142,9 +1149,11 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
1142 1149
1143 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1150 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1144 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 1151 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
1145 BUG_TRAP(len >= 0); 1152 int end;
1153
1154 BUG_TRAP(start <= offset + len);
1146 1155
1147 end = offset + frag->size; 1156 end = start + frag->size;
1148 if ((copy = end - offset) > 0) { 1157 if ((copy = end - offset) > 0) {
1149 u8 *vaddr; 1158 u8 *vaddr;
1150 1159
@@ -1152,7 +1161,8 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
1152 copy = len; 1161 copy = len;
1153 1162
1154 vaddr = kmap_skb_frag(frag); 1163 vaddr = kmap_skb_frag(frag);
1155 memcpy(vaddr + frag->page_offset, from, copy); 1164 memcpy(vaddr + frag->page_offset + offset - start,
1165 from, copy);
1156 kunmap_skb_frag(vaddr); 1166 kunmap_skb_frag(vaddr);
1157 1167
1158 if ((len -= copy) == 0) 1168 if ((len -= copy) == 0)
@@ -1160,25 +1170,30 @@ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
1160 offset += copy; 1170 offset += copy;
1161 from += copy; 1171 from += copy;
1162 } 1172 }
1173 start = end;
1163 } 1174 }
1164 1175
1165 if (skb_shinfo(skb)->frag_list) { 1176 if (skb_shinfo(skb)->frag_list) {
1166 struct sk_buff *list = skb_shinfo(skb)->frag_list; 1177 struct sk_buff *list = skb_shinfo(skb)->frag_list;
1167 1178
1168 for (; list; list = list->next) { 1179 for (; list; list = list->next) {
1169 BUG_TRAP(len >= 0); 1180 int end;
1170 1181
1171 end = offset + list->len; 1182 BUG_TRAP(start <= offset + len);
1183
1184 end = start + list->len;
1172 if ((copy = end - offset) > 0) { 1185 if ((copy = end - offset) > 0) {
1173 if (copy > len) 1186 if (copy > len)
1174 copy = len; 1187 copy = len;
1175 if (skb_store_bits(list, 0, from, copy)) 1188 if (skb_store_bits(list, offset - start,
1189 from, copy))
1176 goto fault; 1190 goto fault;
1177 if ((len -= copy) == 0) 1191 if ((len -= copy) == 0)
1178 return 0; 1192 return 0;
1179 offset += copy; 1193 offset += copy;
1180 from += copy; 1194 from += copy;
1181 } 1195 }
1196 start = end;
1182 } 1197 }
1183 } 1198 }
1184 if (!len) 1199 if (!len)
@@ -1195,8 +1210,8 @@ EXPORT_SYMBOL(skb_store_bits);
1195__wsum skb_checksum(const struct sk_buff *skb, int offset, 1210__wsum skb_checksum(const struct sk_buff *skb, int offset,
1196 int len, __wsum csum) 1211 int len, __wsum csum)
1197{ 1212{
1198 int end = skb_headlen(skb); 1213 int start = skb_headlen(skb);
1199 int i, copy = end - offset; 1214 int i, copy = start - offset;
1200 int pos = 0; 1215 int pos = 0;
1201 1216
1202 /* Checksum header. */ 1217 /* Checksum header. */
@@ -1211,9 +1226,11 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
1211 } 1226 }
1212 1227
1213 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1228 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1214 BUG_TRAP(len >= 0); 1229 int end;
1230
1231 BUG_TRAP(start <= offset + len);
1215 1232
1216 end = offset + skb_shinfo(skb)->frags[i].size; 1233 end = start + skb_shinfo(skb)->frags[i].size;
1217 if ((copy = end - offset) > 0) { 1234 if ((copy = end - offset) > 0) {
1218 __wsum csum2; 1235 __wsum csum2;
1219 u8 *vaddr; 1236 u8 *vaddr;
@@ -1222,8 +1239,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
1222 if (copy > len) 1239 if (copy > len)
1223 copy = len; 1240 copy = len;
1224 vaddr = kmap_skb_frag(frag); 1241 vaddr = kmap_skb_frag(frag);
1225 csum2 = csum_partial(vaddr + frag->page_offset, 1242 csum2 = csum_partial(vaddr + frag->page_offset +
1226 copy, 0); 1243 offset - start, copy, 0);
1227 kunmap_skb_frag(vaddr); 1244 kunmap_skb_frag(vaddr);
1228 csum = csum_block_add(csum, csum2, pos); 1245 csum = csum_block_add(csum, csum2, pos);
1229 if (!(len -= copy)) 1246 if (!(len -= copy))
@@ -1231,26 +1248,31 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
1231 offset += copy; 1248 offset += copy;
1232 pos += copy; 1249 pos += copy;
1233 } 1250 }
1251 start = end;
1234 } 1252 }
1235 1253
1236 if (skb_shinfo(skb)->frag_list) { 1254 if (skb_shinfo(skb)->frag_list) {
1237 struct sk_buff *list = skb_shinfo(skb)->frag_list; 1255 struct sk_buff *list = skb_shinfo(skb)->frag_list;
1238 1256
1239 for (; list; list = list->next) { 1257 for (; list; list = list->next) {
1240 BUG_TRAP(len >= 0); 1258 int end;
1241 1259
1242 end = offset + list->len; 1260 BUG_TRAP(start <= offset + len);
1261
1262 end = start + list->len;
1243 if ((copy = end - offset) > 0) { 1263 if ((copy = end - offset) > 0) {
1244 __wsum csum2; 1264 __wsum csum2;
1245 if (copy > len) 1265 if (copy > len)
1246 copy = len; 1266 copy = len;
1247 csum2 = skb_checksum(list, 0, copy, 0); 1267 csum2 = skb_checksum(list, offset - start,
1268 copy, 0);
1248 csum = csum_block_add(csum, csum2, pos); 1269 csum = csum_block_add(csum, csum2, pos);
1249 if ((len -= copy) == 0) 1270 if ((len -= copy) == 0)
1250 return csum; 1271 return csum;
1251 offset += copy; 1272 offset += copy;
1252 pos += copy; 1273 pos += copy;
1253 } 1274 }
1275 start = end;
1254 } 1276 }
1255 } 1277 }
1256 BUG_ON(len); 1278 BUG_ON(len);
@@ -1263,8 +1285,8 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset,
1263__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, 1285__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
1264 u8 *to, int len, __wsum csum) 1286 u8 *to, int len, __wsum csum)
1265{ 1287{
1266 int end = skb_headlen(skb); 1288 int start = skb_headlen(skb);
1267 int i, copy = end - offset; 1289 int i, copy = start - offset;
1268 int pos = 0; 1290 int pos = 0;
1269 1291
1270 /* Copy header. */ 1292 /* Copy header. */
@@ -1281,9 +1303,11 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
1281 } 1303 }
1282 1304
1283 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1305 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1284 BUG_TRAP(len >= 0); 1306 int end;
1307
1308 BUG_TRAP(start <= offset + len);
1285 1309
1286 end = offset + skb_shinfo(skb)->frags[i].size; 1310 end = start + skb_shinfo(skb)->frags[i].size;
1287 if ((copy = end - offset) > 0) { 1311 if ((copy = end - offset) > 0) {
1288 __wsum csum2; 1312 __wsum csum2;
1289 u8 *vaddr; 1313 u8 *vaddr;
@@ -1293,8 +1317,9 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
1293 copy = len; 1317 copy = len;
1294 vaddr = kmap_skb_frag(frag); 1318 vaddr = kmap_skb_frag(frag);
1295 csum2 = csum_partial_copy_nocheck(vaddr + 1319 csum2 = csum_partial_copy_nocheck(vaddr +
1296 frag->page_offset, 1320 frag->page_offset +
1297 to, copy, 0); 1321 offset - start, to,
1322 copy, 0);
1298 kunmap_skb_frag(vaddr); 1323 kunmap_skb_frag(vaddr);
1299 csum = csum_block_add(csum, csum2, pos); 1324 csum = csum_block_add(csum, csum2, pos);
1300 if (!(len -= copy)) 1325 if (!(len -= copy))
@@ -1303,6 +1328,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
1303 to += copy; 1328 to += copy;
1304 pos += copy; 1329 pos += copy;
1305 } 1330 }
1331 start = end;
1306 } 1332 }
1307 1333
1308 if (skb_shinfo(skb)->frag_list) { 1334 if (skb_shinfo(skb)->frag_list) {
@@ -1310,13 +1336,16 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
1310 1336
1311 for (; list; list = list->next) { 1337 for (; list; list = list->next) {
1312 __wsum csum2; 1338 __wsum csum2;
1313 BUG_TRAP(len >= 0); 1339 int end;
1340
1341 BUG_TRAP(start <= offset + len);
1314 1342
1315 end = offset + list->len; 1343 end = start + list->len;
1316 if ((copy = end - offset) > 0) { 1344 if ((copy = end - offset) > 0) {
1317 if (copy > len) 1345 if (copy > len)
1318 copy = len; 1346 copy = len;
1319 csum2 = skb_copy_and_csum_bits(list, 0, 1347 csum2 = skb_copy_and_csum_bits(list,
1348 offset - start,
1320 to, copy, 0); 1349 to, copy, 0);
1321 csum = csum_block_add(csum, csum2, pos); 1350 csum = csum_block_add(csum, csum2, pos);
1322 if ((len -= copy) == 0) 1351 if ((len -= copy) == 0)
@@ -1325,6 +1354,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
1325 to += copy; 1354 to += copy;
1326 pos += copy; 1355 pos += copy;
1327 } 1356 }
1357 start = end;
1328 } 1358 }
1329 } 1359 }
1330 BUG_ON(len); 1360 BUG_ON(len);
@@ -1996,8 +2026,8 @@ void __init skb_init(void)
1996int 2026int
1997skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) 2027skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
1998{ 2028{
1999 int end = skb_headlen(skb); 2029 int start = skb_headlen(skb);
2000 int i, copy = end - offset; 2030 int i, copy = start - offset;
2001 int elt = 0; 2031 int elt = 0;
2002 2032
2003 if (copy > 0) { 2033 if (copy > 0) {
@@ -2013,39 +2043,45 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
2013 } 2043 }
2014 2044
2015 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 2045 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
2016 BUG_TRAP(len >= 0); 2046 int end;
2017 2047
2018 end = offset + skb_shinfo(skb)->frags[i].size; 2048 BUG_TRAP(start <= offset + len);
2049
2050 end = start + skb_shinfo(skb)->frags[i].size;
2019 if ((copy = end - offset) > 0) { 2051 if ((copy = end - offset) > 0) {
2020 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 2052 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
2021 2053
2022 if (copy > len) 2054 if (copy > len)
2023 copy = len; 2055 copy = len;
2024 sg[elt].page = frag->page; 2056 sg[elt].page = frag->page;
2025 sg[elt].offset = frag->page_offset; 2057 sg[elt].offset = frag->page_offset+offset-start;
2026 sg[elt].length = copy; 2058 sg[elt].length = copy;
2027 elt++; 2059 elt++;
2028 if (!(len -= copy)) 2060 if (!(len -= copy))
2029 return elt; 2061 return elt;
2030 offset += copy; 2062 offset += copy;
2031 } 2063 }
2064 start = end;
2032 } 2065 }
2033 2066
2034 if (skb_shinfo(skb)->frag_list) { 2067 if (skb_shinfo(skb)->frag_list) {
2035 struct sk_buff *list = skb_shinfo(skb)->frag_list; 2068 struct sk_buff *list = skb_shinfo(skb)->frag_list;
2036 2069
2037 for (; list; list = list->next) { 2070 for (; list; list = list->next) {
2038 BUG_TRAP(len >= 0); 2071 int end;
2072
2073 BUG_TRAP(start <= offset + len);
2039 2074
2040 end = offset + list->len; 2075 end = start + list->len;
2041 if ((copy = end - offset) > 0) { 2076 if ((copy = end - offset) > 0) {
2042 if (copy > len) 2077 if (copy > len)
2043 copy = len; 2078 copy = len;
2044 elt += skb_to_sgvec(list, sg+elt, 0, copy); 2079 elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
2045 if ((len -= copy) == 0) 2080 if ((len -= copy) == 0)
2046 return elt; 2081 return elt;
2047 offset += copy; 2082 offset += copy;
2048 } 2083 }
2084 start = end;
2049 } 2085 }
2050 } 2086 }
2051 BUG_ON(len); 2087 BUG_ON(len);