aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2008-04-15 22:04:54 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-15 22:04:54 -0400
commit85035568a96065de6fb29478707a3ad5f1fed169 (patch)
tree1f90673d173b40ca48de6eb7d3d65a3d3e64ea46 /net/tipc/link.c
parentfe13dda2d24eca2ee8a6bb8a0af88ab84d589fd6 (diff)
[TIPC]: Enhance validation of format on incoming messages
This patch ensures that TIPC properly handles incoming messages that have incorrect or unexpected formats. Most significantly, it now ensures that each sl_buff has at least as much data as the message header indicates it should, and that the entire message header is stored contiguously; this prevents TIPC from accidentally accessing memory that is not part of the sk_buff. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c89
1 files changed, 77 insertions, 12 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 087379366d3c..2a26a16e269f 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1785,6 +1785,56 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
1785 return buf; 1785 return buf;
1786} 1786}
1787 1787
1788/**
1789 * link_recv_buf_validate - validate basic format of received message
1790 *
1791 * This routine ensures a TIPC message has an acceptable header, and at least
1792 * as much data as the header indicates it should. The routine also ensures
1793 * that the entire message header is stored in the main fragment of the message
1794 * buffer, to simplify future access to message header fields.
1795 *
1796 * Note: Having extra info present in the message header or data areas is OK.
1797 * TIPC will ignore the excess, under the assumption that it is optional info
1798 * introduced by a later release of the protocol.
1799 */
1800
1801static int link_recv_buf_validate(struct sk_buff *buf)
1802{
1803 static u32 min_data_hdr_size[8] = {
1804 SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE,
1805 MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
1806 };
1807
1808 struct tipc_msg *msg;
1809 u32 tipc_hdr[2];
1810 u32 size;
1811 u32 hdr_size;
1812 u32 min_hdr_size;
1813
1814 if (unlikely(buf->len < MIN_H_SIZE))
1815 return 0;
1816
1817 msg = skb_header_pointer(buf, 0, sizeof(tipc_hdr), tipc_hdr);
1818 if (msg == NULL)
1819 return 0;
1820
1821 if (unlikely(msg_version(msg) != TIPC_VERSION))
1822 return 0;
1823
1824 size = msg_size(msg);
1825 hdr_size = msg_hdr_sz(msg);
1826 min_hdr_size = msg_isdata(msg) ?
1827 min_data_hdr_size[msg_type(msg)] : INT_H_SIZE;
1828
1829 if (unlikely((hdr_size < min_hdr_size) ||
1830 (size < hdr_size) ||
1831 (buf->len < size) ||
1832 (size - hdr_size > TIPC_MAX_USER_MSG_SIZE)))
1833 return 0;
1834
1835 return pskb_may_pull(buf, hdr_size);
1836}
1837
1788void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) 1838void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1789{ 1839{
1790 read_lock_bh(&tipc_net_lock); 1840 read_lock_bh(&tipc_net_lock);
@@ -1794,9 +1844,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1794 struct link *l_ptr; 1844 struct link *l_ptr;
1795 struct sk_buff *crs; 1845 struct sk_buff *crs;
1796 struct sk_buff *buf = head; 1846 struct sk_buff *buf = head;
1797 struct tipc_msg *msg = buf_msg(buf); 1847 struct tipc_msg *msg;
1798 u32 seq_no = msg_seqno(msg); 1848 u32 seq_no;
1799 u32 ackd = msg_ack(msg); 1849 u32 ackd;
1800 u32 released = 0; 1850 u32 released = 0;
1801 int type; 1851 int type;
1802 1852
@@ -1804,12 +1854,11 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1804 TIPC_SKB_CB(buf)->handle = b_ptr; 1854 TIPC_SKB_CB(buf)->handle = b_ptr;
1805 1855
1806 head = head->next; 1856 head = head->next;
1807 if (unlikely(msg_version(msg) != TIPC_VERSION)) 1857
1858 /* Ensure message is well-formed */
1859
1860 if (unlikely(!link_recv_buf_validate(buf)))
1808 goto cont; 1861 goto cont;
1809#if 0
1810 if (msg_user(msg) != LINK_PROTOCOL)
1811#endif
1812 msg_dbg(msg,"<REC<");
1813 1862
1814 /* Ensure message data is a single contiguous unit */ 1863 /* Ensure message data is a single contiguous unit */
1815 1864
@@ -1817,6 +1866,10 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1817 goto cont; 1866 goto cont;
1818 } 1867 }
1819 1868
1869 /* Handle arrival of a non-unicast link message */
1870
1871 msg = buf_msg(buf);
1872
1820 if (unlikely(msg_non_seq(msg))) { 1873 if (unlikely(msg_non_seq(msg))) {
1821 link_recv_non_seq(buf); 1874 link_recv_non_seq(buf);
1822 continue; 1875 continue;
@@ -1826,19 +1879,26 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1826 (msg_destnode(msg) != tipc_own_addr))) 1879 (msg_destnode(msg) != tipc_own_addr)))
1827 goto cont; 1880 goto cont;
1828 1881
1882 /* Locate unicast link endpoint that should handle message */
1883
1829 n_ptr = tipc_node_find(msg_prevnode(msg)); 1884 n_ptr = tipc_node_find(msg_prevnode(msg));
1830 if (unlikely(!n_ptr)) 1885 if (unlikely(!n_ptr))
1831 goto cont; 1886 goto cont;
1832
1833 tipc_node_lock(n_ptr); 1887 tipc_node_lock(n_ptr);
1888
1834 l_ptr = n_ptr->links[b_ptr->identity]; 1889 l_ptr = n_ptr->links[b_ptr->identity];
1835 if (unlikely(!l_ptr)) { 1890 if (unlikely(!l_ptr)) {
1836 tipc_node_unlock(n_ptr); 1891 tipc_node_unlock(n_ptr);
1837 goto cont; 1892 goto cont;
1838 } 1893 }
1839 /* 1894
1840 * Release acked messages 1895 /* Validate message sequence number info */
1841 */ 1896
1897 seq_no = msg_seqno(msg);
1898 ackd = msg_ack(msg);
1899
1900 /* Release acked messages */
1901
1842 if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) { 1902 if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
1843 if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported) 1903 if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported)
1844 tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); 1904 tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
@@ -1857,6 +1917,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1857 l_ptr->first_out = crs; 1917 l_ptr->first_out = crs;
1858 l_ptr->out_queue_size -= released; 1918 l_ptr->out_queue_size -= released;
1859 } 1919 }
1920
1921 /* Try sending any messages link endpoint has pending */
1922
1860 if (unlikely(l_ptr->next_out)) 1923 if (unlikely(l_ptr->next_out))
1861 tipc_link_push_queue(l_ptr); 1924 tipc_link_push_queue(l_ptr);
1862 if (unlikely(!list_empty(&l_ptr->waiting_ports))) 1925 if (unlikely(!list_empty(&l_ptr->waiting_ports)))
@@ -1866,6 +1929,8 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1866 tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); 1929 tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
1867 } 1930 }
1868 1931
1932 /* Now (finally!) process the incoming message */
1933
1869protocol_check: 1934protocol_check:
1870 if (likely(link_working_working(l_ptr))) { 1935 if (likely(link_working_working(l_ptr))) {
1871 if (likely(seq_no == mod(l_ptr->next_in_no))) { 1936 if (likely(seq_no == mod(l_ptr->next_in_no))) {