Bug 171111 - (libperl) could not run system-config-printer
Summary: (libperl) could not run system-config-printer
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: perl
Version: 4.0
Hardware: athlon
OS: Linux
medium
medium
Target Milestone: ---
: ---
Assignee: Jason Vas Dias
QA Contact: David Lawrence
URL:
Whiteboard:
Depends On: 144536
Blocks: 172317
TreeView+ depends on / blocked
 
Reported: 2005-10-18 11:50 UTC by Jindrich Novy
Modified: 2013-07-02 23:10 UTC (History)
12 users (show)

Fixed In Version: RHSA-2005-880
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2006-03-12 18:18:59 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
test case from https://rt.perl.org/rt3/Ticket/Display.html?id=38223 (429 bytes, application/x-perl)
2006-03-13 12:54 UTC, Jan Lieskovsky
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2005:880 0 normal SHIPPED_LIVE Moderate: perl security update 2005-12-20 05:00:00 UTC

Comment 3 Jason Vas Dias 2005-10-24 20:49:59 UTC
OK, it appears this command has caused a SIGSEGV when run with STDIN 
directed a USB printer device:

# perl -e 'ioctl(STDIN,0x84005001,$result); print $result' </dev/usb/lp0

from:
/usr/share/printconf/util/printconf_conf.py, @ line 1460:
	magic_perl = "perl -e 'ioctl(STDIN,0x84005001,$result);"
	magic_perl += "print $result' 2>/dev/null <"
	foo = os.popen (magic_perl + dev)
	rawid = foo.readlines ()

Why not use the Python fcntl.ioctl() call here ?

It would be interesting to see if python also has a problem with this ioctl:

# python
>>> import os, fcntl, array;
>>> result=array.array(1024) 
>>> fcntl.ioctl( os.open("/dev/usb/lp0","r"), -2080354303, result, 1 )
  
I've just now tried running the perl command above with STDIN directed to an
RS-232 serial port, (the only serial device I have here at work) on up-to-date
Rawhide, FC-4, RHEL-4 and FC-3 systems, and have not been able to reproduce
the problem. 

I do have a USB printer at home, and I try to reproduce this problem there.

But googling for 0x84005001 turned up 

http://home.techwiz.ca/ftp/Linux/dist/MandrakeLinux/official/9.2/i586/Mandrake/mdkinst/usr/bin/perl-install/printer/detect.pm.gz
:
	    # Calculation of IOCTL function 0x84005001 (to get device ID
	    # string):
	    # len = 1024
	    # IOCNR_GET_DEVICE_ID = 1
	    # LPIOC_GET_DEVICE_ID(len) =
	    #     _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
	    # _IOC(), _IOC_READ as defined in /usr/include/asm/ioctl.h
	    # Use "eval" so that program does not stop when IOCTL fails
	    eval { 
		my $output = "\0" x 1024; 
		ioctl($PORT, 0x84005001, $output);
		$idstr = $output;
	    } or do {
		close $PORT;
		next;
	    };

Note how the programmer is careful to allocate a 1024 buffer for the RW
ioctl $output parameter, since the 0x84005001 says "I am passing in 
an 1024 byte RW buffer" .

Perhaps the SEGV occurs only when a USB printer is on STDIN, because 
only a USB printer actually returns an ID string, which writes into the 
(empty) $result buffer ?

Does the problem still occur if the command is ammended :

perl -e '$result="\0" x 1024; ioctl(STDIN,0x84005001,$result);print
$result,"\n";' </dev/usb/lp0

If not, I don't think it this a PERL bug , but a programming error - any 
use of ioctl(x,0x84005001,buf), invoked from a C program, will cause a 
SIGSEGV if the ioctl returns data in buf and buf does not point to a 1024 byte
buffer .

Can anyone reading this with access to a USB printer please verify, with 
latest versions that this is still a bug:

1. Does this command produces a SIGSEGV:
# perl -e 'ioctl(STDIN,0x84005001,$result); print $result' </dev/usb/lp0

2. Does this command produce a SIGSEGV :
# perl -e '$result="\0" x 1024; ioctl(STDIN,0x84005001,$result); print $result'
</dev/usb/lp0

If the answer to (2) is NO, then this is not a PERL bug.


Comment 4 Jason Vas Dias 2005-10-25 22:20:07 UTC
OK, I've finally found and fixed the problem here, now that I've brought my
USB printer in to work from home (unecessarily! :-)

perl was looking for an IOCPARM_LEN(ioctl_number) macro to return the 
length bits from the ioctl function number. This works OK on BSD systems.
But if IOCPARM_LEN was not defined, perl.h "guessed" and defined 
IOCPARM_LEN(ioctl_number) to be 256 . Linux has no IOCPARM_LEN(x) macro.

