Skip to content

Commit 686ed0a

Browse files
author
David S. Miller
committed
into nuts.davemloft.net:/disk1/BK/net-2.6
2 parents 6781fde + e343efc commit 686ed0a

File tree

5 files changed

+100
-75
lines changed

5 files changed

+100
-75
lines changed

include/net/sctp/command.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ typedef enum {
9393
SCTP_CMD_PROCESS_OPERR, /* Process an ERROR chunk. */
9494
SCTP_CMD_REPORT_FWDTSN, /* Report new cumulative TSN Ack. */
9595
SCTP_CMD_PROCESS_FWDTSN, /* Skips were reported, so process further. */
96+
SCTP_CMD_CLEAR_INIT_TAG, /* Clears association peer's inittag. */
9697
SCTP_CMD_LAST
9798
} sctp_verb_t;
9899

include/net/sctp/sm.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,23 @@ static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_a
440440
BUG();
441441
}
442442

443+
/* Check VTAG of the packet matches the sender's own tag. */
444+
static inline int
445+
sctp_vtag_verify(const struct sctp_chunk *chunk,
446+
const struct sctp_association *asoc)
447+
{
448+
/* RFC 2960 Sec 8.5 When receiving an SCTP packet, the endpoint
449+
* MUST ensure that the value in the Verification Tag field of
450+
* the received SCTP packet matches its own Tag. If the received
451+
* Verification Tag value does not match the receiver's own
452+
* tag value, the receiver shall silently discard the packet...
453+
*/
454+
if (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)
455+
return 1;
456+
457+
return 0;
458+
}
459+
443460
/* Check VTAG of the packet matches the sender's own tag OR its peer's
444461
* tag and the T bit is set in the Chunk Flags.
445462
*/

net/sctp/sm_sideeffect.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,9 @@ static void sctp_cmd_init_failed(sctp_cmd_seq_t *commands,
429429
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
430430
SCTP_ULPEVENT(event));
431431

432+
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
433+
SCTP_STATE(SCTP_STATE_CLOSED));
434+
432435
/* SEND_FAILED sent later when cleaning up the association. */
433436
asoc->outqueue.error = error;
434437
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -457,6 +460,10 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
457460
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
458461
SCTP_STATE(SCTP_STATE_CLOSED));
459462

463+
/* Set sk_err to ECONNRESET on a 1-1 style socket. */
464+
if (!sctp_style(asoc->base.sk, UDP))
465+
asoc->base.sk->sk_err = ECONNRESET;
466+
460467
/* SEND_FAILED sent later when cleaning up the association. */
461468
asoc->outqueue.error = error;
462469
sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
@@ -1272,6 +1279,9 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
12721279
case SCTP_CMD_PROCESS_OPERR:
12731280
sctp_cmd_process_operr(commands, asoc, chunk);
12741281
break;
1282+
case SCTP_CMD_CLEAR_INIT_TAG:
1283+
asoc->peer.i.init_tag = 0;
1284+
break;
12751285
default:
12761286
printk(KERN_WARNING "Impossible command: %u, %p\n",
12771287
cmd->verb, cmd->obj.ptr);

net/sctp/sm_statefuns.c

Lines changed: 62 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
171171
* Verification Tag field to Tag_A, and also provide its own
172172
* Verification Tag (Tag_Z) in the Initiate Tag field.
173173
*
174-
* Verification Tag: No checking.
174+
* Verification Tag: Must be 0.
175175
*
176176
* Inputs
177177
* (endpoint, asoc, chunk)
@@ -219,6 +219,12 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
219219
(sk->sk_ack_backlog >= sk->sk_max_ack_backlog)))
220220
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
221221

222+
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
223+
* Tag.
224+
*/
225+
if (chunk->sctp_hdr->vtag != 0)
226+
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
227+
222228
/* Verify the INIT chunk before processing it. */
223229
err_chunk = NULL;
224230
if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
@@ -377,6 +383,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
377383
if (!chunk->singleton)
378384
return SCTP_DISPOSITION_VIOLATION;
379385

386+
if (!sctp_vtag_verify(chunk, asoc))
387+
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
388+
380389
/* Grab the INIT header. */
381390
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
382391

