From simon@comsys.ntu-kpi.kiev.ua  Mon Mar  5 13:12:52 2012
Return-Path: <simon@comsys.ntu-kpi.kiev.ua>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 69E44106564A
	for <FreeBSD-gnats-submit@freebsd.org>; Mon,  5 Mar 2012 13:12:52 +0000 (UTC)
	(envelope-from simon@comsys.ntu-kpi.kiev.ua)
Received: from comsys.kpi.ua (comsys.kpi.ua [77.47.192.42])
	by mx1.freebsd.org (Postfix) with ESMTP id 566558FC13
	for <FreeBSD-gnats-submit@freebsd.org>; Mon,  5 Mar 2012 13:12:50 +0000 (UTC)
Received: from pm513-1.comsys.kpi.ua ([10.18.52.101] helo=pm513-1.comsys.ntu-kpi.kiev.ua)
	by comsys.kpi.ua with esmtpsa (TLSv1:AES256-SHA:256)
	(Exim 4.63)
	(envelope-from <simon@comsys.ntu-kpi.kiev.ua>)
	id 1S4Xib-0001FW-D4
	for FreeBSD-gnats-submit@freebsd.org; Mon, 05 Mar 2012 15:12:49 +0200
Received: by pm513-1.comsys.ntu-kpi.kiev.ua (Postfix, from userid 1001)
	id A8D531CC36; Mon,  5 Mar 2012 15:12:49 +0200 (EET)
Message-Id: <20120305131249.GA74922@pm513-1.comsys.ntu-kpi.kiev.ua>
Date: Mon, 5 Mar 2012 15:12:49 +0200
From: Andrey Simonenko <simon@comsys.ntu-kpi.kiev.ua>
To: FreeBSD-gnats-submit@freebsd.org
Subject: RPC: getnetconfig() and other netconfig's functions correct
 implementation.

>Number:         165710
>Category:       kern
>Synopsis:       [libc] [patch] RPC: getnetconfig() and other netconfig's functions correct implementation.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 05 13:20:09 UTC 2012
>Closed-Date:    Mon Sep 23 13:32:05 UTC 2013
>Last-Modified:  Mon Sep 23 13:32:05 UTC 2013
>Originator:     Andrey Simonenko
>Release:        FreeBSD 10.0-CURRENT amd64
>Organization:
>Environment:
>Description:

While developing a program that uses RPC I found out that functions
from libc/rpc/getnetconfig.c and getnetpath.c do not worked as expected
or have mistakes:

1.  __nc_error() does not check return value from malloc() and can
    pass NULL pointer to thr_setspecific().

2.  setnetconfig() has a race condition with reference counter when
    several threads call this function and only one thread successfully
    opened database file, while other threads failed in this function.
    If that one thread called endnetconfig(), then it can keep cached data
    in memory, but all threads will not have opened handles.

3.  getnetconfig() should return entries from /etc/netconfig file in
    the same order as they are specified according to netconfig(5).
    If several threads call getnetconfig() using different handlers,
    then entries for each handler will be returned in random order.

4.  getnetconfig() has a race condition that can cause NULL pointer
    dereference when several threads call this function using one handler.

5.  getnetconfig() allows to continue to get entries if database file has
    invalid format, because it does not remember previous state.

6.  endnetconfig() has a race condition with reference count and
    can keep cached data, while all handlers are closed.

7.  getnetconfigent() uses getnetconfig() and has the same mistakes,
    also this function duplicates code from getnetconfig().

8.  getnetconfig() and getnetconfigent() use too much memory for
    entry data, each entry require ~1 kbytes of memory, while usually
    only 50 bytes is needed.

9.  parse_ncp() incorrectly parses flags in netconfig entry and allows
    wrong combinations of flags, it does not allow spaces before entry,
    does not check number of elements in each netconfig entry, does not
    allow empty lines.

10. nc_sperror() is not optimal.

11. dup_ncp() is not optimal, allocates more memory than was used in
    the original structure, call strcpy() several times instead of
    calling memcpy() one time.

12. setnetpath() is not optimal, e.g. it calls setnetconfig() and then
    calls endnetconfig().

13. getnetpath() uses getnetconfig() and getnetconfigent() and has
    the same mistakes.

14. getnetpath() has race conditions when several threads call this
    function using one handler, as a result there are memory leaks
    and not synchronized access with modifications to data if the NETPATH
    environment variable is set.

15. _get_next_token() is too complex, incorrectly understand \-sequences.

16. All functions do not specify error code in all possible cases,
    so nc_sperror() and nc_perror() functions are useless.

I tried to modify getnetconfig.c and getnetpath.c files, but all
above listed mistakes (I could forget few other mistakes) required
complete rewriting of these two files.

So, I created a new file libc/rpc/netconfig.c that contains all
functions described in getnetconfig.3 and getnetpath.3.

Difference between netconfig.c vs getnetconfig.c and getnetpath.c:

1. __nc_error() was corrected, but its implementation is the same,
   this is a standard implementation for thread-specific data handling.
   nc_perror() was taken from getnetconfig.c, it cannot be written
   in other way.

2. Some errors messages were taken from getnetconfig.c.

3. New nc_parse() (old parse_ncp()) was corrected and optimized a bit,
   it just parses white space separated fields in a string.

4. Some variables and macro variables names were taken from getnetconfig.c.

5. All other functions and data structures were rewritten.

Additionally I corrected libc/include/reentrant.h, getnetconfig.3,
and getnetpath.3.

>How-To-Repeat:
>Fix:
 [ patch elided -gavin@ ]
State-Changed-From-To: open->closed 
State-Changed-By: gavin 
State-Changed-When: Mon Sep 23 13:31:17 UTC 2013 
State-Changed-Why:  
PR closed at request of submitter. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=165710 
>Release-Note:
>Audit-Trail:
>Unformatted:
