Commit c8beccc6 authored by Parthasarathy Bhuvaragan's avatar Parthasarathy Bhuvaragan Committed by David S. Miller

tipc: fix connection abort during subscription cancellation

In 'commit 7fe8097c ("tipc: fix nullpointer bug when subscribing
to events")', we terminate the connection if the subscription
creation fails.
In the same commit, the subscription creation result was based on
the value of subscription pointer (set in the function) instead of
the return code.

Unfortunately, the same function also handles subscription
cancellation request. For a subscription cancellation request,
the subscription pointer cannot be set. Thus the connection is
terminated during cancellation request.

In this commit, we move the subcription cancel check outside
of tipc_subscrp_create(). Hence,
- tipc_subscrp_create() will create a subscripton
- tipc_subscrb_rcv_cb() will subscribe or cancel a subscription.

Fixes: 'commit 7fe8097c ("tipc: fix nullpointer bug when subscribing to events")'
Acked-by: default avatarYing Xue <ying.xue@windriver.com>
Reviewed-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: default avatarParthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c13c622
...@@ -235,22 +235,11 @@ static void tipc_subscrp_cancel(struct tipc_subscr *s, ...@@ -235,22 +235,11 @@ static void tipc_subscrp_cancel(struct tipc_subscr *s,
static struct tipc_subscription *tipc_subscrp_create(struct net *net, static struct tipc_subscription *tipc_subscrp_create(struct net *net,
struct tipc_subscr *s, struct tipc_subscr *s,
struct tipc_subscriber *subscriber) int swap)
{ {
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_subscription *sub; struct tipc_subscription *sub;
u32 filter; u32 filter = htohl(s->filter, swap);
int swap;
/* Determine subscriber's endianness */
swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE));
/* Detect & process a subscription cancellation request */
if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {
s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
tipc_subscrp_cancel(s, subscriber);
return NULL;
}
/* Refuse subscription if global limit exceeded */ /* Refuse subscription if global limit exceeded */
if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) {
...@@ -268,7 +257,6 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net, ...@@ -268,7 +257,6 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net,
/* Initialize subscription object */ /* Initialize subscription object */
sub->net = net; sub->net = net;
filter = htohl(s->filter, swap);
if (((filter & TIPC_SUB_PORTS) && (filter & TIPC_SUB_SERVICE)) || if (((filter & TIPC_SUB_PORTS) && (filter & TIPC_SUB_SERVICE)) ||
(htohl(s->seq.lower, swap) > htohl(s->seq.upper, swap))) { (htohl(s->seq.lower, swap) > htohl(s->seq.upper, swap))) {
pr_warn("Subscription rejected, illegal request\n"); pr_warn("Subscription rejected, illegal request\n");
...@@ -284,13 +272,13 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net, ...@@ -284,13 +272,13 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net,
} }
static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s,
struct tipc_subscriber *subscriber) struct tipc_subscriber *subscriber, int swap)
{ {
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_subscription *sub = NULL; struct tipc_subscription *sub = NULL;
u32 timeout; u32 timeout;
sub = tipc_subscrp_create(net, s, subscriber); sub = tipc_subscrp_create(net, s, swap);
if (!sub) if (!sub)
return tipc_conn_terminate(tn->topsrv, subscriber->conid); return tipc_conn_terminate(tn->topsrv, subscriber->conid);
...@@ -299,7 +287,7 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, ...@@ -299,7 +287,7 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s,
spin_unlock_bh(&subscriber->lock); spin_unlock_bh(&subscriber->lock);
sub->subscriber = subscriber; sub->subscriber = subscriber;
timeout = htohl(sub->evt.s.timeout, sub->swap); timeout = htohl(sub->evt.s.timeout, swap);
if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout))) if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)))
tipc_subscrb_get(subscriber); tipc_subscrb_get(subscriber);
tipc_nametbl_subscribe(sub); tipc_nametbl_subscribe(sub);
...@@ -316,8 +304,20 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, ...@@ -316,8 +304,20 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid,
struct sockaddr_tipc *addr, void *usr_data, struct sockaddr_tipc *addr, void *usr_data,
void *buf, size_t len) void *buf, size_t len)
{ {
tipc_subscrp_subscribe(net, (struct tipc_subscr *)buf, struct tipc_subscriber *subscriber = usr_data;
(struct tipc_subscriber *)usr_data); struct tipc_subscr *s = (struct tipc_subscr *)buf;
int swap;
/* Determine subscriber's endianness */
swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE));
/* Detect & process a subscription cancellation request */
if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {
s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
return tipc_subscrp_cancel(s, subscriber);
}
tipc_subscrp_subscribe(net, s, subscriber, swap);
} }
/* Handle one request to establish a new subscriber */ /* Handle one request to establish a new subscriber */
......
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