diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-09-16 19:02:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-09-16 19:02:12 -0400 |
commit | 293035479942400a7fe8e4f72465d4e4e466b91a (patch) | |
tree | af9890403a554b4cf8389a9116080a0d1aa187fb /include | |
parent | ddeee3ce7fbf0e800f2a26a76d6018b42b337cc2 (diff) |
[SCTP]: Add RCU synchronization around sctp_localaddr_list
sctp_localaddr_list is modified dynamically via NETDEV_UP
and NETDEV_DOWN events, but there is not synchronization
between writer (even handler) and readers. As a result,
the readers can access an entry that has been freed and
crash the sytem.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Sridhar Samdurala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/sctp/sctp.h | 1 | ||||
-rw-r--r-- | include/net/sctp/structs.h | 6 |
2 files changed, 7 insertions, 0 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index d529045c1679..c9cc00c85782 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -123,6 +123,7 @@ | |||
123 | * sctp/protocol.c | 123 | * sctp/protocol.c |
124 | */ | 124 | */ |
125 | extern struct sock *sctp_get_ctl_sock(void); | 125 | extern struct sock *sctp_get_ctl_sock(void); |
126 | extern void sctp_local_addr_free(struct rcu_head *head); | ||
126 | extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, | 127 | extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, |
127 | sctp_scope_t, gfp_t gfp, | 128 | sctp_scope_t, gfp_t gfp, |
128 | int flags); | 129 | int flags); |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index c0d5848c33dc..a89e36197afb 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -207,6 +207,9 @@ extern struct sctp_globals { | |||
207 | * It is a list of sctp_sockaddr_entry. | 207 | * It is a list of sctp_sockaddr_entry. |
208 | */ | 208 | */ |
209 | struct list_head local_addr_list; | 209 | struct list_head local_addr_list; |
210 | |||
211 | /* Lock that protects the local_addr_list writers */ | ||
212 | spinlock_t addr_list_lock; | ||
210 | 213 | ||
211 | /* Flag to indicate if addip is enabled. */ | 214 | /* Flag to indicate if addip is enabled. */ |
212 | int addip_enable; | 215 | int addip_enable; |
@@ -242,6 +245,7 @@ extern struct sctp_globals { | |||
242 | #define sctp_port_alloc_lock (sctp_globals.port_alloc_lock) | 245 | #define sctp_port_alloc_lock (sctp_globals.port_alloc_lock) |
243 | #define sctp_port_hashtable (sctp_globals.port_hashtable) | 246 | #define sctp_port_hashtable (sctp_globals.port_hashtable) |
244 | #define sctp_local_addr_list (sctp_globals.local_addr_list) | 247 | #define sctp_local_addr_list (sctp_globals.local_addr_list) |
248 | #define sctp_local_addr_lock (sctp_globals.addr_list_lock) | ||
245 | #define sctp_addip_enable (sctp_globals.addip_enable) | 249 | #define sctp_addip_enable (sctp_globals.addip_enable) |
246 | #define sctp_prsctp_enable (sctp_globals.prsctp_enable) | 250 | #define sctp_prsctp_enable (sctp_globals.prsctp_enable) |
247 | 251 | ||
@@ -737,8 +741,10 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk); | |||
737 | /* This is a structure for holding either an IPv6 or an IPv4 address. */ | 741 | /* This is a structure for holding either an IPv6 or an IPv4 address. */ |
738 | struct sctp_sockaddr_entry { | 742 | struct sctp_sockaddr_entry { |
739 | struct list_head list; | 743 | struct list_head list; |
744 | struct rcu_head rcu; | ||
740 | union sctp_addr a; | 745 | union sctp_addr a; |
741 | __u8 use_as_src; | 746 | __u8 use_as_src; |
747 | __u8 valid; | ||
742 | }; | 748 | }; |
743 | 749 | ||
744 | typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *); | 750 | typedef struct sctp_chunk *(sctp_packet_phandler_t)(struct sctp_association *); |