bin/136419: [regression] pkg_add segfault on adding package when
it's a broken symlink
pluknet
pluknet at gmail.com
Tue Jul 7 11:20:02 UTC 2009
>Number: 136419
>Category: bin
>Synopsis: [regression] pkg_add segfault on adding package when it's a broken symlink
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Jul 07 11:20:01 UTC 2009
>Closed-Date:
>Last-Modified:
>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 at host-156]$ ls -l foo
lrwxr-xr-x 1 pluknet pluknet 7 7 июл 14:40 foo -> bar/baz
[pluknet at host-156]$ ls -l bar
ls: bar: No such file or directory
[pluknet at 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 at host-156]$ ./test foo
checking foo..
looks good
Segmentation fault: 11 (core dumped)
. and on older access() check:
[pluknet at 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 at host-156]$ ./test foo
checking foo..
bad fnpath
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list