ruby-changes:25072
From: nobu <ko1@a...>
Date: Tue, 9 Oct 2012 17:13:38 +0900 (JST)
Subject: [ruby-changes:25072] nobu:r37124 (trunk): process.c: uid gid exec options
nobu 2012-10-09 17:13:29 +0900 (Tue, 09 Oct 2012) New Revision: 37124 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37124 Log: process.c: uid gid exec options * process.c (rb_execarg_addopt, rb_execarg_run_options): add :uid and :gid options. [ruby-core:47414] [Feature #6975] Modified files: trunk/ChangeLog trunk/internal.h trunk/process.c trunk/test/ruby/test_process.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 37123) +++ ChangeLog (revision 37124) @@ -1,3 +1,8 @@ +Tue Oct 9 17:13:27 2012 Nobuyoshi Nakada <nobu@r...> + + * process.c (rb_execarg_addopt, rb_execarg_run_options): add :uid and + :gid options. [ruby-core:47414] [Feature #6975] + Tue Oct 9 14:36:11 2012 Koichi Sasada <ko1@a...> * iseq.c (iseq_free): fix memory leak. Index: process.c =================================================================== --- process.c (revision 37123) +++ process.c (revision 37124) @@ -136,7 +136,56 @@ #define preserving_errno(stmts) \ do {int saved_errno = errno; stmts; errno = saved_errno;} while (0) +static void check_uid_switch(void); +static void check_gid_switch(void); +#if 1 +#define p_uid_from_name p_uid_from_name +#define p_gid_from_name p_gid_from_name +#endif + +#if defined(HAVE_PWD_H) +# ifdef HAVE_GETPWNAM_R +# define PREPARE_GETPWNAM \ + long getpw_buf_len = sysconf(_SC_GETPW_R_SIZE_MAX); \ + char *getpw_buf = ALLOCA_N(char, (getpw_buf_len < 0 ? (getpw_buf_len = 4096) : getpw_buf_len)); +# define OBJ2UID(id) obj2uid((id), getpw_buf, getpw_buf_len) +static rb_uid_t obj2uid(VALUE id, char *getpw_buf, size_t getpw_buf_len); +# else +# define PREPARE_GETPWNAM /* do nothing */ +# define OBJ2UID(id) obj2uid((id)) +static rb_uid_t obj2uid(VALUE id); +# endif +#else +# define PREPARE_GETPWNAM /* do nothing */ +# define OBJ2UID(id) NUM2UIDT(id) +# ifdef p_uid_from_name +# undef p_uid_from_name +# define p_uid_from_name rb_f_notimplement +# endif +#endif + +#if defined(HAVE_GRP_H) +# ifdef HAVE_GETGRNAM_R +# define PREPARE_GETGRNAM \ + long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX); \ + char *getgr_buf = ALLOCA_N(char, (getgr_buf_len < 0 ? (getgr_buf_len = 4096) : getgr_buf_len)); +# define OBJ2GID(id) obj2gid((id), getgr_buf, getgr_buf_len) +static rb_gid_t obj2gid(VALUE id, char *getgr_buf, size_t getgr_buf_len); +# else +# define PREPARE_GETGRNAM /* do nothing */ +# define OBJ2GID(id) obj2gid((id)) +static rb_gid_t obj2gid(VALUE id); +# endif +#else +# define PREPARE_GETGRNAM /* do nothing */ +# define OBJ2GID(id) NUM2GIDT(id) +# ifdef p_gid_from_name +# undef p_gid_from_name +# define p_gid_from_name rb_f_notimplement +# endif +#endif + /* * call-seq: * Process.pid -> fixnum @@ -1664,6 +1713,38 @@ key = INT2FIX(2); goto redirect; } + else if (id == rb_intern("uid")) { +#ifdef HAVE_SETUID + if (eargp->uid_given) { + rb_raise(rb_eArgError, "uid option specified twice"); + } + check_uid_switch(); + { + PREPARE_GETPWNAM; + eargp->uid = OBJ2UID(val); + eargp->uid_given = 1; + } +#else + rb_raise(rb_eNotImpError, + "uid option is unimplemented on this machine"); +#endif + } + else if (id == rb_intern("gid")) { +#ifdef HAVE_SETGID + if (eargp->gid_given) { + rb_raise(rb_eArgError, "gid option specified twice"); + } + check_gid_switch(); + { + PREPARE_GETGRNAM; + eargp->gid = OBJ2GID(val); + eargp->gid_given = 1; + } +#else + rb_raise(rb_eNotImpError, + "gid option is unimplemented on this machine"); +#endif + } else { return ST_STOP; } @@ -2875,6 +2956,23 @@ } } +#ifdef HAVE_SETGID + if (eargp->gid_given) { + if (setgid(eargp->gid) < 0) { + ERRMSG("setgid"); + return -1; + } + } +#endif +#ifdef HAVE_SETUID + if (eargp->uid_given) { + if (setuid(eargp->uid) < 0) { + ERRMSG("setuid"); + return -1; + } + } +#endif + if (sargp) { VALUE ary = sargp->fd_dup2; if (ary != Qfalse) { @@ -4581,22 +4679,7 @@ * <code>Process::UID</code>, and <code>Process::GID</code> modules. */ -#if 1 -#define p_uid_from_name p_uid_from_name -#define p_gid_from_name p_gid_from_name -#endif - #if defined(HAVE_PWD_H) -# ifdef HAVE_GETPWNAM_R -# define PREPARE_GETPWNAM \ - long getpw_buf_len = sysconf(_SC_GETPW_R_SIZE_MAX); \ - char *getpw_buf = ALLOCA_N(char, (getpw_buf_len < 0 ? (getpw_buf_len = 4096) : getpw_buf_len)); -# define OBJ2UID(id) obj2uid((id), getpw_buf, getpw_buf_len) -# else -# define PREPARE_GETPWNAM /* do nothing */ -# define OBJ2UID(id) obj2uid((id)) -# endif - static rb_uid_t obj2uid(VALUE id # ifdef HAVE_GETPWNAM_R @@ -4642,26 +4725,9 @@ return UIDT2NUM(OBJ2UID(id)); } # endif -#else -# define PREPARE_GETPWNAM /* do nothing */ -# define OBJ2UID(id) NUM2UIDT(id) -# ifdef p_uid_from_name -# undef p_uid_from_name -# define p_uid_from_name rb_f_notimplement -# endif #endif #if defined(HAVE_GRP_H) -# ifdef HAVE_GETGRNAM_R -# define PREPARE_GETGRNAM \ - long getgr_buf_len = sysconf(_SC_GETGR_R_SIZE_MAX); \ - char *getgr_buf = ALLOCA_N(char, (getgr_buf_len < 0 ? (getgr_buf_len = 4096) : getgr_buf_len)); -# define OBJ2GID(id) obj2gid((id), getgr_buf, getgr_buf_len) -# else -# define PREPARE_GETGRNAM /* do nothing */ -# define OBJ2GID(id) obj2gid((id)) -# endif - static rb_gid_t obj2gid(VALUE id # ifdef HAVE_GETGRNAM_R @@ -4707,13 +4773,6 @@ return GIDT2NUM(OBJ2GID(id)); } # endif -#else -# define PREPARE_GETGRNAM /* do nothing */ -# define OBJ2GID(id) NUM2GIDT(id) -# ifdef p_gid_from_name -# undef p_gid_from_name -# define p_gid_from_name rb_f_notimplement -# endif #endif #if defined HAVE_SETUID Index: internal.h =================================================================== --- internal.h (revision 37123) +++ internal.h (revision 37124) @@ -203,9 +203,13 @@ unsigned chdir_given : 1; unsigned new_pgroup_given : 1; unsigned new_pgroup_flag : 1; + unsigned uid_given : 1; + unsigned gid_given : 1; rb_pid_t pgroup_pgid; /* asis(-1), new pgroup(0), specified pgroup (0<V). */ VALUE rlimit_limits; /* Qfalse or [[rtype, softlim, hardlim], ...] */ mode_t umask_mask; + rb_uid_t uid; + rb_gid_t gid; VALUE fd_dup2; VALUE fd_close; VALUE fd_open; Index: test/ruby/test_process.rb =================================================================== --- test/ruby/test_process.rb (revision 37123) +++ test/ruby/test_process.rb (revision 37124) @@ -1478,6 +1478,50 @@ assert_nothing_raised { IO.popen([*TRUECOMMAND, :new_pgroup=>true]) {} } end + def test_execopts_uid + feature6975 = '[ruby-core:47414]' + + [30000, [ENV["USER"], Process.uid]].each do |user, uid| + assert_nothing_raised(feature6975) do + begin + system(*TRUECOMMAND, uid: user) + rescue Errno::EPERM, NotImplementedError + end + end + + uid = "#{uid || user}" + assert_nothing_raised(feature6975) do + begin + u = IO.popen([RUBY, "-e", "print Process.uid", uid: user], &:read) + assert_equal(uid, u, feature6975) + rescue Errno::EPERM, NotImplementedError + end + end + end + end + + def test_execopts_gid + feature6975 = '[ruby-core:47414]' + + [30000, *Process.groups.map {|g| g = Etc.getgrgid(g); [g.name, g.gid]}].each do |group, gid| + assert_nothing_raised(feature6975) do + begin + system(*TRUECOMMAND, gid: group) + rescue Errno::EPERM, NotImplementedError + end + end + + gid = "#{gid || group}" + assert_nothing_raised(feature6975) do + begin + g = IO.popen([RUBY, "-e", "print Process.gid", gid: group], &:read) + assert_equal(gid, g, feature6975) + rescue Errno::EPERM, NotImplementedError + end + end + end + end + def test_sigpipe system(RUBY, "-e", "") with_pipe {|r, w| -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/