Commit b26ddd81 authored by Neil Horman's avatar Neil Horman Committed by David S. Miller

sctp: Clean up type-punning in sctp_cmd_t union

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: default avatarDavid S. Miller <davem@davemloft.net>
parent 1a940835
...@@ -130,8 +130,6 @@ typedef union { ...@@ -130,8 +130,6 @@ typedef union {
__be16 err; __be16 err;
sctp_state_t state; sctp_state_t state;
sctp_event_timeout_t to; sctp_event_timeout_t to;
unsigned long zero;
void *ptr;
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
struct sctp_association *asoc; struct sctp_association *asoc;
struct sctp_transport *transport; struct sctp_transport *transport;
...@@ -154,23 +152,15 @@ typedef union { ...@@ -154,23 +152,15 @@ typedef union {
* which takes an __s32 and returns a sctp_arg_t containing the * which takes an __s32 and returns a sctp_arg_t containing the
* __s32. So, after foo = SCTP_I32(arg), foo.i32 == arg. * __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) \ #define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
static inline sctp_arg_t \ static inline sctp_arg_t \
SCTP_## name (type arg) \ 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(I32, __s32, i32)
SCTP_ARG_CONSTRUCTOR(U32, __u32, u32) SCTP_ARG_CONSTRUCTOR(U32, __u32, u32)
...@@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR, int, error) ...@@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR, int, error)
SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */ SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */
SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) 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(CHUNK, struct sctp_chunk *, chunk)
SCTP_ARG_CONSTRUCTOR(ASOC, struct sctp_association *, asoc) SCTP_ARG_CONSTRUCTOR(ASOC, struct sctp_association *, asoc)
SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport) SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport)
...@@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet) ...@@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet)
SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh) SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh)
SCTP_ARG_CONSTRUCTOR(DATAMSG, struct sctp_datamsg *, msg) 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 { typedef struct {
sctp_arg_t obj; sctp_arg_t obj;
sctp_verb_t verb; sctp_verb_t verb;
......
...@@ -72,7 +72,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev); ...@@ -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); void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
/* Perform partial delivery. */ /* 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. */ /* Abort the partial delivery. */
void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t); void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t);
......
...@@ -1268,14 +1268,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1268,14 +1268,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_outq_uncork(&asoc->outqueue); sctp_outq_uncork(&asoc->outqueue);
local_cork = 0; local_cork = 0;
} }
asoc = cmd->obj.ptr; asoc = cmd->obj.asoc;
/* Register with the endpoint. */ /* Register with the endpoint. */
sctp_endpoint_add_asoc(ep, asoc); sctp_endpoint_add_asoc(ep, asoc);
sctp_hash_established(asoc); sctp_hash_established(asoc);
break; break;
case SCTP_CMD_UPDATE_ASSOC: case SCTP_CMD_UPDATE_ASSOC:
sctp_assoc_update(asoc, cmd->obj.ptr); sctp_assoc_update(asoc, cmd->obj.asoc);
break; break;
case SCTP_CMD_PURGE_OUTQUEUE: case SCTP_CMD_PURGE_OUTQUEUE:
...@@ -1315,7 +1315,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1315,7 +1315,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break; break;
case SCTP_CMD_PROCESS_FWDTSN: case SCTP_CMD_PROCESS_FWDTSN:
sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.ptr); sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.chunk);
break; break;
case SCTP_CMD_GEN_SACK: case SCTP_CMD_GEN_SACK:
...@@ -1331,7 +1331,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1331,7 +1331,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_PROCESS_SACK: case SCTP_CMD_PROCESS_SACK:
/* Process an inbound SACK. */ /* Process an inbound SACK. */
error = sctp_cmd_process_sack(commands, asoc, error = sctp_cmd_process_sack(commands, asoc,
cmd->obj.ptr); cmd->obj.chunk);
break; break;
case SCTP_CMD_GEN_INIT_ACK: case SCTP_CMD_GEN_INIT_ACK:
...@@ -1352,15 +1352,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1352,15 +1352,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* layer which will bail. * layer which will bail.
*/ */
error = sctp_cmd_process_init(commands, asoc, chunk, error = sctp_cmd_process_init(commands, asoc, chunk,
cmd->obj.ptr, gfp); cmd->obj.init, gfp);
break; break;
case SCTP_CMD_GEN_COOKIE_ECHO: case SCTP_CMD_GEN_COOKIE_ECHO:
/* Generate a COOKIE ECHO chunk. */ /* Generate a COOKIE ECHO chunk. */
new_obj = sctp_make_cookie_echo(asoc, chunk); new_obj = sctp_make_cookie_echo(asoc, chunk);
if (!new_obj) { if (!new_obj) {
if (cmd->obj.ptr) if (cmd->obj.chunk)
sctp_chunk_free(cmd->obj.ptr); sctp_chunk_free(cmd->obj.chunk);
goto nomem; goto nomem;
} }
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
...@@ -1369,9 +1369,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -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 /* If there is an ERROR chunk to be sent along with
* the COOKIE_ECHO, send it, too. * the COOKIE_ECHO, send it, too.
*/ */
if (cmd->obj.ptr) if (cmd->obj.chunk)
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(cmd->obj.ptr)); SCTP_CHUNK(cmd->obj.chunk));
if (new_obj->transport) { if (new_obj->transport) {
new_obj->transport->init_sent_count++; new_obj->transport->init_sent_count++;
...@@ -1417,18 +1417,18 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1417,18 +1417,18 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_CHUNK_ULP: case SCTP_CMD_CHUNK_ULP:
/* Send a chunk to the sockets layer. */ /* Send a chunk to the sockets layer. */
SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n", SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
"chunk_up:", cmd->obj.ptr, "chunk_up:", cmd->obj.chunk,
"ulpq:", &asoc->ulpq); "ulpq:", &asoc->ulpq);
sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.ptr, sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.chunk,
GFP_ATOMIC); GFP_ATOMIC);
break; break;
case SCTP_CMD_EVENT_ULP: case SCTP_CMD_EVENT_ULP:
/* Send a notification to the sockets layer. */ /* Send a notification to the sockets layer. */
SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n", SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
"event_up:",cmd->obj.ptr, "event_up:",cmd->obj.ulpevent,
"ulpq:",&asoc->ulpq); "ulpq:",&asoc->ulpq);
sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ptr); sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ulpevent);
break; break;
case SCTP_CMD_REPLY: case SCTP_CMD_REPLY:
...@@ -1438,12 +1438,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1438,12 +1438,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
local_cork = 1; local_cork = 1;
} }
/* Send a chunk to our peer. */ /* 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; break;
case SCTP_CMD_SEND_PKT: case SCTP_CMD_SEND_PKT:
/* Send a full packet to our peer. */ /* Send a full packet to our peer. */
packet = cmd->obj.ptr; packet = cmd->obj.packet;
sctp_packet_transmit(packet); sctp_packet_transmit(packet);
sctp_ootb_pkt_free(packet); sctp_ootb_pkt_free(packet);
break; break;
...@@ -1480,7 +1480,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1480,7 +1480,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break; break;
case SCTP_CMD_SETUP_T2: case SCTP_CMD_SETUP_T2:
sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr); sctp_cmd_setup_t2(commands, asoc, cmd->obj.chunk);
break; break;
case SCTP_CMD_TIMER_START_ONCE: case SCTP_CMD_TIMER_START_ONCE:
...@@ -1514,7 +1514,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1514,7 +1514,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break; break;
case SCTP_CMD_INIT_CHOOSE_TRANSPORT: case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
chunk = cmd->obj.ptr; chunk = cmd->obj.chunk;
t = sctp_assoc_choose_alter_transport(asoc, t = sctp_assoc_choose_alter_transport(asoc,
asoc->init_last_sent_to); asoc->init_last_sent_to);
asoc->init_last_sent_to = t; asoc->init_last_sent_to = t;
...@@ -1665,17 +1665,16 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1665,17 +1665,16 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break; break;
case SCTP_CMD_PART_DELIVER: case SCTP_CMD_PART_DELIVER:
sctp_ulpq_partial_delivery(&asoc->ulpq, cmd->obj.ptr, sctp_ulpq_partial_delivery(&asoc->ulpq, GFP_ATOMIC);
GFP_ATOMIC);
break; break;
case SCTP_CMD_RENEGE: case SCTP_CMD_RENEGE:
sctp_ulpq_renege(&asoc->ulpq, cmd->obj.ptr, sctp_ulpq_renege(&asoc->ulpq, cmd->obj.chunk,
GFP_ATOMIC); GFP_ATOMIC);
break; break;
case SCTP_CMD_SETUP_T4: case SCTP_CMD_SETUP_T4:
sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr); sctp_cmd_setup_t4(commands, asoc, cmd->obj.chunk);
break; break;
case SCTP_CMD_PROCESS_OPERR: case SCTP_CMD_PROCESS_OPERR:
...@@ -1734,8 +1733,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, ...@@ -1734,8 +1733,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break; break;
default: default:
pr_warn("Impossible command: %u, %p\n", pr_warn("Impossible command: %u\n",
cmd->verb, cmd->obj.ptr); cmd->verb);
break; break;
} }
......
...@@ -997,7 +997,6 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed) ...@@ -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. */ /* Partial deliver the first message as there is pressure on rwnd. */
void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq, void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
struct sctp_chunk *chunk,
gfp_t gfp) gfp_t gfp)
{ {
struct sctp_ulpevent *event; struct sctp_ulpevent *event;
...@@ -1060,7 +1059,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, ...@@ -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_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
sctp_ulpq_tail_data(ulpq, chunk, gfp); 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); sk_mem_reclaim(asoc->base.sk);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment