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);