Hi,
Please take a look and consider applying. One question: why
we need to set sk->dead to 1 before calling inet_sock_release in
inet6_create? sock_orphan does this for us and is called by
inet_sock_release.
- Arnaldo
--- linux-2.4.0-test8/net/ipv6/af_inet6.c Wed Apr 26 16:13:17 2000
+++ linux-2.4.0-test8.acme/net/ipv6/af_inet6.c Sun Sep 10 20:44:16 2000
@@ -11,6 +11,7 @@
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
+ * Arnaldo Melo : check proc_net_create return, cleanups
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -104,37 +105,45 @@
static int inet6_create(struct socket *sock, int protocol)
{
- struct sock *sk;
+ int err = -EPROTONOSUPPORT;
struct proto *prot;
+ struct sock *sk = sk_alloc(PF_INET6, GFP_KERNEL, 1);
- sk = sk_alloc(PF_INET6, GFP_KERNEL, 1);
if (sk == NULL)
- goto do_oom;
+ return -ENOBUFS;
- if(sock->type == SOCK_STREAM || sock->type == SOCK_SEQPACKET) {
- if (protocol && protocol != IPPROTO_TCP)
- goto free_and_noproto;
- protocol = IPPROTO_TCP;
- prot = &tcpv6_prot;
- sock->ops = &inet6_stream_ops;
- } else if(sock->type == SOCK_DGRAM) {
- if (protocol && protocol != IPPROTO_UDP)
- goto free_and_noproto;
- protocol = IPPROTO_UDP;
- sk->no_check = UDP_CSUM_DEFAULT;
- prot=&udpv6_prot;
- sock->ops = &inet6_dgram_ops;
- } else if(sock->type == SOCK_RAW) {
- if (!capable(CAP_NET_RAW))
- goto free_and_badperm;
- if (!protocol)
- goto free_and_noproto;
- prot = &rawv6_prot;
- sock->ops = &inet6_dgram_ops;
- sk->reuse = 1;
- sk->num = protocol;
- } else {
- goto free_and_badtype;
+ switch(sock->type) {
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ if (protocol && protocol != IPPROTO_TCP)
+ goto cleanup_sk;
+ protocol = IPPROTO_TCP;
+ prot = &tcpv6_prot;
+ sock->ops = &inet6_stream_ops;
+ break;
+ case SOCK_DGRAM:
+ if (protocol && protocol != IPPROTO_UDP)
+ goto cleanup_sk;
+ protocol = IPPROTO_UDP;
+ sk->no_check = UDP_CSUM_DEFAULT;
+ prot = &udpv6_prot;
+ sock->ops = &inet6_dgram_ops;
+ break;
+ case SOCK_RAW:
+ if (!capable(CAP_NET_RAW)) {
+ err = -EPERM;
+ goto cleanup_sk;
+ }
+ if (!protocol)
+ goto cleanup_sk;
+ prot = &rawv6_prot;
+ sock->ops = &inet6_dgram_ops;
+ sk->reuse = 1;
+ sk->num = protocol;
+ break;
+ default:
+ err = -ESOCKTNOSUPPORT;
+ goto cleanup_sk;
}
sock_init_data(sock, sk);
@@ -191,22 +200,14 @@
if (err != 0) {
sk->dead = 1;
inet_sock_release(sk);
+ MOD_DEC_USE_COUNT;
return(err);
}
}
return(0);
-
-free_and_badtype:
- sk_free(sk);
- return -ESOCKTNOSUPPORT;
-free_and_badperm:
- sk_free(sk);
- return -EPERM;
-free_and_noproto:
+cleanup_sk:
sk_free(sk);
- return -EPROTONOSUPPORT;
-do_oom:
- return -ENOBUFS;
+ return err;
}
@@ -395,10 +396,8 @@
{
case FIOSETOWN:
case SIOCSPGRP:
- err = get_user(pid, (int *) arg);
- if(err)
- return err;
-
+ if (get_user(pid, (int *) arg))
+ return -EFAULT;
/* see sock_no_fcntl */
if (current->pid != pid && current->pgrp != -pid &&
!capable(CAP_NET_ADMIN))
@@ -407,24 +406,14 @@
return(0);
case FIOGETOWN:
case SIOCGPGRP:
- err = put_user(sk->proc,(int *)arg);
- if(err)
- return err;
- return(0);
+ return put_user(sk->proc,(int *)arg);
case SIOCGSTAMP:
if(sk->stamp.tv_sec==0)
return -ENOENT;
- err = copy_to_user((void *)arg, &sk->stamp,
- sizeof(struct timeval));
- if (err)
- return -EFAULT;
- return 0;
-
+ return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
case SIOCADDRT:
case SIOCDELRT:
-
return(ipv6_route_ioctl(cmd,(void *)arg));
-
case SIOCSIFADDR:
return addrconf_add_ifaddr((void *) arg);
case SIOCDIFADDR:
@@ -550,6 +539,20 @@
err = igmp6_init(&inet6_family_ops);
if (err)
goto igmp_fail;
+ /* Create /proc/foo6 entries. */
+#ifdef CONFIG_PROC_FS
+ err = -ENOMEM;
+ if (!proc_net_create("raw6", 0, raw6_get_info))
+ goto proc_raw6_fail;
+ if (!proc_net_create("tcp6", 0, tcp6_get_info))
+ goto proc_tcp6_fail;
+ if (!proc_net_create("udp6", 0, udp6_get_info))
+ goto proc_udp6_fail;
+ if (!proc_net_create("sockstat6", 0, afinet6_get_info))
+ goto proc_sockstat6_fail;
+ if (!proc_net_create("snmp6", 0, afinet6_get_snmp))
+ goto proc_snmp6_fail;
+#endif
ipv6_netdev_notif_init();
ipv6_packet_init();
ip6_route_init();
@@ -561,15 +564,6 @@
udpv6_init();
tcpv6_init();
- /* Create /proc/foo6 entries. */
-#ifdef CONFIG_PROC_FS
- proc_net_create("raw6", 0, raw6_get_info);
- proc_net_create("tcp6", 0, tcp6_get_info);
- proc_net_create("udp6", 0, udp6_get_info);
- proc_net_create("sockstat6", 0, afinet6_get_info);
- proc_net_create("snmp6", 0, afinet6_get_snmp);
-#endif
-
/* Now the userspace is allowed to create INET6 sockets. */
(void) sock_register(&inet6_family_ops);
@@ -579,6 +573,18 @@
return;
#endif
+#ifdef CONFIG_PROC_FS
+proc_snmp6_fail:
+ proc_net_remove("sockstat6");
+proc_sockstat6_fail:
+ proc_net_remove("udp6");
+proc_udp6_fail:
+ proc_net_remove("tcp6");
+proc_tcp6_fail:
+ proc_net_remove("raw6");
+proc_raw6_fail:
+ igmp6_cleanup();
+#endif
igmp_fail:
ndisc_cleanup();
ndisc_fail:
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Fri Sep 15 2000 - 21:00:14 EST