so, das Problem ist gelöst! Vielen vielen Dank.
Lösung:
String[] envp = {"DISPLAY=:0", "XAUTHORITY=/home/marcel/.Xauthority"}; Runtime.getRuntime().exec("audacious -p", envp);
(Themenstarter)
Anmeldungsdatum: Beiträge: 30 |
so, das Problem ist gelöst! Vielen vielen Dank. Lösung: String[] envp = {"DISPLAY=:0", "XAUTHORITY=/home/marcel/.Xauthority"}; Runtime.getRuntime().exec("audacious -p", envp); |
Anmeldungsdatum: Beiträge: 2159 |
user unknown hat geschrieben:
Häh? #!/usr/bin/perl use warnings; use strict; # Aktuelle pid und ppid printf "PID: %s PPID: %s\n", $$, getppid(); # PATH Variable Ausgeben print "PATH: $ENV{PATH}\n"; # PATH Variable neu setzen. $ENV{PATH} = '/bin'; # PATH wieder ausgeben print "PATH: $ENV{PATH}\n\n"; # Forken my $pid = fork; die "Fehler bei fork: $!\n" if not defined $pid; if ($pid) { #Parent printf "Parent: PID: %s PPID %s\n", $$, getppid(); print "Parent: PATH: $ENV{PATH}\n"; } else { #Child printf "Child: PID: %s PPID %s\n", $$, getppid(); print "Child: PATH: $ENV{PATH}\n"; } Das Programm gibt bei mir folgendes aus: PID: 6768 PPID: 5395 PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games PATH: /bin Child: PID: 6769 PPID 6768 Child: PATH: /bin Parent: PID: 6768 PPID 5395 Parent: PATH: /bin |
![]() Anmeldungsdatum: Beiträge: 17622 Wohnort: Berlin |
Sid Burn hat geschrieben:
Das sagst Du so. Wenn ich das richtig sehe, dann bleibt bei Deinem Perlprogramm das Programm im Perlkontext, und ruft nie ein Systemprogramm auf - daher wundert es nicht, daß Änderungen an der Umgebung im Kontext auch bekannt sind. import java.util.*; import java.io.*; public class SysVar { public SysVar () { sysProps (); System.setProperty ("FOO", "42"); System.setProperty ("LANG", "en_US.UTF-8"); String [] command = {"/bin/bash", "-c", "export PATH=$PATH:/no/such/PFAT; echo $PATH; echo $LANG; echo $FOO"}; try { Runtime runtime = Runtime.getRuntime (); Process proc = runtime.exec (command); BufferedReader br = new BufferedReader (new InputStreamReader (proc.getInputStream ())); String line = null; System.out.println ("==========================="); do { line = br.readLine (); if (line != null) System.out.println (line); }while (line != null); } catch (IOException ex) { ex.printStackTrace (); } sysProps (); } public void sysProps () { System.out.println ("---------------------------"); Map <String, String> m = System.getenv (); System.out.println (m.get ("PATH")); System.out.println (m.get ("LANG")); System.out.println (m.get ("FOO")); } public static void main (String args[]) { new SysVar (); } } Die Ausgabe hier ist:
Interessanterweise ändert selbst der Aufruf von System.setProperty (key, value) offenbar nichts - das verwundert auch mich. Die einzige Änderung ist der PATH in dem exec () - Aufruf, wo wie gewollt '/no/such/PFAT' auftaucht. |
Anmeldungsdatum: Beiträge: 5792 |
radoe2 hat geschrieben:
Wieso? Das ist unter Linux ziemlich üblich... Das berühmte system() aus C macht auch nichts anderes als eine Shell zu starten. Unter anderem deswegen ist es unter Linux ja so wichtig, dass unter /bin/sh eine POSIX kompatible Shell liegt. radoe2 hat geschrieben:
Wie gesagt, dass Starten von Programmen wird unter Linux meistens über eine Shell durchgeführt. Andernfalls ist dass nämlich nur mittels einer Kombination aus fork() und exec*() zu erreichen, was den Code zum Starten eines einfachen Programms schnell in den zweistelligen Zeilenbereich bringt. Dieser sichere Weg hat viel eher mit Kanonen und Spatzen zu tun 😉 user unknown hat geschrieben:
Was soll den der "Perlkontext" sein? Durch das Forking wird ein neuer Prozess gestartet. Um es deutlich zu machen: Nach dem Fork existieren auf Sids System zwei Perl-Prozesse, von denen der eine den if und der andere den else Zweig abhandelt. Da gibt es keinen gemeinsamen "Perlkontext" mehr. Das funktioniert so in jeder Sprache: Man kann Sids Beispiel auch in Python oder C implementieren. Man kann die Sprachen sogar mischen: Statt die PID und den PATH im Else Zweig mit Perl auszugeben, hätte Sid auch ein kleines C Programm dazu schreiben können, welches er mittels execvp aufruft. Das Ergebnis wäre exakt das gleiche gewesen. Das beobachtete Verhalten hat nichts mit Perl zu tun, sondern ist das normale Verhalten des Systemaufrufs fork unter Linux. |
Anmeldungsdatum: Beiträge: 2159 |
@user unknown
In meinen Beispiel hat kein Child irgendwas am Parent verändert. Das ist ja nicht Möglich. Es ist so wie Luna sagte. Nach einem fork() hat man zwei voneinander getrennte Prozesse die sozusagen an der selben Codezeile weiter arbeiten. Der Parent Prozess erfüllt die Bediengung für das if (dieser enthält nämlich die PID des Child Prozesses, und beim Child Prozess selber enthält $pid eine 0). Erfüllt also nicht die if Bediengung und springt im else Zweig. Ansonsten gibt es keinen gemeinsamen "Kontext". Ich kann auch beliebig mit system() irgendetwas aufrufen oder mit fork() und exec() arbeiten. env.pl #!/usr/bin/perl use warnings; use strict; print "$ENV{PATH}\n"; $ENV{PATH} = '/bin'; system('echo $PATH'); system('./path.pl'); my $pid = fork; die "Cannot fork: $!\n" if not defined $pid; if ($pid) { # Parent exit 0; } else { exec './path.pl'; } path.pl #!/usr/bin/perl use warnings; use strict; print "$0: $ENV{PATH}\n"; Einmal rufe ich dann path.pl über system() und einmal über fork() und exec() auf. Wenn ich die Umgebungsvariablen ändere und dann forke dann werden diese änderungen wie bereits gesagt auf alle Childs übertragen. Den das Perl Programm ist der Parent und gibt die Systemvariablen vor, und es wird nicht irgendwie eine komplett unabhängige Shell gestartet die dann erst mein Programm aufruft. Wenn ich env.pl starte kommt dann letztendlich folgendes heraus: sidburn@sid ~/perl/env $ ./env.pl /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games /bin ./path.pl: /bin ./path.pl: /bin Wenn ich nur path.pl starte logischerweise das hier. sidburn@sid ~/perl/env $ ./path.pl ./path.pl: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/usr/games Wenn sich das ändern der Umgebungsvariable nicht auf den aktuellen Prozess auswirkt, und auch nicht auf alle Child prozesse, welchen Sinn würde es denn dann überhaupt geben Funktionen anzubieten die Umgebungsvariablen verändern können, letztendlich aber doch keine Auswirkung haben? Ansonsten glaube ich das wir uns beide entweder nicht verstehen, etwas anderes meinen, oder aneinander vorbeireden. oO |
Anmeldungsdatum: Beiträge: 243 |
Lunar hat geschrieben:
Die Shell ist unnötig in diesem Fall und bringt erstens Overhead und hat zweitens in den meisten Fällen Sicherheitsimplikationen, die es zu bedenken gilt. Als jemand, der Perl und system() als Beispiele anführt, solltest du das wissen. Ausserdem ging es hier weder im Linux im allgemeinen und fork()/exec() im besonderen, sondern um Java und System.exec() (und später dann um den eleganteren Weg mit dem ProzessBuilder). Diese nehmen dir den ganzen Aufwand (ja, ich habe sehr häufig das Vergnügen, Nebenläufigkeit in C,Perl und Python gemischt realisieren zu dürfen) der fork()/dup()/close()/exec()/wait() Kaskaden ab. Aber darum ging es hier doch gar nicht. |
![]() Anmeldungsdatum: Beiträge: 17622 Wohnort: Berlin |
@radeo: Eben. Genau. Der Java-exec-Aufruf startet einen neuen Prozeß mit dem alten Environment, und ändert dies, und das das aufrufende Javaprogramm diese Änderung nicht von seinem Child erbt - das überrascht Dich doch auch nicht? Das Javaprogramm, um diese Behauptung zu bewisen habe ich ja nun gepostet. @Lunar: Dito. Was hat es übrigens mit den Sicherheitsbedenken auf sich, die ihr äußert? |
Anmeldungsdatum: Beiträge: 2159 |
Ok, dann sind wir da einer Meinung.
Natürlich überascht es mich nicht das ein Parent nicht die Änderung von sein Child erbt. Etwas anderes habe ich auch nie behauptet. Wenn ich also zusammenfassen darf. Man kann Systemvariablen für sein eigenen Prozess ändern, diese sind auch nur für diesen prozess gültig, und alle Childs "vererben" diese veränderten Systemvariablen. Damit sind wir nun wieder genau an der Behauptung angekommen die ich in meinen aller ersten Post schrieb:
Und an dieser Behauptung hattest du ja irgendetwas auszusetzen?!?
Wie du bereits richtig sagst sind dies Beispiele. Reicht eigentlich schon als begründung system() nicht zu nutzen. 😉
system() kann zur ersten Sicherheitslücke werden wenn du dort einfach Code ausführst den z.B. Benutzer eingegeben haben. Wenn dein Programm mit root Rechten läuft, z.B. Webserver und ein entsprechendes Skript und ein Benutzer dort einen String eingibt und er durch gute Wahl des Strings ein "rm -rf /" ausführen kann, hat er somit dein Rechner gelöscht. Klar kannst du auch ein Java Programm schreiben das mit "root" rechten das gleiche macht. Aber es ist ja wohl ein Unterschied ob du selber das Programm startest und schreibst und bereits mit vorhandenen root rechten ausführst. Oder ob 8 Milliarden Menschen auf der Welt mal eben einen String eingeben können, und dann etwas passiert was du nicht wolltest. 😉 Andere Problematik ist einfach die, dass du dir nie Sicher sein kannst was da nun wirklich ausgeführt wird. Führt ein "ls -l" nun wirklich das "ls" aus was du meinst oder ein fremdes untergeschobenes "ls"? Ansonsten zur Portabilität. Vielleicht hast du ein OS was diese Shellkommandos gar nicht kennt. Damit läuft dann dein programm nicht mehr. Gerade bei den Unterschiedlichen Linux Versionen kann es passieren das mal eine andere Version eines Tools installiert ist. Damit kennt es z.B. manche Kommandozeilen Optionen nicht. Auch zwischen BSD und Linux passiert es oft das Kommandoswitches halt eine andere Funktionalität haben. Aber die letzten Sache gelten Generell für jede Art von Shell Skript. Ich meinte ich kannte mal mehr gravierende Sicherheitslücken die man schnell mit system() einbauen kann. Aber kenne diese nicht mehr. Hab mir nur im Kopf behalten system() einfach nicht nutzen und fertig. Aber wäre gut wenn radoe2 nochmal paar Wörter dazu sagt. |
![]() Anmeldungsdatum: Beiträge: 17622 Wohnort: Berlin |
Ja. Ein hübsches Aneinandervorbeireden also. |
Anmeldungsdatum: Beiträge: 5792 |
radoe2 hat geschrieben:
Ich und Perl? Bewahre mich vor diesem Unheil 😉 Sid ist hier der Perl-Jünger, meine Wenigkeit liebt Python. Ich glaube, du hast da ein paar Leute hier zusammen geworfen 😉 Sicher ist Overhead dabei, aber wenn ich schnell ein kleines Programm nur für den privaten Gebrauch in C schreiben wollte, würde ich system() verwenden, schon allein deswegen, weil es schneller zu coden ist. In diesem Szenario sind die Sicherheitsprobleme eher zweitrangig, weil der potentielle Nutzer auch gleich dem Programmierer ist. Ich werde wohl kaum meinen eigenen Rechner angreifen 😉 Das man system() in ernsthaften Anwendungen nicht benutzt, darüber brauchen wir nicht diskutieren. radoe2 hat geschrieben:
Nun, aber es ging darum, ob der Weg über die Shell zum Starten eines neuen Prozesses nun umständlich oder gar übertrieben wäre. Das sehe ich nicht so. Zum einen ist es ziemlich üblich, Prozesse über eine neue Shell zu starten (trotz der einhergehenden Risiken). Aus deiner Position gesehen, wäre der gesamte Boot-Prozess eines Linux-Systems ein einziger Overhead, weil er ausschließlich über Shell-Skripte läuft. |