tipc: Fix skb_under_panic when configuring TIPC without privileges
authorAllan Stephens <allan.stephens@windriver.com>
Wed, 21 May 2008 21:52:30 +0000 (14:52 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 21 May 2008 21:52:30 +0000 (14:52 -0700)
This patch prevents a TIPC configuration command requiring network
administrator privileges from triggering an skbuff underrun if it
is issued by a process lacking those privileges.  The revised error
handling code avoids the use of a potentially uninitialized global
variable by transforming the unauthorized command into a new command,
then following the standard command processing path to generate the
required error message.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/tipc_config.h
net/tipc/config.c
net/tipc/netlink.c

index b0c916d1f37508f817ef52dba253d3f939391fb0..2bc6fa4adeb5e2d2076b456ad4cfd6943952cef9 100644 (file)
@@ -2,7 +2,7 @@
  * include/linux/tipc_config.h: Include file for TIPC configuration interface
  * 
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #define  TIPC_CMD_SET_MAX_SLAVES    0x800A    /* tx unsigned, rx none */
 #define  TIPC_CMD_SET_NETID         0x800B    /* tx unsigned, rx none */
 
+/*
+ * Reserved commands:
+ * May not be issued by any process.
+ * Used internally by TIPC.
+ */
+
+#define  TIPC_CMD_NOT_NET_ADMIN     0xC001    /* tx none, rx none */
+
 /*
  * TLV types defined for TIPC
  */
index 91d56f8fee9f1a94249ec8fdf4e79b2602894757..16e7cb74969b02204b007d59ef9861372fdd4c11 100644 (file)
@@ -2,7 +2,7 @@
  * net/tipc/config.c: TIPC configuration management code
  *
  * Copyright (c) 2002-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 2004-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -602,6 +602,10 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
        case TIPC_CMD_GET_NETID:
                rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
                break;
+       case TIPC_CMD_NOT_NET_ADMIN:
+               rep_tlv_buf =
+                       tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
+               break;
        default:
                rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
                                                          " (unknown command)");
index 6a7f7b4c2595b365ff5f3b015b23e553080baa8e..c387217bb23066d20c6324cd0c9ee0d8200a91bd 100644 (file)
@@ -2,7 +2,7 @@
  * net/tipc/netlink.c: TIPC configuration handling
  *
  * Copyright (c) 2005-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2007, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,15 +45,17 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
        struct nlmsghdr *req_nlh = info->nlhdr;
        struct tipc_genlmsghdr *req_userhdr = info->userhdr;
        int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN);
+       u16 cmd;
 
        if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
-               rep_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
+               cmd = TIPC_CMD_NOT_NET_ADMIN;
        else
-               rep_buf = tipc_cfg_do_cmd(req_userhdr->dest,
-                                         req_userhdr->cmd,
-                                         NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
-                                         NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
-                                         hdr_space);
+               cmd = req_userhdr->cmd;
+
+       rep_buf = tipc_cfg_do_cmd(req_userhdr->dest, cmd,
+                       NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
+                       NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
+                       hdr_space);
 
        if (rep_buf) {
                skb_push(rep_buf, hdr_space);