"Fossies" - the Fresh Open Source Software Archive

Member "pidentd-3.0.19/src/k_osf5.c" (23 Apr 2001, 10071 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_osf5.c" see the Fossies "Dox" file reference documentation.

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