2015-10-21 5 views
5

Wie kann der Systemaufruf mount von Perl erfolgen? Folgende:Ausführen von Mount-System-Aufruf von Perl

$ret = syscall(&SYS_mount, "/proc", "/path/to/my/mount/point", 0, 0, 0); 

Ergebnisse in:

Modification of a read-only value attempted at ... 

kann ich nicht nennen das mount Programm system, weil ich ein mount() Systemaufruf machen müssen, dass das mount Programm nicht in der Lage zu sein scheint. Genauer gesagt, muss ich nennen:

mount("/proc", "/path/to/my/mpoint/point", NULL, MS_REC|MS_PRIVATE|MS_BIND, NULL); 

Aber wenn ich versuche, die folgenden mit einem unprivilegierten unshared Mount-Linux-Namensraum zu laufen:

mount --make-rprivate --bind /proc /path/to/my/mountpoint 

Dann habe ich die folgende Fehlermeldung erhalten:

mount: wrong fs type, bad option, bad superblock on /proc, 
     missing codepage or helper program, or other error 

     In some cases useful info is found in syslog - try 
     dmesg | tail or so. 

strace zeigt, dass das, was das mount Programm tatsächlich tut, ist:

mount("/proc", "/path/to/my/mountpoint", ..., MS_MGC_VAL|MS_BIND, NULL); 
mount("none", "/path/to/my/mointpoint", NULL, MS_REC|MS_PRIVATE, NULL); 

Aber diese Aufteilung der Optionen funktioniert nicht. Ich brauche MS_BIND und MS_REC|MS_PRIVATE in einem einzigen Aufruf an den Systemaufruf mount, damit es in einem nicht privilegierten Mount-Namespace funktioniert.

Also wie kann ich meinen ersten Systemaufruf in Perl ohne die Fehlermeldung über einen Versuch einer Änderung eines schreibgeschützten Werts tun?

bearbeiten:

Zum Glück ikegami war schnell darauf hin, was ich falsch gemacht haben, wenn syscall Funktion Perl zu verwenden versuchen, aber falls dies jemand findet, wenn für die Suche, wie ein Verzeichnis zu binden Halterung innerhalb einer unprivilegierten Halterung Namensraum nur mit dem mount Zeilen-Utility-Befehl, hier ist, wie:

mount --rbind /proc /path/to/my/mountpoint 

Dies wiederum intern die folgende syscall rufen:

mount("proc", "/path/to/my/mountpoint", ..., MS_MGC_VAL|MS_BIND|MS_REC, 0); 

Die MS_MGC_VAL Flag scheint nur für die Abwärtskompatibilität mit Kernel-Versionen vor 2.4 zu sein. Die wichtigen Bits sind MS_BIND (für das Bind-Mounting selbst) und MS_REC (um es rekursiv zu tun, so dass Verzeichnisse, deren Inhalt durch andere Mounts verdeckt ist, nicht in den Mount-Namespace geladen werden).

So, jetzt muss ich entscheiden, ob ich mit einem Perl system Funktionsaufruf gehen oder einfach nur tun, um die mount Systemcall, weil beide arbeiten genauso gut :)

Antwort

8

syscall weigert sich, einen Zeiger auf den String-Puffer einer konstanten passieren da es keine Ahnung hat, ob das Argument char * oder const char * ist.

You can't use a string literal (or other read-only string) as an argument to syscall because Perl has to assume that any string pointer might be written through

Die Lösung ist einfach. Kopieren Sie die Konstante zuerst in eine Variable.

my $ret = syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0); 

Test:

$ perl -E' 
    require "syscall.ph"; 
    my $ret = syscall(&SYS_mount, "/proc", "/path/to/my/mount/point", 0, 0, 0); 
    say $ret; 
' 
Modification of a read-only value attempted at -e line 3. 

$ perl -E' 
    require "syscall.ph"; 
    my $ret = syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0); 
    say $ret; 
' 
-1 

$ strace perl -e' 
    require "syscall.ph"; 
    syscall(&SYS_mount, my $s="/proc", my $t="/path/to/my/mount/point", 0, 0, 0); 
' 2>&1 | grep mount 
mount("/proc", "/path/to/my/mount/point", NULL, 0, NULL) = -1 ENOENT (No such file or directory) 
+0

Sie Herr/Frau habe gerade meinen Tag! Ich sehe jetzt, dass die Dokumentation von 'syscall' sagt:" Sie können ein Zeichenfolgenliteral (oder eine andere schreibgeschützte Zeichenfolge) nicht als Argument verwenden "... albern, ich hätte RTFM ... Trotzdem, seit Ihnen habe mir gerade viele Kopfschmerzen erspart Ich wünsche dir viele Upvotes :) – josch

+0

Doh! Hatte das auch nicht gelesen! Verbesserte meine Antwort ein wenig. – ikegami