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 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 #include <sys/types.h>
31 #include <sys/t_lock.h>
32 #include <sys/param.h>
33 #include <sys/cmn_err.h>
34 #include <sys/cred.h>
35 #include <sys/priv.h>
36 #include <sys/debug.h>
37 #include <sys/errno.h>
38 #include <sys/inline.h>
39 #include <sys/kmem.h>
40 #include <sys/mman.h>
41 #include <sys/proc.h>
42 #include <sys/brand.h>
43 #include <sys/sobject.h>
44 #include <sys/sysmacros.h>
48 #include <sys/vfs.h>
49 #include <sys/vnode.h>
50 #include <sys/session.h>
51 #include <sys/pcb.h>
52 #include <sys/signal.h>
53 #include <sys/user.h>
54 #include <sys/disp.h>
55 #include <sys/class.h>
56 #include <sys/ts.h>
57 #include <sys/bitmap.h>
58 #include <sys/poll.h>
59 #include <sys/shm_impl.h>
60 #include <sys/fault.h>
61 #include <sys/syscall.h>
62 #include <sys/procfs.h>
63 #include <sys/processor.h>
64 #include <sys/cpuvar.h>
65 #include <sys/copyops.h>
66 #include <sys/time.h>
67 #include <sys/msacct.h>
68 #include <vm/as.h>
69 #include <vm/rm.h>
70 #include <vm/seg.h>
71 #include <vm/seg_vn.h>
72 #include <vm/seg_dev.h>
73 #include <vm/seg_spt.h>
74 #include <vm/page.h>
75 #include <sys/vmparam.h>
76 #include <sys/swap.h>
77 #include <fs/proc/prdata.h>
78 #include <sys/task.h>
79 #include <sys/project.h>
80 #include <sys/contract_impl.h>
81 #include <sys/contract/process.h>
82 #include <sys/contract/process_impl.h>
83 #include <sys/schedctl.h>
84 #include <sys/pool.h>
85 #include <sys/zone.h>
86 #include <sys/atomic.h>
87 #include <sys/sdt.h>
1437 pr_u64tos(uint64_t n, char *s)
1438 {
1439 char cbuf[21]; /* 64-bit unsigned integer fits in 20 digits */
1440 char *cp = cbuf;
1441 int len;
1442
1443 do {
1444 *cp++ = (char)(n % 10 + '0');
1445 n /= 10;
1446 } while (n);
1447
1448 len = (int)(cp - cbuf);
1449
1450 do {
1451 *s++ = *--cp;
1452 } while (cp > cbuf);
1453
1454 return (len);
1455 }
1456
1457 void
1458 pr_object_name(char *name, vnode_t *vp, struct vattr *vattr)
1459 {
1460 char *s = name;
1461 struct vfs *vfsp;
1462 struct vfssw *vfsswp;
1463
1464 if ((vfsp = vp->v_vfsp) != NULL &&
1465 ((vfsswp = vfssw + vfsp->vfs_fstype), vfsswp->vsw_name) &&
1466 *vfsswp->vsw_name) {
1467 (void) strcpy(s, vfsswp->vsw_name);
1468 s += strlen(s);
1469 *s++ = '.';
1470 }
1471 s += pr_u32tos(getmajor(vattr->va_fsid), s, 0);
1472 *s++ = '.';
1473 s += pr_u32tos(getminor(vattr->va_fsid), s, 0);
1474 *s++ = '.';
1475 s += pr_u64tos(vattr->va_nodeid, s);
1476 *s++ = '\0';
1477 }
1546 iol->piol_usedsize + sizeof (*iol) + itemsize) {
1547 /*
1548 * Out of space in the current buffer. Allocate more.
1549 */
1550 piol_t *newiol;
1551
1552 newiol = kmem_alloc(MAPSIZE, KM_SLEEP);
1553 newiol->piol_size = MAPSIZE;
1554 newiol->piol_usedsize = 0;
1555
1556 list_insert_after(iolhead, iol, newiol);
1557 iol = list_next(iolhead, iol);
1558 ASSERT(iol == newiol);
1559 }
1560 new = (char *)PIOL_DATABUF(iol) + iol->piol_usedsize;
1561 iol->piol_usedsize += itemsize;
1562 bzero(new, itemsize);
1563 return (new);
1564 }
1565
1566 int
1567 pr_iol_copyout_and_free(list_t *iolhead, caddr_t *tgt, int errin)
1568 {
1569 int error = errin;
1570 piol_t *iol;
1571
1572 while ((iol = list_head(iolhead)) != NULL) {
1573 list_remove(iolhead, iol);
1574 if (!error) {
1575 if (copyout(PIOL_DATABUF(iol), *tgt,
1576 iol->piol_usedsize))
1577 error = EFAULT;
1578 *tgt += iol->piol_usedsize;
1579 }
1580 kmem_free(iol, iol->piol_size);
1581 }
1582 list_destroy(iolhead);
1583
1584 return (error);
1585 }
2358 } while ((t = t->t_forw) != p->p_tlist);
2359
2360 psp->pr_pctcpu = prgetpctcpu(pct);
2361 }
2362 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
2363 psp->pr_size = 0;
2364 psp->pr_rssize = 0;
2365 } else {
2366 mutex_exit(&p->p_lock);
2367 AS_LOCK_ENTER(as, RW_READER);
2368 psp->pr_size = btopr(as->a_resvsize) *
2369 (PAGESIZE / 1024);
2370 psp->pr_rssize = rm_asrss(as) * (PAGESIZE / 1024);
2371 psp->pr_pctmem = rm_pctmemory(as);
2372 AS_LOCK_EXIT(as);
2373 mutex_enter(&p->p_lock);
2374 }
2375 }
2376 }
2377
2378 #ifdef _SYSCALL32_IMPL
2379 void
2380 prgetpsinfo32(proc_t *p, psinfo32_t *psp)
2381 {
2382 kthread_t *t;
2383 struct cred *cred;
2384 hrtime_t hrutime, hrstime;
2385
2386 ASSERT(MUTEX_HELD(&p->p_lock));
2387
2388 if ((t = prchoose(p)) == NULL) /* returns locked thread */
2389 bzero(psp, sizeof (*psp));
2390 else {
2391 thread_unlock(t);
2392 bzero(psp, sizeof (*psp) - sizeof (psp->pr_lwp));
2393 }
2394
2395 /*
2396 * only export SSYS and SMSACCT; everything else is off-limits to
2397 * userland apps.
|
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 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 #include <sys/types.h>
32 #include <sys/t_lock.h>
33 #include <sys/param.h>
34 #include <sys/cmn_err.h>
35 #include <sys/cred.h>
36 #include <sys/priv.h>
37 #include <sys/debug.h>
38 #include <sys/errno.h>
39 #include <sys/inline.h>
40 #include <sys/kmem.h>
41 #include <sys/mman.h>
42 #include <sys/proc.h>
43 #include <sys/brand.h>
44 #include <sys/sobject.h>
45 #include <sys/sysmacros.h>
49 #include <sys/vfs.h>
50 #include <sys/vnode.h>
51 #include <sys/session.h>
52 #include <sys/pcb.h>
53 #include <sys/signal.h>
54 #include <sys/user.h>
55 #include <sys/disp.h>
56 #include <sys/class.h>
57 #include <sys/ts.h>
58 #include <sys/bitmap.h>
59 #include <sys/poll.h>
60 #include <sys/shm_impl.h>
61 #include <sys/fault.h>
62 #include <sys/syscall.h>
63 #include <sys/procfs.h>
64 #include <sys/processor.h>
65 #include <sys/cpuvar.h>
66 #include <sys/copyops.h>
67 #include <sys/time.h>
68 #include <sys/msacct.h>
69 #include <sys/flock_impl.h>
70 #include <sys/stropts.h>
71 #include <sys/strsubr.h>
72 #include <sys/pathname.h>
73 #include <sys/mode.h>
74 #include <sys/socketvar.h>
75 #include <sys/autoconf.h>
76 #include <sys/dtrace.h>
77 #include <sys/timod.h>
78 #include <netinet/udp.h>
79 #include <netinet/tcp.h>
80 #include <inet/cc.h>
81 #include <vm/as.h>
82 #include <vm/rm.h>
83 #include <vm/seg.h>
84 #include <vm/seg_vn.h>
85 #include <vm/seg_dev.h>
86 #include <vm/seg_spt.h>
87 #include <vm/page.h>
88 #include <sys/vmparam.h>
89 #include <sys/swap.h>
90 #include <fs/proc/prdata.h>
91 #include <sys/task.h>
92 #include <sys/project.h>
93 #include <sys/contract_impl.h>
94 #include <sys/contract/process.h>
95 #include <sys/contract/process_impl.h>
96 #include <sys/schedctl.h>
97 #include <sys/pool.h>
98 #include <sys/zone.h>
99 #include <sys/atomic.h>
100 #include <sys/sdt.h>
1450 pr_u64tos(uint64_t n, char *s)
1451 {
1452 char cbuf[21]; /* 64-bit unsigned integer fits in 20 digits */
1453 char *cp = cbuf;
1454 int len;
1455
1456 do {
1457 *cp++ = (char)(n % 10 + '0');
1458 n /= 10;
1459 } while (n);
1460
1461 len = (int)(cp - cbuf);
1462
1463 do {
1464 *s++ = *--cp;
1465 } while (cp > cbuf);
1466
1467 return (len);
1468 }
1469
1470 file_t *
1471 pr_getf(proc_t *p, uint_t fd, short *flag)
1472 {
1473 uf_entry_t *ufp;
1474 uf_info_t *fip;
1475 file_t *fp;
1476
1477 ASSERT(MUTEX_HELD(&p->p_lock));
1478
1479 fip = P_FINFO(p);
1480
1481 if (fd >= fip->fi_nfiles)
1482 return (NULL);
1483
1484 mutex_exit(&p->p_lock);
1485 mutex_enter(&fip->fi_lock);
1486 UF_ENTER(ufp, fip, fd);
1487 if ((fp = ufp->uf_file) != NULL && fp->f_count > 0) {
1488 if (flag != NULL)
1489 *flag = ufp->uf_flag;
1490 ufp->uf_refcnt++;
1491 } else {
1492 fp = NULL;
1493 }
1494 UF_EXIT(ufp);
1495 mutex_exit(&fip->fi_lock);
1496 mutex_enter(&p->p_lock);
1497
1498 return (fp);
1499 }
1500
1501 void
1502 pr_releasef(proc_t *p, uint_t fd)
1503 {
1504 uf_entry_t *ufp;
1505 uf_info_t *fip;
1506
1507 ASSERT(MUTEX_HELD(&p->p_lock));
1508
1509 fip = P_FINFO(p);
1510
1511 mutex_exit(&p->p_lock);
1512 mutex_enter(&fip->fi_lock);
1513 UF_ENTER(ufp, fip, fd);
1514 ASSERT(ufp->uf_refcnt > 0);
1515 ufp->uf_refcnt--;
1516 UF_EXIT(ufp);
1517 mutex_exit(&fip->fi_lock);
1518 mutex_enter(&p->p_lock);
1519 }
1520
1521 void
1522 pr_object_name(char *name, vnode_t *vp, struct vattr *vattr)
1523 {
1524 char *s = name;
1525 struct vfs *vfsp;
1526 struct vfssw *vfsswp;
1527
1528 if ((vfsp = vp->v_vfsp) != NULL &&
1529 ((vfsswp = vfssw + vfsp->vfs_fstype), vfsswp->vsw_name) &&
1530 *vfsswp->vsw_name) {
1531 (void) strcpy(s, vfsswp->vsw_name);
1532 s += strlen(s);
1533 *s++ = '.';
1534 }
1535 s += pr_u32tos(getmajor(vattr->va_fsid), s, 0);
1536 *s++ = '.';
1537 s += pr_u32tos(getminor(vattr->va_fsid), s, 0);
1538 *s++ = '.';
1539 s += pr_u64tos(vattr->va_nodeid, s);
1540 *s++ = '\0';
1541 }
1610 iol->piol_usedsize + sizeof (*iol) + itemsize) {
1611 /*
1612 * Out of space in the current buffer. Allocate more.
1613 */
1614 piol_t *newiol;
1615
1616 newiol = kmem_alloc(MAPSIZE, KM_SLEEP);
1617 newiol->piol_size = MAPSIZE;
1618 newiol->piol_usedsize = 0;
1619
1620 list_insert_after(iolhead, iol, newiol);
1621 iol = list_next(iolhead, iol);
1622 ASSERT(iol == newiol);
1623 }
1624 new = (char *)PIOL_DATABUF(iol) + iol->piol_usedsize;
1625 iol->piol_usedsize += itemsize;
1626 bzero(new, itemsize);
1627 return (new);
1628 }
1629
1630 void
1631 pr_iol_freelist(list_t *iolhead)
1632 {
1633 piol_t *iol;
1634
1635 while ((iol = list_head(iolhead)) != NULL) {
1636 list_remove(iolhead, iol);
1637 kmem_free(iol, iol->piol_size);
1638 }
1639 list_destroy(iolhead);
1640 }
1641
1642 int
1643 pr_iol_copyout_and_free(list_t *iolhead, caddr_t *tgt, int errin)
1644 {
1645 int error = errin;
1646 piol_t *iol;
1647
1648 while ((iol = list_head(iolhead)) != NULL) {
1649 list_remove(iolhead, iol);
1650 if (!error) {
1651 if (copyout(PIOL_DATABUF(iol), *tgt,
1652 iol->piol_usedsize))
1653 error = EFAULT;
1654 *tgt += iol->piol_usedsize;
1655 }
1656 kmem_free(iol, iol->piol_size);
1657 }
1658 list_destroy(iolhead);
1659
1660 return (error);
1661 }
2434 } while ((t = t->t_forw) != p->p_tlist);
2435
2436 psp->pr_pctcpu = prgetpctcpu(pct);
2437 }
2438 if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
2439 psp->pr_size = 0;
2440 psp->pr_rssize = 0;
2441 } else {
2442 mutex_exit(&p->p_lock);
2443 AS_LOCK_ENTER(as, RW_READER);
2444 psp->pr_size = btopr(as->a_resvsize) *
2445 (PAGESIZE / 1024);
2446 psp->pr_rssize = rm_asrss(as) * (PAGESIZE / 1024);
2447 psp->pr_pctmem = rm_pctmemory(as);
2448 AS_LOCK_EXIT(as);
2449 mutex_enter(&p->p_lock);
2450 }
2451 }
2452 }
2453
2454 static size_t
2455 prfdinfomisc(list_t *data, uint_t type, void *val, off_t vlen)
2456 {
2457 pr_misc_header_t *misc;
2458 size_t len;
2459
2460 len = sizeof (*misc) + vlen;
2461
2462 if (data != NULL) {
2463 misc = pr_iol_newbuf(data, len);
2464 misc->pr_misc_type = type;
2465 misc->pr_misc_size = len;
2466 misc++;
2467 bcopy((char *)val, (char *)misc, vlen);
2468 }
2469
2470 return (len);
2471 }
2472
2473 /*
2474 * There's no elegant way to determine if a character device
2475 * supports TLI, so just check a hardcoded list of known TLI
2476 * devices.
2477 */
2478
2479 static boolean_t
2480 pristli(vnode_t *vp)
2481 {
2482 static const char *tlidevs[] = {
2483 "udp", "udp6", "tcp", "tcp6", NULL
2484 };
2485 struct devnames *dnp;
2486 major_t major;
2487 uint_t i;
2488
2489 ASSERT(vp != NULL);
2490 ASSERT(vp->v_type == VCHR);
2491
2492 if (vp->v_rdev == 0)
2493 return (B_FALSE);
2494
2495 major = getmajor(vp->v_rdev);
2496 if (major == DDI_MAJOR_T_NONE || major > devcnt)
2497 return (B_FALSE);
2498
2499 dnp = &devnamesp[major];
2500
2501 for (i = 0; tlidevs[i] != NULL; i++) {
2502 if (strcmp(dnp->dn_name, tlidevs[i]) == 0)
2503 return (B_TRUE);
2504 }
2505
2506 return (B_FALSE);
2507 }
2508
2509 static size_t
2510 prfdinfopath(proc_t *p, vnode_t *vp, list_t *data, cred_t *cred)
2511 {
2512 char pathname[MAXPATHLEN];
2513 vnode_t *vrootp;
2514 size_t sz = 0;
2515
2516 mutex_enter(&p->p_lock);
2517 if ((vrootp = PTOU(p)->u_rdir) == NULL)
2518 vrootp = rootdir;
2519 VN_HOLD(vrootp);
2520 mutex_exit(&p->p_lock);
2521
2522 if (vnodetopath(vrootp, vp, pathname, sizeof (pathname), cred) == 0) {
2523 sz += prfdinfomisc(data, PR_PATHNAME,
2524 pathname, strlen(pathname));
2525 }
2526 VN_RELE(vrootp);
2527
2528 return (sz);
2529 }
2530
2531 static size_t
2532 prfdinfotlisockopt(vnode_t *vp, list_t *data, cred_t *cred)
2533 {
2534 strcmd_t strcmd;
2535 int32_t rval;
2536 size_t sz = 0;
2537
2538 strcmd.sc_cmd = TI_GETMYNAME;
2539 strcmd.sc_timeout = 1;
2540 strcmd.sc_len = STRCMDBUFSIZE;
2541
2542 if (VOP_IOCTL(vp, _I_CMD, (intptr_t)&strcmd, FKIOCTL, cred,
2543 &rval, NULL) == 0 && strcmd.sc_len > 0) {
2544 sz += prfdinfomisc(data, PR_SOCKETNAME, strcmd.sc_buf,
2545 strcmd.sc_len);
2546 }
2547
2548 strcmd.sc_cmd = TI_GETPEERNAME;
2549 strcmd.sc_timeout = 1;
2550 strcmd.sc_len = STRCMDBUFSIZE;
2551
2552 if (VOP_IOCTL(vp, _I_CMD, (intptr_t)&strcmd, FKIOCTL, cred,
2553 &rval, NULL) == 0 && strcmd.sc_len > 0) {
2554 sz += prfdinfomisc(data, PR_PEERSOCKNAME, strcmd.sc_buf,
2555 strcmd.sc_len);
2556 }
2557
2558 return (sz);
2559 }
2560
2561 static size_t
2562 prfdinfosockopt(vnode_t *vp, list_t *data, cred_t *cred)
2563 {
2564 sonode_t *so;
2565 socklen_t vlen;
2566 size_t sz = 0;
2567 uint_t i;
2568
2569 if (vp->v_stream) {
2570 so = VTOSO(vp->v_stream->sd_vnode);
2571
2572 if (so->so_version == SOV_STREAM)
2573 so = NULL;
2574 } else {
2575 so = VTOSO(vp);
2576 }
2577
2578 if (so == NULL)
2579 return (0);
2580
2581 DTRACE_PROBE1(sonode, sonode_t *, so);
2582
2583 /* prmisc - PR_SOCKETNAME */
2584
2585 struct sockaddr_storage buf;
2586 struct sockaddr *name = (struct sockaddr *)&buf;
2587
2588 vlen = sizeof (buf);
2589 if (SOP_GETSOCKNAME(so, name, &vlen, cred) == 0 && vlen > 0)
2590 sz += prfdinfomisc(data, PR_SOCKETNAME, name, vlen);
2591
2592 /* prmisc - PR_PEERSOCKNAME */
2593
2594 vlen = sizeof (buf);
2595 if (SOP_GETPEERNAME(so, name, &vlen, B_FALSE, cred) == 0 && vlen > 0)
2596 sz += prfdinfomisc(data, PR_PEERSOCKNAME, name, vlen);
2597
2598 /* prmisc - PR_SOCKOPTS_BOOL_OPTS */
2599
2600 static struct boolopt {
2601 int level;
2602 int opt;
2603 int bopt;
2604 } boolopts[] = {
2605 { SOL_SOCKET, SO_DEBUG, PR_SO_DEBUG },
2606 { SOL_SOCKET, SO_REUSEADDR, PR_SO_REUSEADDR },
2607 #ifdef SO_REUSEPORT
2608 /* SmartOS and OmniOS have SO_REUSEPORT */
2609 { SOL_SOCKET, SO_REUSEPORT, PR_SO_REUSEPORT },
2610 #endif
2611 { SOL_SOCKET, SO_KEEPALIVE, PR_SO_KEEPALIVE },
2612 { SOL_SOCKET, SO_DONTROUTE, PR_SO_DONTROUTE },
2613 { SOL_SOCKET, SO_BROADCAST, PR_SO_BROADCAST },
2614 { SOL_SOCKET, SO_OOBINLINE, PR_SO_OOBINLINE },
2615 { SOL_SOCKET, SO_DGRAM_ERRIND, PR_SO_DGRAM_ERRIND },
2616 { SOL_SOCKET, SO_ALLZONES, PR_SO_ALLZONES },
2617 { SOL_SOCKET, SO_MAC_EXEMPT, PR_SO_MAC_EXEMPT },
2618 { SOL_SOCKET, SO_MAC_IMPLICIT, PR_SO_MAC_IMPLICIT },
2619 { SOL_SOCKET, SO_EXCLBIND, PR_SO_EXCLBIND },
2620 { SOL_SOCKET, SO_VRRP, PR_SO_VRRP },
2621 { IPPROTO_UDP, UDP_NAT_T_ENDPOINT,
2622 PR_UDP_NAT_T_ENDPOINT }
2623 };
2624 prsockopts_bool_opts_t opts;
2625 int val;
2626
2627 if (data != NULL) {
2628 opts.prsock_bool_opts = 0;
2629
2630 for (i = 0; i < sizeof (boolopts) / sizeof (boolopts[0]);
2631 i++) {
2632 vlen = sizeof (val);
2633 if (SOP_GETSOCKOPT(so, boolopts[i].level,
2634 boolopts[i].opt, &val, &vlen, 0, cred) == 0 &&
2635 val != 0) {
2636 opts.prsock_bool_opts |= boolopts[i].bopt;
2637 }
2638 }
2639 }
2640
2641 sz += prfdinfomisc(data, PR_SOCKOPTS_BOOL_OPTS, &opts, sizeof (opts));
2642
2643 /* prmisc - PR_SOCKOPT_LINGER */
2644
2645 struct linger l;
2646
2647 vlen = sizeof (l);
2648 if (SOP_GETSOCKOPT(so, SOL_SOCKET, SO_LINGER, &l, &vlen,
2649 0, cred) == 0 && vlen > 0) {
2650 sz += prfdinfomisc(data, PR_SOCKOPT_LINGER, &l, vlen);
2651 }
2652
2653 /* prmisc - PR_SOCKOPT_* int types */
2654
2655 static struct sopt {
2656 int level;
2657 int opt;
2658 int bopt;
2659 } sopts[] = {
2660 { SOL_SOCKET, SO_TYPE, PR_SOCKOPT_TYPE },
2661 { SOL_SOCKET, SO_SNDBUF, PR_SOCKOPT_SNDBUF },
2662 { SOL_SOCKET, SO_RCVBUF, PR_SOCKOPT_RCVBUF }
2663 };
2664
2665 for (i = 0; i < sizeof (sopts) / sizeof (sopts[0]); i++) {
2666 vlen = sizeof (val);
2667 if (SOP_GETSOCKOPT(so, sopts[i].level, sopts[i].opt,
2668 &val, &vlen, 0, cred) == 0 && vlen > 0) {
2669 sz += prfdinfomisc(data, sopts[i].bopt, &val, vlen);
2670 }
2671 }
2672
2673 /* prmisc - PR_SOCKOPT_IP_NEXTHOP */
2674
2675 in_addr_t nexthop_val;
2676
2677 vlen = sizeof (nexthop_val);
2678 if (SOP_GETSOCKOPT(so, IPPROTO_IP, IP_NEXTHOP,
2679 &nexthop_val, &vlen, 0, cred) == 0 && vlen > 0) {
2680 sz += prfdinfomisc(data, PR_SOCKOPT_IP_NEXTHOP,
2681 &nexthop_val, vlen);
2682 }
2683
2684 /* prmisc - PR_SOCKOPT_IPV6_NEXTHOP */
2685
2686 struct sockaddr_in6 nexthop6_val;
2687
2688 vlen = sizeof (nexthop6_val);
2689 if (SOP_GETSOCKOPT(so, IPPROTO_IPV6, IPV6_NEXTHOP,
2690 &nexthop6_val, &vlen, 0, cred) == 0 && vlen > 0) {
2691 sz += prfdinfomisc(data, PR_SOCKOPT_IPV6_NEXTHOP,
2692 &nexthop6_val, vlen);
2693 }
2694
2695 /* prmisc - PR_SOCKOPT_TCP_CONGESTION */
2696
2697 char cong[CC_ALGO_NAME_MAX];
2698
2699 vlen = sizeof (cong);
2700 if (SOP_GETSOCKOPT(so, IPPROTO_TCP, TCP_CONGESTION,
2701 &cong, &vlen, 0, cred) == 0 && vlen > 0) {
2702 sz += prfdinfomisc(data, PR_SOCKOPT_TCP_CONGESTION, cong, vlen);
2703 }
2704
2705 /* prmisc - PR_SOCKFILTERS_PRIV */
2706
2707 struct fil_info fi;
2708
2709 vlen = sizeof (fi);
2710 if (SOP_GETSOCKOPT(so, SOL_FILTER, FIL_LIST,
2711 &fi, &vlen, 0, cred) == 0 && vlen != 0) {
2712 pr_misc_header_t *misc;
2713 size_t len;
2714
2715 /*
2716 * We limit the number of returned filters to 32.
2717 * This is the maximum number that pfiles will print
2718 * anyway.
2719 */
2720 vlen = MIN(32, fi.fi_pos + 1);
2721 vlen *= sizeof (fi);
2722
2723 len = sizeof (*misc) + vlen;
2724 sz += len;
2725
2726 if (data != NULL) {
2727 misc = pr_iol_newbuf(data, len);
2728 misc->pr_misc_type = PR_SOCKFILTERS_PRIV;
2729 misc->pr_misc_size = len;
2730 misc++;
2731 len = vlen;
2732 if (SOP_GETSOCKOPT(so, SOL_FILTER, FIL_LIST,
2733 misc, &vlen, 0, cred) == 0) {
2734 /*
2735 * In case the number of filters has reduced
2736 * since the first call, explicitly zero out
2737 * any unpopulated space.
2738 */
2739 if (vlen < len)
2740 bzero(misc + vlen, len - vlen);
2741 } else {
2742 /* Something went wrong, zero out the result */
2743 bzero(misc, vlen);
2744 }
2745 }
2746 }
2747
2748 return (sz);
2749 }
2750
2751 u_offset_t
2752 prgetfdinfosize(proc_t *p, vnode_t *vp, cred_t *cred)
2753 {
2754 u_offset_t sz;
2755
2756 /*
2757 * All fdinfo files will be at least this big -
2758 * sizeof fdinfo struct + zero length trailer
2759 */
2760 sz = offsetof(prfdinfov2_t, pr_misc) + sizeof (pr_misc_header_t);
2761
2762 /* Pathname */
2763 if (vp->v_type != VSOCK && vp->v_type != VDOOR)
2764 sz += prfdinfopath(p, vp, NULL, cred);
2765
2766 /* Socket options */
2767 if (vp->v_type == VSOCK)
2768 sz += prfdinfosockopt(vp, NULL, cred);
2769
2770 /* TLI/XTI sockets */
2771 if (vp->v_type == VCHR && pristli(vp) && vp->v_stream != NULL)
2772 sz += prfdinfotlisockopt(vp, NULL, cred);
2773
2774 return (sz);
2775 }
2776
2777 int
2778 prgetfdinfo(proc_t *p, vnode_t *vp, prfdinfov2_t *fdinfo, cred_t *cred,
2779 list_t *data)
2780 {
2781 vattr_t vattr;
2782 int error;
2783
2784 if (vp == NULL)
2785 return (ENOENT);
2786
2787 /*
2788 * Initialise defaults for values that do not default to zero.
2789 */
2790 fdinfo->pr_uid = (uid_t)-1;
2791 fdinfo->pr_gid = (gid_t)-1;
2792 fdinfo->pr_size = -1;
2793 fdinfo->pr_locktype = F_UNLCK;
2794 fdinfo->pr_lockpid = -1;
2795 fdinfo->pr_locksysid = -1;
2796 fdinfo->pr_peerpid = -1;
2797
2798 /* Offset */
2799
2800 switch (vp->v_type) {
2801 case VFIFO:
2802 case VDOOR:
2803 case VSOCK:
2804 /* Do not provide an offset for these file types */
2805 fdinfo->pr_offset = -1;
2806 break;
2807 }
2808
2809 /* Attributes */
2810 vattr.va_mask = AT_STAT;
2811 if (VOP_GETATTR(vp, &vattr, 0, cred, NULL) == 0) {
2812 fdinfo->pr_major = getmajor(vattr.va_fsid);
2813 fdinfo->pr_minor = getminor(vattr.va_fsid);
2814 fdinfo->pr_rmajor = getmajor(vattr.va_rdev);
2815 fdinfo->pr_rminor = getminor(vattr.va_rdev);
2816 fdinfo->pr_ino = (ino64_t)vattr.va_nodeid;
2817 fdinfo->pr_size = (off64_t)vattr.va_size;
2818 fdinfo->pr_mode = VTTOIF(vattr.va_type) | vattr.va_mode;
2819 fdinfo->pr_uid = vattr.va_uid;
2820 fdinfo->pr_gid = vattr.va_gid;
2821 if (vp->v_type == VSOCK)
2822 fdinfo->pr_fileflags |= sock_getfasync(vp);
2823 }
2824
2825 /* locks */
2826
2827 flock64_t bf;
2828
2829 bzero(&bf, sizeof (bf));
2830 bf.l_type = F_WRLCK;
2831
2832 if (VOP_FRLOCK(vp, F_GETLK, &bf,
2833 (uint16_t)(fdinfo->pr_fileflags & 0xffff), 0, NULL,
2834 cred, NULL) == 0 && bf.l_type != F_UNLCK) {
2835 fdinfo->pr_locktype = bf.l_type;
2836 fdinfo->pr_lockpid = bf.l_pid;
2837 fdinfo->pr_locksysid = bf.l_sysid;
2838 }
2839
2840 /* peer cred */
2841
2842 k_peercred_t kpc;
2843
2844 switch (vp->v_type) {
2845 case VFIFO:
2846 case VSOCK: {
2847 int32_t rval;
2848
2849 error = VOP_IOCTL(vp, _I_GETPEERCRED, (intptr_t)&kpc,
2850 FKIOCTL, cred, &rval, NULL);
2851 break;
2852 }
2853 case VCHR: {
2854 struct strioctl strioc;
2855 int32_t rval;
2856
2857 if (vp->v_stream == NULL) {
2858 error = ENOTSUP;
2859 break;
2860 }
2861 strioc.ic_cmd = _I_GETPEERCRED;
2862 strioc.ic_timout = INFTIM;
2863 strioc.ic_len = (int)sizeof (k_peercred_t);
2864 strioc.ic_dp = (char *)&kpc;
2865
2866 error = strdoioctl(vp->v_stream, &strioc, FNATIVE | FKIOCTL,
2867 STR_NOSIG | K_TO_K, cred, &rval);
2868 break;
2869 }
2870 default:
2871 error = ENOTSUP;
2872 }
2873
2874 if (error == 0 && kpc.pc_cr != NULL) {
2875 proc_t *peerp;
2876
2877 fdinfo->pr_peerpid = kpc.pc_cpid;
2878
2879 crfree(kpc.pc_cr);
2880
2881 mutex_enter(&pidlock);
2882 if ((peerp = prfind(fdinfo->pr_peerpid)) != NULL) {
2883 user_t *up;
2884
2885 mutex_enter(&peerp->p_lock);
2886 mutex_exit(&pidlock);
2887
2888 up = PTOU(peerp);
2889 bcopy(up->u_comm, fdinfo->pr_peername,
2890 MIN(sizeof (up->u_comm),
2891 sizeof (fdinfo->pr_peername) - 1));
2892
2893 mutex_exit(&peerp->p_lock);
2894 } else {
2895 mutex_exit(&pidlock);
2896 }
2897 }
2898
2899 /*
2900 * Don't attempt to determine the vnode path for a socket or a door
2901 * as it will cause a linear scan of the dnlc table given there is no
2902 * v_path associated with the vnode.
2903 */
2904 if (vp->v_type != VSOCK && vp->v_type != VDOOR)
2905 (void) prfdinfopath(p, vp, data, cred);
2906
2907 if (vp->v_type == VSOCK)
2908 (void) prfdinfosockopt(vp, data, cred);
2909
2910 /* TLI/XTI stream sockets */
2911 if (vp->v_type == VCHR && pristli(vp) && vp->v_stream != NULL)
2912 (void) prfdinfotlisockopt(vp, data, cred);
2913
2914 /*
2915 * Add a terminating record with a zero size (pr_iol_newbuf will
2916 * bzero the memory)
2917 */
2918 (void) pr_iol_newbuf(data, sizeof (pr_misc_header_t));
2919
2920 return (0);
2921 }
2922
2923 #ifdef _SYSCALL32_IMPL
2924 void
2925 prgetpsinfo32(proc_t *p, psinfo32_t *psp)
2926 {
2927 kthread_t *t;
2928 struct cred *cred;
2929 hrtime_t hrutime, hrstime;
2930
2931 ASSERT(MUTEX_HELD(&p->p_lock));
2932
2933 if ((t = prchoose(p)) == NULL) /* returns locked thread */
2934 bzero(psp, sizeof (*psp));
2935 else {
2936 thread_unlock(t);
2937 bzero(psp, sizeof (*psp) - sizeof (psp->pr_lwp));
2938 }
2939
2940 /*
2941 * only export SSYS and SMSACCT; everything else is off-limits to
2942 * userland apps.
|