*** empty log message ***
authorroot <root>
Sun, 8 Jan 2006 08:43:11 +0000 (08:43 +0000)
committerroot <root>
Sun, 8 Jan 2006 08:43:11 +0000 (08:43 +0000)
Changes
doc/rxvt.1.pod
src/main.C
src/rxvtperl.h
src/rxvtperl.xs
src/urxvt.pm

diff --git a/Changes b/Changes
index 8c990d3195e786fcb9e37e24057e00b80c6f57c7..1e4f5f0e08ea5c92211c73f101e9f118d6ba8322 100644 (file)
--- a/Changes
+++ b/Changes
@@ -10,7 +10,6 @@ WISH: just for fun, do shade and tint with XRender.
 WISH: support tex fonts
 
 TODO: document transient_for, vt and the grab etc. functionality
-TODO: add warning about perl interpreter and setuid/setgid
 
        - perl: implement additional hook: line_update, add_lines.
         - perl: urxvt::line now can set via ->t and ->r.
@@ -19,6 +18,8 @@ TODO: add warning about perl interpreter and setuid/setgid
         - perl: much increased functionality, better overlays, popup support
           and much much more.
         - perl: anyevent support.
+        - perl: run tainted and ignore perl-eval/perl-lib if installed
+          setuid/setgid.
         - free the resource database: this plugs a massive memory hole. as a
           side effect, it also gets rid of XGetDefault calls.
         - free one of the cursors, fixes a small memory leaks.
index 9fd984ce02512095f45e8145abc30ce0b0601265..665a003a062d0207b8d46b1e9069abfcd53413bb 100644 (file)
@@ -1105,15 +1105,17 @@ all instances, while B<perl-ext> is used for specific instances.
 
 =item B<perl-eval>: I<string>
 
-Perl code to be evaluated when all extensions have been registered. See the
-@@RXVT_NAME@@perl(3) manpage.
+Perl code to be evaluated when all extensions have been registered. See
+the @@RXVT_NAME@@perl(3) manpage. Due to security reasons, this resource
+will be ignored when running setuid/setgid.
 
 =item B<perl-lib>: I<path>
 
 Colon-separated list of additional directories that hold extension
 scripts. When looking for extensions specified by the C<perl> resource,
 @@RXVT_NAME@@ will first look in these directories and then in
-F<@@RXVT_LIBDIR@@/urxvt/perl/>.
+F<@@RXVT_LIBDIR@@/urxvt/perl/>. Due to security reasons, this resource
+will be ignored when running setuid/setgid.
 
 See the @@RXVT_NAME@@perl(3) manpage.
 
index 97cac986bdc0a5e2b33a6a3264f3c7c2208ed06b..90ea32c479ee246a8278d785f1c62be36e7aea2c 100644 (file)
 # include <termios.h>
 #endif
 
+#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__)
+static uid_t saved_euid;
+static gid_t saved_egid;
+#endif
+
 vector<rxvt_term *> rxvt_term::termlist;
 
 static char curlocale[128], savelocale[128];
@@ -499,7 +504,24 @@ rxvt_term::init (int argc, const char *const *argv)
       || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2])
       || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
     {
-      rxvt_perl.init ();
+      bool tainted = false;
+
+#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__)
+      // ignore some perl-related arguments if some bozo installed us set[ug]id
+      if (getuid () != saved_euid || getgid () != saved_egid)
+        {
+          tainted = true;
+
+          if ((rs[Rs_perl_lib] && *rs[Rs_perl_lib])
+              || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
+            {
+              rxvt_warn ("running with elevated privileges: ignoring perl-lib and perl-eval.\n");
+              rs[Rs_perl_lib] = 0;
+              rs[Rs_perl_eval] = "our $tainted = 1";
+            }
+        }
+#endif
+      rxvt_perl.init (tainted);
       HOOK_INVOKE ((this, HOOK_INIT, DT_END));
     }
 #endif
@@ -667,11 +689,6 @@ rxvt_realloc (void *ptr, size_t size)
 void
 rxvt_privileges (rxvt_privaction action)
 {
-#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__)
-  static uid_t euid;
-  static gid_t egid;
-#endif
-
 #if ! defined(__CYGWIN32__)
 # if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
   /* setreuid () is the poor man's setuid (), seteuid () */
@@ -691,12 +708,12 @@ rxvt_privileges (rxvt_privaction action)
         setegid (getgid ());
         break;
       case SAVE:
-        euid = geteuid ();
-        egid = getegid ();
+        saved_euid = geteuid ();
+        saved_egid = getegid ();
         break;
       case RESTORE:
-        seteuid (euid);
-        setegid (egid);
+        seteuid (saved_euid);
+        setegid (saved_egid);
         break;
     }
 # else
index bf69305d952a231e8800f005155b5a3dede23b05..747cf1039697b10c36e39d139ff206b61d420ea2 100644 (file)
@@ -41,7 +41,7 @@ struct rxvt_perl_interp
 
   bool should_invoke[HOOK_NUM];
 
-  void init ();
+  void init (bool tainted);
   bool invoke (rxvt_term *term, hook_type htype, ...);
   void line_update (rxvt_term *term);
 };
index d32ee753448813d21e6d9b031b0532b980287b13..530a67f7a7b5a983c252a324a2392a7ac2938963 100644 (file)
 
 /////////////////////////////////////////////////////////////////////////////
 
