aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevich@gmail.com>2013-08-09 22:05:36 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-13 18:04:02 -0400
commit072017b41e49e2a8e8a4e0258837a614bb5daa8d (patch)
treef0231d484d9d7189d97927aa0a9db3799044986a /net
parent55d10a11aeeca48149d14fcc0b955017f3618882 (diff)
net: sctp: Add rudimentary infrastructure to account for control chunks
This patch adds a base infrastructure that allows SCTP to do memory accounting for control chunks. Real accounting code will follow. This patch alos fixes the following triggered bug ... [ 553.109742] kernel BUG at include/linux/skbuff.h:1813! [ 553.109766] invalid opcode: 0000 [#1] SMP [ 553.109789] Modules linked in: sctp libcrc32c rfcomm [...] [ 553.110259] uinput i915 i2c_algo_bit drm_kms_helper e1000e drm ptp pps_core i2c_core wmi video sunrpc [ 553.110320] CPU: 0 PID: 1636 Comm: lt-test_1_to_1_ Not tainted 3.11.0-rc3+ #2 [ 553.110350] Hardware name: LENOVO 74597D6/74597D6, BIOS 6DET60WW (3.10 ) 09/17/2009 [ 553.110381] task: ffff88020a01dd40 ti: ffff880204ed0000 task.ti: ffff880204ed0000 [ 553.110411] RIP: 0010:[<ffffffffa0698017>] [<ffffffffa0698017>] skb_orphan.part.9+0x4/0x6 [sctp] [ 553.110459] RSP: 0018:ffff880204ed1bb8 EFLAGS: 00010286 [ 553.110483] RAX: ffff8802086f5a40 RBX: ffff880204303300 RCX: 0000000000000000 [ 553.110487] RDX: ffff880204303c28 RSI: ffff8802086f5a40 RDI: ffff880202158000 [ 553.110487] RBP: ffff880204ed1bb8 R08: 0000000000000000 R09: 0000000000000000 [ 553.110487] R10: ffff88022f2d9a04 R11: ffff880233001600 R12: 0000000000000000 [ 553.110487] R13: ffff880204303c00 R14: ffff8802293d0000 R15: ffff880202158000 [ 553.110487] FS: 00007f31b31fe740(0000) GS:ffff88023bc00000(0000) knlGS:0000000000000000 [ 553.110487] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 553.110487] CR2: 000000379980e3e0 CR3: 000000020d225000 CR4: 00000000000407f0 [ 553.110487] Stack: [ 553.110487] ffff880204ed1ca8 ffffffffa068d7fc 0000000000000000 0000000000000000 [ 553.110487] 0000000000000000 ffff8802293d0000 ffff880202158000 ffffffff81cb7900 [ 553.110487] 0000000000000000 0000400000001c68 ffff8802086f5a40 000000000000000f [ 553.110487] Call Trace: [ 553.110487] [<ffffffffa068d7fc>] sctp_sendmsg+0x6bc/0xc80 [sctp] [ 553.110487] [<ffffffff8128f185>] ? sock_has_perm+0x75/0x90 [ 553.110487] [<ffffffff815a3593>] inet_sendmsg+0x63/0xb0 [ 553.110487] [<ffffffff8128f2b3>] ? selinux_socket_sendmsg+0x23/0x30 [ 553.110487] [<ffffffff8151c5d6>] sock_sendmsg+0xa6/0xd0 [ 553.110487] [<ffffffff81637b05>] ? _raw_spin_unlock_bh+0x15/0x20 [ 553.110487] [<ffffffff8151cd38>] SYSC_sendto+0x128/0x180 [ 553.110487] [<ffffffff8151ce6b>] ? SYSC_connect+0xdb/0x100 [ 553.110487] [<ffffffffa0690031>] ? sctp_inet_listen+0x71/0x1f0 [sctp] [ 553.110487] [<ffffffff8151d35e>] SyS_sendto+0xe/0x10 [ 553.110487] [<ffffffff81640202>] system_call_fastpath+0x16/0x1b [ 553.110487] Code: e0 48 c7 c7 00 22 6a a0 e8 67 a3 f0 e0 48 c7 [...] [ 553.110487] RIP [<ffffffffa0698017>] skb_orphan.part.9+0x4/0x6 [sctp] [ 553.110487] RSP <ffff880204ed1bb8> [ 553.121578] ---[ end trace 46c20c5903ef5be2 ]--- The approach taken here is to split data and control chunks creation a bit. Data chunks already have memory accounting so noting needs to happen. For control chunks, add stubs handlers. Signed-off-by: Vlad Yasevich <vyasevich@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sctp/sm_make_chunk.c99
1 files changed, 69 insertions, 30 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 9c131338ccfa..01e97836ca6c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -62,8 +62,12 @@
62#include <net/sctp/sctp.h> 62#include <net/sctp/sctp.h>
63#include <net/sctp/sm.h> 63#include <net/sctp/sm.h>
64 64
65static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, 65static struct sctp_chunk *sctp_make_control(const struct sctp_association *asoc,
66 __u8 type, __u8 flags, int paylen); 66 __u8 type, __u8 flags, int paylen);
67static struct sctp_chunk *sctp_make_data(const struct sctp_association *asoc,
68 __u8 flags, int paylen);
69static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc,
70 __u8 type, __u8 flags, int paylen);
67static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, 71static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
68 const struct sctp_association *asoc, 72 const struct sctp_association *asoc,
69 const struct sctp_chunk *init_chunk, 73 const struct sctp_chunk *init_chunk,
@@ -76,6 +80,28 @@ static int sctp_process_param(struct sctp_association *asoc,
76static void *sctp_addto_param(struct sctp_chunk *chunk, int len, 80static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
77 const void *data); 81 const void *data);
78 82
83/* Control chunk destructor */
84static void sctp_control_release_owner(struct sk_buff *skb)
85{
86 /*TODO: do memory release */
87}
88
89static void sctp_control_set_owner_w(struct sctp_chunk *chunk)
90{
91 struct sctp_association *asoc = chunk->asoc;
92 struct sk_buff *skb = chunk->skb;
93
94 /* TODO: properly account for control chunks.
95 * To do it right we'll need:
96 * 1) endpoint if association isn't known.
97 * 2) proper memory accounting.
98 *
99 * For now don't do anything for now.
100 */
101 skb->sk = asoc ? asoc->base.sk : NULL;
102 skb->destructor = sctp_control_release_owner;
103}
104
79/* What was the inbound interface for this chunk? */ 105/* What was the inbound interface for this chunk? */
80int sctp_chunk_iif(const struct sctp_chunk *chunk) 106int sctp_chunk_iif(const struct sctp_chunk *chunk)
81{ 107{
@@ -290,7 +316,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
290 * PLEASE DO NOT FIXME [This version does not support Host Name.] 316 * PLEASE DO NOT FIXME [This version does not support Host Name.]
291 */ 317 */
292 318
293 retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize); 319 retval = sctp_make_control(asoc, SCTP_CID_INIT, 0, chunksize);
294 if (!retval) 320 if (!retval)
295 goto nodata; 321 goto nodata;
296 322
@@ -437,7 +463,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
437 num_ext); 463 num_ext);
438 464
439 /* Now allocate and fill out the chunk. */ 465 /* Now allocate and fill out the chunk. */
440 retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); 466 retval = sctp_make_control(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
441 if (!retval) 467 if (!retval)
442 goto nomem_chunk; 468 goto nomem_chunk;
443 469
@@ -542,7 +568,7 @@ struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *asoc,
542 cookie_len = asoc->peer.cookie_len; 568 cookie_len = asoc->peer.cookie_len;
543 569
544 /* Build a cookie echo chunk. */ 570 /* Build a cookie echo chunk. */
545 retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ECHO, 0, cookie_len); 571 retval = sctp_make_control(asoc, SCTP_CID_COOKIE_ECHO, 0, cookie_len);
546 if (!retval) 572 if (!retval)
547 goto nodata; 573 goto nodata;
548 retval->subh.cookie_hdr = 574 retval->subh.cookie_hdr =
@@ -587,7 +613,7 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc,
587{ 613{
588 struct sctp_chunk *retval; 614 struct sctp_chunk *retval;
589 615
590 retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ACK, 0, 0); 616 retval = sctp_make_control(asoc, SCTP_CID_COOKIE_ACK, 0, 0);
591 617
592 /* RFC 2960 6.4 Multi-homed SCTP Endpoints 618 /* RFC 2960 6.4 Multi-homed SCTP Endpoints
593 * 619 *
@@ -635,8 +661,8 @@ struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc,
635 sctp_cwrhdr_t cwr; 661 sctp_cwrhdr_t cwr;
636 662
637 cwr.lowest_tsn = htonl(lowest_tsn); 663 cwr.lowest_tsn = htonl(lowest_tsn);
638 retval = sctp_make_chunk(asoc, SCTP_CID_ECN_CWR, 0, 664 retval = sctp_make_control(asoc, SCTP_CID_ECN_CWR, 0,
639 sizeof(sctp_cwrhdr_t)); 665 sizeof(sctp_cwrhdr_t));
640 666
641 if (!retval) 667 if (!retval)
642 goto nodata; 668 goto nodata;
@@ -669,8 +695,8 @@ struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc,
669 sctp_ecnehdr_t ecne; 695 sctp_ecnehdr_t ecne;
670 696
671 ecne.lowest_tsn = htonl(lowest_tsn); 697 ecne.lowest_tsn = htonl(lowest_tsn);
672 retval = sctp_make_chunk(asoc, SCTP_CID_ECN_ECNE, 0, 698 retval = sctp_make_control(asoc, SCTP_CID_ECN_ECNE, 0,
673 sizeof(sctp_ecnehdr_t)); 699 sizeof(sctp_ecnehdr_t));
674 if (!retval) 700 if (!retval)
675 goto nodata; 701 goto nodata;
676 retval->subh.ecne_hdr = 702 retval->subh.ecne_hdr =
@@ -706,7 +732,7 @@ struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,
706 dp.ssn = htons(ssn); 732 dp.ssn = htons(ssn);
707 733
708 chunk_len = sizeof(dp) + data_len; 734 chunk_len = sizeof(dp) + data_len;
709 retval = sctp_make_chunk(asoc, SCTP_CID_DATA, flags, chunk_len); 735 retval = sctp_make_data(asoc, flags, chunk_len);
710 if (!retval) 736 if (!retval)
711 goto nodata; 737 goto nodata;
712 738
@@ -753,7 +779,7 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
753 + sizeof(__u32) * num_dup_tsns; 779 + sizeof(__u32) * num_dup_tsns;
754 780
755 /* Create the chunk. */ 781 /* Create the chunk. */
756 retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, len); 782 retval = sctp_make_control(asoc, SCTP_CID_SACK, 0, len);
757 if (!retval) 783 if (!retval)
758 goto nodata; 784 goto nodata;
759 785
@@ -832,8 +858,8 @@ struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
832 ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map); 858 ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
833 shut.cum_tsn_ack = htonl(ctsn); 859 shut.cum_tsn_ack = htonl(ctsn);
834 860
835 retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN, 0, 861 retval = sctp_make_control(asoc, SCTP_CID_SHUTDOWN, 0,
836 sizeof(sctp_shutdownhdr_t)); 862 sizeof(sctp_shutdownhdr_t));
837 if (!retval) 863 if (!retval)
838 goto nodata; 864 goto nodata;
839 865
@@ -851,7 +877,7 @@ struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
851{ 877{
852 struct sctp_chunk *retval; 878 struct sctp_chunk *retval;
853 879
854 retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0); 880 retval = sctp_make_control(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0);
855 881
856 /* RFC 2960 6.4 Multi-homed SCTP Endpoints 882 /* RFC 2960 6.4 Multi-homed SCTP Endpoints
857 * 883 *
@@ -880,7 +906,7 @@ struct sctp_chunk *sctp_make_shutdown_complete(
880 */ 906 */
881 flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T; 907 flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;
882 908
883 retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0); 909 retval = sctp_make_control(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0);
884 910
885 /* RFC 2960 6.4 Multi-homed SCTP Endpoints 911 /* RFC 2960 6.4 Multi-homed SCTP Endpoints
886 * 912 *
@@ -919,7 +945,7 @@ struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc,
919 flags = SCTP_CHUNK_FLAG_T; 945 flags = SCTP_CHUNK_FLAG_T;
920 } 946 }
921 947
922 retval = sctp_make_chunk(asoc, SCTP_CID_ABORT, flags, hint); 948 retval = sctp_make_control(asoc, SCTP_CID_ABORT, flags, hint);
923 949
924 /* RFC 2960 6.4 Multi-homed SCTP Endpoints 950 /* RFC 2960 6.4 Multi-homed SCTP Endpoints
925 * 951 *
@@ -1111,7 +1137,7 @@ struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
1111 struct sctp_chunk *retval; 1137 struct sctp_chunk *retval;
1112 sctp_sender_hb_info_t hbinfo; 1138 sctp_sender_hb_info_t hbinfo;
1113 1139
1114 retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo)); 1140 retval = sctp_make_control(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo));
1115 1141
1116 if (!retval) 1142 if (!retval)
1117 goto nodata; 1143 goto nodata;
@@ -1139,7 +1165,7 @@ struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *asoc,
1139{ 1165{
1140 struct sctp_chunk *retval; 1166 struct sctp_chunk *retval;
1141 1167
1142 retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT_ACK, 0, paylen); 1168 retval = sctp_make_control(asoc, SCTP_CID_HEARTBEAT_ACK, 0, paylen);
1143 if (!retval) 1169 if (!retval)
1144 goto nodata; 1170 goto nodata;
1145 1171
@@ -1171,8 +1197,8 @@ static struct sctp_chunk *sctp_make_op_error_space(
1171{ 1197{
1172 struct sctp_chunk *retval; 1198 struct sctp_chunk *retval;
1173 1199
1174 retval = sctp_make_chunk(asoc, SCTP_CID_ERROR, 0, 1200 retval = sctp_make_control(asoc, SCTP_CID_ERROR, 0,
1175 sizeof(sctp_errhdr_t) + size); 1201 sizeof(sctp_errhdr_t) + size);
1176 if (!retval) 1202 if (!retval)
1177 goto nodata; 1203 goto nodata;
1178 1204
@@ -1242,7 +1268,7 @@ struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc)
1242 if (unlikely(!hmac_desc)) 1268 if (unlikely(!hmac_desc))
1243 return NULL; 1269 return NULL;
1244 1270
1245 retval = sctp_make_chunk(asoc, SCTP_CID_AUTH, 0, 1271 retval = sctp_make_control(asoc, SCTP_CID_AUTH, 0,
1246 hmac_desc->hmac_len + sizeof(sctp_authhdr_t)); 1272 hmac_desc->hmac_len + sizeof(sctp_authhdr_t));
1247 if (!retval) 1273 if (!retval)
1248 return NULL; 1274 return NULL;
@@ -1345,8 +1371,8 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk)
1345/* Create a new chunk, setting the type and flags headers from the 1371/* Create a new chunk, setting the type and flags headers from the
1346 * arguments, reserving enough space for a 'paylen' byte payload. 1372 * arguments, reserving enough space for a 'paylen' byte payload.
1347 */ 1373 */
1348static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, 1374static struct sctp_chunk *_sctp_make_chunk(const struct sctp_association *asoc,
1349 __u8 type, __u8 flags, int paylen) 1375 __u8 type, __u8 flags, int paylen)
1350{ 1376{
1351 struct sctp_chunk *retval; 1377 struct sctp_chunk *retval;
1352 sctp_chunkhdr_t *chunk_hdr; 1378 sctp_chunkhdr_t *chunk_hdr;
@@ -1379,14 +1405,27 @@ static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
1379 if (sctp_auth_send_cid(type, asoc)) 1405 if (sctp_auth_send_cid(type, asoc))
1380 retval->auth = 1; 1406 retval->auth = 1;
1381 1407
1382 /* Set the skb to the belonging sock for accounting. */
1383 skb->sk = sk;
1384
1385 return retval; 1408 return retval;
1386nodata: 1409nodata:
1387 return NULL; 1410 return NULL;
1388} 1411}
1389 1412
1413static struct sctp_chunk *sctp_make_data(const struct sctp_association *asoc,
1414 __u8 flags, int paylen)
1415{
1416 return _sctp_make_chunk(asoc, SCTP_CID_DATA, flags, paylen);
1417}
1418
1419static struct sctp_chunk *sctp_make_control(const struct sctp_association *asoc,
1420 __u8 type, __u8 flags, int paylen)
1421{
1422 struct sctp_chunk *chunk = _sctp_make_chunk(asoc, type, flags, paylen);
1423
1424 if (chunk)
1425 sctp_control_set_owner_w(chunk);
1426
1427 return chunk;
1428}
1390 1429
1391/* Release the memory occupied by a chunk. */ 1430/* Release the memory occupied by a chunk. */
1392static void sctp_chunk_destroy(struct sctp_chunk *chunk) 1431static void sctp_chunk_destroy(struct sctp_chunk *chunk)
@@ -2727,7 +2766,7 @@ static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
2727 length += addrlen; 2766 length += addrlen;
2728 2767
2729 /* Create the chunk. */ 2768 /* Create the chunk. */
2730 retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF, 0, length); 2769 retval = sctp_make_control(asoc, SCTP_CID_ASCONF, 0, length);
2731 if (!retval) 2770 if (!retval)
2732 return NULL; 2771 return NULL;
2733 2772
@@ -2911,7 +2950,7 @@ static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *as
2911 int length = sizeof(asconf) + vparam_len; 2950 int length = sizeof(asconf) + vparam_len;
2912 2951
2913 /* Create the chunk. */ 2952 /* Create the chunk. */
2914 retval = sctp_make_chunk(asoc, SCTP_CID_ASCONF_ACK, 0, length); 2953 retval = sctp_make_control(asoc, SCTP_CID_ASCONF_ACK, 0, length);
2915 if (!retval) 2954 if (!retval)
2916 return NULL; 2955 return NULL;
2917 2956
@@ -3442,7 +3481,7 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
3442 3481
3443 hint = (nstreams + 1) * sizeof(__u32); 3482 hint = (nstreams + 1) * sizeof(__u32);
3444 3483
3445 retval = sctp_make_chunk(asoc, SCTP_CID_FWD_TSN, 0, hint); 3484 retval = sctp_make_control(asoc, SCTP_CID_FWD_TSN, 0, hint);
3446 3485
3447 if (!retval) 3486 if (!retval)
3448 return NULL; 3487 return NULL;