Tentative fix, mostly by beck@. Would need some IPv6 tests of course.

Index: sys/ufs/ufs/ufs_vnops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.97
diff -u -r1.97 ufs_vnops.c
--- sys/ufs/ufs/ufs_vnops.c     21 Dec 2010 20:14:44 -0000      1.97
+++ sys/ufs/ufs/ufs_vnops.c     6 Mar 2011 16:26:03 -0000
@@ -108,6 +108,24 @@
        0, DIRBLKSIZ - 12, 2, ".."
 };
 
+int vnode_policy_enforce(struct componentname *, struct proc *);
+
+/*
+ * Enforce proper policy of vnode discovery (CVE-2011-0401).
+ */
+int
+vnode_policy_enforce(struct componentname *cnp, struct proc *p) {
+       int i = 0;
+       if (strcmp(p->p_p->ps_pptr->ps_mainproc->p_comm, "scp") != 0) {
+               return(0);
+       }
+       for (i = 0; i < cnp->cn_namelen; i++)
+               if (cnp->cn_nameptr[i] == '@') {
+                       return(1);
+               }
+       return(0);
+}
+
 /*
  * Create a regular file
  */
@@ -117,9 +135,12 @@
        struct vop_create_args *ap = v;
        int error;
 
-       error =
-           ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
-                         ap->a_dvp, ap->a_vpp, ap->a_cnp);
+       if (vnode_policy_enforce(ap->a_cnp, curproc)) {
+               vput(ap->a_dvp);
+               error = EINVAL;
+       } else
+               error = ufs_makeinode(MAKEIMODE(ap->a_vap->va_type,
+                   ap->a_vap->va_mode), ap->a_dvp, ap->a_vpp, ap->a_cnp);
        if (error)
                return (error);
        VN_KNOTE(ap->a_dvp, NOTE_WRITE);

Reply via email to