From: Jarkko Hietaniemi Date: Wed, 20 Jun 2001 04:54:53 +0000 (+0000) Subject: After some reading I don't think we can blindly X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=cb5953d685cec7d1e5d677ac4d2ddbe33ef0a803;p=p5sagit%2Fp5-mst-13.2.git After some reading I don't think we can blindly use systems' realpath(). Too many security problems, too many buggy implementations. TODO: the realpath() emulation code in util.c doesn't seem fully operational? (readlink(), for example?) p4raw-id: //depot/perl@10744 --- diff --git a/Configure b/Configure index b6ed6d9..2f76d15 100755 --- a/Configure +++ b/Configure @@ -20,7 +20,7 @@ # $Id: Head.U,v 3.0.1.9 1997/02/28 15:02:09 ram Exp $ # -# Generated on Wed Jun 20 02:24:20 EET DST 2001 [metaconfig 3.0 PL70] +# Generated on Wed Jun 20 08:47:08 EET DST 2001 [metaconfig 3.0 PL70] # (with additional metaconfig patches by perlbug@perl.org) cat >c1$$ <$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un */ #$d_flockproto HAS_FLOCK_PROTO /**/ -/* HAS_REALPATH: - * This symbol, if defined, indicates that the realpath routine is - * available to do resolve paths. - */ -#$d_realpath HAS_REALPATH /**/ - /* HAS_SIGPROCMASK: * This symbol, if defined, indicates that the sigprocmask * system call is available to examine or change the signal mask diff --git a/embed.pl b/embed.pl index 5f44ceb..64e0e5b 100755 --- a/embed.pl +++ b/embed.pl @@ -2058,7 +2058,7 @@ Apd |void |sv_pos_b2u |SV* sv|I32* offsetp Aopd |char* |sv_pvn_force |SV* sv|STRLEN* lp Apd |char* |sv_pvutf8n_force|SV* sv|STRLEN* lp Apd |char* |sv_pvbyten_force|SV* sv|STRLEN* lp -Apd |int |sv_realpath |SV* sv|char *path|STRLEN len +Apd |int |sv_realpath |SV* sv|char *path|STRLEN maxlen Apd |char* |sv_reftype |SV* sv|int ob Apd |void |sv_replace |SV* sv|SV* nsv Apd |void |sv_report_used diff --git a/perlapi.c b/perlapi.c index e910818..8c5901c 100644 --- a/perlapi.c +++ b/perlapi.c @@ -3172,9 +3172,9 @@ Perl_sv_pvbyten_force(pTHXo_ SV* sv, STRLEN* lp) #undef Perl_sv_realpath int -Perl_sv_realpath(pTHXo_ SV* sv, char *path, STRLEN len) +Perl_sv_realpath(pTHXo_ SV* sv, char *path, STRLEN maxlen) { - return ((CPerlObj*)pPerl)->Perl_sv_realpath(sv, path, len); + return ((CPerlObj*)pPerl)->Perl_sv_realpath(sv, path, maxlen); } #undef Perl_sv_reftype diff --git a/pod/perldiag.pod b/pod/perldiag.pod index de8956b..75f9ec0 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -3286,6 +3286,12 @@ assignment or as a subroutine argument for example). (F) Your Perl was compiled with B<-D>SETUID_SCRIPTS_ARE_SECURE_NOW, but a version of the setuid emulator somehow got run anyway. +=item sv_realpath: %s + +(S) You probably used some form of getcwd. The implementation of +that functionality detected something odd in your filesystem +environment and gave up (returning undef). + =item Switch (?(condition)... contains too many branches in regex; marked by <-- HERE in m/%s/ diff --git a/pod/perltoc.pod b/pod/perltoc.pod index 1094d8c..0912724 100644 --- a/pod/perltoc.pod +++ b/pod/perltoc.pod @@ -3908,7 +3908,7 @@ PUSHn, PUSHp, PUSHs, PUSHu, PUTBACK, Renew, Renewc, require_pv, RETVAL, Safefree, savepv, savepvn, SAVETMPS, SP, SPAGAIN, ST, strEQ, strGE, strGT, strLE, strLT, strNE, strnEQ, strnNE, StructCopy, SvCUR, SvCUR_set, SvEND, SvGETMAGIC, SvGROW, SvIOK, SvIOKp, SvIOK_notUV, SvIOK_off, SvIOK_on, -SvIOK_only, SvIOK_only_UV, SvIOK_UV, SvIV, SvIVx, SvIVX, SvLEN, SvNIOK, +SvIOK_only, SvIOK_only_UV, SvIOK_UV, SvIV, SvIVX, SvIVx, SvLEN, SvNIOK, SvNIOKp, SvNIOK_off, SvNOK, SvNOKp, SvNOK_off, SvNOK_on, SvNOK_only, SvNV, SvNVx, SvNVX, SvOK, SvOOK, SvPOK, SvPOKp, SvPOK_off, SvPOK_on, SvPOK_only, SvPOK_only_UTF8, SvPV, SvPVbyte, SvPVbytex, SvPVbytex_force, @@ -4575,22 +4575,26 @@ I =item Incompatible Changes +=over 4 + +=item 64-bit platforms and malloc + =item Future Deprecations +=back + =item Core Enhancements =item Modules and Pragmata =over 4 -=item New Modules +=item New Modules and Distribution =item Updated And Improved Modules and Pragmata =back -=item Performance Enhancements - =item Utility Changes =item New Documentation @@ -4651,6 +4655,8 @@ I =item Self-tying of Arrays and Hashes Is Forbidden +=item Variable Attributes are not Currently Usable for Tieing + =item Building Extensions Can Fail Because Of Largefiles =item The Compiler Suite Is Still Experimental diff --git a/uconfig.h b/uconfig.h index 67578fa..4d51056 100644 --- a/uconfig.h +++ b/uconfig.h @@ -1015,7 +1015,7 @@ * 4 and 8. The default is eight, for safety. */ #if defined(USE_CROSS_COMPILE) || defined(MULTIARCH) -#define MEM_ALIGNBYTES 8 +# define MEM_ALIGNBYTES 8 #else #define MEM_ALIGNBYTES 4 #endif @@ -3368,12 +3368,6 @@ */ /*#define HAS_FLOCK_PROTO / **/ -/* HAS_REALPATH: - * This symbol, if defined, indicates that the realpath routine is - * available to do resolve paths. - */ -/*#define HAS_REALPATH / **/ - /* HAS_SIGPROCMASK: * This symbol, if defined, indicates that the sigprocmask * system call is available to examine or change the signal mask diff --git a/uconfig.sh b/uconfig.sh index 52e34b7..ca35351 100755 --- a/uconfig.sh +++ b/uconfig.sh @@ -218,7 +218,6 @@ d_quad='undef' d_readdir='undef' d_readlink='undef' d_readv='undef' -d_realpath='undef' d_recvmsg='undef' d_rename='undef' d_rewinddir='undef' diff --git a/util.c b/util.c index 02c907d..1d69fe5 100644 --- a/util.c +++ b/util.c @@ -3624,6 +3624,9 @@ Perl_sv_getcwd(pTHX_ register SV *sv) SvGROW(sv, 128); while ((getcwd(SvPVX(sv), SvLEN(sv)-1) == NULL) && errno == ERANGE) { + if (SvLEN(sv) + 128 >= MAXPATHLEN) { + SV_CWD_RETURN_UNDEF; + } SvGROW(sv, SvLEN(sv) + 128); } SvCUR_set(sv, strlen(SvPVX(sv))); @@ -3687,6 +3690,10 @@ Perl_sv_getcwd(pTHX_ register SV *sv) SV_CWD_RETURN_UNDEF; } + if (pathlen + namelen + 1 >= MAXPATHLEN) { + SV_CWD_RETURN_UNDEF; + } + SvGROW(sv, pathlen + namelen + 1); if (pathlen) { @@ -3737,62 +3744,44 @@ Perl_sv_getcwd(pTHX_ register SV *sv) /* =for apidoc sv_realpath -Wrap or emulate realpath(3). +Emulate realpath(3). + +The real realpath() is not used because it's a known can of worms. +We may have bugs but hey, they are our very own. =cut */ int -Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len) +Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN maxlen) { #ifndef PERL_MICRO - char name[MAXPATHLEN] = { 0 }, *s; + char name[MAXPATHLEN] = { 0 }; + char dotdots[MAXPATHLEN] = { 0 }; + char *s; STRLEN pathlen, namelen; + DIR *parent; + Direntry_t *dp; + struct stat cst, pst, tst; - /* Don't use strlen() to avoid running off the end. */ - s = memchr(path, '\0', MAXPATHLEN); - pathlen = s ? s - path : MAXPATHLEN; - -#ifdef HAS_REALPATH - - /* Be paranoid about the use of realpath(), - * it is an infamous source of buffer overruns. */ - - /* Is the source buffer too long? */ - if (pathlen == MAXPATHLEN) { - Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)", - path, s ? '=' : '>', MAXPATHLEN); - SV_CWD_RETURN_UNDEF; - } - - /* Here goes nothing. */ - if (realpath(path, name) == NULL) { - Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %s", - path, Strerror(errno)); + if (!sv || !path || !maxlen) { + Perl_warn(aTHX_ "sv_realpath: realpath(0x%x, 0x%x, "")", + sv, path, maxlen); SV_CWD_RETURN_UNDEF; } - /* Is the destination buffer too long? + /* Is the source buffer too long? * Don't use strlen() to avoid running off the end. */ - s = memchr(name, '\0', MAXPATHLEN); - namelen = s ? s - name : MAXPATHLEN; - if (namelen == MAXPATHLEN) { - Perl_warn(aTHX_ "sv_realpath: realpath(\"%s\"): %c= (MAXPATHLEN = %d)", - path, s ? '=' : '>', MAXPATHLEN); + if (maxlen >= MAXPATHLEN) + pathlen = maxlen; + else { + s = memchr(path, '\0', MAXPATHLEN); + pathlen = s ? s - path : MAXPATHLEN; + } + if (pathlen >= MAXPATHLEN) { + Perl_warn(aTHX_ "sv_realpath: source too large"); SV_CWD_RETURN_UNDEF; } - /* The coast is clear? */ - sv_setpvn(sv, name, namelen); - SvPOK_only(sv); - - return TRUE; -#else - { - DIR *parent; - Direntry_t *dp; - char dotdots[MAXPATHLEN] = { 0 }; - struct stat cst, pst, tst; - if (PerlLIO_stat(path, &cst) < 0) { Perl_warn(aTHX_ "sv_realpath: stat(\"%s\"): %s", path, Strerror(errno)); @@ -3801,10 +3790,9 @@ Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len) (void)SvUPGRADE(sv, SVt_PV); - if (!len) { - len = strlen(path); - } - Copy(path, dotdots, len, char); + Copy(path, dotdots, maxlen, char); + + pathlen = 0; for (;;) { strcat(dotdots, "/.."); @@ -3864,6 +3852,11 @@ Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len) SV_CWD_RETURN_UNDEF; } + if (pathlen + namelen + 1 >= MAXPATHLEN) { + Perl_warn(aTHX_ "sv_realpath: too long name"); + SV_CWD_RETURN_UNDEF; + } + SvGROW(sv, pathlen + namelen + 1); if (pathlen) { /* shift down */ @@ -3890,10 +3883,8 @@ Perl_sv_realpath(pTHX_ SV *sv, char *path, STRLEN len) SvPOK_only(sv); return TRUE; - } -#endif #else - return FALSE; + return FALSE; /* MICROPERL */ #endif } diff --git a/vos/config.alpha.def b/vos/config.alpha.def index 2319650..0065516 100644 --- a/vos/config.alpha.def +++ b/vos/config.alpha.def @@ -194,7 +194,6 @@ $d_quad='undef' $d_readdir='define' $d_readlink='define' $d_readv='undef' -$d_realpath='undef' $d_recvmsg='undef' $d_rename='define' $d_rewinddir='define' diff --git a/vos/config.alpha.h b/vos/config.alpha.h index 54dfc0c..3f47acf 100644 --- a/vos/config.alpha.h +++ b/vos/config.alpha.h @@ -3368,12 +3368,6 @@ */ /*#define HAS_FLOCK_PROTO /**/ -/* HAS_REALPATH: - * This symbol, if defined, indicates that the realpath routine is - * available to do resolve paths. - */ -/*#define HAS_REALPATH /**/ - /* HAS_SIGPROCMASK: * This symbol, if defined, indicates that the sigprocmask * system call is available to examine or change the signal mask diff --git a/vos/config.ga.def b/vos/config.ga.def index 9a0a02c..4d49cf5 100644 --- a/vos/config.ga.def +++ b/vos/config.ga.def @@ -194,7 +194,6 @@ $d_quad='undef' $d_readdir='define' $d_readlink='define' $d_readv='undef' -$d_realpath='undef' $d_recvmsg='undef' $d_rename='define' $d_rewinddir='define' diff --git a/vos/config.ga.h b/vos/config.ga.h index 8c4dd35..5b283e3 100644 --- a/vos/config.ga.h +++ b/vos/config.ga.h @@ -3368,12 +3368,6 @@ */ /*#define HAS_FLOCK_PROTO /**/ -/* HAS_REALPATH: - * This symbol, if defined, indicates that the realpath routine is - * available to do resolve paths. - */ -/*#define HAS_REALPATH /**/ - /* HAS_SIGPROCMASK: * This symbol, if defined, indicates that the sigprocmask * system call is available to examine or change the signal mask diff --git a/win32/config_H.bc b/win32/config_H.bc index 6efd9ca..6f1d3c1 100644 --- a/win32/config_H.bc +++ b/win32/config_H.bc @@ -3368,12 +3368,6 @@ */ /*#define HAS_FLOCK_PROTO /**/ -/* HAS_REALPATH: - * This symbol, if defined, indicates that the realpath routine is - * available to do resolve paths. - */ -/*#define HAS_REALPATH /**/ - /* HAS_SIGPROCMASK: * This symbol, if defined, indicates that the sigprocmask * system call is available to examine or change the signal mask diff --git a/win32/config_H.gc b/win32/config_H.gc index 0f20bce..ce85240 100644 --- a/win32/config_H.gc +++ b/win32/config_H.gc @@ -3368,12 +3368,6 @@ */ /*#define HAS_FLOCK_PROTO /**/ -/* HAS_REALPATH: - * This symbol, if defined, indicates that the realpath routine is - * available to do resolve paths. - */ -/*#define HAS_REALPATH /**/ - /* HAS_SIGPROCMASK: * This symbol, if defined, indicates that the sigprocmask * system call is available to examine or change the signal mask diff --git a/win32/config_H.vc b/win32/config_H.vc index 476245e..e48c157 100644 --- a/win32/config_H.vc +++ b/win32/config_H.vc @@ -3368,12 +3368,6 @@ */ /*#define HAS_FLOCK_PROTO /**/ -/* HAS_REALPATH: - * This symbol, if defined, indicates that the realpath routine is - * available to do resolve paths. - */ -/*#define HAS_REALPATH /**/ - /* HAS_SIGPROCMASK: * This symbol, if defined, indicates that the sigprocmask * system call is available to examine or change the signal mask