From nobody@FreeBSD.org  Tue Jul  7 11:17:32 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 72A50106564A
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  7 Jul 2009 11:17:32 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 602638FC0A
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  7 Jul 2009 11:17:32 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n67BHVCH072444
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 7 Jul 2009 11:17:31 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n67BHVNX072443;
	Tue, 7 Jul 2009 11:17:31 GMT
	(envelope-from nobody)
Message-Id: <200907071117.n67BHVNX072443@www.freebsd.org>
Date: Tue, 7 Jul 2009 11:17:31 GMT
From: pluknet <pluknet@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [regression] pkg_add segfault on adding package when it's a broken symlink
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         136419
>Category:       bin
>Synopsis:       [regression] pkg_add(1) segfault on adding package when it's a broken symlink
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    portmgr
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 07 11:20:01 UTC 2009
>Closed-Date:    Mon May 21 13:32:51 UTC 2012
>Last-Modified:  Mon May 21 13:32:51 UTC 2012
>Originator:     pluknet
>Release:        6.4-RELEASE-p5
>Organization:
>Environment:
world and kernel are in sync
>Description:
pkg_add coredumps in strdup() on adding package which is a broken symlink.
Symlink is a sort of foo -> bar/baz, where bar doesn't exists.

# file /usr/sbin/pkg_add 
/usr/sbin/pkg_add: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), for FreeBSD 6.4, dynamically linked (uses shared libs), FreeBSD-style, stripped
>How-To-Repeat:
Add package: pkg_add cannot process properly a broken symlink.

# pkg_add /usr/local/src/packages/p5-IO-Tty-1.08.tbz 
Segmentation fault (core dumped)
# ls -l /usr/local/src/packages/p5-IO-Tty-1.08.tbz 
lrwxr-xr-x  1 root  wheel  34 Jul  6 18:34 /usr/local/src/packages/p5-IO-Tty-1.08.tbz -> ../packages-6.4/p5-IO-Tty-1.08.tbz
# ls /usr/local/src/
packages
# ./pkg_add /usr/local/src/packages/p5-IO-Tty-1.08.tbz 
Segmentation fault (core dumped)
# gdb ./pkg_add pkg_add.core
[...]
#0  0x28262ff0 in strdup () from /lib/libc.so.6
(gdb) bt
#0  0x28262ff0 in strdup () from /lib/libc.so.6
#1  0x0804a1d3 in real_main (argc=0, argv=0xbfbfec80) at main.c:245
#2  0x0804d8f4 in main ()
(gdb) f 1
#1  0x0804a1d3 in real_main (argc=0, argv=0xbfbfec80) at main.c:245
245                         pkgs[ch] = strdup(realpath(*argv, temp));
(gdb) list
240                     if (strlcpy(temp, remotepkg, sizeof(temp)) >= sizeof(temp))
241                         errx(1, "package name too long");
242                     pkgs[ch] = strdup(temp);
243                 } else {                    /* expand all pathnames to fullnames */
244                     if (fexists(*argv)) /* refers to a file directly */
245                         pkgs[ch] = strdup(realpath(*argv, temp));
246                     else {          /* look for the file in the expected places */
247                         if (!(cp = fileFindByPath(NULL, *argv))) {
248                             /* let pkg_do() fail later, so that error is reported */
249                             if (strlcpy(temp, *argv, sizeof(temp)) >= sizeof(temp))

>Fix:
Workaround: restore a broken symlink.

# mount -t nfs nfs-server:/path/to/packages-6.4 /usr/local/src/packages-6.4
# ./pkg_add /usr/local/src/packages/p5-IO-Tty-1.08.tbz                 
#

Fix: revert usr.sbin/pkg_install/lib/file.c cvs r1.11 to a lesser bogus access() check. From r1.11 change:
@@ -30,7 +30,8 @@ static const char *rcsid = "$Id: file.c,
 Boolean
 fexists(char *fname)
 {
-    if (!access(fname, F_OK))
+    struct stat dummy;
+    if (!lstat(fname, &dummy))
 	return TRUE;
     return FALSE;
 }

Let's see how fexists() taken from lib/file.c goes on current lstat():

[pluknet@host-156]$ ls -l foo 
lrwxr-xr-x  1 pluknet  pluknet  7  7 &#1080;&#1102;&#1083; 14:40 foo -> bar/baz
[pluknet@host-156]$ ls -l bar
ls: bar: No such file or directory
[pluknet@host-156]$ head -21 test.c | tail -12
fexists(const char *fname)
{ 
    struct stat dummy;

    printf("checking %s..\n", fname);
    if (!lstat(fname, &dummy)) {
        printf("looks good\n");
        return 1;
    }
    printf("bad fnpath\n");
    return 0;
} 
[pluknet@host-156]$ ./test foo
checking foo..
looks good
Segmentation fault: 11 (core dumped)

. and on older access() check:

[pluknet@host-156]$ head -21 test.c | tail -12
fexists(const char *fname)
{ 
//    struct stat dummy;

    printf("checking %s..\n", fname);
    if (!access(fname, F_OK)) {
        printf("looks good\n");
        return 1;
    }
    printf("bad fnpath\n");
    return 0;
} 
[pluknet@host-156]$ ./test foo
checking foo..
bad fnpath


>Release-Note:
>Audit-Trail:

From: Efstratios Karatzas <gpf.kira@gmail.com>
To: bug-followup@freebsd.org
Cc:  
Subject: Re: bin/136419: [regression] pkg_add(1) segfault on adding package 
	when it's a broken symlink
Date: Thu, 11 Feb 2010 17:32:06 +0200

 Just a quick note, this PR as well as bin/139606 refer to the same problem.
 Both have a patch although this one doesn't take the race condition under
 consideration so pkg_add(1) may still segfault.
 
 -- 
 
 Efstratios "GPF" Karatzas
State-Changed-From-To: open->patched 
State-Changed-By: flz 
State-Changed-When: Thu Apr 1 17:10:32 UTC 2010 
State-Changed-Why:  
A patch addressing this issue has been committed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=136419 
Responsible-Changed-From-To: freebsd-bugs->portmgr 
Responsible-Changed-By: flz 
Responsible-Changed-When: Thu Apr 1 17:20:24 UTC 2010 
Responsible-Changed-Why:  
pkg_install is maintained by portmgr. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=136419 
State-Changed-From-To: patched->closed 
State-Changed-By: bapt 
State-Changed-When: Mon May 21 13:32:49 UTC 2012 
State-Changed-Why:  
A fix has already been committed 

http://www.freebsd.org/cgi/query-pr.cgi?pr=136419 
>Unformatted:
