diff options
author | Willy Tarreau <w@1wt.eu> | 2010-09-05 22:34:10 +0200 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2010-09-05 22:34:10 +0200 |
commit | 21f5f8cfb99d14d1418d31e99e3f37d53566c797 (patch) | |
tree | fdcfde13ca01948d13023ae76d867360bf497b6d | |
parent | 9d178b0686733742f2bc4e193999322c1e2fd42d (diff) | |
download | linux-2.4-21f5f8cfb99d14d1418d31e99e3f37d53566c797.tar.gz |
irda: correctly free memory on irda_bind() failure
This is a backport of one memory leak issue fixed in 2.6 by Jesper Juhl,
which was more recently completed by David Miller based on a regression
reported by Tavis Ormandy.
Original 2.6 patch: 61e44b4815063a5cc31242d3669d5f87beeaa45f
Signed-off-by: Willy Tarreau <w@1wt.eu>
-rw-r--r-- | net/irda/af_irda.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index ea20371390a31..38b1dfe8f9dc7 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -820,12 +820,18 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) } #endif /* CONFIG_IRDA_ULTRA */ + self->ias_obj = irias_new_object(addr->sir_name, jiffies); + if (self->ias_obj == NULL) + return -ENOMEM; + err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); - if (err < 0) + if (err < 0) { + irias_delete_object(self->ias_obj); + self->ias_obj = NULL; return err; + } /* Register with LM-IAS */ - self->ias_obj = irias_new_object(addr->sir_name, jiffies); irias_add_integer_attrib(self->ias_obj, "IrDA:TinyTP:LsapSel", self->stsap_sel, IAS_KERNEL_ATTR); irias_insert_object(self->ias_obj); @@ -1806,7 +1812,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, struct irda_ias_set *ias_opt; struct ias_object *ias_obj; struct ias_attrib * ias_attr; /* Attribute in IAS object */ - int opt; + int opt, free_ias = 0; self = sk->protinfo.irda; ASSERT(self != NULL, return -1;); @@ -1865,11 +1871,20 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, /* Create a new object */ ias_obj = irias_new_object(ias_opt->irda_class_name, jiffies); + if (ias_obj == NULL) { + kfree(ias_opt); + return -ENOMEM; + } + free_ias = 1; } /* Do we have the attribute already ? */ if(irias_find_attrib(ias_obj, ias_opt->irda_attrib_name)) { kfree(ias_opt); + if (free_ias) { + kfree(ias_obj->name); + kfree(ias_obj); + } return -EINVAL; } @@ -1888,6 +1903,10 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, if(ias_opt->attribute.irda_attrib_octet_seq.len > IAS_MAX_OCTET_STRING) { kfree(ias_opt); + if (free_ias) { + kfree(ias_obj->name); + kfree(ias_obj); + } return -EINVAL; } /* Add an octet sequence attribute */ @@ -1904,6 +1923,10 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, if(ias_opt->attribute.irda_attrib_string.len > IAS_MAX_STRING) { kfree(ias_opt); + if (free_ias) { + kfree(ias_obj->name); + kfree(ias_obj); + } return -EINVAL; } /* NULL terminate the string (avoid troubles) */ @@ -1917,6 +1940,10 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, break; default : kfree(ias_opt); + if (free_ias) { + kfree(ias_obj->name); + kfree(ias_obj); + } return -EINVAL; } irias_insert_object(ias_obj); |