Autor Thema: Probleme mit openat() bei 32bit (gelöst)  (Gelesen 10358 mal)

mv

  • Newbie
  • *
  • Beiträge: 22
    • Profil anzeigen
Probleme mit openat() bei 32bit (gelöst)
« am: Mai 28, 2014, 10:30:42 Vormittag »
Hallo,

ich bin auf ein seltsames Problem im Zusammenhang mit openat() gestoßen, das merkwürdigerweise nur bei den 32bit-Treibern auftritt, aber nicht bei den 64bit-Treibern. Das Problem wurde in https://forums.gentoo.org/viewtopic-t-991874.html beschrieben, aber ich fasse hier noch einmal zusammen.

Problembeschreibung: Mit tar-1.27.1 (bei tar-1.26 scheint eine andere Implementierung das Problem zu vermeiden, andere Versionen habe ich nicht getestet) entpacke man zweimal ein Archiv (mit relativen Pfaden) in das selbe Directory. Beim zweitenmal versucht tar, die Dateien nach "/" statt in das aktuelle Directory zu entpacken. Wenn man /etc/ld.so.preload entfernt, verschwindet das Problem, so dass die sundtek-Treiber zumindest implizit mitverantwortlich sind. Das Problem tritt nur bei 32bit, nicht aber bei 64bit auf. Bei 32bit tritt das Problem sowohl mit glibc-2.17 als auch mit glibc-2.19 auf.

Analyse: Obwohl tar-1.27.1 zwar eine Fallback-Implementation von openat() mitbringt, wird diese (zumindest auf meinem System) anscheinend nicht benutzt, sondern direkt die glibc-Funktion openat() aufgerufen. "strace" zeigt, dass openat() vom Sundtek-Treiber anscheinend (direkt oder indirekt) überladen wird, und dass sich der openat()-Bibliotheksaufruf von tar dadurch effektiv in folgende Aufrufe (auf dem 32Bit-System) übersetzt:
openat(AT_FDCWD, "somedir/somefile", O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_NONBLOCK|O_CLOEXEC, 0644) = -1 EEXIST (File exists)
readlink("/proc/self/fd/-100", 0xfbcf5293, 100) = -1 ENOENT (No such file or directory)
open("/somedir/somefile", O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_NONBLOCK|O_CLOEXEC, 0644) = -1 ENOENT (No such file or directory)
Auf dem 64bit-System ohne das Problem sieht die Übersetzung anders auf:
openat(AT_FDCWD, "somedir/somefile", O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_NONBLOCK|O_CLOEXEC, 0644) = -1 EEXIST (File exists)
unlinkat(AT_FDCWD, "somedir/somefile", 0) = 0
openat(AT_FDCWD, "somedir/somefile", O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_NONBLOCK|O_CLOEXEC, 0644) = 4
Anders als bei 32bit wird bei 64bit also weder der merkwürdige "readlink()"-Aufruf ausgeführt, noch wird ein open() mit vorgestelltem "/" aufgerufen.

Edit: Möglicherweise tritt das Problem erst mit neueren Versionen des Sundtek-Treibers auf; ich kann aber nicht mehr nachvollziehen, seit wann, und habe ältere Versionen jetzt auch nicht systematisch getestet.
« Letzte Änderung: Mai 29, 2014, 12:18:17 Vormittag von mv »

Sundtek

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 8604
    • Profil anzeigen
Re:Probleme mit openat() bei 32bit
« Antwort #1 am: Mai 28, 2014, 10:48:10 Vormittag »
Kannst du uns eventuell via Skype kontaktieren (sundtek)?

openat wird mittlerweile von VLC benutzt.

64Bit hat wohl den Syscall SYS_openat, daher klappt das dort warscheinlich bei dir. Ich wüsste nicht das es bei unseren Tests damals Probleme gab.
Failure is a good thing! I'll fix it

mv

  • Newbie
  • *
  • Beiträge: 22
    • Profil anzeigen
Re:Probleme mit openat() bei 32bit
« Antwort #2 am: Mai 28, 2014, 07:07:03 Nachmittag »
Kannst du uns eventuell via Skype kontaktieren (sundtek)?
Zu normalen Arbeitszeiten ist das derzeit schwierig, aber vielleicht klappt es Freitag mittag.

Ich habe versucht, eine Minimalbeispiel in C mit openat() zu schreiben, aber merkwürdigerweise scheint in dem Fall der openat()-Aufruf exakt ans System weitergereicht zu werden; was tar-1.27.1 da anders macht, kann ich nicht erkennen.

Hier ist auf jeden Fall eine Kommandozeile zum schnellen Testen mit (GNU) tar-1.27.1:
:>|test ; tar c test |tar xFührt man die als $USER auf 32bit aus (mit /etc/ld.so.preload von sundtak), bekommt man die Fehlermeldung dass "test" nicht erstellt werden kann. Führt man sie als root aus, wird /test (im /-Directory!) erstellt. Ohne /etc/ld.so.preload wird einfach "./test" ohne Fehlermeldung zweimal hintereinander leer erstellt, wie es sein soll.

Sundtek

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 8604
    • Profil anzeigen
Re:Probleme mit openat() bei 32bit
« Antwort #3 am: Mai 28, 2014, 07:18:51 Nachmittag »
gegen Abend kein Problem, füge uns mal im Skype hinzu (sundtek) oder Chat: irc.freenode.net #sundtek (dort wird eher sporadisch geantwortet aber es wird geantwortet).
Failure is a good thing! I'll fix it

mv

  • Newbie
  • *
  • Beiträge: 22
    • Profil anzeigen
Re:Probleme mit openat() bei 32bit
« Antwort #4 am: Mai 28, 2014, 08:01:11 Nachmittag »
gegen Abend kein Problem, füge uns mal im Skype hinzu
Schon gemacht. Vielleicht klappt es später.

Inzwischen habe ich ein Minimalbeispiel: Man muss openat64 (statt openat) aufrufen und sich darauf verlassen, dass AT_FDCWD das aktuelle Directory ist.
#include <fcntl.h>

int main(int argc, char** argv) {
  return openat64(AT_FDCWD, "t", O_WRONLY|O_CREAT|O_EXCL, 0644);
}
(Compilation mit gcc ohne irgendwelche Optionen).
Führt man dieses Programm zum ersten mal aus, wird "t" im aktuellen Directory angelegt, beim zweiten Mal wird versucht, "/t" anzulegen.

Sundtek

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 8604
    • Profil anzeigen
Re:Probleme mit openat() bei 32bit
« Antwort #5 am: Mai 28, 2014, 10:09:58 Nachmittag »
AT_FDCWD den special Filedescriptor haben wir nicht beachtet, vielen Dank für die Information!
Failure is a good thing! I'll fix it

mv

  • Newbie
  • *
  • Beiträge: 22
    • Profil anzeigen
Re:Probleme mit openat() bei 32bit (gelöst)
« Antwort #6 am: Mai 29, 2014, 12:22:41 Vormittag »
Vielen herzlichen Dank für den schnellen Fix.

Das Gentoo Ebuild für den Treiber (im mv Overlay) benutzt jetzt den neuesten Treiber mit dem Fix.