So any printer that returned an ID string > 256 bytes would cause a SIGSEGV .

Linux has the _IOC_SIZE(x) macro, so I changed perl.h to use _IOC_SIZE(x) if
IOCPARM_LEN is not defined instead of constant 256.

I have submitted this bug upstream with perlbug - waiting for a RT #.

So this bug is now fixed in Rawhide (FC-5) with perl-5.8.7-0.6.fc5 . 
It will now have to be fixed in RHEL-3, RHEL-4, FC-4, FC-3 .


Comment 7 Fedora Update System 2005-12-01 23:56:41 UTC
From User-Agent: XML-RPC

perl-5.8.5-18.FC3 has been pushed for FC3, which should resolve this issue.  If these problems are still present in this version, then please make note of it in this bug report.

Comment 10 Red Hat Bugzilla 2005-12-20 14:30:44 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHSA-2005-880.html


Comment 11 Rafael Garcia-Suarez 2006-01-13 12:25:28 UTC
This patch needed another core patch to work properly, I'm not sure why.
See : https://rt.perl.org/rt3/Ticket/Display.html?id=38223

Comment 13 Jason Vas Dias 2006-03-12 18:18:59 UTC
This bug is fixed: perl programs passing in the length bitfield parameter to 
ioctl will now get the correct length, instead of the default 256; as a result,
system-config-printer works fine. 
The upstream refinement to this patch was to retain the previous 256 default
as a minimum length; ie., if the ioctl did not pass in the length, and the
argument is less than 256 bytes in length, then it is made to be 256 bytes.
This does not affect system-config-printer, and is a new bug - I'm closing
this bug and raising another to document it.



Comment 14 Jan Lieskovsky 2006-03-13 12:48:47 UTC
Have run the test script from
https://rt.perl.org/rt3/Ticket/Display.html?id=38223 (will attach this file)
on 3 systems with 3 format of the "perl.h" file:

1, perl 5.8.8

./test.perl
(row,col) = (54,155)     => PASS

Form of the patch: 

#ifndef IOCPARM_LEN
#   ifdef IOCPARM_MASK
        /* on BSDish systems we're safe */
#       define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
#   else
#       if defined(_IOC_SIZE) && defined(__GLIBC__)
        /* on Linux systems we're safe; except when we're not [perl #38223] */
#           define IOCPARM_LEN(x) (_IOC_SIZE(x) < 256 ? 256 : _IOC_SIZE(x))
#       else
        /* otherwise guess at what's safe */
#           define IOCPARM_LEN(x)       256
#       endif
#   endif
#endif

2, perl 5.8.6

./test.perl
(row,col) = (54,155)  => PASS

Form of the patch: 

#ifndef IOCPARM_LEN
#   ifdef IOCPARM_MASK
        /* on BSDish systes we're safe */
#       define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
#   else
        /* otherwise guess at what's safe */
#       define IOCPARM_LEN(x)   256
#   endif
#endif

=> seems it's enough to hardly set the value of IOCPARM_LEN(x) to 256
and don't take into account the Linux system's branch, because:

3, perl 5.8.6

./test.perl
Possible memory corruption: ioctl overflowed 3rd argument at ./test.perl line 5.

=> FAIL 

Form of the patch: 

#ifndef IOCPARM_LEN
#   ifdef IOCPARM_MASK
        /* on BSDish systems we're safe */
#       define IOCPARM_LEN(x)  (((x) >> 16) & IOCPARM_MASK)
#   else
#       ifdef _IOC_SIZE
                /* on Linux systems we're safe */
#               define IOCPARM_LEN(x) _IOC_SIZE(x)
#       else
                /* otherwise guess at what's safe (we're UNSAFE!) */
#               warning "unsafe assumption of IOCPARM_LEN=256"
#               define IOCPARM_LEN(x)   256
#       endif
#   endif
#endif

This patch doesn't work. 

So the solution is either to use patch without the linux branch, and hardly
set value of IOCPARM_LEN(x) to 256 (patch 2,), or take into account  
_IOC_SIZE and use the newest patch ( patch 1,).

Comment 15 Jan Lieskovsky 2006-03-13 12:54:12 UTC
Created attachment 126033 [details]
test case from https://rt.perl.org/rt3/Ticket/Display.html?id=38223

Comment 16 Jason Vas Dias 2006-03-13 16:45:02 UTC
I have raised bug 185240 to cover the issues raised in 
Comment #11, Comment #12, Comment #14, Comment #15 -
(perlbug RT #38223) - it will be fixed in perl-5.8.5-24.RHEL4+.
The specific problem with system-config-printer reported in this 
bug has definitely been fixed with the current perl-5.8.5-22.RHEL-4 
release in RHEL-4-U3 .






Note You need to log in before you can comment on or make changes to this bug.