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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/param.h>
  28 #include <sys/sysmacros.h>
  29 #include <sys/bitmap.h>
  30 #include <sys/var.h>
  31 #include <sys/thread.h>
  32 #include <sys/proc.h>
  33 #include <sys/brand.h>
  34 #include <sys/zone.h>
  35 #include <sys/lx_brand.h>
  36 #include <sys/lx_pid.h>
  37 
  38 #define LINUX_PROC_FACTOR       8       /* factor down the hash table by this */
  39 static int hash_len = 4;                /* desired average hash chain length */
  40 static int hash_size;                   /* no of buckets in the hash table */
  41 
  42 static struct lx_pid **stol_pid_hash;
  43 static struct lx_pid **ltos_pid_hash;
  44 
  45 #define LTOS_HASH(pid)          ((pid) & (hash_size - 1))
  46 #define STOL_HASH(pid, tid)     (((pid) + (tid)) & (hash_size - 1))
  47 
  48 static kmutex_t hash_lock;
  49 
  50 static void
  51 lx_pid_insert_hash(struct lx_pid *lpidp)
  52 {
  53         int shash = STOL_HASH(lpidp->s_pid, lpidp->s_tid);
  54         int lhash = LTOS_HASH(lpidp->l_pid);
  55 
  56         ASSERT(MUTEX_HELD(&hash_lock));
  57 
  58         lpidp->stol_next = stol_pid_hash[shash];
  59         stol_pid_hash[shash] = lpidp;
  60 
  61         lpidp->ltos_next = ltos_pid_hash[lhash];
  62         ltos_pid_hash[lhash] = lpidp;
  63 }
  64 
  65 static struct lx_pid *
  66 lx_pid_remove_hash(pid_t pid, id_t tid)
  67 {
  68         struct lx_pid **hpp;
  69         struct lx_pid *lpidp;
  70 
  71         ASSERT(MUTEX_HELD(&hash_lock));
  72 
  73         hpp = &stol_pid_hash[STOL_HASH(pid, tid)];
  74         while (*hpp) {
  75                 if ((*hpp)->s_pid == pid && (*hpp)->s_tid == tid) {
  76                         lpidp = *hpp;
  77                         *hpp = (*hpp)->stol_next;
  78                         break;
  79                 }
  80                 hpp = &(*hpp)->stol_next;
  81         }
  82 
  83         /*
  84          * when called during error recovery the pid may already
  85          * be released
  86          */
  87         if (lpidp == NULL)
  88                 return (NULL);
  89 
  90         hpp = &ltos_pid_hash[LTOS_HASH(lpidp->l_pid)];
  91         while (*hpp) {
  92                 if (*hpp == lpidp) {
  93                         *hpp = lpidp->ltos_next;
  94                         break;
  95                 }
  96                 hpp = &(*hpp)->ltos_next;
  97         }
  98 
  99         return (lpidp);
 100 }
 101 
 102 /*
 103  * given a solaris pid/tid pair, create a linux pid
 104  */
 105 int
 106 lx_pid_assign(kthread_t *t)
 107 {
 108         proc_t *p = ttoproc(t);
 109         pid_t s_pid = p->p_pid;
 110         id_t s_tid = t->t_tid;
 111         struct pid *pidp;
 112         struct lx_pid *lpidp;
 113         lx_lwp_data_t *lwpd = ttolxlwp(t);
 114         pid_t newpid;
 115 
 116         if (p->p_lwpcnt > 0) {
 117                 /*
 118                  * Allocate a pid for any thread other than the first
 119                  */
 120                 if ((newpid = pid_allocate(p, 0, 0)) < 0)
 121                         return (-1);
 122 
 123                 pidp = pid_find(newpid);
 124         } else {
 125                 pidp = NULL;
 126                 newpid = s_pid;
 127         }
 128 
 129         lpidp = kmem_alloc(sizeof (struct lx_pid), KM_SLEEP);
 130         lpidp->l_pid = newpid;
 131         lpidp->s_pid = s_pid;
 132         lpidp->s_tid = s_tid;
 133         lpidp->l_pidp = pidp;
 134         lpidp->l_start = t->t_start;
 135 
 136         /*
 137          * now put the pid into the linux-solaris and solaris-linux
 138          * conversion hash tables
 139          */
 140         mutex_enter(&hash_lock);
 141         lx_pid_insert_hash(lpidp);
 142         mutex_exit(&hash_lock);
 143 
 144         lwpd->br_pid = newpid;
 145 
 146         return (0);
 147 }
 148 
 149 /*
 150  * If we are exec()ing the process, this thread's tid is about to be reset
 151  * to 1.  Make sure the Linux PID bookkeeping reflects that change.
 152  */
 153 void
 154 lx_pid_reassign(kthread_t *t)
 155 {
 156         proc_t *p = ttoproc(t);
 157         struct pid *old_pidp;
 158         struct lx_pid *lpidp;
 159 
 160         ASSERT(p->p_lwpcnt == 1);
 161 
 162         mutex_enter(&hash_lock);
 163 
 164         /*
 165          * Clean up all the traces of this thread's 'fake' Linux PID.
 166          */
 167         lpidp = lx_pid_remove_hash(p->p_pid, t->t_tid);
 168         ASSERT(lpidp != NULL);
 169         old_pidp = lpidp->l_pidp;
 170         lpidp->l_pidp = NULL;
 171 
 172         /*
 173          * Now register this thread as (pid, 1).
 174          */
 175         lpidp->l_pid = p->p_pid;
 176         lpidp->s_pid = p->p_pid;
 177         lpidp->s_tid = 1;
 178         lx_pid_insert_hash(lpidp);
 179 
 180         mutex_exit(&hash_lock);
 181 
 182         if (old_pidp)
 183                 (void) pid_rele(old_pidp);
 184 }
 185 
 186 /*
 187  * release a solaris pid/tid pair
 188  */
 189 void
 190 lx_pid_rele(pid_t pid, id_t tid)
 191 {
 192         struct lx_pid *lpidp;
 193 
 194         mutex_enter(&hash_lock);
 195         lpidp = lx_pid_remove_hash(pid, tid);
 196         mutex_exit(&hash_lock);
 197 
 198         if (lpidp) {
 199                 if (lpidp->l_pidp)
 200                         (void) pid_rele(lpidp->l_pidp);
 201 
 202                 kmem_free(lpidp, sizeof (*lpidp));
 203         }
 204 }
 205 
 206 /*
 207  * given a linux pid, return the solaris pid/tid pair
 208  */
 209 int
 210 lx_lpid_to_spair(pid_t l_pid, pid_t *s_pid, id_t *s_tid)
 211 {
 212         struct lx_pid *hp;
 213 
 214         mutex_enter(&hash_lock);
 215         for (hp = ltos_pid_hash[LTOS_HASH(l_pid)]; hp; hp = hp->ltos_next) {
 216                 if (l_pid == hp->l_pid) {
 217                         if (s_pid)
 218                                 *s_pid = hp->s_pid;
 219                         if (s_tid)
 220                                 *s_tid = hp->s_tid;
 221                         break;
 222                 }
 223         }
 224         mutex_exit(&hash_lock);
 225         if (hp != NULL)
 226                 return (0);
 227 
 228         /*
 229          * We didn't find this pid in our translation table.
 230          * But this still could be the pid of a native process
 231          * running in the current zone so check for that here.
 232          *
 233          * Note that prfind() only searches for processes in the current zone.
 234          */
 235         mutex_enter(&pidlock);
 236         if (prfind(l_pid) != NULL) {
 237                 mutex_exit(&pidlock);
 238                 if (s_pid)
 239                         *s_pid = l_pid;
 240                 if (s_tid)
 241                         *s_tid = 0;
 242                 return (0);
 243         }
 244         mutex_exit(&pidlock);
 245 
 246         return (-1);
 247 }
 248 
 249 /*
 250  * Given an lwp, return the Linux pid of its parent.  If the caller
 251  * wants them, we return the Solaris (pid, tid) as well.
 252  */
 253 pid_t
 254 lx_lwp_ppid(klwp_t *lwp, pid_t *ppidp, id_t *ptidp)
 255 {
 256         lx_lwp_data_t *lwpd = lwptolxlwp(lwp);
 257         proc_t *p = lwptoproc(lwp);
 258         struct lx_pid *hp;
 259         pid_t zoneinit = curproc->p_zone->zone_proc_initpid;
 260         pid_t lppid, ppid;
 261 
 262         /*
 263          * Be sure not to return a parent pid that should be invisible
 264          * within this zone.
 265          */
 266         ppid = ((p->p_flag & SZONETOP)
 267             ? curproc->p_zone->zone_zsched->p_pid : p->p_ppid);
 268 
 269         /*
 270          * If the parent process's pid is the zone's init process, force it
 271          * to the Linux init pid value of 1.
 272          */
 273         if (ppid == zoneinit)
 274                 ppid = 1;
 275 
 276         /*
 277          * There are two cases in which the Linux definition of a 'parent'
 278          * matches that of Solaris:
 279          *
 280          * - if our tgid is the same as our PID, then we are either the
 281          *   first thread in the process or a CLONE_THREAD thread.
 282          *
 283          * - if the brand lwp value for ppid is 0, then we are either the
 284          *   child of a differently-branded process or a CLONE_PARENT thread.
 285          */
 286         if (p->p_pid == lwpd->br_tgid || lwpd->br_ppid == 0) {
 287                 if (ppidp != NULL)
 288                         *ppidp = ppid;
 289                 if (ptidp != NULL)
 290                         *ptidp = -1;
 291                 return (ppid);
 292         }
 293 
 294         /*
 295          * Set the default Linux parent pid to be the pid of the zone's init
 296          * process; this will get converted back to the Linux default of 1
 297          * later.
 298          */
 299         lppid = zoneinit;
 300 
 301         /*
 302          * If the process's parent isn't init, try and look up the Linux "pid"
 303          * corresponding to the process's parent.
 304          */
 305         if (ppid != 1) {
 306                 /*
 307                  * In all other cases, we are looking for the parent of this
 308                  * specific thread, which in Linux refers to the thread that
 309                  * clone()d it.   We stashed that thread's PID away when this
 310                  * thread was created.
 311                  */
 312                 mutex_enter(&hash_lock);
 313                 for (hp = ltos_pid_hash[LTOS_HASH(lwpd->br_ppid)]; hp;
 314                     hp = hp->ltos_next) {
 315                         if (lwpd->br_ppid == hp->l_pid) {
 316                                 /*
 317                                  * We found the PID we were looking for, but
 318                                  * since we cached its value in this LWP's brand
 319                                  * structure, it has exited and been reused by
 320                                  * another process.
 321                                  */
 322                                 if (hp->l_start > lwptot(lwp)->t_start)
 323                                         break;
 324 
 325                                 lppid = lwpd->br_ppid;
 326                                 if (ppidp != NULL)
 327                                         *ppidp = hp->s_pid;
 328                                 if (ptidp != NULL)
 329                                         *ptidp = hp->s_tid;
 330 
 331                                 break;
 332                         }
 333                 }
 334                 mutex_exit(&hash_lock);
 335         }
 336 
 337         if (lppid == zoneinit) {
 338                 lppid = 1;
 339 
 340                 if (ppidp != NULL)
 341                         *ppidp = lppid;
 342                 if (ptidp != NULL)
 343                         *ptidp = -1;
 344         }
 345 
 346         return (lppid);
 347 }
 348 
 349 void
 350 lx_pid_init(void)
 351 {
 352         hash_size = 1 << highbit(v.v_proc / (hash_len * LINUX_PROC_FACTOR));
 353 
 354         stol_pid_hash = kmem_zalloc(sizeof (struct lx_pid *) * hash_size,
 355             KM_SLEEP);
 356         ltos_pid_hash = kmem_zalloc(sizeof (struct lx_pid *) * hash_size,
 357             KM_SLEEP);
 358 
 359         mutex_init(&hash_lock, NULL, MUTEX_DEFAULT, NULL);
 360 }
 361 
 362 void
 363 lx_pid_fini(void)
 364 {
 365         kmem_free(stol_pid_hash, sizeof (struct lx_pid *) * hash_size);
 366         kmem_free(ltos_pid_hash, sizeof (struct lx_pid *) * hash_size);
 367 }