[PATCH] af_ipv6.c: check proc_net_create and cleanups

From: Arnaldo Carvalho de Melo (acme@conectiva.com.br)
Date: Sun Sep 10 2000 - 18:58:52 EST


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