Filehandles schliessen...

Filehandles schliessen...

am 07.03.2006 21:13:21 von Josef Wolf

Hallo!

Wenn es um sichere Programmierung geht, wird haeufig die Empfehlung gegeben,
sicherzustellen dass genau die drei standard-filehandles offen sind. In C
sieht man also haeufig code wie (habe das jetzt mal bei amanda geklaut):


safe_fd(fd_start, fd_count)
int fd_start;
int fd_count;
{
int fd;

for(fd = 0; fd < FD_SETSIZE; fd++) {
if (fd < 3) {
/*
* Open three file descriptors. If one of the standard
* descriptors is not open it will be pointed to /dev/null...
*
* This avoids, for instance, someone running us with stderr
* closed so that when we open some other file, messages
* sent to stderr do not accidentally get written to the
* wrong file.
*/
if (fcntl(fd, F_GETFD) == -1) {
if (open("/dev/null", O_RDWR) == -1) {
fprintf(stderr, "/dev/null is inaccessable: %s\n",
strerror(errno));
exit(1);
}
}
} else {
/*
* Make sure nobody spoofs us with a lot of extra open files
* that would cause an open we do to get a very high file
* descriptor, which in turn might be used as an index into
* an array (e.g. an fd_set).
*/
if (fd < fd_start || fd >= fd_start + fd_count) {
close(fd);
}
}
}
}


Ich kann allerdings nirgends Hinweise finden, wie man das Aequivalent in
perl macht. Macht das perl etwa schon selbst? Wenn nicht, wie mache ich
das zu fuss?

Re: Filehandles schliessen...

am 08.03.2006 09:32:34 von Christian Lackas

* Josef Wolf [2006-03-07]:

Hallo Josef,

> Ich kann allerdings nirgends Hinweise finden, wie man das Aequivalent in
> perl macht. Macht das perl etwa schon selbst? Wenn nicht, wie mache ich
> das zu fuss?

du kannst C-Code in Perl einbinden:

perldoc Inline::C
perldoc perlxstut

Gruß
Christian

--
Leute, geht in Euch - und bleibt dort.
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker

Re: Filehandles schliessen...

am 08.03.2006 11:11:35 von Frank Seitz

Christian Lackas wrote:
> * Josef Wolf [2006-03-07]:
>>
>>Ich kann allerdings nirgends Hinweise finden, wie man das Aequivalent in
>>perl macht. Macht das perl etwa schon selbst? Wenn nicht, wie mache ich
>>das zu fuss?
>
> du kannst C-Code in Perl einbinden:
>
> perldoc Inline::C
> perldoc perlxstut

Ich frage mich, ob die Probleme, die der C-Code vermeiden soll,
in Perl überhaupt auftreten können.

Zum ersten Teil: Kann nicht eintreten, denke ich,
da man in Perl nicht direkt auf Deskriptoren schreibt.

Zum zweiten Teil: Kann nicht eintreten, da man in Perl wohl
nicht über die Grenzen eines Bitvectors
hinausschreiben kann.

Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Re: Filehandles schliessen...

am 11.03.2006 10:11:49 von hjp-usenet2

Frank Seitz wrote:
> Christian Lackas wrote:
>> * Josef Wolf [2006-03-07]:
>>>Ich kann allerdings nirgends Hinweise finden, wie man das Aequivalent in
>>>perl macht. Macht das perl etwa schon selbst? Wenn nicht, wie mache ich
>>>das zu fuss?
[...]
> Ich frage mich, ob die Probleme, die der C-Code vermeiden soll,
> in Perl überhaupt auftreten können.

Im Prinzip ja, in der Praxis eher nicht.

> Zum ersten Teil: Kann nicht eintreten, denke ich,
> da man in Perl nicht direkt auf Deskriptoren schreibt.

Das ist egal. Ob Du nun direkt oder indirekt auf einen Filedescriptor
schreibst, macht keinen Unterschied. Wenn sowohl der Filehandle F als
auch STDERR sich auf den Filedescriptor 2 beziehen, wird deren Output
vermischt.

