Module: Process::GID

Defined in:
process.c

Overview

The Process::GID module contains a collection of module functions which can be used to portably get, set, and switch the current process's real, effective, and saved group IDs.

Class Method Summary (collapse)

Class Method Details

+ (Fixnum) Process::GID.change_privilege(integer)

Change the current process's real and effective group ID to that specified by integer. Returns the new group ID. Not available on all platforms.

[Process.gid, Process.egid]          #=> [0, 0]
Process::GID.change_privilege(33)    #=> 33
[Process.gid, Process.egid]          #=> [33, 33]


# File 'process.c'

/*
 *  call-seq:
 *     Process::GID.change_privilege(integer)   -> fixnum
 *
 *  Change the current process's real and effective group ID to that
 *  specified by _integer_. Returns the new group ID. Not
 *  available on all platforms.
 *
 *     [Process.gid, Process.egid]          #=> [0, 0]
 *     Process::GID.change_privilege(33)    #=> 33
 *     [Process.gid, Process.egid]          #=> [33, 33]
 */

static VALUE
p_gid_change_privilege(VALUE obj, VALUE id)
{
    rb_gid_t gid;

    check_gid_switch();

    gid = NUM2GIDT(id);

    if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESGID)
    if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#elif defined HAVE_SETGID
    if (setgid(gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    if (getgid() == gid) {
        if (SAVED_GROUP_ID == gid) {
        if (setregid(-1, gid) < 0) rb_sys_fail(0);
        } else {
        if (gid == 0) { /* (r,e,s) == (root, y, x) */
            if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
            if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
            if (setregid(gid, gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        } else { /* (r,e,s) == (z, y, x) */
            if (setregid(0, 0) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = 0;
            if (setregid(gid, gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        }
        }
    } else {
        if (setregid(gid, gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
    }
#elif defined(HAVE_SETRGID) && defined (HAVE_SETEGID)
    if (getgid() == gid) {
        if (SAVED_GROUP_ID == gid) {
        if (setegid(gid) < 0) rb_sys_fail(0);
        } else {
        if (gid == 0) {
            if (setegid(gid) < 0) rb_sys_fail(0);
            if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = 0;
            if (setrgid(0) < 0) rb_sys_fail(0);
        } else {
            if (setrgid(0) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = 0;
            if (setegid(gid) < 0) rb_sys_fail(0);
            if (setrgid(gid) < 0) rb_sys_fail(0);
            SAVED_GROUP_ID = gid;
        }
        }
    } else {
        if (setegid(gid) < 0) rb_sys_fail(0);
        if (setrgid(gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
    }
#else
    rb_notimplement();
#endif
    } else { /* unprivileged user */
#if defined(HAVE_SETRESGID)
    if (setresgid((getgid() == gid)? -1: gid,
              (getegid() == gid)? -1: gid,
              (SAVED_GROUP_ID == gid)? -1: gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    if (SAVED_GROUP_ID == gid) {
        if (setregid((getgid() == gid)? -1: gid,
             (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
    } else if (getgid() != gid) {
        if (setregid(gid, (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
    } else if (/* getgid() == gid && */ getegid() != gid) {
        if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
        if (setregid(gid, -1) < 0) rb_sys_fail(0);
    } else { /* getgid() == gid && getegid() == gid */
        if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
        if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
        if (setregid(gid, -1) < 0) rb_sys_fail(0);
    }
#elif defined(HAVE_SETRGID) && defined(HAVE_SETEGID)
    if (SAVED_GROUP_ID == gid) {
        if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
        if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
    } else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
        if (getgid() != gid) {
        if (setrgid(gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
        } else {
        if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
        if (setrgid(gid) < 0) rb_sys_fail(0);
    }
    } else if (/* getegid() != gid && */ getgid() == gid) {
        if (setegid(gid) < 0) rb_sys_fail(0);
        if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
        if (setrgid(gid) < 0) rb_sys_fail(0);
    } else {
        errno = EPERM;
        rb_sys_fail(0);
    }
#elif defined HAVE_44BSD_SETGID
    if (getgid() == gid) {
        /* (r,e,s)==(gid,?,?) ==> (gid,gid,gid) */
        if (setgid(gid) < 0) rb_sys_fail(0);
        SAVED_GROUP_ID = gid;
    } else {
        errno = EPERM;
        rb_sys_fail(0);
    }
#elif defined HAVE_SETEGID
    if (getgid() == gid && SAVED_GROUP_ID == gid) {
        if (setegid(gid) < 0) rb_sys_fail(0);
    } else {
        errno = EPERM;
        rb_sys_fail(0);
    }
#elif defined HAVE_SETGID
    if (getgid() == gid && SAVED_GROUP_ID == gid) {
        if (setgid(gid) < 0) rb_sys_fail(0);
    } else {
        errno = EPERM;
        rb_sys_fail(0);
    }
#else
    rb_notimplement();
#endif
    }
    return id;
}

+ (Fixnum) egid + (Fixnum) Process::GID.eid + (Fixnum) Process::Sys.geteid

Returns the effective group ID for this process. Not available on all platforms.

Process.egid   #=> 500


# File 'process.c'

/*
 *  call-seq:
 *     Process.egid          -> fixnum
 *     Process::GID.eid      -> fixnum
 *     Process::Sys.geteid   -> fixnum
 *
 *  Returns the effective group ID for this process. Not available on
 *  all platforms.
 *
 *     Process.egid   #=> 500
 */

static VALUE
proc_getegid(VALUE obj)
{
    rb_gid_t egid = getegid();

    return GIDT2NUM(egid);
}

+ (Fixnum) Process::GID.grant_privilege(integer) + (Fixnum) Process::GID.eid( = integer)

Set the effective group ID, and if possible, the saved group ID of the process to the given integer. Returns the new effective group ID. Not available on all platforms.

[Process.gid, Process.egid]          #=> [0, 0]
Process::GID.grant_privilege(31)     #=> 33
[Process.gid, Process.egid]          #=> [0, 33]


# File 'process.c'

/*
 *  call-seq:
 *     Process::GID.grant_privilege(integer)    -> fixnum
 *     Process::GID.eid = integer               -> fixnum
 *
 *  Set the effective group ID, and if possible, the saved group ID of
 *  the process to the given _integer_. Returns the new
 *  effective group ID. Not available on all platforms.
 *
 *     [Process.gid, Process.egid]          #=> [0, 0]
 *     Process::GID.grant_privilege(31)     #=> 33
 *     [Process.gid, Process.egid]          #=> [0, 33]
 */

static VALUE
p_gid_grant_privilege(VALUE obj, VALUE id)
{
    rb_setegid_core(NUM2GIDT(id));
    return id;
}

+ (Fixnum) Process::GID.re_exchange

Exchange real and effective group IDs and return the new effective group ID. Not available on all platforms.

[Process.gid, Process.egid]   #=> [0, 33]
Process::GID.re_exchange      #=> 0
[Process.gid, Process.egid]   #=> [33, 0]


# File 'process.c'

/*
 *  call-seq:
 *     Process::GID.re_exchange   -> fixnum
 *
 *  Exchange real and effective group IDs and return the new effective
 *  group ID. Not available on all platforms.
 *
 *     [Process.gid, Process.egid]   #=> [0, 33]
 *     Process::GID.re_exchange      #=> 0
 *     [Process.gid, Process.egid]   #=> [33, 0]
 */

static VALUE
p_gid_exchange(VALUE obj)
{
    rb_gid_t gid, egid;

    check_gid_switch();

    gid = getgid();
    egid = getegid();

#if defined(HAVE_SETRESGID)
    if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    if (setregid(egid,gid) < 0) rb_sys_fail(0);
    SAVED_GROUP_ID = gid;
#else
    rb_notimplement();
#endif
    return GIDT2NUM(gid);
}

+ (Boolean) Process::GID.re_exchangeable?

Returns true if the real and effective group IDs of a process may be exchanged on the current platform.



# File 'process.c'

/*
 *  call-seq:
 *     Process::GID.re_exchangeable?   -> true or false
 *
 *  Returns +true+ if the real and effective group IDs of a
 *  process may be exchanged on the current platform.
 *
 */

static VALUE
p_gid_exchangeable(void)
{
#if defined(HAVE_SETRESGID)
    return Qtrue;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    return Qtrue;
#else
    return Qfalse;
#endif
}

+ (Fixnum) gid + (Fixnum) Process::GID.rid + (Fixnum) Process::Sys.getgid

Returns the (real) group ID for this process.

Process.gid   #=> 500


# File 'process.c'

/*
 *  call-seq:
 *     Process.gid           -> fixnum
 *     Process::GID.rid      -> fixnum
 *     Process::Sys.getgid   -> fixnum
 *
 *  Returns the (real) group ID for this process.
 *
 *     Process.gid   #=> 500
 */

static VALUE
proc_getgid(VALUE obj)
{
    rb_gid_t gid = getgid();
    return GIDT2NUM(gid);
}

+ (Boolean) Process::GID.sid_available?

Returns true if the current platform has saved group ID functionality.



# File 'process.c'

/*
 *  call-seq:
 *     Process::GID.sid_available?   -> true or false
 *
 *  Returns +true+ if the current platform has saved group
 *  ID functionality.
 *
 */

static VALUE
p_gid_have_saved_id(void)
{
#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS)
    return Qtrue;
#else
    return Qfalse;
#endif
}

+ (Fixnum) Process::GID.switch + (Object) Process::GID.switch { ... }

Switch the effective and real group IDs of the current process. If a block is given, the group IDs will be switched back after the block is executed. Returns the new effective group ID if called without a block, and the return value of the block if one is given.

Overloads:

  • + (Object) Process::GID.switch { ... }

    Yields:



# File 'process.c'

/*
 *  call-seq:
 *     Process::GID.switch              -> fixnum
 *     Process::GID.switch {|| block}   -> object
 *
 *  Switch the effective and real group IDs of the current process. If
 *  a <em>block</em> is given, the group IDs will be switched back
 *  after the block is executed. Returns the new effective group ID if
 *  called without a block, and the return value of the block if one
 *  is given.
 *
 */

static VALUE
p_gid_switch(VALUE obj)
{
    rb_gid_t gid, egid;

    check_gid_switch();

    gid = getgid();
    egid = getegid();

    if (gid != egid) {
    proc_setegid(obj, GIDT2NUM(gid));
    if (rb_block_given_p()) {
        under_gid_switch = 1;
        return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID);
    } else {
        return GIDT2NUM(egid);
    }
    }
    else if (egid != SAVED_GROUP_ID) {
    proc_setegid(obj, GIDT2NUM(SAVED_GROUP_ID));
    if (rb_block_given_p()) {
        under_gid_switch = 1;
        return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid);
    } else {
        return GIDT2NUM(gid);
    }
    }
    else {
    errno = EPERM;
    rb_sys_fail(0);
    }
}