|
Lines 59-64
Link Here
|
| 59 |
#include <sys/unistd.h> |
59 |
#include <sys/unistd.h> |
| 60 |
#include <sys/vnode.h> |
60 |
#include <sys/vnode.h> |
| 61 |
#include <sys/proc.h> |
61 |
#include <sys/proc.h> |
|
|
62 |
#include <sys/jail.h> |
| 62 |
#include <sys/dirent.h> |
63 |
#include <sys/dirent.h> |
| 63 |
#include <sys/extattr.h> |
64 |
#include <sys/extattr.h> |
| 64 |
|
65 |
|
|
Lines 72-77
Link Here
|
| 72 |
|
73 |
|
| 73 |
static int change_dir __P((struct nameidata *ndp, struct proc *p)); |
74 |
static int change_dir __P((struct nameidata *ndp, struct proc *p)); |
| 74 |
static void checkdirs __P((struct vnode *olddp)); |
75 |
static void checkdirs __P((struct vnode *olddp)); |
|
|
76 |
static int check_prison_mount __P((struct proc *p, struct statfs *sp)); |
| 77 |
static void trim_prison_mount __P((struct statfs *sp, int pripl)); |
| 75 |
static int chroot_refuse_vdir_fds __P((struct filedesc *fdp)); |
78 |
static int chroot_refuse_vdir_fds __P((struct filedesc *fdp)); |
| 76 |
static int getutimes __P((const struct timeval *, struct timespec *)); |
79 |
static int getutimes __P((const struct timeval *, struct timespec *)); |
| 77 |
static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t)); |
80 |
static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t)); |
|
Lines 609-614
Link Here
|
| 609 |
} |
612 |
} |
| 610 |
|
613 |
|
| 611 |
/* |
614 |
/* |
|
|
615 |
* Check if we're imprisoned and whether the mountpoint |
| 616 |
* is inside our prison. Return values: |
| 617 |
* -1 if we're not supposed to see this mount. |
| 618 |
* 0 if it's alright. |
| 619 |
* >0 strip that many characters from the beginning of |
| 620 |
* the path of the mountpoint. E.g. if the mount |
| 621 |
* point is /foo/bar and the jail is chrooted at /foo, |
| 622 |
* 4 is be returned, so only /bar will be left. |
| 623 |
*/ |
| 624 |
static int |
| 625 |
check_prison_mount(p, sp) |
| 626 |
struct proc *p; |
| 627 |
struct statfs *sp; |
| 628 |
{ |
| 629 |
register char *prip; /* prison path */ |
| 630 |
register int pripl; /* prison path length */ |
| 631 |
|
| 632 |
if (!p->p_prison) |
| 633 |
return (0); |
| 634 |
prip = p->p_prison->pr_path; |
| 635 |
pripl = strlen(prip); |
| 636 |
if (pripl > 0 && prip[pripl - 1] == '/') |
| 637 |
pripl--; /* ignore trailing slash, if any */ |
| 638 |
/* |
| 639 |
* Note that it is not sufficient to check for the |
| 640 |
* first <pripl> characters to be the same. |
| 641 |
* We also have to make sure that the next character |
| 642 |
* in the mountpoint path is either '\0' or '/'. |
| 643 |
* Otherwise a jail in "/foo/bar" would be allowed |
| 644 |
* to see a mount at "/foo/barbara". |
| 645 |
*/ |
| 646 |
if (strncmp(prip, sp->f_mntonname, pripl) != 0 || |
| 647 |
(sp->f_mntonname[pripl] != '\0' && sp->f_mntonname[pripl] != '/')) |
| 648 |
return (-1); /* not our business */ |
| 649 |
return (pripl); |
| 650 |
} |
| 651 |
|
| 652 |
/* |
| 653 |
* Remove the jail chroot path from the mountpoint, |
| 654 |
* so that imprisoned users see everything relative |
| 655 |
* to their jail chroot. |
| 656 |
*/ |
| 657 |
static void |
| 658 |
trim_prison_mount(sp, pripl) |
| 659 |
struct statfs *sp; |
| 660 |
int pripl; /* prison path length */ |
| 661 |
{ |
| 662 |
strcpy(sp->f_mntonname, sp->f_mntonname + pripl); |
| 663 |
/* If there's nothing left, this ought to be "/". */ |
| 664 |
if (sp->f_mntonname[0] == '\0') { |
| 665 |
sp->f_mntonname[0] = '/'; |
| 666 |
sp->f_mntonname[1] = '\0'; |
| 667 |
} |
| 668 |
} |
| 669 |
|
| 670 |
/* |
| 612 |
* Get filesystem statistics. |
671 |
* Get filesystem statistics. |
| 613 |
*/ |
672 |
*/ |
| 614 |
#ifndef _SYS_SYSPROTO_H_ |
673 |
#ifndef _SYS_SYSPROTO_H_ |
|
Lines 629-634
Link Here
|
| 629 |
register struct mount *mp; |
688 |
register struct mount *mp; |
| 630 |
register struct statfs *sp; |
689 |
register struct statfs *sp; |
| 631 |
int error; |
690 |
int error; |
|
|
691 |
int pripl; |
| 692 |
int nonsu; |
| 632 |
struct nameidata nd; |
693 |
struct nameidata nd; |
| 633 |
struct statfs sb; |
694 |
struct statfs sb; |
| 634 |
|
695 |
|
|
Lines 639-651
Link Here
|
| 639 |
sp = &mp->mnt_stat; |
700 |
sp = &mp->mnt_stat; |
| 640 |
NDFREE(&nd, NDF_ONLY_PNBUF); |
701 |
NDFREE(&nd, NDF_ONLY_PNBUF); |
| 641 |
vrele(nd.ni_vp); |
702 |
vrele(nd.ni_vp); |
|
|
703 |
if ((pripl = check_prison_mount(p, sp)) < 0) |
| 704 |
return (ENOENT); |
| 642 |
error = VFS_STATFS(mp, sp, p); |
705 |
error = VFS_STATFS(mp, sp, p); |
| 643 |
if (error) |
706 |
if (error) |
| 644 |
return (error); |
707 |
return (error); |
| 645 |
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; |
708 |
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; |
| 646 |
if (suser_xxx(p->p_ucred, 0, 0)) { |
709 |
nonsu = suser_xxx(p->p_ucred, 0, 0); |
|
|
710 |
if (nonsu || pripl) { |
| 647 |
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); |
711 |
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); |
| 648 |
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; |
712 |
if (nonsu) |
|
|
713 |
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; |
| 714 |
if (pripl) |
| 715 |
trim_prison_mount(&sb, pripl); |
| 649 |
sp = &sb; |
716 |
sp = &sb; |
| 650 |
} |
717 |
} |
| 651 |
return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); |
718 |
return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); |
|
Lines 673-691
Link Here
|
| 673 |
struct mount *mp; |
740 |
struct mount *mp; |
| 674 |
register struct statfs *sp; |
741 |
register struct statfs *sp; |
| 675 |
int error; |
742 |
int error; |
|
|
743 |
int pripl; |
| 744 |
int nonsu; |
| 676 |
struct statfs sb; |
745 |
struct statfs sb; |
| 677 |
|
746 |
|
| 678 |
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) |
747 |
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) |
| 679 |
return (error); |
748 |
return (error); |
| 680 |
mp = ((struct vnode *)fp->f_data)->v_mount; |
749 |
mp = ((struct vnode *)fp->f_data)->v_mount; |
| 681 |
sp = &mp->mnt_stat; |
750 |
sp = &mp->mnt_stat; |
|
|
751 |
if ((pripl = check_prison_mount(p, sp)) < 0) |
| 752 |
return (ENOENT); |
| 682 |
error = VFS_STATFS(mp, sp, p); |
753 |
error = VFS_STATFS(mp, sp, p); |
| 683 |
if (error) |
754 |
if (error) |
| 684 |
return (error); |
755 |
return (error); |
| 685 |
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; |
756 |
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; |
| 686 |
if (suser_xxx(p->p_ucred, 0, 0)) { |
757 |
nonsu = suser_xxx(p->p_ucred, 0, 0); |
|
|
758 |
if (nonsu || pripl) { |
| 687 |
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); |
759 |
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); |
| 688 |
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; |
760 |
if (nonsu) |
|
|
761 |
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; |
| 762 |
if (pripl) |
| 763 |
trim_prison_mount(&sb, pripl); |
| 689 |
sp = &sb; |
764 |
sp = &sb; |
| 690 |
} |
765 |
} |
| 691 |
return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); |
766 |
return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); |
|
Lines 714-726
Link Here
|
| 714 |
register struct statfs *sp; |
789 |
register struct statfs *sp; |
| 715 |
caddr_t sfsp; |
790 |
caddr_t sfsp; |
| 716 |
long count, maxcount, error; |
791 |
long count, maxcount, error; |
|
|
792 |
int pripl; |
| 793 |
struct statfs sb; |
| 717 |
|
794 |
|
| 718 |
maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); |
795 |
maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); |
| 719 |
sfsp = (caddr_t)SCARG(uap, buf); |
796 |
sfsp = (caddr_t)SCARG(uap, buf); |
| 720 |
count = 0; |
797 |
count = 0; |
| 721 |
simple_lock(&mountlist_slock); |
798 |
simple_lock(&mountlist_slock); |
| 722 |
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { |
799 |
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { |
| 723 |
if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { |
800 |
pripl = check_prison_mount(p, &mp->mnt_stat); |
|
|
801 |
if (pripl < 0 || vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { |
| 724 |
nmp = TAILQ_NEXT(mp, mnt_list); |
802 |
nmp = TAILQ_NEXT(mp, mnt_list); |
| 725 |
continue; |
803 |
continue; |
| 726 |
} |
804 |
} |
|
Lines 740-745
Link Here
|
| 740 |
continue; |
818 |
continue; |
| 741 |
} |
819 |
} |
| 742 |
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; |
820 |
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; |
|
|
821 |
if (pripl) { |
| 822 |
bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); |
| 823 |
trim_prison_mount(&sb, pripl); |
| 824 |
sp = &sb; |
| 825 |
} |
| 743 |
error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); |
826 |
error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); |
| 744 |
if (error) { |
827 |
if (error) { |
| 745 |
vfs_unbusy(mp, p); |
828 |
vfs_unbusy(mp, p); |