diff -Ndur linux-2.6.32-700/fs/proc/web100.c linux-2.6.32-700-xidmask/fs/proc/web100.c --- linux-2.6.32-700/fs/proc/web100.c 2013-01-10 14:18:50.429337747 -0500 +++ linux-2.6.32-700-xidmask/fs/proc/web100.c 2013-02-06 17:36:52.308961450 -0500 @@ -427,10 +427,10 @@ local_port = vars->LocalPort; remote_port = vars->RemPort; - len += v6addr_str(tmpbuf + len, (short *)&vars->LocalAddress.v6addr.addr); - len += sprintf(tmpbuf + len, ".%d ", local_port); - len += v6addr_str(tmpbuf + len, (short *)&vars->RemAddress.v6addr.addr); - len += sprintf(tmpbuf + len, ".%d\n", remote_port); + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "%pI6", &vars->LocalAddress.v6addr.addr); + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, ".%d ", local_port); + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, "%pI6", &vars->RemAddress.v6addr.addr); + len += snprintf(tmpbuf + len, sizeof(tmpbuf) - len, ".%d\n", remote_port); } else { printk(KERN_ERR "connection_spec_ascii_read: LocalAddressType invalid\n"); return 0; @@ -655,7 +655,8 @@ stats = web100stats_first; while (stats && n < max) { - if (!stats->wc_dead) { + // only return readable stats + if ( 1 == vx_can_read_stats(stats) ) { if (pos <= 0) cids[n++] = stats->wc_cid; else diff -Ndur linux-2.6.32-700/include/linux/vserver/context.h linux-2.6.32-700-xidmask/include/linux/vserver/context.h --- linux-2.6.32-700/include/linux/vserver/context.h 2013-01-10 14:18:49.949337361 -0500 +++ linux-2.6.32-700-xidmask/include/linux/vserver/context.h 2013-01-19 23:27:42.280655065 -0500 @@ -79,6 +79,7 @@ #define VXC_KTHREAD 0x01000000 #define VXC_NAMESPACE 0x02000000 +#define VXC_ENABLE_WEB100 0x10000000 #ifdef __KERNEL__ diff -Ndur linux-2.6.32-700/include/net/tcp.h linux-2.6.32-700-xidmask/include/net/tcp.h --- linux-2.6.32-700/include/net/tcp.h 2013-01-10 14:18:49.880337393 -0500 +++ linux-2.6.32-700-xidmask/include/net/tcp.h 2013-01-19 15:41:28.218337671 -0500 @@ -251,6 +251,7 @@ #ifdef CONFIG_WEB100_STATS extern int sysctl_web100_fperms; extern int sysctl_web100_gid; +extern int sysctl_web100_sidestream_xid; #endif extern atomic_t tcp_memory_allocated; diff -Ndur linux-2.6.32-700/include/net/web100.h linux-2.6.32-700-xidmask/include/net/web100.h --- linux-2.6.32-700/include/net/web100.h 2013-01-10 14:18:49.874218972 -0500 +++ linux-2.6.32-700-xidmask/include/net/web100.h 2013-01-19 23:44:09.561660368 -0500 @@ -46,7 +46,9 @@ extern rwlock_t web100_linkage_lock; /* For /proc/web100 */ -extern struct web100stats *web100stats_lookup(int cid); +extern int vx_can_read_stats(struct web100stats *stats); +extern struct web100stats *vx_web100stats_lookup(int cid, int vx_filter); +#define web100stats_lookup(cid) vx_web100stats_lookup(cid, 1) /* For the TCP code */ extern int web100_stats_create(struct sock *sk); diff -Ndur linux-2.6.32-700/net/ipv4/sysctl_net_ipv4.c linux-2.6.32-700-xidmask/net/ipv4/sysctl_net_ipv4.c --- linux-2.6.32-700/net/ipv4/sysctl_net_ipv4.c 2013-01-10 14:18:50.233320698 -0500 +++ linux-2.6.32-700-xidmask/net/ipv4/sysctl_net_ipv4.c 2013-01-19 15:41:52.767269242 -0500 @@ -754,6 +754,14 @@ .mode = 0644, .proc_handler = &web100_proc_dointvec_update, }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "web100_sidestream_xid", + .data = &sysctl_web100_sidestream_xid, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &web100_proc_dointvec_update, + }, #endif { .ctl_name = CTL_UNNUMBERED, diff -Ndur linux-2.6.32-700/net/ipv4/tcp.c linux-2.6.32-700-xidmask/net/ipv4/tcp.c --- linux-2.6.32-700/net/ipv4/tcp.c 2013-01-10 14:18:50.234322447 -0500 +++ linux-2.6.32-700-xidmask/net/ipv4/tcp.c 2013-01-19 15:42:50.975214376 -0500 @@ -297,6 +297,7 @@ #ifdef CONFIG_WEB100_STATS int sysctl_web100_fperms = CONFIG_WEB100_FPERMS; int sysctl_web100_gid = CONFIG_WEB100_GID; +int sysctl_web100_sidestream_xid = -1; #endif atomic_t tcp_memory_allocated; /* Current allocated memory. */ @@ -848,7 +849,7 @@ if (copied) { tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); #ifdef CONFIG_WEB100_STATS - web100_update_writeq(sk); + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_writeq(sk)); #endif } @@ -1101,7 +1102,7 @@ if (copied) { tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); #ifdef CONFIG_WEB100_STATS - web100_update_writeq(sk); + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_writeq(sk)); #endif } @@ -1471,7 +1472,7 @@ tp->rcv_nxt, flags); } #ifdef CONFIG_WEB100_STATS - web100_update_recvq(sk); + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_recvq(sk)); #endif /* Well, if we have backlog, try to process it now yet. */ diff -Ndur linux-2.6.32-700/net/ipv4/tcp_input.c linux-2.6.32-700-xidmask/net/ipv4/tcp_input.c --- linux-2.6.32-700/net/ipv4/tcp_input.c 2013-01-10 14:18:50.232318345 -0500 +++ linux-2.6.32-700-xidmask/net/ipv4/tcp_input.c 2013-01-10 14:21:16.371337187 -0500 @@ -3177,7 +3177,7 @@ } #ifdef CONFIG_WEB100_NET100 - if (vars->WAD_NoAI) { + if (stats != NULL && vars->WAD_NoAI) { tp->snd_cwnd += vars->WAD_CwndAdjust; vars->WAD_CwndAdjust = 0; tp->snd_cwnd_stamp = tcp_time_stamp; @@ -4426,7 +4426,7 @@ tcp_fast_path_check(sk); #ifdef CONFIG_WEB100_STATS - web100_update_recvq(sk); + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_recvq(sk)); #endif if (eaten > 0) @@ -4484,7 +4484,7 @@ tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); #ifdef CONFIG_WEB100_STATS - web100_update_recvq(sk); + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_recvq(sk)); #endif skb_set_owner_r(skb, sk); @@ -5372,7 +5372,7 @@ } #ifdef CONFIG_WEB100_STATS - web100_update_recvq(sk); + WEB100_UPDATE_FUNC(tcp_sk(sk), web100_update_recvq(sk)); #endif tcp_event_data_recv(sk, skb); diff -Ndur linux-2.6.32-700/net/ipv4/tcp_ipv4.c linux-2.6.32-700-xidmask/net/ipv4/tcp_ipv4.c --- linux-2.6.32-700/net/ipv4/tcp_ipv4.c 2013-01-10 14:18:50.235319018 -0500 +++ linux-2.6.32-700-xidmask/net/ipv4/tcp_ipv4.c 2013-01-10 14:21:16.372284450 -0500 @@ -1383,7 +1383,9 @@ sk_free(newsk); goto exit; } - tcp_sk(newsk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV4; + if ( tcp_sk(newsk)->tcp_stats != NULL ) { + tcp_sk(newsk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV4; + } #endif newsk->sk_gso_type = SKB_GSO_TCPV4; @@ -1857,7 +1859,9 @@ if ((err = web100_stats_create(sk))) { return err; } - tcp_sk(sk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV4; + if ( tcp_sk(sk)->tcp_stats != NULL ) { + tcp_sk(sk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV4; + } } #endif diff -Ndur linux-2.6.32-700/net/ipv4/web100_stats.c linux-2.6.32-700-xidmask/net/ipv4/web100_stats.c --- linux-2.6.32-700/net/ipv4/web100_stats.c 2013-01-10 14:18:50.231318735 -0500 +++ linux-2.6.32-700-xidmask/net/ipv4/web100_stats.c 2013-02-06 22:25:11.711402213 -0500 @@ -72,7 +72,99 @@ 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 && !vx_info_ccaps(vxi, VXC_ENABLE_WEB100) ) { + /* do not create stats struct */ + return 0; + } + } + /* 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) + return 1; + } + + vxi = current_vx_info(); + if ( NULL == vxi ) { + /* non-root context is missing vx_info; cannot check access flags */ + return 0; + } + + if ( vx_current_xid() == sysctl_web100_sidestream_xid ) { + /* the sidestream xid can view all stats. */ + 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 */ + return 1; + } + + /* all checks have failed, so deny read permission. */ + 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,7 +175,10 @@ stats = web100stats_ht[web100stats_hash(cid)]; while (stats && stats->wc_cid != cid) stats = stats->wc_hash_next; - return stats; + if ( 0 == vx_filter || 1 == vx_can_read_stats(stats) ) { + return stats; + } + return NULL; } /* This will get really slow as the cid space fills. This can be done @@ -99,7 +194,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 +348,12 @@ struct web100directs *vars; struct tcp_sock *tp = tcp_sk(sk); struct timeval tv; + + if ( 0 == vx_can_create_stats(sk) ) { + /* do not create web100 stats for this socket */ + tp->tcp_stats = NULL; + return 0; + } if ((stats = kmalloc(sizeof (struct web100stats), gfp_any())) == NULL) return -ENOMEM; @@ -294,6 +396,9 @@ void web100_stats_destroy(struct web100stats *stats) { + if ( NULL == stats ) { + return; + } /* Attribute final sndlim time. */ web100_update_sndlim(tcp_sk(stats->wc_sk), stats->wc_limstate); diff -Ndur linux-2.6.32-700/net/ipv6/tcp_ipv6.c linux-2.6.32-700-xidmask/net/ipv6/tcp_ipv6.c --- linux-2.6.32-700/net/ipv6/tcp_ipv6.c 2013-01-10 14:18:50.219284269 -0500 +++ linux-2.6.32-700-xidmask/net/ipv6/tcp_ipv6.c 2013-01-10 14:21:16.373337472 -0500 @@ -1380,7 +1380,9 @@ sk_free(newsk); goto out; } - tcp_sk(newsk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV6; + if ( tcp_sk(newsk)->tcp_stats != NULL ) { + tcp_sk(newsk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV6; + } #endif /* @@ -1901,7 +1903,9 @@ if ((err = web100_stats_create(sk))) { return err; } - tcp_sk(sk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV6; + if ( tcp_sk(sk)->tcp_stats != NULL ) { + tcp_sk(sk)->tcp_stats->wc_vars.LocalAddressType = WC_ADDRTYPE_IPV6; + } } #endif