Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Perl: porters

[perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value

 

 

Perl porters RSS feed   Index | Next | Previous | View Threaded


perlbug-followup at perl

Jul 4, 2012, 5:56 AM

Post #1 of 10 (115 views)
Permalink
[perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value

# New Ticket Created by Oleg Nesterov
# Please include the string: [perl #113980]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=113980 >


Hello,

I noticed today that syscall(9, ...) (mmap) doesn't work for me.

The problem is obvious, pp_syscall() uses I32 for retval and the
"long" address doesn't fit into "int".

The one-liner below should fix the problem. I am not sure where
should I send this patch, how should I write the changelog, etc.
IOW, sorry if my email doesn't conform the rules.

And btw, thanks to all perl developers for perl ;)

Oleg.

--- a/pp_sys.c
+++ b/pp_sys.c
@@ -5456,7 +5456,7 @@ PP(pp_syscall)
register I32 items = SP - MARK;
unsigned long a[20];
register I32 i = 0;
- I32 retval = -1;
+ IV retval = -1;

if (PL_tainting) {
while (++MARK <= SP) {


perlbug-followup at perl

Jul 4, 2012, 9:08 AM

Post #2 of 10 (105 views)
Permalink
[perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

On Wed Jul 04 05:56:04 2012, oleg [at] redhat wrote:
> Hello,
>
> I noticed today that syscall(9, ...) (mmap) doesn't work for me.
>
> The problem is obvious, pp_syscall() uses I32 for retval and the
> "long" address doesn't fit into "int".
>
> The one-liner below should fix the problem. I am not sure where
> should I send this patch, how should I write the changelog, etc.
> IOW, sorry if my email doesn't conform the rules.
>
> And btw, thanks to all perl developers for perl ;)
>
> Oleg.
>
> --- a/pp_sys.c
> +++ b/pp_sys.c
> @@ -5456,7 +5456,7 @@ PP(pp_syscall)
> register I32 items = SP - MARK;
> unsigned long a[20];
> register I32 i = 0;
> - I32 retval = -1;
> + IV retval = -1;
>
> if (PL_tainting) {
> while (++MARK <= SP) {
>

Thank you. Applied as f9344c91a4. I don’t supposed it’s possible to
write an automated test for this, is it?

--

Father Chrysostomos


---
via perlbug: queue: perl5 status: new
https://rt.perl.org:443/rt3/Ticket/Display.html?id=113980


oleg at redhat

Jul 4, 2012, 10:25 AM

Post #3 of 10 (104 views)
Permalink
Re: [perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

Father,

I do not know if it is OK to reply to perlbug-followup [at] perl,
so I CC'ed you explicitly.

On 07/04, Father Chrysostomos via RT wrote:
>
> I don’t supposed it’s possible to
> write an automated test for this, is it?

Well, please see below. Not sure it is the best...

So. The test-case assumes 64-bit linux, otherwise it won't work.

It exploits the fact that vdso is mmapped at "high" address which
can't fit in I32.

It does mremap(vdso_addr, 1, 1, 0) which is "nop" but should return
the original address.

Btw, "-w" complains:

Hexadecimal number > 0xffffffff non-portable at ...

a bit annoying on 64-bit systems... Not sure why Perl_grok_hex()
thinks this is not portable.

Oleg.

-------------------------------------------------------------------
#!/usr/bin/perl -w
use strict;

sub find_vdso()
{
open my $maps, '<', '/proc/self/maps' or die;
/^(.*?)-.*\[vdso\]$/ and return hex $1 for <$maps>;
}

my $vdso_addr = find_vdso || die 'not 64-bit linux?';

my $ret = syscall 25, # __NR_mremap
$vdso_addr, # old_addr
1, # old_len
1, # new_len
0, # flags
0; # new_addr (unused)

$ret == $vdso_addr or die "FAILED\n";


blgl at stacken

Jul 4, 2012, 7:05 PM

Post #4 of 10 (103 views)
Permalink
Re: [perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

Quoth Oleg Nesterov:
> --- a/pp_sys.c
> +++ b/pp_sys.c
> @@ -5456,7 +5456,7 @@ PP(pp_syscall)
> register I32 items = SP - MARK;
> unsigned long a[20];
> register I32 i = 0;
> - I32 retval = -1;
> + IV retval = -1;
>
> if (PL_tainting) {
> while (++MARK <= SP) {

Note that this doesn't help if the syscall function itself is declared as

int syscall(int, ...);

which is not unheard of.


/Bo Lindbergh


oleg at redhat

Jul 5, 2012, 8:50 AM

Post #5 of 10 (104 views)
Permalink
Re: [perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

On 07/04, Bo Lindbergh via RT wrote:
>
> Quoth Oleg Nesterov:
> > --- a/pp_sys.c
> > +++ b/pp_sys.c
> > @@ -5456,7 +5456,7 @@ PP(pp_syscall)
> > register I32 items = SP - MARK;
> > unsigned long a[20];
> > register I32 i = 0;
> > - I32 retval = -1;
> > + IV retval = -1;
> >
> > if (PL_tainting) {
> > while (++MARK <= SP) {
>
> Note that this doesn't help if the syscall function itself is declared as
>
> int syscall(int, ...);
>
> which is not unheard of.

Sure, this change is not needed in this case, but it doesn't hurt?
I am not familiar with perl's implementation but PUSHi(retval) and
Perl_sv_setiv() uses (IV)retval anyway, so I don't think this change
can make any difference.

If you meant that libc itself can be buggy (so that the library
function truncates the result of syscall), then perl can do nothing.

Or I misunderstood your point?

Oleg.


perlbug-followup at perl

Jul 8, 2012, 10:53 PM

Post #6 of 10 (97 views)
Permalink
[perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

On Thu Jul 05 02:15:16 2012, oleg [at] redhat wrote:
> Father,
>
> I do not know if it is OK to reply to perlbug-followup [at] perl,
> so I CC'ed you explicitly.
>
> On 07/04, Father Chrysostomos via RT wrote:
> >
> > I don’t supposed it’s possible to
> > write an automated test for this, is it?
>
> Well, please see below. Not sure it is the best...
>
> So. The test-case assumes 64-bit linux, otherwise it won't work.
>
> It exploits the fact that vdso is mmapped at "high" address which
> can't fit in I32.
>
> It does mremap(vdso_addr, 1, 1, 0) which is "nop" but should return
> the original address.
>
> Btw, "-w" complains:
>
> Hexadecimal number > 0xffffffff non-portable at ...
>
> a bit annoying on 64-bit systems... Not sure why Perl_grok_hex()
> thinks this is not portable.
>
> Oleg.
>
> -------------------------------------------------------------------
> #!/usr/bin/perl -w
> use strict;
>
> sub find_vdso()
> {
> open my $maps, '<', '/proc/self/maps' or die;
> /^(.*?)-.*\[vdso\]$/ and return hex $1 for <$maps>;
> }
>
> my $vdso_addr = find_vdso || die 'not 64-bit linux?';
>
> my $ret = syscall 25, # __NR_mremap
> $vdso_addr, # old_addr
> 1, # old_len
> 1, # new_len
> 0, # flags
> 0; # new_addr (unused)
>
> $ret == $vdso_addr or die "FAILED\n";
>

Thank you. I’ll have to adjust this a bit to turn it into a test. Does
$^O give you ‘linux’?

There is a possibility that another OS might have a plain file called
/proc/self/maps whose contents just happen to match the regular
expression, resulting in an invalid syscall, and perhaps a crash.

So we should skip early if $^O is not appropriate.

--

Father Chrysostomos


---
via perlbug: queue: perl5 status: resolved
https://rt.perl.org:443/rt3/Ticket/Display.html?id=113980


oleg at redhat

Jul 9, 2012, 5:53 AM

Post #7 of 10 (94 views)
Permalink
Re: [perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

On 07/08, Father Chrysostomos via RT wrote:
>
> On Thu Jul 05 02:15:16 2012, oleg [at] redhat wrote:
> > -------------------------------------------------------------------
> > #!/usr/bin/perl -w
> > use strict;
> >
> > sub find_vdso()
> > {
> > open my $maps, '<', '/proc/self/maps' or die;
> > /^(.*?)-.*\[vdso\]$/ and return hex $1 for <$maps>;
> > }
> >
> > my $vdso_addr = find_vdso || die 'not 64-bit linux?';
> >
> > my $ret = syscall 25, # __NR_mremap
> > $vdso_addr, # old_addr
> > 1, # old_len
> > 1, # new_len
> > 0, # flags
> > 0; # new_addr (unused)
> >
> > $ret == $vdso_addr or die "FAILED\n";
> >
>
> Thank you. I’ll have to adjust this a bit to turn it into a test. Does
> $^O give you ‘linux’?

Yes,

> There is a possibility that another OS might have a plain file called
> /proc/self/maps whose contents just happen to match the regular
> expression, resulting in an invalid syscall, and perhaps a crash.
>
> So we should skip early if $^O is not appropriate.

Yes, yes, sure.

Bu just in case, please note $^O eq 'linux' is not enough.

The test-case assumes 64-bit linux and perl should be compiled
as 64-bit application too. Otherwise syscall(25) means stime()
and should be skipped.

Oleg.


nick at ccl4

Jul 26, 2012, 9:18 AM

Post #8 of 10 (77 views)
Permalink
Re: [perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

On Wed, Jul 25, 2012 at 11:15:01PM -0700, Father Chrysostomos via RT wrote:
> On Wed Jul 11 03:57:53 2012, oleg [at] redhat wrote:

> > The test-case assumes 64-bit linux and perl should be compiled
> > as 64-bit application too. Otherwise syscall(25) means stime()
> > and should be skipped.
>
> This line accounts for that, does it not?
>
> my $vdso_addr = find_vdso || die 'not 64-bit linux?';
>
> Please try out the attached patch, based on your script. If it works
> for you, I'll apply it.
>
> I don't have access to a 32-bit linux system, so I am unable to test the
> skip. Are you?

I get this failure on an x86 system:

$ ./perl -I../lib op/syscall-113980.t
1..1
not ok 1 - syscall retval is not truncated
# Failed test 1 - syscall retval is not truncated at op/syscall-113980.t line 26
# got "-1"
# expected "3077869568"

for information:

$ cat /proc/self/maps
08048000-08052000 r-xp 00000000 ca:01 131074 /bin/cat
08052000-08053000 rw-p 0000a000 ca:01 131074 /bin/cat
08de5000-08e06000 rw-p 00000000 00:00 0 [heap]
b75c4000-b75c5000 rw-p 00000000 00:00 0
b75c5000-b7705000 r-xp 00000000 ca:01 1647095 /lib/i686/cmov/libc-2.11.3.so
b7705000-b7706000 ---p 00140000 ca:01 1647095 /lib/i686/cmov/libc-2.11.3.so
b7706000-b7708000 r--p 00140000 ca:01 1647095 /lib/i686/cmov/libc-2.11.3.so
b7708000-b7709000 rw-p 00142000 ca:01 1647095 /lib/i686/cmov/libc-2.11.3.so
b7709000-b770c000 rw-p 00000000 00:00 0
b7718000-b771c000 rw-p 00000000 00:00 0
b771c000-b771d000 r-xp 00000000 00:00 0 [vdso]
b771d000-b7738000 r-xp 00000000 ca:01 1630731 /lib/ld-2.11.3.so
b7738000-b7739000 r--p 0001b000 ca:01 1630731 /lib/ld-2.11.3.so
b7739000-b773a000 rw-p 0001c000 ca:01 1630731 /lib/ld-2.11.3.so
bfbda000-bfbef000 rw-p 00000000 00:00 0 [stack]

The sparc linux build is still ongoing...
(I think this is a 32 build on a sparc64 system. The machine is slow, and I'm
not going to interrupt it to find out out for sure)

I've not yet tried coaxing a build with -m32 on x86_64

Nicholas Clark


nick at ccl4

Jul 26, 2012, 12:02 PM

Post #9 of 10 (76 views)
Permalink
Re: [perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

On Thu, Jul 26, 2012 at 09:59:49AM -0700, Father Chrysostomos via RT wrote:
> On Thu Jul 26 09:19:42 2012, nicholas wrote:

> > The sparc linux build is still ongoing...
> > (I think this is a 32 build on a sparc64 system. The machine is slow,
> > and I'm
> > not going to interrupt it to find out out for sure)

However, the 4 core MIPs box is faster. And on it,

$ ./perl -I../lib op/syscall-113980.t
1..1
not ok 1 - syscall retval is not truncated
# Failed test 1 - syscall retval is not truncated at op/syscall-113980.t line 26
# got "-1"
# expected "2147434496"

> > I've not yet tried coaxing a build with -m32 on x86_64

... -Accflags=-m32 -Aldflags=-m32 -Alddlflags=-m32\ -shared

[.and I don't know why I need to add -shared - is the hints file buggy?]

$ ./perl -I../lib op/syscall-113980.t
1..1
not ok 1 - syscall retval is not truncated
# Failed test 1 - syscall retval is not truncated at op/syscall-113980.t line 26
# got "-1"
# expected "4160614400"

(output of ./perl -pe0 /proc/self/maps >maps attached)

> Thank you. That means the skip is not being triggered. Do you know how
> to test that this is a 64-bit linux system? Or is this bug something we
> just can't reliably test?

No, I don't for sure. I think if one is sure it's Linux, run uname -m

eg

$ uname -m
x86_64
$ uname -m
mips64
$ uname -m
sparc64

vs

$ uname -m
i686
$ uname -m
armv6l

I think all the 64 bit architectures happen to match /64$/
However, I suspect that syscall numbers vary with architecture, and arguments
might too, so it's not going to be safe to use a hardcoded magic number
even on systems which seem to be 64 bits - really, check if it's exactly
x86_64. This also assumes that syscall numbers do not change on Linux.
I guess that they can't now, given that 3.x.y is really just 2.6.z, but I
presume that they can be deprecated and eventually dropped.

But as the above demonstrates, it would need to be a 64 bit process on a 64
bit OS. I think the latter is fairly easy - $Config{ptrsize}.

> Obviously calling stime is no good, even if it only works under root.
> Running tests under root should not set the system time. :-)

For starters, I think skip it if running as root.
But yes, also skip unless it's linux, skip unless it's x86_64, and skip
unless it's a 64 bit build.

But I'm not confident how safe or reliable this sort of thing is ever going
to be.

Nicholas Clark


nick at ccl4

Jul 30, 2012, 6:31 AM

Post #10 of 10 (73 views)
Permalink
Re: [perl #113980] [PATCH] pp_syscall: "I32 retval" truncates the returned value [In reply to]

On Thu, Jul 26, 2012 at 12:18:01PM -0700, Father Chrysostomos via RT wrote:
> On Thu Jul 26 12:03:15 2012, nicholas wrote:
> > For starters, I think skip it if running as root.
> > But yes, also skip unless it's linux, skip unless it's x86_64, and
> > skip
> > unless it's a 64 bit build.
> >
> > But I'm not confident how safe or reliable this sort of thing is ever
> > going
> > to be.
>
> I think we just have to leave this untested.

Yes, I suspect so too.

Nicholas Clark

Perl porters RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.