diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-08-23 13:11:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-08-23 13:11:45 -0400 |
commit | 01d7dd0e9f8c5f1888619d2649c7da389232b408 (patch) | |
tree | ee4f22a33557bae4883eb2f4fb1359e97ac74186 /net/ax25/af_ax25.c | |
parent | 53b924b31fa53ac3007df3fef6870d5074a9adf8 (diff) |
[AX25]: UID fixes
o Brown paperbag bug - ax25_findbyuid() was always returning a NULL pointer
as the result. Breaks ROSE completly and AX.25 if UID policy set to deny.
o While the list structure of AX.25's UID to callsign mapping table was
properly protected by a spinlock, it's elements were not refcounted
resulting in a race between removal and usage of an element.
Signed-off-by: Ralf Baechle DL5RB <ralf@linux-mips.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ax25/af_ax25.c')
-rw-r--r-- | net/ax25/af_ax25.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 7d8ecadba668..a5c94f11547c 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -1002,7 +1002,8 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1002 | struct sock *sk = sock->sk; | 1002 | struct sock *sk = sock->sk; |
1003 | struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; | 1003 | struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; |
1004 | ax25_dev *ax25_dev = NULL; | 1004 | ax25_dev *ax25_dev = NULL; |
1005 | ax25_address *call; | 1005 | ax25_uid_assoc *user; |
1006 | ax25_address call; | ||
1006 | ax25_cb *ax25; | 1007 | ax25_cb *ax25; |
1007 | int err = 0; | 1008 | int err = 0; |
1008 | 1009 | ||
@@ -1021,9 +1022,15 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1021 | if (addr->fsa_ax25.sax25_family != AF_AX25) | 1022 | if (addr->fsa_ax25.sax25_family != AF_AX25) |
1022 | return -EINVAL; | 1023 | return -EINVAL; |
1023 | 1024 | ||
1024 | call = ax25_findbyuid(current->euid); | 1025 | user = ax25_findbyuid(current->euid); |
1025 | if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) { | 1026 | if (user) { |
1026 | return -EACCES; | 1027 | call = user->call; |
1028 | ax25_uid_put(user); | ||
1029 | } else { | ||
1030 | if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) | ||
1031 | return -EACCES; | ||
1032 | |||
1033 | call = addr->fsa_ax25.sax25_call; | ||
1027 | } | 1034 | } |
1028 | 1035 | ||
1029 | lock_sock(sk); | 1036 | lock_sock(sk); |
@@ -1034,10 +1041,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1034 | goto out; | 1041 | goto out; |
1035 | } | 1042 | } |
1036 | 1043 | ||
1037 | if (call == NULL) | 1044 | ax25->source_addr = call; |
1038 | ax25->source_addr = addr->fsa_ax25.sax25_call; | ||
1039 | else | ||
1040 | ax25->source_addr = *call; | ||
1041 | 1045 | ||
1042 | /* | 1046 | /* |
1043 | * User already set interface with SO_BINDTODEVICE | 1047 | * User already set interface with SO_BINDTODEVICE |