Commit cadc0ef0 authored by Sridhar Samudrala's avatar Sridhar Samudrala Committed by Jon Grimm

[SCTP] Fix for panic on recvmsg() with MSG_PEEK flag and some ulpevent

       cleanup.
parent 1a750002
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us> * Karl Knutson <karl@athena.chicago.il.us>
* Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
...@@ -72,9 +73,8 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb) ...@@ -72,9 +73,8 @@ static inline struct sctp_ulpevent *sctp_skb2event(struct sk_buff *skb)
} }
struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp); struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp);
struct sctp_ulpevent *sctp_ulpevent_init(struct sctp_ulpevent *, int flags); void sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
void sctp_ulpevent_free(struct sctp_ulpevent *); void sctp_ulpevent_free(struct sctp_ulpevent *);
void sctp_ulpevent_kfree_skb(struct sk_buff *skb);
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *); int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
void sctp_queue_purge_ulpevents(struct sk_buff_head *list); void sctp_queue_purge_ulpevents(struct sk_buff_head *list);
......
...@@ -1342,8 +1342,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -1342,8 +1342,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
/* When only partial message is copied to the user, increase /* When only partial message is copied to the user, increase
* rwnd by that amount. If all the data in the skb is read, * rwnd by that amount. If all the data in the skb is read,
* rwnd is updated when the skb's destructor is called via * rwnd is updated when the event is freed.
* sctp_ulpevent_free().
*/ */
sctp_assoc_rwnd_increase(event->asoc, copied); sctp_assoc_rwnd_increase(event->asoc, copied);
goto out; goto out;
...@@ -1354,7 +1353,18 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -1354,7 +1353,18 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
msg->msg_flags &= ~MSG_EOR; msg->msg_flags &= ~MSG_EOR;
out_free: out_free:
sctp_ulpevent_kfree_skb(skb); /* Free the skb. */ if (flags & MSG_PEEK) {
/* Release the skb reference acquired after peeking the skb in
* sctp_skb_recv_datagram().
*/
kfree_skb(skb);
} else {
/* Free the event which includes releasing the reference to
* the owner of the skb, freeing the skb and updating the
* rwnd.
*/
sctp_ulpevent_free(event);
}
out: out:
sctp_release_sock(sk); sctp_release_sock(sk);
return err; return err;
......
This diff is collapsed.
...@@ -99,12 +99,12 @@ void sctp_ulpq_flush(struct sctp_ulpq *ulpq) ...@@ -99,12 +99,12 @@ void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
while ((skb = __skb_dequeue(&ulpq->lobby))) { while ((skb = __skb_dequeue(&ulpq->lobby))) {
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
sctp_ulpevent_kfree_skb(skb); sctp_ulpevent_free(event);
} }
while ((skb = __skb_dequeue(&ulpq->reasm))) { while ((skb = __skb_dequeue(&ulpq->reasm))) {
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
sctp_ulpevent_kfree_skb(skb); sctp_ulpevent_free(event);
} }
} }
...@@ -237,7 +237,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) ...@@ -237,7 +237,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
if (sctp_event2skb(event)->list) if (sctp_event2skb(event)->list)
sctp_queue_purge_ulpevents(sctp_event2skb(event)->list); sctp_queue_purge_ulpevents(sctp_event2skb(event)->list);
else else
sctp_ulpevent_kfree_skb(sctp_event2skb(event)); sctp_ulpevent_free(event);
return 0; return 0;
} }
...@@ -696,7 +696,7 @@ static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed) ...@@ -696,7 +696,7 @@ static __u16 sctp_ulpq_renege_order(struct sctp_ulpq *ulpq, __u16 needed)
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
tsn = event->sndrcvinfo.sinfo_tsn; tsn = event->sndrcvinfo.sinfo_tsn;
sctp_ulpevent_kfree_skb(skb); sctp_ulpevent_free(event);
sctp_tsnmap_renege(tsnmap, tsn); sctp_tsnmap_renege(tsnmap, tsn);
if (freed >= needed) if (freed >= needed)
return freed; return freed;
...@@ -722,7 +722,7 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed) ...@@ -722,7 +722,7 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed)
event = sctp_skb2event(skb); event = sctp_skb2event(skb);
tsn = event->sndrcvinfo.sinfo_tsn; tsn = event->sndrcvinfo.sinfo_tsn;
sctp_ulpevent_kfree_skb(skb); sctp_ulpevent_free(event);
sctp_tsnmap_renege(tsnmap, tsn); sctp_tsnmap_renege(tsnmap, tsn);
if (freed >= needed) if (freed >= needed)
return freed; return freed;
......
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