summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlfred Perlstein <alfred@FreeBSD.org>1999-09-16 02:02:16 +0000
committerAlfred Perlstein <alfred@FreeBSD.org>1999-09-16 02:02:16 +0000
commit0df360701eb64ee65574101f6c7f99990bf114dc (patch)
tree46fd957528d194f601524b104030134334b4e8c9 /sys
parentecb11b29b4a2b9b494b666faf327fd1c81553bae (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_cache.c10
-rw-r--r--sys/kern/vfs_subr.c1
-rw-r--r--sys/sys/vnode.h3
3 files changed, 13 insertions, 1 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 7c7afa3bd0fa..a4b362895abc 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -105,6 +105,12 @@ static u_long numposhits; STATNODE(CTLFLAG_RD, numposhits, &numposhits);
static u_long numnegzaps; STATNODE(CTLFLAG_RD, numnegzaps, &numnegzaps);
static u_long numneghits; STATNODE(CTLFLAG_RD, numneghits, &numneghits);
+/*
+ * Max aliases to a name, avoids DoS of the system via hardlinks
+ */
+static int ncmaxaliases = 4;
+SYSCTL_INT(_vfs_cache, OID_AUTO, maxaliases, CTLFLAG_RW, &ncmaxaliases, 4,
+ "Maximum amount of cache entries that can point to a particular file");
static void cache_zap __P((struct namecache *ncp));
@@ -126,6 +132,7 @@ cache_zap(ncp)
vdrop(ncp->nc_dvp);
if (ncp->nc_vp) {
TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
+ ncp->nc_vp->v_cache_dst_count--;
} else {
TAILQ_REMOVE(&ncneg, ncp, nc_dst);
numneg--;
@@ -296,6 +303,9 @@ cache_enter(dvp, vp, cnp)
vhold(dvp);
LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src);
if (vp) {
+ while (vp->v_cache_dst_count > ncmaxaliases)
+ cache_zap(TAILQ_LAST(&vp->v_cache_dst, cdst));
+ vp->v_cache_dst_count++;
TAILQ_INSERT_HEAD(&vp->v_cache_dst, ncp, nc_dst);
} else {
TAILQ_INSERT_TAIL(&ncneg, ncp, nc_dst);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 90f3f6ff4ea9..c7375a2b0979 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -487,6 +487,7 @@ getnewvnode(tag, mp, vops, vpp)
vp->v_socket = 0;
vp->v_writecount = 0; /* XXX */
vp->v_maxio = 0;
+ vp->v_cache_dst_count = 0;
} else {
simple_unlock(&vnode_free_list_slock);
vp = (struct vnode *) zalloc(vnode_zone);
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index e89a871b3561..dd0f51450ca0 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -116,7 +116,8 @@ struct vnode {
enum vtagtype v_tag; /* type of underlying data */
void *v_data; /* private data for fs */
LIST_HEAD(, namecache) v_cache_src; /* Cache entries from us */
- TAILQ_HEAD(, namecache) v_cache_dst; /* Cache entries to us */
+ TAILQ_HEAD(cdst, namecache) v_cache_dst; /* Cache entries to us */
+ int v_cache_dst_count; /* number of cache entries pointing to us */
struct vnode *v_dd; /* .. vnode */
u_long v_ddid; /* .. capability identifier */
struct {