Skip to content

Commit

Permalink
sctp: Clean up type-punning in sctp_cmd_t union
Browse files Browse the repository at this point in the history
Lots of points in the sctp_cmd_interpreter function treat the sctp_cmd_t arg as
a void pointer, even though they are written as various other types.  Theres no
need for this as doing so just leads to possible type-punning issues that could
cause crashes, and if we remain type-consistent we can actually just remove the
void * member of the union entirely.

Change Notes:

v2)
	* Dropped chunk that modified SCTP_NULL to create a marker pattern
	 should anyone try to use a SCTP_NULL() assigned sctp_arg_t, Assigning
	 to .zero provides the same effect and should be faster, per Vlad Y.

v3)
	* Reverted part of V2, opting to use memset instead of .zero, so that
	 the entire union is initalized thus avoiding the i164 speculative load
	 problems previously encountered, per Dave M..  Also rewrote
	 SCTP_[NO]FORCE so as to use common infrastructure a little more

Signed-off-by: Neil Horman <nhorman@tuxdriver.com
CC: Vlad Yasevich <vyasevich@gmail.com>
CC: "David S. Miller" <davem@davemloft.net>
CC: linux-sctp@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Neil Horman authored and David S. Miller committed Nov 3, 2012
1 parent 1a94083 commit b26ddd8
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 42 deletions.
38 changes: 22 additions & 16 deletions include/net/sctp/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ typedef union {
__be16 err;
sctp_state_t state;
sctp_event_timeout_t to;
unsigned long zero;
void *ptr;
struct sctp_chunk *chunk;
struct sctp_association *asoc;
struct sctp_transport *transport;
Expand All @@ -154,23 +152,15 @@ typedef union {
* which takes an __s32 and returns a sctp_arg_t containing the
* __s32. So, after foo = SCTP_I32(arg), foo.i32 == arg.
*/
static inline sctp_arg_t SCTP_NULL(void)
{
sctp_arg_t retval; retval.ptr = NULL; return retval;
}
static inline sctp_arg_t SCTP_NOFORCE(void)
{
sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval;
}
static inline sctp_arg_t SCTP_FORCE(void)
{
sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval;
}

#define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
static inline sctp_arg_t \
SCTP_## name (type arg) \
{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; }
{ sctp_arg_t retval;\
memset(&retval, 0, sizeof(sctp_arg_t));\
retval.elt = arg;\
return retval;\
}

SCTP_ARG_CONSTRUCTOR(I32, __s32, i32)
SCTP_ARG_CONSTRUCTOR(U32, __u32, u32)
Expand All @@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR, int, error)
SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */
SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to)
SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr)
SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk)
SCTP_ARG_CONSTRUCTOR(ASOC, struct sctp_association *, asoc)
SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport)
Expand All @@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet)
SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh)
SCTP_ARG_CONSTRUCTOR(DATAMSG, struct sctp_datamsg *, msg)

static inline sctp_arg_t SCTP_FORCE(void)
{
return SCTP_I32(1);
}

static inline sctp_arg_t SCTP_NOFORCE(void)
{
return SCTP_I32(0);
}

static inline sctp_arg_t SCTP_NULL(void)
{
sctp_arg_t retval;
memset(&retval, 0, sizeof(sctp_arg_t));
return retval;
}

typedef struct {
sctp_arg_t obj;
sctp_verb_t verb;
Expand Down
2 changes: 1 addition & 1 deletion include/net/sctp/ulpqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);

/* Perform partial delivery. */
void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
void sctp_ulpq_partial_delivery(struct sctp_ulpq *, gfp_t);

/* Abort the partial delivery. */
void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t);
Expand Down
45 changes: 22 additions & 23 deletions net/sctp/sm_sideeffect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1268,14 +1268,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_outq_uncork(&asoc->outqueue);
local_cork = 0;
}
asoc = cmd->obj.ptr;
asoc = cmd->obj.asoc;
/* Register with the endpoint. */
sctp_endpoint_add_asoc(ep, asoc);
sctp_hash_established(asoc);
break;

case SCTP_CMD_UPDATE_ASSOC:
sctp_assoc_update(asoc, cmd->obj.ptr);
sctp_assoc_update(asoc, cmd->obj.asoc);
break;

case SCTP_CMD_PURGE_OUTQUEUE:
Expand Down Expand Up @@ -1315,7 +1315,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;

case SCTP_CMD_PROCESS_FWDTSN:
sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.ptr);
sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.chunk);
break;

case SCTP_CMD_GEN_SACK:
Expand All @@ -1331,7 +1331,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_PROCESS_SACK:
/* Process an inbound SACK. */
error = sctp_cmd_process_sack(commands, asoc,
cmd->obj.ptr);
cmd->obj.chunk);
break;

