int setegid(gid_t egid) { struct Capability cap; OSCALLENTER(OSCALL_setegid); if (__current->egid == egid) return 0; /* Layout the desired capability */ cap.c_perm = CL_DUP | CL_W; cap.c_valid = 1; cap.c_isptr = 0; cap.c_len = egid ? 3 : 1; cap.c_name[0] = 2; cap.c_name[1] = egid >> 8; cap.c_name[2] = egid & 0xFF; /* Try to forge the new gid capability with CAP_GID */ if (sys_self_forge(CAP_GID, CAP_EGID, &cap) < 0) { errno = EPERM; OSCALLEXIT(OSCALL_setegid); return -1; } __current->egid = egid; OSCALLEXIT(OSCALL_setegid); return 0; }
int setuid(uid_t uid) { struct Capability cap; OSCALLENTER(OSCALL_setuid); /* Layout the desired capability */ cap.c_perm = CL_ALL; cap.c_valid = 1; cap.c_isptr = 0; cap.c_len = uid ? 3 : 1; cap.c_name[0] = 1; cap.c_name[1] = uid >> 8; cap.c_name[2] = uid & 0xFF; /* Try to forge the new uid capability with CAP_EUID */ if (sys_self_forge(CAP_EUID, CAP_SCRATCH, &cap) < 0) { /* Couldn't forge, are we just blowing away the euid? */ if (uid == __current->uid) { sys_self_forge(CAP_UID, CAP_EUID, &__curenv->env_clist[CAP_UID]); __current->euid = uid; __current->fsuid = uid; OSCALLEXIT(OSCALL_setuid); return 0; } else { errno = EPERM; OSCALLEXIT(OSCALL_setuid); return -1; } } /* CAP_SCRATCH is now a token for `cap', move this into euid and uid */ /* These can't fail since we just forged `cap' into CAP_SCRATCH */ sys_self_forge(CAP_SCRATCH, CAP_UID, &cap); sys_self_forge(CAP_SCRATCH, CAP_EUID, &cap); __current->uid = uid; __current->euid = uid; __current->fsuid = uid; OSCALLEXIT(OSCALL_setuid); return 0; }
int setgid(gid_t gid) { struct Capability cap; OSCALLENTER(OSCALL_setgid); /* Layout the desired capability */ cap.c_perm = CL_DUP | CL_W; cap.c_valid = 1; cap.c_isptr = 0; cap.c_len = gid ? 3 : 1; cap.c_name[0] = 2; cap.c_name[1] = gid >> 8; cap.c_name[2] = gid & 0xFF; /* Try to forge the new gid capability with CAP_EGID and CAP_EUID */ if (sys_self_forge(CAP_EGID, CAP_SCRATCH, &cap) < 0 && sys_self_forge(CAP_EUID, CAP_SCRATCH, &cap) < 0) { /* Couldn't forge, Use CAP_GID only if we are setting egid back to gid */ if (gid == __current->gid) { sys_self_forge(CAP_GID, CAP_EGID, &__curenv->env_clist[CAP_GID]); __current->egid = gid; OSCALLEXIT(OSCALL_setgid); return 0; } else { errno = EPERM; OSCALLEXIT(OSCALL_setgid); return -1; } } /* CAP_SCRATCH is now a token for `cap', move this into euid and uid */ /* These can't fail since we know CAP_SCRATCH dominates/equals `cap' */ sys_self_forge(CAP_SCRATCH, CAP_GID, &cap); sys_self_forge(CAP_SCRATCH, CAP_EGID, &cap); __current->gid = gid; __current->egid = gid; OSCALLEXIT(OSCALL_setgid); return 0; }
void InitCaps() { struct Capability cap; int r; /* clear cname */ bzero (cap.c_name, sizeof (cap.c_name)); /* JJJ Keep root capability here until we handle caps better. */ sys_self_forge(CAP_ENV, CAP_ROOT, &__curenv->env_clist[CAP_ENV]); cap.c_valid = 1; cap.c_isptr = 0; cap.c_len = 1; cap.c_perm = CL_ALL; cap.c_name[0] = CAP_NM_UID; sys_self_forge(CAP_ROOT, CAP_UID, &cap); sys_self_forge(CAP_ROOT, CAP_EUID, &cap); cap.c_perm = CL_DUP | CL_W; cap.c_name[0] = CAP_NM_GID; sys_self_forge(CAP_ROOT, CAP_GID, &cap); sys_self_forge(CAP_ROOT, CAP_EGID, &cap); cap.c_len = 3; cap.c_name[1] = 0; cap.c_name[2] = 0; sys_self_forge(CAP_ROOT, CAP_WORLD, &cap); sys_pgacl_setsize(CAP_ROOT, sys_read_pte(UADDR, CAP_ROOT, __envid, &r), 2); sys_pgacl_mod(CAP_ROOT, sys_read_pte(UADDR, CAP_ROOT, __envid, &r), 2, &cap); }