[ovs-dev] [PATCH] netlink-socket: Avoid use-after-free in nl_lookup_genl_mcgroup().

Ben Pfaff blp at nicira.com
Fri Sep 9 23:44:45 UTC 2011


Thanks, I pushed this.

On Fri, Sep 09, 2011 at 03:38:48PM -0700, Ethan Jackson wrote:
> Looks good,
> 
> Ethan
> 
> On Fri, Sep 9, 2011 at 10:21, Ben Pfaff <blp at nicira.com> wrote:
> > Commit e408762f "netlink-socket: New function nl_lookup_genl_mcgroup()"
> > modified do_lookup_genl_family() to return the Netlink attributes to the
> > caller, but it still freed the Netlink message itself, which meant that
> > the attributes pointed into freed memory. ?This commit fixes the problem.
> >
> > This commit is not a minimal fix. ?It refactors do_lookup_genl_family(),
> > changing the return value from "negative errno value or positive genl
> > family id" to the more common "zero or positive errno value".
> >
> > Found by valgrind.
> > ---
> > ?lib/netlink-socket.c | ? 71 +++++++++++++++++++++++++++++---------------------
> > ?1 files changed, 41 insertions(+), 30 deletions(-)
> >
> > diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c
> > index 394107e..2d2aa29 100644
> > --- a/lib/netlink-socket.c
> > +++ b/lib/netlink-socket.c
> > @@ -727,45 +727,41 @@ genl_family_to_name(uint16_t id)
> > ?}
> >
> > ?static int
> > -do_lookup_genl_family(const char *name, struct nlattr **attrs)
> > +do_lookup_genl_family(const char *name, struct nlattr **attrs,
> > + ? ? ? ? ? ? ? ? ? ? ?struct ofpbuf **replyp)
> > ?{
> > ? ? struct nl_sock *sock;
> > ? ? struct ofpbuf request, *reply;
> > - ? ?int retval;
> > + ? ?int error;
> >
> > - ? ?retval = nl_sock_create(NETLINK_GENERIC, &sock);
> > - ? ?if (retval) {
> > - ? ? ? ?return -retval;
> > + ? ?*replyp = NULL;
> > + ? ?error = nl_sock_create(NETLINK_GENERIC, &sock);
> > + ? ?if (error) {
> > + ? ? ? ?return error;
> > ? ? }
> >
> > ? ? ofpbuf_init(&request, 0);
> > ? ? nl_msg_put_genlmsghdr(&request, 0, GENL_ID_CTRL, NLM_F_REQUEST,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? CTRL_CMD_GETFAMILY, 1);
> > ? ? nl_msg_put_string(&request, CTRL_ATTR_FAMILY_NAME, name);
> > - ? ?retval = nl_sock_transact(sock, &request, &reply);
> > + ? ?error = nl_sock_transact(sock, &request, &reply);
> > ? ? ofpbuf_uninit(&request);
> > - ? ?if (retval) {
> > + ? ?if (error) {
> > ? ? ? ? nl_sock_destroy(sock);
> > - ? ? ? ?return -retval;
> > + ? ? ? ?return error;
> > ? ? }
> >
> > ? ? if (!nl_policy_parse(reply, NLMSG_HDRLEN + GENL_HDRLEN,
> > - ? ? ? ? ? ? ? ? ? ? ? ? family_policy, attrs, ARRAY_SIZE(family_policy))) {
> > + ? ? ? ? ? ? ? ? ? ? ? ? family_policy, attrs, ARRAY_SIZE(family_policy))
> > + ? ? ? ?|| nl_attr_get_u16(attrs[CTRL_ATTR_FAMILY_ID]) == 0) {
> > ? ? ? ? nl_sock_destroy(sock);
> > ? ? ? ? ofpbuf_delete(reply);
> > - ? ? ? ?return -EPROTO;
> > + ? ? ? ?return EPROTO;
> > ? ? }
> >
> > - ? ?retval = nl_attr_get_u16(attrs[CTRL_ATTR_FAMILY_ID]);
> > - ? ?if (retval == 0) {
> > - ? ? ? ?retval = -EPROTO;
> > - ? ?} else {
> > - ? ? ? ?define_genl_family(retval, name);
> > - ? ?}
> > ? ? nl_sock_destroy(sock);
> > - ? ?ofpbuf_delete(reply);
> > -
> > - ? ?return retval;
> > + ? ?*replyp = reply;
> > + ? ?return 0;
> > ?}
> >
> > ?/* Finds the multicast group called 'group_name' in genl family 'family_name'.
> > @@ -777,15 +773,15 @@ nl_lookup_genl_mcgroup(const char *family_name, const char *group_name,
> > ?{
> > ? ? struct nlattr *family_attrs[ARRAY_SIZE(family_policy)];
> > ? ? struct ofpbuf all_mcs;
> > + ? ?struct ofpbuf *reply;
> > ? ? struct nlattr *mc;
> > ? ? unsigned int left;
> > - ? ?int retval;
> > + ? ?int error;
> >
> > ? ? *multicast_group = 0;
> > - ? ?retval = do_lookup_genl_family(family_name, family_attrs);
> > - ? ?if (retval <= 0) {
> > - ? ? ? ?assert(retval);
> > - ? ? ? ?return -retval;
> > + ? ?error = do_lookup_genl_family(family_name, family_attrs, &reply);
> > + ? ?if (error) {
> > + ? ? ? ?return error;
> > ? ? }
> >
> > ? ? nl_attr_get_nested(family_attrs[CTRL_ATTR_MCAST_GROUPS], &all_mcs);
> > @@ -799,18 +795,23 @@ nl_lookup_genl_mcgroup(const char *family_name, const char *group_name,
> > ? ? ? ? const char *mc_name;
> >
> > ? ? ? ? if (!nl_parse_nested(mc, mc_policy, mc_attrs, ARRAY_SIZE(mc_policy))) {
> > - ? ? ? ? ? ?return EPROTO;
> > + ? ? ? ? ? ?error = EPROTO;
> > + ? ? ? ? ? ?goto exit;
> > ? ? ? ? }
> >
> > ? ? ? ? mc_name = nl_attr_get_string(mc_attrs[CTRL_ATTR_MCAST_GRP_NAME]);
> > ? ? ? ? if (!strcmp(group_name, mc_name)) {
> > ? ? ? ? ? ? *multicast_group =
> > ? ? ? ? ? ? ? ? nl_attr_get_u32(mc_attrs[CTRL_ATTR_MCAST_GRP_ID]);
> > - ? ? ? ? ? ?return 0;
> > + ? ? ? ? ? ?error = 0;
> > + ? ? ? ? ? ?goto exit;
> > ? ? ? ? }
> > ? ? }
> > + ? ?error = EPROTO;
> >
> > - ? ?return EPROTO;
> > +exit:
> > + ? ?ofpbuf_delete(reply);
> > + ? ?return error;
> > ?}
> >
> > ?/* If '*number' is 0, translates the given Generic Netlink family 'name' to a
> > @@ -820,10 +821,20 @@ nl_lookup_genl_mcgroup(const char *family_name, const char *group_name,
> > ?int
> > ?nl_lookup_genl_family(const char *name, int *number)
> > ?{
> > - ? ?struct nlattr *attrs[ARRAY_SIZE(family_policy)];
> > -
> > ? ? if (*number == 0) {
> > - ? ? ? ?*number = do_lookup_genl_family(name, attrs);
> > + ? ? ? ?struct nlattr *attrs[ARRAY_SIZE(family_policy)];
> > + ? ? ? ?struct ofpbuf *reply;
> > + ? ? ? ?int error;
> > +
> > + ? ? ? ?error = do_lookup_genl_family(name, attrs, &reply);
> > + ? ? ? ?if (!error) {
> > + ? ? ? ? ? ?*number = nl_attr_get_u16(attrs[CTRL_ATTR_FAMILY_ID]);
> > + ? ? ? ? ? ?define_genl_family(*number, name);
> > + ? ? ? ?} else {
> > + ? ? ? ? ? ?*number = -error;
> > + ? ? ? ?}
> > + ? ? ? ?ofpbuf_delete(reply);
> > +
> > ? ? ? ? assert(*number != 0);
> > ? ? }
> > ? ? return *number > 0 ? 0 : -*number;
> > --
> > 1.7.4.4
> >
> > _______________________________________________
> > dev mailing list
> > dev at openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
> >



More information about the dev mailing list