Commit bd304a6c authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Protect ipc_head list

Make sure that the ipc_head list cannot change under us by
protecting it with a spin lock.
parent 6565c3f9
...@@ -557,6 +557,7 @@ ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb) ...@@ -557,6 +557,7 @@ ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb)
} }
static LIST_HEAD(ipc_head); static LIST_HEAD(ipc_head);
static spinlock_t ipc_head_lock;
int int
ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit, ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
...@@ -571,43 +572,48 @@ ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit, ...@@ -571,43 +572,48 @@ ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit,
printk(KERN_DEBUG "[%d] Set %scompressor type %d\n", unit, printk(KERN_DEBUG "[%d] Set %scompressor type %d\n", unit,
data->flags & IPPP_COMP_FLAG_XMIT ? "" : "de", num); data->flags & IPPP_COMP_FLAG_XMIT ? "" : "de", num);
spin_lock(&ipc_head_lock);
list_for_each_entry(ipc, &ipc_head, list) { list_for_each_entry(ipc, &ipc_head, list) {
if (ipc->num != num) if (ipc->num == num &&
continue; try_module_get(ipc->owner))
goto found;
if (!try_module_get(ipc->owner)) }
continue; spin_unlock(&ipc_head_lock);
return -EINVAL;
stat = ipc->alloc(data);
if (!stat) { found:
printk(KERN_ERR "Can't alloc (de)compression!\n"); spin_unlock(&ipc_head_lock);
module_put(ipc->owner);
break; stat = ipc->alloc(data);
} if (!stat) {
ret = ipc->init(stat, data, unit, 0); printk(KERN_ERR "Can't alloc (de)compression!\n");
if(!ret) { goto err;
printk(KERN_ERR "Can't init (de)compression!\n"); }
ipc->free(stat); ret = ipc->init(stat, data, unit, 0);
module_put(ipc->owner); if(!ret) {
break; printk(KERN_ERR "Can't init (de)compression!\n");
ipc->free(stat);
goto err;
}
if (data->flags & IPPP_COMP_FLAG_XMIT) {
if (ccp->comp_stat) {
ccp->compressor->free(ccp->comp_stat);
module_put(ccp->compressor->owner);
} }
if (data->flags & IPPP_COMP_FLAG_XMIT) {
if (ccp->comp_stat) {
ccp->compressor->free(ccp->comp_stat);
module_put(ccp->compressor->owner);
}
ccp->comp_stat = stat; ccp->comp_stat = stat;
ccp->compressor = ipc; ccp->compressor = ipc;
} else { } else {
if (ccp->decomp_stat) { if (ccp->decomp_stat) {
ccp->decompressor->free(ccp->decomp_stat); ccp->decompressor->free(ccp->decomp_stat);
module_put(ccp->decompressor->owner); module_put(ccp->decompressor->owner);
}
ccp->decomp_stat = stat;
ccp->decompressor = ipc;
} }
return 0; ccp->decomp_stat = stat;
ccp->decompressor = ipc;
} }
return 0;
err:
module_put(ipc->owner);
return -EINVAL; return -EINVAL;
} }
...@@ -618,25 +624,34 @@ ippp_ccp_get_compressors(unsigned long protos[8]) ...@@ -618,25 +624,34 @@ ippp_ccp_get_compressors(unsigned long protos[8])
int i, j; int i, j;
memset(protos, 0, sizeof(unsigned long) * 8); memset(protos, 0, sizeof(unsigned long) * 8);
spin_lock(&ipc_head_lock);
list_for_each_entry(ipc, &ipc_head, list) { list_for_each_entry(ipc, &ipc_head, list) {
j = ipc->num / (sizeof(long)*8); j = ipc->num / (sizeof(long)*8);
i = ipc->num % (sizeof(long)*8); i = ipc->num % (sizeof(long)*8);
if (j < 8) if (j < 8)
protos[j] |= 1 << i; protos[j] |= 1 << i;
} }
spin_unlock(&ipc_head_lock);
} }
int int
isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
{ {
spin_lock(&ipc_head_lock);
list_add_tail(&ipc->list, &ipc_head); list_add_tail(&ipc->list, &ipc_head);
spin_unlock(&ipc_head_lock);
return 0; return 0;
} }
int int
isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc) isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
{ {
spin_lock(&ipc_head_lock);
list_del(&ipc->list); list_del(&ipc->list);
spin_unlock(&ipc_head_lock);
return 0; return 0;
} }
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