int main(int argc, char *argv[]) { int error; fprintf(stderr, "test capabilities: "); #ifdef SETSUGID_SUPPORTED fprintf(stderr, "[SETSUGID_SUPPORTED] "); #endif #ifdef SETSUGID_SUPPORTED_BUT_NO_LIBC_STUB fprintf(stderr, "[SETSUGID_SUPPORTED_BUT_NO_LIBC_STUB] "); #endif #ifdef CHECK_CRED_SET fprintf(stderr, "[CHECK_CRED_SET] "); #endif fprintf(stderr, "\n"); error = setugid(1); if (error) { perror("setugid"); fprintf(stderr, "This test suite requires options REGRESSION\n"); return (-1); } enact_scenarios(); return (0); }
/* * create a file and send fd on success * return -errno on error */ static int do_create(struct iovec *iovec) { int ret; V9fsString path; int flags, mode, uid, gid, cur_uid, cur_gid; v9fs_string_init(&path); ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, "sdddd", &path, &flags, &mode, &uid, &gid); if (ret < 0) { goto unmarshal_err_out; } ret = setugid(uid, gid, &cur_uid, &cur_gid); if (ret < 0) { goto unmarshal_err_out; } ret = open(path.data, flags, mode); if (ret < 0) { ret = -errno; } resetugid(cur_uid, cur_gid); unmarshal_err_out: v9fs_string_free(&path); return ret; }
/* * Set the current process's credentials to match the passed credential. */ static int cred_set(struct cred *cred) { int error; error = setresuid(cred->cr_ruid, cred->cr_euid, cred->cr_svuid); if (error) return (error); error = setugid(cred->cr_issetugid); if (error) { perror("__setugid"); return (error); } #ifdef CHECK_CRED_SET { uid_t ruid, euid, svuid; error = getresuid(&ruid, &euid, &svuid); if (error) { perror("getresuid"); return (-1); } assert(ruid == cred->cr_ruid); assert(euid == cred->cr_euid); assert(svuid == cred->cr_svuid); assert(cred->cr_issetugid == issetugid()); } #endif /* !CHECK_CRED_SET */ return (0); }
/* * create other filesystem objects and send 0 on success * return -errno on error */ static int do_create_others(int type, struct iovec *iovec) { dev_t rdev; int retval = 0; int offset = PROXY_HDR_SZ; V9fsString oldpath, path; int mode, uid, gid, cur_uid, cur_gid; v9fs_string_init(&path); v9fs_string_init(&oldpath); retval = proxy_unmarshal(iovec, offset, "dd", &uid, &gid); if (retval < 0) { return retval; } offset += retval; retval = setugid(uid, gid, &cur_uid, &cur_gid); if (retval < 0) { goto unmarshal_err_out; } switch (type) { case T_MKNOD: retval = proxy_unmarshal(iovec, offset, "sdq", &path, &mode, &rdev); if (retval < 0) { goto err_out; } retval = mknod(path.data, mode, rdev); break; case T_MKDIR: retval = proxy_unmarshal(iovec, offset, "sd", &path, &mode); if (retval < 0) { goto err_out; } retval = mkdir(path.data, mode); break; case T_SYMLINK: retval = proxy_unmarshal(iovec, offset, "ss", &oldpath, &path); if (retval < 0) { goto err_out; } retval = symlink(oldpath.data, path.data); break; } if (retval < 0) { retval = -errno; } err_out: resetugid(cur_uid, cur_gid); unmarshal_err_out: v9fs_string_free(&path); v9fs_string_free(&oldpath); return retval; }