3129 int n;
3130
3131 /*
3132 * By fiat, a system process has no address space.
3133 */
3134 if ((p->p_flag & SSYS) || as == &kas) {
3135 error = EINVAL;
3136 } else if (cmaddr) {
3137 /*
3138 * We drop p_lock before grabbing the address
3139 * space lock in order to avoid a deadlock with
3140 * the clock thread. The process will not
3141 * disappear and its address space will not
3142 * change because it is marked P_PR_LOCK.
3143 */
3144 mutex_exit(&p->p_lock);
3145 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
3146 seg = as_segat(as, va);
3147 if (seg != NULL &&
3148 seg->s_ops == &segvn_ops &&
3149 SEGOP_GETVP(seg, va, &xvp) == 0 &&
3150 xvp != NULL &&
3151 xvp->v_type == VREG) {
3152 VN_HOLD(xvp);
3153 } else {
3154 error = EINVAL;
3155 }
3156 AS_LOCK_EXIT(as, &as->a_lock);
3157 mutex_enter(&p->p_lock);
3158 } else if ((xvp = p->p_exec) == NULL) {
3159 error = EINVAL;
3160 } else {
3161 VN_HOLD(xvp);
3162 }
3163
3164 prunlock(pnp);
3165
3166 if (error == 0) {
3167 if ((error = VOP_ACCESS(xvp, VREAD, 0, cr, NULL)) == 0)
3168 error = fassign(&xvp, FREAD, &n);
3169 if (error) {
3534 if ((seg = AS_SEGFIRST(as)) == NULL)
3535 return (0);
3536
3537 brkseg = break_seg(p);
3538 stkseg = as_segat(as, prgetstackbase(p));
3539
3540 do {
3541 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3542 caddr_t saddr, naddr;
3543 void *tmp = NULL;
3544
3545 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3546 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3547 if (saddr == naddr)
3548 continue;
3549
3550 mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3551
3552 mp->pr_vaddr = saddr;
3553 mp->pr_size = naddr - saddr;
3554 mp->pr_off = SEGOP_GETOFFSET(seg, saddr);
3555 mp->pr_mflags = 0;
3556 if (prot & PROT_READ)
3557 mp->pr_mflags |= MA_READ;
3558 if (prot & PROT_WRITE)
3559 mp->pr_mflags |= MA_WRITE;
3560 if (prot & PROT_EXEC)
3561 mp->pr_mflags |= MA_EXEC;
3562 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3563 mp->pr_mflags |= MA_SHARED;
3564 if (seg == brkseg)
3565 mp->pr_mflags |= MA_BREAK;
3566 else if (seg == stkseg)
3567 mp->pr_mflags |= MA_STACK;
3568 mp->pr_pagesize = PAGESIZE;
3569 }
3570 ASSERT(tmp == NULL);
3571 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3572
3573 return (0);
3574 }
3575
3576 #ifdef _SYSCALL32_IMPL
3577 static int
3578 oprgetmap32(proc_t *p, list_t *iolhead)
3579 {
3580 struct as *as = p->p_as;
3581 ioc_prmap32_t *mp;
3582 struct seg *seg;
3594 if ((seg = AS_SEGFIRST(as)) == NULL)
3595 return (0);
3596
3597 brkseg = break_seg(p);
3598 stkseg = as_segat(as, prgetstackbase(p));
3599
3600 do {
3601 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3602 caddr_t saddr, naddr;
3603 void *tmp = NULL;
3604
3605 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3606 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3607 if (saddr == naddr)
3608 continue;
3609
3610 mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3611
3612 mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
3613 mp->pr_size = (size32_t)(naddr - saddr);
3614 mp->pr_off = (off32_t)SEGOP_GETOFFSET(seg, saddr);
3615 mp->pr_mflags = 0;
3616 if (prot & PROT_READ)
3617 mp->pr_mflags |= MA_READ;
3618 if (prot & PROT_WRITE)
3619 mp->pr_mflags |= MA_WRITE;
3620 if (prot & PROT_EXEC)
3621 mp->pr_mflags |= MA_EXEC;
3622 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3623 mp->pr_mflags |= MA_SHARED;
3624 if (seg == brkseg)
3625 mp->pr_mflags |= MA_BREAK;
3626 else if (seg == stkseg)
3627 mp->pr_mflags |= MA_STACK;
3628 mp->pr_pagesize = PAGESIZE;
3629 }
3630 ASSERT(tmp == NULL);
3631 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3632
3633 return (0);
3634 }
3635 #endif /* _SYSCALL32_IMPL */
3636
3637 /*
3638 * Return the size of the old /proc page data file.
3639 */
3640 size_t
3641 oprpdsize(struct as *as)
3642 {
3736 void *tmp = NULL;
3737
3738 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3739 size_t len;
3740 size_t npage;
3741 uint_t prot;
3742 uintptr_t next;
3743
3744 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3745 if ((len = naddr - saddr) == 0)
3746 continue;
3747 npage = len / PAGESIZE;
3748 next = (uintptr_t)(pmp + 1) + roundlong(npage);
3749 /*
3750 * It's possible that the address space can change
3751 * subtlely even though we're holding as->a_lock
3752 * due to the nondeterminism of page_exists() in
3753 * the presence of asychronously flushed pages or
3754 * mapped files whose sizes are changing.
3755 * page_exists() may be called indirectly from
3756 * pr_getprot() by a SEGOP_INCORE() routine.
3757 * If this happens we need to make sure we don't
3758 * overrun the buffer whose size we computed based
3759 * on the initial iteration through the segments.
3760 * Once we've detected an overflow, we need to clean
3761 * up the temporary memory allocated in pr_getprot()
3762 * and retry. If there's a pending signal, we return
3763 * EINTR so that this thread can be dislodged if
3764 * a latent bug causes us to spin indefinitely.
3765 */
3766 if (next > (uintptr_t)buf + size) {
3767 pr_getprot_done(&tmp);
3768 AS_LOCK_EXIT(as, &as->a_lock);
3769
3770 kmem_free(buf, size);
3771
3772 if (ISSIG(curthread, JUSTLOOKING))
3773 return (EINTR);
3774
3775 goto again;
3776 }
3777
3778 php->pr_nmap++;
3779 php->pr_npage += npage;
3780 pmp->pr_vaddr = saddr;
3781 pmp->pr_npage = npage;
3782 pmp->pr_off = SEGOP_GETOFFSET(seg, saddr);
3783 pmp->pr_mflags = 0;
3784 if (prot & PROT_READ)
3785 pmp->pr_mflags |= MA_READ;
3786 if (prot & PROT_WRITE)
3787 pmp->pr_mflags |= MA_WRITE;
3788 if (prot & PROT_EXEC)
3789 pmp->pr_mflags |= MA_EXEC;
3790 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3791 pmp->pr_mflags |= MA_SHARED;
3792 pmp->pr_pagesize = PAGESIZE;
3793 hat_getstat(as, saddr, len, hatid,
3794 (char *)(pmp + 1), HAT_SYNC_ZERORM);
3795 pmp = (prasmap_t *)next;
3796 }
3797 ASSERT(tmp == NULL);
3798 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3799
3800 AS_LOCK_EXIT(as, &as->a_lock);
3801
3802 ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
3803 error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3804 kmem_free(buf, size);
3805
3806 return (error);
3807 }
3808
3809 #ifdef _SYSCALL32_IMPL
3810 int
3843 void *tmp = NULL;
3844
3845 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3846 size_t len;
3847 size_t npage;
3848 uint_t prot;
3849 uintptr_t next;
3850
3851 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3852 if ((len = naddr - saddr) == 0)
3853 continue;
3854 npage = len / PAGESIZE;
3855 next = (uintptr_t)(pmp + 1) + round4(npage);
3856 /*
3857 * It's possible that the address space can change
3858 * subtlely even though we're holding as->a_lock
3859 * due to the nondeterminism of page_exists() in
3860 * the presence of asychronously flushed pages or
3861 * mapped files whose sizes are changing.
3862 * page_exists() may be called indirectly from
3863 * pr_getprot() by a SEGOP_INCORE() routine.
3864 * If this happens we need to make sure we don't
3865 * overrun the buffer whose size we computed based
3866 * on the initial iteration through the segments.
3867 * Once we've detected an overflow, we need to clean
3868 * up the temporary memory allocated in pr_getprot()
3869 * and retry. If there's a pending signal, we return
3870 * EINTR so that this thread can be dislodged if
3871 * a latent bug causes us to spin indefinitely.
3872 */
3873 if (next > (uintptr_t)buf + size) {
3874 pr_getprot_done(&tmp);
3875 AS_LOCK_EXIT(as, &as->a_lock);
3876
3877 kmem_free(buf, size);
3878
3879 if (ISSIG(curthread, JUSTLOOKING))
3880 return (EINTR);
3881
3882 goto again;
3883 }
3884
3885 php->pr_nmap++;
3886 php->pr_npage += npage;
3887 pmp->pr_vaddr = (uint32_t)(uintptr_t)saddr;
3888 pmp->pr_npage = (uint32_t)npage;
3889 pmp->pr_off = (int32_t)SEGOP_GETOFFSET(seg, saddr);
3890 pmp->pr_mflags = 0;
3891 if (prot & PROT_READ)
3892 pmp->pr_mflags |= MA_READ;
3893 if (prot & PROT_WRITE)
3894 pmp->pr_mflags |= MA_WRITE;
3895 if (prot & PROT_EXEC)
3896 pmp->pr_mflags |= MA_EXEC;
3897 if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3898 pmp->pr_mflags |= MA_SHARED;
3899 pmp->pr_pagesize = PAGESIZE;
3900 hat_getstat(as, saddr, len, hatid,
3901 (char *)(pmp + 1), HAT_SYNC_ZERORM);
3902 pmp = (ioc_prasmap32_t *)next;
3903 }
3904 ASSERT(tmp == NULL);
3905 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3906
3907 AS_LOCK_EXIT(as, &as->a_lock);
3908
3909 ASSERT((uintptr_t)pmp == (uintptr_t)buf + size);
3910 error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3911 kmem_free(buf, size);
3912
3913 return (error);
3914 }
3915 #endif /* _SYSCALL32_IMPL */
3916
3917 /*ARGSUSED*/
|
3129 int n;
3130
3131 /*
3132 * By fiat, a system process has no address space.
3133 */
3134 if ((p->p_flag & SSYS) || as == &kas) {
3135 error = EINVAL;
3136 } else if (cmaddr) {
3137 /*
3138 * We drop p_lock before grabbing the address
3139 * space lock in order to avoid a deadlock with
3140 * the clock thread. The process will not
3141 * disappear and its address space will not
3142 * change because it is marked P_PR_LOCK.
3143 */
3144 mutex_exit(&p->p_lock);
3145 AS_LOCK_ENTER(as, &as->a_lock, RW_READER);
3146 seg = as_segat(as, va);
3147 if (seg != NULL &&
3148 seg->s_ops == &segvn_ops &&
3149 segop_getvp(seg, va, &xvp) == 0 &&
3150 xvp != NULL &&
3151 xvp->v_type == VREG) {
3152 VN_HOLD(xvp);
3153 } else {
3154 error = EINVAL;
3155 }
3156 AS_LOCK_EXIT(as, &as->a_lock);
3157 mutex_enter(&p->p_lock);
3158 } else if ((xvp = p->p_exec) == NULL) {
3159 error = EINVAL;
3160 } else {
3161 VN_HOLD(xvp);
3162 }
3163
3164 prunlock(pnp);
3165
3166 if (error == 0) {
3167 if ((error = VOP_ACCESS(xvp, VREAD, 0, cr, NULL)) == 0)
3168 error = fassign(&xvp, FREAD, &n);
3169 if (error) {
3534 if ((seg = AS_SEGFIRST(as)) == NULL)
3535 return (0);
3536
3537 brkseg = break_seg(p);
3538 stkseg = as_segat(as, prgetstackbase(p));
3539
3540 do {
3541 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3542 caddr_t saddr, naddr;
3543 void *tmp = NULL;
3544
3545 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3546 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3547 if (saddr == naddr)
3548 continue;
3549
3550 mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3551
3552 mp->pr_vaddr = saddr;
3553 mp->pr_size = naddr - saddr;
3554 mp->pr_off = segop_getoffset(seg, saddr);
3555 mp->pr_mflags = 0;
3556 if (prot & PROT_READ)
3557 mp->pr_mflags |= MA_READ;
3558 if (prot & PROT_WRITE)
3559 mp->pr_mflags |= MA_WRITE;
3560 if (prot & PROT_EXEC)
3561 mp->pr_mflags |= MA_EXEC;
3562 if (segop_gettype(seg, saddr) & MAP_SHARED)
3563 mp->pr_mflags |= MA_SHARED;
3564 if (seg == brkseg)
3565 mp->pr_mflags |= MA_BREAK;
3566 else if (seg == stkseg)
3567 mp->pr_mflags |= MA_STACK;
3568 mp->pr_pagesize = PAGESIZE;
3569 }
3570 ASSERT(tmp == NULL);
3571 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3572
3573 return (0);
3574 }
3575
3576 #ifdef _SYSCALL32_IMPL
3577 static int
3578 oprgetmap32(proc_t *p, list_t *iolhead)
3579 {
3580 struct as *as = p->p_as;
3581 ioc_prmap32_t *mp;
3582 struct seg *seg;
3594 if ((seg = AS_SEGFIRST(as)) == NULL)
3595 return (0);
3596
3597 brkseg = break_seg(p);
3598 stkseg = as_segat(as, prgetstackbase(p));
3599
3600 do {
3601 caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3602 caddr_t saddr, naddr;
3603 void *tmp = NULL;
3604
3605 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3606 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3607 if (saddr == naddr)
3608 continue;
3609
3610 mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3611
3612 mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
3613 mp->pr_size = (size32_t)(naddr - saddr);
3614 mp->pr_off = (off32_t)segop_getoffset(seg, saddr);
3615 mp->pr_mflags = 0;
3616 if (prot & PROT_READ)
3617 mp->pr_mflags |= MA_READ;
3618 if (prot & PROT_WRITE)
3619 mp->pr_mflags |= MA_WRITE;
3620 if (prot & PROT_EXEC)
3621 mp->pr_mflags |= MA_EXEC;
3622 if (segop_gettype(seg, saddr) & MAP_SHARED)
3623 mp->pr_mflags |= MA_SHARED;
3624 if (seg == brkseg)
3625 mp->pr_mflags |= MA_BREAK;
3626 else if (seg == stkseg)
3627 mp->pr_mflags |= MA_STACK;
3628 mp->pr_pagesize = PAGESIZE;
3629 }
3630 ASSERT(tmp == NULL);
3631 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3632
3633 return (0);
3634 }
3635 #endif /* _SYSCALL32_IMPL */
3636
3637 /*
3638 * Return the size of the old /proc page data file.
3639 */
3640 size_t
3641 oprpdsize(struct as *as)
3642 {
3736 void *tmp = NULL;
3737
3738 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3739 size_t len;
3740 size_t npage;
3741 uint_t prot;
3742 uintptr_t next;
3743
3744 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3745 if ((len = naddr - saddr) == 0)
3746 continue;
3747 npage = len / PAGESIZE;
3748 next = (uintptr_t)(pmp + 1) + roundlong(npage);
3749 /*
3750 * It's possible that the address space can change
3751 * subtlely even though we're holding as->a_lock
3752 * due to the nondeterminism of page_exists() in
3753 * the presence of asychronously flushed pages or
3754 * mapped files whose sizes are changing.
3755 * page_exists() may be called indirectly from
3756 * pr_getprot() by a segop_incore() routine.
3757 * If this happens we need to make sure we don't
3758 * overrun the buffer whose size we computed based
3759 * on the initial iteration through the segments.
3760 * Once we've detected an overflow, we need to clean
3761 * up the temporary memory allocated in pr_getprot()
3762 * and retry. If there's a pending signal, we return
3763 * EINTR so that this thread can be dislodged if
3764 * a latent bug causes us to spin indefinitely.
3765 */
3766 if (next > (uintptr_t)buf + size) {
3767 pr_getprot_done(&tmp);
3768 AS_LOCK_EXIT(as, &as->a_lock);
3769
3770 kmem_free(buf, size);
3771
3772 if (ISSIG(curthread, JUSTLOOKING))
3773 return (EINTR);
3774
3775 goto again;
3776 }
3777
3778 php->pr_nmap++;
3779 php->pr_npage += npage;
3780 pmp->pr_vaddr = saddr;
3781 pmp->pr_npage = npage;
3782 pmp->pr_off = segop_getoffset(seg, saddr);
3783 pmp->pr_mflags = 0;
3784 if (prot & PROT_READ)
3785 pmp->pr_mflags |= MA_READ;
3786 if (prot & PROT_WRITE)
3787 pmp->pr_mflags |= MA_WRITE;
3788 if (prot & PROT_EXEC)
3789 pmp->pr_mflags |= MA_EXEC;
3790 if (segop_gettype(seg, saddr) & MAP_SHARED)
3791 pmp->pr_mflags |= MA_SHARED;
3792 pmp->pr_pagesize = PAGESIZE;
3793 hat_getstat(as, saddr, len, hatid,
3794 (char *)(pmp + 1), HAT_SYNC_ZERORM);
3795 pmp = (prasmap_t *)next;
3796 }
3797 ASSERT(tmp == NULL);
3798 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3799
3800 AS_LOCK_EXIT(as, &as->a_lock);
3801
3802 ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
3803 error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3804 kmem_free(buf, size);
3805
3806 return (error);
3807 }
3808
3809 #ifdef _SYSCALL32_IMPL
3810 int
3843 void *tmp = NULL;
3844
3845 for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3846 size_t len;
3847 size_t npage;
3848 uint_t prot;
3849 uintptr_t next;
3850
3851 prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3852 if ((len = naddr - saddr) == 0)
3853 continue;
3854 npage = len / PAGESIZE;
3855 next = (uintptr_t)(pmp + 1) + round4(npage);
3856 /*
3857 * It's possible that the address space can change
3858 * subtlely even though we're holding as->a_lock
3859 * due to the nondeterminism of page_exists() in
3860 * the presence of asychronously flushed pages or
3861 * mapped files whose sizes are changing.
3862 * page_exists() may be called indirectly from
3863 * pr_getprot() by a segop_incore() routine.
3864 * If this happens we need to make sure we don't
3865 * overrun the buffer whose size we computed based
3866 * on the initial iteration through the segments.
3867 * Once we've detected an overflow, we need to clean
3868 * up the temporary memory allocated in pr_getprot()
3869 * and retry. If there's a pending signal, we return
3870 * EINTR so that this thread can be dislodged if
3871 * a latent bug causes us to spin indefinitely.
3872 */
3873 if (next > (uintptr_t)buf + size) {
3874 pr_getprot_done(&tmp);
3875 AS_LOCK_EXIT(as, &as->a_lock);
3876
3877 kmem_free(buf, size);
3878
3879 if (ISSIG(curthread, JUSTLOOKING))
3880 return (EINTR);
3881
3882 goto again;
3883 }
3884
3885 php->pr_nmap++;
3886 php->pr_npage += npage;
3887 pmp->pr_vaddr = (uint32_t)(uintptr_t)saddr;
3888 pmp->pr_npage = (uint32_t)npage;
3889 pmp->pr_off = (int32_t)segop_getoffset(seg, saddr);
3890 pmp->pr_mflags = 0;
3891 if (prot & PROT_READ)
3892 pmp->pr_mflags |= MA_READ;
3893 if (prot & PROT_WRITE)
3894 pmp->pr_mflags |= MA_WRITE;
3895 if (prot & PROT_EXEC)
3896 pmp->pr_mflags |= MA_EXEC;
3897 if (segop_gettype(seg, saddr) & MAP_SHARED)
3898 pmp->pr_mflags |= MA_SHARED;
3899 pmp->pr_pagesize = PAGESIZE;
3900 hat_getstat(as, saddr, len, hatid,
3901 (char *)(pmp + 1), HAT_SYNC_ZERORM);
3902 pmp = (ioc_prasmap32_t *)next;
3903 }
3904 ASSERT(tmp == NULL);
3905 } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3906
3907 AS_LOCK_EXIT(as, &as->a_lock);
3908
3909 ASSERT((uintptr_t)pmp == (uintptr_t)buf + size);
3910 error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3911 kmem_free(buf, size);
3912
3913 return (error);
3914 }
3915 #endif /* _SYSCALL32_IMPL */
3916
3917 /*ARGSUSED*/
|