1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2015, Joyent, Inc.
  14  */
  15 
  16 #include <sys/types.h>
  17 #include <sys/sunddi.h>
  18 #include <sys/proc.h>
  19 #include <sys/procfs.h>
  20 #include <sys/sysmacros.h>
  21 #include <vm/as.h>
  22 
  23 /*
  24  * Safely read a contiguous region of memory from 'addr' in the address space
  25  * of a particular process into the supplied kernel buffer (*buf, sz).
  26  * Partially mapped regions will result in a partial read terminating at the
  27  * first hole in the address space.  The number of bytes actually read is
  28  * returned to the caller via 'rdsz'.
  29  */
  30 int
  31 prreadbuf(proc_t *p, uintptr_t ustart, uint8_t *buf, size_t sz, size_t *rdsz)
  32 {
  33         int error = 0;
  34         size_t rem = sz;
  35         off_t pos = 0;
  36 
  37         if (rdsz != NULL)
  38                 *rdsz = 0;
  39 
  40         while (rem != 0) {
  41                 uintptr_t addr = ustart + pos;
  42                 size_t len = MIN(rem, PAGESIZE - (addr & PAGEOFFSET));
  43 
  44                 if ((error = uread(p, buf + pos, len, addr)) != 0) {
  45                         if (error == ENXIO) {
  46                                 /*
  47                                  * ENXIO from uread() indicates that the page
  48                                  * does not exist.  This will simply be a
  49                                  * partial read.
  50                                  */
  51                                 error = 0;
  52                         }
  53                         break;
  54                 }
  55 
  56                 rem -= len;
  57                 pos += len;
  58         }
  59 
  60         if (rdsz != NULL)
  61                 *rdsz = pos;
  62 
  63         return (error);
  64 }
  65 
  66 /*
  67  * Attempt to read the argument vector (argv) from this process.  The caller
  68  * must hold the p_lock mutex, and have marked the process P_PR_LOCK (e.g. via
  69  * prlock or lx_prlock).
  70  *
  71  * The caller must provide a buffer (buf, buflen).  We will concatenate each
  72  * argument string (including the NUL terminator) into this buffer.  The number
  73  * of characters written to this buffer (including the final NUL terminator)
  74  * will be stored in 'slen'.
  75  */
  76 int
  77 prreadargv(proc_t *p, char *buf, size_t bufsz, size_t *slen)
  78 {
  79         int error;
  80         user_t *up;
  81         struct as *as;
  82         size_t pos = 0;
  83         caddr_t *argv = NULL;
  84         size_t argvsz = 0;
  85         int i;
  86 
  87         VERIFY(MUTEX_HELD(&p->p_lock));
  88         VERIFY(p->p_proc_flag & P_PR_LOCK);
  89 
  90         up = PTOU(p);
  91         as = p->p_as;
  92 
  93         if ((p->p_flag & SSYS) || as == &kas || up->u_argv == NULL) {
  94                 /*
  95                  * Return the regular psargs string to the caller.
  96                  */
  97                 bcopy(up->u_psargs, buf, MIN(bufsz, sizeof (up->u_psargs)));
  98                 buf[bufsz - 1] = '\0';
  99                 *slen = strlen(buf) + 1;
 100 
 101                 return (0);
 102         }
 103 
 104         /*
 105          * Allocate space to store argv array.
 106          */
 107         argvsz = up->u_argc * (p->p_model == DATAMODEL_ILP32 ?
 108             sizeof (caddr32_t) : sizeof (caddr_t));
 109         argv = kmem_alloc(argvsz, KM_SLEEP);
 110 
 111         /*
 112          * Extract the argv array from the target process.  Drop p_lock
 113          * while we do I/O to avoid deadlock with the clock thread.
 114          */
 115         mutex_exit(&p->p_lock);
 116         if ((error = prreadbuf(p, up->u_argv, (uint8_t *)argv, argvsz,
 117             NULL)) != 0) {
 118                 kmem_free(argv, argvsz);
 119                 mutex_enter(&p->p_lock);
 120                 VERIFY(p->p_proc_flag & P_PR_LOCK);
 121                 return (-1);
 122         }
 123 
 124         /*
 125          * Read each argument string from the pointers in the argv array.
 126          */
 127         pos = 0;
 128         for (i = 0; i < up->u_argc; i++) {
 129                 size_t rdsz, trysz;
 130                 uintptr_t arg;
 131                 off_t j;
 132                 boolean_t found_nul;
 133                 boolean_t do_retry = B_TRUE;
 134 
 135 #ifdef  _SYSCALL32_IMPL
 136                 if (p->p_model == DATAMODEL_ILP32) {
 137                         arg = (uintptr_t)((caddr32_t *)argv)[i];
 138                 } else {
 139                         arg = (uintptr_t)argv[i];
 140                 }
 141 #else
 142                 arg = (uintptr_t)argv[i];
 143 #endif
 144 
 145                 /*
 146                  * Stop trying to read arguments if we reach a NULL
 147                  * pointer in the vector.
 148                  */
 149                 if (arg == NULL)
 150                         break;
 151 
 152                 /*
 153                  * Stop reading if we have read the maximum length
 154                  * we can return to the user.
 155                  */
 156                 if (pos >= bufsz)
 157                         break;
 158 
 159                 /*
 160                  * Initially we try a short read, on the assumption that
 161                  * most individual argument strings are less than 80
 162                  * characters long.
 163                  */
 164                 if ((trysz = MIN(80, bufsz - pos - 1)) < 80) {
 165                         /*
 166                          * We don't have room in the target buffer for even
 167                          * an entire short read, so there is no need to retry
 168                          * with a longer read.
 169                          */
 170                         do_retry = B_FALSE;
 171                 }
 172 
 173 retry:
 174                 /*
 175                  * Read string data for this argument.  Leave room
 176                  * in the buffer for a final NUL terminator.
 177                  */
 178                 if ((error = prreadbuf(p, arg, (uint8_t *)&buf[pos], trysz,
 179                     &rdsz)) != 0) {
 180                         /*
 181                          * There was a problem reading this string
 182                          * from the process.  Give up.
 183                          */
 184                         break;
 185                 }
 186 
 187                 /*
 188                  * Find the NUL terminator.
 189                  */
 190                 found_nul = B_FALSE;
 191                 for (j = 0; j < rdsz; j++) {
 192                         if (buf[pos + j] == '\0') {
 193                                 found_nul = B_TRUE;
 194                                 break;
 195                         }
 196                 }
 197 
 198                 if (!found_nul && do_retry) {
 199                         /*
 200                          * We did not find a NUL terminator, but this
 201                          * was a first pass short read.  Try once more
 202                          * with feeling.
 203                          */
 204                         trysz = bufsz - pos - 1;
 205                         do_retry = B_FALSE;
 206                         goto retry;
 207                 }
 208 
 209                 /*
 210                  * Commit the string we read to the buffer.
 211                  */
 212                 pos += j + 1;
 213                 if (!found_nul && pos < bufsz) {
 214                         /*
 215                          * A NUL terminator was not found; add one.
 216                          */
 217                         buf[pos++] = '\0';
 218                 }
 219         }
 220 
 221         /*
 222          * Ensure the entire string is NUL-terminated.
 223          */
 224         buf[bufsz - 1] = '\0';
 225 
 226         mutex_enter(&p->p_lock);
 227         VERIFY(p->p_proc_flag & P_PR_LOCK);
 228         kmem_free(argv, argvsz);
 229 
 230         /*
 231          * If the operation was a success, return the copied string length
 232          * to the caller.
 233          */
 234         *slen = (error == 0) ? pos : 0;
 235 
 236         return (error);
 237 }
 238 
 239 /*
 240  * Similar to prreadargv except reads the env vector. This is slightly more
 241  * complex because there is no count for the env vector that corresponds to
 242  * u_argc.
 243  */
 244 int
 245 prreadenvv(proc_t *p, char *buf, size_t bufsz, size_t *slen)
 246 {
 247         int error;
 248         user_t *up;
 249         struct as *as;
 250         size_t pos = 0;
 251         caddr_t *envp = NULL;
 252         uintptr_t tmpp = NULL;
 253         size_t envpsz = 0, rdsz = 0;
 254         int i;
 255         int cnt, bound;
 256 
 257         VERIFY(MUTEX_HELD(&p->p_lock));
 258         VERIFY(p->p_proc_flag & P_PR_LOCK);
 259 
 260         up = PTOU(p);
 261         as = p->p_as;
 262 
 263         if ((p->p_flag & SSYS) || as == &kas || up->u_envp == NULL) {
 264                 /*
 265                  * Return empty string.
 266                  */
 267                 buf[0] = '\0';
 268                 *slen = 1;
 269 
 270                 return (0);
 271         }
 272 
 273         /*
 274          * Drop p_lock while we do I/O to avoid deadlock with the clock thread.
 275          */
 276         mutex_exit(&p->p_lock);
 277 
 278         /*
 279          * We first have to count how many env entries we have. This is
 280          * somewhat painful. We extract the env entries from the target process
 281          * one entry at a time. Stop trying to read env entries if we reach a
 282          * NULL pointer in the vector or hit our upper bound (which we take
 283          * as the bufsz/4) to ensure we don't run off.
 284          */
 285         rdsz = (p->p_model == DATAMODEL_ILP32 ?
 286             sizeof (caddr32_t) : sizeof (caddr_t));
 287         bound = (int)(bufsz / 4);
 288         for (cnt = 0, tmpp = up->u_envp; cnt < bound; cnt++, tmpp += rdsz) {
 289                 caddr_t tmp = NULL;
 290 
 291                 if ((error = prreadbuf(p, tmpp, (uint8_t *)&tmp, rdsz,
 292                     NULL)) != 0) {
 293                         mutex_enter(&p->p_lock);
 294                         VERIFY(p->p_proc_flag & P_PR_LOCK);
 295                         return (-1);
 296                 }
 297 
 298                 if (tmp == NULL)
 299                         break;
 300         }
 301         if (cnt == 0) {
 302                 /* Return empty string. */
 303                 buf[0] = '\0';
 304                 *slen = 1;
 305                 mutex_enter(&p->p_lock);
 306                 VERIFY(p->p_proc_flag & P_PR_LOCK);
 307                 return (0);
 308         }
 309 
 310         /*
 311          * Allocate space to store env array.
 312          */
 313         envpsz = cnt * (p->p_model == DATAMODEL_ILP32 ?
 314             sizeof (caddr32_t) : sizeof (caddr_t));
 315         envp = kmem_alloc(envpsz, KM_SLEEP);
 316 
 317         /*
 318          * Extract the env array from the target process.
 319          */
 320         if ((error = prreadbuf(p, up->u_envp, (uint8_t *)envp, envpsz,
 321             NULL)) != 0) {
 322                 kmem_free(envp, envpsz);
 323                 mutex_enter(&p->p_lock);
 324                 VERIFY(p->p_proc_flag & P_PR_LOCK);
 325                 return (-1);
 326         }
 327 
 328         /*
 329          * Read each env string from the pointers in the env array.
 330          */
 331         pos = 0;
 332         for (i = 0; i < cnt; i++) {
 333                 size_t rdsz, trysz;
 334                 uintptr_t ev;
 335                 off_t j;
 336                 boolean_t found_nul;
 337                 boolean_t do_retry = B_TRUE;
 338 
 339 #ifdef  _SYSCALL32_IMPL
 340                 if (p->p_model == DATAMODEL_ILP32) {
 341                         ev = (uintptr_t)((caddr32_t *)envp)[i];
 342                 } else {
 343                         ev = (uintptr_t)envp[i];
 344                 }
 345 #else
 346                 ev = (uintptr_t)envp[i];
 347 #endif
 348 
 349                 /*
 350                  * Stop trying to read env entries if we reach a NULL
 351                  * pointer in the vector.
 352                  */
 353                 if (ev == NULL)
 354                         break;
 355 
 356                 /*
 357                  * Stop reading if we have read the maximum length
 358                  * we can return to the user.
 359                  */
 360                 if (pos >= bufsz)
 361                         break;
 362 
 363                 /*
 364                  * Initially we try a short read, on the assumption that
 365                  * most individual env strings are less than 80
 366                  * characters long.
 367                  */
 368                 if ((trysz = MIN(80, bufsz - pos - 1)) < 80) {
 369                         /*
 370                          * We don't have room in the target buffer for even
 371                          * an entire short read, so there is no need to retry
 372                          * with a longer read.
 373                          */
 374                         do_retry = B_FALSE;
 375                 }
 376 
 377 retry:
 378                 /*
 379                  * Read string data for this env var.  Leave room
 380                  * in the buffer for a final NUL terminator.
 381                  */
 382                 if ((error = prreadbuf(p, ev, (uint8_t *)&buf[pos], trysz,
 383                     &rdsz)) != 0) {
 384                         /*
 385                          * There was a problem reading this string
 386                          * from the process.  Give up.
 387                          */
 388                         break;
 389                 }
 390 
 391                 /*
 392                  * Find the NUL terminator.
 393                  */
 394                 found_nul = B_FALSE;
 395                 for (j = 0; j < rdsz; j++) {
 396                         if (buf[pos + j] == '\0') {
 397                                 found_nul = B_TRUE;
 398                                 break;
 399                         }
 400                 }
 401 
 402                 if (!found_nul && do_retry) {
 403                         /*
 404                          * We did not find a NUL terminator, but this
 405                          * was a first pass short read.  Try once more
 406                          * with feeling.
 407                          */
 408                         trysz = bufsz - pos - 1;
 409                         do_retry = B_FALSE;
 410                         goto retry;
 411                 }
 412 
 413                 /*
 414                  * Commit the string we read to the buffer.
 415                  */
 416                 pos += j + 1;
 417                 if (!found_nul && pos < bufsz) {
 418                         /*
 419                          * A NUL terminator was not found; add one.
 420                          */
 421                         buf[pos++] = '\0';
 422                 }
 423         }
 424 
 425         /*
 426          * Ensure the entire string is NUL-terminated.
 427          */
 428         buf[bufsz - 1] = '\0';
 429 
 430         mutex_enter(&p->p_lock);
 431         VERIFY(p->p_proc_flag & P_PR_LOCK);
 432         kmem_free(envp, envpsz);
 433 
 434         /*
 435          * If the operation was a success, return the copied string length
 436          * to the caller.
 437          */
 438         *slen = (error == 0) ? pos : 0;
 439 
 440         return (error);
 441 }