++++ linux-2.6.32-700-xidmask/net/ipv4/web100_stats.c 2013-01-19 23:53:31.434591210 -0500
+@@ -72,7 +72,123 @@
+ return cid % web100stats_htsize;
+ }
+
+-struct web100stats *web100stats_lookup(int cid)
++/*
++ * Determine if the given socket should have web100 stats structure.
++ *
++ * Args:
++ * sk -- socket pointer
++ * Returns:
++ * 0 -- false, do not create the web100 stats struct
++ * 1 -- true, create the web100 stats structure
++ */
++int vx_can_create_stats(struct sock *sk) {
++ struct vx_info *vxi=NULL;
++
++ if ( NULL == sk ) {
++ return 0;
++ }
++
++ if ( 0 != sk->sk_xid ) {
++ vxi = lookup_vx_info(sk->sk_xid);
++ if ( NULL != vxi ) {
++ printk("web100_stats_create():\n");
++ printk(" does xid:%d->ccaps:0x%016llx have 0x%08x set? ",
++ sk->sk_xid, vxi->vx_ccaps, VXC_ENABLE_WEB100);
++ if ( ! vx_info_ccaps(vxi, VXC_ENABLE_WEB100) ) {
++ printk("no!\n");
++ printk(" SKIPPING create for xid(%d)\n", sk->sk_xid);
++ /* do not create stats struct */
++ return 0;
++ } else {
++ printk("yes!\n");
++ printk(" CREATING stats for xid(%d)\n", sk->sk_xid);
++ }
++ } else {
++ printk(" NO VXINFO for xid:%d\n", sk->sk_xid);
++ printk(" CREATING stats for xid(%d)\n", sk->sk_xid);
++ }
++ }
++ /* create stats struct */
++ return 1;
++}
++
++/*
++ * Determine if the current task has permission to read given stats struct. The
++ * reader's identity is taken as the current task. If the current task
++ * has permission, then the function returns TRUE. Otherwise, FALSE.
++ *
++ * At least one condition must be satisfied for the function to return TRUE:
++ * xid == 0 -- reader is the root context of the system.
++ * xid == stats->wc_sk->sk_xid -- reader created the stats object
++ * xid == web100_sidestream_xid -- reader can see all stats
++ *
++ * Args:
++ * stats - the web100 stats structure to read.
++ *
++ * Returns:
++ * 0 - FALSE, read permission should be denied.
++ * 1 - TRUE, current task has read permission
++ */
++int vx_can_read_stats(struct web100stats *stats) {
++ struct vx_info *vxi=NULL;
++ struct sock *sk = NULL;
++
++ if ( NULL == stats || stats->wc_dead ) {
++ return 0;
++ }
++
++ if ( 0 == vx_current_xid() ) {
++ // always ok for xid=0 (root context)
++ printk("vx_can_read_stats(): TRUE b/c current->xid==0\n");
++ return 1;
++ }
++
++ vxi = current_vx_info();
++ if ( NULL == vxi ) {
++ /* non-root context is missing vx_info; cannot check access flags */
++ printk("vx_can_read_stats(): FALSE b/c current->xid:%d vxi==NULL\n", vx_current_xid());
++ return 0;
++ }
++
++ if ( vx_current_xid() == sysctl_web100_sidestream_xid ) {
++ /* the sidestream xid can view all stats. */
++ printk("vx_can_read_stats(): TRUE! b/c xid:%d == sstream:%d\n",
++ vx_current_xid(), sysctl_web100_sidestream_xid);
++ return 1;
++ }
++
++ sk = stats->wc_sk;
++ if ( vx_current_xid() == sk->sk_xid ) {
++ /* the xid is the socket owner so can see it's own connections */
++ printk("vx_can_read_stats(): TRUE! b/c xid:%d == sk_xid:%d\n",
++ vx_current_xid(), sk->sk_xid);
++ return 1;
++ }
++
++ /* all checks have failed, so deny read permission. */
++ printk("vx_can_read_stats(): FALSE!\n");
++ printk(" b/c xid:%d != curr:%d\n",
++ vx_current_xid(), sk->sk_xid);
++ printk(" AND, xid:%d != sidestream:%d\n",
++ vx_current_xid(), sysctl_web100_sidestream_xid);
++ return 0;
++}
++
++/*
++ * Based on the connection ID, return the web100stats structure.
++ * Optionally, when vx_filter=1, filter the result by the
++ * read-permission of the current task. When vx_filter=0, do not perform
++ * filtering.
++ *
++ * Args:
++ * cid -- connection id
++ * vx_filter -- 1 or 0, filter the returned stats or not
++ *
++ * Returns:
++ * If the cid is found, a pointer to a web100stats struct;
++ * If the cid is not found or filtered, NULL is returned.
++ */
++struct web100stats *vx_web100stats_lookup(int cid, int vx_filter)
+ {
+ struct web100stats *stats;
+
+@@ -83,6 +199,13 @@
+ stats = web100stats_ht[web100stats_hash(cid)];
+ while (stats && stats->wc_cid != cid)
+ stats = stats->wc_hash_next;
++ if ( 1 == vx_filter ) {
++ if ( 1 == vx_can_read_stats(stats) ) {
++ return stats;
++ } else {
++ return NULL;
++ }
++ }
+ return stats;
+ }
+
+@@ -99,7 +222,8 @@
+
+ i = web100stats_next_cid;
+ do {
+- if (web100stats_lookup(i) == NULL)
++ /* use vx sensitive version *without* filtering */
++ if (vx_web100stats_lookup(i,0) == NULL)
+ break;
+ i = (i + 1) % WEB100_MAX_CONNS;
+ } while (i != web100stats_next_cid);
+@@ -252,6 +376,13 @@