In der Praxis wird das kaum ein Problem sein, weil Perl (zumindest
v5.8.4 built for i386-linux-thread-multi) Filedescriptoren < 3 nie
schließt. Selbst wenn zum Startzeitpunkt STDIN, STDOUT und STDERR nicht
offen sind, sind sie es spätestens nach zwei "use". Mit "use warnings"
und "use strict" ist man also schon sicher :-).

Demo:

-------- fh1 -----------------------------------------------------------
#!/usr/bin/perl
use warnings;
use strict;
use utf8;

close(STDERR);
close(STDIN);
system("./fh2");
open(F, "<", "fh2.txt");
while () {
if (/error/) {
print "erwischt!\n";
exit(0);
}
}
print "Glück gehabt.\n"
------------------------------------------------------------ ------------

-------- fh2 -----------------------------------------------------------
#!/usr/bin/perl

sleep(60);
open(F, ">", "fh2.txt");
print F "ein test ein test\n";
print STDERR "error: stupid script detected\n";
close(F);
------------------------------------------------------------ ------------

../fh1 gibt "erwischt!" aus. Ein lsof während des sleep

fh2 31953 hjp cwd DIR 254,1 12288 217156 /home/hjp/tmp
fh2 31953 hjp rtd DIR 254,0 1024 2 /
fh2 31953 hjp txt REG 254,2 1057324 262352 /usr/bin/perl
fh2 31953 hjp mem REG 254,0 88168 77021 /lib/ld-2.3.5.so
fh2 31953 hjp mem REG 254,0 9592 77027 /lib/libdl-2.3.5.so
fh2 31953 hjp mem REG 254,0 145168 77028 /lib/libm-2.3.5.so
fh2 31953 hjp mem REG 254,0 87884
77038 /lib/libpthread-0.10.so
fh2 31953 hjp mem REG 254,0 1144316 77024 /lib/libc-2.3.5.so
fh2 31953 hjp mem REG 254,0 21872
77026 /lib/libcrypt-2.3.5.so
fh2 31953 hjp mem REG 254,2 1626944
311374 /usr/lib/locale/locale-archive
fh2 31953 hjp 0r REG 254,1 143 216527 /home/hjp/tmp/fh2
fh2 31953 hjp 1u CHR 136,6 8 /dev/pts/6
fh2 31953 hjp 4r CHR 1,3 64776 /dev/null

Zeigt, dass STDIN (Fd 0) das Script selbst ist. STDOUT (Fd 1) war beim
Aufruf schon
offen. STDERR (Fd 2) ist nicht offen, wird also vom nächsten open
verwendet werden. Das ist

open(F, ">", "fh2.txt");

und somit schreiben dann

print F "ein test ein test\n";
print STDERR "error: stupid script detected\n";

ins gleiche File.

Wenn ich nun fh2 um

use warnings;
use strict;

erweitere, dann gibt ./fh1 "Glück gehabt." aus und ein lsof zeigt:

[...]
fh2 31916 hjp 0r REG 254,1 169 216527 /home/hjp/tmp/fh2
fh2 31916 hjp 1u CHR 136,6 8 /dev/pts/6
fh2 31916 hjp 2r REG 254,2 12827
328085 /usr/share/perl/5.8.4/warnings.pm
fh2 31916 hjp 4r CHR 1,3 64776 /dev/null

dass nun der Filedescriptor 2 auf warnings.pm (read-only) geöffnet ist.
Somit bekommt fh2.txt den Filedescriptor 3 und

print F "ein test ein test\n";

schreibt weiterhin ins richtige File, während

print STDERR "error: stupid script detected\n";

vergeblich versucht, warnings.pm zu überschreiben.

> Zum zweiten Teil: Kann nicht eintreten, da man in Perl wohl
> nicht über die Grenzen eines Bitvectors
> hinausschreiben kann.

Aus dem zweiten Teil werde ich auch nicht ganz schlau. Schaut m.E. nach
einem spezifischen Würgaround für ein Problem von select(2) und/oder
dessen falsche Verwendung aus. Da wäre es aber vermutlich sinnvoller,
das Übel an der Wurzel zu packen.

hp

--
_ | Peter J. Holzer | Löschung von at.usenet.schmankerl?
|_|_) | Sysadmin WSR/LUGA |
| | | hjp@hjp.at | Diskussion derzeit in at.usenet.gruppen
__/ | http://www.hjp.at/ |