NetBSD Problem Report #50772

From prlw1@cam.ac.uk  Fri Feb  5 15:03:09 2016
Return-Path: <prlw1@cam.ac.uk>
Received: from mail.netbsd.org (mail.NetBSD.org [199.233.217.200])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 3CACA7A217
	for <gnats-bugs@gnats.NetBSD.org>; Fri,  5 Feb 2016 15:03:09 +0000 (UTC)
Message-Id: <20160205150305.GB7432@quark.internal.precedence.co.uk>
Date: Fri, 5 Feb 2016 15:03:05 +0000
From: Patrick Welche <prlw1@cam.ac.uk>
Reply-To: prlw1@cam.ac.uk
To: gnats-bugs@NetBSD.org
Cc: prlw1@cam.ac.uk
Subject: perl and check_interpreter

>Number:         50772
>Category:       pkg
>Synopsis:       hard linked perl returns surprising name in $^X
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Feb 05 15:05:00 +0000 2016
>Last-Modified:  Sat Nov 19 17:35:00 +0000 2016
>Originator:     Patrick Welche
>Release:        NetBSD 7.99.26
>Organization:
>Environment:
NetBSD-7.99.26/amd64 and pkgsrc-current
>Description:
Our perl package installs perl as "perl" and as a binary with the
version number in the name, as hard links, e.g.:

$ ls -li /usr/pkg/bin/perl*
18781554 -rwxr-xr-x  2 root  wheel  11103 Dec 29 12:05 /usr/pkg/bin/perl
18781554 -rwxr-xr-x  2 root  wheel  11103 Dec 29 12:05 /usr/pkg/bin/perl5.22.1
...

The output of the following script comes as a surprise:
$ cat foo.pl
#! /usr/pkg/bin/perl
print "$^X\n"; # $EXECUTABLE_NAME in English
$ ./foo.pl
/usr/pkg/bin/perl5.22.1

Breaking the hard link with
# mv /usr/pkg/bin/perl5.22.1 /tmp; mv /tmp/perl5.22.1 /usr/pkg/bin

gets the expected:
$ ./foo.pl
/usr/pkg/bin/perl


This matters for rc.d scripts using command_interpreter="@PERL5@" to work
as rc.subr's _find_processes tries to match the command_interpreter
even given a valid pid file.

This manifested itself with spamassassin's spamd: on reload, it execs
itself with $^X, after which command_interpreter no longer matches and
status will show "not running".
>How-To-Repeat:
run
/etc/rc.d/spamd start
/etc/rc.d/spamd status
/etc/rc.d/spamd reload
/etc/rc.d/spamd status
>Fix:
Many possibilities, but which is closest to "correct"?
1) Don't hard link, but copy /usr/pkg/bin/perl.
2) Patch spamd to exec $perl_from_hashbang_line instead of $EXECUTABLE_NAME
   ( = $^X).
3) Patch /etc/rc.d/spamd to avoid using rc.subr with its command_interpreter
   checks.
4) Patch /etc/rc.subr to override procname match given pidfile.

>Audit-Trail:
From: David Holland <dholland-pbugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: pkg/50772: perl and check_interpreter
Date: Sat, 6 Feb 2016 06:02:09 +0000

 On Fri, Feb 05, 2016 at 03:05:00PM +0000, Patrick Welche wrote:
  > The output of the following script comes as a surprise:
  > $ cat foo.pl
  > #! /usr/pkg/bin/perl
  > print "$^X\n"; # $EXECUTABLE_NAME in English
  > $ ./foo.pl
  > /usr/pkg/bin/perl5.22.1

 What mechanism is underneath that?

  > Many possibilities, but which is closest to "correct"?
  > 1) Don't hard link, but copy /usr/pkg/bin/perl.
  > 2) Patch spamd to exec $perl_from_hashbang_line instead of $EXECUTABLE_NAME
  >    ( = $^X).
  > 3) Patch /etc/rc.d/spamd to avoid using rc.subr with its command_interpreter
  >    checks.
  > 4) Patch /etc/rc.subr to override procname match given pidfile.

 my vote would be (5) fix perl.

 -- 
 David A. Holland
 dholland@netbsd.org

