[Python-Dev] Pondering some changes to python.c...

Sean Reifschneider jafo-python-dev@tummy.com
Sun, 7 Apr 2002 04:20:38 -0600


I've been pondering some changes to the main() interpreter code for a
while.  I'd like to get some feedback on them.

One is making changes to the process title to remove the interpreter name.
I've implemented some code to do this, which I'll include below.  I realize
that this code won't work for every platform, but for some it would be
quite a nice change.  In particular, it would allow things like "killall"
to be able to work on python programs.

The basics are that I check to make sure all the argv elements are
sequential, then just do "memcpy(argv[0], argv[1], appropriateSize)", and
pad strlen(orig_argv[0]) at the end with '\0'.  This is after saving a copy
of the original argv to hand off to Python itself.

The other thing I've been thinking of is a SUID python.  I recently needed
to make some code which ran SUID (so it could write files into a mail
queue with the right ownership, no matter if it was coming in from the
network or a local user).  I ended up making my own copy of python.c which
did the appropriate thing.  However, it would seem like something that
there should probably be an "official" one...

It's just too hard to do it right otherwise...

It would seem that if you were to unset LD_LIBRARY_PATH and PYTHONPATH (I'm
probably missing something), and then pick up the priveleges specified in
argv[1], that you could safely do SUID Python.  Some folks I've mentioned
it to seem to think it's just a bad idea to have an SUID python, but I
think it's better to solve the problems once than have people re-inventing
the wheel badly...

I've had about 4 occasions where I needed to run something with particular
privileges, and in at least one case my first cut at doing it left a fairly
big hole (because I failed to unset LD_LIBRARY_PATH).

Thoughts?

Sean
===========================
*** python.c.old	Sun Apr  7 04:18:11 2002
--- python.c	Sun Apr  7 04:19:32 2002
***************
*** 4,11 ****
--- 4,71 ----
  
  extern DL_EXPORT(int) Py_Main(int, char **);
  
+ #include <string.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ 
+ 
+ int setprocstr(int argc, char ***argvIn)
+ {
+ 	char *endp, **argv = *argvIn;
+ 	int argsLen = 0, i;
+ 
+ 
+ 	/*  do not change it if there is only one parameter  */
+ 	if (argc < 2) return(0);
+ 
+ 	/*  get max proc title length  */
+ 	for (endp = *argv, i = 0; i < argc; i++) {
+ 		endp += strlen(endp) + 1;
+ 		if (i == argc - 1) break;
+ 
+ 		/*  if arguments are not contiguous, abort  */
+ 		if ((endp) != argv[i + 1]) return(0);
+ 		}
+ 	argsLen = endp - argv[0];
+ 
+ 	/*  preserve copy of args  */
+ 	{
+ 		char **tmpArgv;
+ 		int argvLen = sizeof(char *) * (argc + 1), offset;
+ 
+ 
+ 		/*  allocate new argv  */
+ 		if (!(tmpArgv = malloc(argsLen + argvLen)))
+ 			 return(0);
+ 
+ 		/*  copy over argument vectors  */
+ 		offset = argvLen;
+ 		for (i = 0; i < argc; i++) {
+ 			tmpArgv[i] = ((char *) tmpArgv) + offset;
+ 			offset += strlen(argv[i]) + 1;
+ 			}
+ 		tmpArgv[i] = NULL;
+ 
+ 		/*  copy over argument data  */
+ 		memcpy(tmpArgv[0], argv[0], argsLen);
+ 
+ 		/*  copy to passed-in pointer  */
+ 		*argvIn = tmpArgv;
+ 	}
+ 
+ 	/*  copy to new location and zero out remaining  */
+ 	memcpy(argv[0], argv[1], argsLen - (argv[1] - argv[0]));
+ 	memset(endp - (argv[1] - argv[0]), '\0', argv[1] - argv[0]);
+ 	argv[1] = NULL;
+ 
+ 	return(1);
+ }
+ 
+ 
  int
  main(int argc, char **argv)
  {
+ 	setprocstr(argc, &argv);
  	return Py_Main(argc, argv);
  }
-- 
 Q:  What kind of dog goes "BOFH!  BOFH!"?
 A:  A rootweiler
Sean Reifschneider, Inimitably Superfluous <jafo@tummy.com>
tummy.com - Linux Consulting since 1995. Qmail, KRUD, Firewalls, Python