View | Details | Raw Unified | Return to bug 26740
Collapse All | Expand All

(-)src/sys/sys/jail.h (+12 lines)
Lines 30-35 Link Here
30
MALLOC_DECLARE(M_PRISON);
30
MALLOC_DECLARE(M_PRISON);
31
#endif
31
#endif
32
32
33
34
#ifndef MNAMELEN
35
/* This is taken from sys/mount.h. */
36
#ifdef __i386__
37
#define	MNAMELEN	80	/* length of buffer for returned name */
38
#endif
39
#ifdef __alpha__
40
#define	MNAMELEN	72	/* length of buffer for returned name */
41
#endif
42
#endif
43
33
/*
44
/*
34
 * This structure describes a prison.  It is pointed to by all struct
45
 * This structure describes a prison.  It is pointed to by all struct
35
 * proc's of the inmates.  pr_ref keeps track of them and is used to
46
 * proc's of the inmates.  pr_ref keeps track of them and is used to
Lines 39-44 Link Here
39
struct prison {
50
struct prison {
40
	int		pr_ref;
51
	int		pr_ref;
41
	char 		pr_host[MAXHOSTNAMELEN];
52
	char 		pr_host[MAXHOSTNAMELEN];
53
	char		pr_path[MNAMELEN];
42
	u_int32_t	pr_ip;
54
	u_int32_t	pr_ip;
43
	void		*pr_linux;
55
	void		*pr_linux;
44
};
56
};
(-)src/sys/kern/kern_jail.c (+3 lines)
Lines 69-74 Link Here
69
	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
69
	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
70
	if (error) 
70
	if (error) 
71
		goto bail;
71
		goto bail;
72
	error = copyinstr(j.path, &pr->pr_path, sizeof pr->pr_path, 0);
73
	if (error)
74
		goto bail;
72
	pr->pr_ip = j.ip_number;
75
	pr->pr_ip = j.ip_number;
73
76
74
	ca.path = j.path;
77
	ca.path = j.path;
(-)src/sys/kern/vfs_syscalls.c (-5 / +88 lines)
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);

Return to bug 26740