From: Stephen Borrill <netbsd@precedence.co.uk>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: pkg/50772 perl and check_interpreter
Date: Fri, 18 Nov 2016 12:20:49 +0000 (GMT)

 A few notes:

 Problem is not 100% reproducible. I expect this is depend on the order 
 that the link names are returned when looked up. On two different 
 systems:

 $ cat foo24.pl
 #! /usr/pkg/bin/perl5.24.0
 print "$^X\n"; # $EXECUTABLE_NAME in English

 $ cat foo.pl
 #! /usr/pkg/bin/perl
 print "$^X\n"; # $EXECUTABLE_NAME in English

 # ./foo.pl
 /usr/pkg/bin/perl
 # ./foo24.pl
 /usr/pkg/bin/perl5.24.0
 # ls -l /usr/pkg/bin/perl*
 -rwxr-xr-x  2 root  wheel  11103 Aug 11 10:30 /usr/pkg/bin/perl
 -rwxr-xr-x  2 root  wheel  11103 Aug 11 10:30 /usr/pkg/bin/perl5.24.0

 mail# ./foo.pl
 /usr/pkg/bin/perl5.24.0
 mail# ./foo24.pl
 /usr/pkg/bin/perl5.24.0
 mail# ls -l /usr/pkg/bin/perl*
 -rwxr-xr-x  2 root  wheel  11103 Oct 20 16:45 /usr/pkg/bin/perl
 -rwxr-xr-x  2 root  wheel  11103 Oct 20 16:45 /usr/pkg/bin/perl5.24.0

 On the machine exhibiting the problem, I ran through a few steps regarding 
 Patrick's option 3):

 mail# ps axww -p `cat /var/run/spamd.pid`
    PID TTY STAT    TIME COMMAND
 25312 ?   Ss   0:13.71 /usr/pkg/bin/perl5.24.0 -T -w /usr/pkg/bin/spamd -m 15 -x -u spamassassin -d -r /var/run/spamd.pid
 mail# . /etc/rc.subr
 mail# check_pidfile /var/run/spamd.pid /usr/pkg/bin/spamd
 mail# check_pidfile /var/run/spamd.pid /usr/pkg/bin/spamd /usr/pkg/bin/perl
 mail# check_pidfile /var/run/spamd.pid /usr/pkg/bin/spamd /usr/pkg/bin/perl5.24.0
 sh: WARNING: $command_interpreter /usr/pkg/bin/perl5.24.0 != /usr/pkg/bin/perl

 Patrick worked on his step 2) and has submitted a bug report and a 
 patch for spamd to spamassassin:

 https://bz.apache.org/SpamAssassin/show_bug.cgi?id=7295
 https://bz.apache.org/SpamAssassin/attachment.cgi?id=5377&action=view

 I've been using his patch in production for a while without problems

 -- 
 Stephen

From: David Holland <dholland-pbugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: pkg/50772 perl and check_interpreter
Date: Sat, 19 Nov 2016 17:32:54 +0000

 On Fri, Nov 18, 2016 at 12:25:01PM +0000, Stephen Borrill wrote:
  >  A few notes:
  >  
  >  Problem is not 100% reproducible. I expect this is depend on the order 
  >  that the link names are returned when looked up. On two different 
  >  systems:

 I was about to say I can't reproduce it at all, except after trying
 all my machines I found one that does... which isn't any different
 from the others.

 Using ktrace shows that it's is getting it by calling readlink on
 /proc/curproc/exe. It is a namecache issue (but not a readily fixable
 one) that /proc/curproc/exe returns an arbitrary name for the file and
 not the one used to open it.

 It's a bug in perl (or maybe an error in handling linux-specific
 logic) that it is using this information.

 One can reproduce the behavior fairly easily without perl:

    --- x.c ---
 #include <stdio.h>
 #include <unistd.h>
 #include <limits.h>
 #include <assert.h>
 #include <err.h>

 int
 main(void)
 {
         char buf[PATH_MAX+1];
         ssize_t len;

         len = readlink("/proc/curproc/exe", buf, sizeof(buf) - 1);
         if (len == -1) {
                 err(1, "readlink: /proc/curproc/exe");
         }
         assert(len < sizeof(buf));
         buf[len] = 0;
         printf("%s\n", buf);
         return 0;
 }
    ------

 % gcc -Wall x.c -o x
 % ./x
 /tmp/foo/x
 % ln x y
 % ./x
 /tmp/foo/x
 % ./y
 /tmp/foo/y
 % ./x
 /tmp/foo/y
 % 

 although the exact behavior will depend on how the namecache hashes
 the names you use.

 -- 
 David A. Holland
 dholland@netbsd.org

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.