+static SV *
+taint (SV *sv)
+{
+  SvTAINT (sv);
+  return sv;
+}
+
+static SV *
+taint_if (SV *sv, SV *src)
+{
+  if (SvTAINTED (src))
+    SvTAINT (sv);
+
+  return sv;
+}
+
 static wchar_t *
 sv2wcs (SV *sv)
 {
@@ -392,19 +408,20 @@ rxvt_perl_interp::~rxvt_perl_interp ()
 }
 
 void
-rxvt_perl_interp::init ()
+rxvt_perl_interp::init (bool tainted)
 {
   if (!perl)
     {
       char *argv[] = {
         "",
         "-edo '" LIBDIR "/urxvt.pm' or ($@ and die $@) or exit 1",
+        "-T",
       };
 
       perl = perl_alloc ();
       perl_construct (perl);
 
-      if (perl_parse (perl, xs_init, 2, argv, (char **)NULL)
+      if (perl_parse (perl, xs_init, 2 + !!tainted, argv, (char **)NULL)
           || perl_run (perl))
         {
           rxvt_warn ("unable to initialize perl-interpreter, continuing without.\n");
@@ -475,7 +492,7 @@ rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...)
           break;
 
         case DT_STR:
-          XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
+          XPUSHs (taint (sv_2mortal (newSVpv (va_arg (ap, char *), 0))));
           break;
 
         case DT_STR_LEN:
@@ -483,7 +500,7 @@ rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...)
             char *str = va_arg (ap, char *);
             int len = va_arg (ap, int);
 
-            XPUSHs (sv_2mortal (newSVpvn (str, len)));
+            XPUSHs (taint (sv_2mortal (newSVpvn (str, len))));
           }
           break;
 
@@ -492,7 +509,7 @@ rxvt_perl_interp::invoke (rxvt_term *term, hook_type htype, ...)
             wchar_t *wstr = va_arg (ap, wchar_t *);
             int wlen = va_arg (ap, int);
 
-            XPUSHs (sv_2mortal (wcs2sv (wstr, wlen)));
+            XPUSHs (taint (sv_2mortal (wcs2sv (wstr, wlen))));
           }
          break;
 
@@ -816,7 +833,7 @@ rxvt_term::locale_encode (SV *str)
 
         free (wstr);
 
-        RETVAL = newSVpv (mbstr, 0);
+        RETVAL = taint_if (newSVpv (mbstr, 0), str);
         free (mbstr);
 }
        OUTPUT:
@@ -833,7 +850,7 @@ rxvt_term::locale_decode (SV *octets)
         wchar_t *wstr = rxvt_mbstowcs (data, len);
         rxvt_pop_locale ();
 
-        RETVAL = wcs2sv (wstr);
+        RETVAL = taint_if (wcs2sv (wstr), octets);
         free (wstr);
 }
        OUTPUT:
@@ -950,7 +967,7 @@ rxvt_term::ROW_t (int row_number, SV *new_text = 0, int start_col = 0, int start
             for (int col = 0; col < THIS->ncol; col++)
               wstr [col] = l.t [col];
 
-            XPUSHs (sv_2mortal (wcs2sv (wstr, THIS->ncol)));
+            XPUSHs (taint (sv_2mortal (wcs2sv (wstr, THIS->ncol))));
 
             delete [] wstr;
           }
@@ -1081,7 +1098,7 @@ rxvt_term::special_encode (SV *string)
 
        rxvt_pop_locale ();
 
-        RETVAL = wcs2sv (rstr, r - rstr);
+        RETVAL = taint_if (wcs2sv (rstr, r - rstr), string);
 
         delete [] rstr;
 }
@@ -1117,7 +1134,7 @@ rxvt_term::special_decode (SV *text)
           else
             *r++ = *s;
 
-        RETVAL = wcs2sv (rstr, r - rstr);
+        RETVAL = taint_if (wcs2sv (rstr, r - rstr), text);
 
         delete [] rstr;
 }
@@ -1149,7 +1166,7 @@ rxvt_term::_resource (char *name, int index, SV *newval = 0)
           croak ("requested out-of-bound resource %s+%d,", name, index - rs->value);
 
         if (GIMME_V != G_VOID)
-          XPUSHs (THIS->rs [index] ? sv_2mortal (newSVpv (THIS->rs [index], 0)) : &PL_sv_undef);
+          XPUSHs (THIS->rs [index] ? sv_2mortal (taint (newSVpv (THIS->rs [index], 0))) : &PL_sv_undef);
 
         if (newval)
           {
@@ -1240,7 +1257,7 @@ rxvt_term::selection (SV *newtext = 0)
         PPCODE:
 {
         if (GIMME_V != G_VOID)
-          XPUSHs (sv_2mortal (wcs2sv (THIS->selection.text, THIS->selection.len)));
+          XPUSHs (taint (sv_2mortal (wcs2sv (THIS->selection.text, THIS->selection.len))));
 
         if (newtext)
           {
index d64d4df397523d49675561056d963ca29c260dcf..e285d151e304ce8f0ce59e025e0a12c520120b99 100644 (file)
@@ -473,6 +473,8 @@ sub extension_package($) {
                    . (do { local $/; <$fh> })
                    . "\n};\n1";
 
+      $source =~ /(.*)/s and $source = $1; # untaint
+
       eval $source or die "$path: $@";
 
       $pkg