case SCTP_CMD_GEN_INIT_ACK:
Expand All @@ -1352,15 +1352,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* layer which will bail.
*/
error = sctp_cmd_process_init(commands, asoc, chunk,
cmd->obj.ptr, gfp);
cmd->obj.init, gfp);
break;

case SCTP_CMD_GEN_COOKIE_ECHO:
/* Generate a COOKIE ECHO chunk. */
new_obj = sctp_make_cookie_echo(asoc, chunk);
if (!new_obj) {
if (cmd->obj.ptr)
sctp_chunk_free(cmd->obj.ptr);
if (cmd->obj.chunk)
sctp_chunk_free(cmd->obj.chunk);
goto nomem;
}
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
Expand All @@ -1369,9 +1369,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
/* If there is an ERROR chunk to be sent along with
* the COOKIE_ECHO, send it, too.
*/
if (cmd->obj.ptr)
if (cmd->obj.chunk)
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(cmd->obj.ptr));
SCTP_CHUNK(cmd->obj.chunk));

if (new_obj->transport) {
new_obj->transport->init_sent_count++;
Expand Down Expand Up @@ -1417,18 +1417,18 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_CHUNK_ULP:
/* Send a chunk to the sockets layer. */
SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
"chunk_up:", cmd->obj.ptr,
"chunk_up:", cmd->obj.chunk,
"ulpq:", &asoc->ulpq);
sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.ptr,
sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.chunk,
GFP_ATOMIC);
break;

case SCTP_CMD_EVENT_ULP:
/* Send a notification to the sockets layer. */
SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
"event_up:",cmd->obj.ptr,
"event_up:",cmd->obj.ulpevent,
"ulpq:",&asoc->ulpq);
sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ptr);
sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ulpevent);
break;

case SCTP_CMD_REPLY:
Expand All @@ -1438,12 +1438,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
local_cork = 1;
}
/* Send a chunk to our peer. */
error = sctp_outq_tail(&asoc->outqueue, cmd->obj.ptr);
error = sctp_outq_tail(&asoc->outqueue, cmd->obj.chunk);
break;

case SCTP_CMD_SEND_PKT:
/* Send a full packet to our peer. */
packet = cmd->obj.ptr;
packet = cmd->obj.packet;
sctp_packet_transmit(packet);
sctp_ootb_pkt_free(packet);
break;
Expand Down Expand Up @@ -1480,7 +1480,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;

case SCTP_CMD_SETUP_T2:
sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr);
sctp_cmd_setup_t2(commands, asoc, cmd->obj.chunk);
break;

case SCTP_CMD_TIMER_START_ONCE:
Expand Down Expand Up @@ -1514,7 +1514,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;

case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
chunk = cmd->obj.ptr;
chunk = cmd->obj.chunk;
t = sctp_assoc_choose_alter_transport(asoc,
asoc->init_last_sent_to);
asoc->init_last_sent_to = t;
Expand Down Expand Up @@ -1665,17 +1665,16 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;

case SCTP_CMD_PART_DELIVER:
sctp_ulpq_partial_delivery(&asoc->ulpq, cmd->obj.ptr,
GFP_ATOMIC);
sctp_ulpq_partial_delivery(&asoc->ulpq, GFP_ATOMIC);
break;

case SCTP_CMD_RENEGE:
sctp_ulpq_renege(&asoc->ulpq, cmd->obj.ptr,
sctp_ulpq_renege(&asoc->ulpq, cmd->obj.chunk,
GFP_ATOMIC);
break;

case SCTP_CMD_SETUP_T4:
sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr);
sctp_cmd_setup_t4(commands, asoc, cmd->obj.chunk);
break;

case SCTP_CMD_PROCESS_OPERR:
Expand Down Expand Up @@ -1734,8 +1733,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;

default:
pr_warn("Impossible command: %u, %p\n",
cmd->verb, cmd->obj.ptr);
pr_warn("Impossible command: %u\n",
cmd->verb);
break;
}

Expand Down
3 changes: 1 addition & 2 deletions net/sctp/ulpqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,6 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed)

/* Partial deliver the first message as there is pressure on rwnd. */
void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
struct sctp_chunk *chunk,
gfp_t gfp)
{
struct sctp_ulpevent *event;
Expand Down Expand Up @@ -1060,7 +1059,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
sctp_ulpq_tail_data(ulpq, chunk, gfp);

sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
sctp_ulpq_partial_delivery(ulpq, gfp);
}

sk_mem_reclaim(asoc->base.sk);
Expand Down

0 comments on commit b26ddd8

Please sign in to comment.