]> git.neil.brown.name Git - portmap.git/commitdiff
Only fail an 'unregister' attempt if nothing can be unregistered. master
authorDenis Zaitceff <zaitceff@gmail.com>
Fri, 20 Jun 2014 17:09:26 +0000 (23:09 +0600)
committerNeil Brown <neilb@suse.de>
Mon, 23 Jun 2014 01:19:03 +0000 (11:19 +1000)
It is possible that the registration for some protocol can be
unregistered by a given request, but others cannot.
Currently we abort if we find something that cannot be unregistered,
even if we have already successfuly unregistered something else.
It is better to unregister whatever we can, and return success if
anything was successful.

Original comment:

There is some inconsistency(-alike?) in the portmap protocol:

a) PMAPPROC_SET registers the only one program using the
 (prog,vers,prot) key, while PMAPPROC_UNSET unregisters all the (two)
 programs, as it uses just the (prog,vers) key.

b) Then, it seems to be pretty legal, if two different processes SET
 the same (prog,vers) tuples - one for TCP and another for UDP.

And at the UNSET step, portmap can catch some security question: say,
one process has been used the privileged port for registration, while
another process has not.  And, considering b), portmap must refuse to
UNSET the privileged port if it was asked by unprivileged port's
process.  And this should not be considered as an error, while ever
one port is UNSET.  But in the current implementation, that "mixed"
cases are treated as just an error.  The patch fixes this behaviour.
Please apply it, if my understanding is correct.

Signed-off-by: Neil Brown <neilb@suse.de>
from_local.c
portmap.c

index da851c687820889f59448b877ede6e1218cb1299..eb02a9956745207d89bd250ed0a5ca26a167e378 100644 (file)
@@ -162,6 +162,16 @@ int from_local(struct sockaddr_in *addr)
                   sizeof(struct in_addr)) == 0)
            return (TRUE);
     }
+    /* maybe a new interface was added */
+    free(addrs);
+    addrs = NULL;
+    find_local();
+    for (i = 0; i < num_local; i++) {
+       if (memcmp((char *) &(addr->sin_addr), (char *) &(addrs[i]),
+                  sizeof(struct in_addr)) == 0)
+           return (TRUE);
+    }
+
     return (FALSE);
 }
 
index ed8e50c7873dd22e5f6930529f18d9a99679394a..6a7586fe9eb3646386a16a9dec25a539f8ae53b0 100644 (file)
--- a/portmap.c
+++ b/portmap.c
@@ -568,17 +568,14 @@ static void reg_service(struct svc_req *rqstp, SVCXPRT *xprt)
                                if (!check_privileged_port(svc_getcaller(xprt), 
                                    rqstp->rq_proc, 
                                    reg.pm_prog, 
-                                   pml->pml_map.pm_port)) {
-                                       ans = 0;
-                                       break;
-                               }
+                                   pml->pml_map.pm_port))
+                                       continue;
+
                                fpml = (struct flagged_pml*)pml;
                                if (fpml->priv &&
                                    (ntohs(svc_getcaller(xprt)->sin_port)
-                                    >= IPPORT_RESERVED)) {
-                                       ans = 0;
-                                       break;
-                               }
+                                    >= IPPORT_RESERVED))
+                                       continue;
 
                                ans = 1;
                                t = (caddr_t)pml;