pidentd  3.0.19
About: implementation of the RFC1413 identification server (more or less complete rewrite compared to version 2)
  Fossies Dox: pidentd-3.0.19.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

k_osf4.c
Go to the documentation of this file.
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 }
pid_entry::peu_s
struct pid_entry::@0::@1 peu_s
s_free
void s_free(void *p)
Definition: safeio.c:153
kainfo
Definition: k_aix42.c:73
N_NPID
#define N_NPID
Definition: k_osf4.c:124
ka_init
int ka_init(void)
Definition: k_osf4.c:134
pid_entry::pe_un
union pid_entry::@0 pe_un
pid_entry::peus_sess
int peus_sess
Definition: k_osf4.c:103
f_s
#define f_s
kvm_nlist
int kvm_nlist(kvm_t *kd, struct nlist *nl)
pidentd.h
kernel::remote
struct sockaddr_gen remote
Definition: kernel.h:29
kvm_t
Definition: pkvm.h:18
kainfo::kd
int kd
Definition: k_aix42.c:75
the_proc
#define the_proc
ka_lookup
int ka_lookup(void *vp, struct kernel *kp)
Definition: k_osf4.c:190
kernel::local
struct sockaddr_gen local
Definition: kernel.h:28
badr
#define badr(k, addr, buf, len)
pid_entry::peu_nxt
struct pid_entry * peu_nxt
Definition: k_osf4.c:100
s_malloc
void * s_malloc(size_t size)
Definition: safeio.c:132
pid_entry::peus_pgrp
int peus_pgrp
Definition: k_osf4.c:102
N_PIDTAB
#define N_PIDTAB
Definition: k_osf4.c:123
PID_INVALID
#define PID_INVALID(pid)
Definition: k_osf4.c:109
p_i
#define p_i
kernel::euid
uid_t euid
Definition: kernel.h:35
kvm_close
int kvm_close(kvm_t *kd)
osinfo_get
char * osinfo_get(char *buf)
Definition: support.c:39
kvm_open
kvm_t * kvm_open(const char *namelist, const char *corefile, const char *swapfile, int flag, const char *errstr)
debug
int debug
Definition: gen_osinfo.c:23
kernel::ruid
uid_t ruid
Definition: kernel.h:36
pid_entry::pe_pid
pid_t pe_pid
Definition: k_osf4.c:96
ka_open
int ka_open(void **misc)
Definition: k_osf4.c:149
kernel::pid
pid_t pid
Definition: kernel.h:38
NOFILE_IN_U
#define NOFILE_IN_U
Definition: k_osf4.c:118
pkvm.h
pid_entry::pe_proc
struct proc * pe_proc
Definition: k_osf4.c:98
INVALID_UID
#define INVALID_UID(uid)
Definition: k_osf4.c:112
osinfo_build
char osinfo_build[]
kernel
Definition: kernel.h:25
pid_entry
Definition: k_osf4.c:95
pid_entry::pe_generation
int pe_generation
Definition: k_osf4.c:97
kainfo::nl
struct nlist nl[4]
Definition: k_bsd42.c:74