--- lilypond-2.4.4/lily/main.cc 2004-11-04 17:46:43.000000000 +0100 +++ lilypond-2.4.4-patched/lily/main.cc 2005-03-04 19:09:47.237182653 +0100 @@ -11,6 +11,11 @@ #include #include #include +#include +#include +#include +#include +#include #include "config.hh" @@ -115,6 +120,19 @@ LOCAL_LILYPOND_DATADIR = /usr/share/lilypond/ */ char const *prefix_directory[] = {LILYPOND_DATADIR, LOCAL_LILYPOND_DATADIR, 0}; +/* The directory to be used to perform chroot(). */ +static char const *change_root; + +/* The user to which to switch (after chroot'ing). */ +static char const *set_user; + +/* The group to which to switch (after chroot'ing). */ +static char const *set_group; + +/* The directory in which to move before compiling (after chroot'ing). */ +static char const *change_directory; + + /* The option parser */ static Getopt_long *option_parser = 0; @@ -128,7 +146,9 @@ _i ("set option, use -e '(ly:option-usage)' for help")}, /* Bug in option parser: --output=foe is taken as an abbreviation for --output-format. */ + {_i ("DIR"), "chdir", 'd', _i ("change the current directory to DIR before compiling (but after chroot'ing)")}, {_i ("EXT"), "format", 'f', _i ("select back-end to use")}, + {_i ("GROUP"), "set-group", 'g', _i ("change the group to GROUP before compiling (but after chroot'ing)")}, {0, "help", 'h', _i ("print this help")}, {_i ("FIELD"), "header", 'H', _i ("write header field to BASENAME.FIELD")}, {_i ("DIR"), "include", 'I', _i ("add DIR to search path")}, @@ -142,7 +162,9 @@ {0, "dvi", 0, _i ("generate DVI")}, {0, "pdf", 0, _i ("generate PDF (default)")}, {0, "tex", 0, _i ("generate TeX")}, + {_i ("DIR"), "chroot", 'r', _i ("chroot to DIR before compiling")}, {0, "safe-mode", 's', _i ("run in safe mode")}, + {_i ("USER"), "set-user", 'u', _i ("change the user to USER before compiling (but after chroot'ing)")}, {0, "version", 'v', _i ("print version number")}, {0, "verbose", 'V', _i ("be verbose")}, {0, "warranty", 'w', _i ("show warranty and copyright")}, @@ -339,6 +361,62 @@ exit (2); } + /* Now we chroot, setuid/setgrp and chdir. If something goes wrong, we exit (this is a + security-sensitive area). */ + + /* We must retrieve the user/group id *before* chroot'ing! */ + int uid, gid; + + if (set_user) { + errno = 0; + struct passwd *passwd = getpwnam(set_user); + if (passwd == NULL) { + if (errno == 0) error (_ ("user not found")); + else error(_f ("can't get user id from user name (%s)", strerror (errno))); + exit (3); + } + uid = passwd->pw_uid; + } + + if (set_group) { + errno = 0; + struct group *group = getgrnam(set_group); + if (group == NULL) { + if (errno == 0) error (_ ("group not found")); + else error(_f ("can't get group id from group name (%s)", strerror (errno))); + exit (3); + } + gid = group->gr_gid; + } + + if (change_root) { + if (chroot(change_root)) { + error (_f ("can't chroot (%s)", strerror (errno))); + exit (3); + } + } + + if (set_user) { + if (setuid (uid)) { + error (_f ("can't set user id (%s)", strerror (errno))); + exit (3); + } + } + + if (set_group) { + if (setuid (gid)) { + error (_f ("can't set group id (%s)", strerror (errno))); + exit (3); + } + } + + if (change_directory) { + if (chdir(change_directory)) { + error (_f ("can't change current directory (%s)", strerror (errno))); + exit (3); + } + } + SCM result = scm_call_1 (ly_scheme_function ("lilypond-main"), files); (void) result; @@ -402,6 +480,18 @@ output_name_global = file_name.to_string (); } break; + case 'd': + change_directory = option_parser->optional_argument_str0_; + break; + case 'r': + change_root = option_parser->optional_argument_str0_; + break; + case 'u': + set_user = option_parser->optional_argument_str0_; + break; + case 'g': + set_group = option_parser->optional_argument_str0_; + break; case 'e': init_scheme_code_string += option_parser->optional_argument_str0_; break;