2.11BSD/src/libexec/identd/src/kernel/uw2.c
/*
** kernel/uw2.c UnixWare v2.x specific kernel access functions
**
**
** Last update: 28 Nov 1995
**
** Please send mods/bug fixes/bug reports to: Paul F. Wells <paul@wellserv.com>
**
*/
#define _KMEMUSER
#include <sys/types.h>
#include <sys/ksynch.h>
#include <sys/flock.h>
#include <sys/pid.h>
#include <sys/var.h>
#include <sys/proc.h>
#include <sys/cred.h>
#include <sys/session.h>
#include <sys/socket.h>
#include <sys/strsubr.h>
#include <net/route.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp_kern.h>
#include <sys/fs/snode.h>
#include <sys/stat.h>
#include <sys/mkdev.h>
#undef _KMEMUSER
#include <sys/ksym.h>
#include <sys/sysmacros.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "paths.h"
#include "kvm.h"
#include "identd.h"
#include "error.h"
#include <stdio.h> /* this kinda reeks */
#ifndef TRUE
enum { FALSE, TRUE };
#endif
static kvm_t *kd;
int k_open()
{
/*
** Open the kernel memory device
*/
if (!(kd = kvm_open(path_unix, path_kmem, NULL, O_RDONLY, NULL)))
ERROR("main: kvm_open");
#ifndef UW2 /* don't really need this */
/*
** Extract offsets to the needed variables in the kernel
*/
if (kvm_nlist(kd, nl) != 0)
ERROR("main: kvm_nlist");
#endif
return 0;
}
/*
** Get a piece of kernel memory with error handling.
** Returns 1 if call succeeded, else 0 (zero).
*/
static int
getbuf(long addr,void *buf,int len,char *what)
{
if (kvm_read(kd, addr, buf, len) < 0) {
if (syslog_flag)
syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
addr, len, what);
return 0;
}
return 1;
}
int
k_getuid(struct in_addr *faddr,int fport,struct in_addr *laddr,int lport,int *uid)
{
int gotit;
ulong_t info;
struct stat tcpstat;
dev_t tcp_clone;
minor_t tcp_minor;
snode_t **snode_base, *snodep, spec_node;
int snode_hash;
vnode_t *vnodep;
struct inpcb pcb, *tcb_first;
proc_t *proc_head, *procp, uproc;
int maxfd;
int ifdt, fdtable_len;
fd_entry_t *fdp;
file_t *filep, file_entry;
cred_t creds;
/* initialize & find pcb for specified connection */
if (stat("/dev/tcp", &tcpstat) != 0)
return -1;
tcp_minor = minor(tcpstat.st_rdev);
info = 0;
tcb_first = NULL;
if (getksym("tcb", (ulong_t *) &tcb_first, &info) < 0)
return -1;
for (gotit = FALSE, pcb.inp_prev = tcb_first; ; ) {
/* why do we have to go backward? */
if (!getbuf((long) pcb.inp_prev, &pcb, sizeof(pcb), "inp_prev"))
return -1;
if (
pcb.inp_faddr.s_addr == faddr->s_addr &&
pcb.inp_laddr.s_addr == laddr->s_addr &&
pcb.inp_fport == fport &&
pcb.inp_lport == lport
) {
/* I screwed up: 2.01 allowed makedev() */
tcp_clone = makedevice(tcp_minor, pcb.inp_minor);
gotit = TRUE;
break;
}
if (pcb.inp_prev == NULL || pcb.inp_prev == tcb_first) break;
}
if (!gotit) return -1;
/* now crawl through snodes to find vnode of clone device */
info = 0;
snode_base = NULL;
if (getksym("spectable", (ulong_t *) &snode_base, &info) < 0)
return -1;
snode_hash = SPECTBHASH(tcp_clone);
if (!getbuf((long) (snode_base + snode_hash), &snodep, sizeof(snodep), "snode_hash"))
return -1;
for (gotit = FALSE; snodep != NULL ; snodep = spec_node.s_next) {
if (!getbuf((long) snodep, &spec_node, sizeof(spec_node), "snodep"))
return -1;
if (spec_node.s_dev == tcp_clone) {
vnodep = (vnode_t *) ((char *) snodep + offsetof(struct snode, s_vnode));
gotit = TRUE;
break;
}
}
if (!gotit || (spec_node.s_flag & SINVALID)) return -1;
/* find process with this vnode */
info = 0;
procp = NULL;
if (getksym("practive", (ulong_t *) &procp, &info) < 0)
return -1;
if (!getbuf((long) procp, &proc_head, sizeof(proc_head), "practive"))
return -1;
for (gotit = FALSE, procp = proc_head; procp != NULL; procp = uproc.p_next) {
if (!getbuf((long) procp, &uproc, sizeof(uproc), "procp"))
return -1;
if((maxfd = uproc.p_fdtab.fdt_sizeused) == 0) continue;
fdtable_len = maxfd * sizeof(fd_entry_t);
if ((fdp = (fd_entry_t *) malloc(fdtable_len)) == NULL)
return -1;
if (!getbuf((long) uproc.p_fdtab.fdt_entrytab, fdp, fdtable_len, "fdt_entrytab")) {
free(fdp);
return -1;
}
for (ifdt = 0; ifdt < maxfd; ifdt++) {
if (fdp[ifdt].fd_status != FD_INUSE) continue;
filep = fdp[ifdt].fd_file;
if (!getbuf((long) filep, &file_entry, sizeof(file_entry), "filep")) {
free(fdp);
return -1;
}
if (vnodep == file_entry.f_vnode) {
if (file_entry.f_cred != NULL) {
if (!getbuf((long) file_entry.f_cred, &creds, sizeof(creds), "f_cred")) {
free(fdp);
return -1;
}
free(fdp);
gotit = TRUE;
goto got_proc;
}
}
}
free(fdp);
}
got_proc: ; /* maybe */
if (!gotit) return -1;
/* wow! */
*uid = creds.cr_ruid;
return 0;
}