1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 /*
  29  * lxprsubr.c: Various functions for the /lxproc vnodeops.
  30  */
  31 
  32 #include <sys/varargs.h>
  33 
  34 #include <sys/cpuvar.h>
  35 #include <sys/mman.h>
  36 #include <sys/vmsystm.h>
  37 #include <sys/prsystm.h>
  38 
  39 #include "lx_proc.h"
  40 
  41 #define LXPRCACHE_NAME "lxpr_cache"
  42 
  43 static int lxpr_node_constructor(void*, void*, int);
  44 static void lxpr_node_destructor(void*, void*);
  45 
  46 static kmem_cache_t *lxpr_node_cache;
  47 
  48 struct lxpr_uiobuf {
  49         uio_t *uiop;
  50         char *buffer;
  51         uint32_t buffsize;
  52         char *pos;
  53         size_t beg;
  54         int error;
  55 };
  56 
  57 #define BUFSIZE 4000
  58 
  59 struct lxpr_uiobuf *
  60 lxpr_uiobuf_new(uio_t *uiop)
  61 {
  62         /* Allocate memory for both lxpr_uiobuf and output buffer */
  63         struct lxpr_uiobuf *uiobuf =
  64             kmem_alloc(sizeof (struct lxpr_uiobuf) + BUFSIZE, KM_SLEEP);
  65 
  66         uiobuf->uiop = uiop;
  67         uiobuf->buffer = (char *)&uiobuf[1];
  68         uiobuf->buffsize = BUFSIZE;
  69         uiobuf->pos = uiobuf->buffer;
  70         uiobuf->beg = 0;
  71         uiobuf->error = 0;
  72 
  73         return (uiobuf);
  74 }
  75 
  76 void
  77 lxpr_uiobuf_free(struct lxpr_uiobuf *uiobuf)
  78 {
  79         ASSERT(uiobuf != NULL);
  80         ASSERT(uiobuf->pos == uiobuf->buffer);
  81 
  82         kmem_free(uiobuf, sizeof (struct lxpr_uiobuf) + uiobuf->buffsize);
  83 }
  84 
  85 void
  86 lxpr_uiobuf_seek(struct lxpr_uiobuf *uiobuf, offset_t offset)
  87 {
  88         uiobuf->uiop->uio_offset = offset;
  89 }
  90 
  91 void
  92 lxpr_uiobuf_seterr(struct lxpr_uiobuf *uiobuf, int err)
  93 {
  94         ASSERT(uiobuf->error == 0);
  95 
  96         uiobuf->error = err;
  97 }
  98 
  99 int
 100 lxpr_uiobuf_flush(struct lxpr_uiobuf *uiobuf)
 101 {
 102         off_t off = uiobuf->uiop->uio_offset;
 103         caddr_t uaddr = uiobuf->buffer;
 104         size_t beg = uiobuf->beg;
 105 
 106         size_t size = uiobuf->pos - uaddr;
 107 
 108         if (uiobuf->error == 0 && uiobuf->uiop->uio_resid != 0) {
 109                 ASSERT(off >= beg);
 110 
 111                 if (beg+size > off && off >= 0)
 112                         uiobuf->error =
 113                             uiomove(uaddr+(off-beg), size-(off-beg),
 114                             UIO_READ, uiobuf->uiop);
 115 
 116                 uiobuf->beg += size;
 117         }
 118 
 119         uiobuf->pos = uaddr;
 120 
 121         return (uiobuf->error);
 122 }
 123 
 124 void
 125 lxpr_uiobuf_write(struct lxpr_uiobuf *uiobuf, const char *buf, size_t size)
 126 {
 127         /* While we can still carry on */
 128         while (uiobuf->error == 0 && uiobuf->uiop->uio_resid != 0) {
 129                 uint_t remain
 130                     = uiobuf->buffsize-(uiobuf->pos-uiobuf->buffer);
 131 
 132                 /* Enough space in buffer? */
 133                 if (remain >= size) {
 134                         bcopy(buf, uiobuf->pos, size);
 135                         uiobuf->pos += size;
 136                         return;
 137                 }
 138 
 139                 /* Not enough space, so copy all we can and try again */
 140                 bcopy(buf, uiobuf->pos, remain);
 141                 uiobuf->pos += remain;
 142                 (void) lxpr_uiobuf_flush(uiobuf);
 143                 buf += remain;
 144                 size -= remain;
 145         }
 146 }
 147 
 148 #define TYPBUFFSIZE 256
 149 void
 150 lxpr_uiobuf_printf(struct lxpr_uiobuf *uiobuf, const char *fmt, ...)
 151 {
 152         va_list args;
 153         char buff[TYPBUFFSIZE];
 154         int len;
 155         char *buffer;
 156 
 157         /* Can we still do any output */
 158         if (uiobuf->error != 0 || uiobuf->uiop->uio_resid == 0)
 159                 return;
 160 
 161         va_start(args, fmt);
 162 
 163         /* Try using stack allocated buffer */
 164         len = vsnprintf(buff, TYPBUFFSIZE, fmt, args);
 165         if (len < TYPBUFFSIZE) {
 166                 va_end(args);
 167                 lxpr_uiobuf_write(uiobuf, buff, len);
 168                 return;
 169         }
 170 
 171         /* Not enough space in pre-allocated buffer */
 172         buffer = kmem_alloc(len+1, KM_SLEEP);
 173 
 174         /*
 175          * We know we allocated the correct amount of space
 176          * so no check on the return value
 177          */
 178         (void) vsnprintf(buffer, len+1, fmt, args);
 179         lxpr_uiobuf_write(uiobuf, buffer, len);
 180         va_end(args);
 181         kmem_free(buffer, len+1);
 182 }
 183 
 184 /*
 185  * lxpr_lock():
 186  *
 187  * Lookup process from pid and return with p_plock and P_PR_LOCK held.
 188  */
 189 proc_t *
 190 lxpr_lock(pid_t pid)
 191 {
 192         proc_t *p;
 193         kmutex_t *mp;
 194 
 195         ASSERT(!MUTEX_HELD(&pidlock));
 196 
 197         for (;;) {
 198                 mutex_enter(&pidlock);
 199 
 200                 /*
 201                  * If the pid is 1, we really want the zone's init process
 202                  */
 203                 p = prfind((pid == 1) ?
 204                     curproc->p_zone->zone_proc_initpid : pid);
 205 
 206                 if (p == NULL || p->p_stat == SIDL) {
 207                         mutex_exit(&pidlock);
 208                         return (NULL);
 209                 }
 210                 /*
 211                  * p_lock is persistent, but p itself is not -- it could
 212                  * vanish during cv_wait().  Load p->p_lock now so we can
 213                  * drop it after cv_wait() without referencing p.
 214                  */
 215                 mp = &p->p_lock;
 216                 mutex_enter(mp);
 217 
 218                 mutex_exit(&pidlock);
 219 
 220                 if (!(p->p_proc_flag & P_PR_LOCK))
 221                         break;
 222 
 223                 cv_wait(&pr_pid_cv[p->p_slot], mp);
 224                 mutex_exit(mp);
 225         }
 226         p->p_proc_flag |= P_PR_LOCK;
 227         THREAD_KPRI_REQUEST();
 228         return (p);
 229 }
 230 
 231 /*
 232  * lxpr_unlock()
 233  *
 234  * Unlock locked process
 235  */
 236 void
 237 lxpr_unlock(proc_t *p)
 238 {
 239         ASSERT(p->p_proc_flag & P_PR_LOCK);
 240         ASSERT(MUTEX_HELD(&p->p_lock));
 241         ASSERT(!MUTEX_HELD(&pidlock));
 242 
 243         cv_signal(&pr_pid_cv[p->p_slot]);
 244         p->p_proc_flag &= ~P_PR_LOCK;
 245         mutex_exit(&p->p_lock);
 246         THREAD_KPRI_RELEASE();
 247 }
 248 
 249 void
 250 lxpr_initnodecache()
 251 {
 252         lxpr_node_cache = kmem_cache_create(LXPRCACHE_NAME,
 253             sizeof (lxpr_node_t), 0,
 254             lxpr_node_constructor, lxpr_node_destructor, NULL, NULL, NULL, 0);
 255 }
 256 
 257 void
 258 lxpr_fininodecache()
 259 {
 260         kmem_cache_destroy(lxpr_node_cache);
 261 }
 262 
 263 /* ARGSUSED */
 264 static int
 265 lxpr_node_constructor(void *buf, void *un, int kmflags)
 266 {
 267         lxpr_node_t     *lxpnp = buf;
 268         vnode_t         *vp;
 269 
 270         vp = lxpnp->lxpr_vnode = vn_alloc(kmflags);
 271         if (vp == NULL)
 272                 return (-1);
 273 
 274         (void) vn_setops(vp, lxpr_vnodeops);
 275         vp->v_data = lxpnp;
 276 
 277         return (0);
 278 }
 279 
 280 /* ARGSUSED */
 281 static void
 282 lxpr_node_destructor(void *buf, void *un)
 283 {
 284         lxpr_node_t     *lxpnp = buf;
 285 
 286         vn_free(LXPTOV(lxpnp));
 287 }
 288 
 289 /*
 290  * Calculate an inode number
 291  *
 292  * This takes various bits of info and munges them
 293  * to give the inode number for an lxproc node
 294  */
 295 ino_t
 296 lxpr_inode(lxpr_nodetype_t type, pid_t pid, int fd)
 297 {
 298         if (pid == 1)
 299                 pid = curproc->p_zone->zone_proc_initpid;
 300 
 301         switch (type) {
 302         case LXPR_PIDDIR:
 303                 return (pid + 1);
 304         case LXPR_PROCDIR:
 305                 return (maxpid + 2);
 306         case LXPR_PID_FD_FD:
 307                 return (maxpid + 2 +
 308                     (pid * (LXPR_FD_PERPROC + LXPR_NFILES)) +
 309                     LXPR_NFILES + fd);
 310         default:
 311                 return (maxpid + 2 +
 312                     (pid * (LXPR_FD_PERPROC + LXPR_NFILES)) +
 313                     type);
 314         }
 315 }
 316 
 317 /*
 318  * Return inode number of parent (directory)
 319  */
 320 ino_t
 321 lxpr_parentinode(lxpr_node_t *lxpnp)
 322 {
 323         /*
 324          * If the input node is the root then the parent inode
 325          * is the mounted on inode so just return our inode number
 326          */
 327         if (lxpnp->lxpr_type != LXPR_PROCDIR)
 328                 return (VTOLXP(lxpnp->lxpr_parent)->lxpr_ino);
 329         else
 330                 return (lxpnp->lxpr_ino);
 331 }
 332 
 333 /*
 334  * Allocate a new lxproc node
 335  *
 336  * This also allocates the vnode associated with it
 337  */
 338 lxpr_node_t *
 339 lxpr_getnode(vnode_t *dp, lxpr_nodetype_t type, proc_t *p, int fd)
 340 {
 341         lxpr_node_t *lxpnp;
 342         vnode_t *vp;
 343         user_t *up;
 344         timestruc_t now;
 345 
 346         /*
 347          * Allocate a new node. It is deallocated in vop_innactive
 348          */
 349         lxpnp = kmem_cache_alloc(lxpr_node_cache, KM_SLEEP);
 350 
 351         /*
 352          * Set defaults (may be overridden below)
 353          */
 354         gethrestime(&now);
 355         lxpnp->lxpr_type = type;
 356         lxpnp->lxpr_realvp = NULL;
 357         lxpnp->lxpr_parent = dp;
 358         VN_HOLD(dp);
 359         if (p != NULL) {
 360                 lxpnp->lxpr_pid = ((p->p_pid ==
 361                     curproc->p_zone->zone_proc_initpid) ? 1 : p->p_pid);
 362 
 363                 lxpnp->lxpr_time = PTOU(p)->u_start;
 364                 lxpnp->lxpr_uid = crgetruid(p->p_cred);
 365                 lxpnp->lxpr_gid = crgetrgid(p->p_cred);
 366                 lxpnp->lxpr_ino = lxpr_inode(type, p->p_pid, fd);
 367         } else {
 368                 /* Pretend files without a proc belong to sched */
 369                 lxpnp->lxpr_pid = 0;
 370                 lxpnp->lxpr_time = now;
 371                 lxpnp->lxpr_uid = lxpnp->lxpr_gid = 0;
 372                 lxpnp->lxpr_ino = lxpr_inode(type, 0, 0);
 373         }
 374 
 375         /* initialize the vnode data */
 376         vp = lxpnp->lxpr_vnode;
 377         vn_reinit(vp);
 378         vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT;
 379         vp->v_vfsp = dp->v_vfsp;
 380 
 381         /*
 382          * Do node specific stuff
 383          */
 384         switch (type) {
 385         case LXPR_PROCDIR:
 386                 vp->v_flag |= VROOT;
 387                 vp->v_type = VDIR;
 388                 lxpnp->lxpr_mode = 0555;     /* read-search by everyone */
 389                 break;
 390 
 391         case LXPR_PID_CURDIR:
 392                 ASSERT(p != NULL);
 393 
 394                 /*
 395                  * Zombie check.  p_stat is officially protected by pidlock,
 396                  * but we can't grab pidlock here because we already hold
 397                  * p_lock.  Luckily if we look at the process exit code
 398                  * we see that p_stat only transisions from SRUN to SZOMB
 399                  * while p_lock is held.  Aside from this, the only other
 400                  * p_stat transition that we need to be aware about is
 401                  * SIDL to SRUN, but that's not a problem since lxpr_lock()
 402                  * ignores nodes in the SIDL state so we'll never get a node
 403                  * that isn't already in the SRUN state.
 404                  */
 405                 if (p->p_stat == SZOMB) {
 406                         lxpnp->lxpr_realvp = NULL;
 407                 } else {
 408                         up = PTOU(p);
 409                         lxpnp->lxpr_realvp = up->u_cdir;
 410                         ASSERT(lxpnp->lxpr_realvp != NULL);
 411                         VN_HOLD(lxpnp->lxpr_realvp);
 412                 }
 413                 vp->v_type = VLNK;
 414                 lxpnp->lxpr_mode = 0777;     /* anyone does anything ! */
 415                 break;
 416 
 417         case LXPR_PID_ROOTDIR:
 418                 ASSERT(p != NULL);
 419                 /* Zombie check.  see locking comment above */
 420                 if (p->p_stat == SZOMB) {
 421                         lxpnp->lxpr_realvp = NULL;
 422                 } else {
 423                         up = PTOU(p);
 424                         lxpnp->lxpr_realvp =
 425                             up->u_rdir != NULL ? up->u_rdir : rootdir;
 426                         ASSERT(lxpnp->lxpr_realvp != NULL);
 427                         VN_HOLD(lxpnp->lxpr_realvp);
 428                 }
 429                 vp->v_type = VLNK;
 430                 lxpnp->lxpr_mode = 0777;     /* anyone does anything ! */
 431                 break;
 432 
 433         case LXPR_PID_EXE:
 434                 ASSERT(p != NULL);
 435                 lxpnp->lxpr_realvp = p->p_exec;
 436                 if (lxpnp->lxpr_realvp != NULL) {
 437                         VN_HOLD(lxpnp->lxpr_realvp);
 438                 }
 439                 vp->v_type = VLNK;
 440                 lxpnp->lxpr_mode = 0777;
 441                 break;
 442 
 443         case LXPR_SELF:
 444                 vp->v_type = VLNK;
 445                 lxpnp->lxpr_mode = 0777;     /* anyone does anything ! */
 446                 break;
 447 
 448         case LXPR_PID_FD_FD:
 449                 ASSERT(p != NULL);
 450                 /* lxpr_realvp is set after we return */
 451                 vp->v_type = VLNK;
 452                 lxpnp->lxpr_mode = 0700;     /* read-write-exe owner only */
 453                 break;
 454 
 455         case LXPR_PID_FDDIR:
 456                 ASSERT(p != NULL);
 457                 vp->v_type = VDIR;
 458                 lxpnp->lxpr_mode = 0500;     /* read-search by owner only */
 459                 break;
 460 
 461         case LXPR_PIDDIR:
 462                 ASSERT(p != NULL);
 463                 vp->v_type = VDIR;
 464                 lxpnp->lxpr_mode = 0511;
 465                 break;
 466 
 467         case LXPR_NETDIR:
 468                 vp->v_type = VDIR;
 469                 lxpnp->lxpr_mode = 0555;     /* read-search by all */
 470                 break;
 471 
 472         case LXPR_PID_ENV:
 473         case LXPR_PID_MEM:
 474                 ASSERT(p != NULL);
 475                 /*FALLTHRU*/
 476         case LXPR_KCORE:
 477                 vp->v_type = VREG;
 478                 lxpnp->lxpr_mode = 0400;     /* read-only by owner only */
 479                 break;
 480 
 481         default:
 482                 vp->v_type = VREG;
 483                 lxpnp->lxpr_mode = 0444;     /* read-only by all */
 484                 break;
 485         }
 486 
 487         return (lxpnp);
 488 }
 489 
 490 
 491 /*
 492  * Free the storage obtained from lxpr_getnode().
 493  */
 494 void
 495 lxpr_freenode(lxpr_node_t *lxpnp)
 496 {
 497         ASSERT(lxpnp != NULL);
 498         ASSERT(LXPTOV(lxpnp) != NULL);
 499 
 500         /*
 501          * delete any association with realvp
 502          */
 503         if (lxpnp->lxpr_realvp != NULL)
 504                 VN_RELE(lxpnp->lxpr_realvp);
 505 
 506         /*
 507          * delete any association with parent vp
 508          */
 509         if (lxpnp->lxpr_parent != NULL)
 510                 VN_RELE(lxpnp->lxpr_parent);
 511 
 512         /*
 513          * Release the lxprnode.
 514          */
 515         kmem_cache_free(lxpr_node_cache, lxpnp);
 516 }