In Files

  • process.c

Process::GID

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.

Public Class Methods

Process::GID.change_privilege(integer) => fixnum click to toggle source

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;
}
            
egid => fixnum click to toggle source
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);
}
            
Process::GID.grant_privilege(integer) => fixnum click to toggle source
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;
}
            
Process::GID.re_exchange => fixnum click to toggle source

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) &&  !defined(__CHECKER__)
    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);
}
            
Process::GID.re_exchangeable? => true or false click to toggle source

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) &&  !defined(__CHECKER__)
    return Qtrue;
#elif defined(HAVE_SETREGID) && !defined(OBSOLETE_SETREGID)
    return Qtrue;
#else
    return Qfalse;
#endif
}
            
gid => fixnum click to toggle source
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);
}
            
Process::GID.sid_available? => true or false click to toggle source

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
}
            
Process::GID.switch => fixnum click to toggle source
Process::GID.switch {|| block} => object

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.

 
               static VALUE
p_gid_switch(VALUE obj)
{
    int 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);
    }
}