Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: af_key: Free dumping state on socket close XFRM,IPv6: initialize ip6_dst_blackhole_ops.kmem_cachep ipv6: NULL pointer dereferrence in tcp_v6_send_ack tcp: Fix NULL dereference in tcp_4_send_ack() sctp: Fix kernel panic while process protocol violation parameter iucv: Fix mismerge again. ipsec: Fix pskb_expand_head corruption in xfrm_state_check_space
This commit is contained in:
commit
ae1cfb1174
@ -227,6 +227,9 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
|
|||||||
const struct sctp_chunk *,
|
const struct sctp_chunk *,
|
||||||
const __u8 *,
|
const __u8 *,
|
||||||
const size_t );
|
const size_t );
|
||||||
|
struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *,
|
||||||
|
const struct sctp_chunk *,
|
||||||
|
struct sctp_paramhdr *);
|
||||||
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
|
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
|
||||||
const struct sctp_transport *,
|
const struct sctp_transport *,
|
||||||
const void *payload,
|
const void *payload,
|
||||||
|
@ -618,7 +618,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
|
|||||||
];
|
];
|
||||||
} rep;
|
} rep;
|
||||||
struct ip_reply_arg arg;
|
struct ip_reply_arg arg;
|
||||||
struct net *net = dev_net(skb->dev);
|
struct net *net = dev_net(skb->dst->dev);
|
||||||
|
|
||||||
memset(&rep.th, 0, sizeof(struct tcphdr));
|
memset(&rep.th, 0, sizeof(struct tcphdr));
|
||||||
memset(&arg, 0, sizeof(arg));
|
memset(&arg, 0, sizeof(arg));
|
||||||
|
@ -2688,6 +2688,8 @@ int __init ip6_route_init(void)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out_kmem_cache;
|
goto out_kmem_cache;
|
||||||
|
|
||||||
|
ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
|
||||||
|
|
||||||
/* Registering of the loopback is done before this portion of code,
|
/* Registering of the loopback is done before this portion of code,
|
||||||
* the loopback reference in rt6_info will not be taken, do it
|
* the loopback reference in rt6_info will not be taken, do it
|
||||||
* manually for init_net */
|
* manually for init_net */
|
||||||
|
@ -1050,7 +1050,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
|
|||||||
struct tcphdr *th = tcp_hdr(skb), *t1;
|
struct tcphdr *th = tcp_hdr(skb), *t1;
|
||||||
struct sk_buff *buff;
|
struct sk_buff *buff;
|
||||||
struct flowi fl;
|
struct flowi fl;
|
||||||
struct net *net = dev_net(skb->dev);
|
struct net *net = dev_net(skb->dst->dev);
|
||||||
struct sock *ctl_sk = net->ipv6.tcp_sk;
|
struct sock *ctl_sk = net->ipv6.tcp_sk;
|
||||||
unsigned int tot_len = sizeof(struct tcphdr);
|
unsigned int tot_len = sizeof(struct tcphdr);
|
||||||
__be32 *topt;
|
__be32 *topt;
|
||||||
|
@ -524,7 +524,6 @@ static int iucv_enable(void)
|
|||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
for_each_online_cpu(cpu)
|
for_each_online_cpu(cpu)
|
||||||
smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
|
smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1);
|
||||||
preempt_enable();
|
|
||||||
if (cpus_empty(iucv_buffer_cpumask))
|
if (cpus_empty(iucv_buffer_cpumask))
|
||||||
/* No cpu could declare an iucv buffer. */
|
/* No cpu could declare an iucv buffer. */
|
||||||
goto out_path;
|
goto out_path;
|
||||||
@ -547,7 +546,9 @@ out:
|
|||||||
*/
|
*/
|
||||||
static void iucv_disable(void)
|
static void iucv_disable(void)
|
||||||
{
|
{
|
||||||
|
get_online_cpus();
|
||||||
on_each_cpu(iucv_retrieve_cpu, NULL, 1);
|
on_each_cpu(iucv_retrieve_cpu, NULL, 1);
|
||||||
|
put_online_cpus();
|
||||||
kfree(iucv_path_table);
|
kfree(iucv_path_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,22 +73,18 @@ static int pfkey_can_dump(struct sock *sk)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pfkey_do_dump(struct pfkey_sock *pfk)
|
static void pfkey_terminate_dump(struct pfkey_sock *pfk)
|
||||||
{
|
{
|
||||||
int rc;
|
if (pfk->dump.dump) {
|
||||||
|
pfk->dump.done(pfk);
|
||||||
rc = pfk->dump.dump(pfk);
|
pfk->dump.dump = NULL;
|
||||||
if (rc == -ENOBUFS)
|
pfk->dump.done = NULL;
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
pfk->dump.done(pfk);
|
|
||||||
pfk->dump.dump = NULL;
|
|
||||||
pfk->dump.done = NULL;
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pfkey_sock_destruct(struct sock *sk)
|
static void pfkey_sock_destruct(struct sock *sk)
|
||||||
{
|
{
|
||||||
|
pfkey_terminate_dump(pfkey_sk(sk));
|
||||||
skb_queue_purge(&sk->sk_receive_queue);
|
skb_queue_purge(&sk->sk_receive_queue);
|
||||||
|
|
||||||
if (!sock_flag(sk, SOCK_DEAD)) {
|
if (!sock_flag(sk, SOCK_DEAD)) {
|
||||||
@ -310,6 +306,18 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pfkey_do_dump(struct pfkey_sock *pfk)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = pfk->dump.dump(pfk);
|
||||||
|
if (rc == -ENOBUFS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
pfkey_terminate_dump(pfk);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig)
|
static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig)
|
||||||
{
|
{
|
||||||
*new = *orig;
|
*new = *orig;
|
||||||
|
@ -1012,6 +1012,29 @@ end:
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sctp_chunk *sctp_make_violation_paramlen(
|
||||||
|
const struct sctp_association *asoc,
|
||||||
|
const struct sctp_chunk *chunk,
|
||||||
|
struct sctp_paramhdr *param)
|
||||||
|
{
|
||||||
|
struct sctp_chunk *retval;
|
||||||
|
static const char error[] = "The following parameter had invalid length:";
|
||||||
|
size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) +
|
||||||
|
sizeof(sctp_paramhdr_t);
|
||||||
|
|
||||||
|
retval = sctp_make_abort(asoc, chunk, payload_len);
|
||||||
|
if (!retval)
|
||||||
|
goto nodata;
|
||||||
|
|
||||||
|
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION,
|
||||||
|
sizeof(error) + sizeof(sctp_paramhdr_t));
|
||||||
|
sctp_addto_chunk(retval, sizeof(error), error);
|
||||||
|
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param);
|
||||||
|
|
||||||
|
nodata:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make a HEARTBEAT chunk. */
|
/* Make a HEARTBEAT chunk. */
|
||||||
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
|
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
|
||||||
const struct sctp_transport *transport,
|
const struct sctp_transport *transport,
|
||||||
@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
|
|||||||
const struct sctp_chunk *chunk,
|
const struct sctp_chunk *chunk,
|
||||||
struct sctp_chunk **errp)
|
struct sctp_chunk **errp)
|
||||||
{
|
{
|
||||||
static const char error[] = "The following parameter had invalid length:";
|
|
||||||
size_t payload_len = WORD_ROUND(sizeof(error)) +
|
|
||||||
sizeof(sctp_paramhdr_t);
|
|
||||||
|
|
||||||
|
|
||||||
/* This is a fatal error. Any accumulated non-fatal errors are
|
/* This is a fatal error. Any accumulated non-fatal errors are
|
||||||
* not reported.
|
* not reported.
|
||||||
*/
|
*/
|
||||||
@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
|
|||||||
sctp_chunk_free(*errp);
|
sctp_chunk_free(*errp);
|
||||||
|
|
||||||
/* Create an error chunk and fill it in with our payload. */
|
/* Create an error chunk and fill it in with our payload. */
|
||||||
*errp = sctp_make_op_error_space(asoc, chunk, payload_len);
|
*errp = sctp_make_violation_paramlen(asoc, chunk, param);
|
||||||
|
|
||||||
if (*errp) {
|
|
||||||
sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
|
|
||||||
sizeof(error) + sizeof(sctp_paramhdr_t));
|
|
||||||
sctp_addto_chunk(*errp, sizeof(error), error);
|
|
||||||
sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
|
|||||||
const struct sctp_endpoint *ep,
|
const struct sctp_endpoint *ep,
|
||||||
const struct sctp_association *asoc,
|
const struct sctp_association *asoc,
|
||||||
const sctp_subtype_t type,
|
const sctp_subtype_t type,
|
||||||
void *arg,
|
void *arg, void *ext,
|
||||||
sctp_cmd_seq_t *commands);
|
sctp_cmd_seq_t *commands);
|
||||||
|
|
||||||
static sctp_disposition_t sctp_sf_violation_ctsn(
|
static sctp_disposition_t sctp_sf_violation_ctsn(
|
||||||
@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
|
|||||||
addr_param = (union sctp_addr_param *)hdr->params;
|
addr_param = (union sctp_addr_param *)hdr->params;
|
||||||
length = ntohs(addr_param->p.length);
|
length = ntohs(addr_param->p.length);
|
||||||
if (length < sizeof(sctp_paramhdr_t))
|
if (length < sizeof(sctp_paramhdr_t))
|
||||||
return sctp_sf_violation_paramlen(ep, asoc, type,
|
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
||||||
(void *)addr_param, commands);
|
(void *)addr_param, commands);
|
||||||
|
|
||||||
/* Verify the ASCONF chunk before processing it. */
|
/* Verify the ASCONF chunk before processing it. */
|
||||||
@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
|
|||||||
(sctp_paramhdr_t *)((void *)addr_param + length),
|
(sctp_paramhdr_t *)((void *)addr_param + length),
|
||||||
(void *)chunk->chunk_end,
|
(void *)chunk->chunk_end,
|
||||||
&err_param))
|
&err_param))
|
||||||
return sctp_sf_violation_paramlen(ep, asoc, type,
|
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
||||||
(void *)&err_param, commands);
|
(void *)err_param, commands);
|
||||||
|
|
||||||
/* ADDIP 5.2 E1) Compare the value of the serial number to the value
|
/* ADDIP 5.2 E1) Compare the value of the serial number to the value
|
||||||
* the endpoint stored in a new association variable
|
* the endpoint stored in a new association variable
|
||||||
@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
|
|||||||
(sctp_paramhdr_t *)addip_hdr->params,
|
(sctp_paramhdr_t *)addip_hdr->params,
|
||||||
(void *)asconf_ack->chunk_end,
|
(void *)asconf_ack->chunk_end,
|
||||||
&err_param))
|
&err_param))
|
||||||
return sctp_sf_violation_paramlen(ep, asoc, type,
|
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
||||||
(void *)&err_param, commands);
|
(void *)err_param, commands);
|
||||||
|
|
||||||
if (last_asconf) {
|
if (last_asconf) {
|
||||||
addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
|
addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
|
||||||
@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
|
|||||||
const struct sctp_endpoint *ep,
|
const struct sctp_endpoint *ep,
|
||||||
const struct sctp_association *asoc,
|
const struct sctp_association *asoc,
|
||||||
const sctp_subtype_t type,
|
const sctp_subtype_t type,
|
||||||
void *arg,
|
void *arg, void *ext,
|
||||||
sctp_cmd_seq_t *commands) {
|
sctp_cmd_seq_t *commands)
|
||||||
static const char err_str[] = "The following parameter had invalid length:";
|
{
|
||||||
|
struct sctp_chunk *chunk = arg;
|
||||||
|
struct sctp_paramhdr *param = ext;
|
||||||
|
struct sctp_chunk *abort = NULL;
|
||||||
|
|
||||||
return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
|
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
|
||||||
sizeof(err_str));
|
goto discard;
|
||||||
|
|
||||||
|
/* Make the abort chunk. */
|
||||||
|
abort = sctp_make_violation_paramlen(asoc, chunk, param);
|
||||||
|
if (!abort)
|
||||||
|
goto nomem;
|
||||||
|
|
||||||
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
|
||||||
|
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
|
||||||
|
|
||||||
|
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
|
||||||
|
SCTP_ERROR(ECONNABORTED));
|
||||||
|
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
|
||||||
|
SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
|
||||||
|
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
|
||||||
|
|
||||||
|
discard:
|
||||||
|
sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
|
||||||
|
|
||||||
|
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
|
||||||
|
|
||||||
|
return SCTP_DISPOSITION_ABORT;
|
||||||
|
nomem:
|
||||||
|
return SCTP_DISPOSITION_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a protocol violation when the peer trying to advance the
|
/* Handle a protocol violation when the peer trying to advance the
|
||||||
|
@ -27,10 +27,14 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
|
|||||||
- skb_headroom(skb);
|
- skb_headroom(skb);
|
||||||
int ntail = dst->dev->needed_tailroom - skb_tailroom(skb);
|
int ntail = dst->dev->needed_tailroom - skb_tailroom(skb);
|
||||||
|
|
||||||
if (nhead > 0 || ntail > 0)
|
if (nhead <= 0) {
|
||||||
return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC);
|
if (ntail <= 0)
|
||||||
|
return 0;
|
||||||
|
nhead = 0;
|
||||||
|
} else if (ntail < 0)
|
||||||
|
ntail = 0;
|
||||||
|
|
||||||
return 0;
|
return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xfrm_output_one(struct sk_buff *skb, int err)
|
static int xfrm_output_one(struct sk_buff *skb, int err)
|
||||||
|
Loading…
Reference in New Issue
Block a user