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/rose | |
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/rose')
-rw-r--r-- | net/rose/af_rose.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 3fe7e562125a..5480caf8ccc2 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -626,7 +626,8 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
626 | struct rose_sock *rose = rose_sk(sk); | 626 | struct rose_sock *rose = rose_sk(sk); |
627 | struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; | 627 | struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; |
628 | struct net_device *dev; | 628 | struct net_device *dev; |
629 | ax25_address *user, *source; | 629 | ax25_address *source; |
630 | ax25_uid_assoc *user; | ||
630 | int n; | 631 | int n; |
631 | 632 | ||
632 | if (!sock_flag(sk, SOCK_ZAPPED)) | 633 | if (!sock_flag(sk, SOCK_ZAPPED)) |
@@ -651,14 +652,17 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
651 | 652 | ||
652 | source = &addr->srose_call; | 653 | source = &addr->srose_call; |
653 | 654 | ||
654 | if ((user = ax25_findbyuid(current->euid)) == NULL) { | 655 | user = ax25_findbyuid(current->euid); |
656 | if (user) { | ||
657 | rose->source_call = user->call; | ||
658 | ax25_uid_put(user); | ||
659 | } else { | ||
655 | if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) | 660 | if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) |
656 | return -EACCES; | 661 | return -EACCES; |
657 | user = source; | 662 | rose->source_call = *source; |
658 | } | 663 | } |
659 | 664 | ||
660 | rose->source_addr = addr->srose_addr; | 665 | rose->source_addr = addr->srose_addr; |
661 | rose->source_call = *user; | ||
662 | rose->device = dev; | 666 | rose->device = dev; |
663 | rose->source_ndigis = addr->srose_ndigis; | 667 | rose->source_ndigis = addr->srose_ndigis; |
664 | 668 | ||
@@ -685,8 +689,8 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le | |||
685 | struct rose_sock *rose = rose_sk(sk); | 689 | struct rose_sock *rose = rose_sk(sk); |
686 | struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; | 690 | struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; |
687 | unsigned char cause, diagnostic; | 691 | unsigned char cause, diagnostic; |
688 | ax25_address *user; | ||
689 | struct net_device *dev; | 692 | struct net_device *dev; |
693 | ax25_uid_assoc *user; | ||
690 | int n; | 694 | int n; |
691 | 695 | ||
692 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | 696 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { |
@@ -736,12 +740,14 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le | |||
736 | if ((dev = rose_dev_first()) == NULL) | 740 | if ((dev = rose_dev_first()) == NULL) |
737 | return -ENETUNREACH; | 741 | return -ENETUNREACH; |
738 | 742 | ||
739 | if ((user = ax25_findbyuid(current->euid)) == NULL) | 743 | user = ax25_findbyuid(current->euid); |
744 | if (!user) | ||
740 | return -EINVAL; | 745 | return -EINVAL; |
741 | 746 | ||
742 | memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); | 747 | memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); |
743 | rose->source_call = *user; | 748 | rose->source_call = user->call; |
744 | rose->device = dev; | 749 | rose->device = dev; |
750 | ax25_uid_put(user); | ||
745 | 751 | ||
746 | rose_insert_socket(sk); /* Finish the bind */ | 752 | rose_insert_socket(sk); /* Finish the bind */ |
747 | } | 753 | } |