"Fossies" - the Fresh Open Source Software Archive

Member "pidentd-3.0.19/src/k_osf4.c" (20 Jan 1999, 10184 Bytes) of package /linux/misc/old/pidentd-3.0.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "k_osf4.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** k_osf4.c - Digital Unix / OSF/1 4.0 kernel access functions
    3 **
    4 ** Copyright (c) 1997-1998 Peter Eriksson <pen@lysator.liu.se>
    5 **
    6 ** This program is free software; you can redistribute it and/or
    7 ** modify it as you wish - as long as you don't claim that you wrote
    8 ** it.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   13 */
   14 
   15 /*
   16  * 16 Apr 96 - Changes by Paul Szabo <psz@maths.usyd.edu.au>
   17  *
   18  * May 23, 1994 - Modified by Allan E. Johannesen (aej@wpi.edu) from code
   19  * kindly provided by Digital during the Beta test of Digital Alpha AXP OSF/1
   20  * 3.0 when WPI discovered that the file structures had changed.  Prior to 3.0,
   21  * OSF/1 ident support had only needed 64-bit modifications to the `other.c'
   22  * kernel routine (those mods done at WPI during the initial OSF/1 Beta tests).
   23  *
   24  * NOTE:
   25  *   This tool is NOT part of DEC OSF/1 and is NOT a supported product.
   26  *
   27  * BASED ON code provided by
   28  *   Aju John, UEG, Digital Equipment Corp. (ZK3) Nashua, NH.
   29  *
   30  * The following is an **unsupported** tool. Digital Equipment Corporation
   31  * makes no representations about the suitability of the software described
   32  * herein for any purpose. It is provided "as is" without express or implied
   33  * warranty.
   34  *
   35  * BASED ON:
   36  *  PADS program by Stephen Carpenter, UK UNIX Support, Digital Equipment Corp.
   37  * */
   38 
   39 /*
   40  * Multiple, almost simultaneous identd requests were causing a
   41  * 'kernel panic' crash on our 2-CPU 2100 server running OSF 3.2C
   42  * (though no such problems were seen on Alphastations). We were
   43  * initially told to try patch 158. When that did not cure the
   44  * problem, Digital service came up with the following on 9 May 96:
   45  *
   46  * > The following came from an outage in the states about the same thing.
   47  * > 
   48  * > The active program was "identd" which is a freeware
   49  * > program that identifies the user who is opening a port on the system.
   50  * > 
   51  * > Careful analysis shows that the identd program is causing the crash by
   52  * > seeking to an invalid address in /dev/kmem. The program, identd reads
   53  * > through /dev/kmem looking for open files that are sockets, which then send
   54  * > pertainent information back to the other end. In this case, the socket has
   55  * > gone away before the read has been performed thereby causing a panic.
   56  * > 
   57  * > identd reading /dev/kmem, causing a fault on the  kernel stack guard pages
   58  * > which in turn cause the kernel to panic. To fix  this problem, set the
   59  * > following in /etc/sysconfigtab:
   60  * > 
   61  * > vm:
   62  * >         kernel-stack-guard-pages = 0
   63  * > 
   64  * > could you try this and see if that fixes your problem.
   65  *
   66  * This has fixed our problem, though I am worried what other
   67  * effects this may have.
   68  */
   69 
   70 #include "config.h"
   71 
   72 #include <stdlib.h>
   73 #include <stdio.h>
   74 #include <syslog.h>
   75 #include <nlist.h>
   76 #include <sys/types.h>
   77 #define SHOW_UTT
   78 #include <sys/user.h>
   79 #define KERNEL_FILE
   80 #include <sys/file.h>
   81 #include <sys/proc.h>
   82 #include <sys/socket.h>
   83 #include <sys/socketvar.h>
   84 #include <net/route.h>
   85 #include <netinet/in.h>
   86 #include <netinet/ip.h>
   87 #include <netinet/in_pcb.h>
   88 
   89 #include "pkvm.h"
   90 
   91 #include "pidentd.h"
   92 
   93 
   94 /* The following is in <sys/proc.h>, but only if _KERNEL is defined */
   95 struct pid_entry {
   96     pid_t   pe_pid;                /* process id */
   97     int     pe_generation;         /* checks for struct re-use */
   98     struct proc *pe_proc;          /* pointer to this pid's proc */
   99     union {
  100     struct pid_entry *peu_nxt;     /* next entry in free list */
  101     struct {
  102         int     peus_pgrp;     /* pid is pgrp leader? */
  103         int     peus_sess;     /* pid is session leader? */
  104     } peu_s;
  105     } pe_un;
  106 };
  107 
  108 /* The following is in <sys/proc.h>, but only if _KERNEL is defined */
  109 #define PID_INVALID(pid) ((pid_t)(pid) < 0 || (pid_t)(pid) > (pid_t)PID_MAX)
  110 
  111 /* The following is in <sys/ucred.h>, but only if _KERNEL is defined */
  112 #define INVALID_UID(uid) ((uid_t)(uid) < 0 || (uid_t)(uid) > (uid_t)UID_MAX)
  113 
  114 
  115 #ifdef NOFILE_IN_U      /* more than 64 open files per process ? */
  116 #  define OFILE_EXTEND
  117 #else
  118 #  define NOFILE_IN_U NOFILE
  119 #endif
  120 
  121 #define BUFLEN 1024 /* buffer length */
  122 
  123 #define N_PIDTAB 0
  124 #define N_NPID 1
  125 
  126 
  127 struct kainfo
  128 {
  129     kvm_t *kd;
  130     struct nlist nl[3];
  131 };
  132 
  133 int
  134 ka_init(void)
  135 {
  136     char osinfo_current[256];
  137 
  138     if (osinfo_get(osinfo_current) == NULL)
  139     return -1;
  140 
  141     return strcmp(osinfo_build, osinfo_current);
  142 }
  143 
  144 
  145 /*
  146 ** Open kernel devices, lookup kernel symbols etc...
  147 */
  148 int
  149 ka_open(void **misc)
  150 {
  151     struct kainfo *kp;
  152 
  153 
  154     kp = s_malloc(sizeof(*kp));
  155     
  156     /*
  157     ** Open the kernel memory device
  158     */
  159     if ((kp->kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
  160     {
  161     syslog(LOG_ERR, "kvm_open: %m");
  162     s_free(kp);
  163     return -1;
  164     }
  165     
  166     kp->nl[0].n_name = "_pidtab";
  167     kp->nl[1].n_name = "_npid";
  168     kp->nl[2].n_name = NULL;
  169     
  170     /*
  171     ** Extract offsets to the needed variables in the kernel
  172     */
  173     if (kvm_nlist(kp->kd, kp->nl) != 0)
  174     {
  175     syslog(LOG_ERR, "kvm_nlist: %m");
  176     kvm_close(kp->kd);
  177     s_free(kp);
  178     return -1;
  179     }
  180 
  181     *misc = (void *) kp;
  182     return 0;
  183 }
  184 
  185 
  186 /*
  187 ** Return the user number for the connection owner
  188 */
  189 int
  190 ka_lookup(void *vp, struct kernel *kp)
  191 {
  192     struct kainfo *kip;
  193     kvm_t *kd;
  194     struct nlist *name_list;
  195     
  196     struct in_addr *faddr;
  197     int fport;
  198     struct in_addr *laddr;
  199     int lport;
  200 
  201     off_t pidtab_base;  /* Start address of the process table */
  202     int npid;       /* Number of processes in the process table */
  203     
  204     struct proc_plus_utask {
  205     struct proc The_Proc;
  206     struct utask Proc_Utask;
  207     } pu;
  208     
  209     struct pid_entry *the_pid_entry = NULL;
  210     struct file **ofile_table_extension = NULL, open_file;
  211     int index, index1;
  212     
  213 #define the_proc pu.The_Proc
  214 #define proc_utask pu.Proc_Utask
  215 #define p_i the_pid_entry[index]
  216 #define f_s proc_utask.uu_file_state
  217 
  218 
  219 /* Just to save us some typing: we ALWAYS test return from kvm_read */
  220 #define goodr(k,addr,buf,len) (kvm_read(k,addr,buf,len) == len)
  221 #define badr(k,addr,buf,len)  (kvm_read(k,addr,buf,len) != len)
  222 
  223     kip = (struct kainfo *) vp;
  224     kd = kip->kd;
  225     name_list = kip->nl;
  226     
  227     faddr = &kp->remote.sin_addr;
  228     laddr = &kp->local.sin_addr;
  229     fport = kp->remote.sin_port;
  230     lport = kp->local.sin_port;
  231     
  232 #ifdef OFILE_EXTEND
  233     /* Reserve space for the extended open file table of a process */
  234     ofile_table_extension = s_malloc((getdtablesize ())
  235                      * sizeof(struct file *));
  236 #endif
  237 
  238     if (debug)
  239     {
  240     fprintf (stderr, "Looking up faddr %08x  fport %d\n",
  241          faddr->s_addr, fport);
  242     fprintf (stderr, "           laddr %08x  lport %d\n",
  243          laddr->s_addr, lport);
  244     }
  245     
  246     /* Find the start of the process table */
  247     if (badr(kd, (off_t) name_list[N_PIDTAB].n_value,
  248          &pidtab_base, sizeof(pidtab_base)))
  249     {
  250     syslog(LOG_INFO, "Cannot read pidtab_base");
  251     goto Fail;
  252     }
  253     
  254     /* Find the size of the process table */
  255     if (badr(kd, (off_t) name_list[N_NPID].n_value, &npid, sizeof(npid)))
  256     {
  257     syslog(LOG_INFO, "Cannot read npid");
  258     goto Fail;
  259     }
  260     
  261     if (debug)
  262     fprintf (stderr, "Number of processes: %d\n", npid);
  263     
  264     /* Read in the process structure */
  265     the_pid_entry = s_malloc(sizeof(struct pid_entry) * npid);
  266     
  267     if (badr(kd, pidtab_base, the_pid_entry, sizeof(struct pid_entry) * npid))
  268     {
  269     syslog(LOG_INFO, "Cannot read process structure");
  270     goto Fail;
  271     }
  272     
  273     for (index = 0; index < npid; index++)
  274     {
  275     if (p_i.pe_proc == 0)
  276         continue;
  277 
  278     if (PID_INVALID(p_i.pe_pid))
  279         continue;
  280         
  281     /* Read in the proc and utask structs of the process */
  282     if (badr(kd, (off_t) p_i.pe_proc, &pu, sizeof(pu)))
  283         continue;
  284 
  285     if (p_i.pe_pid != the_proc.p_pid)
  286         continue;
  287 
  288     if (INVALID_UID(the_proc.p_ruid))
  289         continue;
  290     
  291     if (debug > 1)
  292         fprintf (stderr, "Looking at proc slot %d: PID %d, UID %d\n", index,
  293             the_proc.p_pid, the_proc.p_ruid);
  294     
  295     /* Sanity checks */
  296     if (f_s.uf_lastfile < 0)
  297         continue;
  298 
  299     if (f_s.uf_lastfile + 1 > getdtablesize())
  300         continue;
  301     
  302 #ifdef OFILE_EXTEND
  303     if (f_s.uf_lastfile >= NOFILE_IN_U)
  304     {
  305         if (f_s.uf_of_count > getdtablesize())
  306         continue;
  307         
  308         if (badr(kd, (off_t) f_s.uf_ofile_of, ofile_table_extension,
  309              f_s.uf_of_count * sizeof(struct file *)))
  310         continue;
  311     }
  312 #endif
  313 
  314     if (debug > 1)
  315         fprintf (stderr, "proc slot %d uses %d files\n", index, f_s.uf_lastfile);
  316 
  317     
  318     for (index1 = 0; index1 <= f_s.uf_lastfile; index1++)
  319     {
  320         if (index1 < NOFILE_IN_U)
  321         {
  322         if (f_s.uf_ofile[index1] == NULL)
  323             continue;
  324         if (f_s.uf_ofile[index1] == (struct file *) -1)
  325             continue;
  326         
  327         if (badr(kd, (off_t) f_s.uf_ofile[index1],
  328              &open_file, sizeof(open_file)))
  329             continue;
  330         }
  331 #ifdef OFILE_EXTEND
  332         else
  333         {
  334         if (ofile_table_extension[index1-NOFILE_IN_U] == NULL)
  335             continue;
  336 
  337         if (badr(kd,
  338              (off_t) ofile_table_extension[index1-NOFILE_IN_U],
  339              &open_file, sizeof(open_file)))
  340             continue;
  341         }
  342 #endif
  343         
  344         if (debug > 2)
  345         fprintf (stderr, "Looking at proc slot %d, file %d\n", index, index1);
  346         
  347         if (open_file.f_type == DTYPE_SOCKET)
  348         {
  349         struct socket try_socket;
  350         struct inpcb try_pcb;
  351         
  352         if (badr(kd, (off_t) open_file.f_data,
  353              &try_socket, sizeof(try_socket)))
  354             continue;
  355         
  356         if (try_socket.so_pcb != NULL)
  357         {
  358             if (badr(kd, (off_t) try_socket.so_pcb,
  359                  &try_pcb, sizeof(try_pcb)))
  360             continue;
  361 
  362             if (debug > 2)
  363             fprintf (stderr, "\tSocket: %x:%d - %x:%d\n",
  364                  try_pcb.inp_faddr.s_addr,
  365                  try_pcb.inp_fport,
  366                  try_pcb.inp_laddr.s_addr,
  367                  try_pcb.inp_lport);
  368             
  369             if (try_pcb.inp_faddr.s_addr == faddr->s_addr &&
  370             try_pcb.inp_laddr.s_addr == laddr->s_addr &&
  371             try_pcb.inp_fport        == fport &&
  372             try_pcb.inp_lport        == lport)
  373             {
  374             kp->ruid = the_proc.p_ruid;
  375             kp->euid = the_proc.p_svuid;
  376             kp->pid  = the_proc.p_pid;
  377             
  378             s_free(ofile_table_extension);
  379             s_free(the_pid_entry);
  380             return 1;
  381             }
  382         }
  383         }
  384     }
  385     }
  386     
  387     s_free(ofile_table_extension);
  388     s_free(the_pid_entry);
  389     return 0;
  390     
  391   Fail:
  392     s_free(ofile_table_extension);
  393     s_free(the_pid_entry);
  394     return -1;
  395 }