@@ -659,8 +668,12 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
659668
const sctp_subtype_t type, void *arg,
660669
sctp_cmd_seq_t *commands)
661670
{
671+
struct sctp_chunk *chunk = arg;
662672
struct sctp_ulpevent *ev;
663673

674+
if (!sctp_vtag_verify(chunk, asoc))
675+
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
676+
664677
/* RFC 2960 5.1 Normal Establishment of an Association
665678
*
666679
* E) Upon reception of the COOKIE ACK, endpoint "A" will move
@@ -807,13 +820,7 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
807820
struct sctp_chunk *reply;
808821
size_t paylen = 0;
809822

810-
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
811-
* that the value in the Verification Tag field of the
812-
* received SCTP packet matches its own Tag. If the received
813-
* Verification Tag value does not match the receiver's own
814-
* tag value, the receiver shall silently discard the packet...
815-
*/
816-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
823+
if (!sctp_vtag_verify(chunk, asoc))
817824
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
818825

819826
/* 8.3 The receiver of the HEARTBEAT should immediately
@@ -876,11 +883,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
876883
sctp_sender_hb_info_t *hbinfo;
877884
unsigned long max_interval;
878885

879-
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
880-
* that the value in the Verification Tag field of the
881-
* received SCTP packet matches its own Tag. ...
882-
*/
883-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
886+
if (!sctp_vtag_verify(chunk, asoc))
884887
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
885888

886889
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
@@ -1130,6 +1133,12 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
11301133
if (!chunk->singleton)
11311134
return SCTP_DISPOSITION_VIOLATION;
11321135

1136+
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
1137+
* Tag.
1138+
*/
1139+
if (chunk->sctp_hdr->vtag != 0)
1140+
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
1141+
11331142
/* Grab the INIT header. */
11341143
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
11351144

@@ -1386,6 +1395,8 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
13861395
sctp_init_chunk_t *peer_init;
13871396
struct sctp_ulpevent *ev;
13881397
struct sctp_chunk *repl;
1398+
struct sctp_chunk *err;
1399+
sctp_disposition_t disposition;
13891400

13901401
/* new_asoc is a brand-new association, so these are not yet
13911402
* side effects--it is safe to run them here.
@@ -1405,6 +1416,29 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
14051416
return SCTP_DISPOSITION_CONSUME;
14061417
}
14071418

1419+
/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
1420+
* the peer has restarted (Action A), it MUST NOT setup a new
1421+
* association but instead resend the SHUTDOWN ACK and send an ERROR
1422+
* chunk with a "Cookie Received while Shutting Down" error cause to
1423+
* its peer.
1424+
*/
1425+
if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) {
1426+
disposition = sctp_sf_do_9_2_reshutack(ep, asoc,
1427+
SCTP_ST_CHUNK(chunk->chunk_hdr->type),
1428+
chunk, commands);
1429+
if (SCTP_DISPOSITION_NOMEM == disposition)
1430+
goto nomem;
1431+
1432+
err = sctp_make_op_error(asoc, chunk,
1433+
SCTP_ERROR_COOKIE_IN_SHUTDOWN,
1434+
NULL, 0);
1435+
if (err)
1436+
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
1437+
SCTP_CHUNK(err));
1438+
1439+
return SCTP_DISPOSITION_CONSUME;
1440+
}
1441+
14081442
/* For now, fail any unsent/unacked data. Consider the optional
14091443
* choice of resending of this data.
14101444
*/
@@ -1883,6 +1917,9 @@ sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
18831917

18841918
sctp_addto_chunk(reply, sizeof(bht), &bht);
18851919

1920+
/* Clear peer's init_tag cached in assoc as we are sending a new INIT */
1921+
sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL());
1922+
18861923
/* Cast away the const modifier, as we want to just
18871924
* rerun it through as a sideffect.
18881925
*/
@@ -2071,13 +2108,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
20712108
skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
20722109
chunk->subh.shutdown_hdr = sdh;
20732110

2074-
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
2075-
* that the value in the Verification Tag field of the
2076-
* received SCTP packet matches its own Tag. If the received
2077-
* Verification Tag value does not match the receiver's own
2078-
* tag value, the receiver shall silently discard the packet...
2079-
*/
2080-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
2111+
if (!sctp_vtag_verify(chunk, asoc))
20812112
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
20822113

20832114
/* Upon the reception of the SHUTDOWN, the peer endpoint shall
@@ -2190,13 +2221,7 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep,
21902221
sctp_cwrhdr_t *cwr;
21912222
struct sctp_chunk *chunk = arg;
21922223

2193-
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
2194-
* that the value in the Verification Tag field of the
2195-
* received SCTP packet matches its own Tag. If the received
2196-
* Verification Tag value does not match the receiver's own
2197-
* tag value, the receiver shall silently discard the packet...
2198-
*/
2199-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
2224+
if (!sctp_vtag_verify(chunk, asoc))
22002225
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
22012226

22022227
cwr = (sctp_cwrhdr_t *) chunk->skb->data;
@@ -2246,13 +2271,7 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep,
22462271
sctp_ecnehdr_t *ecne;
22472272
struct sctp_chunk *chunk = arg;
22482273

2249-
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
2250-
* that the value in the Verification Tag field of the
2251-
* received SCTP packet matches its own Tag. If the received
2252-
* Verification Tag value does not match the receiver's own
2253-
* tag value, the receiver shall silently discard the packet...
2254-
*/
2255-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
2274+
if (!sctp_vtag_verify(chunk, asoc))
22562275
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
22572276

