aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/port.c
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2008-05-12 18:42:28 -0400
committerDavid S. Miller <davem@davemloft.net>2008-05-12 18:42:28 -0400
commit7ef43ebaa538e0cc9063cbf84593a05091bcace2 (patch)
treed2bac748f6620cc2f217672105918b2116f6c958 /net/tipc/port.c
parent4e3e6dcb43c3669a8817cb3d0f920f91661afd98 (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.c20
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
219u32 tipc_createport_raw(void *usr_handle, 221u32 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;