diff options
author | Allan Stephens <allan.stephens@windriver.com> | 2008-05-12 18:42:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-12 18:42:28 -0400 |
commit | 7ef43ebaa538e0cc9063cbf84593a05091bcace2 (patch) | |
tree | d2bac748f6620cc2f217672105918b2116f6c958 /net/tipc/port.c | |
parent | 4e3e6dcb43c3669a8817cb3d0f920f91661afd98 (diff) |
tipc: Fix race condition when creating socket or native port
This patch eliminates the (very remote) chance of a crash resulting
from a partially initialized socket or native port unexpectedly
receiving a message. Now, during the creation of a socket or native
port, the underlying generic port's lock is not released until all
initialization required to handle incoming messages has been done.
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/port.c')
-rw-r--r-- | net/tipc/port.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/net/tipc/port.c b/net/tipc/port.c index 2f5806410c64..757de38fe6af 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -211,15 +211,18 @@ exit: | |||
211 | } | 211 | } |
212 | 212 | ||
213 | /** | 213 | /** |
214 | * tipc_createport_raw - create a native TIPC port | 214 | * tipc_createport_raw - create a generic TIPC port |
215 | * | 215 | * |
216 | * Returns local port reference | 216 | * Returns port reference, or 0 if unable to create it |
217 | * | ||
218 | * Note: The newly created port is returned in the locked state. | ||
217 | */ | 219 | */ |
218 | 220 | ||
219 | u32 tipc_createport_raw(void *usr_handle, | 221 | u32 tipc_createport_raw(void *usr_handle, |
220 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | 222 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), |
221 | void (*wakeup)(struct tipc_port *), | 223 | void (*wakeup)(struct tipc_port *), |
222 | const u32 importance) | 224 | const u32 importance, |
225 | struct tipc_port **tp_ptr) | ||
223 | { | 226 | { |
224 | struct port *p_ptr; | 227 | struct port *p_ptr; |
225 | struct tipc_msg *msg; | 228 | struct tipc_msg *msg; |
@@ -237,7 +240,6 @@ u32 tipc_createport_raw(void *usr_handle, | |||
237 | return 0; | 240 | return 0; |
238 | } | 241 | } |
239 | 242 | ||
240 | tipc_port_lock(ref); | ||
241 | p_ptr->publ.usr_handle = usr_handle; | 243 | p_ptr->publ.usr_handle = usr_handle; |
242 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; | 244 | p_ptr->publ.max_pkt = MAX_PKT_DEFAULT; |
243 | p_ptr->publ.ref = ref; | 245 | p_ptr->publ.ref = ref; |
@@ -262,7 +264,7 @@ u32 tipc_createport_raw(void *usr_handle, | |||
262 | INIT_LIST_HEAD(&p_ptr->port_list); | 264 | INIT_LIST_HEAD(&p_ptr->port_list); |
263 | list_add_tail(&p_ptr->port_list, &ports); | 265 | list_add_tail(&p_ptr->port_list, &ports); |
264 | spin_unlock_bh(&tipc_port_list_lock); | 266 | spin_unlock_bh(&tipc_port_list_lock); |
265 | tipc_port_unlock(p_ptr); | 267 | *tp_ptr = &p_ptr->publ; |
266 | return ref; | 268 | return ref; |
267 | } | 269 | } |
268 | 270 | ||
@@ -1053,6 +1055,7 @@ int tipc_createport(u32 user_ref, | |||
1053 | { | 1055 | { |
1054 | struct user_port *up_ptr; | 1056 | struct user_port *up_ptr; |
1055 | struct port *p_ptr; | 1057 | struct port *p_ptr; |
1058 | struct tipc_port *tp_ptr; | ||
1056 | u32 ref; | 1059 | u32 ref; |
1057 | 1060 | ||
1058 | up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); | 1061 | up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC); |
@@ -1060,12 +1063,13 @@ int tipc_createport(u32 user_ref, | |||
1060 | warn("Port creation failed, no memory\n"); | 1063 | warn("Port creation failed, no memory\n"); |
1061 | return -ENOMEM; | 1064 | return -ENOMEM; |
1062 | } | 1065 | } |
1063 | ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance); | 1066 | ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, |
1064 | p_ptr = tipc_port_lock(ref); | 1067 | importance, &tp_ptr); |
1065 | if (!p_ptr) { | 1068 | if (ref == 0) { |
1066 | kfree(up_ptr); | 1069 | kfree(up_ptr); |
1067 | return -ENOMEM; | 1070 | return -ENOMEM; |
1068 | } | 1071 | } |
1072 | p_ptr = (struct port *)tp_ptr; | ||
1069 | 1073 | ||
1070 | p_ptr->user_port = up_ptr; | 1074 | p_ptr->user_port = up_ptr; |
1071 | up_ptr->user_ref = user_ref; | 1075 | up_ptr->user_ref = user_ref; |