core-extra/kernel/freebsd/symlinks-8.1-RELEASE.diff

79 lines
2 KiB
Diff
Raw Normal View History

Index: sys/kern/vfs_lookup.c
===========================================================================
--- sys/kern/vfs_lookup.c 2010/06/17 19:18:00 #3
+++ sys/kern/vfs_lookup.c 2010/06/17 19:18:00
@@ -59,6 +59,8 @@
#include <sys/ktrace.h>
#endif
+#include <net/vnet.h>
+
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -72,6 +74,19 @@
"unsigned long");
SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *");
+#ifdef VIMAGE
+#define IMUNES_SYMLINK_HACK
+#endif
+
+#ifdef IMUNES_SYMLINK_HACK
+static VNET_DEFINE(int, morphing_symlinks);
+#define V_morphing_symlinks VNET(morphing_symlinks)
+
+SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW,
+ &VNET_NAME(morphing_symlinks), 0,
+ "Resolve @ to vimage name in symlinks");
+#endif
+
/*
* Allocation zone for namei
*/
@@ -333,6 +348,44 @@
error = ENOENT;
break;
}
+#ifdef IMUNES_SYMLINK_HACK
+ /*
+ * If the symbolic link includes a special character '@',
+ * and V_morphing_symlinks is set, substitute the first
+ * occurence of '@' with full path to jail / vimage name.
+ * If the full path includes subhierarchies, s/./\// when
+ * expanding '@' to jail / vimage name.
+ *
+ * XXX revisit buffer length checking.
+ */
+ CURVNET_SET_QUIET(TD_TO_VNET(curthread));
+ if (V_morphing_symlinks) {
+ char *sp = strchr(cp, '@');
+
+ if (sp) {
+ char *vname = td->td_ucred->cr_prison->pr_name;
+ int vnamelen = strlen(vname);
+ int i;
+
+ if (vnamelen >= auio.uio_resid) {
+ if (ndp->ni_pathlen > 1)
+ uma_zfree(namei_zone, cp);
+ error = ENAMETOOLONG;
+ CURVNET_RESTORE();
+ break;
+ }
+ bcopy(sp + 1, sp + vnamelen,
+ linklen - (sp - cp));
+ bcopy(td->td_ucred->cr_prison->pr_name,
+ sp, vnamelen);
+ linklen += (vnamelen - 1);
+ for (i = 0; i < vnamelen; i++)
+ if (sp[i] == '.')
+ sp[i] = '/';
+ }
+ }
+ CURVNET_RESTORE();
+#endif
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
if (ndp->ni_pathlen > 1)
uma_zfree(namei_zone, cp);