22582277
ecne = (sctp_ecnehdr_t *) chunk->skb->data;
@@ -2309,13 +2328,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
23092328
int tmp;
23102329
__u32 tsn;
23112330

2312-
/* RFC 2960 8.5 Verification Tag
2313-
*
2314-
* When receiving an SCTP packet, the endpoint MUST ensure
2315-
* that the value in the Verification Tag field of the
2316-
* received SCTP packet matches its own Tag.
2317-
*/
2318-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
2331+
if (!sctp_vtag_verify(chunk, asoc)) {
23192332
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
23202333
SCTP_NULL());
23212334
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2569,13 +2582,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
25692582
int tmp;
25702583
__u32 tsn;
25712584

2572-
/* RFC 2960 8.5 Verification Tag
2573-
*
2574-
* When receiving an SCTP packet, the endpoint MUST ensure
2575-
* that the value in the Verification Tag field of the
2576-
* received SCTP packet matches its own Tag.
2577-
*/
2578-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
2585+
if (!sctp_vtag_verify(chunk, asoc)) {
25792586
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
25802587
SCTP_NULL());
25812588
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2745,11 +2752,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
27452752
sctp_sackhdr_t *sackh;
27462753
__u32 ctsn;
27472754

2748-
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
2749-
* that the value in the Verification Tag field of the
2750-
* received SCTP packet matches its own Tag. ...
2751-
*/
2752-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
2755+
if (!sctp_vtag_verify(chunk, asoc))
27532756
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
27542757

27552758
/* Pull the SACK chunk from the data buffer */
@@ -2895,6 +2898,9 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep,
28952898
struct sctp_chunk *reply;
28962899
struct sctp_ulpevent *ev;
28972900

2901+
if (!sctp_vtag_verify(chunk, asoc))
2902+
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
2903+
28982904
/* 10.2 H) SHUTDOWN COMPLETE notification
28992905
*
29002906
* When SCTP completes the shutdown procedures (section 9.2) this
@@ -3229,13 +3235,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
32293235
__u16 len;
32303236
__u32 tsn;
32313237

3232-
/* RFC 2960 8.5 Verification Tag
3233-
*
3234-
* When receiving an SCTP packet, the endpoint MUST ensure
3235-
* that the value in the Verification Tag field of the
3236-
* received SCTP packet matches its own Tag.
3237-
*/
3238-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
3238+
if (!sctp_vtag_verify(chunk, asoc)) {
32393239
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
32403240
SCTP_NULL());
32413241
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -3293,13 +3293,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
32933293
__u16 len;
32943294
__u32 tsn;
32953295

3296-
/* RFC 2960 8.5 Verification Tag
3297-
*
3298-
* When receiving an SCTP packet, the endpoint MUST ensure
3299-
* that the value in the Verification Tag field of the
3300-
* received SCTP packet matches its own Tag.
3301-
*/
3302-
if (ntohl(chunk->sctp_hdr->vtag) != asoc->c.my_vtag) {
3296+
if (!sctp_vtag_verify(chunk, asoc)) {
33033297
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
33043298
SCTP_NULL());
33053299
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -3376,13 +3370,7 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
33763370

33773371
SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk);
33783372

3379-
/* 8.5 When receiving an SCTP packet, the endpoint MUST ensure
3380-
* that the value in the Verification Tag field of the
3381-
* received SCTP packet matches its own Tag. If the received
3382-
* Verification Tag value does not match the receiver's own
3383-
* tag value, the receiver shall silently discard the packet.
3384-
*/
3385-
if (ntohl(unk_chunk->sctp_hdr->vtag) != asoc->c.my_vtag)
3373+
if (!sctp_vtag_verify(unk_chunk, asoc))
33863374
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
33873375

33883376
switch (type.chunk & SCTP_CID_ACTION_MASK) {

net/sctp/socket.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
11641164
if (!asoc) {
11651165
SCTP_DEBUG_PRINTK("There is no association yet.\n");
11661166

1167+
if (sinfo_flags & (MSG_EOF | MSG_ABORT)) {
1168+
err = -EINVAL;
1169+
goto out_unlock;
1170+
}
1171+
11671172
/* Check for invalid stream against the stream counts,
11681173
* either the default or the user specified stream counts.
11691174
*/
@@ -4388,7 +4393,11 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
43884393
return err;
43894394

43904395
do_error:
4391-
err = -ECONNREFUSED;
4396+
if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
4397+
asoc->max_init_attempts)
4398+
err = -ETIMEDOUT;
4399+
else
4400+
err = -ECONNREFUSED;
43924401
goto out;
43934402

43944403
do_interrupted:

0 commit comments

Comments
 (0)